blob: 22d9fdf0be2150eae7bcd6ea883945132f20c2fd [file] [log] [blame]
// Copyright 2014 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CONTENT_BROWSER_RENDERER_HOST_NAVIGATION_REQUEST_H_
#define CONTENT_BROWSER_RENDERER_HOST_NAVIGATION_REQUEST_H_
#include <memory>
#include <optional>
#include <string>
#include <utility>
#include <vector>
#include "base/debug/crash_logging.h"
#include "base/functional/callback.h"
#include "base/functional/callback_forward.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/raw_ptr_exclusion.h"
#include "base/memory/safe_ref.h"
#include "base/memory/weak_ptr.h"
#include "base/strings/string_util.h"
#include "base/time/time.h"
#include "base/timer/timer.h"
#include "build/build_config.h"
#include "content/browser/fenced_frame/fenced_frame_url_mapping.h"
#include "content/browser/loader/keep_alive_url_loader_service.h"
#include "content/browser/loader/navigation_url_loader_delegate.h"
#include "content/browser/loader/subresource_proxying_url_loader_service.h"
#include "content/browser/navigation_subresource_loader_params.h"
#include "content/browser/renderer_host/browsing_context_group_swap.h"
#include "content/browser/renderer_host/commit_deferring_condition_runner.h"
#include "content/browser/renderer_host/cookie_access_observers.h"
#include "content/browser/renderer_host/navigation_controller_impl.h"
#include "content/browser/renderer_host/navigation_policy_container_builder.h"
#include "content/browser/renderer_host/navigation_throttle_registry_impl.h"
#include "content/browser/renderer_host/navigation_type.h"
#include "content/browser/renderer_host/render_frame_host_impl.h"
#include "content/browser/renderer_host/scoped_view_transition_resources.h"
#include "content/browser/security/coop/cross_origin_opener_policy_status.h"
#include "content/browser/security/dip/document_isolation_policy_reporter.h"
#include "content/browser/site_instance_impl.h"
#include "content/browser/webui/web_ui_controller_factory_registry.h"
#include "content/browser/webui/web_ui_impl.h"
#include "content/common/content_export.h"
#include "content/common/navigation_client.mojom-forward.h"
#include "content/public/browser/global_routing_id.h"
#include "content/public/browser/navigation_handle.h"
#include "content/public/browser/navigation_throttle.h"
#include "content/public/browser/preloading_trigger_type.h"
#include "content/public/browser/render_process_host_observer.h"
#include "content/public/browser/weak_document_ptr.h"
#include "content/public/browser/web_ui_controller.h"
#include "content/public/common/content_constants.h"
#include "mojo/public/cpp/bindings/associated_remote.h"
#include "mojo/public/cpp/bindings/pending_associated_remote.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
#include "mojo/public/cpp/system/data_pipe.h"
#include "mojo/public/cpp/system/simple_watcher.h"
#include "net/base/isolation_info.h"
#include "net/dns/public/resolve_error_info.h"
#include "net/http/http_connection_info.h"
#include "services/metrics/public/cpp/ukm_builders.h"
#include "services/metrics/public/cpp/ukm_source_id.h"
#include "services/network/public/cpp/content_security_policy/csp_context.h"
#include "services/network/public/mojom/blocked_by_response_reason.mojom-shared.h"
#include "services/network/public/mojom/content_security_policy.mojom.h"
#include "services/network/public/mojom/shared_dictionary_access_observer.mojom.h"
#include "services/network/public/mojom/trust_token_access_observer.mojom-shared.h"
#include "services/network/public/mojom/web_sandbox_flags.mojom-shared.h"
#include "third_party/blink/public/common/runtime_feature_state/runtime_feature_state_context.h"
#include "third_party/blink/public/common/tokens/tokens.h"
#include "third_party/blink/public/mojom/confidence_level.mojom.h"
#include "third_party/blink/public/mojom/lcp_critical_path_predictor/lcp_critical_path_predictor.mojom.h"
#include "third_party/blink/public/mojom/loader/mixed_content.mojom-forward.h"
#include "third_party/blink/public/mojom/navigation/navigation_initiator_activation_and_ad_status.mojom.h"
#include "third_party/blink/public/mojom/navigation/navigation_params.mojom-forward.h"
#include "url/gurl.h"
#include "url/gurl_debug.h"
#include "url/origin.h"
#include "url/origin_debug.h"
#if BUILDFLAG(IS_ANDROID)
#include "base/android/scoped_java_ref.h"
#include "content/browser/android/navigation_handle_proxy.h"
#endif
namespace network {
struct IntegrityPolicy;
struct URLLoaderCompletionStatus;
} // namespace network
namespace ui {
class CompositorLock;
} // namespace ui
namespace content {
class AgentClusterKey;
class CrossOriginEmbedderPolicyReporter;
class FrameTreeNode;
class NavigationUIData;
class NavigationURLLoader;
class NavigatorDelegate;
class PrefetchedSignedExchangeCache;
class PrerenderHostRegistry;
class RenderFrameHostCSPContext;
class ServiceWorkerMainResourceHandle;
class SubframeHistoryNavigationThrottle;
// The primary implementation of NavigationHandle.
//
// Lives from navigation start until the navigation has been committed.
class CONTENT_EXPORT NavigationRequest
: public NavigationHandle,
public NavigationURLLoaderDelegate,
public CommitDeferringConditionRunner::Delegate,
public FencedFrameURLMapping::MappingResultObserver,
public mojom::NavigationRendererCancellationListener,
private RenderProcessHostObserver,
private network::mojom::TrustTokenAccessObserver,
private network::mojom::SharedDictionaryAccessObserver,
public network::mojom::DeviceBoundSessionAccessObserver {
public:
// Keeps track of the various stages of a NavigationRequest.
// To see what state transitions are allowed, see |SetState|.
enum NavigationState {
// Initial state.
NOT_STARTED = 0,
// Waiting for a BeginNavigation IPC from the renderer in a
// browser-initiated navigation. If there is no live renderer when the
// request is created, this stage is skipped.
WAITING_FOR_RENDERER_RESPONSE,
// TODO(zetamoo): Merge this state with WILL_START_REQUEST.
// Temporary state where:
// - Before unload handlers have run and this navigation is allowed to
// start.
// - The navigation is still not visible to embedders (via
// NavigationHandle).
WILL_START_NAVIGATION,
// The navigation is visible to embedders (via NavigationHandle). Wait for
// the NavigationThrottles to finish running the WillStartRequest event.
// This is potentially asynchronous.
// For navigations that have already committed synchronously in the renderer
// (see |is_synchronous_renderer_commit_|), this will synchronously proceed
// to DID_COMMIT directly without any waiting (or the navigation might not
// commit in certain cases, and be cleared in this state). All other
// navigations can only reach DID_COMMIT from READY_TO_COMMIT.
WILL_START_REQUEST,
// The request is being redirected. Wait for the NavigationThrottles to
// finish running the WillRedirectRequest event. This is potentially
// asynchronous.
WILL_REDIRECT_REQUEST,
// The response is being processed. Wait for the NavigationThrottles to
// finish running the WillProcessResponse event. This is potentially
// asynchronous.
WILL_PROCESS_RESPONSE,
// The navigation does not require a request/response. Wait only for
// NavigationThrottles to finish before calling CommitNavigation(). This
// will only be asynchronous if a throttle defers the navigation.
WILL_COMMIT_WITHOUT_URL_LOADER,
// The browser process has asked the renderer to commit the response
// and is waiting for acknowledgement that it has been committed.
READY_TO_COMMIT,
// The response has been committed. This is one of the two final states of
// the request.
DID_COMMIT,
// The request is being canceled.
CANCELING,
// The request is failing. Wait for the NavigationThrottles to finish
// running the WillFailRequest event. This is potentially asynchronous.
WILL_FAIL_REQUEST,
// The request failed with a net error code and an error page should be
// displayed. This is one of the two final states for the request.
DID_COMMIT_ERROR_PAGE,
};
// The RenderFrameHost currently associated with the navigation. Note that the
// final value will only be known when the response is received, or the
// navigation fails, as server redirects can modify the RenderFrameHost to use
// for the navigation.
enum class AssociatedRenderFrameHostType {
NONE = 0,
// The navigation reuses the current RenderFrameHost.
CURRENT,
// The navigation uses a new RenderFrameHost, the speculative
// RenderFrameHost.
SPECULATIVE,
};
// This enum is used in UMA histograms, so existing values should neither be
// reordered or removed.
enum class OriginAgentClusterEndResult {
// The first four enums are for use when OAC-by-default is disabled.
kNotRequestedAndNotOriginKeyed,
kNotRequestedButOriginKeyed,
kRequestedButNotOriginKeyed,
kRequestedAndOriginKeyed,
// The remaining enums are for use when OAC-by-default is enabled.
kExplicitlyNotRequestedAndNotOriginKeyed,
kExplicitlyNotRequestedButOriginKeyed,
kExplicitlyRequestedButNotOriginKeyed,
kExplicitlyRequestedAndOriginKeyed,
kNotExplicitlyRequestedButNotOriginKeyed,
kNotExplicitlyRequestedAndOriginKeyed,
kMaxValue = kNotExplicitlyRequestedAndOriginKeyed
};
// If this navigation is a browser-initiated error page navigation, this enum
// describes the scenario that triggered the navigation, and how session
// history will be affected as a result.
enum class BrowserInitiatedErrorNavigationType {
// This navigation is not a browser-initiated error page navigation. The
// default value for all newly-created NavigationRequests.
kNone,
// This is a normal error navigation as triggered by
// NavigationControllerImpl::NavigateFrameToErrorPage(). The current session
// history item will be fully replaced when the navigation commits.
kRegular,
// This is a post-commit error page navigation as triggered by
// NavigationController::LoadPostCommitErrorPage(). The current session
// history item will be set aside when the navigation commits, and replaced
// when any following navigation commits.
kPostCommit,
};
// A detailed reason on why errors in navigation happened, to be assigned in
// the extended error code field. Mostly focusing on `net::ERR_ABORTED`
// failures.
//
// These values are persisted to logs. Entries should not be renumbered and
// numeric values should never be reused.
//
// LINT.IfChange(ErrorNavigationTrigger)
enum class ErrorNavigationTrigger {
// An unknown trigger caused navigation abort.
kUnknown = 0,
// Caused by the cancelation from the navigation throttle.
kNavigationThrottleCancel,
// Caused by being blocked by the navigation throtle.
kNavigationThrottleBlock,
// Caused by the redirect not allowed due to the security policy.
kRedirectNotAllowed,
// Caused by the Credentialed subresource check blocked.
kCredentialedSubresourceBlocked,
// Caused by the embedder-initiated navigation of FencedFrame being blocked.
kFencedFrameEmbedderInitiatedNavigation,
// Caused by the permission policy of fenced frames being blocked.
kFencedFramesPermissionPolicyBlocked,
// Caused by the content decoder data pipe creation failing.
kContentDecoderDataPipeCreationFailed,
// The response should not be rendered (e.g. a download).
kShouldNotRenderResponse,
// The embedder overrides/blocks the URL load.
kShouldOverrideUrlLoading,
// The render initiated cross process navigation is not allowed, and blocked
// the navigation.
kRenderInitiatedCrossProcessNavigationNotAllowed,
// The render initiated navigation could not request the URL.
kRendererInitiatedCanNotRequestURL,
// The response rendered fallback content, due to e.g. Http errors.
kShouldRenderFallbackContent,
kMaxValue = kShouldRenderFallbackContent,
};
// LINT.ThenChange(//tools/metrics/histograms/metadata/navigation/enums.xml:ErrorNavigationTrigger)
// Creates a request for a browser-initiated navigation.
static std::unique_ptr<NavigationRequest> CreateBrowserInitiated(
FrameTreeNode* frame_tree_node,
blink::mojom::CommonNavigationParamsPtr common_params,
blink::mojom::CommitNavigationParamsPtr commit_params,
bool was_opener_suppressed,
const std::string& extra_headers,
FrameNavigationEntry* frame_entry,
NavigationEntryImpl* entry,
bool is_form_submission,
std::unique_ptr<NavigationUIData> navigation_ui_data,
const std::optional<blink::Impression>& impression,
bool is_pdf,
bool is_embedder_initiated_fenced_frame_navigation = false,
std::optional<std::u16string> embedder_shared_storage_context =
std::nullopt);
// Creates a request for either a browser-initiated navigation or a
// renderer-initiated navigation. Returns nullptr if the navigation could not
// be started, such as when network access has been revoked (see
// RenderFrameHost::IsUntrustedNetworkDisabled()). Normally,
// renderer-initiated navigations use CreateRendererInitiated(), but some
// legacy renderer-initiated navigation paths, such as OpenURL, are stuck
// using this path instead; these cases specify `browser_initiated` as false.
//
// Do NOT add more uses of this function. Browser-initiated navigations
// should use CreateBrowserInitiated() and renderer-initiated navigations
// should use CreateRendererInitiated().
//
// TODO(crbug.com/40249771): Refactor the remaining uses of this function to
// use either CreateBrowserInitiated() or CreateRendererInitiated() and then
// remove this helper.
static std::unique_ptr<NavigationRequest> Create(
FrameTreeNode* frame_tree_node,
blink::mojom::CommonNavigationParamsPtr common_params,
blink::mojom::CommitNavigationParamsPtr commit_params,
bool browser_initiated,
bool was_opener_suppressed,
const std::optional<blink::LocalFrameToken>& initiator_frame_token,
int initiator_process_id,
const std::string& extra_headers,
FrameNavigationEntry* frame_entry,
NavigationEntryImpl* entry,
bool is_form_submission,
std::unique_ptr<NavigationUIData> navigation_ui_data,
const std::optional<blink::Impression>& impression,
blink::mojom::NavigationInitiatorActivationAndAdStatus
initiator_activation_and_ad_status,
bool is_pdf,
bool is_embedder_initiated_fenced_frame_navigation = false,
bool is_container_initiated = false,
bool has_rel_opener = false,
net::StorageAccessApiStatus storage_access_api_status =
net::StorageAccessApiStatus::kNone,
std::optional<std::u16string> embedder_shared_storage_context =
std::nullopt);
// Creates a request for a renderer-initiated navigation.
static std::unique_ptr<NavigationRequest> CreateRendererInitiated(
FrameTreeNode* frame_tree_node,
NavigationEntryImpl* entry,
blink::mojom::CommonNavigationParamsPtr common_params,
blink::mojom::BeginNavigationParamsPtr begin_params,
int current_history_list_index,
int current_history_list_length,
bool override_user_agent,
scoped_refptr<network::SharedURLLoaderFactory> blob_url_loader_factory,
mojo::PendingAssociatedRemote<mojom::NavigationClient> navigation_client,
scoped_refptr<PrefetchedSignedExchangeCache>
prefetched_signed_exchange_cache,
mojo::PendingReceiver<mojom::NavigationRendererCancellationListener>
renderer_cancellation_listener);
// Creates a NavigationRequest for synchronous navigation that have committed
// in the renderer process. Those are:
// - same-document renderer-initiated navigations.
// - synchronous about:blank navigations.
//
// TODO(clamy): Eventually, this should only be called for same-document
// renderer-initiated navigations.
static std::unique_ptr<NavigationRequest> CreateForSynchronousRendererCommit(
FrameTreeNode* frame_tree_node,
RenderFrameHostImpl* render_frame_host,
bool is_same_document,
const GURL& url,
const url::Origin& origin,
const std::optional<GURL>& initiator_base_url,
const net::IsolationInfo& isolation_info_for_subresources,
blink::mojom::ReferrerPtr referrer,
const ui::PageTransition& transition,
bool should_replace_current_entry,
const std::string& method,
bool has_transient_activation,
bool is_overriding_user_agent,
const std::vector<GURL>& redirects,
const GURL& original_url,
std::unique_ptr<CrossOriginEmbedderPolicyReporter> coep_reporter,
std::unique_ptr<DocumentIsolationPolicyReporter> dip_reporter,
int http_response_code,
base::TimeTicks actual_navigation_start);
static NavigationRequest* From(NavigationHandle* handle);
// If |type| is a reload, returns the equivalent ReloadType. Otherwise returns
// ReloadType::NONE.
static ReloadType NavigationTypeToReloadType(
blink::mojom::NavigationType type);
NavigationRequest(const NavigationRequest&) = delete;
NavigationRequest& operator=(const NavigationRequest&) = delete;
~NavigationRequest() override;
// Returns true if this request's URL matches |origin| and the request state
// is at (or past) WILL_PROCESS_RESPONSE.
bool HasCommittingOrigin(const url::Origin& origin);
// Returns true if this navigation's COOP header implies that the destination
// site of this navigation should be site-isolated. In addition to checking
// for eligible COOP header values, this function also verifies other
// criteria, such as whether this feature is enabled on the device (e.g.,
// above memory threshold) or whether the site is already isolated.
bool ShouldRequestSiteIsolationForCOOP();
// NavigationHandle implementation:
int64_t GetNavigationId() const override;
ukm::SourceId GetNextPageUkmSourceId() override;
const GURL& GetURL() override;
SiteInstanceImpl* GetStartingSiteInstance() override;
SiteInstanceImpl* GetSourceSiteInstance() override;
bool IsInMainFrame() const override;
bool IsInPrimaryMainFrame() const override;
bool IsInOutermostMainFrame() const override;
bool IsInPrerenderedMainFrame() const override;
bool IsPrerenderedPageActivation() const override;
bool IsInFencedFrameTree() const override;
bool IsGuestViewMainFrame() const override;
FrameType GetNavigatingFrameType() const override;
bool IsRendererInitiated() override;
blink::mojom::NavigationInitiatorActivationAndAdStatus
GetNavigationInitiatorActivationAndAdStatus() override;
bool IsSameOrigin() override;
bool WasServerRedirect() override;
const std::vector<GURL>& GetRedirectChain() override;
FrameTreeNodeId GetFrameTreeNodeId() override;
RenderFrameHostImpl* GetParentFrame() override;
RenderFrameHostImpl* GetParentFrameOrOuterDocument() override;
base::TimeTicks NavigationStart() override;
base::TimeTicks NavigationInputStart() override;
const NavigationHandleTiming& GetNavigationHandleTiming() override;
bool IsPost() override;
std::string GetRequestMethod() override;
const blink::mojom::Referrer& GetReferrer() override;
void SetReferrer(blink::mojom::ReferrerPtr referrer) override;
bool HasUserGesture() override;
ui::PageTransition GetPageTransition() override;
NavigationUIData* GetNavigationUIData() override;
bool IsExternalProtocol() override;
net::Error GetNetErrorCode() override;
int GetNetExtendedErrorCode() override;
RenderFrameHostImpl* GetRenderFrameHost() const override;
bool IsSameDocument() const override;
bool IsHistory() const override;
bool HasCommitted() const override;
bool IsErrorPage() const override;
bool HasSubframeNavigationEntryCommitted() override;
bool DidReplaceEntry() override;
bool ShouldUpdateHistory() override;
const GURL& GetPreviousPrimaryMainFrameURL() override;
net::IPEndPoint GetSocketAddress() override;
const net::HttpRequestHeaders& GetRequestHeaders() override;
void RemoveRequestHeader(const std::string& header_name) override;
void SetRequestHeader(const std::string& header_name,
const std::string& header_value) override;
void SetCorsExemptRequestHeader(const std::string& header_name,
const std::string& header_value) override;
void SetLCPPNavigationHint(
const blink::mojom::LCPCriticalPathPredictorNavigationTimeHint& hint)
override;
const blink::mojom::LCPCriticalPathPredictorNavigationTimeHintPtr&
GetLCPPNavigationHint() override;
const net::HttpResponseHeaders* GetResponseHeaders() override;
net::HttpConnectionInfo GetConnectionInfo() override;
const std::optional<net::SSLInfo>& GetSSLInfo() override;
const std::optional<net::AuthChallengeInfo>& GetAuthChallengeInfo() override;
net::ResolveErrorInfo GetResolveErrorInfo() override;
net::IsolationInfo GetIsolationInfo() override;
void RegisterThrottleForTesting(
std::unique_ptr<NavigationThrottle> navigation_throttle) override;
bool IsDeferredForTesting() override;
bool IsCommitDeferringConditionDeferredForTesting() override;
CommitDeferringCondition* GetCommitDeferringConditionForTesting() override;
bool WasStartedFromContextMenu() override;
const GURL& GetSearchableFormURL() override;
const std::string& GetSearchableFormEncoding() override;
ReloadType GetReloadType() const override;
RestoreType GetRestoreType() const override;
const GURL& GetBaseURLForDataURL() override;
const GlobalRequestID& GetGlobalRequestID() override;
bool IsDownload() override;
bool IsFormSubmission() override;
bool WasInitiatedByLinkClick() override;
bool IsSignedExchangeInnerResponse() override;
bool HasPrefetchedAlternativeSubresourceSignedExchange() override;
bool WasResponseCached() override;
const std::string& GetHrefTranslate() override;
const std::optional<blink::Impression>& GetImpression() override;
const std::optional<blink::LocalFrameToken>& GetInitiatorFrameToken()
override;
int GetInitiatorProcessId() override;
const std::optional<url::Origin>& GetInitiatorOrigin() override;
const std::optional<GURL>& GetInitiatorBaseUrl() override;
const std::vector<std::string>& GetDnsAliases() override;
bool IsSameProcess() override;
NavigationEntry* GetNavigationEntry() const override;
int GetNavigationEntryOffset() const override;
void RegisterSubresourceOverride(
blink::mojom::TransferrableURLLoaderPtr transferrable_loader) override;
GlobalRenderFrameHostId GetPreviousRenderFrameHostId() override;
ChildProcessId GetExpectedRenderProcessHostId() override;
bool IsServedFromBackForwardCache() override;
void SetIsOverridingUserAgent(bool override_ua) override;
void SetSilentlyIgnoreErrors() override;
void SetVisitedLinkSalt(uint64_t salt) override;
network::mojom::WebSandboxFlags SandboxFlagsInitiator() override;
network::mojom::WebSandboxFlags SandboxFlagsInherited() override;
network::mojom::WebSandboxFlags SandboxFlagsToCommit() override;
bool IsWaitingToCommit() override;
bool WasResourceHintsReceived() override;
bool IsPdf() override;
void WriteIntoTrace(perfetto::TracedProto<TraceProto> context) const override;
bool SetNavigationTimeout(base::TimeDelta timeout) override;
void CancelNavigationTimeout() override;
void SetAllowCookiesFromBrowser(bool allow_cookies_from_browser) override;
void GetResponseBody(ResponseBodyCallback callback) override;
PreloadingTriggerType GetPrerenderTriggerType() override;
std::string GetPrerenderEmbedderHistogramSuffix() override;
#if BUILDFLAG(IS_ANDROID)
const base::android::JavaRef<jobject>& GetJavaNavigationHandle() override;
#endif
base::SafeRef<NavigationHandle> GetSafeRef() override;
bool ExistingDocumentWasDiscarded() const override;
blink::RuntimeFeatureStateContext& GetMutableRuntimeFeatureStateContext()
override;
void SetContentSettings(
blink::mojom::RendererContentSettingsPtr content_settings) override;
blink::mojom::RendererContentSettingsPtr GetContentSettingsForTesting()
override;
void SetIsAdTagged() override;
std::optional<NavigationDiscardReason> GetNavigationDiscardReason() override;
// NOTE: Read function comments in NavigationHandle before use!
std::optional<url::Origin> GetOriginToCommit() override;
// End of NavigationHandle implementation.
// mojom::NavigationRendererCancellationListener implementation:
void RendererCancellationWindowEnded() override;
// End of mojom::NavigationRendererCancellationListener implementation.
void RegisterCommitDeferringConditionForTesting(
std::unique_ptr<CommitDeferringCondition> condition);
// Used by tests that want to control the timing of cookie access
// notifications.
void SetCookieAccessObserversForTesting(
std::unique_ptr<CookieAccessObservers> cookie_access_observers);
// Called on the UI thread by the Navigator to start the navigation.
// The NavigationRequest can be deleted while BeginNavigation() is called.
void BeginNavigation();
const blink::mojom::CommonNavigationParams& common_params() const {
return *common_params_;
}
const blink::mojom::BeginNavigationParams& begin_params() const {
return *begin_params_;
}
const blink::mojom::CommitNavigationParams& commit_params() const {
return *commit_params_;
}
// This describes the cases where the navigation start time is adjusted to be
// later in time, after BeforeUnloadCompleted. This enum is used in UMA
// histograms, so existing values should be neither reordered nor removed.
enum class NavigationStartAdjustmentType {
// No adjustment to the navigation start time was made.
kNone = 0,
// The start time was adjusted so that the navigation could proceed via a
// posted task, even though there were no beforeunload handlers registered.
kLegacyPostTask = 1,
// The start time was adjusted because beforeunload handlers ran, but no
// dialog was displayed to the user.
kBeforeUnloadHandlers = 2,
// The start time was adjusted because a beforeunload dialog was shown.
kBeforeUnloadDialog = 3,
kMaxValue = kBeforeUnloadDialog,
};
// Updates the navigation start time, after beforeunload has completed.
// `for_legacy` indicates that the navigation proceeded in a separate task for
// legacy reasons, without running beforeunload handlers. `showed_dialog`
// indicates whether the beforeunload handlers actually displayed a dialog.
void UpdateNavigationStartTime(const base::TimeTicks& time,
bool for_legacy,
bool showed_dialog);
void set_is_cross_site_cross_browsing_context_group(
bool is_cross_site_cross_browsing_context_group) {
commit_params_->is_cross_site_cross_browsing_context_group =
is_cross_site_cross_browsing_context_group;
}
NavigationURLLoader* loader_for_testing() const { return loader_.get(); }
NavigationState state() const { return state_; }
FrameTreeNode* frame_tree_node() const { return frame_tree_node_; }
bool is_synchronous_renderer_commit() const {
return is_synchronous_renderer_commit_;
}
SiteInstanceImpl* dest_site_instance() const {
return dest_site_instance_.get();
}
std::optional<BindingsPolicySet> bindings() const { return bindings_; }
bool browser_initiated() const {
return commit_params_->is_browser_initiated;
}
bool from_begin_navigation() const { return from_begin_navigation_; }
AssociatedRenderFrameHostType GetAssociatedRFHType() const;
void SetAssociatedRFHType(AssociatedRenderFrameHostType type);
bool HasRenderFrameHost() const { return render_frame_host_.has_value(); }
void set_was_discarded() { commit_params_->was_discarded = true; }
void set_net_error(net::Error net_error) { net_error_ = net_error; }
const std::string& GetMimeType() {
return response_head_ ? response_head_->mime_type : base::EmptyString();
}
const network::mojom::URLResponseHead* response() {
return response_head_.get();
}
const mojo::DataPipeConsumerHandle& response_body() {
DCHECK_EQ(state_, WILL_PROCESS_RESPONSE);
return response_body_.get();
}
mojo::ScopedDataPipeConsumerHandle& mutable_response_body_for_testing() {
return response_body_;
}
void SetWaitingForRendererResponse();
// Notifies the NavigatorDelegate the navigation started. This should be
// called after any previous NavigationRequest for the FrameTreeNode has been
// destroyed.
void StartNavigation();
void set_on_start_checks_complete_closure_for_testing(
base::OnceClosure closure) {
on_start_checks_complete_closure_ = std::move(closure);
}
// Updates the destination SiteInfo for this navigation. This is called on
// redirects. |post_redirect_process| is the renderer process that should
// handle the navigation following the redirect if it can be handled by an
// existing RenderProcessHost. Otherwise, it should be null.
void UpdateSiteInfo(RenderProcessHost* post_redirect_process);
int nav_entry_id() const { return nav_entry_id_; }
// For automation driver-initiated navigations over the devtools protocol,
// |devtools_navigation_token_| is used to tag the navigation. This navigation
// token is then sent into the renderer and lands on the DocumentLoader. That
// way subsequent Blink-level frame lifecycle events can be associated with
// the concrete navigation.
// - The value should not be sent back to the browser.
// - The value on DocumentLoader may be generated in the renderer in some
// cases, and thus shouldn't be trusted.
// TODO(crbug.com/40549185): Replace devtools navigation token with the
// generic navigation token that can be passed from renderer to the browser.
const base::UnguessableToken& devtools_navigation_token() const {
return devtools_navigation_token_;
}
blink::mojom::ConfidenceLevel navigation_confidence() const {
return confidence_level_;
}
// This token is passed in various IPCs pertaining to navigations, such as
// frame and proxy creation as well as CommitNavigation, and is used by
// renderer-side metrics code to tie together different IPCs that were sent as
// part of performing a particular navigation. It is not intended to be used
// for anything other than metrics and trace events.
//
// Note that this token is stored in CommitNavigationParams, even though it's
// also needed before CommitNavigation (e.g., it needs to be included in frame
// and proxy creation IPCs which are sent before CommitNavigation) - this
// should be ok since commit_params() are initialized when a NavigationRequest
// is created.
const base::UnguessableToken& navigation_metrics_token() const {
return commit_params().navigation_metrics_token;
}
// Called on same-document navigation requests that need to be restarted as
// cross-document navigations. This happens when a same-document commit fails
// due to another navigation committing in the meantime.
void ResetForCrossDocumentRestart();
// If the navigation redirects cross-process or otherwise is forced to use a
// different SiteInstance than anticipated (e.g., for switching between error
// states), then reset any sensitive state that shouldn't carry over to the
// new process.
void ResetStateForSiteInstanceChange();
// If a navigation has been cancelled, and was initiated by the parent
// document, report it with the appropriate ResourceTiming entry information.
//
// The ResourceTiming entry may not be sent if the current frame
// does not have a parent, or if the navigation was cancelled before
// a request was made.
void MaybeAddResourceTimingEntryForCancelledNavigation();
// Adds a resource timing entry to the parent in case of cancelled navigations
// and failed <object> navigations.
void AddResourceTimingEntryForFailedSubframeNavigation(
const network::URLLoaderCompletionStatus& status);
// Lazily initializes and returns the mojo::NavigationClient interface used
// for commit.
mojom::NavigationClient* GetCommitNavigationClient();
void set_transition(ui::PageTransition transition) {
common_params_->transition = transition;
}
void set_has_user_gesture(bool has_user_gesture) {
common_params_->has_user_gesture = has_user_gesture;
}
// Ignores any interface disconnect that might happen to the
// navigation_client used to commit.
void IgnoreCommitInterfaceDisconnection();
// Resume and CancelDeferredNavigation must only be called by the
// NavigationThrottle that is currently deferring the navigation.
// |resuming_throttle| and |cancelling_throttle| are the throttles calling
// these methods.
void Resume(NavigationThrottle* resuming_throttle);
void CancelDeferredNavigation(NavigationThrottle* cancelling_throttle,
NavigationThrottle::ThrottleCheckResult result);
// Returns the underlying NavigationThrottleRegistry for tests to manipulate.
NavigationThrottleRegistryImpl* GetNavigationThrottleRegistryForTesting() {
return throttle_registry_.get();
}
// Simulates renderer cancelling the navigation.
void RendererRequestedNavigationCancellationForTesting();
typedef base::OnceCallback<bool(NavigationThrottle::ThrottleCheckResult)>
ThrottleChecksFinishedCallback;
// Called when the navigation was committed.
// This will update the |state_|.
// |navigation_entry_committed| indicates whether the navigation changed which
// NavigationEntry is current.
// |did_replace_entry| is true if the committed entry has replaced the
// existing one. A non-user initiated redirect causes such replacement.
void DidCommitNavigation(const mojom::DidCommitProvisionalLoadParams& params,
bool navigation_entry_committed,
bool did_replace_entry,
const GURL& previous_main_frame_url);
NavigationType navigation_type() const {
DCHECK(state_ == DID_COMMIT || state_ == DID_COMMIT_ERROR_PAGE);
return navigation_type_;
}
void set_navigation_type(NavigationType navigation_type) {
navigation_type_ = navigation_type;
}
void set_browser_initiated_error_navigation_type(
BrowserInitiatedErrorNavigationType type) {
browser_initiated_error_navigation_type_ = type;
}
BrowserInitiatedErrorNavigationType
browser_initiated_error_navigation_type() {
return browser_initiated_error_navigation_type_;
}
void set_error_page_html(const std::string& error_page_html) {
CHECK(browser_initiated_error_navigation_type_ !=
BrowserInitiatedErrorNavigationType::kNone);
error_page_html_ = error_page_html;
}
void set_from_download_cross_origin_redirect(
bool from_download_cross_origin_redirect) {
from_download_cross_origin_redirect_ = from_download_cross_origin_redirect;
}
// This should be a private method. The only valid reason to be used
// outside of the class constructor is in the case of an initial history
// navigation in a subframe. This allows a browser-initiated NavigationRequest
// to be canceled by the renderer.
void SetNavigationClient(
mojo::PendingAssociatedRemote<mojom::NavigationClient> navigation_client);
// Whether the navigation loads an MHTML document or a subframe of an MHTML
// document. The navigation might or might not be fullfilled from the MHTML
// archive (see `is_mhtml_subframe_loaded_from_achive` in the NeedsUrlLoader
// method). The navigation will commit in the main frame process.
bool IsMhtmlOrSubframe();
// Whether this navigation navigates a subframe of an MHTML document.
bool IsForMhtmlSubframe() const;
// Whether the navigation has a non-OK net error code.
// Note that this is different from IsErrorPage(), which only returns true if
// the navigation has finished committing an error page. The net error code
// can be non-OK before commit and also in cases that didn't result in the
// navigation being committed (e.g. canceled navigations).
virtual bool DidEncounterError() const;
void set_begin_navigation_callback_for_testing(base::OnceClosure callback) {
begin_navigation_callback_for_testing_ = std::move(callback);
}
void set_complete_callback_for_testing(
ThrottleChecksFinishedCallback callback) {
complete_callback_for_testing_ = std::move(callback);
}
network::mojom::URLLoaderClientEndpointsPtr&
mutable_url_loader_client_endpoints_for_testing() {
return url_loader_client_endpoints_;
}
void set_ready_to_commit_callback_for_testing(base::OnceClosure callback) {
ready_to_commit_callback_for_testing_ = std::move(callback);
}
// Whether this navigation is queued, waiting for an existing pending commit
// RenderFrameHost to finish navigating.
bool IsQueued() const { return !!resume_commit_closure_; }
void set_renderer_cancellation_window_ended_callback(
base::OnceClosure callback) {
DCHECK(!renderer_cancellation_window_ended());
renderer_cancellation_window_ended_callback_ = std::move(callback);
}
bool renderer_cancellation_window_ended() const {
return renderer_cancellation_window_ended_;
}
// Returns true if this navigation should wait for the renderer-initiated
// navigation cancellation window to end before committing, and returns false
// otherwise. See comment for `renderer_cancellation_listener_` for more
// details.
bool ShouldWaitForRendererCancellationWindowToEnd();
// Sets the READY_TO_COMMIT -> DID_COMMIT timeout. Resets the timeout to the
// default value if |timeout| is zero.
static void SetCommitTimeoutForTesting(const base::TimeDelta& timeout);
// Returns the `rfh_restored_from_back_forward_cache_` if the navigation is
// a BFCache restore, or nullptr otherwise.
RenderFrameHostImpl* GetRenderFrameHostRestoredFromBackForwardCache() const;
// The NavigatorDelegate to notify/query for various navigation events. This
// is always the WebContents.
NavigatorDelegate* GetDelegate() const;
blink::mojom::RequestContextType request_context_type() const {
return begin_params_->request_context_type;
}
network::mojom::RequestDestination request_destination() const {
return common_params_->request_destination;
}
blink::mojom::MixedContentContextType mixed_content_context_type() const {
return begin_params_->mixed_content_context_type;
}
// Returns true if the navigation was started by the Navigator by calling
// BeginNavigation(), or if the request was created at commit time by calling
// CreateForCommit().
bool IsNavigationStarted() const;
std::unique_ptr<viz::PeakGpuMemoryTracker> TakePeakGpuMemoryTracker();
std::unique_ptr<NavigationEarlyHintsManager> TakeEarlyHintsManager();
// Returns true for navigation responses to be rendered in a renderer process.
// This excludes:
// - 204/205 navigation responses
// - Most downloads
// (Note: downloads with unsuccessful response codes will render an error
// page, causing this to return true.)
//
// Must not be called before having received the response. After
// OnResponseStarted(), this is expected to be equivalent to
// HasRenderFrameHost().
bool response_should_be_rendered() const {
DCHECK_GE(state_, WILL_PROCESS_RESPONSE);
return response_should_be_rendered_;
}
// Returns the `ClientSecurityState` we should pass to
// `NavigationURLLoaderFactory`.
//
// For subresource requests the `ClientSecurityState` is passed through
// `URLLoaderFactoryParams`, since each request client has a dedicated
// factory. That does not work for navigation requests because they all share
// a common factory, so each request is tagged with a `ClientSecurityState` to
// use instead.
network::mojom::ClientSecurityStatePtr
BuildClientSecurityStateForNavigationFetch();
// Returns the `ClientSecurityState` to be used for subresource fetches by the
// document we are navigating to.
//
// Must only be called after `ReadyToCommitNavigation()`.
network::mojom::ClientSecurityStatePtr
BuildClientSecurityStateForCommittedDocument();
bool ua_change_requires_reload() const { return ua_change_requires_reload_; }
void SetRequiredCSP(network::mojom::ContentSecurityPolicyPtr csp);
network::mojom::ContentSecurityPolicyPtr TakeRequiredCSP();
bool is_credentialless() const { return is_credentialless_; }
// Returns a pointer to the policies copied from the navigation initiator.
// Returns nullptr if this navigation had no initiator.
const PolicyContainerPolicies* GetInitiatorPolicyContainerPolicies() const;
// The DocumentToken that should be used for the document created as a result
// of committing this navigation.
// - must only be called for cross-document navigations
// - must not be called before the navigation is ready to commit
const blink::DocumentToken& GetDocumentToken() const;
// Returns the policies of the new document being navigated to.
//
// Must only be called after ReadyToCommitNavigation().
const PolicyContainerPolicies& GetPolicyContainerPolicies() const;
// Creates a new policy container for Blink connected to this navigation's
// PolicyContainerHost.
//
// Must only be called after ReadyToCommitNavigation().
blink::mojom::PolicyContainerPtr CreatePolicyContainerForBlink();
// Returns a new refptr to this navigation's PolicyContainerHost.
//
// Must only be called after ReadyToCommitNavigation().
// It is invalid to call after `TakePolicyContainerHost()`.
scoped_refptr<PolicyContainerHost> GetPolicyContainerHost();
// Moves this navigation's PolicyContainerHost out of this instance.
//
// Must only be called after ReadyToCommitNavigation().
scoped_refptr<PolicyContainerHost> TakePolicyContainerHost();
CrossOriginEmbedderPolicyReporter* coep_reporter() {
return coep_reporter_.get();
}
DocumentIsolationPolicyReporter* dip_reporter() {
return dip_reporter_.get();
}
std::unique_ptr<CrossOriginEmbedderPolicyReporter> TakeCoepReporter();
std::unique_ptr<DocumentIsolationPolicyReporter> TakeDipReporter();
// Returns UKM SourceId for the page we are navigating away from.
// Equal to GetRenderFrameHost()->GetPageUkmSourceId() for subframe
// and same-document navigations and to
// RenderFrameHost::FromID(GetPreviousRenderFrameHostId())
// ->GetPageUkmSourceId() for main-frame cross-document navigations.
// Note: If this method is called on a prerender navigation, it will return
// ukm::kInvalidSourceId due to our data collection policy.
ukm::SourceId GetPreviousPageUkmSourceId();
void OnServiceWorkerAccessed(const GURL& scope,
AllowServiceWorkerResult allowed);
// Take all cookie observers associated with this navigation.
// Typically this is called when navigation commits to move these observers to
// the committed document.
[[nodiscard]] std::vector<
std::pair<mojo::PendingReceiver<network::mojom::CookieAccessObserver>,
CookieAccessDetails::Source>>
TakeCookieObservers();
void NotifyCookiesAccessed(
std::vector<network::mojom::CookieAccessDetailsPtr> details_vector,
CookieAccessDetails::Source source);
// Take all Trust Token observers associated with this navigation.
// Typically this is called when navigation commits to move these observers to
// the committed document.
[[nodiscard]] std::vector<
mojo::PendingReceiver<network::mojom::TrustTokenAccessObserver>>
TakeTrustTokenObservers();
// Take all shared dictionary observers associated with this navigation.
// Typically this is called when navigation commits to move these observers to
// the committed document.
[[nodiscard]] std::vector<
mojo::PendingReceiver<network::mojom::SharedDictionaryAccessObserver>>
TakeSharedDictionaryAccessObservers();
[[nodiscard]] std::vector<
mojo::PendingReceiver<network::mojom::DeviceBoundSessionAccessObserver>>
TakeDeviceBoundSessionAccessObservers();
// Returns the coop status information relevant to the current navigation.
CrossOriginOpenerPolicyStatus& coop_status() { return coop_status_; }
// Returns true if this is a NavigationRequest represents a WebView
// loadDataWithBaseUrl navigation.
bool IsLoadDataWithBaseURL() const;
// Calculates the origin that this NavigationRequest may commit.
//
// GetTentativeOriginAtRequestTime must be called before the final HTTP
// response is received (unlike GetOriginToCommit), but the returned origin
// may differ from the final origin committed by this navigation (e.g. the
// origin may change because of subsequent redirects, or because of CSP
// headers in the final response; or because no commit may happen at all in
// case of downloads or 204 responses). Prefer to use GetOriginToCommit if
// possible.
url::Origin GetTentativeOriginAtRequestTime();
// If this navigation fails with net::ERR_BLOCKED_BY_CLIENT, act as if it were
// cancelled by the user and do not commit an error page.
void SetSilentlyIgnoreBlockedByClient() {
silently_ignore_blocked_by_client_ = true;
}
// Returns the current url from GetURL() packaged with other state required to
// properly determine SiteInstances and process allocation.
UrlInfo GetUrlInfo();
bool is_overriding_user_agent() const {
return commit_params_->is_overriding_user_agent;
}
// Returns the IsolationInfo that should be used to load subresources.
const net::IsolationInfo& isolation_info_for_subresources() const {
return isolation_info_for_subresources_;
}
// NeedsUrlLoader() returns true if the navigation needs to use the
// NavigationURLLoader for loading the document.
//
// A few types of navigations don't make any network requests. They can be
// committed immediately in BeginNavigation(). They self-contain the data
// needed for commit:
// - about:blank: The renderer already knows how to load the empty document.
// - about:srcdoc: The data is stored in the iframe srcdoc attribute.
// - same-document: Only the history and URL are updated, no new document.
// - MHTML subframe: The data is in the archive, owned by the main frame.
//
// Note #1: Even though "data:" URLs don't generate actual network requests,
// including within MHTML subframes, they are still handled by the network
// stack. The reason is that a few of them can't always be handled otherwise.
// For instance:
// - the ones resulting in downloads.
// - the "invalid" ones. An error page is generated instead.
// - the ones with an unsupported MIME type.
// - the ones targeting the top-level frame on Android.
//
// Note #2: Even though "javascript:" URL and RendererDebugURL fit very well
// in this category, they don't use the NavigationRequest.
//
// Note #3: Navigations that do not use a URL loader do not send the usual
// set of callbacks to NavigationThrottle. Instead, they send a single
// separate callback, WillCommitWithoutUrlLoader().
bool NeedsUrlLoader();
network::mojom::PrivateNetworkRequestPolicy private_network_request_policy()
const {
return private_network_request_policy_;
}
// Whether this navigation request waits for the result of beforeunload before
// proceeding.
bool IsWaitingForBeforeUnload();
// Returns the original request url:
// - If this navigation resulted in an error page, this will return the URL
// of the page that failed to load.
// - If this is navigation is triggered by loadDataWithBaseURL or related
// functions, this will return the data URL (or data header, in case of
// loadDataAsStringWithBaseURL).
// - Otherwise, this will return the first URL in |redirect_chain_|. This
// means if the navigation is started due to a client redirect, we will return
// the URL of the page that initiated the client redirect. Otherwise we will
// return the first destination URL for this navigation.
// NOTE: This might result in a different value than original_url in
// |commit_params_|, which is always set to the first destination URL for this
// navigation.
const GURL& GetOriginalRequestURL();
// The previous main frame URL. This may be empty if there was no last
// committed entry.
const GURL& GetPreviousMainFrameURL() const;
// This is the same as |NavigationHandle::IsServedFromBackForwardCache|, but
// adds a const qualifier.
bool IsServedFromBackForwardCache() const;
// Whether this navigation is activating an existing page (e.g. served from
// the BackForwardCache or Prerender)
bool IsPageActivation() const override;
// Returns whether the navigation type is a restore navigation.
bool IsRestore() const;
// Returns whether the navigation type is a reload navigation.
bool IsReload() const;
// Sets state pertaining to prerender activations. This is only called if
// this navigation is a prerender activation.
void SetPrerenderActivationNavigationState(
std::unique_ptr<NavigationEntryImpl> prerender_navigation_entry,
const blink::mojom::FrameReplicationState& replication_state);
std::unique_ptr<NavigationEntryImpl> TakePrerenderNavigationEntry();
// Returns value that is only valid for prerender activation navigations.
const blink::mojom::FrameReplicationState&
prerender_main_frame_replication_state() {
return prerender_navigation_state_->prerender_main_frame_replication_state;
}
// Origin-keyed Agent Cluster (OAC) state needs to be tracked for origins that
// opt-in or opt-out, so that a given origin is treated consistently within a
// given BrowsingInstance. This ensures that foo.example.com will have the
// same OAC state in a BrowsingInstance even if multiple documents in the
// origin have different headers.
//
// This function ensures that this OAC state is tracked in cases where it is
// not handled elsewhere. For example, OAC origins that end up in origin-keyed
// processes already track their OAC state during SiteInstance creation.
// However, SiteInstance does not track origin state in the following cases,
// which this function handles:
//
// 1) If process isolation for OAC is disabled (e.g., on low-memory Android
// devices), the origin will use a site-keyed SiteInstance that does not
// record OAC state for the origin.
//
// 2) If the origin has no header but ends up with OAC-by-default (and
// kOriginKeyedProcessesByDefault is not enabled), the origin will use a
// site-keyed SiteInstance.
//
// 3) If the origin opts-out of OAC using a header, it will use a site-keyed
// SiteInstance.
//
// 4)If the origin opts-in to OAC using a header, but it is first placed in a
// speculative RenderFrameHost before the header is received, it creates a
// SiteInfo with default isolation and an origin-keyed process (by default).
// In this case, the origin was not tracked when the SiteInstance was created,
// and needs to be tracked later when the opt-in header is observed.
//
// In all of these cases, this function updates the BrowsingInstance to keep
// track of the OAC state for this NavigationRequest's origin.
//
// TODO(wjmaclean): Cases 1 and 2 will not be necessary once we use
// origin-keyed SiteInstances within a site-keyed process, via
// SiteInstanceGroup. Cases 3 and 4 will still be needed at that point, but
// might become simpler.
void AddOriginAgentClusterStateIfNecessary(
const IsolationContext& isolation_context);
// Store a console message, which will be sent to the final RenderFrameHost
// immediately after requesting the navigation to commit.
//
// /!\ WARNING /!\: Beware of not leaking cross-origin information to a
// potentially compromised renderer when using this method.
void AddDeferredConsoleMessage(blink::mojom::ConsoleMessageLevel level,
std::string message);
bool is_deferred_on_fenced_frame_url_mapping_for_testing() const {
return is_deferred_on_fenced_frame_url_mapping_;
}
base::WeakPtr<NavigationRequest> GetWeakPtr();
bool is_running_potential_prerender_activation_checks() const {
return is_running_potential_prerender_activation_checks_;
}
FrameTreeNodeId prerender_frame_tree_node_id() const {
DCHECK(prerender_frame_tree_node_id_.has_value())
<< "Must be called after StartNavigation()";
return prerender_frame_tree_node_id_.value();
}
const std::optional<FencedFrameProperties>& GetFencedFrameProperties() const {
return fenced_frame_properties_;
}
// Compute and return the `FencedFrameProperties` that this
// `NavigationRequest` acts under, i.e. the properties attached to this
// `NavigationRequest` if present.
// Otherwise, returns the fenced frame properties associated with the given
// source. See `FrameTreeNode::GetFencedFrameProperties()` on how fenced
// frame properties are obtained for different sources.
// TODO(crbug.com/40060657): Once navigation support for urn::uuid in iframes
// is deprecated, remove the parameter `node_source`.
const std::optional<FencedFrameProperties>& ComputeFencedFrameProperties(
FencedFramePropertiesNodeSource node_source =
FencedFramePropertiesNodeSource::kClosestAncestor) const;
const std::optional<base::UnguessableToken> ComputeFencedFrameNonce() const;
void RenderFallbackContentForObjectTag();
// Returns the vector of web features used during the navigation, whose
// recording was delayed until the new document that used them commits.
//
// Empties this instance's vector.
std::vector<blink::mojom::WebFeature> TakeWebFeaturesToLog();
void set_subresource_proxying_url_loader_service_bind_context(
base::WeakPtr<SubresourceProxyingURLLoaderService::BindContext>
bind_context) {
DCHECK(!subresource_proxying_url_loader_service_bind_context_);
subresource_proxying_url_loader_service_bind_context_ = bind_context;
}
base::WeakPtr<KeepAliveURLLoaderService::FactoryContext>
keep_alive_url_loader_factory_context() {
return keep_alive_url_loader_factory_context_;
}
void set_keep_alive_url_loader_factory_context(
base::WeakPtr<KeepAliveURLLoaderService::FactoryContext> factory_context);
base::WeakPtr<KeepAliveURLLoaderService::FactoryContext>
fetch_later_loader_factory_context() {
return fetch_later_loader_factory_context_;
}
void set_fetch_later_loader_factory_context(
base::WeakPtr<KeepAliveURLLoaderService::FactoryContext> factory_context);
void SetKeepAliveURLLoaderFactoryContextForTesting(
base::WeakPtr<KeepAliveURLLoaderService::FactoryContext> factory_context);
void SetFetchLaterLoaderFactoryContextForTesting(
base::WeakPtr<KeepAliveURLLoaderService::FactoryContext> factory_context);
// Helper for logging crash keys related to a NavigationRequest (e.g.
// "navigation_request_url", "navigation_request_initiator", and
// "navigation_request_is_same_document"). The crash keys will be logged if a
// ScopedCrashKeys instance exists when a crash or DumpWithoutCrashing
// happens.
class ScopedCrashKeys {
public:
explicit ScopedCrashKeys(NavigationRequest& navigation_request);
~ScopedCrashKeys();
// No copy constructor and no copy assignment operator.
ScopedCrashKeys(const ScopedCrashKeys&) = delete;
ScopedCrashKeys& operator=(const ScopedCrashKeys&) = delete;
private:
url::debug::ScopedOriginCrashKey initiator_origin_;
url::debug::ScopedUrlCrashKey url_;
base::debug::ScopedCrashKeyString is_same_document_;
};
// Prerender2:
void set_prerender_trigger_type(PreloadingTriggerType type) {
DCHECK(!prerender_trigger_type_.has_value());
prerender_trigger_type_ = type;
}
void set_prerender_embedder_histogram_suffix(const std::string& suffix) {
prerender_embedder_histogram_suffix_ = suffix;
}
// Used in tests to indicate this navigation should force a BrowsingInstance
// swap.
void set_force_new_browsing_instance(bool force_new_browsing_instance) {
force_new_browsing_instance_ = force_new_browsing_instance;
}
// When this returns true, it indicates this navigation should force a
// BrowsingInstance swap. Used only in tests.
bool force_new_browsing_instance() { return force_new_browsing_instance_; }
// Marks this navigation as requiring a new compositor (RenderWidgetHost).
void set_force_new_compositor(bool force_new_compositor) {
force_new_compositor_ = force_new_compositor;
}
// True if this navigation requires a new compositor (RenderWidgetHost).
bool force_new_compositor() { return force_new_compositor_; }
const scoped_refptr<NavigationOrDocumentHandle>&
navigation_or_document_handle() {
return navigation_or_document_handle_;
}
// Initializes state which is passed from the old Document to the new Document
// for a ViewTransition.
void SetViewTransitionState(
std::unique_ptr<ScopedViewTransitionResources> resources,
blink::ViewTransitionState view_transition_state);
// Returns a const reference to a blink::RuntimeFeatureStateContext (RFSC)
// object. Once the commit params are sent to the renderer we no longer allow
// write access to the RFSC, but read access is still available.
//
// Note: This method has another
// version, `GetMutableRuntimeFeatureStateContext()`, accessible via
// NavigationHandle and will return a mutable reference to the RFSC.
const blink::RuntimeFeatureStateContext& GetRuntimeFeatureStateContext();
BrowsingContextGroupSwap browsing_context_group_swap() const {
return browsing_context_group_swap_;
}
// If the navigation fails before commit and |pending_navigation_api_key_| has
// been set, then the renderer will be notified of the pre-commit failure and
// provide |pending_navigation_api_key_| so that the Navigation API can fire
// events and reject promises.
// This should only be set if this request's frame initiated the navigation,
// because only the initiating frame has outstanding promises to reject.
void set_pending_navigation_api_key(std::optional<std::string> key) {
pending_navigation_api_key_ = key;
}
// Returns the navigation token for this request if this NavigationRequest
// is for a history navigation, and it might be cancelled via the navigate
// event. In that case, any associated subframe history navigations will be
// deferred until this navigation commits.
// This may only be called if this is a main-frame same-document navigation.
// Will return a valid token if canceling traversals via the navigate event is
// enabled, this is a history navigation, a navigate event is registered in
// the renderer, and the frame has met the user activation requirements to be
// allowed to cancel the navigation.
// This token will then be provided to the subframe NavigationRequests via
// set_main_frame_same_document_history_token().
std::optional<base::UnguessableToken>
GetNavigationTokenForDeferringSubframes();
// For subframe NavigationRequests, these set and return the main frame's
// NavigationRequest token, in the case that the main frame returns it from
// GetNavigationTokenForDeferringSubframes(). Note that by the time
// `main_frame_same_document_history_token()` is called, the NavigationRequest
// represented by that token may have already finished and been deleted, so
// any attempt to lookup based on this token must null-check the request.
void set_main_frame_same_document_history_token(
std::optional<base::UnguessableToken> token) {
main_frame_same_document_navigation_token_ = token;
}
std::optional<base::UnguessableToken>
main_frame_same_document_history_token() {
return main_frame_same_document_navigation_token_;
}
// When a SubframeHistoryNavigationThrottle is created, it registers itself
// with the NavigationRequest for the main frame. If the main frame
// NavigationRequest commits, then these throttles will be resumed in
// UnblockPendingSubframeNavigationRequestsIfNeeded().
// If it is canceled instead, these throttles will all be canceled.
// Takes a WeakPtr because `throttle` is owned by another NavigationRequest,
// and that request may be canceled outside of our control, in which case
// `throttle` will be destroyed.
void AddDeferredSubframeNavigationThrottle(
base::WeakPtr<SubframeHistoryNavigationThrottle> throttle);
std::unique_ptr<RenderFrameHostImpl::CookieChangeListener>
TakeCookieChangeListener() {
return std::move(cookie_change_listener_);
}
std::unique_ptr<RenderFrameHostImpl::DeviceBoundSessionObserver>
TakeDeviceBoundSessionObserver() {
return std::move(device_bound_session_observer_);
}
// Returns true if there is a speculative RFH that has a pending commit
// cross-document navigation, and this NavigationRequest is not a pending
// commit NavigationRequest itself. This means that this navigation should be
// queued (i.e. wait for the pending commit navigation to finish committing),
// before continuing and creating a new speculative RFH to commit in, so that
// it won't cause the existing pending commit RFH to be deleted. This function
// should only be called for navigations that are owned by the FrameTreeNode
// (i.e. it hasn't moved to the RenderFrameHost that it will commit in yet),
// as only those navigations can be queued.
bool ShouldQueueDueToExistingPendingCommitRFH() const;
void set_resume_commit_closure(base::OnceClosure closure) {
resume_commit_closure_ = std::move(closure);
}
// Records metrics for `GetFrameHostForNavigation()` attempts that failed due
// to this `NavigationRequest` being in the pending commit state.
// `commit_attempt` should be true if `GetFrameHostForNavigation()` failed
// when trying to get a RenderFrameHost when committing a navigation.
void RecordMetricsForBlockedGetFrameHostAttempt(bool commit_attempt);
// Creates a WebUI object for this navigation and saves it in `web_ui_`. Later
// on, the WebUI created will be moved to `frame_host` (if `frame_host` is
// null, it means a RenderFrameHost has not been picked for the navigation).
void CreateWebUIIfNeeded(RenderFrameHostImpl* frame_host);
bool HasWebUI() { return !!web_ui_; }
WebUIImpl* web_ui() { return web_ui_.get(); }
std::unique_ptr<WebUIImpl> TakeWebUI() {
CHECK(HasWebUI());
return std::move(web_ui_);
}
bool shared_storage_writable_eligible() const {
return shared_storage_writable_eligible_;
}
enum ErrorPageProcess {
kNotErrorPage,
kPostCommitErrorPage,
kCurrentProcess,
kDestinationProcess,
kIsolatedProcess
};
// Helper to determine whether a navigation is committing an error page and
// should stay in the current process (kCurrentProcess), the destination
// URL's process (kDestinationProcess), an isolated process
// (kIsolatedProcess), or is a post-commit error page that does not have any
// specific process requirements and goes through the "normal navigation"
// path. Returns kNotErrorPage if the navigation is not anerror page
// navigation.
ErrorPageProcess ComputeErrorPageProcess();
// This describes the reason for performing an early RenderFrameHost swap, if
// any. This enum is used in UMA histograms, so existing values should be
// neither reordered nor removed.
enum class EarlyRenderFrameHostSwapType {
kNone = 0,
kInitialFrame = 1,
kCrashedFrame = 2,
kNavigationTransition = 3, // DEPRECATED
kMaxValue = kNavigationTransition,
};
// Remember if this navigation triggered an early swap of a speculative
// RenderFrameHost to become a current RenderFrameHost prior to the
// navigation commit, and if so, what triggered it.
void set_early_render_frame_host_swap_type(
EarlyRenderFrameHostSwapType type) {
early_render_frame_host_swap_type_ = type;
}
EarlyRenderFrameHostSwapType early_render_frame_host_swap_type() const {
return early_render_frame_host_swap_type_;
}
void set_previous_render_frame_host_id(GlobalRenderFrameHostId id) {
previous_render_frame_host_id_ = id;
}
// Returns true if URL Loader has been created and hasn't been reset yet for
// this navigation.
bool HasLoader() const;
// Notifies that an IPC will be sent to the old Document's renderer to
// dispatch the `pageswap` event. Returns the parameters which should be
// used for the event if this is a same-origin navigation.
blink::mojom::PageSwapEventParamsPtr WillDispatchPageSwap();
// Returns true if this navigation is eligible for dispatching a `pageswap`
// event on the old Document and the event has not been dispatched already.
bool ShouldDispatchPageSwapEvent() const;
// Returns true if there have been any cross-origin redirects in the
// navigation's lifetime. A redirect is cross-origin if the redirect url is
// cross-origin with "previous URL" of the navigation. previous URL here is
// either the initial URL (which the navigation started with) or the URL from
// the last redirect.
//
// Note: This will be false if the initial url is cross-origin and there are
// no redirects.
bool did_encounter_cross_origin_redirect() const {
return did_encounter_cross_origin_redirect_;
}
// Determines whether this navigation request was initiated by an animated
// transition.
void set_was_initiated_by_animated_transition() {
was_initiated_by_animated_transition_ = true;
}
bool was_initiated_by_animated_transition() const {
return was_initiated_by_animated_transition_;
}
void set_navigation_discard_reason(
NavigationDiscardReason navigation_discard_reason) {
CHECK(!navigation_discard_reason_.has_value());
navigation_discard_reason_ = navigation_discard_reason;
}
// Returns the type of this navigation (e.g. history, browser-initiated, etc)
// to set as a discard reason on another navigation that is being discarded
// because this navigation is taking its place in the FrameTreeNode.
NavigationDiscardReason GetTypeForNavigationDiscardReason();
void set_force_no_https_upgrade() { force_no_https_upgrade_ = true; }
bool was_reset_for_cross_document_restart() const {
return was_reset_for_cross_document_restart_;
}
// Returns the document sequence number from the associated
// FrameNavigationEntry, if this NavigationRequest corresponds to a session
// history navigation. The value is cleared if the navigation performs a
// redirect or results in an origin change, in which case the
// NavigationRequest is no longer tied to the original entry.
int64_t frame_entry_document_sequence_number() const {
return frame_entry_document_sequence_number_;
}
// Called when the browser process is about to process beforeunload handlers
// for this navigation, including sending an IPC to the renderer process to
// run beforeunload handlers when necessary.
void WillStartBeforeUnload();
// This struct holds timestamps of various stages of one navigation. This is
// useful for recording a trace of a navigation, as well as metrics for
// durations of all intervals within a navigation once a navigation finishes
// committing. Note that a navigation finishes committing once
// RenderFrameHostImpl::DidCommitNavigation completes, which could be slightly
// after the corresponding NavigationRequest has been destroyed.
//
// Over the course of a navigation, various timestamps are kept in different
// places, such as NavigationRequest fields, NavigationHandleTiming,
// CommonNavigationParams, etc. The purpose of this struct is to bring all the
// relevant timestamps into one place, and make it possible to record a
// complete navigation timeline after NavigationRequest destruction. Note that
// this is different from NavigationHandleTiming, because the latter is in
// content/public and exposed to content embedders, making it tricky to modify
// or extend.
//
// This struct should be created near the end of NavigationRequest's lifetime
// (see `GenerateNavigationTimelineForMetrics()`), and `MarkFinish()` should
// be called at the end of a navigation before using the `Timeline`'s
// timestamp values in traces and metrics.
struct Timeline {
Timeline();
Timeline(const Timeline& timeline);
~Timeline();
// Record the timestamp for when the navigation finishes. Should be done at
// the end of RenderFrameHostImpl::DidCommitNavigationInternal() before
// recording a trace of this timeline.
void MarkFinish();
// The timestamps below are in chronological order. Note that some of them
// might be null depending on the navigation (e.g., navigations that don't
// use the network stack will not populate the loader-related timestamps,
// and renderer-initiated same-document navigations would be missing most
// timestamps except for `start`, `finish`, and the DidCommit IPC
// timestamps).
// The time at which the navigation starts, as accurately as we can
// determine. Note that for renderer-initiated navigations, this will be the
// time when the navigation starts in the renderer.
//
// Note that this may not be the start time used by many current navigation
// related metrics, such as FCP, since those often use `common_params_start`
// to avoid including beforeunload durations.
// TODO(crbug.com/385170155): Update these metrics to have a more consistent
// and representative start time and duration.
base::TimeTicks start;
// For navigations that start in the renderer and target local frames, this
// is the time at which "beforeunload phase 1" starts, when ShouldClose is
// called for any local frames that may be affected. This is null for other
// types of navigations which do not use beforeunload phase 1 (e.g., browser
// initiated navigations, or navigations that target remote frames). See
// also beforeunload_phase2_start, for the second phase of running
// beforeunload handlers which may exist in other processes.
//
// The delta between this and `start` captures the time the renderer process
// spends initializing the navigation, including notifying
// RenderFrameObserver::DidStartNavigation observers.
base::TimeTicks beforeunload_phase1_start;
// The time "beforeunload phase 1" ends in the initiating renderer process,
// or null if that phase is not used in this navigation. Recording this
// allows beforeunload duration to be excluded from navigation metrics,
// since that time may include user-visible dialogs or JavaScript code that
// is out of our control.
base::TimeTicks beforeunload_phase1_end;
// The time at which the NavigationRequest is created. The delta between
// this and `start` covers the time between starting the navigation
// (possibly in the renderer process) and the browser process starting
// doing work for it. It is often useful to exclude beforeunload phase 1
// duration from this delta.
base::TimeTicks navigation_request_creation;
// The time "beforeunload phase 2" processing was started by the browser
// process. This phase can occur on any type of navigation (e.g., browser or
// renderer initiated), to run beforeunload handlers in any process that may
// be affected by the navigation (e.g., remote frames, OOPIFs). Might be
// null if the navigation did not need to run beforeunload handlers, or if
// all of the necessary handlers have already run in "beforeunload phase 1."
// Note that legacy PostTask cases (which do not run beforeunload handlers)
// are not treated as beforeunload phase 2.
//
// The delta between this and `navigation_request_creation` captures the
// time the browser process spends initializing the navigation, including
// creating a speculative RenderFrameHost (if needed) and picking a target
// SiteInstance/process.
base::TimeTicks beforeunload_phase2_start;
// The time "beforeunload phase 2" processing ends, or null if that phase is
// not used in this navigation. Recording this allows beforeunload duration
// to be excluded from navigation metrics, since that may include
// user-visible dialogs or JavaScript code that is out of our control.
base::TimeTicks beforeunload_phase2_end;
// The adjusted start time used by many navigation metrics, such as FCP.
// This is currently set inconsistently, and can be after beforeunload phase
// 1 in the initiating renderer, or early in a browser-initiated navigation,
// or after beforeunload phase 2 in the browser process if that phase is
// used. As a result, this value may not be in chronological order in this
// struct, and it is mainly recorded here for metrics that measure the start
// time inconsistency.
// TODO(crbug.com/385170155): Remove this once navigation start metrics are
// more consistent.
base::TimeTicks common_params_start;
// The time at which NavigationRequest::BeginNavigation() is called. This is
// a decision point at which a network request may or may not be made. The
// delta between this and `navigation_request_creation` (with any
// beforeunload phase 2 duration removed) captures additional navigation
// work in the browser process.
base::TimeTicks begin_navigation;
// The time at which the NavigationURLLoader for the navigation was started.
// This captures the time for additional initialization in the browser
// process before the network request is sent, including processing of
// WillStartRequest NavigationThrottle events.
base::TimeTicks loader_start;
// The time when the browser is ready to fetch the document using an HTTP
// request.
base::TimeTicks loader_fetch_start;
// The time when the final (which might also be the first) headers are
// received.
base::TimeTicks loader_receive_headers;
// The time when the HTTP response is received and
// NavigationRequest::OnResponseStarted() is called. The delta between this
// and `loader_start` captures the time spent waiting for a response from
// the network stack.
base::TimeTicks receive_response;
// The time when the CommitNavigation IPC is sent to the renderer process.
// Might be null if a navigation doesn't send the CommitNavigation IPC, such
// as for renderer-initiated same-document navigations or synchronous
// about:blank navigations. The delta between this and `receive_response`
// captures the time spent running throttles and possibly selecting a more
// appropriate renderer process.
base::TimeTicks commit_ipc_sent;
// The time when the renderer receives the CommitNavigation IPC. Taken in
// the renderer process. Might be null in the same cases as
// `commit_ipc_sent` above. The delta between this and `commit_ipc_sent`
// represents the mojo and task delay to deliver the CommitNavigation
// message from the browser process to renderer process.
base::TimeTicks renderer_commit_ipc_received;
// The time when the renderer finishes processing the navigation commit and
// replies to the browser's CommitNavigation IPC. Taken in the renderer
// process. The delta between this and `renderer_commit_ipc_received`
// represents the total time the renderer process spend on committing the
// navigation (e.g., swapping in the new frame/document and destroying the
// old document).
base::TimeTicks renderer_did_commit_ipc_sent;
// The time at which the DidCommitNavigation IPC (which is usually a
// response to the CommitNavigation IPC) is received by RenderFrameHost. The
// delta between `renderer_did_commit_ipc_sent` and this represents the mojo
// delay to deliver the response from the renderer process to the browser
// process.
base::TimeTicks did_commit_ipc_received;
// The time at which DidCommitNavigation is completed. This includes the
// time to commit the navigation, dispatch events such as
// DidFinishNavigation() to observers, and destroy the NavigationRequest.
// `MarkFinish()` is used to record this timestamp at the end of navigation.
base::TimeTicks finish;
};
// Fill in the timestamps needed to generate a trace of the navigation
// timeline. This should only be called when processing the
// DidCommitNavigation IPC, once the final DidCommitProvisionalLoadParams are
// received from the renderer and timestamps from prior navigation stages are
// already collected.
//
// Note that this leaves the `finish` timestamp empty in the returned
// `Timeline` object. `finish` cannot be recorded within NavigationRequest
// because a navigation actually ends after a NavigationRequest is destroyed.
// `MarkFinish()` should be called on the returned `Timeline` to manually
// record that timestamp before using it to record trace events or metrics.
NavigationRequest::Timeline GenerateNavigationTimelineForMetrics(
const mojom::DidCommitProvisionalLoadParams& params,
const base::TimeTicks& did_commit_ipc_received_time);
// Returns a UKM builder for the navigation timeline if UKMs should be
// recorded for this navigation. Navigation timeline UKMs are recorded at the
// frequency of 0.001.
std::optional<ukm::builders::NavigationTimeline>
GetNavigationTimelineUkmBuilder();
// Called when the NavigationThrottleRunner is done processing the navigation
// event of type `event`. `result` is the final
// NavigationThrottle::ThrottleCheckResult for this event.
void OnNavigationEventProcessed(
NavigationThrottleEvent event,
NavigationThrottle::ThrottleCheckResult result);
private:
friend class NavigationRequestTest;
FRIEND_TEST_ALL_PREFIXES(NavigationRequestTest, SanitizeRedirectsForCommit);
struct ConsoleMessage {
blink::mojom::ConsoleMessageLevel level;
std::string message;
};
NavigationRequest(
FrameTreeNode* frame_tree_node,
blink::mojom::CommonNavigationParamsPtr common_params,
blink::mojom::BeginNavigationParamsPtr begin_params,
blink::mojom::CommitNavigationParamsPtr commit_params,
bool browser_initiated,
bool from_begin_navigation,
bool is_synchronous_renderer_commit,
const FrameNavigationEntry* frame_navigation_entry,
NavigationEntryImpl* navitation_entry,
std::unique_ptr<NavigationUIData> navigation_ui_data,
scoped_refptr<network::SharedURLLoaderFactory> blob_url_loader_factory,
mojo::PendingAssociatedRemote<mojom::NavigationClient> navigation_client,
scoped_refptr<PrefetchedSignedExchangeCache>
prefetched_signed_exchange_cache,
std::optional<base::SafeRef<RenderFrameHostImpl>>
rfh_restored_from_back_forward_cache,
int initiator_process_id,
bool was_opener_suppressed,
bool is_pdf,
bool is_embedder_initiated_fenced_frame_navigation = false,
mojo::PendingReceiver<mojom::NavigationRendererCancellationListener>
renderer_cancellation_listener = mojo::NullReceiver(),
std::optional<std::u16string> embedder_shared_storage_context =
std::nullopt);
// Checks if this navigation may activate a prerendered page. If it's
// possible, schedules to start running CommitDeferringConditions for
// prerendered page activation and returns true.
bool MaybeStartPrerenderingActivationChecks();
// Called from OnCommitDeferringConditionChecksComplete() if this request is
// activating a prerendered page.
void OnPrerenderingActivationChecksComplete(
CommitDeferringCondition::NavigationType navigation_type,
std::optional<FrameTreeNodeId> candidate_prerender_frame_tree_node_id);
// Get the `FencedFrameURLMapping` associated with the current page.
FencedFrameURLMapping& GetFencedFrameURLMap();
// True if this is a fenced frame navigation to an urn:uuid.
bool NeedFencedFrameURLMapping();
// FencedFrameURLMapping::MappingResultObserver implementation.
// Called from `FencedFrameURLMapping` when the mapping decision is made, and
// resume the deferred navigation.
void OnFencedFrameURLMappingComplete(
const std::optional<FencedFrameProperties>& properties) override;
// Called from BeginNavigation(), OnPrerenderingActivationChecksComplete(),
// or OnFencedFrameURLMappingComplete().
void BeginNavigationImpl();
// Checks if the response requests an isolated origin via the
// Origin-Agent-Cluster header, and if so opts in the origin to be isolated.
void CheckForIsolationOptIn(const GURL& url);
// Returns whether this navigation request is requesting opt-in
// origin-isolation.
bool IsOriginAgentClusterOptInRequested();
// Returns whether this navigation request is requesting opt-out from
// origin-isolation. Always returns false if
// AreOriginAgentClustersEnabledByDefault() is false.
bool IsOriginAgentClusterOptOutRequested();
// Returns whether this NavigationRequest should use an origin-keyed agent
// cluster, specifically in cases where no Origin-Agent-Cluster header has
// been observed, either because no response has yet been received or because
// it had no such header. (Returns false if the header is observed.)
//
// Note that an origin-keyed process may be used if this returns true, if
// kOriginKeyedProcessesByDefault is enabled.
bool IsIsolationImplied();
// The Origin-Agent-Cluster end result is determined early in the lifecycle of
// a NavigationRequest, but used late. In particular, we want to trigger use
// counters and console warnings once navigation has committed.
void DetermineOriginAgentClusterEndResult();
void ProcessOriginAgentClusterEndResult();
void PopulateDocumentTokenForCrossDocumentNavigation();
// NavigationURLLoaderDelegate implementation.
void OnRequestRedirected(
const net::RedirectInfo& redirect_info,
const net::NetworkAnonymizationKey& network_anonymization_key,
network::mojom::URLResponseHeadPtr response_head) override;
void OnResponseStarted(
network::mojom::URLLoaderClientEndpointsPtr url_loader_client_endpoints,
network::mojom::URLResponseHeadPtr response_head,
mojo::ScopedDataPipeConsumerHandle response_body,
GlobalRequestID request_id,
bool is_download,
net::NetworkAnonymizationKey network_anonymization_key,
SubresourceLoaderParams subresource_loader_params,
EarlyHints early_hints) override;
void OnRequestFailed(
const network::URLLoaderCompletionStatus& status) override;
std::optional<NavigationEarlyHintsManagerParams>
CreateNavigationEarlyHintsManagerParams(
const network::mojom::EarlyHints& early_hints) override;
// Selecting a `RenderFrameHost` to commit a navigation may occasionally fail.
// When this happens, the navigation will bind a closure to continue the
// navigation and assign it to `resume_commit_closure_`. This closure may run
// even when it is still not possible to proceed; see the comment on the
// `resume_commit_closure_` field for the full details.
// Corresponds to navigations committing from `OnResponseStarted()`:
void SelectFrameHostForOnResponseStarted(
network::mojom::URLLoaderClientEndpointsPtr url_loader_client_endpoints,
bool is_download,
SubresourceLoaderParams subresource_loader_params);
void SelectFrameHostForOnRequestFailedInternal(
bool exists_in_cache,
bool skip_throttles,
const std::optional<std::string>& error_page_content);
void SelectFrameHostForCrossDocumentNavigationWithNoUrlLoader();
// To be called whenever a navigation request fails. If |skip_throttles| is
// true, the registered NavigationThrottle(s) won't get a chance to intercept
// NavigationThrottle::WillFailRequest. It should be used when a request
// failed due to a throttle result itself. |error_page_content| is only used
// when |skip_throttles| is true. If |collapse_frame| is true, the associated
// frame tree node is collapsed.
void OnRequestFailedInternal(
const network::URLLoaderCompletionStatus& status,
bool skip_throttles,
const std::optional<std::string>& error_page_content,
bool collapse_frame);
// Called when the NavigationThrottles have been checked by the
// NavigationHandle.
void OnStartChecksComplete(NavigationThrottle::ThrottleCheckResult result);
void OnRedirectChecksComplete(NavigationThrottle::ThrottleCheckResult result);
void OnFailureChecksComplete(NavigationThrottle::ThrottleCheckResult result);
void OnWillProcessResponseChecksComplete(
NavigationThrottle::ThrottleCheckResult result);
void OnWillCommitWithoutUrlLoaderChecksComplete(
NavigationThrottle::ThrottleCheckResult result);
// Runs CommitDeferringConditions.
//
// For prerendered page activation, this is called at the beginning of the
// navigation (i.e., in BeginNavigation()). This is because activating a
// prerendered page must be an atomic, synchronous operation so there is no
// chance for the prerender to be cancelled during the operation. The
// CommitDeferringConditions are asynchronous, so they run at the beginning
// of navigation. Once they finish, the atomic activation sequence runs.
void RunCommitDeferringConditions();
// Similar to the NavigationThrottle checks above but this is called from
// CommitDeferringConditionRunner rather than NavigationThrottles and is
// invoked after all throttle checks and commit checks have completed and the
// navigation can proceed to commit.
void OnCommitDeferringConditionChecksComplete(
CommitDeferringCondition::NavigationType navigation_type,
std::optional<FrameTreeNodeId> candidate_prerender_frame_tree_node_id)
override;
// Called either by OnFailureChecksComplete() or OnRequestFailed() directly.
// |error_page_content| contains the content of the error page (i.e. flattened
// HTML, JS, CSS).
void CommitErrorPage(const std::optional<std::string>& error_page_content);
// Have a RenderFrameHost commit the navigation. The NavigationRequest will
// be destroyed sometime after this call, typically after the renderer has
// informed the browser process that the commit has finished.
void CommitNavigation();
// Commits the navigation to an existing page (back-forward cache navigation
// or prerender activation). NavigationRequest will be destroyed after this
// call.
void CommitPageActivation();
// Checks if the specified CSP context's relevant CSP directive
// allows the navigation. This is called to perform the frame-src check.
bool IsAllowedByCSPDirective(
const std::vector<network::mojom::ContentSecurityPolicyPtr>& policies,
network::CSPContext* context,
network::mojom::CSPDirectiveName directive,
bool has_followed_redirect,
bool url_upgraded_after_redirect,
bool is_opaque_fenced_frame,
network::CSPContext::CheckCSPDisposition disposition);
// Checks if CSP allows the navigation. This will check the frame-src and
// fenced-frame-src directives. Returns net::OK if the checks
// pass, and net::ERR_ABORTED or net::ERR_BLOCKED_BY_CSP depending on which
// checks fail.
net::Error CheckCSPDirectives(
RenderFrameHostCSPContext parent_context,
const PolicyContainerPolicies* parent_policies,
RenderFrameHostCSPContext initiator_context,
const PolicyContainerPolicies* initiator_policies,
bool has_followed_redirect,
bool url_upgraded_after_redirect,
bool is_response_check,
network::CSPContext::CheckCSPDisposition disposition);
// Check whether a request should be allowed to continue or should be blocked
// because it violates a CSP. This method can have two side effects:
// - If a CSP is configured to send reports and the request violates the CSP,
// a report will be sent.
// - The navigation request may be upgraded from HTTP to HTTPS if a CSP is
// configured to upgrade insecure requests.
net::Error CheckContentSecurityPolicy(bool has_followed_redirect,
bool url_upgraded_after_redirect,
bool is_response_check);
// Builds the parameters used to commit a navigation to a page that was
// restored from the back-forward cache.
mojom::DidCommitProvisionalLoadParamsPtr
MakeDidCommitProvisionalLoadParamsForBFCacheRestore();
// Builds the parameters used to commit a navigation to a prerendered page
// that was activated.
mojom::DidCommitProvisionalLoadParamsPtr
MakeDidCommitProvisionalLoadParamsForPrerenderActivation();
// Builds generic activation parameters used to commit a navigation to a page.
mojom::DidCommitProvisionalLoadParamsPtr
MakeDidCommitProvisionalLoadParamsForActivation();
// This enum describes the result of the credentialed subresource check for
// the request.
enum class CredentialedSubresourceCheckResult {
ALLOW_REQUEST,
BLOCK_REQUEST,
};
// Chrome blocks subresource requests whose URLs contain embedded credentials
// (e.g. `https://user:[email protected]/page.html`). Check whether the
// request should be allowed to continue or should be blocked.
CredentialedSubresourceCheckResult CheckCredentialedSubresource() const;
// This enum describes the result of the legacy protocol check for
// the request.
enum class LegacyProtocolInSubresourceCheckResult {
ALLOW_REQUEST,
BLOCK_REQUEST,
};
// Block about:srcdoc navigation that aren't expected to happen. For instance,
// main frame navigations or about:srcdoc#foo.
enum class AboutSrcDocCheckResult {
ALLOW_REQUEST,
BLOCK_REQUEST,
};
AboutSrcDocCheckResult CheckAboutSrcDoc() const;
// When the embedder requires the use of Content Security Policy via Embedded
// Enforcement, framed documents must either:
// 1. Use the 'allow-csp-from' header to opt-into enforcement.
// 2. Enforce its own CSP that subsumes the required CSP.
// Framed documents that fail to do either of these will be blocked.
//
// See:
// - https://w3c.github.io/webappsec-cspee/#required-csp-header
// - https://w3c.github.io/webappsec-cspee/#allow-csp-from-header
//
// SetupCSPEmbeddedEnforcement() retrieve the iframe 'csp' attribute applying.
// CheckCSPEmbeddedEnforcement() inspects the response headers. It decides if
// the 'csp' attribute should be installed into the child. This might also
// block it and display an error page instead.
void SetupCSPEmbeddedEnforcement();
enum class CSPEmbeddedEnforcementResult {
ALLOW_RESPONSE,
BLOCK_RESPONSE,
};
CSPEmbeddedEnforcementResult CheckCSPEmbeddedEnforcement();
// Called before a commit. Updates the history index and length held in
// CommitNavigationParams. This is used to update this shared state with the
// renderer process.
void UpdateHistoryParamsInCommitNavigationParams();
// Helper method to sanitize URLs for redirects before the commit IPC is sent
// to the renderer process. Must be called right before sending the IPC.
void SanitizeRedirectsForCommit(
blink::mojom::CommitNavigationParamsPtr& commit_params);
// The disconnect handler for the NavigationClient Mojo interface; used as a
// signal to potentially cancel navigations, e.g. when the renderer replaces
// an existing NavigationClient connection with a new one or when the renderer
// process crashes.
void OnNavigationClientDisconnected(uint32_t reason,
const std::string& description);
// Binds the given error_handler to be called when an interface disconnection
// happens on the renderer side.
void HandleInterfaceDisconnection(
mojo::AssociatedRemote<mojom::NavigationClient>&);
// When called, this NavigationRequest will no longer interpret the interface
// disconnection on the renderer side as an AbortNavigation.
// TODO(crbug.com/40276805): remove this function when
// NavigationRequest properly handles interface disconnection in all cases.
void IgnoreInterfaceDisconnection();
// Sets ID of the RenderProcessHost we expect the navigation to commit in.
// This is used to inform the RenderProcessHost to expect a navigation to the
// url we're navigating to.
void SetExpectedProcess(RenderProcessHost* expected_process);
// Inform the RenderProcessHost to no longer expect a navigation.
void ResetExpectedProcess();
// If this is a same-site main-frame navigation where we did a proactive
// BrowsingInstance swap but we're reusing the old page's process, we need
// to send the routing ID and the updated lifecycle state of the old page so
// that we can run pagehide and visibilitychange handlers of the old page
// when we commit the new page.
void AddOldPageInfoToCommitParamsIfNeeded();
// Record download related UseCounters when navigation is a download before
// filtered by download_policy.
void RecordDownloadUseCountersPrePolicyCheck();
// Record download related UseCounters when navigation is a download after
// filtered by download_policy.
void RecordDownloadUseCountersPostPolicyCheck();
void OnWillStartRequestProcessed(
NavigationThrottle::ThrottleCheckResult result);
void OnWillRedirectRequestProcessed(
NavigationThrottle::ThrottleCheckResult result);
void OnWillFailRequestProcessed(
NavigationThrottle::ThrottleCheckResult result);
void OnWillProcessResponseProcessed(
NavigationThrottle::ThrottleCheckResult result);
void OnWillCommitWithoutUrlLoaderProcessed(
NavigationThrottle::ThrottleCheckResult result);
void CancelDeferredNavigationInternal(
NavigationThrottle::ThrottleCheckResult result);
// TODO(zetamoo): Remove the Will* methods and fold them into their callers.
// Called when the URLRequest will start in the network stack.
void WillStartRequest();
// Called when the URLRequest will be redirected in the network stack.
// This will also inform the delegate that the request was redirected.
//
// |post_redirect_process| is the renderer process we expect to use to commit
// the navigation now that it has been redirected. It can be null if there is
// no live process that can be used. In that case, a suitable renderer process
// will be created at commit time.
//
void WillRedirectRequest(const GURL& new_referrer_url,
RenderProcessHost* post_redirect_process);
// Called when the URLRequest will fail.
void WillFailRequest();
// Called when the URLRequest has delivered response headers and metadata.
// |callback| will be called when all throttle checks have completed,
// allowing the caller to cancel the navigation or let it proceed.
// NavigationHandle will not call |callback| with a result of DEFER.
// If the result is PROCEED, then 'ReadyToCommitNavigation' will be called
// just before calling |callback|.
void WillProcessResponse();
// Called when no URLRequest will be needed to perform this navigation, just
// before commit.
void WillCommitWithoutUrlLoader();
// Checks for attempts to navigate to a page that is already referenced more
// than once in the frame's ancestors. This is a helper function used by
// WillStartRequest and WillRedirectRequest to prevent the navigation.
bool IsSelfReferentialURL();
// RenderProcessHostObserver implementation.
void RenderProcessExited(RenderProcessHost* host,
const ChildProcessTerminationInfo& info) override;
void RenderProcessHostDestroyed(RenderProcessHost* host) override;
// Updates navigation handle timings.
void UpdateNavigationHandleTimingsOnResponseReceived(bool is_redirect,
bool is_first_response);
void UpdateNavigationHandleTimingsOnCommitSent();
// Helper function that computes the SiteInfo for |common_params_.url|.
// Note: |site_info_| should only be updated with the result of this function.
SiteInfo GetSiteInfoForCommonParamsURL();
// Updates the state of the navigation handle after encountering a server
// redirect.
void UpdateStateFollowingRedirect(const GURL& new_referrer_url);
// Updates |private_network_request_policy_| for ReadyToCommitNavigation().
//
// Must not be called for same-document navigation requests nor for requests
// served from the back-forward cache or from prerendered pages.
void UpdatePrivateNetworkRequestPolicy();
// Called when the navigation is ready to be committed. This will update the
// |state_| and inform the delegate.
void ReadyToCommitNavigation(bool is_error);
// Called if READY_TO_COMMIT -> COMMIT state transition takes an unusually
// long time.
void OnCommitTimeout();
// Called by the RenderProcessHost to handle the case when the process changed
// its state of being blocked.
void RenderProcessBlockedStateChanged(bool blocked);
void StopCommitTimeout();
void RestartCommitTimeout();
std::vector<std::string> TakeRemovedRequestHeaders() {
return std::move(removed_request_headers_);
}
net::HttpRequestHeaders TakeModifiedRequestHeaders() {
return std::move(modified_request_headers_);
}
// Returns true if the contents of |common_params_| requires
// |source_site_instance_| to be set. This is used to ensure that data: and
// about:blank URLs with valid initiator origins always have
// |source_site_instance_| set so that site isolation enforcements work
// properly.
bool RequiresInitiatorBasedSourceSiteInstance() const;
// Sets |source_site_instance_| to a SiteInstance that is derived from
// |common_params_->initiator_origin| and related to the |frame_tree_node_|'s
// current SiteInstance. |source_site_instance_| is only set if it doesn't
// already have a value and RequiresInitiatorBasedSourceSiteInstance() returns
// true.
void SetSourceSiteInstanceToInitiatorIfNeeded();
void ForceEnableOriginTrials(const std::vector<std::string>& trials) override;
void CreateCoepReporter(StoragePartition* storage_partition);
void CreateDipReporter(StoragePartition* storage_partition);
// [spec]: https://html.spec.whatwg.org/C/#obtain-an-embedder-policy
//
// Returns the CrossOriginEmbedderPolicy for the document, which is inherited
// or retrieved from response headers.
network::CrossOriginEmbedderPolicy ComputeCrossOriginEmbedderPolicy();
struct IntegrityPolicies {
network::IntegrityPolicy enforced;
network::IntegrityPolicy report_only;
};
// Calculates the integrity policies for a document, based on the
// `Integrity-Policy` and `Integrity-Policy-Report-Only` headers.
IntegrityPolicies ComputeIntegrityPolicies();
// [spec]:
// https://html.spec.whatwg.org/C/#check-a-navigation-response's-adherence-to-its-embedder-policy
//
// Return whether the response's COEP is compatible with its parent's COEP. It
// also sends COEP reports if needed.
bool CheckResponseAdherenceToCoep(const GURL& url);
std::optional<network::mojom::BlockedByResponseReason> EnforceCOEP();
// Check the COOP value of the page is compatible with the COEP value of each
// of its documents. COOP:kSameOriginPlusCoep is incompatible with COEP:kNone.
// If they aren't, this emits a crash report.
void CoopCoepSanityCheck();
// Checks that, given an origin to be committed, all of the permissions
// policies that a fenced frame requires to be enabled are enabled. If not, it
// logs a console message and returns false.
bool CheckPermissionsPoliciesForFencedFrames(const url::Origin&);
// Helper function that determines if a given required permissions policy
// feature is properly enabled for a given origin to be committed.
bool IsFencedFrameRequiredPolicyFeatureAllowed(
const url::Origin&,
const network::mojom::PermissionsPolicyFeature feature);
// Returns the user-agent override, or an empty string if one isn't set.
std::string GetUserAgentOverride();
mojo::PendingRemote<network::mojom::CookieAccessObserver>
CreateCookieAccessObserver();
mojo::PendingRemote<network::mojom::TrustTokenAccessObserver>
CreateTrustTokenAccessObserver();
// network::mojom::TrustTokenAccessObserver:
void OnTrustTokensAccessed(
network::mojom::TrustTokenAccessDetailsPtr details) override;
void Clone(mojo::PendingReceiver<network::mojom::TrustTokenAccessObserver>
observer) override;
mojo::PendingRemote<network::mojom::SharedDictionaryAccessObserver>
CreateSharedDictionaryAccessObserver();
// network::mojom::SharedDictionaryAccessObserver:
void OnSharedDictionaryAccessed(
network::mojom::SharedDictionaryAccessDetailsPtr details) override;
void Clone(
mojo::PendingReceiver<network::mojom::SharedDictionaryAccessObserver>
observer) override;
mojo::PendingRemote<network::mojom::DeviceBoundSessionAccessObserver>
CreateDeviceBoundSessionObserver();
// network::mojom::DeviceBoundSessionAccessObserver:
void OnDeviceBoundSessionAccessed(
const net::device_bound_sessions::SessionAccess& access) override;
void Clone(
mojo::PendingReceiver<network::mojom::DeviceBoundSessionAccessObserver>
observer) override;
// Convenience function to return the NavigationControllerImpl this
// NavigationRequest is in.
NavigationControllerImpl* GetNavigationController() const;
// Convenience function to return the PrerenderHostRegistry this
// NavigationRequest can be associated with.
PrerenderHostRegistry& GetPrerenderHostRegistry();
// Returns the RenderFrameHost of the initiator document, iff there is such
// a document and its RenderFrameHost has not committed a different document
// since this navigation started. Otherwise returns nullptr.
RenderFrameHostImpl* GetInitiatorDocumentRenderFrameHost();
// Records the appropriate kAddressSpace* WebFeature for the response we just
// received on the initiator document, if possible.
void RecordAddressSpaceFeature();
// Computes the PolicyContainerPolicies and the sandbox flags to use for
// committing a regular document.
// Called when the response to commit is known.
void ComputePoliciesToCommit();
// Computes the PolicyContainerPolicies and the sandbox flags to use for
// committing an error document.
//
// Note:
// |ComputePoliciesToCommit()| can be followed by
// |ComputePoliciesToCommitForErrorPage()|. This happens when the decision to
// commit an error document happens after receiving the regular document's
// response.
void ComputePoliciesToCommitForError();
// DCHECK that tranistioning from the current state to |state| valid. This
// does nothing in non-debug builds.
void CheckStateTransition(NavigationState state) const;
// Set |state_| to |state| and also DCHECK that this state transition is
// valid.
void SetState(NavigationState state);
// When a navigation fails, one of two things can happen:
// 1) An error page commits and replaces the old document.
// 2) The navigation is canceled, and the previous document is kept.
//
// If appropriate, this applies (2), deletes |this|, and returns true.
// In that case, the caller must immediately return.
bool MaybeCancelFailedNavigation();
// Called just after a navigation commits (also in case of error): it
// sends all console messages to the final RenderFrameHost.
void SendDeferredConsoleMessages();
bool ShouldRenderFallbackContentForResponse(
const net::HttpResponseHeaders& response_head) const;
// Whether this is a same-URL navigation that should replace the current entry
// or not. Called when the navigation just started.
bool ShouldReplaceCurrentEntryForSameUrlNavigation() const;
// Whether this navigation happens on the initial empty document or initial
// NavigationEntry, and thus should replace the current entry. Called when the
// navigation just started.
bool ShouldReplaceCurrentEntryForNavigationFromInitialEmptyDocumentOrEntry()
const;
// Whether a failed navigation should replace the current entry or not. Called
// when an error page is about to be committed.
bool ShouldReplaceCurrentEntryForFailedNavigation() const;
// Calculates the origin that this NavigationRequest may commit. See also the
// comment of GetOriginToCommit(). Performs calculation without information
// from RenderFrameHostImpl (e.g. CSPs are ignored). Should be used only in
// situations where the final frame host hasn't been determined but the origin
// is needed to create URLLoaderFactory.
url::Origin GetOriginForURLLoaderFactoryBeforeResponse(
network::mojom::WebSandboxFlags sandbox_flags);
// Superset of GetOriginForURLLoaderFactoryBeforeResponse(). Calculates
// the origin with information from the final frame host. Can be called only
// after the final response is received or ready.
std::optional<url::Origin> GetOriginForURLLoaderFactoryAfterResponse();
// Computes the CrossOriginIsolationKey to use for committing the navigation.
// A nullopt result means that either the cross-origin isolation status of the
// request cannot be determined because we do not have final headers for the
// navigation yet, or that the navigation is not cross-origin isolated.
std::optional<AgentClusterKey::CrossOriginIsolationKey>
ComputeCrossOriginIsolationKey();
// Computes the web-exposed isolation information based on `coop_status_` and
// current `frame_tree_node_` info.
// If the return result is nullopt, it means that the WebExposedIsolationInfo
// is not relevant or unknown. This can happen for example when we do not have
// a network response yet, or when going to an "about:blank" page.
std::optional<WebExposedIsolationInfo> ComputeWebExposedIsolationInfo();
// Assign an invalid frame tree node id to `prerender_frame_tree_node_id_`.
// Called as soon as when we are certain that this navigation won't activate a
// prerendered page. This is needed because `IsPrerenderedPageActivation()`,
// which may be called at any point after BeginNavigation(), will assume that
// 'prerender_frame_tree_node_id_' has an value assigned.
void MaybeAssignInvalidPrerenderFrameTreeNodeId();
// The NavigationDownloadPolicy is currently fully computed by the renderer
// process. It is left empty for browser side initiated navigation. This is a
// problem. This function is an incomplete attempt to start computing it from
// the browser process instead.
// TODO(crbug.com/40249217): Complete the implementation the browser
// side implementation.
void ComputeDownloadPolicy();
blink::NavigationDownloadPolicy& download_policy() {
return common_params_->download_policy;
}
// Called on FrameTreeNode's queued NavigationRequest (if any) when another
// NavigationRequest associated with the same FrameTreeNode is destroyed and
// the queued NavigationRequest can be resumed. Will post a task to run the
// `resume_commit_closure_` asynchronously.
void PostResumeCommitTask();
// See https://crbug.com/1412365
void CheckSoftNavigationHeuristicsInvariants();
// Used to resume any SubframeHistoryNavigationThrottles in this FrameTree
// when this NavigationRequest commits.
// `subframe_history_navigation_throttles_` will only be populated if this
// IsInMainFrame().
void UnblockPendingSubframeNavigationRequestsIfNeeded();
// If this request is a same-origin cross-document traversal (i.e., session
// history navigation), this will send a message to the renderer to have it
// fire the navigate event. Normally, the renderer fires the navigate event at
// navigation start for cross-document navigations, before sending the
// BeginNavigation to the browser. That doesn't work for traversals, because
// the renderer don't know which frame(s) will navigate. This is called after
// beforeunload events fire and after any navigation start throttles have
// resumed, so we know the navigation is proceeding. The navigate event can't
// cancel a cross-document traversal, so it can be sent in parallel, instead
// of blocking and waiting for the result.
void MaybeDispatchNavigateEventForCrossDocumentTraversal();
// Returns if we should add/reset the `CookieChangeListener` for the current
// navigation.
bool ShouldAddCookieChangeListener();
// Returns if we should add/reset the `DeviceBoundSessionObserver` for
// the current navigation.
bool ShouldAddDeviceBoundSessionObserver();
// Returns the `StoragePartition` based on the config from the `site_info_`.
StoragePartition* GetStoragePartitionWithCurrentSiteInfo();
// Passes the response body contents to the original caller using the stored
// callback once the body has been successfully read from its corresponding
// data pipe.
void OnResponseBodyReady(MojoResult result);
// Helper to record early RenderFrameHost swap metrics at the end of a
// navigation.
void RecordEarlyRenderFrameHostSwapMetrics();
// Helpers for GetTentativeOriginAtRequestTime and GetOriginToCommit.
url::Origin GetOriginForURLLoaderFactoryUnchecked();
void MaybeRecordTraceEventsAndHistograms();
// Records how much the navigation start time was adjusted for beforeunload
// handlers, for various scenarios (legacy, beforeunload handlers only, and
// beforeunload dialogs). See https://crbug.com/385170155.
void MaybeRecordNavigationStartAdjustments();
void ResetViewTransitionState();
// This check is to prevent a race condition where a parent fenced frame
// initiates a nested fenced frame navigation right before the entire frame
// tree has network access disabled. If such navigation is allowed to commit,
// the navigated fenced frame will have network access. This allows parent
// fenced frame to communicate cross-site data into child fenced frame, which
// is bad. So we need to disable navigations when both the embedder and nested
// frames have already disabled network.
bool IsDisabledEmbedderInitiatedFencedFrameNavigation();
// Sets the expected process to the process of the current associated RFH.
void SetExpectedProcessIfAssociated();
// Sets the Document-Isolation-Policy header to a default value in unsecure
// contexts or if DocumentIsolationPolicy is not supported.
void SanitizeDocumentIsolationPolicyHeader();
// Sets up service worker client info to inherit controller from the parent
// frame if it is a same origin srcdoc iframe.
// This method creates a ServiceWorkerClient associated with the navigating
// frame. It should not be called when NavigationURLLoader is used as that
// would also create ServiceWorkerClient and cause conflict.
void InheritServiceWorkerControllerFromParentIfNeeded();
// If this navigation has a FrameNavigationEntry with a committed origin,
// ensure that it matches the origin_to_commit when origin-sensitive state
// (such as page_state) is being sent to the renderer.
//
// This invariant guards against scenarios where session history has been
// unintentionally or maliciously corrupted, causing a document to commit
// in a renderer under the wrong origin. This would violate site isolation
// guarantees and could lead to security vulnerabilities.
//
// See https://crbug.com/41487933 for more background on the types of bugs
// this protects against.
void ValidateCommitOrigin(const url::Origin& origin_to_commit);
// Never null. The pointee node owns this navigation request instance.
// This field is not a raw_ptr because of incompatibilities with tracing
// (TRACE_EVENT*), perfetto::TracedDictionary::Add and gmock/EXPECT_THAT.
RAW_PTR_EXCLUSION FrameTreeNode* const frame_tree_node_;
// Returns true if navigation timeline UKMs should be recorded.
// This is also used in `MaybeRecordTraceEventsAndHistograms()`, which should
// eventually be replaced with the navigation timeline metrics.
bool ShouldRecordNavigationTimelineUkm() const;
// Used for short-lived NavigationRequest created at DidCommit time for the
// purpose of committing navigation that were not driven by the browser
// process. This is used in only two cases:
// - same-document navigation initiated by the renderer process.
// - the synchronous about:blank navigation.
const bool is_synchronous_renderer_commit_;
// The RenderFrameHost that this navigation intends to commit in. The value
// will be set when we know the final RenderFrameHost that the navigation will
// commit in (i.e. when we receive the final network response for most
// navigations). Note that currently this can be reset to std::nullopt for
// cross-document restarts and some failed navigations.
// TODO(crbug.com/40063115): Don't reset this on failed navigations,
// and ensure the NavigationRequest doesn't outlive the `render_frame_host_`
// picked for failed Back/Forward Cache restores.
// Invariant: At least one of |loader_| or |render_frame_host_| is
// null/std::nullopt.
std::optional<
base::SafeRef<RenderFrameHostImpl, base::SafeRefDanglingUntriaged>>
render_frame_host_;
// Initialized on creation of the NavigationRequest. Sent to the renderer when
// the navigation is ready to commit.
// Note: When the navigation is ready to commit, the url in |common_params|
// will be set to the final navigation url, obtained after following all
// redirects.
//
// Note: |common_params_| and |begin_params_| are not const as they can be
// modified during redirects.
//
// Note: |commit_params_| is not const because was_discarded will
// be set in CreatedNavigationRequest.
//
// Note: |commit_params_->is_browser_initiated| and |common_params_| may be
// mutated by ContentBrowserClient::OverrideNavigationParams at construction
// time (i.e. before we actually kick off the navigation).
blink::mojom::CommonNavigationParamsPtr common_params_;
blink::mojom::BeginNavigationParamsPtr begin_params_;
blink::mojom::CommitNavigationParamsPtr commit_params_;
bool same_origin_ = false;
// Stores the NavigationUIData for this navigation until the NavigationHandle
// is created. This can be null if the embedded did not provide a
// NavigationUIData at the beginning of the navigation.
std::unique_ptr<NavigationUIData> navigation_ui_data_;
// URLLoaderFactory to facilitate loading blob URLs.
const scoped_refptr<network::SharedURLLoaderFactory> blob_url_loader_factory_;
// A bundle of URLLoaderFactory to facilitate loading subresources.
// It is shared between prefetch, topics, keep-alive, and fetchLater.
scoped_refptr<network::SharedURLLoaderFactory>
subresource_proxying_factory_bundle_ = nullptr;
NavigationState state_ = NOT_STARTED;
bool is_navigation_started_ = false;
// Manages the lifetime of a pre-created ServiceWorkerContainerHost until a
// corresponding container is created in the renderer. This must be destroyed
// after `loader_` to avoid dangling pointers, since `loader_` can have a
// raw_ptr to this object.
std::unique_ptr<ServiceWorkerMainResourceHandle> service_worker_handle_;
std::unique_ptr<NavigationURLLoader> loader_;
bool navigation_visible_to_embedder_ = false;
#if BUILDFLAG(IS_ANDROID)
// For each C++ NavigationHandle, there is a Java counterpart. It is the JNI
// bridge in between the two.
std::unique_ptr<NavigationHandleProxy> navigation_handle_proxy_;
#endif
// These next items are used in browser-initiated navigations to store
// information from the NavigationEntryImpl that is required after request
// creation time.
scoped_refptr<SiteInstanceImpl> source_site_instance_;
scoped_refptr<SiteInstanceImpl> dest_site_instance_;
const RestoreType restore_type_;
const ReloadType reload_type_;
const int nav_entry_id_;
std::optional<BindingsPolicySet> bindings_;
scoped_refptr<SiteInstanceImpl> starting_site_instance_;
// Whether the navigation should be sent to a renderer a process. This is
// true, except for 204/205 responses and downloads.
bool response_should_be_rendered_ = true;
// Whether devtools overrides were applied on the User-Agent request header.
bool devtools_user_agent_override_ = false;
// Whether devtools overrides were applied on the Accept-Language request
// header.
bool devtools_accept_language_override_ = false;
// The type of RenderFrameHost associated with this navigation.
AssociatedRenderFrameHostType associated_rfh_type_ =
AssociatedRenderFrameHostType::NONE;
// Stores the SiteInstance created on redirects to check if there is an
// existing RenderProcessHost that can commit the navigation so that the
// renderer process is not deleted while the navigation is ongoing. If the
// SiteInstance was a brand new SiteInstance, it is not stored.
scoped_refptr<SiteInstance> speculative_site_instance_;
// Whether the NavigationRequest was created after receiving a BeginNavigation
// IPC. When true, main frame navigations should not commit in a different
// process (unless asked by the content/ embedder). When true, the renderer
// process expects to be notified if the navigation is aborted.
const bool from_begin_navigation_;
// Holds objects received from OnResponseStarted while the WillProcessResponse
// checks are performed by the NavigationHandle. Once the checks have been
// completed, these objects will be used to continue the navigation.
network::mojom::URLResponseHeadPtr response_head_;
mojo::ScopedDataPipeConsumerHandle response_body_;
network::mojom::URLLoaderClientEndpointsPtr url_loader_client_endpoints_;
std::optional<net::SSLInfo> ssl_info_;
std::optional<net::AuthChallengeInfo> auth_challenge_info_;
bool is_download_ = false;
GlobalRequestID request_id_;
std::unique_ptr<NavigationEarlyHintsManager> early_hints_manager_;
// Holds information for the navigation while the WillFailRequest
// checks are performed by the NavigationHandle.
bool has_stale_copy_in_cache_ = false;
net::Error net_error_ = net::OK;
int extended_error_code_ = 0;
// Detailed host resolution error information. The error code in
// |resolve_error_info_.error| should be consistent with (but not necessarily
// the same as) |net_error_|. In the case of a host resolution error, for
// example, |net_error_| should be ERR_NAME_NOT_RESOLVED while
// |resolve_error_info_.error| may give a more detailed error such as
// ERR_DNS_TIMED_OUT.
net::ResolveErrorInfo resolve_error_info_;
// Identifies in which RenderProcessHost this navigation is expected to
// commit.
ChildProcessId expected_render_process_host_id_;
// The SiteInfo of this navigation, as obtained from
// SiteInstanceImpl::ComputeSiteInfo().
SiteInfo site_info_;
base::OnceClosure on_start_checks_complete_closure_;
// Used in the network service world to pass the subressource loader params
// to the renderer. Used by ServiceWorker and
// SignedExchangeSubresourcePrefetch.
SubresourceLoaderParams subresource_loader_params_;
// DocumentToken to use for the newly-committed document in a cross-document
// navigation. Currently set immediately before sending CommitNavigation to
// the renderer. In the future, this may be populated earlier to allow lookup
// of a navigation request by the document that it may create, similar to how
// `NavigationOrDocumentHandle` behaves.
std::optional<blink::DocumentToken> document_token_;
// See comment on accessor.
const base::UnguessableToken devtools_navigation_token_ =
base::UnguessableToken::Create();
std::optional<std::vector<blink::mojom::TransferrableURLLoaderPtr>>
subresource_overrides_;
// The NavigationClient interface for that requested this navigation in the
// case of a renderer initiated navigation. It is expected to be bound until
// this navigation commits or is canceled.
mojo::AssociatedRemote<mojom::NavigationClient> request_navigation_client_;
// The NavigationClient interface used to commit the navigation. For now, this
// is only used for same-site renderer-initiated navigation.
// TODO(crbug.com/40276805): Extend to all types of navigation.
mojo::AssociatedRemote<mojom::NavigationClient> commit_navigation_client_;
// If set, any redirects to HTTP for this navigation will be upgraded to
// HTTPS. This is used only on subframe navigations, when
// upgrade-insecure-requests is set as a CSP policy.
bool upgrade_if_insecure_ = false;
// The offset of the new document in the history.
const int navigation_entry_offset_ = 0;
// Owns the NavigationThrottleRegistry associated with this navigation.
std::unique_ptr<NavigationThrottleRegistryImpl> throttle_registry_;
// Once the navigation has passed all throttle checks the navigation will
// commit. However, we may need to defer the commit until certain conditions
// are met. CommitDeferringConditionRunner is responsible for deferring a
// commit if needed and resuming it, by calling
// OnCommitDeferringConditionChecksComplete, once all checks passed.
//
// For prerendered page activation, it doesn't run the NavigationThrottles and
// run the CommitDeferringConditionRunner at the beginning of
// BeginNavigation(). See the comment on RunCommitDeferringConditions() for
// details.
std::unique_ptr<CommitDeferringConditionRunner> commit_deferrer_;
// Indicates whether the navigation changed which NavigationEntry is current.
bool subframe_entry_committed_ = false;
// True if the committed entry has replaced the existing one.
// A non-user initiated redirect causes such replacement.
bool did_replace_entry_ = false;
// Set to false if we want to update the session history but not update the
// browser history. E.g., on unreachable urls or navigations in non-primary
// frame trees.
bool should_update_history_ = false;
// The previous main frame URL that the user was on. This may be empty if
// there was no last committed entry.
GURL previous_main_frame_url_;
// The type of navigation that just occurred. Note that not all types of
// navigations in the enum are valid here, since some of them don't actually
// cause a "commit" and won't generate this notification.
NavigationType navigation_type_ = NAVIGATION_TYPE_UNKNOWN;
// The chain of redirects, including client-side redirect and the current URL.
// TODO(zetamoo): Try to improve redirect tracking during navigation.
std::vector<GURL> redirect_chain_;
// TODO(zetamoo): Try to remove this by always sanitizing the referrer in
// common_params_.
blink::mojom::ReferrerPtr sanitized_referrer_;
bool was_redirected_ = false;
// Whether this navigation was triggered by a x-origin redirect following a
// prior (most likely <a download>) download attempt.
bool from_download_cross_origin_redirect_ = false;
// Used to hold prefetched signed exchanges. This is shared with the
// navigation initiator's RenderFrameHostImpl. This also means that only the
// navigations that were directly initiated by the frame that made the
// prefetches could use the prefetched resources, which is a different
// behavior from regular prefetches (where all prefetched resources are
// stored and shared in http cache).
scoped_refptr<PrefetchedSignedExchangeCache>
prefetched_signed_exchange_cache_;
// Timing information of loading for the navigation. Used for recording UMAs.
NavigationHandleTiming navigation_handle_timing_;
// The original value of navigation start for a given navigation, before any
// adjustment is made to avoid counting beforeunload dialogs. This is null
// (i.e., `TimeTicks()`) unless an adjustment was made.
base::TimeTicks original_navigation_start_;
// Tracks whether an adjustment to the navigation start time was done for
// legacy PostTask reasons rather than for running a beforeunload handler.
bool navigation_start_adjustment_for_legacy_ = false;
// Tracks whether a beforeunload dialog was shown as part of this navigation.
bool beforeunload_dialog_shown_ = false;
// The time this NavigationRequest was created.
base::TimeTicks creation_time_ = base::TimeTicks().Now();
// The time that the browser process started running beforeunload phase 2,
// which is used to run any beforeunload handlers that were not run already in
// an initiating renderer process during beforeunload phase 1 (and may include
// handlers in a remote target frame or OOPIFs within the target frame). This
// value is null if the navigation did not need to run beforeunload phase 2.
// Note that legacy PostTask cases are not considered beforeunload phase 2,
// because they do not run actual beforeunload handlers.
base::TimeTicks beforeunload_phase2_start_time_;
// The time that beforeunload phase 2 ended, if it ran.
base::TimeTicks beforeunload_phase2_end_time_;
// The time BeginNavigation() was called.
base::TimeTicks begin_navigation_time_;
// The time OnResponseStarted() was called.
base::TimeTicks receive_response_time_;
// The time this navigation was ready to commit.
base::TimeTicks ready_to_commit_time_;
// The first `fetchStart` time. This is different from the
// `first_request_start_time` in `NavigationHandleTiming` since the
// `first_fetch_start_time_` is the first time when the browser is
// ready to fetch using an HTTP request, whereas the `requestStart` is
// when the browser has obtained a connection and is ready to send the
// HTTP request.
base::TimeTicks first_fetch_start_time_;
// The time when the final (which might also be the first) headers are
// received.
base::TimeTicks final_receive_headers_end_time_;
// The time WillStartRequest() was called.
base::TimeTicks will_start_request_time_;
// For bfcache and prerender page activations, this is the time that the
// activation commits (after ReadyToCommitNavigation), since no commit IPC is
// sent to the renderer process.
base::TimeTicks page_activation_commit_time_;
// Set in ReadyToCommitNavigation.
bool is_same_process_ = true;
// If set to a value other than NONE, starting the navigation will immediately
// result in an error page with |net_error_| as the network error and
// |error_page_html_| as the content. This value of this field indicates what
// scenario prompted the error navigation.
BrowserInitiatedErrorNavigationType browser_initiated_error_navigation_type_ =
BrowserInitiatedErrorNavigationType::kNone;
// If browser_initiated_error_navigation_type_ is set, this HTML will be
// shown as the content of the resulting error page.
std::string error_page_html_;
// This test-only callback will be run when BeginNavigation() is called.
base::OnceClosure begin_navigation_callback_for_testing_;
// This test-only callback will be run when all throttle checks have been
// performed. If the callback returns true, On*ChecksComplete functions are
// skipped, and only the test callback is being performed.
// TODO(clamy): Revisit the unit test architecture.
ThrottleChecksFinishedCallback complete_callback_for_testing_;
// Test-only callback. Called when we're ready to call CommitNavigation.
// Unlike above, this is informational only; it does not affect the request.
base::OnceClosure ready_to_commit_callback_for_testing_;
// Unique id that identifies the navigation for which this NavigationRequest
// is created.
const int64_t navigation_id_ = ++unique_id_counter_;
// static member for generating the unique id above.
static int64_t unique_id_counter_;
// Timer for detecting an unexpectedly long time to commit a navigation.
base::OneShotTimer commit_timeout_timer_;
base::CallbackListSubscription
render_process_blocked_state_changed_subscription_;
// The headers used for the request. The value of this comes from
// |begin_params_->headers|. If not set, it needs to be calculated.
std::optional<net::HttpRequestHeaders> request_headers_;
// Used to update the request's headers. When modified during the navigation
// start, the headers will be applied to the initial network request. When
// modified during a redirect, the headers will be applied to the redirected
// request.
net::HttpRequestHeaders modified_request_headers_;
net::HttpRequestHeaders cors_exempt_request_headers_;
// Set of headers to remove during the redirect phase. This can only be
// modified during the redirect phase.
std::vector<std::string> removed_request_headers_;
// The RenderFrameHost that is being restored from the back/forward cache.
// This can be null if this navigation is not restoring a page from the
// back/forward cache.
std::optional<base::SafeRef<RenderFrameHostImpl>>
rfh_restored_from_back_forward_cache_;
// Whether the navigation is for restoring a page from the back/forward cache
// or not.
const bool is_back_forward_cache_restore_;
// These are set to the values from the FrameNavigationEntry this
// NavigationRequest is associated with (if any).
int64_t frame_entry_item_sequence_number_ = -1;
int64_t frame_entry_document_sequence_number_ = -1;
// If non-empty, it represents the IsolationInfo explicitly asked to be used
// for this NavigationRequest.
std::optional<net::IsolationInfo> isolation_info_;
// This is used to store the `RenderFrameHostManager::current_frame_host()` id
// when the navigation commits and about to potentially change the current
// RenderFrameHost. The ID (if set) refers to the RFH of the document that was
// replaced when this navigation committed, while the ID saved in
// `current_render_frame_host_id_at_construction_` below refers to the RFH of
// the document that was there when this navigation was started. The two might
// be different, since other navigations could commit and change the current
// RFH before this navigation commits, which can happen with navigation
// queueing or early RFH swap.
GlobalRenderFrameHostId previous_render_frame_host_id_;
// This is used to store the `RenderFrameHostManager::current_frame_host()` id
// at request creation time. See also the comment for
// `previous_render_frame_host_id_` above on how these two IDs may differ.
const GlobalRenderFrameHostId current_render_frame_host_id_at_construction_;
// Frame token of the frame host that initiated the navigation, derived from
// |begin_params().initiator_frame_token|. This is best effort: it is only
// defined for some renderer-initiated navigations (e.g., not drag and drop).
// The frame with the corresponding frame token may have been deleted before
// the navigation begins. This parameter is defined if and only if
// |initiator_process_id_| below is.
const std::optional<blink::LocalFrameToken> initiator_frame_token_;
// ID of the renderer process of the frame host that initiated the navigation.
// This is defined if and only if |initiator_frame_token_| above is, and it is
// only valid in conjunction with it.
const int initiator_process_id_ = ChildProcessHost::kInvalidUniqueID;
// The initiator Document's token, if it is present when this
// NavigationRequest was created.
std::optional<blink::DocumentToken> initiator_document_token_;
// The sandbox flags of the navigation's initiator, if any.
// WebSandboxFlags::kNone otherwise.
const network::mojom::WebSandboxFlags sandbox_flags_initiator_;
// Whether a navigation in a new window had the opener suppressed. False if
// the navigation is not in a new window. Can only be true for renderer
// initiated navigations which use `CreateBrowserInitiated()`.
const bool was_opener_suppressed_ = false;
// This tracks a connection between the current pending entry and this
// request, such that the pending entry can be discarded if no requests are
// left referencing it.
std::unique_ptr<NavigationControllerImpl::PendingEntryRef> pending_entry_ref_;
// Used only by DCHECK.
// True if the NavigationThrottles are running an event, the request then can
// be cancelled for deferring.
bool processing_navigation_throttle_ = false;
// Holds the required CSP for this navigation. This will be moved into
// the RenderFrameHost at DidCommitNavigation time.
network::mojom::ContentSecurityPolicyPtr required_csp_;
// Whether the document loaded by this navigation will be committed inside an
// iframe credentialless. Documents loaded inside credentialless iframes get
// partitioned storage and use a transient NetworkAnonymizationKey.
const bool is_credentialless_;
// Non-nullopt from construction until |TakePolicyContainerHost()| is called.
std::optional<NavigationPolicyContainerBuilder> policy_container_builder_;
std::unique_ptr<CrossOriginEmbedderPolicyReporter> coep_reporter_;
std::unique_ptr<DocumentIsolationPolicyReporter> dip_reporter_;
std::unique_ptr<viz::PeakGpuMemoryTracker> loading_mem_tracker_;
// Structure tracking the effects of the CrossOriginOpenerPolicy on this
// navigation.
CrossOriginOpenerPolicyStatus coop_status_{this};
#if DCHECK_IS_ON()
bool is_safe_to_delete_ = true;
#endif
// UKM source associated with the page we are navigated away from.
const ukm::SourceId previous_page_ukm_source_id_;
// If true, changes to the user-agent override require a reload. If false, a
// reload is not necessary.
bool ua_change_requires_reload_ = true;
// Controls whether or not an error page is displayed on error. If set to
// true, an error will be treated as if the user simply cancelled the
// navigation.
bool silently_ignore_errors_ = false;
// Similar but only suppresses the error page when the error code is
// net::ERR_BLOCKED_BY_CLIENT.
bool silently_ignore_blocked_by_client_ = false;
// Whether the navigation loads an MHTML document or a subframe of an MHTML
// document. The navigation might or might not be fullfilled from the MHTML
// archive (see `is_mhtml_subframe_loaded_from_achive` in the NeedsUrlLoader
// method).
bool is_mhtml_or_subframe_ = false;
// True when at least one preload Link header was received via an Early Hints
// response. This is set only for a main frame navigation.
bool was_resource_hints_received_ = false;
// Set to true when this navigation has created parameters for
// NavigationEarlyHintsManager. Used to check whether cross origin redirects
// happened after Early Hints responses are received.
bool did_create_early_hints_manager_params_ = false;
// Set to true when an Early Hints response was received before cross origin
// redirects during navigation.
bool did_receive_early_hints_before_cross_origin_redirect_ = false;
// Observers listening to cookie access notifications for the network requests
// made by this navigation. unique_ptr so it can be replaced in tests.
std::unique_ptr<CookieAccessObservers> cookie_observers_;
// Observers listening to Trust Token access notifications for the network
// requests made by this navigation.
mojo::ReceiverSet<network::mojom::TrustTokenAccessObserver>
trust_token_observers_;
// Observers listening to shared dictionary access notifications for the
// network requests made by this navigation.
mojo::ReceiverSet<network::mojom::SharedDictionaryAccessObserver>
shared_dictionary_observers_;
mojo::ReceiverSet<network::mojom::DeviceBoundSessionAccessObserver>
device_bound_session_observers_;
OriginAgentClusterEndResult origin_agent_cluster_end_result_ =
OriginAgentClusterEndResult::kNotRequestedAndNotOriginKeyed;
net::IsolationInfo isolation_info_for_subresources_;
// Set while CommitDeferringConditions are running for prerendered page
// activation. This is needed as PrerenderHost hasn't been reserved and
// prerender_frame_tree_node_id() is not available yet while they are
// running.
bool is_running_potential_prerender_activation_checks_ = false;
// Set to true before the fenced frame url mapping. Reset to false when the
// mapping finishes. If the initial mapping state of the urn:uuid is pending,
// the mapping will finish asynchronously; otherwise, the mapping will finish
// synchronously.
bool is_deferred_on_fenced_frame_url_mapping_ = false;
// The start time of fenced frame url mapping.
base::TimeTicks fenced_frame_url_mapping_start_time_;
// The root frame tree node id of the prerendered page. This will be a valid
// FrameTreeNodeId value when this navigation will activate a prerendered
// page. For all other navigations this will be an invalid FrameTreeNodeId. We
// only know whether this is the case when BeginNavigation is called so the
// optional will be empty until then and callers must not query its value
// before it's been computed.
std::optional<FrameTreeNodeId> prerender_frame_tree_node_id_;
// Contains state pertaining to a prerender activation. This is only used if
// this navigation is a prerender activation.
struct PrerenderActivationNavigationState {
PrerenderActivationNavigationState();
~PrerenderActivationNavigationState();
// Used to store a cloned NavigationEntry for activating a prerendered page.
// |prerender_navigation_entry| is cloned and stored in NavigationRequest
// when the prerendered page is transferred to the target FrameTree and is
// consumed when NavigationController needs a new entry to commit.
std::unique_ptr<NavigationEntryImpl> prerender_navigation_entry;
// Used to store the FrameReplicationState for the prerendered page prior to
// activation. Value is to be used to populate
// DidCommitProvisionalLoadParams values and to verify the replication state
// after activation.
blink::mojom::FrameReplicationState prerender_main_frame_replication_state;
};
std::optional<PrerenderActivationNavigationState> prerender_navigation_state_;
// The following fields that constitute the ClientSecurityState. This
// state is used to take security decisions about the request, and later on
// when passed to the RenderFrameHostImpl, about the fetching of subresources.
//
// They have some default values and get updated via inheritance or network
// responses/redirects. Finally they get passed down to the
// RenderFrameHostImpl at commit time.
//
// The policy to apply to private network requests for subresources of the
// document we are navigating to. Influenced by the document's policy
// container, origin, and `ContentBrowserClient`.
network::mojom::PrivateNetworkRequestPolicy private_network_request_policy_ =
network::mojom::PrivateNetworkRequestPolicy::kWarn;
// The list of web features that were used by the new document during
// navigation. These can only be logged once the document commits, so they are
// held in this vector until then.
std::vector<blink::mojom::WebFeature> web_features_to_log_;
// Messages to be printed on the console in the target RenderFrameHost of this
// NavigationRequest.
std::vector<ConsoleMessage> console_messages_;
// Indicates that this navigation is for PDF content in a renderer. On
// Android, this can only be true when a PDF NativePage is created for
// a main frame navigation.
bool is_pdf_ = false;
// Indicates that this navigation is an embedder-initiated navigation of a
// fenced frame root. That is to say, the navigation is caused by a `src`
// attribute mutation on the <fencedframe> element, which cannot be performed
// from inside the fenced frame tree.
// TODO(crbug.com/40202462): Make this `const` again once ShadowDOM is gone.
bool is_embedder_initiated_fenced_frame_navigation_ = false;
// On every embedder-initiated navigation of a fenced frame, i.e.
// `is_embedder_initiated_fenced_frame_navigation_`, we reinitialize
// the fenced frame properties with the default `FencedFrameProperties(url)`
// constructor, which gives the fenced frame a fresh partition nonce.
//
// If the embedder-initiated navigation is to a urn:uuid, we overwrite
// the default properties stored in this `NavigationRequest` with the
// `FencedFrameProperties` bound to that urn:uuid, in
// `NavigationRequest::OnFencedFrameURLMappingComplete`.
//
// For certain actions related to the pending `NavigationRequest` (rather
// than the existing fenced frame document), e.g. partitioned network
// requests for the pending navigation, we use the pending
// `FencedFrameProperties`.
//
// If the navigation commits, this new set of fenced frame properties will be
// stored in the fenced frame root FrameTreeNode in
// `NavigationRequest::DidCommitNavigation`.
//
// If the navigation doesn't commit (e.g. an HTTP 204 response), the fenced
// frame properties will not be stored in the fenced frame root.
std::optional<FencedFrameProperties> fenced_frame_properties_;
// For fenced frames, any contextual string that was written by the embedder
// via `blink::FencedFrameConfig::setSharedStorageContext()` to be later
// retrieved only inside an eligible shared storage worklet in the fenced
// frame via `sharedStorage.context`. absl:nullopt if this request is not for
// a fenced frame or if the context string wasn't set prior to this
// navigation.
std::optional<std::u16string> embedder_shared_storage_context_;
// Prerender2:
// The type to trigger prerendering. The value is valid only when Prerender2
// is enabled.
std::optional<PreloadingTriggerType> prerender_trigger_type_;
// The suffix of a prerender embedder. This value is valid only when
// PreloadingTriggerType is kEmbedder. Only used for metrics.
std::string prerender_embedder_histogram_suffix_;
// Prevents the compositor from requesting main frame updates early in
// navigation.
std::unique_ptr<ui::CompositorLock> compositor_lock_;
// This navigation request should swap browsing instances as part of a test
// reset.
bool force_new_browsing_instance_ = false;
// Indicates this navigation should use a new compositor. This is used by web
// tests to ensure that input state is fully reset between tests. See comments
// at RenderFrameHostImpl::must_be_replaced().
bool force_new_compositor_ = false;
// Whether the ongoing navigation resource request is eligible for topics
// calculation. This is set before the initial request and each subsequent
// redirect. If `topics_eligible_` is true, the request headers will contain
// the "Sec-Browsing-Topics" header, and if the corresponding response headers
// contain "Observe-Browsing-Topics: ?1", a topic observation will be stored.
bool topics_eligible_ = false;
// Whether this navigation request is an iframe navigation for which the
// adAuctionHeaders attribute is set. Only requests with this attribute may be
// eligible for ad auction headerse, but not all requests with this attribute
// are eligible. `ad_auction_headers_eligible_`, below, indicates whether or
// not this request is eligible.
const bool has_ad_auction_headers_attribute_ = false;
// Whether the ongoing navigation resource request should have its Ad Auction
// response headers examined for interception. This is set before the initial
// request for iframe navigations that provide the `adAuctionHeaders`
// attribute. On redirect or error, this is always set to false. If this is
// set to true, the request headers will contain the "Sec-Ad-Auction-Fetch:
// ?1" header, and several response headers will be intercepted. See
// content/browser/interest_group/ad_auction_headers_util.h for more details.
bool ad_auction_headers_eligible_ = false;
// Whether or not the original request (without considering redirects or
// permissions policy) opted-in to write to shared storage from response
// headers. See https://github.com/WICG/shared-storage#from-response-headers
bool shared_storage_writable_opted_in_ = false;
// Whether or not the current request is eligible to shared storage from
// response headers. See
// https://github.com/WICG/shared-storage#from-response-headers
bool shared_storage_writable_eligible_ = false;
// A WeakPtr for the BindContext associated with the browser routing loader
// factory for the committing document. This will be set in
// `CommitNavigation()`, and can become null if the corresponding factory is
// destroyed. Upon `DidCommitNavigation()`,
// `subresource_proxying_url_loader_service_bind_context_` will be notified
// with the committed document.
base::WeakPtr<SubresourceProxyingURLLoaderService::BindContext>
subresource_proxying_url_loader_service_bind_context_;
// A WeakPtr for the FactoryContext associated with the browser fetch
// keepalive loader factory for the committing document.
// This field will be set in `CommitNavigation()`, and can become null if the
// corresponding factory is destroyed.
// Upon `DidCommitNavigation()`, this field will be notified with the
// committed document.
base::WeakPtr<KeepAliveURLLoaderService::FactoryContext>
keep_alive_url_loader_factory_context_;
// A WeakPtr for the FactoryContext associated with the browser fetchlater
// loader factory for the committing document.
// See also `keep_alive_url_loader_factory_context_` for the timing to update.
base::WeakPtr<KeepAliveURLLoaderService::FactoryContext>
fetch_later_loader_factory_context_;
// Set to true when the loaders above are set by unittests that want to avoid
// setting a real connection to the renderer.
bool did_set_keep_alive_url_loader_factory_context_for_testing_ = false;
bool did_set_fetch_later_url_loader_factory_context_for_testing_ = false;
scoped_refptr<NavigationOrDocumentHandle> navigation_or_document_handle_;
// Exposes getters and setters for Blink Runtime-Enabled Features to the
// browser process. Any feature set using the RuntimeFeatureStateContext
// before navigation commit will be communicated back to the renderer process.
// NOTE: these feature changes will apply to the "to-be-created" document.
blink::RuntimeFeatureStateContext runtime_feature_state_context_;
// Renderer-initiated navigations can be canceled until the JS task that
// started the navigation finishes. See RendererCancellationThrottle for more
// details. The window of time in which the renderer can cancel the navigation
// is called the "cancellation window" and the navigation can't commit until
// the cancellation window ended, which `renderer_cancellation_listener_`
// listens to. `renderer_cancellation_window_ended_` is true if the
// cancellation window had ended. If
// `renderer_cancellation_window_ended_callback_` is set, the navigation is
// being deferred by RendererCancellationThrottle to wait for the cancellation
// window to finish or for the navigation to get canceled. If it is set when
// the cancellation window ended, the callback will be run, to resume the
// navigation.
mojo::Receiver<mojom::NavigationRendererCancellationListener>
renderer_cancellation_listener_{this};
bool renderer_cancellation_window_ended_ = false;
base::OnceClosure renderer_cancellation_window_ended_callback_;
// Whether a Cookie header added to this request should not be overwritten by
// the network service.
bool allow_cookies_from_browser_ = false;
// If the browser has asked the renderer to commit the navigation in a
// speculative RenderFrameHost, but the renderer has not yet responded, a
// subsequent navigation request will be queued when it is about to pick its
// final RenderFrameHost, to avoid deleting the previous navigation's pending
// commit RenderFrameHost. A queued navigation should populate this field with
// a closure that resumes committing the navigation when run.
//
// The closure should always be bound with a `WeakPtr` receiver. To avoid
// weird reentrancy bugs, it will be run as a non-nested posted task, which
// means the original NavigationRequest could already be deleted by the
// time the closure runs.
base::OnceClosure resume_commit_closure_;
// Metrics for measuring the impact of navigation queueing. Note that while
// `resume_commit_closure_` is set on the navigation that was *blocked*, these
// metrics are set on the NavigationRequest that is *blocking*.
struct PendingCommitMetrics {
// When this `NavigationRequest` caused its speculative RenderFrameHost to
// enter pending commit.
base::TimeTicks start_time;
// How many `GetFrameHostForNavigation()` calls failed in total.
int blocked_count = 0;
// How many `GetFrameHostForNavigation()` calls failed when trying to assign
// a final `RenderFrameHost` for commit.
int blocked_commit_count = 0;
};
PendingCommitMetrics pending_commit_metrics_;
// Records whether the new document will commit inside another BrowsingContext
// group as a result of this navigation, and for what reason. Deciding whether
// to clear the window name and to clear the proxies are based on this value.
//
// It is created with a default no-swap value, and is set within
// RenderFrameHostManager::GetSiteInstanceForNavigation(). It is generally set
// more than once, first for a speculative computation before receiving
// headers, then for each redirect, and finally once a definitve response has
// been received. It might also never be set if the navigation does not go
// through SiteInstance selection, such as for a renderer initiated
// same-document navigation.
BrowsingContextGroupSwap browsing_context_group_swap_ =
BrowsingContextGroupSwap::CreateDefault();
// See `set_pending_navigation_api_key()` for context.
std::optional<std::string> pending_navigation_api_key_;
// If this NavigationRequest is for a main-frame same-document back/forward
// navigation, any subframe NavigationRequests are deferred until the renderer
// has a chance to fire a navigate event. If the navigate
// event allows the navigation to proceed,
// UnblockPendingSubframeNavigationRequestsIfNeeded() will resume these
// requests
std::vector<base::WeakPtr<SubframeHistoryNavigationThrottle>>
subframe_history_navigation_throttles_;
// If this NavigationRequest is in a subframe and part of a history traversal,
// and the main frame is performing a same-document navigation, this token
// may be set if there is a possibility that JS in the main frame will cancel
// the history traversal via the navigate event. In that case, this token is
// used to look up the main frame's NavigationRequest so that it can be passed
// SubframeHistoryNavigationThrottle can defer this request until the main
// frame commits.
std::optional<base::UnguessableToken>
main_frame_same_document_navigation_token_;
// The listener that receives cookie change events and maintains cookie change
// information for the domain of the URL that this `NavigationRequest` is
// navigating to. The listener will observe all the cookie changes starting
// from the navigation/redirection, and it will be moved to the
// `RenderFrameHostImpl` when the navigation is committed and continues
// observing until the destruction of the document.
// See `RenderFrameHostImpl::CookieChangeListener`.
std::unique_ptr<RenderFrameHostImpl::CookieChangeListener>
cookie_change_listener_;
// The observer that receives device bound session events and
// maintains device bound session information for the domain of the
// URL that this `NavigationRequest` is navigating to. The observer
// will observe all device bound session changes starting from the
// navigation/redirection, and it will be moved to the
// `RenderFrameHostImpl` when the navigation is committed and
// continues observing until the destructoin of the document.
// See `RenderFrameHostImpl::DeviceBoundSessionObserver`.
std::unique_ptr<RenderFrameHostImpl::DeviceBoundSessionObserver>
device_bound_session_observer_;
// LCP Critical Path Predictor managed hint data those were already available
// at the time of navigation. The hint is passed along to the renderer process
// on commit along with the other navigation params.
blink::mojom::LCPCriticalPathPredictorNavigationTimeHint lcpp_hint_;
// The WebUI object to be used for this navigation. When a RenderFrameHost has
// been picked for the navigation, the WebUI object will be moved to be owned
// by the RenderFrameHost.
std::unique_ptr<WebUIImpl> web_ui_;
// Returns whether this navigation is currently deferred.
bool IsDeferred();
// The watcher used to asynchronously read the response body from the data
// pipe. Once the response body is read, it is passed to the original caller
// using the stored callback. This is instantiated when a response body is
// requested and destroyed upon returning the response body.
std::unique_ptr<mojo::SimpleWatcher> response_body_watcher_;
ResponseBodyCallback response_body_callback_;
// Used to confirm that any NavigationThrottle that calls `GetResponseBody()`
// becomes deferred.
bool was_get_response_body_called_ = false;
// Used to prevent re-entrancy into `Resume()`.
bool is_resuming_ = false;
EarlyRenderFrameHostSwapType early_render_frame_host_swap_type_ =
EarlyRenderFrameHostSwapType::kNone;
// Whether the embedder indicated this navigation is being used for
// advertising porpoises.
bool is_ad_tagged_ = false;
// This is the origin to commit value calculated at request time for data: URL
// navigations. It is stored so that the opaque origin nonce can be maintained
// across a navigation. This value is used when a speculative SiteInstance
// is created so the site URL of the navigation can match the initiator
// origin. We store the tentative origin to commit value, since we need it
// before ready to commit time, which is when the regular origin to commit
// value is available.
std::optional<url::Origin> tentative_data_origin_to_commit_;
// `pageswap` can be fired at different stages of the navigation lifecycle:
// - ready to commit if this navigation is associated with a ViewTransition.
// - unload old document if there is no ViewTransition opt-in.
// This tracks whether the pageswap event has been fired for this
// navigation.
bool did_fire_page_swap_ = false;
// Set if there has been any cross-origin redirects in the lifetime of this
// request.
bool did_encounter_cross_origin_redirect_ = false;
// A scoped reference on the ViewTransition resources generated for this
// navigation. This is set after we received the cached results from the old
// Document's renderer. If the navigation commits, the resources are
// transferred to the new Document's view. If the navigation finishes without
// committing, the resources are destroyed with this request.
std::unique_ptr<ScopedViewTransitionResources> view_transition_resources_;
// If true, this means that this navigation request was initiated by an
// animated transition.
bool was_initiated_by_animated_transition_ = false;
// If the navigation is cancelled/discarded before it commits, the reason
// for cancellation will be saved.
std::optional<NavigationDiscardReason> navigation_discard_reason_;
// If true, HTTPS Upgrades will be disabled on this navigation request.
bool force_no_https_upgrade_ = false;
// The initial request method of the request, before any redirects.
std::string request_method_;
// Set to true if `this` started as a same-document navigation but couldn't
// commit, and was restarted as a cross-document navigation. See
// `blink::mojom::CommitResult::RestartCrossDocument`.
bool was_reset_for_cross_document_restart_ = false;
// The confidence level captured at the time the navigation request was
// instantiated.
blink::mojom::ConfidenceLevel confidence_level_ =
blink::mojom::ConfidenceLevel::kHigh;
base::WeakPtrFactory<NavigationRequest> weak_factory_{this};
};
} // namespace content
#endif // CONTENT_BROWSER_RENDERER_HOST_NAVIGATION_REQUEST_H_