Avi Drissman | 4e1b7bc3 | 2022-09-15 14:03:50 | [diff] [blame] | 1 | // Copyright 2015 The Chromium Authors |
danakj | c492bf8 | 2020-09-09 20:02:44 | [diff] [blame] | 2 | // Use of this source code is governed by a BSD-style license that can be |
| 3 | // found in the LICENSE file. |
| 4 | |
| 5 | #ifndef CONTENT_BROWSER_RENDERER_HOST_FRAME_NAVIGATION_ENTRY_H_ |
| 6 | #define CONTENT_BROWSER_RENDERER_HOST_FRAME_NAVIGATION_ENTRY_H_ |
| 7 | |
| 8 | #include <stdint.h> |
| 9 | |
Arthur Sonzogni | c686e8f | 2024-01-11 08:36:37 | [diff] [blame] | 10 | #include <optional> |
| 11 | |
danakj | c492bf8 | 2020-09-09 20:02:44 | [diff] [blame] | 12 | #include "base/memory/ref_counted.h" |
Antonio Sartori | 78a749f | 2020-11-30 12:03:39 | [diff] [blame] | 13 | #include "content/browser/renderer_host/policy_container_host.h" |
danakj | c492bf8 | 2020-09-09 20:02:44 | [diff] [blame] | 14 | #include "content/browser/site_instance_impl.h" |
Lei Zhang | 7ab31375 | 2021-11-17 01:26:00 | [diff] [blame] | 15 | #include "content/common/content_export.h" |
Avi Drissman | 78865bbb | 2024-08-22 20:57:19 | [diff] [blame] | 16 | #include "content/public/common/bindings_policy.h" |
danakj | c492bf8 | 2020-09-09 20:02:44 | [diff] [blame] | 17 | #include "content/public/common/referrer.h" |
danakj | c492bf8 | 2020-09-09 20:02:44 | [diff] [blame] | 18 | #include "services/network/public/cpp/shared_url_loader_factory.h" |
Miyoung Shin | 5d77f7207 | 2020-10-09 15:14:20 | [diff] [blame] | 19 | #include "third_party/blink/public/common/page_state/page_state.h" |
danakj | c492bf8 | 2020-09-09 20:02:44 | [diff] [blame] | 20 | #include "url/gurl.h" |
| 21 | #include "url/origin.h" |
| 22 | |
Lei Zhang | b7fc246 | 2022-09-09 23:27:48 | [diff] [blame] | 23 | namespace network { |
| 24 | class ResourceRequestBody; |
| 25 | } |
| 26 | |
danakj | c492bf8 | 2020-09-09 20:02:44 | [diff] [blame] | 27 | namespace content { |
| 28 | |
danakj | c492bf8 | 2020-09-09 20:02:44 | [diff] [blame] | 29 | // Represents a session history item for a particular frame. It is matched with |
| 30 | // corresponding FrameTreeNodes using unique name (or by the root position). |
Nate Chapin | 9f16907 | 2021-06-09 19:32:37 | [diff] [blame] | 31 | // There is a tree of FrameNavigationEntries in each NavigationEntry, one per |
danakj | c492bf8 | 2020-09-09 20:02:44 | [diff] [blame] | 32 | // frame. |
| 33 | // |
Nate Chapin | 9f16907 | 2021-06-09 19:32:37 | [diff] [blame] | 34 | // This class is refcounted and can be shared across multiple NavigationEntries. |
Charlie Reis | a474fb6 | 2022-03-17 02:31:36 | [diff] [blame] | 35 | // Each RenderFrameHost also keeps a scoped_refptr to its last committed |
| 36 | // FrameNavigationEntry, to accurately track its current state in cases when the |
| 37 | // last committed NavigationEntry may not match (e.g., when missing the |
| 38 | // relevant FrameNavigationEntry or during a history navigation targeting |
| 39 | // multiple frames while only some have committed.) |
danakj | c492bf8 | 2020-09-09 20:02:44 | [diff] [blame] | 40 | class CONTENT_EXPORT FrameNavigationEntry |
| 41 | : public base::RefCounted<FrameNavigationEntry> { |
| 42 | public: |
danakj | c492bf8 | 2020-09-09 20:02:44 | [diff] [blame] | 43 | FrameNavigationEntry( |
| 44 | const std::string& frame_unique_name, |
| 45 | int64_t item_sequence_number, |
| 46 | int64_t document_sequence_number, |
Domenic Denicola | cc094fb | 2022-03-16 23:40:57 | [diff] [blame] | 47 | const std::string& navigation_api_key, |
danakj | c492bf8 | 2020-09-09 20:02:44 | [diff] [blame] | 48 | scoped_refptr<SiteInstanceImpl> site_instance, |
| 49 | scoped_refptr<SiteInstanceImpl> source_site_instance, |
| 50 | const GURL& url, |
Arthur Sonzogni | c686e8f | 2024-01-11 08:36:37 | [diff] [blame] | 51 | const std::optional<url::Origin>& origin, |
danakj | c492bf8 | 2020-09-09 20:02:44 | [diff] [blame] | 52 | const Referrer& referrer, |
Arthur Sonzogni | c686e8f | 2024-01-11 08:36:37 | [diff] [blame] | 53 | const std::optional<url::Origin>& initiator_origin, |
| 54 | const std::optional<GURL>& initiator_base_url, |
danakj | c492bf8 | 2020-09-09 20:02:44 | [diff] [blame] | 55 | const std::vector<GURL>& redirect_chain, |
Miyoung Shin | 5d77f7207 | 2020-10-09 15:14:20 | [diff] [blame] | 56 | const blink::PageState& page_state, |
danakj | c492bf8 | 2020-09-09 20:02:44 | [diff] [blame] | 57 | const std::string& method, |
| 58 | int64_t post_id, |
| 59 | scoped_refptr<network::SharedURLLoaderFactory> blob_url_loader_factory, |
Nate Chapin | 63db0d1 | 2022-01-20 22:03:30 | [diff] [blame] | 60 | std::unique_ptr<PolicyContainerPolicies> policy_container_policies, |
Domenic Denicola | cc094fb | 2022-03-16 23:40:57 | [diff] [blame] | 61 | bool protect_url_in_navigation_api); |
danakj | c492bf8 | 2020-09-09 20:02:44 | [diff] [blame] | 62 | |
Peter Boström | 9b03653 | 2021-10-28 23:37:28 | [diff] [blame] | 63 | FrameNavigationEntry(const FrameNavigationEntry&) = delete; |
| 64 | FrameNavigationEntry& operator=(const FrameNavigationEntry&) = delete; |
| 65 | |
danakj | c492bf8 | 2020-09-09 20:02:44 | [diff] [blame] | 66 | // Creates a copy of this FrameNavigationEntry that can be modified |
| 67 | // independently from the original. |
| 68 | scoped_refptr<FrameNavigationEntry> Clone() const; |
| 69 | |
| 70 | // Updates all the members of this entry. |
| 71 | void UpdateEntry( |
| 72 | const std::string& frame_unique_name, |
| 73 | int64_t item_sequence_number, |
| 74 | int64_t document_sequence_number, |
Domenic Denicola | cc094fb | 2022-03-16 23:40:57 | [diff] [blame] | 75 | const std::string& navigation_api_key, |
danakj | c492bf8 | 2020-09-09 20:02:44 | [diff] [blame] | 76 | SiteInstanceImpl* site_instance, |
| 77 | scoped_refptr<SiteInstanceImpl> source_site_instance, |
| 78 | const GURL& url, |
Arthur Sonzogni | c686e8f | 2024-01-11 08:36:37 | [diff] [blame] | 79 | const std::optional<url::Origin>& origin, |
danakj | c492bf8 | 2020-09-09 20:02:44 | [diff] [blame] | 80 | const Referrer& referrer, |
Arthur Sonzogni | c686e8f | 2024-01-11 08:36:37 | [diff] [blame] | 81 | const std::optional<url::Origin>& initiator_origin, |
| 82 | const std::optional<GURL>& initiator_base_url, |
danakj | c492bf8 | 2020-09-09 20:02:44 | [diff] [blame] | 83 | const std::vector<GURL>& redirect_chain, |
Miyoung Shin | 5d77f7207 | 2020-10-09 15:14:20 | [diff] [blame] | 84 | const blink::PageState& page_state, |
danakj | c492bf8 | 2020-09-09 20:02:44 | [diff] [blame] | 85 | const std::string& method, |
| 86 | int64_t post_id, |
| 87 | scoped_refptr<network::SharedURLLoaderFactory> blob_url_loader_factory, |
Nate Chapin | 63db0d1 | 2022-01-20 22:03:30 | [diff] [blame] | 88 | std::unique_ptr<PolicyContainerPolicies> policy_container_policies, |
Domenic Denicola | cc094fb | 2022-03-16 23:40:57 | [diff] [blame] | 89 | bool protect_url_in_navigation_api); |
danakj | c492bf8 | 2020-09-09 20:02:44 | [diff] [blame] | 90 | |
| 91 | // The unique name of the frame this entry is for. This is a stable name for |
| 92 | // the frame based on its position in the tree and relation to other named |
| 93 | // frames, which does not change after cross-process navigations or restores. |
| 94 | // Only the main frame can have an empty name. |
| 95 | // |
| 96 | // This is unique relative to other frames in the same page, but not among |
| 97 | // other pages (i.e., not globally unique). |
| 98 | const std::string& frame_unique_name() const { return frame_unique_name_; } |
| 99 | void set_frame_unique_name(const std::string& frame_unique_name) { |
| 100 | frame_unique_name_ = frame_unique_name; |
| 101 | } |
| 102 | |
| 103 | // Keeps track of where this entry belongs in the frame's session history. |
| 104 | // The item sequence number identifies each stop in the back/forward history |
| 105 | // and is globally unique. The document sequence number increments for each |
| 106 | // new document and is also globally unique. In-page navigations get a new |
| 107 | // item sequence number but the same document sequence number. These numbers |
| 108 | // should not change once assigned. |
| 109 | void set_item_sequence_number(int64_t item_sequence_number); |
| 110 | int64_t item_sequence_number() const { return item_sequence_number_; } |
| 111 | void set_document_sequence_number(int64_t document_sequence_number); |
| 112 | int64_t document_sequence_number() const { return document_sequence_number_; } |
| 113 | |
Domenic Denicola | cc094fb | 2022-03-16 23:40:57 | [diff] [blame] | 114 | // Identifies a "slot" in the frame's session history for the |
| 115 | // window.navigation API. |
| 116 | void set_navigation_api_key(const std::string& navigation_api_key); |
| 117 | const std::string& navigation_api_key() const { return navigation_api_key_; } |
Nate Chapin | fbfe5af | 2021-06-10 17:22:08 | [diff] [blame] | 118 | |
danakj | c492bf8 | 2020-09-09 20:02:44 | [diff] [blame] | 119 | // The SiteInstance, as assigned at commit time, responsible for rendering |
| 120 | // this frame. All frames sharing a SiteInstance must live in the same |
| 121 | // process. This is a refcounted pointer that keeps the SiteInstance (not |
| 122 | // necessarily the process) alive as long as this object remains in the |
| 123 | // session history. |
danakj | c492bf8 | 2020-09-09 20:02:44 | [diff] [blame] | 124 | SiteInstanceImpl* site_instance() const { return site_instance_.get(); } |
| 125 | |
| 126 | // The |source_site_instance| is used to identify the SiteInstance of the |
| 127 | // frame that initiated the navigation. It is present only for |
| 128 | // renderer-initiated navigations and is cleared once the navigation has |
| 129 | // committed. |
| 130 | void set_source_site_instance( |
| 131 | scoped_refptr<SiteInstanceImpl> source_site_instance) { |
| 132 | source_site_instance_ = std::move(source_site_instance); |
| 133 | } |
| 134 | SiteInstanceImpl* source_site_instance() const { |
| 135 | return source_site_instance_.get(); |
| 136 | } |
| 137 | |
| 138 | // The actual URL loaded in the frame. This is in contrast to the virtual |
| 139 | // URL, which is shown to the user. |
| 140 | void set_url(const GURL& url) { url_ = url; } |
| 141 | const GURL& url() const { return url_; } |
| 142 | |
| 143 | // The referring URL. Can be empty. |
| 144 | void set_referrer(const Referrer& referrer) { referrer_ = referrer; } |
| 145 | const Referrer& referrer() const { return referrer_; } |
| 146 | |
Arthur Sonzogni | c686e8f | 2024-01-11 08:36:37 | [diff] [blame] | 147 | // The origin that initiated the original navigation. std::nullopt means |
danakj | c492bf8 | 2020-09-09 20:02:44 | [diff] [blame] | 148 | // that the original navigation was browser-initiated (e.g. initiated from a |
| 149 | // trusted surface like the omnibox or the bookmarks bar). |
Arthur Sonzogni | c686e8f | 2024-01-11 08:36:37 | [diff] [blame] | 150 | const std::optional<url::Origin>& initiator_origin() const { |
danakj | c492bf8 | 2020-09-09 20:02:44 | [diff] [blame] | 151 | return initiator_origin_; |
| 152 | } |
| 153 | |
W. James MacLean | 23e90a1 | 2022-12-21 04:38:21 | [diff] [blame] | 154 | // The base url of the initiator of the navigation. This is only set if the |
| 155 | // url is about:blank or about:srcdoc. |
Arthur Sonzogni | c686e8f | 2024-01-11 08:36:37 | [diff] [blame] | 156 | const std::optional<GURL>& initiator_base_url() const { |
W. James MacLean | 23e90a1 | 2022-12-21 04:38:21 | [diff] [blame] | 157 | return initiator_base_url_; |
| 158 | } |
| 159 | |
danakj | c492bf8 | 2020-09-09 20:02:44 | [diff] [blame] | 160 | // The origin of the document the frame has committed. It is optional, since |
| 161 | // pending entries do not have an origin associated with them and the real |
| 162 | // origin is set at commit time. |
| 163 | void set_committed_origin(const url::Origin& origin) { |
| 164 | committed_origin_ = origin; |
| 165 | } |
Arthur Sonzogni | c686e8f | 2024-01-11 08:36:37 | [diff] [blame] | 166 | const std::optional<url::Origin>& committed_origin() const { |
danakj | c492bf8 | 2020-09-09 20:02:44 | [diff] [blame] | 167 | return committed_origin_; |
| 168 | } |
| 169 | |
| 170 | // The redirect chain traversed during this frame navigation, from the initial |
| 171 | // redirecting URL to the final non-redirecting current URL. |
| 172 | void set_redirect_chain(const std::vector<GURL>& redirect_chain) { |
| 173 | redirect_chain_ = redirect_chain; |
| 174 | } |
| 175 | const std::vector<GURL>& redirect_chain() const { return redirect_chain_; } |
| 176 | |
Miyoung Shin | 5d77f7207 | 2020-10-09 15:14:20 | [diff] [blame] | 177 | void SetPageState(const blink::PageState& page_state); |
| 178 | const blink::PageState& page_state() const { return page_state_; } |
danakj | c492bf8 | 2020-09-09 20:02:44 | [diff] [blame] | 179 | |
| 180 | // Remember the set of bindings granted to this FrameNavigationEntry at the |
| 181 | // time of commit, to ensure that we do not grant it additional bindings if we |
| 182 | // navigate back to it in the future. This can only be changed once. |
Avi Drissman | 78865bbb | 2024-08-22 20:57:19 | [diff] [blame] | 183 | // bindings() will return nullopt before the bindings are set. |
| 184 | void SetBindings(BindingsPolicySet bindings); |
| 185 | std::optional<BindingsPolicySet> bindings() const { return bindings_; } |
danakj | c492bf8 | 2020-09-09 20:02:44 | [diff] [blame] | 186 | |
| 187 | // The HTTP method used to navigate. |
| 188 | const std::string& method() const { return method_; } |
| 189 | void set_method(const std::string& method) { method_ = method; } |
| 190 | |
| 191 | // Returns true if the HTTP method was POST. |
| 192 | bool get_has_post_data() { return method() == "POST"; } |
| 193 | |
| 194 | // The id of the post corresponding to this navigation or -1 if the |
| 195 | // navigation was not a POST. |
| 196 | int64_t post_id() const { return post_id_; } |
| 197 | void set_post_id(int64_t post_id) { post_id_ = post_id; } |
| 198 | |
| 199 | // The data sent during a POST navigation. Returns nullptr if the navigation |
| 200 | // is not a POST. |
| 201 | scoped_refptr<network::ResourceRequestBody> GetPostData( |
| 202 | std::string* content_type) const; |
| 203 | |
Titouan Rigoudy | 6ec7040 | 2021-02-02 15:42:19 | [diff] [blame] | 204 | // The policy container policies for this entry. This is needed for local |
| 205 | // schemes, since for them the policy container was inherited by the creator, |
| 206 | // while for network schemes we can reconstruct the policy container by |
| 207 | // parsing the network response. |
| 208 | void set_policy_container_policies( |
| 209 | std::unique_ptr<PolicyContainerPolicies> policies) { |
| 210 | policy_container_policies_ = std::move(policies); |
Antonio Sartori | 78a749f | 2020-11-30 12:03:39 | [diff] [blame] | 211 | } |
Titouan Rigoudy | 6ec7040 | 2021-02-02 15:42:19 | [diff] [blame] | 212 | const PolicyContainerPolicies* policy_container_policies() const { |
| 213 | return policy_container_policies_.get(); |
Antonio Sartori | 78a749f | 2020-11-30 12:03:39 | [diff] [blame] | 214 | } |
| 215 | |
danakj | c492bf8 | 2020-09-09 20:02:44 | [diff] [blame] | 216 | // Optional URLLoaderFactory to facilitate blob URL loading. |
| 217 | scoped_refptr<network::SharedURLLoaderFactory> blob_url_loader_factory() |
| 218 | const { |
| 219 | return blob_url_loader_factory_; |
| 220 | } |
| 221 | void set_blob_url_loader_factory( |
| 222 | scoped_refptr<network::SharedURLLoaderFactory> factory) { |
| 223 | blob_url_loader_factory_ = std::move(factory); |
| 224 | } |
| 225 | |
Domenic Denicola | cc094fb | 2022-03-16 23:40:57 | [diff] [blame] | 226 | bool protect_url_in_navigation_api() { |
| 227 | return protect_url_in_navigation_api_; |
| 228 | } |
| 229 | void set_protect_url_in_navigation_api(bool protect) { |
| 230 | protect_url_in_navigation_api_ = protect; |
Nate Chapin | 63db0d1 | 2022-01-20 22:03:30 | [diff] [blame] | 231 | } |
| 232 | |
Baran Erfani | 2e9e2ad5 | 2024-11-07 19:57:43 | [diff] [blame] | 233 | void set_item_sequence_number_for_testing(int64_t item_sequence_number) { |
| 234 | item_sequence_number_ = item_sequence_number; |
| 235 | } |
| 236 | |
danakj | c492bf8 | 2020-09-09 20:02:44 | [diff] [blame] | 237 | private: |
| 238 | friend class base::RefCounted<FrameNavigationEntry>; |
| 239 | virtual ~FrameNavigationEntry(); |
| 240 | |
| 241 | // WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING |
| 242 | // Add all new fields to |UpdateEntry|. |
| 243 | // TODO(creis): These fields have implications for session restore. This is |
| 244 | // currently managed by NavigationEntry, but the logic will move here. |
| 245 | // WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING |
| 246 | |
| 247 | // See the accessors above for descriptions. |
| 248 | std::string frame_unique_name_; |
Nate Chapin | fbfe5af | 2021-06-10 17:22:08 | [diff] [blame] | 249 | |
Domenic Denicola | cc094fb | 2022-03-16 23:40:57 | [diff] [blame] | 250 | // sequence numbers and the navigation API key are also stored in |
| 251 | // |page_state_|. When SetPageState() is called as part of a restore, it also |
| 252 | // initializes these. |
danakj | c492bf8 | 2020-09-09 20:02:44 | [diff] [blame] | 253 | int64_t item_sequence_number_; |
| 254 | int64_t document_sequence_number_; |
Domenic Denicola | cc094fb | 2022-03-16 23:40:57 | [diff] [blame] | 255 | std::string navigation_api_key_; |
Nate Chapin | fbfe5af | 2021-06-10 17:22:08 | [diff] [blame] | 256 | |
Kevin McNee | 80375747 | 2023-08-22 20:50:11 | [diff] [blame] | 257 | // TODO(nasko, creis): The SiteInstance of a FrameNavigationEntry should |
| 258 | // not change once it has been assigned. See https://crbug.com/849430. |
danakj | c492bf8 | 2020-09-09 20:02:44 | [diff] [blame] | 259 | scoped_refptr<SiteInstanceImpl> site_instance_; |
| 260 | // This member is cleared at commit time and is not persisted. |
| 261 | scoped_refptr<SiteInstanceImpl> source_site_instance_; |
| 262 | GURL url_; |
| 263 | // For a committed navigation, holds the origin of the resulting document. |
| 264 | // TODO(nasko): This should be possible to calculate at ReadyToCommit time |
| 265 | // and verified when receiving the DidCommit IPC. |
Arthur Sonzogni | c686e8f | 2024-01-11 08:36:37 | [diff] [blame] | 266 | std::optional<url::Origin> committed_origin_; |
danakj | c492bf8 | 2020-09-09 20:02:44 | [diff] [blame] | 267 | Referrer referrer_; |
Arthur Sonzogni | c686e8f | 2024-01-11 08:36:37 | [diff] [blame] | 268 | std::optional<url::Origin> initiator_origin_; |
| 269 | std::optional<GURL> initiator_base_url_; |
danakj | c492bf8 | 2020-09-09 20:02:44 | [diff] [blame] | 270 | // This is used when transferring a pending entry from one process to another. |
| 271 | // We also send the main frame's redirect chain through session sync for |
| 272 | // offline analysis. |
| 273 | // It is preserved after commit but should not be persisted. |
| 274 | std::vector<GURL> redirect_chain_; |
| 275 | // TODO(creis): Change this to FrameState. |
Miyoung Shin | 5d77f7207 | 2020-10-09 15:14:20 | [diff] [blame] | 276 | blink::PageState page_state_; |
Avi Drissman | 78865bbb | 2024-08-22 20:57:19 | [diff] [blame] | 277 | // TODO(creis): Persist bindings_. https://crbug.com/40076915. |
| 278 | std::optional<BindingsPolicySet> bindings_; |
danakj | c492bf8 | 2020-09-09 20:02:44 | [diff] [blame] | 279 | std::string method_; |
| 280 | int64_t post_id_; |
| 281 | scoped_refptr<network::SharedURLLoaderFactory> blob_url_loader_factory_; |
| 282 | |
Alison Gale | 770f3fc | 2024-04-27 00:39:58 | [diff] [blame] | 283 | // TODO(crbug.com/40053667): Persist these policies. |
Titouan Rigoudy | 6ec7040 | 2021-02-02 15:42:19 | [diff] [blame] | 284 | std::unique_ptr<PolicyContainerPolicies> policy_container_policies_; |
Nate Chapin | 63db0d1 | 2022-01-20 22:03:30 | [diff] [blame] | 285 | |
| 286 | // If the document represented by this FNE hid its full url from appearing |
| 287 | // in a referrer via a "no-referrer" or "origin" referrer policy, this URL |
Domenic Denicola | cc094fb | 2022-03-16 23:40:57 | [diff] [blame] | 288 | // will be hidden from navigation API history entries as well. |
| 289 | bool protect_url_in_navigation_api_; |
danakj | c492bf8 | 2020-09-09 20:02:44 | [diff] [blame] | 290 | }; |
| 291 | |
| 292 | } // namespace content |
| 293 | |
| 294 | #endif // CONTENT_BROWSER_RENDERER_HOST_FRAME_NAVIGATION_ENTRY_H_ |