1
    2
    3
    4
    5
    6
    7
    8
    9
   10
   11
   12
   13
   14
   15
   16
   17
   18
   19
   20
   21
   22
   23
   24
   25
   26
   27
   28
   29
   30
   31
   32
   33
   34
   35
   36
   37
   38
   39
   40
   41
   42
   43
   44
   45
   46
   47
   48
   49
   50
   51
   52
   53
   54
   55
   56
   57
   58
   59
   60
   61
   62
   63
   64
   65
   66
   67
   68
   69
   70
   71
   72
   73
   74
   75
   76
   77
   78
   79
   80
   81
   82
   83
   84
   85
   86
   87
   88
   89
   90
   91
   92
   93
   94
   95
   96
   97
   98
   99
  100
  101
  102
  103
  104
  105
  106
  107
  108
  109
  110
  111
  112
  113
  114
  115
  116
  117
  118
  119
  120
  121
  122
  123
  124
  125
  126
  127
  128
  129
  130
  131
  132
  133
  134
  135
  136
  137
  138
  139
  140
  141
  142
  143
  144
  145
  146
  147
  148
  149
  150
  151
  152
  153
  154
  155
  156
  157
  158
  159
  160
  161
  162
  163
  164
  165
  166
  167
  168
  169
  170
  171
  172
  173
  174
  175
  176
  177
  178
  179
  180
  181
  182
  183
  184
  185
  186
  187
  188
  189
  190
  191
  192
  193
  194
  195
  196
  197
  198
  199
  200
  201
  202
  203
  204
  205
  206
  207
  208
  209
  210
  211
  212
  213
  214
  215
  216
  217
  218
  219
  220
  221
  222
  223
  224
  225
  226
  227
  228
  229
  230
  231
  232
  233
  234
  235
  236
  237
  238
  239
  240
  241
  242
  243
  244
  245
  246
  247
  248
  249
  250
  251
  252
  253
  254
  255
  256
  257
  258
  259
  260
  261
  262
  263
  264
  265
  266
  267
  268
  269
  270
  271
  272
  273
  274
  275
  276
  277
  278
  279
  280
  281
  282
  283
  284
  285
  286
  287
  288
  289
  290

content / browser / renderer_host / frame_navigation_entry.h [blame]

// Copyright 2015 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef CONTENT_BROWSER_RENDERER_HOST_FRAME_NAVIGATION_ENTRY_H_
#define CONTENT_BROWSER_RENDERER_HOST_FRAME_NAVIGATION_ENTRY_H_

#include <stdint.h>

#include <optional>

#include "base/memory/ref_counted.h"
#include "content/browser/renderer_host/policy_container_host.h"
#include "content/browser/site_instance_impl.h"
#include "content/common/content_export.h"
#include "content/public/common/bindings_policy.h"
#include "content/public/common/referrer.h"
#include "services/network/public/cpp/shared_url_loader_factory.h"
#include "third_party/blink/public/common/page_state/page_state.h"
#include "url/gurl.h"
#include "url/origin.h"

namespace network {
class ResourceRequestBody;
}

namespace content {

// Represents a session history item for a particular frame.  It is matched with
// corresponding FrameTreeNodes using unique name (or by the root position).
// There is a tree of FrameNavigationEntries in each NavigationEntry, one per
// frame.
//
// This class is refcounted and can be shared across multiple NavigationEntries.
// Each RenderFrameHost also keeps a scoped_refptr to its last committed
// FrameNavigationEntry, to accurately track its current state in cases when the
// last committed NavigationEntry may not match (e.g., when missing the
// relevant FrameNavigationEntry or during a history navigation targeting
// multiple frames while only some have committed.)
class CONTENT_EXPORT FrameNavigationEntry
    : public base::RefCounted<FrameNavigationEntry> {
 public:
  FrameNavigationEntry(
      const std::string& frame_unique_name,
      int64_t item_sequence_number,
      int64_t document_sequence_number,
      const std::string& navigation_api_key,
      scoped_refptr<SiteInstanceImpl> site_instance,
      scoped_refptr<SiteInstanceImpl> source_site_instance,
      const GURL& url,
      const std::optional<url::Origin>& origin,
      const Referrer& referrer,
      const std::optional<url::Origin>& initiator_origin,
      const std::optional<GURL>& initiator_base_url,
      const std::vector<GURL>& redirect_chain,
      const blink::PageState& page_state,
      const std::string& method,
      int64_t post_id,
      scoped_refptr<network::SharedURLLoaderFactory> blob_url_loader_factory,
      std::unique_ptr<PolicyContainerPolicies> policy_container_policies,
      bool protect_url_in_navigation_api);

  FrameNavigationEntry(const FrameNavigationEntry&) = delete;
  FrameNavigationEntry& operator=(const FrameNavigationEntry&) = delete;

  // Creates a copy of this FrameNavigationEntry that can be modified
  // independently from the original.
  scoped_refptr<FrameNavigationEntry> Clone() const;

  // Updates all the members of this entry.
  void UpdateEntry(
      const std::string& frame_unique_name,
      int64_t item_sequence_number,
      int64_t document_sequence_number,
      const std::string& navigation_api_key,
      SiteInstanceImpl* site_instance,
      scoped_refptr<SiteInstanceImpl> source_site_instance,
      const GURL& url,
      const std::optional<url::Origin>& origin,
      const Referrer& referrer,
      const std::optional<url::Origin>& initiator_origin,
      const std::optional<GURL>& initiator_base_url,
      const std::vector<GURL>& redirect_chain,
      const blink::PageState& page_state,
      const std::string& method,
      int64_t post_id,
      scoped_refptr<network::SharedURLLoaderFactory> blob_url_loader_factory,
      std::unique_ptr<PolicyContainerPolicies> policy_container_policies,
      bool protect_url_in_navigation_api);

  // The unique name of the frame this entry is for.  This is a stable name for
  // the frame based on its position in the tree and relation to other named
  // frames, which does not change after cross-process navigations or restores.
  // Only the main frame can have an empty name.
  //
  // This is unique relative to other frames in the same page, but not among
  // other pages (i.e., not globally unique).
  const std::string& frame_unique_name() const { return frame_unique_name_; }
  void set_frame_unique_name(const std::string& frame_unique_name) {
    frame_unique_name_ = frame_unique_name;
  }

  // Keeps track of where this entry belongs in the frame's session history.
  // The item sequence number identifies each stop in the back/forward history
  // and is globally unique.  The document sequence number increments for each
  // new document and is also globally unique.  In-page navigations get a new
  // item sequence number but the same document sequence number.  These numbers
  // should not change once assigned.
  void set_item_sequence_number(int64_t item_sequence_number);
  int64_t item_sequence_number() const { return item_sequence_number_; }
  void set_document_sequence_number(int64_t document_sequence_number);
  int64_t document_sequence_number() const { return document_sequence_number_; }

  // Identifies a "slot" in the frame's session history for the
  // window.navigation API.
  void set_navigation_api_key(const std::string& navigation_api_key);
  const std::string& navigation_api_key() const { return navigation_api_key_; }

  // The SiteInstance, as assigned at commit time, responsible for rendering
  // this frame.  All frames sharing a SiteInstance must live in the same
  // process.  This is a refcounted pointer that keeps the SiteInstance (not
  // necessarily the process) alive as long as this object remains in the
  // session history.
  SiteInstanceImpl* site_instance() const { return site_instance_.get(); }

  // The |source_site_instance| is used to identify the SiteInstance of the
  // frame that initiated the navigation. It is present only for
  // renderer-initiated navigations and is cleared once the navigation has
  // committed.
  void set_source_site_instance(
      scoped_refptr<SiteInstanceImpl> source_site_instance) {
    source_site_instance_ = std::move(source_site_instance);
  }
  SiteInstanceImpl* source_site_instance() const {
    return source_site_instance_.get();
  }

  // The actual URL loaded in the frame.  This is in contrast to the virtual
  // URL, which is shown to the user.
  void set_url(const GURL& url) { url_ = url; }
  const GURL& url() const { return url_; }

  // The referring URL.  Can be empty.
  void set_referrer(const Referrer& referrer) { referrer_ = referrer; }
  const Referrer& referrer() const { return referrer_; }

  // The origin that initiated the original navigation.  std::nullopt means
  // that the original navigation was browser-initiated (e.g. initiated from a
  // trusted surface like the omnibox or the bookmarks bar).
  const std::optional<url::Origin>& initiator_origin() const {
    return initiator_origin_;
  }

  // The base url of the initiator of the navigation. This is only set if the
  // url is about:blank or about:srcdoc.
  const std::optional<GURL>& initiator_base_url() const {
    return initiator_base_url_;
  }

  // The origin of the document the frame has committed. It is optional, since
  // pending entries do not have an origin associated with them and the real
  // origin is set at commit time.
  void set_committed_origin(const url::Origin& origin) {
    committed_origin_ = origin;
  }
  const std::optional<url::Origin>& committed_origin() const {
    return committed_origin_;
  }

  // The redirect chain traversed during this frame navigation, from the initial
  // redirecting URL to the final non-redirecting current URL.
  void set_redirect_chain(const std::vector<GURL>& redirect_chain) {
    redirect_chain_ = redirect_chain;
  }
  const std::vector<GURL>& redirect_chain() const { return redirect_chain_; }

  void SetPageState(const blink::PageState& page_state);
  const blink::PageState& page_state() const { return page_state_; }

  // Remember the set of bindings granted to this FrameNavigationEntry at the
  // time of commit, to ensure that we do not grant it additional bindings if we
  // navigate back to it in the future.  This can only be changed once.
  // bindings() will return nullopt before the bindings are set.
  void SetBindings(BindingsPolicySet bindings);
  std::optional<BindingsPolicySet> bindings() const { return bindings_; }

  // The HTTP method used to navigate.
  const std::string& method() const { return method_; }
  void set_method(const std::string& method) { method_ = method; }

  // Returns true if the HTTP method was POST.
  bool get_has_post_data() { return method() == "POST"; }

  // The id of the post corresponding to this navigation or -1 if the
  // navigation was not a POST.
  int64_t post_id() const { return post_id_; }
  void set_post_id(int64_t post_id) { post_id_ = post_id; }

  // The data sent during a POST navigation. Returns nullptr if the navigation
  // is not a POST.
  scoped_refptr<network::ResourceRequestBody> GetPostData(
      std::string* content_type) const;

  // The policy container policies for this entry. This is needed for local
  // schemes, since for them the policy container was inherited by the creator,
  // while for network schemes we can reconstruct the policy container by
  // parsing the network response.
  void set_policy_container_policies(
      std::unique_ptr<PolicyContainerPolicies> policies) {
    policy_container_policies_ = std::move(policies);
  }
  const PolicyContainerPolicies* policy_container_policies() const {
    return policy_container_policies_.get();
  }

  // Optional URLLoaderFactory to facilitate blob URL loading.
  scoped_refptr<network::SharedURLLoaderFactory> blob_url_loader_factory()
      const {
    return blob_url_loader_factory_;
  }
  void set_blob_url_loader_factory(
      scoped_refptr<network::SharedURLLoaderFactory> factory) {
    blob_url_loader_factory_ = std::move(factory);
  }

  bool protect_url_in_navigation_api() {
    return protect_url_in_navigation_api_;
  }
  void set_protect_url_in_navigation_api(bool protect) {
    protect_url_in_navigation_api_ = protect;
  }

 private:
  friend class base::RefCounted<FrameNavigationEntry>;
  virtual ~FrameNavigationEntry();

  // WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING
  // Add all new fields to |UpdateEntry|.
  // TODO(creis): These fields have implications for session restore.  This is
  // currently managed by NavigationEntry, but the logic will move here.
  // WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING

  // See the accessors above for descriptions.
  std::string frame_unique_name_;

  // sequence numbers and the navigation API key are also stored in
  // |page_state_|. When SetPageState() is called as part of a restore, it also
  // initializes these.
  int64_t item_sequence_number_;
  int64_t document_sequence_number_;
  std::string navigation_api_key_;

  // TODO(nasko, creis): The SiteInstance of a FrameNavigationEntry should
  // not change once it has been assigned.  See https://crbug.com/849430.
  scoped_refptr<SiteInstanceImpl> site_instance_;
  // This member is cleared at commit time and is not persisted.
  scoped_refptr<SiteInstanceImpl> source_site_instance_;
  GURL url_;
  // For a committed navigation, holds the origin of the resulting document.
  // TODO(nasko): This should be possible to calculate at ReadyToCommit time
  // and verified when receiving the DidCommit IPC.
  std::optional<url::Origin> committed_origin_;
  Referrer referrer_;
  std::optional<url::Origin> initiator_origin_;
  std::optional<GURL> initiator_base_url_;
  // This is used when transferring a pending entry from one process to another.
  // We also send the main frame's redirect chain through session sync for
  // offline analysis.
  // It is preserved after commit but should not be persisted.
  std::vector<GURL> redirect_chain_;
  // TODO(creis): Change this to FrameState.
  blink::PageState page_state_;
  // TODO(creis): Persist bindings_. https://crbug.com/40076915.
  std::optional<BindingsPolicySet> bindings_;
  std::string method_;
  int64_t post_id_;
  scoped_refptr<network::SharedURLLoaderFactory> blob_url_loader_factory_;

  // TODO(crbug.com/40053667): Persist these policies.
  std::unique_ptr<PolicyContainerPolicies> policy_container_policies_;

  // If the document represented by this FNE hid its full url from appearing
  // in a referrer via a "no-referrer" or "origin" referrer policy, this URL
  // will be hidden from navigation API history entries as well.
  bool protect_url_in_navigation_api_;
};

}  // namespace content

#endif  // CONTENT_BROWSER_RENDERER_HOST_FRAME_NAVIGATION_ENTRY_H_