blob: f306b45d161a531ef53e05270473451296343a96 [file] [log] [blame]
Avi Drissman4e1b7bc32022-09-15 14:03:501// Copyright 2013 The Chromium Authors
danakjc492bf82020-09-09 20:02:442// 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_CONTROLLER_IMPL_H_
6#define CONTENT_BROWSER_RENDERER_HOST_NAVIGATION_CONTROLLER_IMPL_H_
7
8#include <stddef.h>
9#include <stdint.h>
10
11#include <memory>
Arthur Sonzognic686e8f2024-01-11 08:36:3712#include <optional>
danakjc492bf82020-09-09 20:02:4413#include <set>
14#include <string>
15#include <vector>
16
Avi Drissmanadac21992023-01-11 23:46:3917#include "base/functional/callback.h"
danakjc492bf82020-09-09 20:02:4418#include "base/gtest_prod_util.h"
Keishi Hattori0e45c022021-11-27 09:25:5219#include "base/memory/raw_ptr.h"
Ali Hijazid87307d2022-11-07 20:15:0320#include "base/memory/raw_ref.h"
danakjc492bf82020-09-09 20:02:4421#include "base/memory/weak_ptr.h"
danakjc492bf82020-09-09 20:02:4422#include "base/time/time.h"
23#include "build/build_config.h"
24#include "content/browser/renderer_host/back_forward_cache_impl.h"
25#include "content/browser/renderer_host/navigation_controller_delegate.h"
26#include "content/browser/renderer_host/navigation_entry_impl.h"
Miyoung Shin3299cbf2022-11-22 01:41:1027#include "content/browser/renderer_host/navigation_type.h"
danakjc492bf82020-09-09 20:02:4428#include "content/browser/ssl/ssl_manager.h"
Lei Zhang7ab313752021-11-17 01:26:0029#include "content/common/content_export.h"
arthursonzogni73fe3212020-11-17 13:24:0730#include "content/common/navigation_client.mojom-forward.h"
danakjc492bf82020-09-09 20:02:4431#include "content/public/browser/navigation_controller.h"
danakjc492bf82020-09-09 20:02:4432#include "content/public/browser/reload_type.h"
33#include "mojo/public/cpp/bindings/pending_associated_remote.h"
W. James MacLean443ef3e2024-07-16 13:42:3434#include "net/storage_access_api/status.h"
Antonio Sartori2f763d9d2021-04-21 10:04:1435#include "services/network/public/mojom/source_location.mojom-forward.h"
Yoav Weiss8c573952022-11-17 17:35:1336#include "third_party/blink/public/common/scheduler/task_attribution_id.h"
Chris Hamilton83272dc2021-02-23 00:24:0237#include "third_party/blink/public/common/tokens/tokens.h"
Domenic Denicolacd30f5f82022-03-16 21:48:0138#include "third_party/blink/public/mojom/navigation/navigation_api_history_entry_arrays.mojom-forward.h"
Yao Xiao720ef9d62022-12-09 05:18:2939#include "third_party/blink/public/mojom/navigation/navigation_initiator_activation_and_ad_status.mojom.h"
Minggang Wangb9f3fa92021-07-01 15:30:3140#include "third_party/blink/public/mojom/navigation/navigation_params.mojom-forward.h"
41
42namespace blink {
43struct NavigationDownloadPolicy;
44} // namespace blink
danakjc492bf82020-09-09 20:02:4445
danakjc492bf82020-09-09 20:02:4446namespace content {
Carlos Caballero40b0efd2021-01-26 11:55:0047class FrameTree;
danakjc492bf82020-09-09 20:02:4448class FrameTreeNode;
William Liu055a3542023-04-02 17:21:1949class NavigationEntryScreenshotCache;
danakjc492bf82020-09-09 20:02:4450class NavigationRequest;
51class RenderFrameHostImpl;
52class SiteInstance;
53struct LoadCommittedDetails;
54
Matt Falkenhagen91a80432021-07-05 03:32:4455// NavigationControllerImpl is 1:1 with FrameTree. See comments on the base
56// class.
danakjc492bf82020-09-09 20:02:4457class CONTENT_EXPORT NavigationControllerImpl : public NavigationController {
58 public:
59 // This tracks one NavigationRequest navigating to a pending NavigationEntry.
60 // In some cases, several NavigationRequests are referencing the same pending
61 // NavigationEntry. For instance:
62 // - A reload requested while a reload is already in progress.
63 // - An history navigation causing several subframes to navigate.
64 //
65 // When no NavigationRequests are referencing the pending NavigationEntry
66 // anymore, it should be discarded to avoid a URL spoof.
67 //
68 // The deletion is not always immediate, because it is not possible to delete
69 // the entry while requesting a navigation to it at the same time. In this
70 // case, the deletion happens later, when returning from the function.
71 //
72 // If the pending NavigationEntry is discarded before the PendingEntryRef(s),
73 // then removing the last associated PendingEntryRef is a no-op. It is a no-op
74 // forever, even if the entry becomes the pending NavigationEntry again in the
75 // meantime. Rather than track the NavigationRequest or pending entry
76 // explicitly, this ref class simply goes into a set that gets cleared with
77 // each change to the pending entry
78 class PendingEntryRef {
79 public:
80 explicit PendingEntryRef(
81 base::WeakPtr<NavigationControllerImpl> controller);
Peter Boström828b9022021-09-21 02:28:4382
83 PendingEntryRef(const PendingEntryRef&) = delete;
84 PendingEntryRef& operator=(const PendingEntryRef&) = delete;
85
danakjc492bf82020-09-09 20:02:4486 ~PendingEntryRef();
87
88 private:
89 base::WeakPtr<NavigationControllerImpl> controller_;
danakjc492bf82020-09-09 20:02:4490 };
91
Carlos Caballero40b0efd2021-01-26 11:55:0092 NavigationControllerImpl(BrowserContext* browser_context,
93 FrameTree& frame_tree,
94 NavigationControllerDelegate* delegate);
Peter Boström9b036532021-10-28 23:37:2895
96 NavigationControllerImpl(const NavigationControllerImpl&) = delete;
97 NavigationControllerImpl& operator=(const NavigationControllerImpl&) = delete;
98
danakjc492bf82020-09-09 20:02:4499 ~NavigationControllerImpl() override;
100
101 // NavigationController implementation:
danakjc492bf82020-09-09 20:02:44102 BrowserContext* GetBrowserContext() override;
103 void Restore(int selected_navigation,
104 RestoreType type,
105 std::vector<std::unique_ptr<NavigationEntry>>* entries) override;
106 NavigationEntryImpl* GetActiveEntry() override;
107 NavigationEntryImpl* GetVisibleEntry() override;
108 int GetCurrentEntryIndex() override;
109 NavigationEntryImpl* GetLastCommittedEntry() override;
Elad Alon32044f532025-03-04 22:16:03110 const NavigationEntryImpl* GetLastCommittedEntry() const override;
danakjc492bf82020-09-09 20:02:44111 int GetLastCommittedEntryIndex() override;
112 bool CanViewSource() override;
113 int GetEntryCount() override;
114 NavigationEntryImpl* GetEntryAtIndex(int index) override;
115 NavigationEntryImpl* GetEntryAtOffset(int offset) override;
116 void DiscardNonCommittedEntries() override;
117 NavigationEntryImpl* GetPendingEntry() override;
118 int GetPendingEntryIndex() override;
Harkiran Bolariaba823e42021-05-21 18:30:36119 base::WeakPtr<NavigationHandle> LoadURL(
120 const GURL& url,
121 const Referrer& referrer,
122 ui::PageTransition type,
123 const std::string& extra_headers) override;
124 base::WeakPtr<NavigationHandle> LoadURLWithParams(
125 const LoadURLParams& params) override;
danakjc492bf82020-09-09 20:02:44126 void LoadIfNecessary() override;
Charlie Reis4c53a962023-06-21 23:17:53127 void LoadOriginalRequestURL() override;
Kevin McNeeccca6172021-10-19 17:11:14128 base::WeakPtr<NavigationHandle> LoadPostCommitErrorPage(
129 RenderFrameHost* render_frame_host,
130 const GURL& url,
Lei Zhanga4770832023-07-19 18:02:36131 const std::string& error_page_html) override;
Xiaochen Zhou9088e642025-07-07 15:08:10132 void NavigateFrameToErrorPage(RenderFrameHost* render_frame_host,
133 const GURL& url,
134 const std::string& error_page_html) override;
danakjc492bf82020-09-09 20:02:44135 bool CanGoBack() override;
136 bool CanGoForward() override;
137 bool CanGoToOffset(int offset) override;
Andrew Verge9a71fa22025-08-21 18:43:16138 bool ShouldEnableBackButton() override;
139 bool ShouldEnableForwardButton() override;
David Bokanb8e0df02025-05-14 22:03:48140 WeakNavigationHandleVector GoBack() override;
141 WeakNavigationHandleVector GoForward() override;
142 WeakNavigationHandleVector GoToIndex(int index) override;
danakjc492bf82020-09-09 20:02:44143 void GoToOffset(int offset) override;
144 bool RemoveEntryAtIndex(int index) override;
145 void PruneForwardEntries() override;
146 const SessionStorageNamespaceMap& GetSessionStorageNamespaceMap() override;
147 SessionStorageNamespace* GetDefaultSessionStorageNamespace() override;
148 bool NeedsReload() override;
149 void SetNeedsReload() override;
150 void CancelPendingReload() override;
151 void ContinuePendingReload() override;
152 bool IsInitialNavigation() override;
153 bool IsInitialBlankNavigation() override;
154 void Reload(ReloadType reload_type, bool check_for_repost) override;
155 void NotifyEntryChanged(NavigationEntry* entry) override;
156 void CopyStateFrom(NavigationController* source, bool needs_reload) override;
danakjc492bf82020-09-09 20:02:44157 bool CanPruneAllButLastCommitted() override;
158 void PruneAllButLastCommitted() override;
159 void DeleteNavigationEntries(
160 const DeletionPredicate& deletionPredicate) override;
danakjc492bf82020-09-09 20:02:44161 BackForwardCacheImpl& GetBackForwardCache() override;
162
Rakina Zata Amnia4e27222021-12-22 01:05:00163 // Discards the pending entry if any. If this is caused by a navigation
164 // committing a new entry, `commit_details` will contain the committed
165 // navigation's details.
166 void DiscardNonCommittedEntriesWithCommitDetails(
167 LoadCommittedDetails* commit_details);
168
Rakina Zata Amniafd3c6582021-11-30 06:19:17169 // Creates the initial NavigationEntry for the NavigationController when its
170 // FrameTree is being initialized. See NavigationEntry::IsInitialEntry() on
171 // what this means.
172 void CreateInitialEntry();
173
William Liu055a3542023-04-02 17:21:19174 // Gets the `NavigationEntryScreenshotCache` for this `NavigationController`.
175 // Due to MPArch there can be multiple `FrameTree`s within a single tab. This
176 // should only be called for the primary FrameTree. This cache is
177 // lazy-initialized when this method is first called.
178 NavigationEntryScreenshotCache* GetNavigationEntryScreenshotCache();
179
danakjc492bf82020-09-09 20:02:44180 // Starts a navigation in a newly created subframe as part of a history
181 // navigation. Returns true if the history navigation could start, false
182 // otherwise. If this returns false, the caller should do a regular
183 // navigation to the default src URL for the frame instead.
184 bool StartHistoryNavigationInNewSubframe(
185 RenderFrameHostImpl* render_frame_host,
Hiroshige Hayashizaki5466bfe82023-05-17 00:34:33186 mojo::PendingAssociatedRemote<mojom::NavigationClient>* navigation_client,
187 blink::LocalFrameToken initiator_frame_token,
Charlie Reisf4d51f402025-05-23 18:00:49188 int initiator_process_id,
189 base::TimeTicks actual_navigation_start);
danakjc492bf82020-09-09 20:02:44190
191 // Reloads the |frame_tree_node| and returns true. In some rare cases, there
192 // is no history related to the frame, nothing happens and this returns false.
193 bool ReloadFrame(FrameTreeNode* frame_tree_node);
194
Nate Chapin45f620582021-09-30 17:45:43195 // Navigates to the specified offset from the "current entry" and marks the
196 // navigations as initiated by the renderer.
Nate Chapinbf682fa32022-09-26 22:41:20197 // |initiator_rfh| is the frame that requested the navigation.
Yoav Weissa7449c3b2022-11-22 15:15:14198 // |soft_navigation_heuristics_task_id| is the task in the renderer that
Yoav Weiss8c573952022-11-17 17:35:13199 // initiated this call (if any).
Charlie Reisf4d51f402025-05-23 18:00:49200 // |actual_navigation_start| is the time the navigation began, for metrics.
Arthur Sonzognic686e8f2024-01-11 08:36:37201 void GoToOffsetFromRenderer(int offset,
202 RenderFrameHostImpl* initiator_rfh,
203 std::optional<blink::scheduler::TaskAttributionId>
Charlie Reisf4d51f402025-05-23 18:00:49204 soft_navigation_heuristics_task_id,
205 base::TimeTicks actual_navigation_start);
Nate Chapin45f620582021-09-30 17:45:43206
William Liu62ae26c2024-08-08 14:28:16207 // A variation of `NavigationController::GoToIndex()`, that also returns all
208 // the created `NavigationRequest`s. If no navigation request is created, the
209 // vector is empty.
210 std::vector<base::WeakPtr<NavigationRequest>> GoToIndexAndReturnAllRequests(
William Liuec04e382024-05-23 18:03:27211 int index);
212
Xiaohan Wang7f8052e02022-01-14 18:44:28213#if BUILDFLAG(IS_ANDROID)
Nate Chapin45f620582021-09-30 17:45:43214 // The difference between (Can)GoToOffsetWithSkipping and
215 // (Can)GoToOffset/(Can)GoToOffsetInSandboxedFrame is that this respects the
216 // history manipulation intervention and will exclude skippable entries.
217 // These should only be used for browser-initiated navigaitons.
WangHui74286d52021-03-31 16:17:15218 bool CanGoToOffsetWithSkipping(int offset);
219 void GoToOffsetWithSkipping(int offset);
220#endif
danakjc492bf82020-09-09 20:02:44221
222 // Called when a document requests a navigation through a
223 // RenderFrameProxyHost.
224 void NavigateFromFrameProxy(
225 RenderFrameHostImpl* render_frame_host,
226 const GURL& url,
Chris Hamilton83272dc2021-02-23 00:24:02227 const blink::LocalFrameToken* initiator_frame_token,
Antonio Sartori9a82f6f32020-12-14 09:22:45228 int initiator_process_id,
Arthur Sonzognic686e8f2024-01-11 08:36:37229 const std::optional<url::Origin>& initiator_origin,
230 const std::optional<GURL>& initiator_base_url,
danakjc492bf82020-09-09 20:02:44231 bool is_renderer_initiated,
232 SiteInstance* source_site_instance,
233 const Referrer& referrer,
234 ui::PageTransition page_transition,
235 bool should_replace_current_entry,
Yeunjoo Choi3df791a2021-02-17 07:07:25236 blink::NavigationDownloadPolicy download_policy,
danakjc492bf82020-09-09 20:02:44237 const std::string& method,
238 scoped_refptr<network::ResourceRequestBody> post_body,
239 const std::string& extra_headers,
Antonio Sartori2f763d9d2021-04-21 10:04:14240 network::mojom::SourceLocationPtr source_location,
danakjc492bf82020-09-09 20:02:44241 scoped_refptr<network::SharedURLLoaderFactory> blob_url_loader_factory,
jongdeok.kim5de823b32022-06-14 04:37:50242 bool is_form_submission,
Arthur Sonzognic686e8f2024-01-11 08:36:37243 const std::optional<blink::Impression>& impression,
Yao Xiao720ef9d62022-12-09 05:18:29244 blink::mojom::NavigationInitiatorActivationAndAdStatus
245 initiator_activation_and_ad_status,
Charlie Reise1d9b8182025-04-02 04:32:12246 base::TimeTicks actual_navigation_start_time,
Nan Lin944e9b4e2022-04-12 13:51:22247 base::TimeTicks navigation_start_time,
Garrett Tanzer405f3402022-07-21 20:12:49248 bool is_embedder_initiated_fenced_frame_navigation = false,
Garrett Tanzerbb8db412022-09-27 21:59:46249 bool is_unfenced_top_navigation = false,
Sergey Poromovdd557c12023-03-01 11:28:45250 bool force_new_browsing_instance = false,
Camillia Smith Barnes6a643962023-03-03 00:28:58251 bool is_container_initiated = false,
Kevin McNee6455638a2024-06-27 22:05:03252 bool has_rel_opener = false,
W. James MacLean443ef3e2024-07-16 13:42:34253 net::StorageAccessApiStatus storage_access_api_status =
254 net::StorageAccessApiStatus::kNone,
Arthur Sonzognic686e8f2024-01-11 08:36:37255 std::optional<std::u16string> embedder_shared_storage_context =
256 std::nullopt);
danakjc492bf82020-09-09 20:02:44257
Domenic Denicolacc094fb2022-03-16 23:40:57258 // Navigates to the history entry associated with the given navigation API
259 // |key|. Searches |entries_| for a FrameNavigationEntry associated with
Nate Chapinbf682fa32022-09-26 22:41:20260 // |initiator_rfh|'s FrameTreeNode that has |key| as its navigation API key.
261 // Searches back from the current index, then forward, so if there are
262 // multiple entries with the same key, the nearest to current should be
263 // selected. Stops searching in the current direction if it finds a
264 // NavigationEntry without a FrameNavigationEntry for |initiator_rfh|'s
265 // FrameTreeNode, or if the FrameNavigationEntry doesn't match origin or site
266 // instance.
Nate Chapinfbfe5af2021-06-10 17:22:08267 //
268 // If no matching entry is found, the navigation is dropped. The renderer
269 // should only send the navigation to the browser if it believes the entry is
270 // in |entries_|, but it might be wrong (if the entry was dropped from
271 // |entries_|, or due to a race condition) or compromised.
272 // If a matching entry is found, navigate to that entry and proceed like any
273 // other history navigation.
Yoav Weissa7449c3b2022-11-22 15:15:14274 // |soft_navigation_heuristics_task_id|: The task in the renderer that
275 // initiated this call (if any).
Charlie Reisf4d51f402025-05-23 18:00:49276 // |actual_navigation_start| is the time the navigation began, for metrics.
Yoav Weissa7449c3b2022-11-22 15:15:14277 void NavigateToNavigationApiKey(
278 RenderFrameHostImpl* initiator_rfh,
Arthur Sonzognic686e8f2024-01-11 08:36:37279 std::optional<blink::scheduler::TaskAttributionId>
Yoav Weissa7449c3b2022-11-22 15:15:14280 soft_navigation_heuristics_task_id,
Charlie Reisf4d51f402025-05-23 18:00:49281 const std::string& key,
282 base::TimeTicks actual_navigation_start);
Nate Chapinfbfe5af2021-06-10 17:22:08283
danakjc492bf82020-09-09 20:02:44284 // Whether this is the initial navigation in an unmodified new tab. In this
285 // case, we know there is no content displayed in the page.
286 bool IsUnmodifiedBlankTab();
287
Dave Tapuska2cf1f532022-08-10 15:30:49288 // The session storage namespace that all child `blink::WebView`s associated
289 // with `partition_config` should use.
Aaron Colwell78b4bde2021-03-16 16:16:09290 SessionStorageNamespace* GetSessionStorageNamespace(
Alex Moshchuk8015afcf2022-01-31 22:59:25291 const StoragePartitionConfig& partition_config);
danakjc492bf82020-09-09 20:02:44292
293 // Returns the index of the specified entry, or -1 if entry is not contained
294 // in this NavigationController.
295 int GetIndexOfEntry(const NavigationEntryImpl* entry) const;
296
297 // Return the index of the entry with the given unique id, or -1 if not found.
298 int GetEntryIndexWithUniqueID(int nav_entry_id) const;
299
Kevin McNee3b3a56192023-03-17 14:40:59300 // Returns the index that would be used by `GoBack`. This respects skippable
301 // entries. Returns nullopt if no unskippable back entry exists.
Arthur Sonzognic686e8f2024-01-11 08:36:37302 std::optional<int> GetIndexForGoBack();
Kevin McNee3b3a56192023-03-17 14:40:59303 // Returns the index that would be used by `GoForward`. This respects
304 // skippable entries. Returns nullopt if no forward entry exists.
Arthur Sonzognic686e8f2024-01-11 08:36:37305 std::optional<int> GetIndexForGoForward();
Kevin McNee3b3a56192023-03-17 14:40:59306
danakjc492bf82020-09-09 20:02:44307 // Return the entry with the given unique id, or null if not found.
308 NavigationEntryImpl* GetEntryWithUniqueID(int nav_entry_id) const;
Adithya Srinivasan9b0c99c2021-08-10 15:19:45309 // Same as above method, but also includes the pending entry in the search
310 // space.
311 NavigationEntryImpl* GetEntryWithUniqueIDIncludingPending(
312 int nav_entry_id) const;
danakjc492bf82020-09-09 20:02:44313
314 NavigationControllerDelegate* delegate() const { return delegate_; }
315
316 // These values are persisted to logs. Entries should not be renumbered and
317 // numeric values should never be reused.
318 enum class NeedsReloadType {
319 kRequestedByClient = 0,
320 kRestoreSession = 1,
321 kCopyStateFrom = 2,
322 kCrashedSubframe = 3,
323 kMaxValue = kCrashedSubframe
324 };
325
326 // Request a reload to happen when activated. Same as the public
327 // SetNeedsReload(), but takes in a |type| which specifies why the reload is
328 // being requested.
329 void SetNeedsReload(NeedsReloadType type);
330
danakjc492bf82020-09-09 20:02:44331 // For use by WebContentsImpl ------------------------------------------------
332
Alex Moshchuke26f2d82021-07-21 23:21:00333 // Visit all FrameNavigationEntries as well as all frame trees and register
W. James MacLeanc07dc41b2022-07-25 18:52:16334 // any instances of |origin| as having the default isolation state with their
335 // respective BrowsingInstances. This is important when |origin| is seen with
336 // an OriginAgentCluster header, so that we only accept such requests in
337 // BrowsingInstances that haven't seen it before.
338 void RegisterExistingOriginAsHavingDefaultIsolation(
339 const url::Origin& origin);
danakjc492bf82020-09-09 20:02:44340
341 // Allow renderer-initiated navigations to create a pending entry when the
342 // provisional load starts.
343 void SetPendingEntry(std::unique_ptr<NavigationEntryImpl> entry);
344
345 // Handles updating the navigation state after the renderer has navigated.
346 // This is used by the WebContentsImpl.
347 //
348 // If a new entry is created, it will return true and will have filled the
349 // given details structure and broadcast the NOTIFY_NAV_ENTRY_COMMITTED
350 // notification. The caller can then use the details without worrying about
351 // listening for the notification.
352 //
353 // In the case that nothing has changed, the details structure is undefined
354 // and it will return false.
355 //
Nate Chapinc7019dd7d2021-06-25 18:29:25356 // |was_on_initial_empty_document| indicates whether the document being
357 // navigated away from was an initial empty document.
358 //
Shivani Sharmaeef521b2024-01-18 13:03:56359 // |previous_document_had_history_intervention_activation| is true if the
360 // previous document had a user activation that is being honored for the
361 // history manipulation intervention (i.e., a new user activation is needed
362 // after same-document back/forward navigations).
363 // See RFHI::honor_sticky_activation_for_history_intervention_ for details.
364 // This is used for a new renderer-initiated navigation to decide if the page
365 // that initiated the navigation should be skipped on back/forward button.
366 bool RendererDidNavigate(
367 RenderFrameHostImpl* rfh,
368 const mojom::DidCommitProvisionalLoadParams& params,
369 LoadCommittedDetails* details,
370 bool is_same_document_navigation,
371 bool was_on_initial_empty_document,
372 bool previous_document_had_history_intervention_activation,
373 NavigationRequest* navigation_request);
danakjc492bf82020-09-09 20:02:44374
375 // Notifies us that we just became active. This is used by the WebContentsImpl
376 // so that we know to load URLs that were pending as "lazy" loads.
377 void SetActive(bool is_active);
378
Alex Moshchuk8015afcf2022-01-31 22:59:25379 // Sets the SessionStorageNamespace for the given |partition_config|. This is
danakjc492bf82020-09-09 20:02:44380 // used during initialization of a new NavigationController to allow
381 // pre-population of the SessionStorageNamespace objects. Session restore,
danakjf26536bf2020-09-10 00:46:13382 // prerendering, and the implementation of window.open() are the primary users
danakjc492bf82020-09-09 20:02:44383 // of this API.
384 //
385 // Calling this function when a SessionStorageNamespace has already been
386 // associated with a |partition_id| will CHECK() fail.
387 void SetSessionStorageNamespace(
Alex Moshchuk8015afcf2022-01-31 22:59:25388 const StoragePartitionConfig& partition_config,
danakjc492bf82020-09-09 20:02:44389 SessionStorageNamespace* session_storage_namespace);
390
391 // Random data ---------------------------------------------------------------
392
Ali Hijazid87307d2022-11-07 20:15:03393 FrameTree& frame_tree() { return *frame_tree_; }
Carlos Caballeroede6f8c2021-01-28 11:01:50394
danakjc492bf82020-09-09 20:02:44395 SSLManager* ssl_manager() { return &ssl_manager_; }
396
397 // Maximum number of entries before we start removing entries from the front.
398 static void set_max_entry_count_for_testing(size_t max_entry_count) {
399 max_entry_count_for_testing_ = max_entry_count;
400 }
401 static size_t max_entry_count();
402
403 void SetGetTimestampCallbackForTest(
404 const base::RepeatingCallback<base::Time()>& get_timestamp_callback);
405
406 // Discards only the pending entry. |was_failure| should be set if the pending
407 // entry is being discarded because it failed to load.
408 void DiscardPendingEntry(bool was_failure);
409
410 // Sets a flag on the pending NavigationEntryImpl instance if any that the
411 // navigation failed due to an SSL error.
412 void SetPendingNavigationSSLError(bool error);
413
414// Returns true if the string corresponds to a valid data URL, false
415// otherwise.
Xiaohan Wang7f8052e02022-01-14 18:44:28416#if BUILDFLAG(IS_ANDROID)
danakjc492bf82020-09-09 20:02:44417 static bool ValidateDataURLAsString(
418 const scoped_refptr<const base::RefCountedString>& data_url_as_string);
419#endif
420
421 // Invoked when a user activation occurs within the page, so that relevant
422 // entries can be updated as needed.
423 void NotifyUserActivation();
424
425 // Tracks a new association between the current pending entry and a
426 // NavigationRequest. Callers are responsible for only calling this for
427 // requests corresponding to the current pending entry.
428 std::unique_ptr<PendingEntryRef> ReferencePendingEntry();
429
Carlos Caballeroede6f8c2021-01-28 11:01:50430 // Another page accessed the initial empty main document, which means it
431 // is no longer safe to display a pending URL without risking a URL spoof.
432 void DidAccessInitialMainDocument();
433
434 // The state for the page changed and should be updated in session history.
435 void UpdateStateForFrame(RenderFrameHostImpl* render_frame_host,
436 const blink::PageState& page_state);
437
Hayato Ito303654c2021-06-30 09:07:54438 // Like NavigationController::CreateNavigationEntry, but takes an extra
Sharon Yang242ef822023-05-15 21:07:32439 // argument, |source_process_site_url|.
Julie Jeongeun Kim5b9aff72022-05-02 02:10:17440 // `rewrite_virtual_urls` is true when it needs to rewrite virtual urls
441 // (e.g., for outermost frames).
danakjc492bf82020-09-09 20:02:44442 static std::unique_ptr<NavigationEntryImpl> CreateNavigationEntry(
443 const GURL& url,
444 Referrer referrer,
Arthur Sonzognic686e8f2024-01-11 08:36:37445 std::optional<url::Origin> initiator_origin,
446 std::optional<GURL> initiator_base_url,
447 std::optional<GURL> source_process_site_url,
danakjc492bf82020-09-09 20:02:44448 ui::PageTransition transition,
449 bool is_renderer_initiated,
450 const std::string& extra_headers,
451 BrowserContext* browser_context,
Julie Jeongeun Kim5b9aff72022-05-02 02:10:17452 scoped_refptr<network::SharedURLLoaderFactory> blob_url_loader_factory,
453 bool rewrite_virtual_urls);
danakjc492bf82020-09-09 20:02:44454
Nate Chapin97d2f542022-02-18 01:34:55455 // Called just before sending the commit to the renderer, or when restoring
456 // from back/forward cache. Walks the session history entries for the relevant
457 // FrameTreeNode, forward and backward from the pending entry. All contiguous
458 // and same-origin FrameNavigationEntries are serialized and returned.
459 // |request| may be nullptr when getting entries for an iframe that is being
460 // restored for back/forward cache (in that case, the iframe itself is not
461 // navigated, so there is no NavigationRequest).
Domenic Denicolacd30f5f82022-03-16 21:48:01462 blink::mojom::NavigationApiHistoryEntryArraysPtr
463 GetNavigationApiHistoryEntryVectors(FrameTreeNode* node,
464 NavigationRequest* request);
Nate Chapind1fe3612021-04-16 20:45:57465
Domenic Denicolacc094fb2022-03-16 23:40:57466 // The window.navigation API exposes the urls of some non-current same-origin
Nate Chapin63db0d12022-01-20 22:03:30467 // FrameNavigationEntries to the renderer. This helper checks whether the
468 // given ReferrerPolicy makes an attempt to hide a page's URL (e.g., in
Domenic Denicolacc094fb2022-03-16 23:40:57469 // referrer headers) and thus whether the URL should be hidden from navigation
470 // API history entries as well.
471 static bool ShouldProtectUrlInNavigationApi(
Nate Chapin63db0d12022-01-20 22:03:30472 network::mojom::ReferrerPolicy referrer_policy);
473
Chris Bookholt27faf8d2022-01-20 01:03:33474 // Returns whether the last NavigationEntry encountered a post-commit error.
Chris Bookholte47eb30a2022-01-21 17:25:35475 bool has_post_commit_error_entry() const {
476 return entry_replaced_by_post_commit_error_ != nullptr;
477 }
Chris Bookholt27faf8d2022-01-20 01:03:33478
Rakina Zata Amni148dcad72022-06-08 14:53:50479 // Whether the current call stack includes NavigateToPendingEntry, to avoid
480 // re-entrant calls to NavigateToPendingEntry.
Alison Gale770f3fc2024-04-27 00:39:58481 // TODO(crbug.com/40841494): Don't expose this once we figure out the
Rakina Zata Amni148dcad72022-06-08 14:53:50482 // root cause for the navigation re-entrancy case in the linked bug.
483 bool in_navigate_to_pending_entry() const {
484 return in_navigate_to_pending_entry_;
485 }
486
Minoru Chikamune646eba42025-04-14 01:25:03487 // This flag is set from RenderFrameHostImpl::SendBeforeUnload() to
488 // investigate whether kAvoidUnnecessaryBeforeUnloadCheckSync feature is safe
489 // to enable or not (see: https://crbug.com/40361673,
490 // https://crbug.com/396998476).
491 void set_can_be_in_navigate_to_pending_entry(
492 const bool can_be_in_navigate_to_pending_entry) {
493 can_be_in_navigate_to_pending_entry_ = can_be_in_navigate_to_pending_entry;
494 }
495
Ian Vollick5c344c52022-08-29 19:31:33496 // Whether to maintain a session history with just one entry.
497 //
498 // This returns true for a prerendering page and for fenced frames.
499 // `frame_tree_node` is checked to see if it belongs to a frame tree for
500 // prerendering or for a fenced frame.
501 // Explainer:
502 // https://github.com/jeremyroman/alternate-loading-modes/blob/main/browsing-context.md#session-history)
Ian Vollick5c344c52022-08-29 19:31:33503 bool ShouldMaintainTrivialSessionHistory(
504 const FrameTreeNode* frame_tree_node) const;
505
Julie Jeongeun Kim0e242242022-11-30 10:45:09506 // Called when the referrer policy changes. It updates whether to protect the
507 // url in the navigation API.
508 void DidChangeReferrerPolicy(FrameTreeNode* node,
509 network::mojom::ReferrerPolicy referrer_policy);
510
William Liu2b6336bc2023-09-07 14:42:39511 base::WeakPtr<NavigationControllerImpl> GetWeakPtr() {
512 return weak_factory_.GetWeakPtr();
513 }
514
danakjc492bf82020-09-09 20:02:44515 private:
516 friend class RestoreHelper;
517
518 FRIEND_TEST_ALL_PREFIXES(TimeSmoother, Basic);
519 FRIEND_TEST_ALL_PREFIXES(TimeSmoother, SingleDuplicate);
520 FRIEND_TEST_ALL_PREFIXES(TimeSmoother, ManyDuplicates);
521 FRIEND_TEST_ALL_PREFIXES(TimeSmoother, ClockBackwardsJump);
Rakina Zata Amni26357782020-12-03 11:45:01522 FRIEND_TEST_ALL_PREFIXES(NavigationControllerBrowserTest, PostThenReload);
523 FRIEND_TEST_ALL_PREFIXES(NavigationControllerBrowserTest,
danakjc492bf82020-09-09 20:02:44524 PostThenReplaceStateThenReload);
Rakina Zata Amni26357782020-12-03 11:45:01525 FRIEND_TEST_ALL_PREFIXES(NavigationControllerBrowserTest,
Rakina Zata Amnid80835a2020-12-09 10:29:07526 PostThenPushStateThenReloadThenHistory);
Rakina Zata Amni26357782020-12-03 11:45:01527 FRIEND_TEST_ALL_PREFIXES(NavigationControllerBrowserTest,
Rakina Zata Amnid80835a2020-12-09 10:29:07528 PostThenFragmentNavigationThenReloadThenHistory);
529 FRIEND_TEST_ALL_PREFIXES(
530 NavigationControllerBrowserTest,
531 PostThenBrowserInitiatedFragmentNavigationThenReload);
532 FRIEND_TEST_ALL_PREFIXES(NavigationControllerBrowserTest, PostSubframe);
Wang Hui96ab1012022-10-11 02:05:49533 FRIEND_TEST_ALL_PREFIXES(NavigationControllerBrowserTest,
534 ResetPendingLoadTypeWhenCancelPendingReload);
WangHui74286d52021-03-31 16:17:15535 FRIEND_TEST_ALL_PREFIXES(NavigationControllerDisableHistoryIntervention,
536 GoToOffsetWithSkippingDisableHistoryIntervention);
537 FRIEND_TEST_ALL_PREFIXES(NavigationControllerHistoryInterventionBrowserTest,
538 GoToOffsetWithSkippingEnableHistoryIntervention);
539 FRIEND_TEST_ALL_PREFIXES(NavigationControllerHistoryInterventionBrowserTest,
540 SetSkipOnBackForwardDoSkipForGoToOffsetWithSkipping);
541 FRIEND_TEST_ALL_PREFIXES(NavigationControllerHistoryInterventionBrowserTest,
542 SetSkipOnBackForwardDoNotSkipForGoToOffset);
danakjc492bf82020-09-09 20:02:44543
544 // Defines possible actions that are returned by
545 // DetermineActionForHistoryNavigation().
546 enum class HistoryNavigationAction {
547 kStopLooking,
548 kKeepLooking,
549 kSameDocument,
550 kDifferentDocument,
551 };
552
Nate Chapin9eb16be72022-09-23 22:54:31553 enum class Direction { kForward, kBack };
554
danakjc492bf82020-09-09 20:02:44555 // Helper class to smooth out runs of duplicate timestamps while still
556 // allowing time to jump backwards.
557 class CONTENT_EXPORT TimeSmoother {
558 public:
559 // Returns |t| with possibly some time added on.
560 base::Time GetSmoothedTime(base::Time t);
561
562 private:
563 // |low_water_mark_| is the first time in a sequence of adjusted
564 // times and |high_water_mark_| is the last.
565 base::Time low_water_mark_;
566 base::Time high_water_mark_;
567 };
568
569 // The repost dialog is suppressed during testing. However, it should be shown
570 // in some tests. This allows a test to elect to allow the repost dialog to
571 // show for a scoped duration.
572 class CONTENT_EXPORT ScopedShowRepostDialogForTesting {
573 public:
574 ScopedShowRepostDialogForTesting();
575 ~ScopedShowRepostDialogForTesting();
576
577 ScopedShowRepostDialogForTesting(const ScopedShowRepostDialogForTesting&) =
578 delete;
579 ScopedShowRepostDialogForTesting& operator=(
580 const ScopedShowRepostDialogForTesting&) = delete;
581
582 private:
583 const bool was_disallowed_;
584 };
585
Charlie Reisd3e4fef2025-05-20 02:04:17586 // Navigations to pending entries do not support re-entrancy due to a risk of
587 // use-after-free, and the pending entry itself should not be deleted during
588 // such a navigation. Create one of these scoped objects around calls to
589 // `Navigator::Navigate` when a pending entry is used, to safely crash rather
590 // than risk memory errors if re-entrancy or an unexpected deletion occurs.
591 // See https://crbug.com/40353566 for details.
592 class ScopedPendingEntryReentrancyGuard {
593 public:
594 explicit ScopedPendingEntryReentrancyGuard(
595 base::SafeRef<NavigationControllerImpl> controller);
596 ~ScopedPendingEntryReentrancyGuard();
597
598 private:
599 base::SafeRef<NavigationControllerImpl> controller_;
600 std::unique_ptr<NavigationControllerImpl::PendingEntryRef>
601 pending_entry_ref_;
602 };
603
Nate Chapin9eb16be72022-09-23 22:54:31604 // Records which navigation API keys are associated with live frames.
605 // On destruction, does a final pass to filter out any keys that are still
606 // present in |entries_|, then sends the removed navigation API keys to the
607 // renderer so that the navigation API can fire dispose events for the
608 // entries associated with those keys.
609 class RemovedEntriesTracker {
610 public:
611 explicit RemovedEntriesTracker(
612 base::SafeRef<NavigationControllerImpl> controller);
613 ~RemovedEntriesTracker();
614
615 private:
616 // Walk both directions from the last committed entry to find the navigation
617 // API keys of any FNEs that could be known by currently live documents.
618 // These FNEs are contiguous, so the walk can stop for a given frame when it
619 // reaches an FNE whose API key is no longer known to the current document.
620 void PopulateKeySet(Direction direction);
621 base::SafeRef<NavigationControllerImpl> controller_;
622 // Preprocessed maps used in PopulateKeySet(), mapping frame names
623 // to their respective FrameTreeNodes, and FrameTreeNode ids to their
624 // current document sequences numbers.
Ali Hijazi60a72b0a2024-09-30 17:58:53625 std::map<std::string, raw_ptr<FrameTreeNode, CtnExperimental>>
626 names_to_nodes_;
Avi Drissmanbd153642024-09-03 18:58:05627 std::map<FrameTreeNodeId, int64_t> frame_tree_node_id_to_doc_seq_nos_;
Nate Chapin9eb16be72022-09-23 22:54:31628
629 // The output of PopulateKeySet(), which maps FrameTreeNode ids to the keys
630 // that frame knows about in the renderer. Used in the destructor.
Avi Drissmanbd153642024-09-03 18:58:05631 std::map<FrameTreeNodeId, std::set<std::string>>
632 frame_tree_node_id_to_keys_;
Nate Chapin9eb16be72022-09-23 22:54:31633 };
634
William Liu62ae26c2024-08-08 14:28:16635 // Navigates in session history to the given index. Returns all the created
636 // `NavigationRequest`s. If no request was created, the returned vector is
637 // empty.
Nate Chapinbf682fa32022-09-26 22:41:20638 // |initiator_rfh| is nullptr for browser-initiated navigations.
Yoav Weissa7449c3b2022-11-22 15:15:14639 // |soft_navigation_heuristics_task_id|: The task in the renderer that
Yoav Weiss8c573952022-11-17 17:35:13640 // initiated this call (if any).
Nate Chapinbf682fa32022-09-26 22:41:20641 // If this navigation originated from the navigation API, |navigation_api_key|
642 // will be set and indicate the navigation api key that |initiator_rfh|
643 // asked to be navigated to.
Charlie Reisf4d51f402025-05-23 18:00:49644 // |actual_navigation_start| is the time the navigation began, for metrics.
William Liu62ae26c2024-08-08 14:28:16645 std::vector<base::WeakPtr<NavigationRequest>> GoToIndex(
William Liuec04e382024-05-23 18:03:27646 int index,
647 RenderFrameHostImpl* initiator_rfh,
648 std::optional<blink::scheduler::TaskAttributionId>
649 soft_navigation_heuristics_task_id,
Charlie Reisf4d51f402025-05-23 18:00:49650 const std::string* navigation_api_key,
651 base::TimeTicks actual_navigation_start);
danakjc492bf82020-09-09 20:02:44652
William Liuec04e382024-05-23 18:03:27653 // Starts a navigation to an already existing pending NavigationEntry. Returns
William Liu62ae26c2024-08-08 14:28:16654 // all the created `NavigationRequest`s. If no request was created, the
655 // returned vector is empty.
Nate Chapinbf682fa32022-09-26 22:41:20656 // |initiator_rfh| is nullptr for browser-initiated navigations.
657 // If this navigation originated from the navigation API, |navigation_api_key|
658 // will be set and indicate the navigation api key that |initiator_rfh|
659 // asked to be navigated to.
Yoav Weissa7449c3b2022-11-22 15:15:14660 // |soft_navigation_heuristics_task_id|: The task in the renderer that
Yoav Weiss8c573952022-11-17 17:35:13661 // initiated this call (if any).
Charlie Reisf4d51f402025-05-23 18:00:49662 // |actual_navigation_start| is the time the navigation began, for metrics.
William Liu62ae26c2024-08-08 14:28:16663 std::vector<base::WeakPtr<NavigationRequest>> NavigateToExistingPendingEntry(
Yoav Weiss8c573952022-11-17 17:35:13664 ReloadType reload_type,
665 RenderFrameHostImpl* initiator_rfh,
Arthur Sonzognic686e8f2024-01-11 08:36:37666 std::optional<blink::scheduler::TaskAttributionId>
Yoav Weiss8c573952022-11-17 17:35:13667 soft_navigation_heuristics_task_id,
Charlie Reisf4d51f402025-05-23 18:00:49668 const std::string* navigation_api_key,
669 base::TimeTicks actual_navigation_start);
danakjc492bf82020-09-09 20:02:44670
671 // Helper function used by FindFramesToNavigate to determine the appropriate
672 // action to take for a particular frame while navigating to
673 // |pending_entry_|.
674 HistoryNavigationAction DetermineActionForHistoryNavigation(
675 FrameTreeNode* frame,
676 ReloadType reload_type);
677
678 // Recursively identifies which frames need to be navigated for a navigation
679 // to |pending_entry_|, starting at |frame| and exploring its children.
680 // |same_document_loads| and |different_document_loads| will be filled with
681 // the NavigationRequests needed to navigate to |pending_entry_|.
Charlie Reisf4d51f402025-05-23 18:00:49682 // |actual_navigation_start| is the time the navigation began, for metrics.
Yoav Weissa7449c3b2022-11-22 15:15:14683 // |soft_navigation_heuristics_task_id|: The task in the renderer that
Yoav Weiss8c573952022-11-17 17:35:13684 // initiated this call (if any).
danakjc492bf82020-09-09 20:02:44685 void FindFramesToNavigate(
686 FrameTreeNode* frame,
687 ReloadType reload_type,
Arthur Sonzognic686e8f2024-01-11 08:36:37688 const std::optional<blink::LocalFrameToken>& initiator_frame_token,
Hiroshige Hayashizaki5466bfe82023-05-17 00:34:33689 int initiator_process_id,
Arthur Sonzognic686e8f2024-01-11 08:36:37690 std::optional<blink::scheduler::TaskAttributionId>
Yoav Weiss8c573952022-11-17 17:35:13691 soft_navigation_heuristics_task_id,
Charlie Reisf4d51f402025-05-23 18:00:49692 base::TimeTicks actual_navigation_start,
danakjc492bf82020-09-09 20:02:44693 std::vector<std::unique_ptr<NavigationRequest>>* same_document_loads,
694 std::vector<std::unique_ptr<NavigationRequest>>*
695 different_document_loads);
696
697 // Starts a new navigation based on |load_params|, that doesn't correspond to
danakjf26536bf2020-09-10 00:46:13698 // an existing NavigationEntry.
Charlie Reisf4d51f402025-05-23 18:00:49699 // |actual_navigation_start| is the time the navigation began, for metrics.
Harkiran Bolariaba823e42021-05-21 18:30:36700 base::WeakPtr<NavigationHandle> NavigateWithoutEntry(
Charlie Reisf4d51f402025-05-23 18:00:49701 const LoadURLParams& load_params,
702 base::TimeTicks actual_navigation_start);
danakjc492bf82020-09-09 20:02:44703
704 // Handles a navigation to a renderer-debug URL.
705 void HandleRendererDebugURL(FrameTreeNode* frame_tree_node, const GURL& url);
706
707 // Creates and returns a NavigationEntry based on |load_params| for a
708 // navigation in |node|.
709 // |override_user_agent|, |should_replace_current_entry| and
710 // |has_user_gesture| will override the values from |load_params|. The same
711 // values should be passed to CreateNavigationRequestFromLoadParams.
712 std::unique_ptr<NavigationEntryImpl> CreateNavigationEntryFromLoadParams(
713 FrameTreeNode* node,
714 const LoadURLParams& load_params,
715 bool override_user_agent,
716 bool should_replace_current_entry,
717 bool has_user_gesture);
718
719 // Creates and returns a NavigationRequest based on |load_params| for a
720 // new navigation in |node|.
721 // Will return nullptr if the parameters are invalid and the navigation cannot
722 // start.
723 // |override_user_agent|, |should_replace_current_entry| and
724 // |has_user_gesture| will override the values from |load_params|. The same
725 // values should be passed to CreateNavigationEntryFromLoadParams.
726 // TODO(clamy): Remove the dependency on NavigationEntry and
727 // FrameNavigationEntry.
728 std::unique_ptr<NavigationRequest> CreateNavigationRequestFromLoadParams(
729 FrameTreeNode* node,
730 const LoadURLParams& load_params,
731 bool override_user_agent,
732 bool should_replace_current_entry,
733 bool has_user_gesture,
Antonio Sartori2f763d9d2021-04-21 10:04:14734 network::mojom::SourceLocationPtr source_location,
danakjc492bf82020-09-09 20:02:44735 ReloadType reload_type,
736 NavigationEntryImpl* entry,
Tsuyoshi Horo167ca6432022-03-09 05:16:39737 FrameNavigationEntry* frame_entry,
Charlie Reise1d9b8182025-04-02 04:32:12738 base::TimeTicks actual_navigation_start_time,
Nan Lin944e9b4e2022-04-12 13:51:22739 base::TimeTicks navigation_start_time,
Garrett Tanzer405f3402022-07-21 20:12:49740 bool is_embedder_initiated_fenced_frame_navigation = false,
Sergey Poromovdd557c12023-03-01 11:28:45741 bool is_unfenced_top_navigation = false,
Camillia Smith Barnes6a643962023-03-03 00:28:58742 bool is_container_initiated = false,
W. James MacLean443ef3e2024-07-16 13:42:34743 net::StorageAccessApiStatus storage_access_api_status =
744 net::StorageAccessApiStatus::kNone,
Arthur Sonzognic686e8f2024-01-11 08:36:37745 std::optional<std::u16string> embedder_shared_storage_context =
746 std::nullopt);
danakjc492bf82020-09-09 20:02:44747
748 // Creates and returns a NavigationRequest for a navigation to |entry|. Will
749 // return nullptr if the parameters are invalid and the navigation cannot
750 // start.
Yoav Weissa7449c3b2022-11-22 15:15:14751 // |soft_navigation_heuristics_task_id|: The task in the renderer that
Yoav Weiss8c573952022-11-17 17:35:13752 // initiated this call (if any).
danakjc492bf82020-09-09 20:02:44753 // TODO(clamy): Ensure this is only called for navigations to existing
754 // NavigationEntries.
755 std::unique_ptr<NavigationRequest> CreateNavigationRequestFromEntry(
756 FrameTreeNode* frame_tree_node,
757 NavigationEntryImpl* entry,
758 FrameNavigationEntry* frame_entry,
759 ReloadType reload_type,
760 bool is_same_document_history_load,
Nate Chapin45f620582021-09-30 17:45:43761 bool is_history_navigation_in_new_child_frame,
Arthur Sonzognic686e8f2024-01-11 08:36:37762 const std::optional<blink::LocalFrameToken>& initiator_frame_token,
Hiroshige Hayashizaki5466bfe82023-05-17 00:34:33763 int initiator_process_id,
Charlie Reisf4d51f402025-05-23 18:00:49764 base::TimeTicks actual_navigation_start,
Arthur Sonzognic686e8f2024-01-11 08:36:37765 std::optional<blink::scheduler::TaskAttributionId>
766 soft_navigation_heuristics_task_id = std::nullopt);
danakjc492bf82020-09-09 20:02:44767
768 // Returns whether there is a pending NavigationEntry whose unique ID matches
769 // the given NavigationRequest's pending_nav_entry_id.
770 bool PendingEntryMatchesRequest(NavigationRequest* request) const;
771
772 // Classifies the given renderer navigation (see the NavigationType enum).
773 NavigationType ClassifyNavigation(
774 RenderFrameHostImpl* rfh,
Rakina Zata Amnif6950d552020-11-24 03:26:10775 const mojom::DidCommitProvisionalLoadParams& params,
Rakina Zata Amni2322f4f82022-01-24 13:24:24776 NavigationRequest* navigation_request);
danakjc492bf82020-09-09 20:02:44777
778 // Handlers for the different types of navigation types. They will actually
779 // handle the navigations corresponding to the different NavClasses above.
780 // They will NOT broadcast the commit notification, that should be handled by
781 // the caller.
782 //
783 // RendererDidNavigateAutoSubframe is special, it may not actually change
784 // anything if some random subframe is loaded. It will return true if anything
785 // changed, or false if not.
786 //
Charlie Reisc0f17d2d2021-01-12 18:52:49787 // The NewEntry and NewSubframe functions take in |replace_entry| to pass to
danakjc492bf82020-09-09 20:02:44788 // InsertOrReplaceEntry, in case the newly created NavigationEntry is meant to
789 // replace the current one (e.g., for location.replace or successful loads
790 // after net errors), in contrast to updating a NavigationEntry in place
791 // (e.g., for history.replaceState).
Charlie Reisc0f17d2d2021-01-12 18:52:49792 void RendererDidNavigateToNewEntry(
danakjc492bf82020-09-09 20:02:44793 RenderFrameHostImpl* rfh,
arthursonzogni73fe3212020-11-17 13:24:07794 const mojom::DidCommitProvisionalLoadParams& params,
danakjc492bf82020-09-09 20:02:44795 bool is_same_document,
796 bool replace_entry,
Shivani Sharmaeef521b2024-01-18 13:03:56797 bool previous_document_had_history_intervention_activation,
Rakina Zata Amnia4e27222021-12-22 01:05:00798 NavigationRequest* request,
799 LoadCommittedDetails* details);
Charlie Reisc0f17d2d2021-01-12 18:52:49800 void RendererDidNavigateToExistingEntry(
danakjc492bf82020-09-09 20:02:44801 RenderFrameHostImpl* rfh,
arthursonzogni73fe3212020-11-17 13:24:07802 const mojom::DidCommitProvisionalLoadParams& params,
danakjc492bf82020-09-09 20:02:44803 bool is_same_document,
804 bool was_restored,
805 NavigationRequest* request,
Rakina Zata Amnia4e27222021-12-22 01:05:00806 bool keep_pending_entry,
807 LoadCommittedDetails* details);
danakjc492bf82020-09-09 20:02:44808 void RendererDidNavigateNewSubframe(
809 RenderFrameHostImpl* rfh,
arthursonzogni73fe3212020-11-17 13:24:07810 const mojom::DidCommitProvisionalLoadParams& params,
danakjc492bf82020-09-09 20:02:44811 bool is_same_document,
812 bool replace_entry,
Shivani Sharmaeef521b2024-01-18 13:03:56813 bool previous_document_had_history_intervention_activation,
Rakina Zata Amnia4e27222021-12-22 01:05:00814 NavigationRequest* request,
815 LoadCommittedDetails* details);
danakjc492bf82020-09-09 20:02:44816 bool RendererDidNavigateAutoSubframe(
817 RenderFrameHostImpl* rfh,
arthursonzogni73fe3212020-11-17 13:24:07818 const mojom::DidCommitProvisionalLoadParams& params,
Antonio Sartori78a749f2020-11-30 12:03:39819 bool is_same_document,
Nate Chapinc7019dd7d2021-06-25 18:29:25820 bool was_on_initial_empty_document,
Rakina Zata Amnia4e27222021-12-22 01:05:00821 NavigationRequest* request,
822 LoadCommittedDetails* details);
danakjc492bf82020-09-09 20:02:44823
824 // Allows the derived class to issue notifications that a load has been
825 // committed. This will fill in the active entry to the details structure.
826 void NotifyNavigationEntryCommitted(LoadCommittedDetails* details);
827
828 // Updates the virtual URL of an entry to match a new URL, for cases where
829 // the real renderer URL is derived from the virtual URL, like view-source:
830 void UpdateVirtualURLToURL(NavigationEntryImpl* entry, const GURL& new_url);
831
832 // Invoked after session/tab restore or cloning a tab. Resets the transition
833 // type of the entries, updates the max page id and creates the active
834 // contents.
835 void FinishRestore(int selected_index, RestoreType type);
836
837 // Inserts a new entry or replaces the current entry with a new one, removing
838 // all entries after it. The new entry will become the active one.
839 // If |was_post_commit_error_| is set, the last committed entry will be saved,
840 // the new entry will replace it, and on any navigation away from the new
841 // entry or on reloads, the old one will replace |entry|.
842 void InsertOrReplaceEntry(std::unique_ptr<NavigationEntryImpl> entry,
843 bool replace,
Dave Tapuska87696ae2021-11-18 18:48:31844 bool was_post_commit_error,
Rakina Zata Amnia4e27222021-12-22 01:05:00845 bool is_in_fenced_frame_tree,
846 LoadCommittedDetails* details);
danakjc492bf82020-09-09 20:02:44847
848 // Removes the entry at |index|, as long as it is not the current entry.
849 void RemoveEntryAtIndexInternal(int index);
850
851 // If we have the maximum number of entries, remove the oldest entry that is
852 // marked to be skipped on back/forward button, in preparation to add another.
853 // If no entry is skippable, then the oldest entry will be pruned.
854 void PruneOldestSkippableEntryIfFull();
855
856 // Removes all entries except the last committed entry. If there is a new
857 // pending navigation it is preserved. In contrast to
858 // PruneAllButLastCommitted() this does not update the session history of the
Dave Tapuska2cf1f532022-08-10 15:30:49859 // `blink::WebView`. Callers must ensure that `CanPruneAllButLastCommitted`
860 // returns true before calling this.
danakjc492bf82020-09-09 20:02:44861 void PruneAllButLastCommittedInternal();
862
863 // Inserts up to |max_index| entries from |source| into this. This does NOT
864 // adjust any of the members that reference entries_
865 // (last_committed_entry_index_ or pending_entry_index_)
866 void InsertEntriesFrom(NavigationControllerImpl* source, int max_index);
867
868 // Returns the navigation index that differs from the current entry by the
869 // specified |offset|. The index returned is not guaranteed to be valid.
WangHui74286d52021-03-31 16:17:15870 // This does not account for skippable entries or the history manipulation
871 // intervention.
danakjc492bf82020-09-09 20:02:44872 int GetIndexForOffset(int offset);
873
874 // History Manipulation intervention:
875 // The previous document that started this navigation needs to be skipped in
876 // subsequent back/forward UI navigations if it never received any user
877 // gesture. This is to intervene against pages that manipulate the history
878 // such that the user is not able to go back to the last site they interacted
879 // with (crbug.com/907167).
880 // Note that this function must be called before the new navigation entry is
881 // inserted in |entries_| to make sure UKM reports the URL of the document
882 // adding the entry.
883 void SetShouldSkipOnBackForwardUIIfNeeded(
danakjc492bf82020-09-09 20:02:44884 bool replace_entry,
Shivani Sharmaeef521b2024-01-18 13:03:56885 bool previous_document_had_history_intervention_activation,
danakjc492bf82020-09-09 20:02:44886 bool is_renderer_initiated,
887 ukm::SourceId previous_page_load_ukm_source_id);
888
889 // This function sets all same document entries with the same value
890 // of skippable flag. This is to avoid back button abuse by inserting
891 // multiple history entries and also to help valid cases where a user gesture
892 // on the document should apply to all same document history entries and none
893 // should be skipped. All entries belonging to the same document as the entry
894 // at |reference_index| will get their skippable flag set to |skippable|.
895 void SetSkippableForSameDocumentEntries(int reference_index, bool skippable);
896
897 // Called when one PendingEntryRef is deleted. When all of the refs for the
898 // current pending entry have been deleted, this automatically discards the
899 // pending NavigationEntry.
900 void PendingEntryRefDeleted(PendingEntryRef* ref);
901
Titouan Rigoudy6ec70402021-02-02 15:42:19902 // Computes the policy container policies to be stored in the
903 // FrameNavigationEntry by RendererDidNavigate.
904 std::unique_ptr<PolicyContainerPolicies>
905 ComputePolicyContainerPoliciesForFrameEntry(RenderFrameHostImpl* rfh,
906 bool is_same_document,
Antonio Sartorib8addf62024-09-16 07:59:21907 bool navigation_encountered_error,
Rakina Zata Amniafd3c6582021-11-30 06:19:17908 const GURL& url);
Antonio Sartori78a749f2020-11-30 12:03:39909
Rakina Zata Amni3460d382021-10-29 00:43:37910 // Adds details from a committed navigation to `entry` and the
911 // FrameNavigationEntry corresponding to `rfh`.
912 void UpdateNavigationEntryDetails(
913 NavigationEntryImpl* entry,
914 RenderFrameHostImpl* rfh,
915 const mojom::DidCommitProvisionalLoadParams& params,
916 NavigationRequest* request,
917 NavigationEntryImpl::UpdatePolicy update_policy,
Rakina Zata Amnia4e27222021-12-22 01:05:00918 bool is_new_entry,
919 LoadCommittedDetails* commit_details);
Rakina Zata Amni3460d382021-10-29 00:43:37920
Charlie Reis99b2eba22025-01-31 19:18:57921 // Broadcasts this controller's session history index and length to all
922 // renderers involved in rendering the current page. The index is
Hayato Ito2c8c08d02021-06-23 03:38:43923 // GetLastCommittedEntryIndex() and length is GetEntryCount().
Charlie Reis99b2eba22025-01-31 19:18:57924 void BroadcastHistoryIndexAndLength();
Carlos Caballeroede6f8c2021-01-28 11:01:50925
Domenic Denicolacd30f5f82022-03-16 21:48:01926 // Used by PopulateNavigationApiHistoryEntryVectors to initialize a single
Nate Chapina2c881f52023-11-07 17:02:09927 // vector. `last_index_checked` is an out parameter that indicates the last
928 // entry index walked in `direction` before stopping.
Domenic Denicolacd30f5f82022-03-16 21:48:01929 std::vector<blink::mojom::NavigationApiHistoryEntryPtr>
930 PopulateSingleNavigationApiHistoryEntryVector(
931 Direction direction,
932 int entry_index,
933 const url::Origin& pending_origin,
934 FrameTreeNode* node,
935 SiteInstance* site_instance,
936 int64_t pending_item_sequence_number,
Nate Chapina2c881f52023-11-07 17:02:09937 int64_t pending_document_sequence_number,
938 int& last_index_checked);
Domenic Denicolacc094fb2022-03-16 23:40:57939 // Helper for NavigateToNavigationApiKey(). Ensures that we only navigate to
Nate Chapinfbfe5af2021-06-10 17:22:08940 // |target_entry| if it matches |current_entry|'s origin and site instance, as
Domenic Denicolacc094fb2022-03-16 23:40:57941 // well as having |navigation_api_key| as its key.
942 HistoryNavigationAction ShouldNavigateToEntryForNavigationApiKey(
Nate Chapinfbfe5af2021-06-10 17:22:08943 FrameNavigationEntry* current_entry,
944 FrameNavigationEntry* target_entry,
Domenic Denicolacc094fb2022-03-16 23:40:57945 const std::string& navigation_api_key);
Nate Chapind1fe3612021-04-16 20:45:57946
Minoru Chikamune646eba42025-04-14 01:25:03947 // When navigation starts, the `can_be_in_navigate_to_pending_entry` flag has
948 // to be false. This is because kAvoidUnnecessaryBeforeUnloadCheckSync feature
949 // will stop using PostTask for the legacy beforeunload code in the near
950 // future. When kAvoidUnnecessaryBeforeUnloadCheckSync is enabled,
951 // `RenderFrameHostImpl::ProcessBeforeUnloadCompletedFromFrame()` and
952 // `Navigator::BeforeUnloadCompleted()` can run in the scope of
953 // `in_navigate_to_pending_entry_` == true, and it might end up crashing on
954 // CHECK(!in_navigate_to_pending_entry_).
955 void CheckPotentialNavigationReentrancy();
956
Andrew Verge754c70a2025-04-17 17:19:19957 // Creates a NavigationRequest to use for browser-initiated error page
958 // navigations. When the request is started, it will navigate the
959 // FrameTreeNode corresponding to |render_frame_host_impl| to an error page,
960 // with |url| as the URL and |error_page_html| as the content. If
961 // |is_post_commit_error_page| is true, the entire NavigationEntry will be
962 // temporarily replaced when the navigation completes, otherwise it will be
963 // fully replaced. See |NavigationController::LoadPostCommitErrorPage()| and
964 // |NavigationControllerImpl::NavigateFrameToErrorPage()| for more details on
965 // this distinction.
966 std::unique_ptr<NavigationRequest> CreateNavigationRequestForErrorPage(
967 RenderFrameHostImpl* render_frame_host_impl,
968 const GURL& url,
969 const std::string& error_page_html,
970 bool is_post_commit_error_page);
971
Emmanuel Arias Soto9e159652025-05-16 07:53:55972 // Finds the target FrameTreeNode for navigation. Returns the node specified
973 // by |params| via ID or name, or the root node if none specified.
974 FrameTreeNode* GetTargetFrameTreeNodeForNavigation(
975 const LoadURLParams& params);
976
danakjc492bf82020-09-09 20:02:44977 // ---------------------------------------------------------------------------
978
Carlos Caballero40b0efd2021-01-26 11:55:00979 // The FrameTree this instance belongs to. Each FrameTree gets its own
980 // NavigationController.
Ali Hijazid87307d2022-11-07 20:15:03981 const raw_ref<FrameTree> frame_tree_;
Carlos Caballero40b0efd2021-01-26 11:55:00982
danakjc492bf82020-09-09 20:02:44983 // The user browser context associated with this controller.
Keishi Hattori0e45c022021-11-27 09:25:52984 const raw_ptr<BrowserContext> browser_context_;
danakjc492bf82020-09-09 20:02:44985
986 // List of |NavigationEntry|s for this controller.
987 std::vector<std::unique_ptr<NavigationEntryImpl>> entries_;
988
989 // An entry we haven't gotten a response for yet. This will be discarded
990 // when we navigate again. It's used only so we know what the currently
991 // displayed tab is.
992 //
993 // This may refer to an item in the entries_ list if the pending_entry_index_
994 // != -1, or it may be its own entry that should be deleted. Be careful with
995 // the memory management.
Paul Semel7e51469e2022-07-12 12:16:33996 raw_ptr<NavigationEntryImpl> pending_entry_ = nullptr;
danakjc492bf82020-09-09 20:02:44997
998 // This keeps track of the NavigationRequests associated with the pending
999 // NavigationEntry. When all of them have been deleted, or have stopped
1000 // loading, the pending NavigationEntry can be discarded.
1001 //
1002 // This is meant to avoid a class of URL spoofs where the navigation is
1003 // canceled, but the stale pending NavigationEntry is left in place.
Ali Hijazi133b2d92024-02-09 14:01:521004 std::set<raw_ptr<PendingEntryRef, SetExperimental>> pending_entry_refs_;
danakjc492bf82020-09-09 20:02:441005
1006 // If a new entry fails loading, details about it are temporarily held here
1007 // until the error page is shown (or 0 otherwise).
1008 //
1009 // TODO(avi): We need a better way to handle the connection between failed
1010 // loads and the subsequent load of the error page. This current approach has
1011 // issues: 1. This might hang around longer than we'd like if there is no
1012 // error page loaded, and 2. This doesn't work very well for frames.
1013 // http://crbug.com/474261
1014 int failed_pending_entry_id_ = 0;
1015
1016 // The index of the currently visible entry.
1017 int last_committed_entry_index_ = -1;
1018
1019 // The index of the pending entry if it is in entries_, or -1 if
1020 // pending_entry_ is a new entry (created by LoadURL).
1021 int pending_entry_index_ = -1;
1022
danakjf26536bf2020-09-10 00:46:131023 // The delegate associated with the controller. Possibly null during
danakjc492bf82020-09-09 20:02:441024 // setup.
Keishi Hattori0e45c022021-11-27 09:25:521025 raw_ptr<NavigationControllerDelegate> delegate_;
danakjc492bf82020-09-09 20:02:441026
1027 // Manages the SSL security UI.
1028 SSLManager ssl_manager_;
1029
1030 // Whether we need to be reloaded when made active.
1031 bool needs_reload_ = false;
1032
1033 // Source of when |needs_reload_| is set. Only valid when |needs_reload_|
1034 // is set.
1035 NeedsReloadType needs_reload_type_ = NeedsReloadType::kRequestedByClient;
1036
1037 // Whether this is the initial navigation.
1038 // Becomes false when initial navigation commits.
1039 bool is_initial_navigation_ = true;
1040
1041 // Prevent unsafe re-entrant calls to NavigateToPendingEntry.
1042 bool in_navigate_to_pending_entry_ = false;
1043
Minoru Chikamune646eba42025-04-14 01:25:031044 // A flag to investigate whether kAvoidUnnecessaryBeforeUnloadCheckSync
1045 // feature is safe to enable or not (see: https://crbug.com/40361673,
1046 // https://crbug.com/396998476).
1047 //
1048 // This flag is true if the above `in_navigate_to_pending_entry_` flag is true
1049 // when RenderFrameHostImpl::SendBeforeUnload() runs, and on top of that, when
1050 // we intend to continue navigation synchronously without posting a task when
1051 // the kAvoidUnnecessaryBeforeUnloadCheckSync feature is enabled in either
1052 // kWithSendBeforeUnload or kWithoutSendBeforeUnload mode.
1053 bool can_be_in_navigate_to_pending_entry_ = false;
1054
danakjc492bf82020-09-09 20:02:441055 // Used to find the appropriate SessionStorageNamespace for the storage
1056 // partition of a NavigationEntry.
1057 //
1058 // A NavigationController may contain NavigationEntries that correspond to
1059 // different StoragePartitions. Even though they are part of the same
1060 // NavigationController, only entries in the same StoragePartition may
1061 // share session storage state with one another.
1062 SessionStorageNamespaceMap session_storage_namespace_map_;
1063
danakjc492bf82020-09-09 20:02:441064 // The maximum number of entries that a navigation controller can store.
1065 static size_t max_entry_count_for_testing_;
1066
1067 // If a repost is pending, its type (RELOAD or RELOAD_BYPASSING_CACHE),
1068 // NO_RELOAD otherwise.
1069 ReloadType pending_reload_ = ReloadType::NONE;
1070
1071 // Used to get timestamps for newly-created navigation entries.
1072 base::RepeatingCallback<base::Time()> get_timestamp_callback_;
1073
1074 // Used to smooth out timestamps from |get_timestamp_callback_|.
1075 // Without this, whenever there is a run of redirects or
1076 // code-generated navigations, those navigations may occur within
1077 // the timer resolution, leading to things sometimes showing up in
1078 // the wrong order in the history view.
1079 TimeSmoother time_smoother_;
1080
1081 // BackForwardCache:
1082 //
1083 // Stores frozen RenderFrameHost. Restores them on history navigation.
1084 // See BackForwardCache class documentation.
1085 BackForwardCacheImpl back_forward_cache_;
1086
William Liu055a3542023-04-02 17:21:191087 // Stores captured screenshots for this `NavigationController`. The
1088 // screenshots are used to present the user with the previews of the
1089 // previously visited pages when the back/forward navigations occur.
1090 std::unique_ptr<NavigationEntryScreenshotCache> nav_entry_screenshot_cache_;
1091
danakjc492bf82020-09-09 20:02:441092 // Holds the entry that was committed at the time an error page was triggered
1093 // due to a call to LoadPostCommitErrorPage. The error entry will take its
1094 // place until the user navigates again, at which point it will go back into
1095 // the entry list instead of the error entry. Set to nullptr if there is no
1096 // post commit error entry. Note that this entry must always correspond to the
1097 // last committed entry index, and that there can be only a single post-commit
1098 // error page entry in its place in entries_. This ensures that its spot in
1099 // entries_ cannot go away (e.g., due to PruneForwardEntries) and that it can
1100 // go back into place after any subsequent commit.
1101 std::unique_ptr<NavigationEntryImpl> entry_replaced_by_post_commit_error_;
1102
1103 // NOTE: This must be the last member.
1104 base::WeakPtrFactory<NavigationControllerImpl> weak_factory_{this};
danakjc492bf82020-09-09 20:02:441105};
1106
1107} // namespace content
1108
1109#endif // CONTENT_BROWSER_RENDERER_HOST_NAVIGATION_CONTROLLER_IMPL_H_