Avi Drissman | 4e1b7bc3 | 2022-09-15 14:03:50 | [diff] [blame] | 1 | // Copyright 2013 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_NAVIGATION_ENTRY_IMPL_H_ |
| 6 | #define CONTENT_BROWSER_RENDERER_HOST_NAVIGATION_ENTRY_IMPL_H_ |
| 7 | |
| 8 | #include <stdint.h> |
| 9 | |
| 10 | #include <memory> |
Arthur Sonzogni | c686e8f | 2024-01-11 08:36:37 | [diff] [blame] | 11 | #include <optional> |
danakj | c492bf8 | 2020-09-09 20:02:44 | [diff] [blame] | 12 | #include <string> |
| 13 | #include <vector> |
| 14 | |
| 15 | #include "base/containers/flat_map.h" |
Keishi Hattori | 0e45c02 | 2021-11-27 09:25:52 | [diff] [blame] | 16 | #include "base/memory/raw_ptr.h" |
danakj | c492bf8 | 2020-09-09 20:02:44 | [diff] [blame] | 17 | #include "base/memory/ref_counted.h" |
danakj | c492bf8 | 2020-09-09 20:02:44 | [diff] [blame] | 18 | #include "base/time/time.h" |
| 19 | #include "build/build_config.h" |
| 20 | #include "content/browser/renderer_host/back_forward_cache_metrics.h" |
| 21 | #include "content/browser/renderer_host/frame_navigation_entry.h" |
William Liu | 525ec5a1 | 2024-06-13 12:47:54 | [diff] [blame] | 22 | #include "content/browser/renderer_host/navigation_transitions/navigation_transition_data.h" |
danakj | c492bf8 | 2020-09-09 20:02:44 | [diff] [blame] | 23 | #include "content/browser/site_instance_impl.h" |
Lei Zhang | 7ab31375 | 2021-11-17 01:26:00 | [diff] [blame] | 24 | #include "content/common/content_export.h" |
danakj | c492bf8 | 2020-09-09 20:02:44 | [diff] [blame] | 25 | #include "content/public/browser/favicon_status.h" |
Avi Drissman | bd15364 | 2024-09-03 18:58:05 | [diff] [blame] | 26 | #include "content/public/browser/frame_tree_node_id.h" |
danakj | c492bf8 | 2020-09-09 20:02:44 | [diff] [blame] | 27 | #include "content/public/browser/global_request_id.h" |
| 28 | #include "content/public/browser/navigation_entry.h" |
| 29 | #include "content/public/browser/reload_type.h" |
| 30 | #include "content/public/browser/replaced_navigation_entry_data.h" |
| 31 | #include "content/public/browser/restore_type.h" |
| 32 | #include "content/public/browser/ssl_status.h" |
danakj | c492bf8 | 2020-09-09 20:02:44 | [diff] [blame] | 33 | #include "net/base/isolation_info.h" |
Miyoung Shin | 5d77f7207 | 2020-10-09 15:14:20 | [diff] [blame] | 34 | #include "third_party/blink/public/common/page_state/page_state.h" |
Minggang Wang | b9f3fa9 | 2021-07-01 15:30:31 | [diff] [blame] | 35 | #include "third_party/blink/public/mojom/navigation/navigation_params.mojom-forward.h" |
Mike Jackson | e2aa7af | 2023-05-17 06:45:07 | [diff] [blame] | 36 | #include "third_party/blink/public/mojom/navigation/system_entropy.mojom-forward.h" |
danakj | c492bf8 | 2020-09-09 20:02:44 | [diff] [blame] | 37 | #include "url/origin.h" |
| 38 | |
Minggang Wang | b9f3fa9 | 2021-07-01 15:30:31 | [diff] [blame] | 39 | namespace blink { |
| 40 | struct FramePolicy; |
Yoav Weiss | 8c57395 | 2022-11-17 17:35:13 | [diff] [blame] | 41 | namespace scheduler { |
| 42 | class TaskAttributionId; |
| 43 | } // namespace scheduler |
Minggang Wang | b9f3fa9 | 2021-07-01 15:30:31 | [diff] [blame] | 44 | } // namespace blink |
| 45 | |
danakj | c492bf8 | 2020-09-09 20:02:44 | [diff] [blame] | 46 | namespace content { |
| 47 | |
Carlos Caballero | 40b0efd | 2021-01-26 11:55:00 | [diff] [blame] | 48 | class FrameTreeNode; |
Nate Chapin | 214a86a | 2021-06-21 20:35:57 | [diff] [blame] | 49 | class NavigationEntryRestoreContext; |
| 50 | class NavigationEntryRestoreContextImpl; |
danakj | c492bf8 | 2020-09-09 20:02:44 | [diff] [blame] | 51 | |
| 52 | class CONTENT_EXPORT NavigationEntryImpl : public NavigationEntry { |
| 53 | public: |
Nate Chapin | 9f16907 | 2021-06-09 19:32:37 | [diff] [blame] | 54 | // Determines whether CloneAndReplace will share the existing |
| 55 | // FrameNavigationEntries in the new NavigationEntry or not. |
| 56 | enum class ClonePolicy { kShareFrameEntries, kCloneFrameEntries }; |
| 57 | |
danakj | c492bf8 | 2020-09-09 20:02:44 | [diff] [blame] | 58 | // Represents a tree of FrameNavigationEntries that make up this joint session |
| 59 | // history item. |
| 60 | struct TreeNode { |
| 61 | TreeNode(TreeNode* parent, scoped_refptr<FrameNavigationEntry> frame_entry); |
| 62 | ~TreeNode(); |
| 63 | |
| 64 | // Returns whether this TreeNode corresponds to |frame_tree_node|. If this |
| 65 | // is called on the root TreeNode, we only check if |frame_tree_node| is the |
| 66 | // main frame. Otherwise, we check if the unique name matches. |
| 67 | bool MatchesFrame(FrameTreeNode* frame_tree_node) const; |
| 68 | |
Nate Chapin | 9f16907 | 2021-06-09 19:32:37 | [diff] [blame] | 69 | // Recursively makes a copy of this TreeNode, either sharing |
| 70 | // FrameNavigationEntries or making deep copies depending on |clone_policy|. |
| 71 | // Replaces the TreeNode corresponding to |target_frame_tree_node|, |
| 72 | // clearing all of its children unless |clone_children_of_target| is true. |
| 73 | // This function omits any subframe history items that do not correspond to |
| 74 | // frames actually in the current page, using |current_frame_tree_node| (if |
Nate Chapin | 214a86a | 2021-06-21 20:35:57 | [diff] [blame] | 75 | // present). |restore_context| is used to keep track of the |
| 76 | // FrameNavigationEntries that have been created during a deep clone, and to |
| 77 | // ensure that multiple copies of the same FrameNavigationEntry in different |
| 78 | // NavigationEntries are de-duplicated. |
danakj | c492bf8 | 2020-09-09 20:02:44 | [diff] [blame] | 79 | std::unique_ptr<TreeNode> CloneAndReplace( |
| 80 | scoped_refptr<FrameNavigationEntry> frame_navigation_entry, |
| 81 | bool clone_children_of_target, |
| 82 | FrameTreeNode* target_frame_tree_node, |
| 83 | FrameTreeNode* current_frame_tree_node, |
Nate Chapin | 9f16907 | 2021-06-09 19:32:37 | [diff] [blame] | 84 | TreeNode* parent_node, |
Nate Chapin | 214a86a | 2021-06-21 20:35:57 | [diff] [blame] | 85 | NavigationEntryRestoreContextImpl* restore_context, |
Nate Chapin | 9f16907 | 2021-06-09 19:32:37 | [diff] [blame] | 86 | ClonePolicy clone_policy) const; |
danakj | c492bf8 | 2020-09-09 20:02:44 | [diff] [blame] | 87 | |
| 88 | // The parent of this node. |
Keishi Hattori | 0e45c02 | 2021-11-27 09:25:52 | [diff] [blame] | 89 | raw_ptr<TreeNode> parent; |
danakj | c492bf8 | 2020-09-09 20:02:44 | [diff] [blame] | 90 | |
| 91 | // Ref counted pointer that keeps the FrameNavigationEntry alive as long as |
| 92 | // it is needed by this node's NavigationEntry. |
| 93 | scoped_refptr<FrameNavigationEntry> frame_entry; |
| 94 | |
| 95 | // List of child TreeNodes, which will be deleted when this node is. |
| 96 | std::vector<std::unique_ptr<TreeNode>> children; |
| 97 | }; |
| 98 | |
| 99 | static NavigationEntryImpl* FromNavigationEntry(NavigationEntry* entry); |
| 100 | static const NavigationEntryImpl* FromNavigationEntry( |
| 101 | const NavigationEntry* entry); |
| 102 | static std::unique_ptr<NavigationEntryImpl> FromNavigationEntry( |
| 103 | std::unique_ptr<NavigationEntry> entry); |
| 104 | |
| 105 | NavigationEntryImpl(); |
| 106 | NavigationEntryImpl( |
| 107 | scoped_refptr<SiteInstanceImpl> instance, |
| 108 | const GURL& url, |
| 109 | const Referrer& referrer, |
Arthur Sonzogni | c686e8f | 2024-01-11 08:36:37 | [diff] [blame] | 110 | const std::optional<url::Origin>& initiator_origin, |
| 111 | const std::optional<GURL>& initiator_base_url, |
Jan Wilken Dörrie | aace0cfef | 2021-03-11 22:01:58 | [diff] [blame] | 112 | const std::u16string& title, |
danakj | c492bf8 | 2020-09-09 20:02:44 | [diff] [blame] | 113 | ui::PageTransition transition_type, |
| 114 | bool is_renderer_initiated, |
Rakina Zata Amni | afd3c658 | 2021-11-30 06:19:17 | [diff] [blame] | 115 | scoped_refptr<network::SharedURLLoaderFactory> blob_url_loader_factory, |
| 116 | bool is_initial_entry); |
Peter Boström | 828b902 | 2021-09-21 02:28:43 | [diff] [blame] | 117 | |
| 118 | NavigationEntryImpl(const NavigationEntryImpl&) = delete; |
| 119 | NavigationEntryImpl& operator=(const NavigationEntryImpl&) = delete; |
| 120 | |
danakj | c492bf8 | 2020-09-09 20:02:44 | [diff] [blame] | 121 | ~NavigationEntryImpl() override; |
| 122 | |
| 123 | // NavigationEntry implementation: |
Rakina Zata Amni | afd3c658 | 2021-11-30 06:19:17 | [diff] [blame] | 124 | bool IsInitialEntry() override; |
danakj | c492bf8 | 2020-09-09 20:02:44 | [diff] [blame] | 125 | int GetUniqueID() override; |
| 126 | PageType GetPageType() override; |
| 127 | void SetURL(const GURL& url) override; |
Elad Alon | 32044f53 | 2025-03-04 22:16:03 | [diff] [blame] | 128 | const GURL& GetURL() const override; |
danakj | c492bf8 | 2020-09-09 20:02:44 | [diff] [blame] | 129 | void SetBaseURLForDataURL(const GURL& url) override; |
| 130 | const GURL& GetBaseURLForDataURL() override; |
Xiaohan Wang | 7f8052e0 | 2022-01-14 18:44:28 | [diff] [blame] | 131 | #if BUILDFLAG(IS_ANDROID) |
danakj | c492bf8 | 2020-09-09 20:02:44 | [diff] [blame] | 132 | void SetDataURLAsString( |
| 133 | scoped_refptr<base::RefCountedString> data_url) override; |
| 134 | const scoped_refptr<const base::RefCountedString>& GetDataURLAsString() |
| 135 | override; |
| 136 | #endif |
| 137 | void SetReferrer(const Referrer& referrer) override; |
| 138 | const Referrer& GetReferrer() override; |
| 139 | void SetVirtualURL(const GURL& url) override; |
Elad Alon | 32044f53 | 2025-03-04 22:16:03 | [diff] [blame] | 140 | const GURL& GetVirtualURL() const override; |
Sky Malice | 5e2945ca | 2024-07-09 17:38:25 | [diff] [blame] | 141 | void SetTitle(std::u16string title) override; |
Jan Wilken Dörrie | aace0cfef | 2021-03-11 22:01:58 | [diff] [blame] | 142 | const std::u16string& GetTitle() override; |
Stanley Hon | f83c4b8b | 2025-01-08 00:52:30 | [diff] [blame] | 143 | void SetApplicationTitle(const std::u16string& application_title) override; |
| 144 | const std::optional<std::u16string>& GetApplicationTitle() override; |
Nate Chapin | 214a86a | 2021-06-21 20:35:57 | [diff] [blame] | 145 | void SetPageState(const blink::PageState& state, |
| 146 | NavigationEntryRestoreContext* context) override; |
Miyoung Shin | 5d77f7207 | 2020-10-09 15:14:20 | [diff] [blame] | 147 | blink::PageState GetPageState() override; |
Jan Wilken Dörrie | aace0cfef | 2021-03-11 22:01:58 | [diff] [blame] | 148 | const std::u16string& GetTitleForDisplay() override; |
danakj | c492bf8 | 2020-09-09 20:02:44 | [diff] [blame] | 149 | bool IsViewSourceMode() override; |
| 150 | void SetTransitionType(ui::PageTransition transition_type) override; |
| 151 | ui::PageTransition GetTransitionType() override; |
| 152 | const GURL& GetUserTypedURL() override; |
| 153 | void SetHasPostData(bool has_post_data) override; |
| 154 | bool GetHasPostData() override; |
| 155 | void SetPostID(int64_t post_id) override; |
| 156 | int64_t GetPostID() override; |
| 157 | void SetPostData( |
| 158 | const scoped_refptr<network::ResourceRequestBody>& data) override; |
| 159 | scoped_refptr<network::ResourceRequestBody> GetPostData() override; |
| 160 | FaviconStatus& GetFavicon() override; |
| 161 | SSLStatus& GetSSL() override; |
| 162 | void SetOriginalRequestURL(const GURL& original_url) override; |
| 163 | const GURL& GetOriginalRequestURL() override; |
| 164 | void SetIsOverridingUserAgent(bool override_ua) override; |
| 165 | bool GetIsOverridingUserAgent() override; |
| 166 | void SetTimestamp(base::Time timestamp) override; |
| 167 | base::Time GetTimestamp() override; |
| 168 | void SetCanLoadLocalResources(bool allow) override; |
| 169 | bool GetCanLoadLocalResources() override; |
| 170 | void SetHttpStatusCode(int http_status_code) override; |
| 171 | int GetHttpStatusCode() override; |
| 172 | void SetRedirectChain(const std::vector<GURL>& redirects) override; |
| 173 | const std::vector<GURL>& GetRedirectChain() override; |
Arthur Sonzogni | c686e8f | 2024-01-11 08:36:37 | [diff] [blame] | 174 | const std::optional<ReplacedNavigationEntryData>& GetReplacedEntryData() |
danakj | c492bf8 | 2020-09-09 20:02:44 | [diff] [blame] | 175 | override; |
| 176 | bool IsRestored() override; |
| 177 | std::string GetExtraHeaders() override; |
| 178 | void AddExtraHeaders(const std::string& extra_headers) override; |
| 179 | int64_t GetMainFrameDocumentSequenceNumber() override; |
| 180 | |
| 181 | // Creates a copy of this NavigationEntryImpl that can be modified |
Nate Chapin | 9f16907 | 2021-06-09 19:32:37 | [diff] [blame] | 182 | // independently from the original, but that shares FrameNavigationEntries. |
| 183 | // Does not copy any value that would be cleared in ResetForCommit. Unlike |
| 184 | // |CloneAndReplace|, this does not check whether the subframe history items |
| 185 | // are for frames that are still in the current page. |
danakj | c492bf8 | 2020-09-09 20:02:44 | [diff] [blame] | 186 | std::unique_ptr<NavigationEntryImpl> Clone() const; |
| 187 | |
Nate Chapin | 9f16907 | 2021-06-09 19:32:37 | [diff] [blame] | 188 | // Creates a true deep copy of this NavigationEntryImpl. The |
| 189 | // FrameNavigationEntries are cloned rather than merely taking a refptr to the |
| 190 | // original. |
Nate Chapin | 214a86a | 2021-06-21 20:35:57 | [diff] [blame] | 191 | // |restore_context| is used when cloning a vector of NavigationEntryImpls to |
| 192 | // ensure that FrameNavigationEntries that are shared across multiple entries |
| 193 | // retain that relationship in the cloned entries. |
| 194 | std::unique_ptr<NavigationEntryImpl> CloneWithoutSharing( |
| 195 | NavigationEntryRestoreContextImpl* restore_context) const; |
Nate Chapin | 9f16907 | 2021-06-09 19:32:37 | [diff] [blame] | 196 | |
danakj | c492bf8 | 2020-09-09 20:02:44 | [diff] [blame] | 197 | // Like |Clone|, but replaces the FrameNavigationEntry corresponding to |
| 198 | // |target_frame_tree_node| with |frame_entry|, clearing all of its children |
| 199 | // unless |clone_children_of_target| is true. This function omits any |
| 200 | // subframe history items that do not correspond to frames actually in the |
| 201 | // current page, using |root_frame_tree_node| (if present). |
danakj | c492bf8 | 2020-09-09 20:02:44 | [diff] [blame] | 202 | std::unique_ptr<NavigationEntryImpl> CloneAndReplace( |
| 203 | scoped_refptr<FrameNavigationEntry> frame_entry, |
| 204 | bool clone_children_of_target, |
| 205 | FrameTreeNode* target_frame_tree_node, |
| 206 | FrameTreeNode* root_frame_tree_node) const; |
| 207 | |
| 208 | // Helper functions to construct NavigationParameters for a navigation to this |
| 209 | // NavigationEntry. |
Minggang Wang | b9f3fa9 | 2021-07-01 15:30:31 | [diff] [blame] | 210 | blink::mojom::CommonNavigationParamsPtr ConstructCommonNavigationParams( |
danakj | c492bf8 | 2020-09-09 20:02:44 | [diff] [blame] | 211 | const FrameNavigationEntry& frame_entry, |
| 212 | const scoped_refptr<network::ResourceRequestBody>& post_body, |
| 213 | const GURL& dest_url, |
| 214 | blink::mojom::ReferrerPtr dest_referrer, |
Minggang Wang | b9f3fa9 | 2021-07-01 15:30:31 | [diff] [blame] | 215 | blink::mojom::NavigationType navigation_type, |
Charlie Reis | e1d9b818 | 2025-04-02 04:32:12 | [diff] [blame] | 216 | base::TimeTicks actual_navigation_start, |
danakj | c492bf8 | 2020-09-09 20:02:44 | [diff] [blame] | 217 | base::TimeTicks navigation_start, |
| 218 | base::TimeTicks input_start); |
Minggang Wang | b9f3fa9 | 2021-07-01 15:30:31 | [diff] [blame] | 219 | blink::mojom::CommitNavigationParamsPtr ConstructCommitNavigationParams( |
danakj | c492bf8 | 2020-09-09 20:02:44 | [diff] [blame] | 220 | const FrameNavigationEntry& frame_entry, |
| 221 | const GURL& original_url, |
danakj | c492bf8 | 2020-09-09 20:02:44 | [diff] [blame] | 222 | const std::string& original_method, |
| 223 | const base::flat_map<std::string, bool>& subframe_unique_names, |
| 224 | bool intended_as_new_entry, |
| 225 | int pending_offset_to_send, |
| 226 | int current_offset_to_send, |
| 227 | int current_length_to_send, |
Liam Brady | d2a41e15 | 2022-07-19 13:58:48 | [diff] [blame] | 228 | const blink::FramePolicy& frame_policy, |
Yoav Weiss | 8c57395 | 2022-11-17 17:35:13 | [diff] [blame] | 229 | bool ancestor_or_self_has_cspee, |
Mike Jackson | e2aa7af | 2023-05-17 06:45:07 | [diff] [blame] | 230 | blink::mojom::SystemEntropy system_entropy_at_navigation_start, |
Arthur Sonzogni | c686e8f | 2024-01-11 08:36:37 | [diff] [blame] | 231 | std::optional<blink::scheduler::TaskAttributionId> |
Yoav Weiss | 8c57395 | 2022-11-17 17:35:13 | [diff] [blame] | 232 | soft_navigation_heuristics_task_id); |
danakj | c492bf8 | 2020-09-09 20:02:44 | [diff] [blame] | 233 | |
| 234 | // Once a navigation entry is committed, we should no longer track several |
| 235 | // pieces of non-persisted state, as documented on the members below. |
| 236 | // |frame_entry| is the FrameNavigationEntry for the frame that committed |
| 237 | // the navigation. It can be null. |
| 238 | void ResetForCommit(FrameNavigationEntry* frame_entry); |
| 239 | |
| 240 | // Exposes the tree of FrameNavigationEntries that make up this joint session |
| 241 | // history item. |
danakj | c492bf8 | 2020-09-09 20:02:44 | [diff] [blame] | 242 | TreeNode* root_node() const { return frame_tree_.get(); } |
| 243 | |
| 244 | // Finds the TreeNode associated with |frame_tree_node|, if any. |
| 245 | NavigationEntryImpl::TreeNode* GetTreeNode( |
| 246 | FrameTreeNode* frame_tree_node) const; |
| 247 | |
| 248 | // Finds the TreeNode associated with |frame_tree_node_id| to add or update |
| 249 | // its FrameNavigationEntry. A new FrameNavigationEntry is added if none |
| 250 | // exists, or else the existing one (which might be shared with other |
Nate Chapin | 9f16907 | 2021-06-09 19:32:37 | [diff] [blame] | 251 | // NavigationEntries) is updated or replaced (based on |update_policy|) with |
| 252 | // the given parameters. |
danakj | c492bf8 | 2020-09-09 20:02:44 | [diff] [blame] | 253 | // Does nothing if there is no entry already and |url| is about:blank, since |
| 254 | // that does not count as a real commit. |
Nate Chapin | 9f16907 | 2021-06-09 19:32:37 | [diff] [blame] | 255 | enum class UpdatePolicy { kUpdate, kReplace }; |
danakj | c492bf8 | 2020-09-09 20:02:44 | [diff] [blame] | 256 | void AddOrUpdateFrameEntry( |
| 257 | FrameTreeNode* frame_tree_node, |
Nate Chapin | 9f16907 | 2021-06-09 19:32:37 | [diff] [blame] | 258 | UpdatePolicy update_policy, |
danakj | c492bf8 | 2020-09-09 20:02:44 | [diff] [blame] | 259 | int64_t item_sequence_number, |
| 260 | int64_t document_sequence_number, |
Domenic Denicola | cc094fb | 2022-03-16 23:40:57 | [diff] [blame] | 261 | const std::string& navigation_api_key, |
danakj | c492bf8 | 2020-09-09 20:02:44 | [diff] [blame] | 262 | SiteInstanceImpl* site_instance, |
| 263 | scoped_refptr<SiteInstanceImpl> source_site_instance, |
| 264 | const GURL& url, |
Arthur Sonzogni | c686e8f | 2024-01-11 08:36:37 | [diff] [blame] | 265 | const std::optional<url::Origin>& origin, |
danakj | c492bf8 | 2020-09-09 20:02:44 | [diff] [blame] | 266 | const Referrer& referrer, |
Arthur Sonzogni | c686e8f | 2024-01-11 08:36:37 | [diff] [blame] | 267 | const std::optional<url::Origin>& initiator_origin, |
| 268 | const std::optional<GURL>& initiator_base_url, |
danakj | c492bf8 | 2020-09-09 20:02:44 | [diff] [blame] | 269 | const std::vector<GURL>& redirect_chain, |
Miyoung Shin | 5d77f7207 | 2020-10-09 15:14:20 | [diff] [blame] | 270 | const blink::PageState& page_state, |
danakj | c492bf8 | 2020-09-09 20:02:44 | [diff] [blame] | 271 | const std::string& method, |
| 272 | int64_t post_id, |
| 273 | scoped_refptr<network::SharedURLLoaderFactory> blob_url_loader_factory, |
Titouan Rigoudy | 6ec7040 | 2021-02-02 15:42:19 | [diff] [blame] | 274 | std::unique_ptr<PolicyContainerPolicies> policy_container_policies); |
danakj | c492bf8 | 2020-09-09 20:02:44 | [diff] [blame] | 275 | |
| 276 | // Returns the FrameNavigationEntry corresponding to |frame_tree_node|, if |
| 277 | // there is one in this NavigationEntry. |
| 278 | FrameNavigationEntry* GetFrameEntry(FrameTreeNode* frame_tree_node) const; |
| 279 | |
Nate Chapin | 9eb16be7 | 2022-09-23 22:54:31 | [diff] [blame] | 280 | // Calls |on_frame_entry| for each FrameNavigationEntry in this |
| 281 | // NavigationEntry. More efficient than calling GetFrameEntry() N times while |
| 282 | // iterating over the current tree of FrameTreeNodes. |
| 283 | using FrameEntryIterationCallback = |
| 284 | base::FunctionRef<void(FrameNavigationEntry*)>; |
| 285 | void ForEachFrameEntry(FrameEntryIterationCallback on_frame_entry); |
| 286 | |
danakj | c492bf8 | 2020-09-09 20:02:44 | [diff] [blame] | 287 | // Returns a map of frame unique names to |is_about_blank| for immediate |
| 288 | // children of the TreeNode associated with |frame_tree_node|. The renderer |
| 289 | // process will use this list of names to know whether to ask the browser |
| 290 | // process for a history item when new subframes are created during a |
| 291 | // back/forward navigation. (|is_about_blank| can be used to skip the request |
| 292 | // if the frame's default URL is about:blank and the history item would be a |
| 293 | // no-op. See https://crbug.com/657896.) |
| 294 | // TODO(creis): Send a data structure that also contains all corresponding |
| 295 | // same-process PageStates for the whole subtree, so that the renderer process |
| 296 | // only needs to ask the browser process to handle the cross-process cases. |
| 297 | // See https://crbug.com/639842. |
| 298 | base::flat_map<std::string, bool> GetSubframeUniqueNames( |
| 299 | FrameTreeNode* frame_tree_node) const; |
| 300 | |
| 301 | // Walks the tree of FrameNavigationEntries to find entries with |origin| so |
| 302 | // their isolation status can be registered. |
W. James MacLean | c07dc41b | 2022-07-25 18:52:16 | [diff] [blame] | 303 | void RegisterExistingOriginAsHavingDefaultIsolation( |
| 304 | const url::Origin& origin); |
danakj | c492bf8 | 2020-09-09 20:02:44 | [diff] [blame] | 305 | |
| 306 | // Removes any subframe FrameNavigationEntries that match the unique name of |
| 307 | // |frame_tree_node|, and all of their children. There should be at most one, |
| 308 | // since collisions are avoided but leave old FrameNavigationEntries in the |
| 309 | // tree after their frame has been detached. |
| 310 | // |
| 311 | // If |only_if_different_position| is specified, then the removal is only |
| 312 | // done if the found FNE is in a different tree position than the |
| 313 | // |frame_tree_node|. |
| 314 | void RemoveEntryForFrame(FrameTreeNode* frame_tree_node, |
| 315 | bool only_if_different_position); |
| 316 | |
Yuzu Saijo | 29f96ca9 | 2022-12-08 04:54:12 | [diff] [blame] | 317 | // Update NotRestoredReasons for |navigation_request| which should be a |
| 318 | // cross-document main frame navigation and is not served from back/forward |
| 319 | // cache. This will create a metrics object if there is none, which can happen |
| 320 | // when doing a session restore. |
| 321 | void UpdateBackForwardCacheNotRestoredReasons( |
| 322 | NavigationRequest* navigation_request); |
| 323 | |
danakj | c492bf8 | 2020-09-09 20:02:44 | [diff] [blame] | 324 | void set_unique_id(int unique_id) { unique_id_ = unique_id; } |
| 325 | |
| 326 | void set_started_from_context_menu(bool started_from_context_menu) { |
| 327 | started_from_context_menu_ = started_from_context_menu; |
| 328 | } |
| 329 | |
| 330 | bool has_started_from_context_menu() const { |
| 331 | return started_from_context_menu_; |
| 332 | } |
| 333 | |
| 334 | // The SiteInstance represents which pages must share processes. This is a |
| 335 | // reference counted pointer to a shared SiteInstance. |
| 336 | // |
| 337 | // Note that the SiteInstance should usually not be changed after it is set, |
| 338 | // but this may happen if the NavigationEntry was cloned and needs to use a |
| 339 | // different SiteInstance. |
danakj | c492bf8 | 2020-09-09 20:02:44 | [diff] [blame] | 340 | SiteInstanceImpl* site_instance() const { |
| 341 | return frame_tree_->frame_entry->site_instance(); |
| 342 | } |
| 343 | |
| 344 | // The |source_site_instance| is used to identify the SiteInstance of the |
| 345 | // frame that initiated the navigation. It is set on the |
| 346 | // FrameNavigationEntry for the main frame. |
| 347 | void set_source_site_instance( |
| 348 | scoped_refptr<SiteInstanceImpl> source_site_instance) { |
| 349 | root_node()->frame_entry->set_source_site_instance( |
| 350 | source_site_instance.get()); |
| 351 | } |
| 352 | |
| 353 | void set_page_type(PageType page_type) { page_type_ = page_type; } |
| 354 | |
| 355 | bool has_virtual_url() const { return !virtual_url_.is_empty(); } |
| 356 | |
| 357 | bool update_virtual_url_with_url() const { |
| 358 | return update_virtual_url_with_url_; |
| 359 | } |
| 360 | void set_update_virtual_url_with_url(bool update) { |
| 361 | update_virtual_url_with_url_ = update; |
| 362 | } |
| 363 | |
| 364 | // Extra headers (separated by \r\n) to send during the request. |
| 365 | void set_extra_headers(const std::string& extra_headers) { |
| 366 | extra_headers_ = extra_headers; |
| 367 | } |
| 368 | const std::string& extra_headers() const { return extra_headers_; } |
| 369 | |
| 370 | // Whether this (pending) navigation is renderer-initiated. Resets to false |
| 371 | // for all types of navigations after commit. |
| 372 | void set_is_renderer_initiated(bool is_renderer_initiated) { |
| 373 | is_renderer_initiated_ = is_renderer_initiated; |
| 374 | } |
| 375 | bool is_renderer_initiated() const { return is_renderer_initiated_; } |
| 376 | |
| 377 | void set_user_typed_url(const GURL& user_typed_url) { |
| 378 | user_typed_url_ = user_typed_url; |
| 379 | } |
| 380 | |
danakj | f26536bf | 2020-09-10 00:46:13 | [diff] [blame] | 381 | // The RestoreType for this entry. This is set if the entry was restored. This |
danakj | c492bf8 | 2020-09-09 20:02:44 | [diff] [blame] | 382 | // is set to RestoreType::NONE once the entry is loaded. |
| 383 | void set_restore_type(RestoreType type) { restore_type_ = type; } |
| 384 | RestoreType restore_type() const { return restore_type_; } |
| 385 | |
| 386 | // The ReloadType for this entry. This is set when a reload is requested. |
| 387 | // This is set to ReloadType::NONE if the entry isn't for a reload, or once |
| 388 | // the entry is loaded. |
| 389 | void set_reload_type(ReloadType type) { reload_type_ = type; } |
| 390 | ReloadType reload_type() const { return reload_type_; } |
| 391 | |
danakj | c492bf8 | 2020-09-09 20:02:44 | [diff] [blame] | 392 | // Whether this (pending) navigation should clear the session history. Resets |
| 393 | // to false after commit. |
| 394 | bool should_clear_history_list() const { return should_clear_history_list_; } |
| 395 | void set_should_clear_history_list(bool should_clear_history_list) { |
| 396 | should_clear_history_list_ = should_clear_history_list; |
| 397 | } |
| 398 | |
| 399 | // Indicates which FrameTreeNode to navigate. Currently only used if the |
| 400 | // --site-per-process flag is passed. |
Avi Drissman | bd15364 | 2024-09-03 18:58:05 | [diff] [blame] | 401 | FrameTreeNodeId frame_tree_node_id() const { return frame_tree_node_id_; } |
| 402 | void set_frame_tree_node_id(FrameTreeNodeId frame_tree_node_id) { |
danakj | c492bf8 | 2020-09-09 20:02:44 | [diff] [blame] | 403 | frame_tree_node_id_ = frame_tree_node_id; |
| 404 | } |
| 405 | |
| 406 | // Returns the history URL for a data URL to use in Blink. |
| 407 | GURL GetHistoryURLForDataURL(); |
| 408 | |
| 409 | // These flags are set when the navigation controller gets notified of an SSL |
| 410 | // error while a navigation is pending. |
| 411 | void set_ssl_error(bool error) { ssl_error_ = error; } |
| 412 | bool ssl_error() const { return ssl_error_; } |
| 413 | |
| 414 | bool has_user_gesture() const { return has_user_gesture_; } |
| 415 | |
| 416 | void set_has_user_gesture(bool has_user_gesture) { |
| 417 | has_user_gesture_ = has_user_gesture; |
| 418 | } |
| 419 | |
| 420 | void set_isolation_info(const net::IsolationInfo& isolation_info) { |
| 421 | isolation_info_ = isolation_info; |
| 422 | } |
| 423 | |
Arthur Sonzogni | c686e8f | 2024-01-11 08:36:37 | [diff] [blame] | 424 | const std::optional<net::IsolationInfo>& isolation_info() const { |
danakj | c492bf8 | 2020-09-09 20:02:44 | [diff] [blame] | 425 | return isolation_info_; |
| 426 | } |
| 427 | |
| 428 | // Stores a record of the what was committed in this NavigationEntry's main |
| 429 | // frame before it was replaced (e.g. by history.replaceState()). |
| 430 | void set_replaced_entry_data(const ReplacedNavigationEntryData& data) { |
| 431 | replaced_entry_data_ = data; |
| 432 | } |
| 433 | |
| 434 | // See comment for should_skip_on_back_forward_ui_. |
| 435 | bool should_skip_on_back_forward_ui() const { |
| 436 | return should_skip_on_back_forward_ui_; |
| 437 | } |
| 438 | |
| 439 | void set_should_skip_on_back_forward_ui(bool should_skip) { |
| 440 | should_skip_on_back_forward_ui_ = should_skip; |
| 441 | } |
| 442 | |
| 443 | BackForwardCacheMetrics* back_forward_cache_metrics() { |
| 444 | return back_forward_cache_metrics_.get(); |
| 445 | } |
| 446 | |
Yuzu Saijo | a725585f | 2022-11-28 04:14:03 | [diff] [blame] | 447 | scoped_refptr<BackForwardCacheMetrics> TakeBackForwardCacheMetrics() { |
| 448 | return std::move(back_forward_cache_metrics_); |
| 449 | } |
| 450 | |
danakj | c492bf8 | 2020-09-09 20:02:44 | [diff] [blame] | 451 | void set_back_forward_cache_metrics( |
| 452 | scoped_refptr<BackForwardCacheMetrics> metrics) { |
| 453 | DCHECK(metrics); |
| 454 | DCHECK(!back_forward_cache_metrics_); |
| 455 | back_forward_cache_metrics_ = metrics; |
| 456 | } |
| 457 | |
Rakina Zata Amni | f297a80 | 2022-01-18 03:53:43 | [diff] [blame] | 458 | // Whether this NavigationEntry is the initial NavigationEntry or not, and |
| 459 | // whether it's for the initial empty document or the synchronously |
| 460 | // committed about:blank document. The original initial NavigationEntry is |
| 461 | // created when the FrameTree is created, so it might not be associated with |
| 462 | // any navigation, but represents a placeholder NavigationEntry for the |
| 463 | // "initial empty document", which commits in the renderer on frame creation |
| 464 | // but doesn't notify the browser of the commit. However, more initial |
| 465 | // NavigationEntries might be created after that in response to navigations, |
| 466 | // and update or replace the original NavigationEntry. The initial |
| 467 | // NavigationEntry will only get replaced with a non-initial NavigationEntry |
| 468 | // by the first navigation that satisfies all of the following conditions: |
| 469 | // 1. Happens on the main frame |
| 470 | // 2. Classified as NEW_ENTRY (won't reuse the NavigationEntry) |
| 471 | // 3. Is not the synchronous about:blank commit |
| 472 | // So the "initial" status will be retained/copied to the new |
| 473 | // NavigationEntry on subframe navigations, or when the NavigationEntry is |
| 474 | // reused/classified as EXISTING_ENTRY (same-document navigations, |
| 475 | // renderer-initiated reloads), or on the synchronous about:blank commit. |
| 476 | // Some other important properties of initial NavigationEntries: |
| 477 | // - The initial NavigationEntry always gets reused or replaced on the next |
| 478 | // navigation (potentially by another initial NavigationEntry), so if there |
| 479 | // is an initial NavigationEntry in the session history, it must be the only |
| 480 | // NavigationEntry (as it is impossible to append to session history if the |
| 481 | // initial NavigationEntry exists), which means it's not possible to do |
| 482 | // a history navigation to an initial NavigationEntry. |
| 483 | // - The initial NavigationEntry never gets restored on session restore, |
| 484 | // because we never restore tabs with only the initial NavigationEntry. |
| 485 | enum class InitialNavigationEntryState { |
| 486 | // An initial NavigationEntry for the initial empty document or a |
| 487 | // renderer-reloaded initial empty document. |
| 488 | kInitialNotForSynchronousAboutBlank, |
| 489 | // An initial NavigationEntry for the synchronously committed about:blank |
| 490 | // document. |
| 491 | kInitialForSynchronousAboutBlank, |
| 492 | // Not an initial NavigationEntry. |
| 493 | kNonInitial |
| 494 | }; |
| 495 | |
| 496 | bool IsInitialEntryNotForSynchronousAboutBlank() { |
| 497 | return initial_navigation_entry_state_ == |
| 498 | InitialNavigationEntryState::kInitialNotForSynchronousAboutBlank; |
| 499 | } |
| 500 | |
| 501 | bool IsInitialEntryForSynchronousAboutBlank() { |
| 502 | return initial_navigation_entry_state_ == |
| 503 | InitialNavigationEntryState::kInitialForSynchronousAboutBlank; |
| 504 | } |
| 505 | |
| 506 | void set_initial_navigation_entry_state( |
| 507 | InitialNavigationEntryState initial_navigation_entry_state) { |
| 508 | initial_navigation_entry_state_ = initial_navigation_entry_state; |
| 509 | } |
| 510 | |
| 511 | InitialNavigationEntryState initial_navigation_entry_state() { |
| 512 | return initial_navigation_entry_state_; |
Rakina Zata Amni | a4e2722 | 2021-12-22 01:05:00 | [diff] [blame] | 513 | } |
| 514 | |
William Liu | 525ec5a1 | 2024-06-13 12:47:54 | [diff] [blame] | 515 | NavigationTransitionData& navigation_transition_data() { |
| 516 | return navigation_transition_data_; |
| 517 | } |
| 518 | const NavigationTransitionData& navigation_transition_data() const { |
| 519 | return navigation_transition_data_; |
William Liu | 7bedaf8e | 2024-05-16 17:15:32 | [diff] [blame] | 520 | } |
| 521 | |
danakj | c492bf8 | 2020-09-09 20:02:44 | [diff] [blame] | 522 | private: |
Nate Chapin | 9f16907 | 2021-06-09 19:32:37 | [diff] [blame] | 523 | std::unique_ptr<NavigationEntryImpl> CloneAndReplaceInternal( |
| 524 | scoped_refptr<FrameNavigationEntry> frame_entry, |
| 525 | bool clone_children_of_target, |
| 526 | FrameTreeNode* target_frame_tree_node, |
| 527 | FrameTreeNode* root_frame_tree_node, |
Nate Chapin | 214a86a | 2021-06-21 20:35:57 | [diff] [blame] | 528 | NavigationEntryRestoreContextImpl* restore_context, |
Nate Chapin | 9f16907 | 2021-06-09 19:32:37 | [diff] [blame] | 529 | ClonePolicy clone_policy) const; |
| 530 | |
danakj | c492bf8 | 2020-09-09 20:02:44 | [diff] [blame] | 531 | // WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING |
| 532 | // Session/Tab restore save portions of this class so that it can be recreated |
| 533 | // later. If you add a new field that needs to be persisted you'll have to |
| 534 | // update SessionService/TabRestoreService and Android WebView |
| 535 | // state_serializer.cc appropriately. |
| 536 | // For all new fields, update |Clone| and possibly |ResetForCommit|. |
| 537 | // WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING |
| 538 | |
| 539 | // Tree of FrameNavigationEntries, one for each frame on the page. |
Nate Chapin | 9f16907 | 2021-06-09 19:32:37 | [diff] [blame] | 540 | // FrameNavigationEntries may be shared with other NavigationEntries; |
| 541 | // TreeNodes are not shared. |
danakj | c492bf8 | 2020-09-09 20:02:44 | [diff] [blame] | 542 | std::unique_ptr<TreeNode> frame_tree_; |
| 543 | |
| 544 | // See the accessors above for descriptions. |
| 545 | int unique_id_; |
| 546 | PageType page_type_; |
| 547 | GURL virtual_url_; |
| 548 | bool update_virtual_url_with_url_; |
Jan Wilken Dörrie | aace0cfef | 2021-03-11 22:01:58 | [diff] [blame] | 549 | std::u16string title_; |
Stanley Hon | f83c4b8b | 2025-01-08 00:52:30 | [diff] [blame] | 550 | // The application title is optional and may be empty. If set to a non-empty |
| 551 | // value, a web app displayed in an app window may use this string instead of |
| 552 | // the regular title. See |
Haben Foto | 533aa35 | 2024-01-09 22:01:16 | [diff] [blame] | 553 | // https://github.com/MicrosoftEdge/MSEdgeExplainers/blob/main/DocumentSubtitle/explainer.md |
Stanley Hon | f83c4b8b | 2025-01-08 00:52:30 | [diff] [blame] | 554 | std::optional<std::u16string> application_title_; |
danakj | c492bf8 | 2020-09-09 20:02:44 | [diff] [blame] | 555 | FaviconStatus favicon_; |
| 556 | SSLStatus ssl_; |
| 557 | ui::PageTransition transition_type_; |
| 558 | GURL user_typed_url_; |
| 559 | RestoreType restore_type_; |
| 560 | GURL original_request_url_; |
| 561 | bool is_overriding_user_agent_; |
| 562 | base::Time timestamp_; |
| 563 | int http_status_code_; |
| 564 | |
| 565 | // This member is not persisted with session restore because it is transient. |
| 566 | // If the post request succeeds, this field is cleared since the same |
| 567 | // information is stored in PageState. It is also only shallow copied with |
| 568 | // compiler provided copy constructor. Cleared in |ResetForCommit|. |
| 569 | scoped_refptr<network::ResourceRequestBody> post_data_; |
| 570 | |
| 571 | // This member is not persisted with session restore. |
| 572 | std::string extra_headers_; |
| 573 | |
| 574 | // Used for specifying base URL for pages loaded via data URLs. Only used and |
| 575 | // persisted by Android WebView. |
| 576 | GURL base_url_for_data_url_; |
| 577 | |
Xiaohan Wang | 7f8052e0 | 2022-01-14 18:44:28 | [diff] [blame] | 578 | #if BUILDFLAG(IS_ANDROID) |
danakj | c492bf8 | 2020-09-09 20:02:44 | [diff] [blame] | 579 | // Used for passing really big data URLs from browser to renderers. Only used |
| 580 | // and persisted by Android WebView. |
| 581 | scoped_refptr<const base::RefCountedString> data_url_as_string_; |
| 582 | #endif |
| 583 | |
| 584 | // Whether the entry, while loading, was created for a renderer-initiated |
| 585 | // navigation. This dictates whether the URL should be displayed before the |
| 586 | // navigation commits. It is cleared in |ResetForCommit| and not persisted. |
| 587 | bool is_renderer_initiated_; |
| 588 | |
| 589 | // This is a cached version of the result of GetTitleForDisplay. It prevents |
| 590 | // us from having to do URL formatting on the URL every time the title is |
| 591 | // displayed. When the URL, virtual URL, or title is set, this should be |
| 592 | // cleared to force a refresh. |
Jan Wilken Dörrie | aace0cfef | 2021-03-11 22:01:58 | [diff] [blame] | 593 | mutable std::u16string cached_display_title_; |
danakj | c492bf8 | 2020-09-09 20:02:44 | [diff] [blame] | 594 | |
danakj | c492bf8 | 2020-09-09 20:02:44 | [diff] [blame] | 595 | // This is set to true when this entry's navigation should clear the session |
| 596 | // history both on the renderer and browser side. The browser side history |
| 597 | // won't be cleared until the renderer has committed this navigation. This |
| 598 | // entry is not persisted by the session restore system, as it is always |
| 599 | // cleared in |ResetForCommit|. |
| 600 | bool should_clear_history_list_; |
| 601 | |
| 602 | // Set when this entry should be able to access local file:// resources. This |
| 603 | // value is not needed after the entry commits and is not persisted. |
| 604 | bool can_load_local_resources_; |
| 605 | |
Avi Drissman | bd15364 | 2024-09-03 18:58:05 | [diff] [blame] | 606 | // If valid, this indicates which FrameTreeNode to navigate. This field is |
danakj | c492bf8 | 2020-09-09 20:02:44 | [diff] [blame] | 607 | // not persisted because it is experimental and only used when the |
| 608 | // --site-per-process flag is passed. It is cleared in |ResetForCommit| |
| 609 | // because we only use it while the navigation is pending. |
| 610 | // TODO(creis): Move this to FrameNavigationEntry. |
Avi Drissman | bd15364 | 2024-09-03 18:58:05 | [diff] [blame] | 611 | FrameTreeNodeId frame_tree_node_id_; |
danakj | c492bf8 | 2020-09-09 20:02:44 | [diff] [blame] | 612 | |
| 613 | // Whether the URL load carries a user gesture. |
| 614 | bool has_user_gesture_; |
| 615 | |
| 616 | // Used to store ReloadType for the entry. This is ReloadType::NONE for |
| 617 | // non-reload navigations. Reset at commit and not persisted. |
| 618 | ReloadType reload_type_; |
| 619 | |
| 620 | // Determine if the navigation was started within a context menu. |
| 621 | bool started_from_context_menu_; |
| 622 | |
| 623 | // Set to true if the navigation controller gets notified about a SSL error |
| 624 | // for a pending navigation. Defaults to false. |
| 625 | bool ssl_error_; |
| 626 | |
| 627 | // The net::IsolationInfo for this NavigationEntry. If provided, this |
| 628 | // determines the IsolationInfo to be used when navigating to this |
| 629 | // NavigationEntry; otherwise, it is determined based on the navigating frame |
| 630 | // and top frame origins. For example, this is used for view-source. |
Arthur Sonzogni | c686e8f | 2024-01-11 08:36:37 | [diff] [blame] | 631 | std::optional<net::IsolationInfo> isolation_info_; |
danakj | c492bf8 | 2020-09-09 20:02:44 | [diff] [blame] | 632 | |
| 633 | // Stores information about the entry prior to being replaced (e.g. |
| 634 | // history.replaceState()). It is preserved after commit (session sync for |
| 635 | // offline analysis) but should not be persisted. The concept is valid for |
| 636 | // subframe navigations but we only need to track it for main frames, that's |
| 637 | // why the field is listed here. |
Arthur Sonzogni | c686e8f | 2024-01-11 08:36:37 | [diff] [blame] | 638 | std::optional<ReplacedNavigationEntryData> replaced_entry_data_; |
danakj | c492bf8 | 2020-09-09 20:02:44 | [diff] [blame] | 639 | |
| 640 | // Set to true if this page does a navigation without ever receiving a user |
| 641 | // gesture. If true, it will be skipped on subsequent back/forward button |
| 642 | // clicks. This is to intervene against pages that manipulate the history such |
| 643 | // that the user is not able to go back to the last site they interacted with. |
| 644 | // Navigation here implies both client side redirects and history.pushState |
| 645 | // calls. |
| 646 | // It is always false the first time an entry's navigation is committed and |
| 647 | // is also reset to false if an entry is reused for any subsequent |
| 648 | // navigations. |
| 649 | // TODO(shivanisha): Persist this field once the intervention is stable. |
| 650 | bool should_skip_on_back_forward_ui_; |
| 651 | |
| 652 | // TODO(altimin, crbug.com/933147): Remove this logic after we are done |
| 653 | // with implement back-forward cache. |
| 654 | // It is preserved at commit but not persisted. |
| 655 | scoped_refptr<BackForwardCacheMetrics> back_forward_cache_metrics_; |
Rakina Zata Amni | afd3c658 | 2021-11-30 06:19:17 | [diff] [blame] | 656 | |
Rakina Zata Amni | f297a80 | 2022-01-18 03:53:43 | [diff] [blame] | 657 | // See comment for the enum for explanation. |
| 658 | InitialNavigationEntryState initial_navigation_entry_state_ = |
| 659 | InitialNavigationEntryState::kNonInitial; |
William Liu | 7bedaf8e | 2024-05-16 17:15:32 | [diff] [blame] | 660 | |
William Liu | 525ec5a1 | 2024-06-13 12:47:54 | [diff] [blame] | 661 | // Information about a navigation transition. See the comments on the class |
| 662 | // for details. |
| 663 | NavigationTransitionData navigation_transition_data_; |
danakj | c492bf8 | 2020-09-09 20:02:44 | [diff] [blame] | 664 | }; |
| 665 | |
| 666 | } // namespace content |
| 667 | |
| 668 | #endif // CONTENT_BROWSER_RENDERER_HOST_NAVIGATION_ENTRY_IMPL_H_ |