// 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.

#include "content/browser/renderer_host/navigation_request.h"

#include <memory>
#include <optional>
#include <string>
#include <utility>
#include <vector>

#include "base/auto_reset.h"
#include "base/check_is_test.h"
#include "base/command_line.h"
#include "base/containers/contains.h"
#include "base/containers/span.h"
#include "base/debug/alias.h"
#include "base/debug/crash_logging.h"
#include "base/debug/dump_without_crashing.h"
#include "base/feature_list.h"
#include "base/files/file_path.h"
#include "base/functional/bind.h"
#include "base/memory/ptr_util.h"
#include "base/memory/safe_ref.h"
#include "base/metrics/field_trial_params.h"
#include "base/metrics/histogram_functions.h"
#include "base/metrics/histogram_macros.h"
#include "base/metrics/user_metrics.h"
#include "base/no_destructor.h"
#include "base/not_fatal_until.h"
#include "base/notreached.h"
#include "base/rand_util.h"
#include "base/state_transitions.h"
#include "base/strings/strcat.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "base/system/sys_info.h"
#include "base/task/sequenced_task_runner.h"
#include "base/time/time.h"
#include "base/timer/elapsed_timer.h"
#include "base/trace_event/trace_event.h"
#include "base/types/optional_util.h"
#include "base/types/pass_key.h"
#include "build/build_config.h"
#include "build/buildflag.h"
#include "components/viz/host/host_frame_sink_manager.h"
#include "content/browser/agent_cluster_key.h"
#include "content/browser/blob_storage/chrome_blob_storage_context.h"
#include "content/browser/browsing_topics/header_util.h"
#include "content/browser/child_process_security_policy_impl.h"
#include "content/browser/client_hints/client_hints.h"
#include "content/browser/devtools/devtools_instrumentation.h"
#include "content/browser/devtools/network_service_devtools_observer.h"
#include "content/browser/download/download_manager_impl.h"
#include "content/browser/fenced_frame/fenced_frame_url_mapping.h"
#include "content/browser/interest_group/ad_auction_headers_util.h"
#include "content/browser/loader/browser_initiated_resource_request.h"
#include "content/browser/loader/cached_navigation_url_loader.h"
#include "content/browser/loader/navigation_early_hints_manager.h"
#include "content/browser/loader/navigation_url_loader.h"
#include "content/browser/loader/object_navigation_fallback_body_loader.h"
#include "content/browser/loader/url_loader_factory_utils.h"
#include "content/browser/navigation_or_document_handle.h"
#include "content/browser/network/cross_origin_embedder_policy_reporter.h"
#include "content/browser/network_service_instance_impl.h"
#include "content/browser/origin_agent_cluster_isolation_state.h"
#include "content/browser/origin_trials/origin_trials_utils.h"
#include "content/browser/permissions/permission_controller_impl.h"
#include "content/browser/preloading/prefetch/prefetch_document_manager.h"
#include "content/browser/preloading/prefetch/prefetch_features.h"
#include "content/browser/preloading/prefetch/prefetch_serving_page_metrics_container.h"
#include "content/browser/preloading/prerender/prerender_host_registry.h"
#include "content/browser/preloading/prerender/prerender_metrics.h"
#include "content/browser/preloading/prerender/prerender_navigation_utils.h"
#include "content/browser/process_lock.h"
#include "content/browser/renderer_host/back_forward_cache_impl.h"
#include "content/browser/renderer_host/concurrent_navigations_commit_deferring_condition.h"
#include "content/browser/renderer_host/cookie_utils.h"
#include "content/browser/renderer_host/debug_urls.h"
#include "content/browser/renderer_host/frame_tree.h"
#include "content/browser/renderer_host/frame_tree_node.h"
#include "content/browser/renderer_host/navigation_controller_impl.h"
#include "content/browser/renderer_host/navigation_request_info.h"
#include "content/browser/renderer_host/navigation_state_keep_alive.h"
#include "content/browser/renderer_host/navigator.h"
#include "content/browser/renderer_host/navigator_delegate.h"
#include "content/browser/renderer_host/page_delegate.h"
#include "content/browser/renderer_host/private_network_access_util.h"
#include "content/browser/renderer_host/render_frame_host_csp_context.h"
#include "content/browser/renderer_host/render_frame_host_delegate.h"
#include "content/browser/renderer_host/render_frame_host_impl.h"
#include "content/browser/renderer_host/render_frame_proxy_host.h"
#include "content/browser/renderer_host/render_process_host_impl.h"
#include "content/browser/renderer_host/render_view_host_delegate.h"
#include "content/browser/renderer_host/render_view_host_impl.h"
#include "content/browser/renderer_host/scoped_view_transition_resources.h"
#include "content/browser/renderer_host/subframe_history_navigation_throttle.h"
#include "content/browser/scoped_active_url.h"
#include "content/browser/security/coop/cross_origin_opener_policy_reporter.h"
#include "content/browser/service_worker/service_worker_client.h"
#include "content/browser/service_worker/service_worker_context_core.h"
#include "content/browser/service_worker/service_worker_context_wrapper.h"
#include "content/browser/service_worker/service_worker_main_resource_handle.h"
#include "content/browser/shared_storage/shared_storage_header_observer.h"
#include "content/browser/site_info.h"
#include "content/browser/site_instance_impl.h"
#include "content/browser/storage_partition_impl.h"
#include "content/browser/url_loader_factory_params_helper.h"
#include "content/browser/web_package/prefetched_signed_exchange_cache.h"
#include "content/common/content_constants_internal.h"
#include "content/common/content_navigation_policy.h"
#include "content/common/debug_utils.h"
#include "content/common/features.h"
#include "content/common/navigation_params_utils.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/child_process_host.h"
#include "content/public/browser/client_hints_controller_delegate.h"
#include "content/public/browser/commit_deferring_condition.h"
#include "content/public/browser/content_browser_client.h"
#include "content/public/browser/cookie_access_details.h"
#include "content/public/browser/global_request_id.h"
#include "content/public/browser/navigation_controller.h"
#include "content/public/browser/navigation_ui_data.h"
#include "content/public/browser/network_service_instance.h"
#include "content/public/browser/network_service_util.h"
#include "content/public/browser/origin_trials_controller_delegate.h"
#include "content/public/browser/peak_gpu_memory_tracker_factory.h"
#include "content/public/browser/reduce_accept_language_controller_delegate.h"
#include "content/public/browser/reduce_accept_language_utils.h"
#include "content/public/browser/render_view_host.h"
#include "content/public/browser/runtime_feature_state/runtime_feature_state_document_data.h"
#include "content/public/browser/site_isolation_policy.h"
#include "content/public/browser/storage_partition.h"
#include "content/public/browser/weak_document_ptr.h"
#include "content/public/common/content_client.h"
#include "content/public/common/content_features.h"
#include "content/public/common/content_switches.h"
#include "content/public/common/origin_util.h"
#include "content/public/common/url_constants.h"
#include "content/public/common/url_utils.h"
#include "mojo/public/cpp/system/data_pipe.h"
#include "net/base/features.h"
#include "net/base/filename_util.h"
#include "net/base/ip_endpoint.h"
#include "net/base/load_flags.h"
#include "net/base/net_errors.h"
#include "net/base/registry_controlled_domains/registry_controlled_domain.h"
#include "net/base/url_util.h"
#include "net/cookies/cookie_access_result.h"
#include "net/filter/source_stream_type.h"
#include "net/http/http_request_headers.h"
#include "net/http/http_status_code.h"
#include "net/storage_access_api/status.h"
#include "net/url_request/redirect_info.h"
#include "services/metrics/public/cpp/ukm_builders.h"
#include "services/metrics/public/cpp/ukm_recorder.h"
#include "services/metrics/public/cpp/ukm_source_id.h"
#include "services/network/public/cpp/client_hints.h"
#include "services/network/public/cpp/content_decoding_interceptor.h"
#include "services/network/public/cpp/content_security_policy/content_security_policy.h"
#include "services/network/public/cpp/cross_origin_embedder_policy.h"
#include "services/network/public/cpp/cross_origin_opener_policy.h"
#include "services/network/public/cpp/cross_origin_resource_policy.h"
#include "services/network/public/cpp/features.h"
#include "services/network/public/cpp/header_util.h"
#include "services/network/public/cpp/integrity_policy.h"
#include "services/network/public/cpp/is_potentially_trustworthy.h"
#include "services/network/public/cpp/permissions_policy/fenced_frame_permissions_policies.h"
#include "services/network/public/cpp/permissions_policy/permissions_policy_declaration.h"
#include "services/network/public/cpp/permissions_policy/permissions_policy_features.h"
#include "services/network/public/cpp/resource_request_body.h"
#include "services/network/public/cpp/supports_loading_mode/supports_loading_mode_parser.h"
#include "services/network/public/cpp/url_loader_completion_status.h"
#include "services/network/public/cpp/web_sandbox_flags.h"
#include "services/network/public/mojom/connection_change_observer_client.mojom.h"
#include "services/network/public/mojom/device_bound_sessions.mojom.h"
#include "services/network/public/mojom/fetch_api.mojom.h"
#include "services/network/public/mojom/permissions_policy/permissions_policy_feature.mojom-shared.h"
#include "services/network/public/mojom/supports_loading_mode.mojom.h"
#include "services/network/public/mojom/url_response_head.mojom-forward.h"
#include "services/network/public/mojom/url_response_head.mojom-shared.h"
#include "services/network/public/mojom/url_response_head.mojom.h"
#include "services/network/public/mojom/web_client_hints_types.mojom-shared.h"
#include "services/network/public/mojom/web_client_hints_types.mojom.h"
#include "services/network/public/mojom/web_sandbox_flags.mojom.h"
#include "storage/browser/blob/blob_url_registry.h"
#include "third_party/abseil-cpp/absl/cleanup/cleanup.h"
#include "third_party/blink/public/common/blob/blob_utils.h"
#include "third_party/blink/public/common/chrome_debug_urls.h"
#include "third_party/blink/public/common/client_hints/client_hints.h"
#include "third_party/blink/public/common/features.h"
#include "third_party/blink/public/common/fenced_frame/fenced_frame_utils.h"
#include "third_party/blink/public/common/fenced_frame/redacted_fenced_frame_config.h"
#include "third_party/blink/public/common/frame/fenced_frame_sandbox_flags.h"
#include "third_party/blink/public/common/frame/frame_owner_element_type.h"
#include "third_party/blink/public/common/navigation/navigation_params.h"
#include "third_party/blink/public/common/navigation/navigation_params_mojom_traits.h"
#include "third_party/blink/public/common/navigation/navigation_policy.h"
#include "third_party/blink/public/common/navigation/preloading_headers.h"
#include "third_party/blink/public/common/origin_trials/trial_token_validator.h"
#include "third_party/blink/public/common/permissions_policy/document_policy.h"
#include "third_party/blink/public/common/permissions_policy/policy_helper_public.h"
#include "third_party/blink/public/common/renderer_preferences/renderer_preferences.h"
#include "third_party/blink/public/common/runtime_feature_state/runtime_feature_state_context.h"
#include "third_party/blink/public/common/security/address_space_feature.h"
#include "third_party/blink/public/common/user_agent/user_agent_metadata.h"
#include "third_party/blink/public/common/web_preferences/web_preferences.h"
#include "third_party/blink/public/mojom/fetch/fetch_api_request.mojom.h"
#include "third_party/blink/public/mojom/loader/mixed_content.mojom.h"
#include "third_party/blink/public/mojom/loader/transferrable_url_loader.mojom.h"
#include "third_party/blink/public/mojom/navigation/navigation_params.mojom-shared.h"
#include "third_party/blink/public/mojom/navigation/navigation_params.mojom.h"
#include "third_party/blink/public/mojom/navigation/prefetched_signed_exchange_info.mojom.h"
#include "third_party/blink/public/mojom/runtime_feature_state/runtime_feature.mojom.h"
#include "third_party/blink/public/mojom/service_worker/service_worker_provider.mojom.h"
#include "third_party/blink/public/mojom/storage_key/ancestor_chain_bit.mojom.h"
#include "third_party/blink/public/mojom/timing/resource_timing.mojom-forward.h"
#include "third_party/blink/public/mojom/use_counter/metrics/web_feature.mojom.h"
#include "third_party/blink/public/platform/resource_request_blocked_reason.h"
#include "third_party/perfetto/include/perfetto/tracing/track.h"
#include "ui/compositor/compositor_lock.h"
#include "url/origin.h"
#include "url/url_constants.h"

#if BUILDFLAG(IS_ANDROID)
#include "content/browser/renderer_host/navigation_transitions/navigation_entry_screenshot_cache.h"
#include "ui/android/window_android.h"
#include "ui/android/window_android_compositor.h"
#endif

namespace content {

namespace {

// Kill-switch for the fix to copy item_sequence_number and
// document_sequence_number from a prerender navigation entry during prerender
// activation (https://crbug.com/442618062).
BASE_FEATURE(kPrerenderFixSequenceNumbers, base::FEATURE_ENABLED_BY_DEFAULT);

// Default timeout for the READY_TO_COMMIT -> COMMIT transition. Chosen
// initially based on the Navigation.ReadyToCommitUntilCommit UMA, and then
// refined based on feedback based on CrashExitCodes.Renderer/RESULT_CODE_HUNG.
constexpr base::TimeDelta kDefaultCommitTimeout = base::Seconds(30);

// Timeout for the READY_TO_COMMIT -> COMMIT transition.
// Overrideable via SetCommitTimeoutForTesting.
base::TimeDelta g_commit_timeout = kDefaultCommitTimeout;

#if BUILDFLAG(IS_ANDROID)
// Timeout for locking the compositor at the beginning of navigation.
constexpr base::TimeDelta kCompositorLockTimeout = base::Milliseconds(150);
#endif

const char kSecSharedStorageWritableRequestHeaderKey[] =
    "Sec-Shared-Storage-Writable";

// Flag to control whether redirect URLs are being sanitized before sending
// them to the renderer process as part of the navigation.
// See https://crbug.com/40095391.
BASE_FEATURE(kSanitizeRedirectUrlsDuringNavigation,
             base::FEATURE_ENABLED_BY_DEFAULT);

const base::FeatureParam<bool> kDeferSpeculativeRFHWaitUntilFinalResponse{
    &features::kDeferSpeculativeRFHCreation, "wait_until_final_response",
    false};

// Denotes the type of user agent string value sent in the User-Agent request
// header.
//
// Corresponds to the "UserAgentStringType" histogram enumeration type in
// tools/metrics/histograms/enums.xml.
//
// PLEASE DO NOT REORDER, REMOVE, OR CHANGE THE MEANING OF THESE VALUES.
enum class UserAgentStringType {
  kFullVersion,
  kReducedVersion,
  kOverriden,
  kMaxValue = kOverriden
};

// Returns the net load flags to use based on the navigation type.
// TODO(clamy): Remove the blink code that sets the caching flags.
void UpdateLoadFlagsWithCacheFlags(int* load_flags,
                                   blink::mojom::NavigationType navigation_type,
                                   bool is_post) {
  switch (navigation_type) {
    case blink::mojom::NavigationType::RELOAD:
      *load_flags |= net::LOAD_VALIDATE_CACHE;
      break;
    case blink::mojom::NavigationType::RELOAD_BYPASSING_CACHE:
      *load_flags |= net::LOAD_BYPASS_CACHE;
      break;
    case blink::mojom::NavigationType::RESTORE:
      *load_flags |= net::LOAD_SKIP_CACHE_VALIDATION;
      break;
    case blink::mojom::NavigationType::RESTORE_WITH_POST:
      *load_flags |=
          net::LOAD_ONLY_FROM_CACHE | net::LOAD_SKIP_CACHE_VALIDATION;
      break;
    case blink::mojom::NavigationType::SAME_DOCUMENT:
    case blink::mojom::NavigationType::DIFFERENT_DOCUMENT:
      if (is_post)
        *load_flags |= net::LOAD_VALIDATE_CACHE;
      break;
    case blink::mojom::NavigationType::HISTORY_SAME_DOCUMENT:
    case blink::mojom::NavigationType::HISTORY_DIFFERENT_DOCUMENT:
      if (is_post) {
        *load_flags |=
            net::LOAD_ONLY_FROM_CACHE | net::LOAD_SKIP_CACHE_VALIDATION;
      } else {
        *load_flags |= net::LOAD_SKIP_CACHE_VALIDATION;
      }
      break;
  }
}

// This should match blink::ResourceRequest::needsHTTPOrigin.
bool NeedsHTTPOrigin(net::HttpRequestHeaders* headers,
                     const std::string& method) {
  // Blink version of this function checks if the Origin header might have
  // already been added to |headers|.  This check is not replicated below
  // because:
  // 1. We want to overwrite the old (renderer-provided) header value
  //    with a new, trustworthy (browser-provided) value.
  // 2. The rest of the function matches the Blink version, so there should
  //    be no discrepancies in the Origin value used.

  // Don't send an Origin header for GET or HEAD to avoid privacy issues.
  // For example, if an intranet page has a hyperlink to an external web
  // site, we don't want to include the Origin of the request because it
  // will leak the internal host name. Similar privacy concerns have lead
  // to the widespread suppression of the Referer header at the network
  // layer.
  if (method == "GET" || method == "HEAD")
    return false;

  // For non-GET and non-HEAD methods, always send an Origin header so the
  // server knows we support this feature.
  return true;
}

// Computes the value that should be set for the User-Agent header, if
// `user_agent_override` is non-empty, `user_agent_override` is returned as the
// header value.
std::string ComputeUserAgentValue(const net::HttpRequestHeaders& headers,
                                  const std::string& user_agent_override,
                                  content::BrowserContext* context) {
  if (!user_agent_override.empty()) {
    base::UmaHistogramEnumeration("Navigation.UserAgentStringType",
                                  UserAgentStringType::kOverriden);
    return user_agent_override;
  }

  base::UmaHistogramEnumeration(
      "Navigation.UserAgentStringType",
      base::FeatureList::IsEnabled(
          blink::features::kReduceUserAgentMinorVersion)
          ? UserAgentStringType::kReducedVersion
          : UserAgentStringType::kFullVersion);

  return GetContentClient()->browser()->GetUserAgentBasedOnPolicy(context);
}

void AddAdditionalRequestHeaders(
    net::HttpRequestHeaders* headers,
    const GURL& url,
    blink::mojom::NavigationType navigation_type,
    ui::PageTransition transition,
    BrowserContext* browser_context,
    const std::string& method,
    const std::string& user_agent_override,
    const std::optional<url::Origin>& initiator_origin,
    blink::mojom::Referrer* referrer,
    FrameTreeNode* frame_tree_node) {
  if (!url.SchemeIsHTTPOrHTTPS())
    return;

  bool is_reload = NavigationTypeUtils::IsReload(navigation_type);
  RenderViewHostImpl* render_view_host =
      frame_tree_node->current_frame_host()->render_view_host();
  const blink::RendererPreferences& render_prefs =
      render_view_host->GetDelegate()->GetRendererPrefs(render_view_host);
  UpdateAdditionalHeadersForBrowserInitiatedRequest(
      headers, browser_context, is_reload, render_prefs,
      /*is_for_worker_script*=*/false);

  // Tack an 'Upgrade-Insecure-Requests' header to outgoing navigational
  // requests, as described in
  // https://w3c.github.io/webappsec/specs/upgrade/#feature-detect
  headers->SetHeaderIfMissing("Upgrade-Insecure-Requests", "1");

  headers->SetHeaderIfMissing(
      net::HttpRequestHeaders::kUserAgent,
      ComputeUserAgentValue(*headers, user_agent_override, browser_context));

  if (!render_prefs.enable_referrers) {
    *referrer =
        blink::mojom::Referrer(GURL(), network::mojom::ReferrerPolicy::kNever);
  }

  // Next, set the HTTP Origin if needed.
  if (NeedsHTTPOrigin(headers, method)) {
    url::Origin origin_header_value = initiator_origin.value_or(url::Origin());
    origin_header_value = Referrer::SanitizeOriginForRequest(
        url, origin_header_value, referrer->policy);
    headers->SetHeader(net::HttpRequestHeaders::kOrigin,
                       origin_header_value.Serialize());
  }

  if (base::FeatureList::IsEnabled(features::kDocumentPolicyNegotiation)) {
    const blink::DocumentPolicyFeatureState& required_policy =
        frame_tree_node->effective_frame_policy().required_document_policy;
    if (!required_policy.empty()) {
      std::optional<std::string> policy_header =
          blink::DocumentPolicy::Serialize(required_policy);
      DCHECK(policy_header);
      headers->SetHeader("Sec-Required-Document-Policy", policy_header.value());
    }
  }

  // Add the "Sec-Purpose: prefetch;prerender" header to prerender navigations
  // including subframe navigations.
  if (frame_tree_node->frame_tree().is_prerendering()) {
    PrerenderHost::GetFromFrameTreeNode(*frame_tree_node)
        .AddAdditionalRequestHeaders(*headers, *frame_tree_node);
  } else if (frame_tree_node->frame_tree()
                 .page_delegate()
                 ->IsPageInPreviewMode()) {
    // Preview mode sends similar request so that it is compatible with
    // prerendering as we can as possible, but adds `preview` for sites that
    // need to identify the preview case from prerendering.
    // Do not send the `Purpose` header as the preview mode is new and don't
    // need to be careful about the compatibility breakage here.
    headers->SetHeader(blink::kSecPurposeHeaderName,
                       blink::kSecPurposePrefetchPrerenderPreviewHeaderValue);
  }
}

bool ShouldPropagateUserActivation(const url::Origin& previous_origin,
                                   const url::Origin& new_origin) {
  if ((previous_origin.scheme() != "http" &&
       previous_origin.scheme() != "https") ||
      (new_origin.scheme() != "http" && new_origin.scheme() != "https")) {
    return false;
  }

  if (previous_origin.host() == new_origin.host())
    return true;

  std::string previous_domain =
      net::registry_controlled_domains::GetDomainAndRegistry(
          previous_origin,
          net::registry_controlled_domains::INCLUDE_PRIVATE_REGISTRIES);
  std::string new_domain =
      net::registry_controlled_domains::GetDomainAndRegistry(
          new_origin,
          net::registry_controlled_domains::INCLUDE_PRIVATE_REGISTRIES);
  return !previous_domain.empty() && previous_domain == new_domain;
}

// LOG_NAVIGATION_TIMING_HISTOGRAM logs |value| for "Navigation.<histogram>" UMA
// as well as supplementary UMAs (depending on |transition| and |priority|)
// for BackForward/Reload/NewNavigation variants.
//
// kMaxTime and kBuckets constants are consistent with
// UmaHistogramMediumTimes, but a custom kMinTime is used for high
// fidelity near the low end of measured values.
//
// TODO(csharrison,nasko): This macro is incorrect for subframe navigations,
// which will only have subframe-specific transition types. This means that all
// subframes currently are tagged as NewNavigations.
#define LOG_NAVIGATION_TIMING_HISTOGRAM(histogram, transition, priority,      \
                                        duration)                             \
  do {                                                                        \
    const base::TimeDelta kMinTime = base::Milliseconds(1);                   \
    const base::TimeDelta kMaxTime = base::Minutes(3);                        \
    const int kBuckets = 50;                                                  \
    UMA_HISTOGRAM_CUSTOM_TIMES("Navigation." histogram, duration, kMinTime,   \
                               kMaxTime, kBuckets);                           \
    if (transition & ui::PAGE_TRANSITION_FORWARD_BACK) {                      \
      UMA_HISTOGRAM_CUSTOM_TIMES("Navigation." histogram ".BackForward",      \
                                 duration, kMinTime, kMaxTime, kBuckets);     \
    } else if (ui::PageTransitionCoreTypeIs(transition,                       \
                                            ui::PAGE_TRANSITION_RELOAD)) {    \
      UMA_HISTOGRAM_CUSTOM_TIMES("Navigation." histogram ".Reload", duration, \
                                 kMinTime, kMaxTime, kBuckets);               \
    } else if (ui::PageTransitionIsNewNavigation(transition)) {               \
      UMA_HISTOGRAM_CUSTOM_TIMES("Navigation." histogram ".NewNavigation",    \
                                 duration, kMinTime, kMaxTime, kBuckets);     \
    } else {                                                                  \
      NOTREACHED() << "Invalid page transition: " << transition;              \
    }                                                                         \
    if (priority.has_value()) {                                               \
      if (priority.value() == base::Process::Priority::kBestEffort) {         \
        UMA_HISTOGRAM_CUSTOM_TIMES("Navigation." histogram                    \
                                   ".BackgroundProcessPriority",              \
                                   duration, kMinTime, kMaxTime, kBuckets);   \
      } else {                                                                \
        UMA_HISTOGRAM_CUSTOM_TIMES("Navigation." histogram                    \
                                   ".ForegroundProcessPriority",              \
                                   duration, kMinTime, kMaxTime, kBuckets);   \
      }                                                                       \
    }                                                                         \
  } while (0)

void RecordStartToCommitMetrics(base::TimeTicks navigation_start_time,
                                ui::PageTransition transition,
                                const base::TimeTicks& ready_to_commit_time,
                                std::optional<base::Process::Priority> priority,
                                bool is_same_process,
                                bool is_main_frame) {
  base::TimeTicks now = base::TimeTicks::Now();
  base::TimeDelta delta = now - navigation_start_time;
  LOG_NAVIGATION_TIMING_HISTOGRAM("StartToCommit", transition, priority, delta);
  if (is_main_frame) {
    LOG_NAVIGATION_TIMING_HISTOGRAM("StartToCommit.MainFrame", transition,
                                    priority, delta);
  } else {
    LOG_NAVIGATION_TIMING_HISTOGRAM("StartToCommit.Subframe", transition,
                                    priority, delta);
  }
  if (is_same_process) {
    LOG_NAVIGATION_TIMING_HISTOGRAM("StartToCommit.SameProcess", transition,
                                    priority, delta);
    if (is_main_frame) {
      LOG_NAVIGATION_TIMING_HISTOGRAM("StartToCommit.SameProcess.MainFrame",
                                      transition, priority, delta);
    } else {
      LOG_NAVIGATION_TIMING_HISTOGRAM("StartToCommit.SameProcess.Subframe",
                                      transition, priority, delta);
    }
  } else {
    LOG_NAVIGATION_TIMING_HISTOGRAM("StartToCommit.CrossProcess", transition,
                                    priority, delta);
    if (is_main_frame) {
      LOG_NAVIGATION_TIMING_HISTOGRAM("StartToCommit.CrossProcess.MainFrame",
                                      transition, priority, delta);
    } else {
      LOG_NAVIGATION_TIMING_HISTOGRAM("StartToCommit.CrossProcess.Subframe",
                                      transition, priority, delta);
    }
  }
  if (!ready_to_commit_time.is_null()) {
    LOG_NAVIGATION_TIMING_HISTOGRAM("ReadyToCommitUntilCommit2", transition,
                                    priority, now - ready_to_commit_time);
  }
}

void RecordReadyToCommitMetrics(
    RenderFrameHostImpl* old_rfh,
    RenderFrameHostImpl* new_rfh,
    const blink::mojom::CommonNavigationParams& common_params,
    base::TimeTicks ready_to_commit_time,
    NavigationRequest::OriginAgentClusterEndResult
        origin_agent_cluster_end_result,
    bool did_receive_early_hints_before_cross_origin_redirect) {
  bool is_main_frame = !new_rfh->GetParent();
  bool is_same_process = old_rfh->GetProcess()->GetDeprecatedID() ==
                         new_rfh->GetProcess()->GetDeprecatedID();

  // Navigation.IsSameBrowsingInstance
  if (is_main_frame) {
    bool is_same_browsing_instance =
        old_rfh->GetSiteInstance()->IsRelatedSiteInstance(
            new_rfh->GetSiteInstance());

    UMA_HISTOGRAM_BOOLEAN("Navigation.IsSameBrowsingInstance",
                          is_same_browsing_instance);
  }

  // Navigation.IsSameSiteInstance
  {
    bool is_same_site_instance =
        old_rfh->GetSiteInstance() == new_rfh->GetSiteInstance();
    UMA_HISTOGRAM_BOOLEAN("Navigation.IsSameSiteInstance",
                          is_same_site_instance);
    if (is_main_frame) {
      UMA_HISTOGRAM_BOOLEAN("Navigation.IsSameSiteInstance.MainFrame",
                            is_same_site_instance);
    } else {
      UMA_HISTOGRAM_BOOLEAN("Navigation.IsSameSiteInstance.Subframe",
                            is_same_site_instance);
    }
  }

  // Navigation.IsLockedProcess
  {
    ProcessLock process_lock = new_rfh->GetProcess()->GetProcessLock();
    UMA_HISTOGRAM_BOOLEAN("Navigation.IsLockedProcess",
                          process_lock.IsLockedToSite());
    if (common_params.url.SchemeIsHTTPOrHTTPS()) {
      UMA_HISTOGRAM_BOOLEAN("Navigation.IsLockedProcess.HTTPOrHTTPS",
                            process_lock.IsLockedToSite());
    }
  }

  // Navigation.RequiresDedicatedProcess
  {
    UMA_HISTOGRAM_BOOLEAN(
        "Navigation.RequiresDedicatedProcess",
        new_rfh->GetSiteInstance()->RequiresDedicatedProcess());
    if (common_params.url.SchemeIsHTTPOrHTTPS()) {
      UMA_HISTOGRAM_BOOLEAN(
          "Navigation.RequiresDedicatedProcess.HTTPOrHTTPS",
          new_rfh->GetSiteInstance()->RequiresDedicatedProcess());
    }
  }

  // TimeToReadyToCommit2
  {
    constexpr std::optional<base::Process::Priority> kPriority = std::nullopt;
    base::TimeDelta delta =
        ready_to_commit_time - common_params.navigation_start;
    ui::PageTransition transition =
        ui::PageTransitionFromInt(common_params.transition);

    LOG_NAVIGATION_TIMING_HISTOGRAM("TimeToReadyToCommit2", transition,
                                    kPriority, delta);
    if (is_main_frame) {
      LOG_NAVIGATION_TIMING_HISTOGRAM("TimeToReadyToCommit2.MainFrame",
                                      transition, kPriority, delta);
    } else {
      LOG_NAVIGATION_TIMING_HISTOGRAM("TimeToReadyToCommit2.Subframe",
                                      transition, kPriority, delta);
    }
    if (is_same_process) {
      LOG_NAVIGATION_TIMING_HISTOGRAM("TimeToReadyToCommit2.SameProcess",
                                      transition, kPriority, delta);
    } else {
      LOG_NAVIGATION_TIMING_HISTOGRAM("TimeToReadyToCommit2.CrossProcess",
                                      transition, kPriority, delta);
    }
    if (did_receive_early_hints_before_cross_origin_redirect) {
      LOG_NAVIGATION_TIMING_HISTOGRAM(
          "TimeToReadyToCommit2.CrossOriginRedirectAfterEarlyHints", transition,
          kPriority, delta);
    }
  }

  // Navigation.OriginAgentCluster
  {
    UMA_HISTOGRAM_ENUMERATION("Navigation.OriginAgentCluster.Result",
                              origin_agent_cluster_end_result);
  }

  // Guest (<webview> tag) metrics.
  {
    base::UmaHistogramBoolean("Navigation.IsGuest",
                              new_rfh->GetSiteInstance()->IsGuest());
    if (new_rfh->GetSiteInstance()->IsGuest()) {
      base::UmaHistogramBoolean("Navigation.Guest.IsHTTPOrHTTPS",
                                common_params.url.SchemeIsHTTPOrHTTPS());
      base::UmaHistogramBoolean("Navigation.Guest.IsMainFrame", is_main_frame);
    }
  }
}

// Convert the navigation type to the appropriate cross-document one.
//
// This is currently used when:
// 1) Restarting a same-document navigation as cross-document.
// 2) Failing a navigation and committing an error page.
blink::mojom::NavigationType ConvertToCrossDocumentType(
    blink::mojom::NavigationType type) {
  switch (type) {
    case blink::mojom::NavigationType::SAME_DOCUMENT:
      return blink::mojom::NavigationType::DIFFERENT_DOCUMENT;
    case blink::mojom::NavigationType::HISTORY_SAME_DOCUMENT:
      return blink::mojom::NavigationType::HISTORY_DIFFERENT_DOCUMENT;
    case blink::mojom::NavigationType::RELOAD:
    case blink::mojom::NavigationType::RELOAD_BYPASSING_CACHE:
    case blink::mojom::NavigationType::RESTORE:
    case blink::mojom::NavigationType::RESTORE_WITH_POST:
    case blink::mojom::NavigationType::HISTORY_DIFFERENT_DOCUMENT:
    case blink::mojom::NavigationType::DIFFERENT_DOCUMENT:
      return type;
  }
}

base::debug::CrashKeyString* GetNavigationRequestUrlCrashKey() {
  static auto* crash_key = base::debug::AllocateCrashKeyString(
      "navigation_request_url", base::debug::CrashKeySize::Size256);
  return crash_key;
}

base::debug::CrashKeyString* GetNavigationRequestInitiatorCrashKey() {
  static auto* crash_key = base::debug::AllocateCrashKeyString(
      "navigation_request_initiator", base::debug::CrashKeySize::Size64);
  return crash_key;
}

base::debug::CrashKeyString* GetNavigationRequestIsSameDocumentCrashKey() {
  static auto* crash_key = base::debug::AllocateCrashKeyString(
      "navigation_request_is_same_document", base::debug::CrashKeySize::Size64);
  return crash_key;
}

// Start a new nested async event with the given name.
void EnterChildTraceEvent(perfetto::StaticString name,
                          NavigationRequest* request) {
  TRACE_EVENT_END("navigation", perfetto::Track(request->GetNavigationId()));
  TRACE_EVENT_BEGIN("navigation", name,
                    perfetto::Track(request->GetNavigationId()));
}

// Start a new nested async event with the given name and args.
template <typename ArgType>
void EnterChildTraceEvent(perfetto::StaticString name,
                          NavigationRequest* request,
                          const char* arg_name,
                          ArgType arg_value) {
  TRACE_EVENT_END("navigation", perfetto::Track(request->GetNavigationId()));
  TRACE_EVENT_BEGIN("navigation", name,
                    perfetto::Track(request->GetNavigationId()), arg_name,
                    arg_value);
}

network::mojom::RequestDestination GetDestinationFromFrameTreeNode(
    FrameTreeNode* frame_tree_node) {
  if (frame_tree_node->IsInFencedFrameTree())
    return network::mojom::RequestDestination::kFencedframe;

  if (frame_tree_node->IsMainFrame()) {
    return network::mojom::RequestDestination::kDocument;
  }

  switch (frame_tree_node->frame_owner_element_type()) {
    case blink::FrameOwnerElementType::kObject:
      return network::mojom::RequestDestination::kObject;
    case blink::FrameOwnerElementType::kEmbed:
      return network::mojom::RequestDestination::kEmbed;
    case blink::FrameOwnerElementType::kIframe:
      return network::mojom::RequestDestination::kIframe;
    case blink::FrameOwnerElementType::kFrame:
      return network::mojom::RequestDestination::kFrame;
    // Main frames are handled above.
    case blink::FrameOwnerElementType::kNone:
      NOTREACHED();
    case blink::FrameOwnerElementType::kFencedframe:
      // Fenced frames are handled above.
      NOTREACHED();
  }
}

// Returns true if the parent's COEP policy `parent_coep` should block a child
// embedded in an <iframe> loaded with `child_coep` policy. The
// `is_credentialless` parameter reflects whether the child will be loaded as a
// credentialless document.
bool CoepBlockIframe(network::mojom::CrossOriginEmbedderPolicyValue parent_coep,
                     network::mojom::CrossOriginEmbedderPolicyValue child_coep,
                     bool is_credentialless) {
  return !is_credentialless &&
         (network::CompatibleWithCrossOriginIsolated(parent_coep) &&
          !network::CompatibleWithCrossOriginIsolated(child_coep));
}

// Computes the history offset of the new document compared to the current one.
int EstimateHistoryOffset(NavigationController& controller,
                          bool should_replace_current_entry) {
  if (should_replace_current_entry)
    return 0;

  int current_index = controller.GetLastCommittedEntryIndex();
  int pending_index = controller.GetPendingEntryIndex();

  // +1 for non history navigation.
  if (current_index == -1 || pending_index == -1)
    return 1;

  return pending_index - current_index;
}

bool IsDocumentToCommitAnonymous(FrameTreeNode* frame,
                                 bool is_synchronous_about_blank_navigation) {
  // FencedFrame do not propagate the credentialless bit deeper.
  // In particular, it means their future response will have to adhere to COEP.
  if (frame->IsFencedFrameRoot())
    return false;

  RenderFrameHostImpl* current_document = frame->current_frame_host();
  RenderFrameHostImpl* parent_document = frame->parent();

  // The synchronous about:blank navigation preserves the state of the initial
  // empty document.
  // TODO(https://github.com/whatwg/html/issues/6863): Remove the synchronous
  // about:blank navigation.
  if (is_synchronous_about_blank_navigation)
    return current_document->IsCredentialless();

  // The document to commit will be credentialless if either the iframe element
  // has the 'credentialless' attribute set or the parent document is
  // credentialless.
  bool parent_is_credentialless =
      parent_document && parent_document->IsCredentialless();
  return parent_is_credentialless || frame->Credentialless();
}

// Returns the "loading" URL in the renderer. This tries to replicate
// RenderFrameImpl::GetLoadingUrl(). This might return a different URL from
// what we get when calling GetLastCommittedURL() on `rfh`, in case the
// document had changed its URL through document.open() before, or
// when calling last_document_url_in_renderer(), in case of error pages and
// loadDataWithBaseURL documents.
// This function should only be used to preserve calculations that were
// previously done in the renderer but got moved to the browser (e.g. URL
// comparisons to determine if a navigation should do a replacement or not).
const GURL& GetLastLoadingURLInRendererForNavigationReplacement(
    RenderFrameHostImpl* rfh) {
  // Handle some special cases:
  // - The "loading URL" for an error page commit is the URL that it failed to
  // load. This will be retained as long as the document stays the same.
  // - For loadDataWithBaseURL() navigations the "loading URL" will be the
  // last committed URL (the data: URL). This will also be retained as long as
  // the document stays the same.
  if (rfh->IsErrorDocument() ||
      rfh->was_loaded_from_load_data_with_base_url()) {
    return rfh->GetLastCommittedURL();
  }

  // Otherwise, return the last document URL.
  return rfh->last_document_url_in_renderer();
}

bool IsOptedInFencedFrame(const net::HttpResponseHeaders& http_headers) {
  network::mojom::SupportsLoadingModePtr result =
      network::ParseSupportsLoadingMode(http_headers);
  return !result.is_null() &&
         base::Contains(result->supported_modes,
                        network::mojom::LoadingMode::kFencedFrame);
}

// If there are any "Origin-Trial" headers on the |response|, persist those
// that correspond to persistent origin trials, provided the tokens are valid.
void PersistOriginTrialsFromHeaders(
    const url::Origin& origin,
    const url::Origin& partition_origin,
    const network::mojom::URLResponseHead* response,
    BrowserContext* browser_context,
    ukm::SourceId source_id) {
  // It is not possible to serialize opaque origins, so we cannot save any
  // information for them.
  if (origin.opaque())
    return;

  // Skip About:blank, about:srcdoc and a few other URLs, because they can't
  // have any Origin-Trial header.
  if (!response || !response->headers)
    return;

  OriginTrialsControllerDelegate* origin_trials_delegate =
      browser_context->GetOriginTrialsControllerDelegate();
  if (!origin_trials_delegate)
    return;

  std::vector<std::string> tokens =
      GetOriginTrialHeaderValues(response->headers.get());
  origin_trials_delegate->PersistTrialsFromTokens(
      origin, partition_origin, tokens, base::Time::Now(), source_id);
}

struct TopicsHeaderValueResult {
  bool topics_eligible = false;
  std::optional<std::string> header_value;
};

// Returns the topics header for a navigation request. Returns std::nullopt if
// the request isn't eligible for topics. This should align with the handling in
// `GetTopicsHeaderValueForSubresourceRequest()`.
TopicsHeaderValueResult GetTopicsHeaderValueForNavigationRequest(
    FrameTreeNode* frame_tree_node,
    const GURL& url) {
  // Skip if the <iframe> does not have the "browsingtopics" opt-in attribute.
  if (!frame_tree_node->browsing_topics()) {
    return TopicsHeaderValueResult{};
  }

  RenderFrameHostImpl* rfh = frame_tree_node->current_frame_host();

  // Skip top frame navigation.
  // TODO(crbug.com/40260337): This should be checked at the mojom boundary of
  // RenderFrameHostImpl::DidChangeIframeAttributes, and should be a DCHECK
  // here.
  if (rfh->is_main_frame()) {
    return {};
  }

  // Skip fenced frames.
  if (rfh->IsNestedWithinFencedFrame()) {
    return {};
  }

  // Skip inactive pages (e.g. prerendered pages).
  if (!rfh->GetPage().IsPrimary()) {
    return {};
  }

  url::Origin origin = url::Origin::Create(url);
  if (origin.opaque()) {
    return {};
  }

  if (!network::IsOriginPotentiallyTrustworthy(origin)) {
    return {};
  }

  const network::PermissionsPolicy* parent_policy =
      rfh->GetParent()->GetPermissionsPolicy();

  DCHECK(parent_policy);

  if (!parent_policy->IsFeatureEnabledForOrigin(
          network::mojom::PermissionsPolicyFeature::kBrowsingTopics, origin) ||
      !parent_policy->IsFeatureEnabledForOrigin(
          network::mojom::PermissionsPolicyFeature::
              kBrowsingTopicsBackwardCompatible,
          origin)) {
    return {};
  }

  std::vector<blink::mojom::EpochTopicPtr> topics;
  bool topics_eligible = GetContentClient()->browser()->HandleTopicsWebApi(
      origin, rfh->GetMainFrame(),
      browsing_topics::ApiCallerSource::kIframeAttribute,
      /*get_topics=*/true,
      /*observe=*/false, topics);

  int num_versions_in_epochs =
      topics_eligible
          ? GetContentClient()->browser()->NumVersionsInTopicsEpochs(
                rfh->GetMainFrame())
          : 0;

  return {
      .topics_eligible = topics_eligible,
      .header_value = DeriveTopicsHeaderValue(topics, num_versions_in_epochs)};
}

ukm::SourceId GetPageUkmSourceId(FrameTreeNode* frame_tree_node) {
  CHECK(frame_tree_node);
  RenderFrameHost* render_frame_host = frame_tree_node->current_frame_host();
  CHECK(render_frame_host);
  // Our data collection policy disallows collecting UKMs while prerendering.
  // So, return kInvalidSourceId when the page is in the prerendering state.
  // See //content/browser/preloading/prerender/README.md and ask the team to
  // explore options to record data for prerendering pages.
  if (render_frame_host->IsInLifecycleState(
          RenderFrameHost::LifecycleState::kPrerendering)) {
    return ukm::kInvalidSourceId;
  }
  return render_frame_host->GetPageUkmSourceId();
}

bool IsMhtmlMimeType(const std::string& mime_type) {
  return mime_type == "multipart/related" || mime_type == "message/rfc822";
}

network::mojom::WebSandboxFlags GetSandboxFlagsInitiator(
    const std::optional<blink::LocalFrameToken>& frame_token,
    int initiator_process_id,
    StoragePartitionImpl* storage_partition) {
  if (!frame_token) {
    return network::mojom::WebSandboxFlags::kNone;
  }

  // Even if the navigation was initiated from an unload handler and the
  // RenderFrameHost is gone, its associated PolicyContainerHost should be
  // available by design.
  //
  // Note: See https://crbug.com/1473165. The "design" is currently not 100%
  // achieved. The PolicyContainer might be missing when the navigation is
  // initiated from RenderViewContextMenu::ExecuteCommand(...).
  const PolicyContainerHost* policy_container_host =
      RenderFrameHostImpl::GetPolicyContainerHost(
          base::OptionalToPtr(frame_token), initiator_process_id,
          storage_partition);
  if (!policy_container_host) {
    return network::mojom::WebSandboxFlags::kNone;
  }

  return policy_container_host->policies().sandbox_flags;
}

bool IsSharedStorageWritableEligibleForNavigationRequest(
    FrameTreeNode* frame_tree_node,
    const GURL& url) {
  // False if the <iframe> does not have the "sharedstoragewritable" opt-in
  // attribute.
  if (!frame_tree_node->shared_storage_writable_opted_in()) {
    return false;
  }

  // Only child frames should have the `sharedstoragewritable` attribute set to
  // true.
  CHECK(!frame_tree_node->IsMainFrame());

  // Apart from fenced frames' frame trees, skip non-primary pages (e.g.
  // prerendered pages).
  if (frame_tree_node->fenced_frame_status() !=
          RenderFrameHostImpl::FencedFrameStatus::
              kIframeNestedWithinFencedFrame &&
      (!frame_tree_node->frame_tree().is_primary() ||
       !frame_tree_node->frame_tree().root()->IsOutermostMainFrame())) {
    return false;
  }

  url::Origin origin = url::Origin::Create(url);
  if (origin.opaque()) {
    return false;
  }

  if (!network::IsOriginPotentiallyTrustworthy(origin)) {
    return false;
  }

  CHECK(frame_tree_node->parent());
  const network::PermissionsPolicy* parent_policy =
      frame_tree_node->parent()->GetPermissionsPolicy();

  DCHECK(parent_policy);
  return parent_policy->IsFeatureEnabledForOrigin(
      network::mojom::PermissionsPolicyFeature::kSharedStorage, origin);
}

std::optional<base::SafeRef<RenderFrameHostImpl>>
GetRenderFrameHostForBackForwardCacheRestore(FrameTreeNode* frame_tree_node,
                                             NavigationEntryImpl* entry) {
  if (!entry) {
    return std::nullopt;
  }

  auto restored_entry = frame_tree_node->navigator()
                            .controller()
                            .GetBackForwardCache()
                            .GetOrEvictEntry(entry->GetUniqueID());
  if (!restored_entry.has_value()) {
    // If there is no active BFCache entry, we can't use the RFH from the
    // BFCache entry for the history navigation.
    return std::nullopt;
  }

  RenderFrameHostImpl* restored_rfh =
      restored_entry.value()->render_frame_host();

  // If there is an ongoing BFCache NavigationRequest with the same entry, that
  // NavigationRequest will be cancelled, and trigger an eviction from the
  // NavigationRequest destructor (see comment there for details). So, we can't
  // restore the to-be-evicted entry anymore.
  NavigationRequest* previous_navigation_request =
      frame_tree_node->navigation_request();
  if (previous_navigation_request &&
      previous_navigation_request->IsServedFromBackForwardCache() &&
      previous_navigation_request
              ->GetRenderFrameHostRestoredFromBackForwardCache() ==
          restored_rfh) {
    // Since the BFCache entry won't be restored, we evict it here with
    // `kNavigationCancelledWhileRestoring` so that the NavigationRequest
    // won't end up with not restored with no reason (or `Unknown` will be
    // added instead).
    // TODO(crbug.com/40283427): Only evict BFCache if the
    // `BackForwardCacheCommitDeferringCondition`, which unfreezes the
    // page and disables the eviction on the renderer side, is completed.
    restored_rfh->EvictFromBackForwardCacheWithReason(
        BackForwardCacheMetrics::NotRestoredReason::
            kNavigationCancelledWhileRestoring);
    return std::nullopt;
  }

  if (!frame_tree_node->IsMainFrame()) {
    // We have a matching BFCache entry for a subframe navigation. This
    // shouldn't happen as we should've triggered deletion of BFCache
    // entries that have the same BrowsingInstance as the current document.
    // See https://crbug.com/1250111.
    CaptureTraceForNavigationDebugScenario(
        DebugScenario::kDebugBackForwardCacheEntryExistsOnSubframeHistoryNav);
    return std::nullopt;
  }

  return restored_rfh->GetSafeRef();
}

void MaybePrewarmHttpDiskCache(
    BrowserContext& browser_context,
    const GURL& url,
    const std::optional<url::Origin>& initiator_origin) {
  if (!base::FeatureList::IsEnabled(
          blink::features::kHttpDiskCachePrewarming) ||
      !blink::features::kHttpDiskCachePrewarmingTriggerOnNavigation.Get()) {
    return;
  }

  if (!url.is_valid() || !url.SchemeIsHTTPOrHTTPS()) {
    return;
  }

  GetContentClient()->browser()->MaybePrewarmHttpDiskCache(
      browser_context, initiator_origin, url);
}

// Returns true in cases where an attempted download will end up replacing the
// current document anyway, due to showing an error page.
bool IsFailedDownload(bool is_download,
                      const net::HttpResponseHeaders* headers) {
  return is_download && headers &&
         !network::IsSuccessfulStatus(headers->response_code());
}

// Returns if the given `rfh` should be evicted from BackForwardCache due to
// ongoing navigation.
bool MaybeEvictFromBackForwardCacheBySubframeNavigation(
    RenderFrameHostImpl* rfh) {
  if (rfh->GetParentOrOuterDocument() &&
      rfh->GetLifecycleState() ==
          RenderFrameHost::LifecycleState::kInBackForwardCache) {
    // Normally, ongoing subframe navigations will be deferred by
    // `BackForwardCacheSubframeNavigationThrottle` before they reach this
    // point, if the page the subframe is on gets BFCached.
    //
    // However, it's possible for subframe navigations to end up here while its
    // page is BFCached, if at the time the navigation went through
    // `BackForwardCacheSubframeNavigationThrottle::WillStartRequest()` or
    // BackForwardCacheSubframeNavigationThrottle::WillCommitWithoutUrlLoader(),
    // the page is not BFCached yet, but then the page gets BFCached in between
    // that time and when this function is called.
    //
    // Outside of tests, this should not be possible, as
    // `BackForwardCacheSubframeNavigationThrottle` are the last throttles to be
    // registered/run. However, in tests, the last throttles to run are
    // test-only throttles, which can introduce an asynchronous step, making it
    // possible for the page to enter BFCache during that time. In that case, we
    // shouldn't continue processing the navigation in the subframe and need to
    // evict the page from BFCache.
    rfh->EvictFromBackForwardCacheWithReason(
        BackForwardCacheMetrics::NotRestoredReason::kSubframeIsNavigating);

    // DO NOT ADD CODE after this. The previous call has destroyed the
    // NavigationRequest.
    return true;
  }
  return false;
}

net::StorageAccessApiStatus ShouldLoadWithStorageAccess(
    const blink::mojom::BeginNavigationParams& begin_params,
    const blink::mojom::CommonNavigationParams& common_params,
    const RenderFrameHostImpl* previous_document_rfh,
    bool did_encounter_cross_origin_redirect,
    const GURL response_url,
    const network::mojom::URLResponseHead* response) {
  // Storage Access API Headers:
  // https://github.com/privacycg/storage-access-headers
  //
  // A server can opt-in to provide storage access to a document by setting the
  // `Activate-Storage-Access: load` header, provided that the user has already
  // granted the relevant `storage-access` permission.
  //
  // Note: As of today, `about:blank`, `about:srcdoc`, and MHTML-iframe do not
  // have a response.
  if (response && response->load_with_storage_access) {
    // TODO(https://crbug.com/344608182): this ought to use a dedicated status,
    // since the JS API was *not* used to get storage access here.
    return net::StorageAccessApiStatus::kAccessViaAPI;
  }

  // Storage Access API: https://privacycg.github.io/storage-access/#navigation
  //
  // If a document has storage access, and initiates a navigation in the same
  // frame toward a document from the same origin, the `has storage access` bit
  // is inherited.
  //
  // This doesn't hold if there is a cross-origin redirect in between.
  //
  // Note: `begin_params` and `common_params` are not trusted, so we have to
  // check the frame token.
  switch (begin_params.storage_access_api_status) {
    case net::StorageAccessApiStatus::kNone:
      return net::StorageAccessApiStatus::kNone;
    case net::StorageAccessApiStatus::kAccessViaAPI:
      return common_params.initiator_origin &&
                     common_params.initiator_origin->IsSameOriginWith(
                         response_url) &&
                     begin_params.initiator_frame_token &&
                     begin_params.initiator_frame_token ==
                         previous_document_rfh->GetFrameToken() &&
                     !did_encounter_cross_origin_redirect
                 ? begin_params.storage_access_api_status
                 : net::StorageAccessApiStatus::kNone;
  }
}

// The sampling rate for UKM.
constexpr double kUkmSamplingRate = 0.001;

}  // namespace

NavigationRequest::PrerenderActivationNavigationState::
    PrerenderActivationNavigationState() = default;
NavigationRequest::PrerenderActivationNavigationState::
    ~PrerenderActivationNavigationState() = default;

// static
std::unique_ptr<NavigationRequest> 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,
    std::optional<std::u16string> embedder_shared_storage_context) {
  auto request = Create(
      frame_tree_node, std::move(common_params), std::move(commit_params),
      /*browser_initiated=*/true, was_opener_suppressed,
      std::nullopt /* initiator_frame_token */,
      ChildProcessHost::kInvalidUniqueID /* initiator_process_id */,
      extra_headers, frame_entry, entry, is_form_submission,
      std::move(navigation_ui_data), impression,
      blink::mojom::NavigationInitiatorActivationAndAdStatus::
          kDidNotStartWithTransientActivation,
      is_pdf, is_embedder_initiated_fenced_frame_navigation,
      /*is_container_initiated=*/false, /*has_rel_opener=*/false,
      net::StorageAccessApiStatus::kNone, embedder_shared_storage_context);
  // It is only possible for a null NavigationRequest to be returned if an
  // initiator_frame_token is provided.
  CHECK(request);
  return request;
}

// static
std::unique_ptr<NavigationRequest> 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,
    bool is_container_initiated,
    bool has_rel_opener,
    net::StorageAccessApiStatus storage_access_api_status,
    std::optional<std::u16string> embedder_shared_storage_context) {
  TRACE_EVENT("navigation", "NavigationRequest::Create", "browser_initiated",
              browser_initiated);

  common_params->request_destination =
      GetDestinationFromFrameTreeNode(frame_tree_node);

  auto navigation_params = blink::mojom::BeginNavigationParams::New(
      initiator_frame_token, extra_headers, net::LOAD_NORMAL,
      false /* skip_service_worker */,
      blink::mojom::RequestContextType::LOCATION,
      blink::mojom::MixedContentContextType::kBlockable, is_form_submission,
      false /* was_initiated_by_link_click */,
      blink::mojom::ForceHistoryPush::kNo, GURL() /* searchable_form_url */,
      std::string() /* searchable_form_encoding */,
      GURL() /* client_side_redirect_url */,
      std::nullopt /* devtools_initiator_info */,
      nullptr /* trust_token_params */, impression,
      base::TimeTicks() /* renderer_before_unload_start */,
      base::TimeTicks() /* renderer_before_unload_end */,
      initiator_activation_and_ad_status, is_container_initiated,
      storage_access_api_status, has_rel_opener);

  // Shift-Reload forces bypassing caches and service workers.
  if (common_params->navigation_type ==
      blink::mojom::NavigationType::RELOAD_BYPASSING_CACHE) {
    navigation_params->load_flags |= net::LOAD_BYPASS_CACHE;
    navigation_params->skip_service_worker = true;
  }

  scoped_refptr<network::SharedURLLoaderFactory> blob_url_loader_factory;
  if (frame_entry) {
    blob_url_loader_factory = frame_entry->blob_url_loader_factory();

    if (common_params->url.SchemeIsBlob() && !blob_url_loader_factory) {
      // If this navigation entry came from session history then the blob
      // factory would have been cleared in
      // NavigationEntryImpl::ResetForCommit(). This is avoid keeping large
      // blobs alive unnecessarily and the spec is unclear. So create a new blob
      // factory which will work if the blob happens to still be alive,
      // resolving the blob URL in the site instance it was loaded in.
      blob_url_loader_factory =
          ChromeBlobStorageContext::URLLoaderFactoryForUrl(
              frame_tree_node->navigator()
                  .controller()
                  .GetBrowserContext()
                  ->GetStoragePartition(frame_entry->site_instance()),
              common_params->url);
    }
  }

  // Ensure that top-level navigations initiated from fenced frames (such as
  // _unfencedTop, pop-ups, and "Open Link in...") fail if the fenced frame's
  // network access is revoked. Some of these paths have additional checks for
  // UX reasons (see: RenderFrameHostImpl::CreateNewWindow and
  // RenderViewContextMenu::IsCommandIdEnabled). This check is only needed for
  // navigations that escape the fenced frame boundary, as the target will have
  // no knowledge of the fenced frame's network revocation nonce. This check
  // does not exist in CreateRendererInitiated() because that path is not hit
  // for navigations that cross fenced frame boundaries.
  if (initiator_frame_token) {
    // It is okay to use the current frame host's storage partition because
    // the storage partition does not change over the lifetime of the fenced
    // frame.
    std::optional<bool> is_untrusted_network_disabled =
        RenderFrameHostImpl::GetIsUntrustedNetworkDisabled(
            base::OptionalToPtr(initiator_frame_token), initiator_process_id,
            static_cast<StoragePartitionImpl*>(
                frame_tree_node->current_frame_host()->GetStoragePartition()));
    if (is_untrusted_network_disabled == true) {
      frame_tree_node->current_frame_host()->AddMessageToConsole(
          blink::mojom::ConsoleMessageLevel::kError,
          "Navigations cannot be initiated from a fenced frame after its "
          "network has been disabled.");
      return nullptr;
    }
  }

  std::unique_ptr<NavigationRequest> navigation_request(new NavigationRequest(
      frame_tree_node, std::move(common_params), std::move(navigation_params),
      std::move(commit_params), browser_initiated,
      false /* from_begin_navigation */,
      false /* is_synchronous_renderer_commit */, frame_entry, entry,
      std::move(navigation_ui_data), std::move(blob_url_loader_factory),
      mojo::NullAssociatedRemote(),
      nullptr /* prefetched_signed_exchange_cache */,
      GetRenderFrameHostForBackForwardCacheRestore(frame_tree_node, entry),
      initiator_process_id, was_opener_suppressed, is_pdf,
      is_embedder_initiated_fenced_frame_navigation,
      mojo::NullReceiver() /* renderer_cancellation_listener */,
      embedder_shared_storage_context));

  return navigation_request;
}

// static
std::unique_ptr<NavigationRequest> 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) {
  TRACE_EVENT("navigation", "NavigationRequest::CreateRendererInitiated");
  // Only normal navigations to a different document or reloads are expected.
  // - Renderer-initiated same document navigations never start in the browser.
  // - Restore-navigations are always browser-initiated.
  // - History-navigations use the browser-initiated path, even the ones that
  //   are initiated by a javascript script.
  DCHECK(NavigationTypeUtils::IsReload(common_params->navigation_type) ||
         common_params->navigation_type ==
             blink::mojom::NavigationType::DIFFERENT_DOCUMENT);

  common_params->request_destination =
      GetDestinationFromFrameTreeNode(frame_tree_node);

  // TODO(clamy): See if the navigation start time should be measured in the
  // renderer and sent to the browser instead of being measured here.
  blink::mojom::CommitNavigationParamsPtr commit_params =
      blink::mojom::CommitNavigationParams::New(
          url::Origin(),
          // The correct storage key will be computed before committing the
          // navigation.
          blink::StorageKey(), override_user_agent,
          /*redirects=*/std::vector<GURL>(),
          /*redirect_response=*/
          std::vector<network::mojom::URLResponseHeadPtr>(),
          /*redirect_infos=*/std::vector<net::RedirectInfo>(),
          /*post_content_type=*/std::string(), common_params->url,
          common_params->method,
          /*can_load_local_resources=*/false,
          /*page_state=*/std::string(),
          /*nav_entry_id=*/0,
          /*subframe_unique_names=*/base::flat_map<std::string, bool>(),
          /*intended_as_new_entry=*/false,
          // Set to -1 because history-navigations do not use this path. See
          // comments above.
          /*pending_history_list_index=*/-1, current_history_list_index,
          current_history_list_length,
          /*was_discarded=*/false,
          /*is_view_source=*/false,
          /*should_clear_history_list=*/false,
          /*navigation_timing=*/blink::mojom::NavigationTiming::New(),
          blink::mojom::WasActivatedOption::kUnknown,
          /*navigation_token=*/base::UnguessableToken::Create(),
          /*prefetched_signed_exchanges=*/
          std::vector<blink::mojom::PrefetchedSignedExchangeInfoPtr>(),
#if BUILDFLAG(IS_ANDROID)
          /*data_url_as_string=*/std::string(),
#endif
          /*is_browser_initiated=*/false,
          /*has_ua_visual_transition*/ false,
          /*document_ukm_source_id=*/ukm::kInvalidSourceId,
          frame_tree_node->pending_frame_policy(),
          /*force_enabled_origin_trials=*/std::vector<std::string>(),
          /*origin_agent_cluster=*/false,
          /*origin_agent_cluster_left_as_default=*/true,
          /*enabled_client_hints=*/
          std::vector<network::mojom::WebClientHintsType>(),
          /*is_cross_site_cross_browsing_context_group=*/false,
          /*should_have_sticky_user_activation=*/false,
          /*old_page_info=*/nullptr, /*http_response_code=*/-1,
          blink::mojom::NavigationApiHistoryEntryArrays::New(),
          /*early_hints_preloaded_resources=*/std::vector<GURL>(),
          // This timestamp will be populated when the commit IPC is sent.
          /*commit_sent=*/base::TimeTicks(), /*srcdoc_value=*/std::string(),
          /*should_load_data_url=*/false,
          /*ancestor_or_self_has_cspee=*/
          frame_tree_node->AncestorOrSelfHasCSPEE(),
          /*reduced_accept_language=*/std::string(),
          /*navigation_delivery_type=*/
          network::mojom::NavigationDeliveryType::kDefault,
          /*view_transition_state=*/std::nullopt,
          /*soft_navigation_heuristics_task_id=*/std::nullopt,
          /*modified_runtime_features=*/
          base::flat_map<::blink::mojom::RuntimeFeature, bool>(),
          /*fenced_frame_properties=*/std::nullopt,
          /*not_restored_reasons=*/nullptr,
          /*load_with_storage_access=*/
          net::StorageAccessApiStatus::kNone,
          /*browsing_context_group_info=*/std::nullopt,
          /*lcpp_hint=*/nullptr, blink::CreateDefaultRendererContentSettings(),
          /*cookie_deprecation_label=*/std::nullopt,
          /*visited_link_salt=*/std::nullopt,
          /*local_surface_id=*/std::nullopt,
          frame_tree_node->current_frame_host()->GetCachedPermissionStatuses(),
          /*should_skip_screenshot=*/false,
          /*force_new_document_sequence_number=*/false,
          /*navigation_metrics_token=*/base::UnguessableToken::Create(),
          /*commit_target_frame_token=*/std::nullopt);

  // CreateRendererInitiated() should only be triggered when the navigation is
  // initiated by a frame in the same process.
  // TODO(crbug.com/40686861): Find a way to DCHECK that the routing ID
  // is from the current RFH.
  int initiator_process_id =
      frame_tree_node->current_frame_host()->GetProcess()->GetDeprecatedID();

  // `was_opener_suppressed` can be true for renderer initiated navigations, but
  // only in cases which get routed through `CreateBrowserInitiated()` instead.
  std::unique_ptr<NavigationRequest> navigation_request(new NavigationRequest(
      frame_tree_node, std::move(common_params), std::move(begin_params),
      std::move(commit_params),
      false,    // browser_initiated
      true,     // from_begin_navigation
      false,    // is_synchronous_renderer_commit
      nullptr,  // frame_entry
      entry,
      nullptr,  // navigation_ui_data
      std::move(blob_url_loader_factory), std::move(navigation_client),
      std::move(prefetched_signed_exchange_cache),
      std::nullopt,  // rfh_restored_from_back_forward_cache
      initiator_process_id,
      /*was_opener_suppressed=*/false, /*is_pdf=*/false,
      /*is_embedder_initiated_fenced_frame_navigation=*/false,
      std::move(renderer_cancellation_listener)));

  return navigation_request;
}

// static
std::unique_ptr<NavigationRequest>
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) {
  TRACE_EVENT("navigation",
              "NavigationRequest::CreateForSynchronousRendererCommit");
  // TODO(clamy): Improve the *NavigationParams and *CommitParams to avoid
  // copying so many parameters here.
  blink::mojom::CommonNavigationParamsPtr common_params =
      blink::mojom::CommonNavigationParams::New(
          url,
          // TODO(nasko): Investigate better value to pass for
          // |initiator_origin|.
          origin, initiator_base_url, std::move(referrer), transition,
          is_same_document ? blink::mojom::NavigationType::SAME_DOCUMENT
                           : blink::mojom::NavigationType::DIFFERENT_DOCUMENT,
          blink::NavigationDownloadPolicy(), should_replace_current_entry,
          GURL() /* base_url_for_data_url*/, actual_navigation_start,
          base::TimeTicks::Now() /* navigation_start */, method /* method */,
          nullptr /* post_data */, network::mojom::SourceLocation::New(),
          false /* started_from_context_menu */, has_transient_activation,
          false /* has_text_fragment_token */,
          network::mojom::CSPDisposition::CHECK,
          std::vector<int>() /* initiator_origin_trial_features */,
          std::string() /* href_translate */,
          false /* is_history_navigation_in_new_child_frame */,
          base::TimeTicks::Now() /* input_start */,
          network::mojom::RequestDestination::kEmpty);
  // Note that some params are set to default values (e.g. page_state set to
  // the default blink::PageState()) even if the DidCommit message that came
  // from the renderer contained relevant info that can be used to fill the
  // params, because setting those values don't match with the pattern used
  // by navigations that went through the browser (e.g. page_state is only
  // set in CommitNavigationParams of history navigations) or these values are
  // not used by the browser after commit.
  blink::mojom::CommitNavigationParamsPtr commit_params =
      blink::mojom::CommitNavigationParams::New(
          url::Origin(),
          // The correct storage key is computed right after creating the
          // NavigationRequest below.
          blink::StorageKey(), is_overriding_user_agent, redirects,
          /*redirect_response=*/
          std::vector<network::mojom::URLResponseHeadPtr>(),
          /*redirect_infos=*/std::vector<net::RedirectInfo>(),
          /*post_content_type=*/std::string(), original_url,
          /*original_method=*/method,
          /*can_load_local_resources=*/false,
          /*page_state=*/std::string(),
          /*nav_entry_id=*/0,
          /*subframe_unique_names=*/base::flat_map<std::string, bool>(),
          /*intended_as_new_entry=*/false,
          /*pending_history_list_index=*/-1,
          /*current_history_list_index=*/-1,
          /*current_history_list_length=*/-1,
          /*was_discarded=*/false,
          /*is_view_source=*/false,
          /*should_clear_history_list=*/false,
          /*navigation_timing=*/blink::mojom::NavigationTiming::New(),
          blink::mojom::WasActivatedOption::kUnknown,
          /*navigation_token=*/base::UnguessableToken::Create(),
          /*prefetched_signed_exchanges=*/
          std::vector<blink::mojom::PrefetchedSignedExchangeInfoPtr>(),
#if BUILDFLAG(IS_ANDROID)
          /*data_url_as_string=*/std::string(),
#endif
          /*is_browser_initiated=*/false,
          /*has_ua_visual_transition*/ false,
          /*document_ukm_source_id=*/ukm::kInvalidSourceId,
          frame_tree_node->pending_frame_policy(),
          /*force_enabled_origin_trials=*/std::vector<std::string>(),
          /*origin_agent_cluster=*/false,
          /*origin_agent_cluster_left_as_default=*/true,
          /*enabled_client_hints=*/
          std::vector<network::mojom::WebClientHintsType>(),
          /*is_cross_site_cross_browsing_context_group=*/false,
          /*should_have_sticky_user_activation=*/false,
          /*old_page_info=*/nullptr, http_response_code,
          blink::mojom::NavigationApiHistoryEntryArrays::New(),
          /*early_hints_preloaded_resources=*/std::vector<GURL>(),
          // This timestamp will be populated when the commit IPC is sent.
          /*commit_sent=*/base::TimeTicks(), /*srcdoc_value=*/std::string(),
          /*should_load_data_url=*/false,
          /*ancestor_or_self_has_cspee=*/
          frame_tree_node->AncestorOrSelfHasCSPEE(),
          /*reduced_accept_language=*/std::string(),
          /*navigation_delivery_type=*/
          network::mojom::NavigationDeliveryType::kDefault,
          /*view_transition_state=*/std::nullopt,
          /*soft_navigation_heuristics_task_id=*/std::nullopt,
          /*modified_runtime_features=*/
          base::flat_map<::blink::mojom::RuntimeFeature, bool>(),
          /*fenced_frame_properties=*/std::nullopt,
          /*not_restored_reasons=*/nullptr,
          /*load_with_storage_access=*/
          net::StorageAccessApiStatus::kNone,
          /*browsing_context_group_info=*/std::nullopt,
          /*lcpp_hint=*/nullptr, blink::CreateDefaultRendererContentSettings(),
          /*cookie_deprecation_label=*/std::nullopt,
          /*visited_link_salt=*/std::nullopt,
          /*local_surface_id=*/std::nullopt,
          render_frame_host->GetCachedPermissionStatuses(),
          /*should_skip_screenshot=*/false,
          /*force_new_document_sequence_number=*/false,
          /*navigation_metrics_token=*/base::UnguessableToken::Create(),
          /*commit_target_frame_token=*/std::nullopt);
  blink::mojom::BeginNavigationParamsPtr begin_params =
      blink::mojom::BeginNavigationParams::New();
  std::unique_ptr<NavigationRequest> navigation_request(new NavigationRequest(
      frame_tree_node, std::move(common_params), std::move(begin_params),
      std::move(commit_params), false /* browser_initiated */,
      false /* from_begin_navigation */,
      true /* is_synchronous_renderer_commit */,
      nullptr /* frame_navigation_entry */, nullptr /* navigation_entry */,
      nullptr /* navigation_ui_data */, nullptr /* blob_url_loader_factory */,
      mojo::NullAssociatedRemote(),
      nullptr /* prefetched_signed_exchange_cache */,
      std::nullopt /* rfh_restored_from_back_forward_cache */,
      ChildProcessHost::kInvalidUniqueID /* initiator_process_id */,
      false /* was_opener_suppressed */, false /* is_pdf */));

  std::optional<base::UnguessableToken> nonce = render_frame_host->ComputeNonce(
      navigation_request->is_credentialless(),
      navigation_request->ComputeFencedFrameNonce());
  url::Origin top_level_origin =
      render_frame_host->ComputeTopFrameOrigin(origin);
  if (nonce) {
    // If the nonce isn't null, we can use the simpler form of the constructor.
    navigation_request->commit_params_->storage_key =
        blink::StorageKey::CreateWithNonce(origin, *nonce);
  } else {
    // Otherwise we need to derive the top_level_site and ancestor_chain_bit.
    net::SchemefulSite top_level_site(top_level_origin);

    blink::mojom::AncestorChainBit ancestor_chain_bit =
        blink::mojom::AncestorChainBit::kSameSite;
    if (render_frame_host->ComputeSiteForCookies().IsNull() ||
        !top_level_site.IsSameSiteWith(origin) || !top_level_site.opaque() ||
        origin.opaque()) {
      ancestor_chain_bit = blink::mojom::AncestorChainBit::kCrossSite;
    }

    navigation_request->commit_params_->storage_key =
        blink::StorageKey::Create(origin, top_level_site, ancestor_chain_bit);
  }
  navigation_request->render_frame_host_ = render_frame_host->GetSafeRef();
  navigation_request->coep_reporter_ = std::move(coep_reporter);
  navigation_request->dip_reporter_ = std::move(dip_reporter);
  navigation_request->isolation_info_for_subresources_ =
      isolation_info_for_subresources;
  navigation_request->associated_rfh_type_ =
      AssociatedRenderFrameHostType::CURRENT;
  navigation_request->StartNavigation();
  DCHECK(navigation_request->IsNavigationStarted());

  return navigation_request;
}

// static class variable used to generate unique navigation ids for
// NavigationRequest.
int64_t NavigationRequest::unique_id_counter_ = 0;

NavigationRequest::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_entry,
    NavigationEntryImpl* 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,
    mojo::PendingReceiver<mojom::NavigationRendererCancellationListener>
        renderer_cancellation_listener,
    std::optional<std::u16string> embedder_shared_storage_context)
    : frame_tree_node_(frame_tree_node),
      is_synchronous_renderer_commit_(is_synchronous_renderer_commit),
      common_params_(std::move(common_params)),
      begin_params_(std::move(begin_params)),
      commit_params_(std::move(commit_params)),
      navigation_ui_data_(std::move(navigation_ui_data)),
      blob_url_loader_factory_(std::move(blob_url_loader_factory)),
      restore_type_(entry ? entry->restore_type() : RestoreType::kNotRestored),
      // Some navigations, such as renderer-initiated subframe navigations,
      // won't have a NavigationEntryImpl. Set |reload_type_| if applicable
      // for them.
      reload_type_(
          entry ? entry->reload_type()
                : NavigationTypeToReloadType(common_params_->navigation_type)),
      nav_entry_id_(entry ? entry->GetUniqueID() : 0),
      from_begin_navigation_(from_begin_navigation),
      site_info_(
          frame_tree_node_->navigator().controller().GetBrowserContext()),
      navigation_entry_offset_(
          EstimateHistoryOffset(frame_tree_node_->navigator().controller(),
                                common_params_->should_replace_current_entry)),
      prefetched_signed_exchange_cache_(
          std::move(prefetched_signed_exchange_cache)),
      rfh_restored_from_back_forward_cache_(
          rfh_restored_from_back_forward_cache),
      is_back_forward_cache_restore_(
          rfh_restored_from_back_forward_cache.has_value()),
      // Store the old RenderFrameHost id at request creation to be used later.
      current_render_frame_host_id_at_construction_(
          frame_tree_node->current_frame_host()->GetGlobalId()),
      initiator_frame_token_(begin_params_->initiator_frame_token),
      initiator_process_id_(initiator_process_id),
      sandbox_flags_initiator_(GetSandboxFlagsInitiator(
          initiator_frame_token_,
          initiator_process_id,
          static_cast<StoragePartitionImpl*>(
              GetStoragePartitionWithCurrentSiteInfo()))),
      was_opener_suppressed_(was_opener_suppressed),
      is_credentialless_(
          IsDocumentToCommitAnonymous(frame_tree_node,
                                      is_synchronous_renderer_commit)),
      previous_page_ukm_source_id_(GetPageUkmSourceId(frame_tree_node_)),
      cookie_observers_(std::make_unique<CookieAccessObservers>(
          base::BindRepeating(&NavigationRequest::NotifyCookiesAccessed,
                              base::Unretained(this)))),
      is_pdf_(is_pdf),
      is_embedder_initiated_fenced_frame_navigation_(
          is_embedder_initiated_fenced_frame_navigation),
      fenced_frame_properties_(
          is_embedder_initiated_fenced_frame_navigation
              ? std::make_optional(FencedFrameProperties(common_params_->url))
              : std::nullopt),
      embedder_shared_storage_context_(embedder_shared_storage_context),
      has_ad_auction_headers_attribute_(frame_tree_node->ad_auction_headers()),
      request_method_(common_params_->method),
      prerender_host_id_(
          GetPrerenderHostRegistry().GetPrerenderHostIdForNavigation(this)) {
  TRACE_EVENT("navigation", "NavigationRequest::NavigationRequest",
              perfetto::Flow::FromPointer(this), "navigation_request", this);
  CHECK(!common_params_->initiator_base_url ||
        !common_params_->initiator_base_url->is_empty());
  DCHECK(!blink::IsRendererDebugURL(common_params_->url));
  DCHECK(common_params_->method == "POST" || !common_params_->post_data);
  DCHECK_EQ(common_params_->url, commit_params_->original_url);
  // Navigations can't be a replacement and a reload at the same time.
  DCHECK(!common_params_->should_replace_current_entry ||
         !NavigationTypeUtils::IsReload(common_params_->navigation_type));
  DCHECK(IsInOutermostMainFrame() ||
         common_params_->base_url_for_data_url.is_empty());
#if BUILDFLAG(IS_ANDROID)
  DCHECK(IsInOutermostMainFrame() ||
         commit_params_->data_url_as_string.empty());
#endif
  CheckSoftNavigationHeuristicsInvariants();

  ScopedCrashKeys crash_keys(*this);

  ComputeDownloadPolicy();

  // Ensure the blink::RuntimeFeatureStateContext is initialized.
  runtime_feature_state_context_ = blink::RuntimeFeatureStateContext();

  TRACE_EVENT_BEGIN("navigation", "NavigationRequest",
                    perfetto::Track(navigation_id_), "navigation_request",
                    this);
  TRACE_EVENT_BEGIN("navigation", "Initializing",
                    perfetto::Track(navigation_id_));

  if (GetInitiatorFrameToken().has_value()) {
    RenderFrameHostImpl* initiator_rfh = RenderFrameHostImpl::FromFrameToken(
        GetInitiatorProcessId(), GetInitiatorFrameToken().value());
    if (initiator_rfh)
      initiator_document_token_ = initiator_rfh->GetDocumentToken();
  }

  // Spec: https://github.com/whatwg/html/issues/8846
  // We only allow the parent to access a subframe resource timing if the
  // navigation is container-initiated, e.g. iframe changed src.
  if (begin_params_->is_container_initiated) {
    // Only same-origin navigations without cross-origin redirects can
    // expose response details (status-code / mime-type).
    // https://github.com/whatwg/fetch/issues/1602
    // Note that this condition checks this navigation is not cross origin.
    // Cross-origin redirects are checked as part of OnRequestRedirected().
    commit_params_->navigation_timing->parent_resource_timing_access =
        GetParentFrame()->GetLastCommittedOrigin().IsSameOriginWith(GetURL())
            ? blink::mojom::ParentResourceTimingAccess::
                  kReportWithResponseDetails
            : blink::mojom::ParentResourceTimingAccess::
                  kReportWithoutResponseDetails;
  }

  navigation_or_document_handle_ =
      NavigationOrDocumentHandle::CreateForNavigation(*this);

  policy_container_builder_.emplace(
      GetParentFrame(),
      initiator_frame_token_.has_value() ? &*initiator_frame_token_ : nullptr,
      initiator_process_id_, GetStoragePartitionWithCurrentSiteInfo(),
      frame_entry);

  NavigationControllerImpl* controller = GetNavigationController();

  if (frame_entry) {
    frame_entry_item_sequence_number_ = frame_entry->item_sequence_number();
    frame_entry_document_sequence_number_ =
        frame_entry->document_sequence_number();
  }

  // Sanitize the referrer.
  common_params_->referrer = Referrer::SanitizeForRequest(
      common_params_->url, *common_params_->referrer);

  if (IsInPrimaryMainFrame()) {
    loading_mem_tracker_ = PeakGpuMemoryTrackerFactory::Create(
        viz::PeakGpuMemoryTracker::Usage::PAGE_LOAD);
  }

  if (frame_tree_node_->IsInFencedFrameTree()) {
    commit_params_->frame_policy.sandbox_flags |=
        blink::kFencedFrameForcedSandboxFlags;
  }

  if (base::FeatureList::IsEnabled(network::features::kSharedStorageAPI)) {
    shared_storage_writable_opted_in_ =
        frame_tree_node_->shared_storage_writable_opted_in();
    shared_storage_writable_eligible_ =
        IsSharedStorageWritableEligibleForNavigationRequest(
            frame_tree_node_, common_params_->url);
  }

  if (from_begin_navigation_) {
    // This is needed to commit data: and about: URLs in the same SiteInstance
    // as the initiator frame. Note that this may not necessarily match the
    // SiteInstance of the RenderFrameHost that sent the BeginNavigation IPC
    // (i.e., `frame_tree_node_->current_frame_host()->GetSiteInstance()`) with
    // SiteInstanceGroups, because some other frame in a different SiteInstance
    // but same SiteInstanceGroup could've initiated this navigation.
    source_site_instance_ =
        RenderFrameHostImpl::GetSourceSiteInstanceFromFrameToken(
            base::OptionalToPtr(GetInitiatorFrameToken()),
            GetInitiatorProcessId(),
            frame_tree_node_->current_frame_host()->GetStoragePartition());

    // If the lookup above failed (e.g., when no initiator frame token was
    // provided), fall back to the navigating frame's current SiteInstance. This
    // ensures that this renderer-initiated navigation still has a valid source
    // SiteInstance corresponding to the renderer process that initiated the
    // navigation, which is needed for certain security checks based on
    // `source_site_instance_`, such as the CanRequestURL() check in
    // `OnRequestRedirected()`.
    if (!source_site_instance_) {
      source_site_instance_ =
          frame_tree_node_->current_frame_host()->GetSiteInstance();
    }

    DCHECK(navigation_client.is_valid());
    SetNavigationClient(std::move(navigation_client));

    // Wait for renderer-initiated cancellation if needed. Navigation can
    // proceed as soon as the corresponding JS task in the renderer finishes
    // without calling window.stop() or other navigation cancellation triggers.
    // That means there is no need to synchronise this signal with other
    // renderer events, so this interface doesn't have to be associated and can
    // use a prioritized task runner.
    // kNavigationNetworkResponse is used as CommitNavigation typically already
    // runs in on a task from this task runner (via OnResponseReceived message
    // received from the network service).
    if (renderer_cancellation_listener.is_valid()) {
      renderer_cancellation_listener_.Bind(
          std::move(renderer_cancellation_listener),
          GetUIThreadTaskRunner({BrowserTaskType::kNavigationNetworkResponse}));
    }
  } else if (entry) {
    DCHECK(!navigation_client.is_valid());
    if (frame_entry) {
      source_site_instance_ = frame_entry->source_site_instance();
      dest_site_instance_ = frame_entry->site_instance();
      bindings_ = frame_entry->bindings();

      // Handle navigations that require a |source_site_instance| but do not
      // have one set yet. This can happen when navigation entries are restored
      // from PageState objects, because the serialized state does not contain a
      // SiteInstance so we need to use the |initiator_origin| to get an
      // appropriate source SiteInstance. This can also happen when the
      // |source_site_instance| was suppressed because of navigating in
      // "noopener" mode.
      //
      // History subframe, restore navigations and |was_opener_suppressed| are
      // the only cases where SetSourceSiteInstanceToInitiatorIfNeeded needs to
      // be called (i.e. the only cases that may have no |source_site_instance_|
      // even though RequiresInitiatorBasedSourceSiteInstance returns true).  We
      // verify that other cases which require a |source_site_instance_| indeed
      // have one with a DCHECK below.
      if (common_params_->is_history_navigation_in_new_child_frame ||
          common_params_->navigation_type ==
              blink::mojom::NavigationType::RESTORE ||
          common_params_->navigation_type ==
              blink::mojom::NavigationType::RESTORE_WITH_POST ||
          was_opener_suppressed) {
        SetSourceSiteInstanceToInitiatorIfNeeded();
      }
    }
    isolation_info_ = entry->isolation_info();

    // Ensure that we always have a |source_site_instance_| for navigations
    // that require it at this point. This is needed to ensure that data: URLs
    // commit in the SiteInstance that initiated them.
    //
    // TODO(acolwell): Move this below so it can be enforced on all paths.
    // This requires auditing same-document and other navigations that don't
    // have |from_begin_navigation_| or |entry| set.
    DCHECK(!RequiresInitiatorBasedSourceSiteInstance() ||
           source_site_instance_);
  }

  // Let the NTP override the navigation params and pretend that this is a
  // browser-initiated, bookmark-like navigation.
  // TODO(crbug.com/40702467): determine why some link navigations on chrome://
  //     pages have |browser_initiated| set to true and others set to false.
  if (source_site_instance_) {
    bool is_renderer_initiated = !browser_initiated;
    Referrer referrer(*common_params_->referrer);
    ui::PageTransition transition =
        ui::PageTransitionFromInt(common_params_->transition);
    // TODO(crbug.com/388998723): Avoid unintentionally creating a process for
    // source_site_instance_ if it doesn't have one.
    GetContentClient()->browser()->OverrideNavigationParams(
        source_site_instance_
            ->GetOrCreateProcess(ProcessAllocationContext{
                ProcessAllocationSource::kOverrideNavigationParams})
            ->GetProcessLock()
            .site_url(),
        &transition, &is_renderer_initiated, &referrer,
        &common_params_->initiator_origin);
    common_params_->transition = transition;
    common_params_->referrer =
        blink::mojom::Referrer::New(referrer.url, referrer.policy);
    browser_initiated = !is_renderer_initiated;
  }
  commit_params_->is_browser_initiated = browser_initiated;

  // Update the load flags with cache information.
  UpdateLoadFlagsWithCacheFlags(&begin_params_->load_flags,
                                common_params_->navigation_type,
                                common_params_->method == "POST");

  // Add necessary headers that may not be present in the
  // blink::mojom::BeginNavigationParams.
  if (entry) {
    if (frame_tree_node->IsOutermostMainFrame() &&
        entry->back_forward_cache_metrics()) {
      entry->back_forward_cache_metrics()
          ->MainFrameDidStartNavigationToDocument();
    }

    // If this NavigationRequest is for the current pending entry, make sure
    // that we will discard the pending entry if all of associated its requests
    // go away, by creating a ref to it.
    if (entry == controller->GetPendingEntry())
      pending_entry_ref_ = controller->ReferencePendingEntry();

    // |commit_params->is_overriding_user_agent| is the single source of truth
    // in NavigationRequest. For history navigations, callers of this
    // constructor must not provide conflicting requirements. Only
    // |commit_params->is_overriding_user_agent| will be taken into account.
    DCHECK_EQ(is_overriding_user_agent(), entry->GetIsOverridingUserAgent());
  }

  net::HttpRequestHeaders headers;
  // Only add specific headers when creating a NavigationRequest before the
  // network request is made, not at commit time.
  if (!is_synchronous_renderer_commit) {
    BrowserContext* browser_context = controller->GetBrowserContext();
    ClientHintsControllerDelegate* client_hints_delegate =
        browser_context->GetClientHintsControllerDelegate();
    // Loading an about:srcdoc url on the main frame will cause a failure later
    // and GetTentativeOriginAtRequestTime() can't handle it until then.
    if ((CheckAboutSrcDoc() != AboutSrcDocCheckResult::BLOCK_REQUEST) &&
        client_hints_delegate) {
      net::HttpRequestHeaders client_hints_headers;
      AddNavigationRequestClientHintsHeaders(
          GetTentativeOriginAtRequestTime(), &client_hints_headers,
          browser_context, client_hints_delegate, is_overriding_user_agent(),
          frame_tree_node_, commit_params_->frame_policy.container_policy,
          common_params_->url);
      headers.MergeFrom(client_hints_headers);
    }

    // Add reduced accept language header.
    if (auto reduce_accept_lang_utils =
            ReduceAcceptLanguageUtils::Create(browser_context);
        reduce_accept_lang_utils && !devtools_accept_language_override_ &&
        !ReduceAcceptLanguageUtils::CheckDisableReduceAcceptLanguageOriginTrial(
            common_params_->url, frame_tree_node_,
            browser_context->GetOriginTrialsControllerDelegate())) {
      // Add the Accept-Language header with the reduce accept language value.
      // Chromium network stack won't overwrite the value if Accept-Language
      // header was already added in the request header.
      net::HttpRequestHeaders accept_language_headers;
      std::optional<std::string> reduced_accept_language =
          reduce_accept_lang_utils.value()
              .AddNavigationRequestAcceptLanguageHeaders(
                  url::Origin::Create(common_params_->url), frame_tree_node_,
                  &accept_language_headers);
      commit_params_->reduced_accept_language =
          reduced_accept_language.value_or("");
      headers.MergeFrom(accept_language_headers);
    }

    headers.AddHeadersFromString(begin_params_->headers);
    AddAdditionalRequestHeaders(
        &headers, common_params_->url, common_params_->navigation_type,
        ui::PageTransitionFromInt(common_params_->transition),
        controller->GetBrowserContext(), common_params_->method,
        GetUserAgentOverride(), common_params_->initiator_origin,
        common_params_->referrer.get(), frame_tree_node);

    if (begin_params_->is_form_submission) {
      // During form resubmit, `commit_params_->post_content_type` is populated
      // from the history. Use it.
      if (!commit_params_->post_content_type.empty()) {
        headers.SetHeaderIfMissing(net::HttpRequestHeaders::kContentType,
                                   commit_params_->post_content_type);
      }

      // Save the Content-Type in case the form is resubmitted. This will get
      // sent back to the renderer in the CommitNavigation IPC. The renderer
      // will then send it back with the post body so that we can access it
      // along with the body in FrameNavigationEntry::page_state_.
      if (std::optional<std::string> content_type =
              headers.GetHeader(net::HttpRequestHeaders::kContentType);
          content_type) {
        commit_params_->post_content_type = std::move(content_type).value();
      }
    }

    TopicsHeaderValueResult topics_header_value_result =
        GetTopicsHeaderValueForNavigationRequest(frame_tree_node,
                                                 common_params_->url);

    topics_eligible_ = topics_header_value_result.topics_eligible;

    if (topics_header_value_result.header_value) {
      headers.SetHeader(kBrowsingTopicsRequestHeaderKey,
                        *topics_header_value_result.header_value);
    }

    if (has_ad_auction_headers_attribute_ &&
        IsAdAuctionHeadersEligibleForNavigation(
            *frame_tree_node_, url::Origin::Create(common_params_->url))) {
      ad_auction_headers_eligible_ = true;
      headers.SetHeader(kAdAuctionRequestHeaderKey, "?1");
    }
  }

  begin_params_->headers = headers.ToString();

#if BUILDFLAG(IS_ANDROID)
  RenderWidgetHostImpl* host = RenderWidgetHostImpl::From(
      frame_tree_node_->current_frame_host()->GetRenderWidgetHost());
  if (NeedsUrlLoader() && IsInPrimaryMainFrame() && host && !host->IsHidden() &&
      host->GetView() && host->GetView()->GetNativeView() &&
      host->GetView()->GetNativeView()->GetWindowAndroid()) {
    // If the compositor changes, we will just let the lock timeout instead of
    // trying to deal with it explicitly.
    ui::WindowAndroidCompositor* compositor =
        host->GetView()->GetNativeView()->GetWindowAndroid()->GetCompositor();
    if (compositor) {
      compositor_lock_ = compositor->GetCompositorLock(kCompositorLockTimeout);
    }
  }

  navigation_handle_proxy_ = std::make_unique<NavigationHandleProxy>(this);
#endif

  if (NeedsUrlLoader() && common_params_->url.SchemeIsHTTPOrHTTPS()) {
    if (GetContentClient()->browser()->ShouldPreconnectNavigation(
            frame_tree_node_->current_frame_host())) {
      auto* storage_partition =
          frame_tree_node_->current_frame_host()->GetStoragePartition();
      storage_partition->GetNetworkContext()->PreconnectSockets(
          1, common_params_->url, network::mojom::CredentialsMode::kInclude,
          GetIsolationInfo().network_anonymization_key(),
          net::MutableNetworkTrafficAnnotationTag(),
          /*keepalive_config=*/std::nullopt, mojo::NullRemote());
    }
  }

  if (NeedsUrlLoader() && IsInOutermostMainFrame()) {
    MaybePrewarmHttpDiskCache(*controller->GetBrowserContext(), GetURL(),
                              GetInitiatorOrigin());
  }

  // Checking OriginCanAccessServiceWorkers() is needed before calling
  // GetTentativeOriginAtRequestTime() since loading an about:srcdoc URL
  // on the main frame will cause a failure while processing
  // GetTentativeOriginAtRequestTime().
  if (OriginCanAccessServiceWorkers(GetURL())) {
    // Preflight request for FindRegistrationForClientUrl. This
    // preflight request speeds-up the upcoming
    // FindRegistrationForClientUrl requests because the upcoming
    // requests will be merged into this preflight request in
    // `ServiceWorkerRegistry::FindRegistrationForClientUrl()` and
    // `ServiceWorkerRegistry::RunFindRegistrationCallbacks()` later.
    if (ServiceWorkerContext* context =
            frame_tree_node_->navigator()
                .controller()
                .GetBrowserContext()
                ->GetStoragePartition(site_info_.storage_partition_config())
                ->GetServiceWorkerContext()) {
      const blink::StorageKey key = blink::StorageKey::CreateFirstParty(
          GetTentativeOriginAtRequestTime());
      if (context->MaybeHasRegistrationForStorageKey(key)) {
        // `CheckHasServiceWorker` calls `FindRegistrationForClientUrl`
        // internally.
        context->CheckHasServiceWorker(GetURL(), key, base::DoNothing());
      }
    }
  }

  // Only update the BackForwardCacheMetrics if this is for a navigation that
  // could've been served from the bfcache.
  if (IsBackForwardCacheEnabled() && !IsServedFromBackForwardCache() && entry &&
      BackForwardCacheMetrics::IsCrossDocumentMainFrameHistoryNavigation(
          this)) {
    // Update NotRestoredReasons and create a metrics object if there's none.
    entry->UpdateBackForwardCacheNotRestoredReasons(this);
    auto* metrics = entry->back_forward_cache_metrics();
    DCHECK(metrics);
    if (base::FeatureList::IsEnabled(
            blink::features::kBackForwardCacheSendNotRestoredReasons)) {
      // Only populate the web-exposed NotRestoredReasons when needed by
      // the NotRestoredReasons API.
      commit_params_->not_restored_reasons =
          metrics->GetWebExposedNotRestoredReasons();

      if (!base::FeatureList::IsEnabled(
              blink::features::kBackForwardCacheUpdateNotRestoredReasonsName)) {
        // Check that the reasons are not null since |this| is not served from
        // back/forward cache.
        // Session restored cases will be reported as null with the flag on and
        // this check will no longer hold true.
        CHECK(!commit_params_->not_restored_reasons.is_null());
      }
    }
  }
  // Check that the reasons are null when |this| is served from back/forward
  // cache.
  if (base::FeatureList::IsEnabled(
          blink::features::kBackForwardCacheSendNotRestoredReasons) &&
      IsBackForwardCacheEnabled() && IsServedFromBackForwardCache()) {
    CHECK(commit_params_->not_restored_reasons.is_null());
  }

  // Record `SameDocumentCrossOriginInitiator` metric. It happens in the
  // NavigationRequest constructor, to catch every kind of same-document
  // navigation: the one initiated from the navigating frame's process, and the
  // others.
  if (common_params_->navigation_type ==
          blink::mojom::NavigationType::SAME_DOCUMENT &&
      GetInitiatorOrigin() &&
      !GetInitiatorOrigin()->IsSameOriginWith(
          GetTentativeOriginAtRequestTime())) {
    // This is reported to navigating frame's current document, because this is
    // the document that behave differently if this navigation was turned into a
    // cross-document one.
    GetContentClient()->browser()->LogWebFeatureForCurrentPage(
        frame_tree_node_->current_frame_host(),
        blink::mojom::WebFeature::kSameDocumentCrossOriginInitiator);
  }

  if (!GetContentClient()->browser()->IsBrowserStartupComplete()) {
    confidence_level_ = blink::mojom::ConfidenceLevel::kLow;
  }
}

NavigationRequest::~NavigationRequest() {
  TRACE_EVENT("navigation", "NavigationRequest::~NavigationRequest",
              perfetto::TerminatingFlow::FromPointer(this));
#if DCHECK_IS_ON()
  // If |is_safe_to_delete_| is false, it means |this| is being deleted at an
  // unexpected time, more specifically a time that is likely to lead to
  // crashing when the stack unwinds (use after free). The typical scenario for
  // this is calling to the delegate when the delegate is not expected to make
  // any sort of state change. For example, when the delegate is informed that a
  // navigation has started the delegate is not expected to call Stop().
  DCHECK(is_safe_to_delete_);
#endif

  // Close "Initializing", or the last child event emitted in
  // EnterChildTraceEvent().
  TRACE_EVENT_END("navigation", perfetto::Track(navigation_id_));
  TRACE_EVENT_END("navigation",
                  /* NavigationRequest */ perfetto::Track(navigation_id_));

  // If navigation has started but not finished, mark it as aborted for
  // Navigation callbacks.
  if (base::FeatureList::IsEnabled(
          features::kAbortNavigationsFromTabClosures) &&
      state_ < DID_COMMIT && net_error_ == net::OK) {
    net_error_ = net::ERR_ABORTED;
  }

  // IMPORTANT NOTE: DO NOT return early from the destructor before this line.
  // Otherwise, a queued navigation might get stuck in a queueing state forever.
  // This navigation has finished. See if there is another NavigationRequest
  // that lives in the associated FrameTreeNode that satisfies these conditions:
  // - Is currently queued to wait for a pending commit navigation to finish
  // - Is not the NavigationRequest that is currently being destructed itself
  if (NavigationRequest* request = frame_tree_node_->navigation_request()) {
    if (request->IsQueued() && request != this) {
      // It might be possible for the pending commit RFH to still exist, e.g. if
      // the navigation being destructed is an unrelated navigation
      // (same-document navigation etc). In that case, don't continue the queued
      // navigation just yet.
      if (!request->ShouldQueueDueToExistingPendingCommitRFH()) {
        request->PostResumeCommitTask();
      }
    }
  }

  if (loading_mem_tracker_)
    loading_mem_tracker_->Cancel();
  ResetExpectedProcess();

#if BUILDFLAG(IS_ANDROID)
  if (IsInPrimaryMainFrame()) {
    if (auto* cache =
            GetNavigationController()->GetNavigationEntryScreenshotCache()) {
      cache->OnNavigationFinished(*this);
    }
  }
#endif  // BUILDFLAG(IS_ANDROID)

  if (HasCommitted()) {
    CHECK(!navigation_discard_reason_.has_value());
  } else {
    if (!navigation_discard_reason_.has_value()) {
      // If a navigation is destructed without having committed, it should have
      // a reason set.
      // TODO(crbug.com/390569133): Change this back to a CHECK once we make
      // sure this is never hit.
      SCOPED_CRASH_KEY_NUMBER("Bug390569133", "navigation_state", (int)state_);
      base::debug::DumpWithoutCrashing();
    }

    // If we're before WILL_START_NAVIGATION, we haven't reported request start
    // to DevTools yet.
    // If we're in WILL_FAIL_REQUEST, the failure has been reported already.
    if (state_ >= WILL_START_NAVIGATION && state_ != WILL_FAIL_REQUEST) {
      devtools_instrumentation::OnNavigationRequestFailed(
          *this, network::URLLoaderCompletionStatus(net::ERR_ABORTED));
    }

    // NavigationRequests with pending Navigation API keys must notify the
    // renderer when they fail.
    if (pending_navigation_api_key_) {
      frame_tree_node_->current_frame_host()
          ->GetAssociatedLocalFrame()
          ->TraverseCancelled(
              *pending_navigation_api_key_,
              blink::mojom::TraverseCancelledReason::kAbortedBeforeCommit);
    }

    // If subframe history navigations were deferred waiting for this request,
    // the cancelation of this request should cancel them, too.
    for (auto& throttle : subframe_history_navigation_throttles_) {
      if (throttle) {
        throttle->Cancel();
      }
    }
    subframe_history_navigation_throttles_.clear();
  }

  // If this NavigationRequest is the last one referencing the pending
  // NavigationEntry, the entry is discarded.
  //
  // Leaving a stale pending NavigationEntry with no matching navigation can
  // potentially lead to URL-spoof issues.
  //
  // Note: Discarding the pending NavigationEntry is done before notifying the
  // navigation finished to the observers. One class is relying on this:
  // org.chromium.chrome.browser.toolbar.ToolbarManager
  pending_entry_ref_.reset();

#if BUILDFLAG(IS_ANDROID)
  if (navigation_visible_to_embedder_)
    navigation_handle_proxy_->DidFinish();
#endif

  if (is_deferred_on_fenced_frame_url_mapping_) {
    CHECK(NeedFencedFrameURLMapping());
    GetFencedFrameURLMap().RemoveObserverForURN(common_params_->url, this);
  }

  RecordEarlyRenderFrameHostSwapMetrics();

  if (IsNavigationStarted()) {
    GetDelegate()->DidFinishNavigation(this);
    ProcessOriginAgentClusterEndResult();
    if (IsInMainFrame()) {
      // Navigation StartToCommit
      TRACE_EVENT_END("navigation",
                      perfetto::NamedTrack("StartToCommit",
                                           reinterpret_cast<uintptr_t>(this)),
                      "URL", common_params_->url.spec(), "Net Error Code",
                      net_error_);
      MaybeRecordTraceEventsAndHistograms();
    }
    MaybeRecordNavigationStartAdjustments();

    // Abandon the prerender host reserved for activation if it exists.
    if (IsPrerenderedPageActivation()) {
      GetPrerenderHostRegistry().OnActivationFinished(
          prerender_frame_tree_node_id_.value());
    }

    if (!HasCommitted()) {
      ResetViewTransitionState();
    }

    if (IsServedFromBackForwardCache()) {
      auto bfcache_entry =
          GetNavigationController()->GetBackForwardCache().GetOrEvictEntry(
              nav_entry_id());
      if (!bfcache_entry.has_value() &&
          bfcache_entry.error() ==
              BackForwardCacheImpl::kEntryIneligibleAndEvicted) {
        // DO NOT ADD CODE after this. When BFCache entry is evicted, the
        // current NavigationRequest has been destroyed.
        return;
      }
      if (bfcache_entry.has_value()) {
        RenderFrameHostImpl* rfh = RenderFrameHostImpl::FromID(
            bfcache_entry.value()->render_frame_host()->GetGlobalId());
        // RFH could have been deleted. E.g. eviction timer fired
        if (rfh && rfh->IsInBackForwardCache()) {
          // rfh is still in the cache so the navigation must have failed. But
          // we have already disabled eviction so the safest thing to do here to
          // recover is to evict.
          // TODO(crbug.com/40283427): Only evict BFCache if the
          // `BackForwardCacheCommitDeferringCondition`, which unfreezes the
          // page and disables the eviction on the renderer side, is completed.
          rfh->EvictFromBackForwardCacheWithReason(
              BackForwardCacheMetrics::NotRestoredReason::
                  kNavigationCancelledWhileRestoring);
        }
      }
    }
  } else {
    GetDelegate()->DidCancelNavigationBeforeStart(this);
  }
}

void NavigationRequest::RegisterCommitDeferringConditionForTesting(
    std::unique_ptr<CommitDeferringCondition> condition) {
  commit_deferrer_->AddConditionForTesting(std::move(condition));  // IN-TEST
}

void NavigationRequest::SetCookieAccessObserversForTesting(
    std::unique_ptr<CookieAccessObservers> observers) {
  cookie_observers_ = std::move(observers);
}

bool NavigationRequest::IsCommitDeferringConditionDeferredForTesting() {
  if (!commit_deferrer_)
    return false;
  return commit_deferrer_->GetDeferringConditionForTesting();  // IN-TEST
}

CommitDeferringCondition*
NavigationRequest::GetCommitDeferringConditionForTesting() {
  if (!commit_deferrer_)
    return nullptr;
  return commit_deferrer_->GetDeferringConditionForTesting();  // IN-TEST
}

void NavigationRequest::BeginNavigation() {
  begin_navigation_time_ = base::TimeTicks::Now();
  TRACE_EVENT("navigation", "NavigationRequest::BeginNavigation",
              perfetto::Flow::FromPointer(this));
  EnterChildTraceEvent("BeginNavigation", this);
  DCHECK(!loader_);
  DCHECK(!HasRenderFrameHost());
  ScopedCrashKeys crash_keys(*this);

  if (begin_navigation_callback_for_testing_) {
    std::move(begin_navigation_callback_for_testing_).Run();
  }

  if (MaybeStartPrerenderingActivationChecks()) {
    // BeginNavigationImpl() will be called after the checks.
    return;
  }

  MaybeAssignInvalidPrerenderFrameTreeNodeId();

  // Fenced frames are not allowed to load if nested in iframes with CSPEE.
  bool is_fenced_frame = frame_tree_node_->IsFencedFrameRoot();
  if (is_fenced_frame) {
    DCHECK(!frame_tree_node_->csp_attribute());
    if (GetParentFrameOrOuterDocument()->required_csp()) {
      GURL sanitized_blocked_url =
          common_params_->url.DeprecatedGetOriginAsURL();
      AddDeferredConsoleMessage(
          blink::mojom::ConsoleMessageLevel::kError,
          base::StringPrintf(
              "Refused to frame '%s' as a fenced frame because "
              "CSP Embedded Enforcement is specified by the embedder",
              sanitized_blocked_url.spec().c_str()));

      StartNavigation();
      OnRequestFailedInternal(
          network::URLLoaderCompletionStatus(net::ERR_BLOCKED_BY_CSP),
          false /*skip_throttles*/, std::nullopt /*error_page_content*/,
          false /*collapse_frame*/);
      // DO NOT ADD CODE after this. The previous call to
      // OnRequestFailedInternal has destroyed the NavigationRequest.
      return;
    }
  }

  // If this is a fenced frame with a urn:uuid, or an iframe with a urn::uuid
  // given blink::features::kAllowURNsInIframes is enabled, then convert it to a
  // url before starting the navigation; otherwise, proceed directly with the
  // navigation.
  // In long term, navigation support for urn::uuid in iframes will be
  // deprecated. Currently we issue a console warning when navigation starts.
  // TODO(crbug.com/40060657)
  if (NeedFencedFrameURLMapping()) {
    if (!is_fenced_frame) {
      // Iframes with urn::uuid.
      DCHECK(!frame_tree_node_->IsMainFrame());
      DCHECK(blink::features::IsAllowURNsInIframeEnabled());
      if (blink::features::DisplayWarningDeprecateURNIframesUseFencedFrames()) {
        AddDeferredConsoleMessage(
            blink::mojom::ConsoleMessageLevel::kWarning,
            "Protected Audience/selectURL will deprecate supporting iframes to "
            "render the winning ad/selected URL. "
            "Please use fenced frames instead. See "
            "https://developer.chrome.com/en/docs/privacy-sandbox/fenced-frame/"
            "#examples");
      }
    }

    UMA_HISTOGRAM_BOOLEAN(
        "Navigation.BrowserMappedUrnUuidInIframeOrFencedFrame",
        !is_fenced_frame);

    FencedFrameURLMapping& fenced_frame_urls_map = GetFencedFrameURLMap();

    // If the mapping finishes synchronously, OnFencedFrameURLMappingComplete
    // will be synchronously called and will reset
    // `is_deferred_on_fenced_frame_url_mapping_` to false.
    is_deferred_on_fenced_frame_url_mapping_ = true;

    fenced_frame_url_mapping_start_time_ = base::TimeTicks::Now();

    // OnFencedFrameURLMappingComplete() and BeginNavigationImpl() will be
    // invoked after this.
    fenced_frame_urls_map.ConvertFencedFrameURNToURL(common_params_->url,
                                                     /*observer=*/this);
    // DO NOT ADD CODE after this. The previous call to
    // ConvertFencedFrameURNToURL may cause the destruction of the
    // NavigationRequest.
    return;
  }

  // Send any potential navigation start automatic beacons for this frame.
  frame_tree_node_->current_frame_host()
      ->MaybeSendFencedFrameAutomaticReportingBeacon(
          *this, blink::mojom::AutomaticBeaconType::kTopNavigationStart);

  // Log a histogram for a top-level navigation that initiates from a fenced
  // frame or URN iframe.
  if (GetInitiatorDocumentRenderFrameHost() &&
      GetInitiatorDocumentRenderFrameHost()
          ->frame_tree_node()
          ->GetFencedFrameProperties()
          .has_value() &&
      IsInOutermostMainFrame()) {
    base::UmaHistogramEnumeration(blink::kFencedFrameTopNavigationHistogram,
                                  blink::FencedFrameNavigationState::kBegin);
  }

  BeginNavigationImpl();
}

void NavigationRequest::UpdateNavigationStartTime(const base::TimeTicks& time,
                                                  bool for_legacy,
                                                  bool showed_dialog) {
  // Track the adjustment details for https://crbug.com/385170155.
  // Note: It is possible to get here more than once for a single request, which
  // might happen if a beforeunload ack for a different navigation is received
  // at the wrong time (see https://crbug.com/402545469). In that case, preserve
  // the existing `original_navigation_start_`.
  // TODO(crbug.com/404286908): Track which NavigationRequest should be updated
  // in response to a given beforeunload completion.
  if (original_navigation_start_.is_null()) {
    original_navigation_start_ = common_params_->navigation_start;
  }
  navigation_start_adjustment_for_legacy_ = for_legacy;
  beforeunload_dialog_shown_ = showed_dialog;

  common_params_->navigation_start = time;

  if (for_legacy) {
    // Legacy PostTasks do not run any actual beforeunload handlers and should
    // be treated as part of navigation overhead, rather than excluded.
    //
    // Note: Due to crbug.com/404286908, it is possible for this function to be
    // called with data from an earlier NavigationRequest that has been canceled
    // before this request started, and thus `for_legacy` may not be accurate.
    // Until that bug is fixed, though, it is still accurate to treat the
    // current request as legacy (even if it meant to run actual beforeunload
    // handlers) because the navigation will proceed anyway without waiting for
    // those handlers.
    beforeunload_phase2_start_time_ = base::TimeTicks();
    beforeunload_phase2_end_time_ = base::TimeTicks();
  } else {
    // Non-legacy cases that ran beforeunload handlers should set an end time
    // for BeforeUnload phase 2 if there was a corresponding start time. This
    // end time should be close to the end of running beforeunload.
    //
    // Note: Until crbug.com/404286908 is fixed, it is possible for `time` to be
    // before the start time, due to updating the wrong NavigationRequest. In
    // that rare case, use the current time instead to ensure the interval is
    // well-defined (even if that causes us to ignore a little more time than
    // necessary by making BeforeUnload phase 2 look a little longer). Also
    // avoid changing the end time once it is set, in case this is called more
    // than once.
    if (!beforeunload_phase2_start_time_.is_null() &&
        beforeunload_phase2_end_time_.is_null()) {
      beforeunload_phase2_end_time_ = (beforeunload_phase2_start_time_ <= time)
                                          ? time
                                          : base::TimeTicks::Now();
    }
  }
}

bool NavigationRequest::MaybeStartPrerenderingActivationChecks() {
  // Find an available prerendered page for this request. If it's found, this
  // request may activate it instead of loading a page via network.
  FrameTreeNodeId candidate_prerender_frame_tree_node_id =
      GetPrerenderHostRegistry().FindPotentialHostToActivate(*this);
  if (candidate_prerender_frame_tree_node_id.is_null()) {
    return false;
  }

  // Run CommitDeferringConditions before activating the prerendered page. See
  // the comemnt on RunCommitDeferringConditions() for details.
  //
  // The prerendered page can be destroyed while the conditions are running.
  // In that case, this request gives up activating it and instead falls back to
  // a regular navigation.
  commit_deferrer_ = CommitDeferringConditionRunner::Create(
      *this,
      CommitDeferringCondition::NavigationType::kPrerenderedPageActivation,
      candidate_prerender_frame_tree_node_id);
  is_running_potential_prerender_activation_checks_ = true;

  // Post a task to run the conditions in case BeginNavigation() is not expected
  // to run synchronously. OnPrerenderingActivationChecksComplete() will be
  // called after all the deferring conditions finish.
  auto commit_deferring_conditions_complete_callback = base::BindOnce(
      &NavigationRequest::OnPrerenderingActivationChecksComplete,
      weak_factory_.GetWeakPtr(),
      CommitDeferringCondition::NavigationType::kPrerenderedPageActivation,
      candidate_prerender_frame_tree_node_id);
  base::SequencedTaskRunner::GetCurrentDefault()->PostNonNestableTask(
      FROM_HERE,
      base::BindOnce(&NavigationRequest::RunCommitDeferringConditions,
                     weak_factory_.GetWeakPtr(),
                     std::move(commit_deferring_conditions_complete_callback)));
  return true;
}

void NavigationRequest::OnPrerenderingActivationChecksComplete(
    CommitDeferringCondition::NavigationType navigation_type,
    std::optional<FrameTreeNodeId> candidate_prerender_frame_tree_node_id) {
  TRACE_EVENT("navigation",
              "NavigationRequest::OnPrerenderingActivationChecksComplete",
              perfetto::Flow::FromPointer(this));
  // Prerendered page activation must run CommitDeferringConditions before
  // StartRequest().
  DCHECK_LT(state_, WILL_START_NAVIGATION);

  DCHECK(candidate_prerender_frame_tree_node_id.has_value());
  DCHECK(!prerender_frame_tree_node_id_.has_value());
  DCHECK(!reserved_prerender_host_info_.has_value());

  // Attempt to reserve the potential PrerenderHost.
  //
  // If it has been requested to cancel prerendered page activation during
  // CommitDeferringConditions, ReserveHostToActivate() returns an invalid
  // FrameTreeNodeId, and then NavigationRequest continues as regular
  // navigation.
  reserved_prerender_host_info_ =
      GetPrerenderHostRegistry().ReserveHostToActivate(
          *this, candidate_prerender_frame_tree_node_id.value());
  prerender_frame_tree_node_id_ =
      reserved_prerender_host_info_.has_value()
          ? reserved_prerender_host_info_->frame_tree_node_id
          : FrameTreeNodeId();
  if (prerender_frame_tree_node_id_.value().is_null()) {
    // If we ran commit deferring conditions for a potential pre-render which
    // eventually wasn't activated, abort the ViewTransition. The state was
    // cached assuming this navigation will be same-origin which might not be
    // the case now that we need to make a network request.
    ResetViewTransitionState();
  } else {
    // The reserved host should match with the potential host. Otherwise the
    // reserved host may not be ready for activation yet as we haven't run
    // PrerenderCommitDeferringCondition for the host to finish navigation in
    // the prerendering main frame.
    DCHECK_EQ(prerender_frame_tree_node_id_.value(),
              candidate_prerender_frame_tree_node_id.value());
  }
  is_running_potential_prerender_activation_checks_ = false;
  commit_deferrer_.reset();

  // We can only activate top-level pages, which can never be at a fenced frame
  // URN that needs to be mapped.
  CHECK(!NeedFencedFrameURLMapping());

  BeginNavigationImpl();
  // DO NOT ADD CODE after this. The previous call to
  // BeginNavigationImpl may cause the destruction of the NavigationRequest.
}

FencedFrameURLMapping& NavigationRequest::GetFencedFrameURLMap() {
  // The usual case here is a fenced frame root navigating to a URNs, in which
  // case we need to consult the `FencedFrameURLMapping` in the *outer*
  // FrameTree.
  bool is_fenced_frame_root =
      frame_tree_node_->current_frame_host()->IsFencedFrameRoot();
  FrameTreeNode* node_to_use = frame_tree_node_->frame_tree()
                                   .root()
                                   ->render_manager()
                                   ->GetOuterDelegateNode();

  // However the very unusual case is an *iframe* (that supports navigations to
  // URNs via `blink::features::IsAllowURNsInIframeEnabled`) navigating to a
  // URN, possibly *inside* of a fenced frame. We can remove support for this
  // case once third party cookies are removed.
  if (!is_fenced_frame_root) {
    node_to_use = frame_tree_node_;
  }
  DCHECK(node_to_use);
  return node_to_use->current_frame_host()->GetPage().fenced_frame_urls_map();
}

bool NavigationRequest::NeedFencedFrameURLMapping() {
  if (!blink::IsValidUrnUuidURL(common_params_->url)) {
    return false;
  }
  if (blink::features::IsAllowURNsInIframeEnabled() &&
      !frame_tree_node_->IsMainFrame() &&
      !frame_tree_node_->IsFencedFrameRoot()) {
    // When urn iframes are enabled, any urn:uuid navigation to an iframe is
    // resolved using the urn mapping.
    is_embedder_initiated_fenced_frame_navigation_ = true;
  }
  return is_embedder_initiated_fenced_frame_navigation_;
}

void NavigationRequest::OnFencedFrameURLMappingComplete(
    const std::optional<FencedFrameProperties>& properties) {
  TRACE_EVENT("navigation",
              "NavigationRequest::OnFencedFrameURLMappingComplete",
              perfetto::Flow::FromPointer(this));
  is_deferred_on_fenced_frame_url_mapping_ = false;

  // The URL mapping might have failed (e.g. because the urn is invalid):
  if (!properties.has_value()) {
    // For iframes, try the urn as-is to maintain existing behavior which will
    // abort the navigation as the url is unresolvable.
    if (!frame_tree_node_->IsFencedFrameRoot()) {
      BeginNavigationImpl();  // DO NOT ADD CODE after this, because it might
                              // have destroyed `this`.
      return;
    }

    StartNavigation();
    OnRequestFailedInternal(
        network::URLLoaderCompletionStatus(net::ERR_INVALID_URL),
        false /* skip_throttles */, std::nullopt /* error_page_content*/,
        false /* collapse_frame */);
    return;
  }

  if (properties->on_navigate_callback()) {
    properties->on_navigate_callback().Run();
  }

  // Currently, all fenced frame use cases include mapped urls. Patch up
  // url-related fields to use the underlying mapped url, rather than the
  // original urn.
  CHECK(properties->mapped_url().has_value());
  const GURL& mapped_url_value =
      properties->mapped_url()->GetValueIgnoringVisibility();
  common_params_->url = mapped_url_value;
  commit_params_->original_url = mapped_url_value;

  // Store the browser's view of the fenced frame properties along with any
  // embedder context for shared storage in the`NavigationRequest`. Upon commit,
  // it will be stored in the fenced frame root `FrameTreeNode`.
  fenced_frame_properties_ = properties;

  // Set the shared storage context in the fenced frame properties.
  DCHECK(fenced_frame_properties_);
  fenced_frame_properties_->SetEmbedderSharedStorageContext(
      embedder_shared_storage_context_);
  embedder_shared_storage_context_ = std::nullopt;

  // For urns loaded into iframes, we disable certain aspects of fenced frames:
  // * a storage/network partition nonce
  // * the ability to call window.fence.disableUntrustedNetwork
  if (!frame_tree_node_->IsFencedFrameRoot()) {
    CHECK(blink::features::IsAllowURNsInIframeEnabled());
    fenced_frame_properties_->AdjustPropertiesForUrnIframe();
  }

  // This implies the URN is created from shared storage.
  if (fenced_frame_properties_->shared_storage_budget_metadata()) {
    base::TimeDelta time_spent_in_fenced_frame_url_mapping =
        base::TimeTicks::Now() - fenced_frame_url_mapping_start_time_;

    base::UmaHistogramTimes(
        "Storage.SharedStorage.Timing.UrlMappingDuringNavigation",
        time_spent_in_fenced_frame_url_mapping);
  }

  BeginNavigationImpl();  // DO NOT ADD CODE after this, because it might have
                          // destroyed `this`.
}

void NavigationRequest::BeginNavigationImpl() {
  TRACE_EVENT("navigation", "NavigationRequest::BeginNavigationImpl",
              perfetto::Flow::FromPointer(this));
  base::ElapsedTimer timer;
  SetState(WILL_START_NAVIGATION);
#if BUILDFLAG(IS_ANDROID)
  base::WeakPtr<NavigationRequest> this_ptr(weak_factory_.GetWeakPtr());
  bool should_override_url_loading = false;

  if (!GetContentClient()->browser()->ShouldOverrideUrlLoading(
          frame_tree_node_->frame_tree_node_id(),
          commit_params_->is_browser_initiated, commit_params_->original_url,
          commit_params_->original_method, common_params_->has_user_gesture,
          false, frame_tree_node_->IsOutermostMainFrame(),
          frame_tree_node_->frame_tree().is_prerendering(),
          ui::PageTransitionFromInt(common_params_->transition),
          &should_override_url_loading)) {
    if (reserved_prerender_host_info_.has_value()) {
      // Prerender activation must not fail but some reports imply it can
      // actually be failing: crbug.com/408969974. This dump is useful for
      // debugging it.
      std::string prerender_type = GeneratePrerenderHistogramSuffix(
          GetPrerenderTriggerType(), GetPrerenderEmbedderHistogramSuffix());
      SCOPED_CRASH_KEY_STRING64("Bug411566699", "prerender_type",
                                prerender_type);
      base::debug::DumpWithoutCrashing();
    }

    // A Java exception was thrown by the embedding application; we
    // need to return from this task. Specifically, it's not safe from
    // this point on to make any JNI calls.
    return;
  }

  // The content/ embedder might cause |this| to be deleted while
  // |ShouldOverrideUrlLoading| is called.
  // See https://crbug.com/770157.
  if (!this_ptr)
    return;

  if (should_override_url_loading) {
    // Don't create a NavigationHandle here to simulate what happened with the
    // old navigation code path (i.e. doesn't fire onPageFinished notification
    // for aborted loads).
    auto completion_status =
        network::URLLoaderCompletionStatus(net::ERR_ABORTED);
    error_navigation_trigger_ =
        ErrorNavigationTrigger::kShouldOverrideUrlLoading;
    OnRequestFailedInternal(completion_status, false /*skip_throttles*/,
                            std::nullopt /*error_page_content*/,
                            false /*collapse_frame*/);
    return;
  }
#endif

  // Check Content Security Policy before the NavigationThrottles run. This
  // gives CSP a chance to modify requests that NavigationThrottles would
  // otherwise block. Similarly, the NavigationHandle is created afterwards, so
  // that it gets the request URL after potentially being modified by CSP.
  net::Error net_error = CheckContentSecurityPolicy(
      false /* has_followed redirect */,
      false /* url_upgraded_after_redirect */, false /* is_response_check */);
  if (net_error != net::OK) {
    SCOPED_CRASH_KEY_NUMBER("NavReq", "net_error", static_cast<int>(net_error));
    SCOPED_CRASH_KEY_NUMBER("NavReq", "navigating_frame_type",
                            static_cast<int>(GetNavigatingFrameType()));
    // Create a navigation handle so that the correct error code can be set on
    // it by OnRequestFailedInternal().
    StartNavigation();
    OnRequestFailedInternal(network::URLLoaderCompletionStatus(net_error),
                            false /* skip_throttles */,
                            std::nullopt /* error_page_content */,
                            false /* collapse_frame */);
    // DO NOT ADD CODE after this. The previous call to OnRequestFailedInternal
    // has destroyed the NavigationRequest.
    return;
  }

  if (CheckCredentialedSubresource() ==
      CredentialedSubresourceCheckResult::BLOCK_REQUEST) {
    // Create a navigation handle so that the correct error code can be set on
    // it by OnRequestFailedInternal().
    StartNavigation();
    auto completion_status =
        network::URLLoaderCompletionStatus(net::ERR_ABORTED);
    error_navigation_trigger_ =
        ErrorNavigationTrigger::kCredentialedSubresourceBlocked;
    OnRequestFailedInternal(completion_status, false /* skip_throttles  */,
                            std::nullopt /* error_page_content */,
                            false /* collapse_frame */);

    // DO NOT ADD CODE after this. The previous call to OnRequestFailedInternal
    // has destroyed the NavigationRequest.
    return;
  }

  StartNavigation();

  // The previous call to `StartNavigation()` could have changed the
  // is_overriding_user_agent value in CommitNavigationParams. If we're trying
  // to restore an entry from the back-forward cache, we need to ensure that
  // the is_overriding_user_agent used in the RenderFrameHost to restore matches
  // the value set in CommitNavigationParams.
  if (IsServedFromBackForwardCache() &&
      GetRenderFrameHostRestoredFromBackForwardCache()
              ->GetPage()
              .is_overriding_user_agent() !=
          commit_params_->is_overriding_user_agent) {
    // Trigger an eviction, which will cancel this navigation and trigger a new
    // one to the same entry (but won't try to restore the entry from the
    // back-forward cache) asynchronously.
    GetRenderFrameHostRestoredFromBackForwardCache()
        ->EvictFromBackForwardCacheWithReason(
            BackForwardCacheMetrics::NotRestoredReason::
                kUserAgentOverrideDiffers);
    // DO NOT ADD CODE after this. The previous call to
    // `EvictFromBackForwardCacheWithReason()`
    // has destroyed the NavigationRequest.
    return;
  }

  if (CheckAboutSrcDoc() == AboutSrcDocCheckResult::BLOCK_REQUEST) {
    OnRequestFailedInternal(
        network::URLLoaderCompletionStatus(net::ERR_INVALID_URL),
        true /* skip_throttles */, std::nullopt /* error_page_content*/,
        false /* collapse_frame */);
    // DO NOT ADD CODE after this. The previous call to OnRequestFailedInternal
    // has destroyed the NavigationRequest.
    return;
  }

  if (browser_initiated_error_navigation_type_ !=
      BrowserInitiatedErrorNavigationType::kNone) {
    OnRequestFailedInternal(network::URLLoaderCompletionStatus(net_error_),
                            true /* skip_throttles  */,
                            error_page_html_ /* error_page_content */,
                            false /* collapse_frame */);
    // DO NOT ADD CODE after this. The previous call to OnRequestFailedInternal
    // has destroyed the NavigationRequest.
    return;
  }

  if (IsForMhtmlSubframe())
    is_mhtml_or_subframe_ = true;

  // TODO(antoniosartori): This takes a snapshot of the 'csp' attribute. This
  // should be done at the beginning of the navigation instead. Otherwise, the
  // attribute might have change while waiting for the beforeunload handlers to
  // complete.
  SetupCSPEmbeddedEnforcement();

  if (!NeedsUrlLoader()) {
    // The types of pages that don't need a URL Loader should never get served
    // from the BackForwardCache or activated from a prerender.
    DCHECK(!IsServedFromBackForwardCache());
    DCHECK(!IsPrerenderedPageActivation());

    // There is no need to make a network request for this navigation, so commit
    // it immediately.
    EnterChildTraceEvent("ResponseStarted", this);

    // |CheckCSPEmbeddedEnforcement()| below populates the |required_csp_|. No
    // URLs will be blocked, because they are either:
    // - allowing blanket enforcement of CSP (about:blank, about:srcdoc, ...).
    // - MHTML document, not supported by CSPEE (https://crbug.com/1164353).
    if (CheckCSPEmbeddedEnforcement() ==
        CSPEmbeddedEnforcementResult::BLOCK_RESPONSE) {
      NOTREACHED();
    }

    ComputePoliciesToCommit();

    // Same-document navigations occur in the currently loaded document. See
    // also RenderFrameHostManager::DidCreateNavigationRequest() which will
    // expect us to use the current RenderFrameHost for this NavigationRequest,
    // and https://crbug.com/1125106.
    if (IsSameDocument()) {
      render_frame_host_ = frame_tree_node_->current_frame_host()->GetSafeRef();

      // The SiteInstance should have a site already from the navigation that
      // committed the document, unless the scheme does not require a site. Same
      // document navigations cannot change scheme or origin, so it should be
      // equivalent to check the current vs destination UrlInfo.
      DCHECK(render_frame_host_.value()->GetSiteInstance()->HasSite() ||
             !SiteInstanceImpl::ShouldAssignSiteForUrlInfo(GetUrlInfo()));

      WillCommitWithoutUrlLoader();
      return;
    } else {
      // [spec]: https://html.spec.whatwg.org/C/#process-a-navigate-response
      // 4. if [...] the result of checking a navigation response's adherence to
      // its embedder policy [...], then set failure to true.
      if (!CheckResponseAdherenceToCoep(common_params_->url)) {
        OnRequestFailedInternal(network::URLLoaderCompletionStatus(
                                    network::mojom::BlockedByResponseReason::
                                        kCoepFrameResourceNeedsCoepHeader),
                                false /* skip_throttles */,
                                std::nullopt /* error_page_content */,
                                false /* collapse_frame */);
        return;
        // DO NOT ADD CODE after this. The previous call to
        // OnRequestFailedInternal has destroyed the NavigationRequest.
      }

      // Enforce cross-origin-opener-policy for about:blank, about:srcdoc and
      // MHTML iframe, before selecting the RenderFrameHost.
      const url::Origin origin = GetOriginForURLLoaderFactoryUnchecked();
      const net::SchemefulSite site = net::SchemefulSite(origin);

      coop_status_.EnforceCOOP(
          policy_container_builder_->FinalPolicies().cross_origin_opener_policy,
          origin, net::NetworkAnonymizationKey::CreateSameSite(site));

      SelectFrameHostForCrossDocumentNavigationWithNoUrlLoader();
      return;
    }
  }

  base::UmaHistogramTimes(
      base::StrCat({"Navigation.BeginNavigationImpl.",
                    IsInMainFrame() ? "MainFrame" : "Subframe"}),
      timer.Elapsed());
  WillStartRequest();
  // DO NOT ADD CODE AFTER THIS, as the NavigationRequest might have been
  // deleted by the previous calls.
}

void NavigationRequest::
    SelectFrameHostForCrossDocumentNavigationWithNoUrlLoader() {
  DCHECK(!NeedsUrlLoader());
  CHECK(!HasRenderFrameHost())
      << "`render_frame_host_` should not be set before the "
         "`NavigationRequest` starts to select the RFH.";

  if (auto result =
          frame_tree_node_->render_manager()->GetFrameHostForNavigation(
              this, &browsing_context_group_swap_,
              ProcessAllocationContext::CreateForNavigationRequest(
                  ProcessAllocationNavigationStage::kNoURLLoader,
                  navigation_id_, IsInOutermostMainFrame()));
      result.has_value()) {
    render_frame_host_ = result.value()->GetSafeRef();
  } else {
    switch (result.error()) {
      case GetFrameHostForNavigationFailed::kCouldNotReinitializeMainFrame:
        // TODO(crbug.com/40250311): This was unhandled before and
        // remains explicitly unhandled. This branch may be removed in the
        // future.
        break;
      case GetFrameHostForNavigationFailed::kBlockedByPendingCommit:
        resume_commit_closure_ = base::BindOnce(
            &NavigationRequest::
                SelectFrameHostForCrossDocumentNavigationWithNoUrlLoader,
            weak_factory_.GetWeakPtr());
        frame_tree_node_->render_manager()
            ->speculative_frame_host()
            ->RecordMetricsForBlockedGetFrameHostAttempt(
                /* commit_attempt=*/true);
        return;
    }
  }

  CHECK(Navigator::CheckWebUIRendererDoesNotDisplayNormalURL(
      &*render_frame_host_.value(), GetUrlInfo(),
      /*is_renderer_initiated_check=*/false));

  auto* site_instance = render_frame_host_.value()->GetSiteInstance();
  if (!site_instance->HasSite() &&
      SiteInstanceImpl::ShouldAssignSiteForUrlInfo(GetUrlInfo())) {
    site_instance->ConvertToDefaultOrSetSite(GetUrlInfo());
  }

  WillCommitWithoutUrlLoader();
}

void NavigationRequest::SetWaitingForRendererResponse() {
  EnterChildTraceEvent("WaitingForRendererResponse", this);
  SetState(WAITING_FOR_RENDERER_RESPONSE);
}

bool NavigationRequest::ShouldAddCookieChangeListener() {
  // Cookies can only be set for http/http(s) URLs, so only create listeners
  // for those navigations. Also only create for non-activation cross-document
  // primary main frame navigations (or if
  // `ShouldAddDeviceBoundSessionObserver()` returns true, which allows
  // prerenders).
  return (!IsPageActivation() && !IsSameDocument() && IsInPrimaryMainFrame() &&
          common_params_->url.SchemeIsHTTPOrHTTPS()) ||
         ShouldAddDeviceBoundSessionObserver();
}

bool NavigationRequest::DidCookiesChangeAfterStart(
    bool exclude_http_only) const {
  CHECK(HasCookieChangeListener());
  if (exclude_http_only) {
    return cookie_change_listener_->cookie_change_info()
        .non_http_only_cookie_modification_count;
  }
  return cookie_change_listener_->cookie_change_info()
      .cookie_modification_count;
}

bool NavigationRequest::ShouldAddDeviceBoundSessionObserver() {
  // Only add if all of these are true:
  // (1) the navigation's protocol is HTTP(s).
  // (2) we allow a document with `Cache-control: no-store` header to
  // enter back/forward.
  // (3) the navigation is neither a same-document navigation nor a page
  // activation, since in these cases, an existing `RenderFrameHost` will be
  // used, and it would already have an existing listener, so we should skip the
  // initialization.
  // (4) the navigation is a primary main frame navigation or it's for
  // prerendering a main frame, as the device-bound session change information
  // will only be used to determine if a page can be restored from back/forward
  // cache, so subframe navigation can be ignored.
  return frame_tree_node_->navigator()
             .controller()
             .GetBackForwardCache()
             .should_allow_storing_pages_with_cache_control_no_store() &&
         !IsPageActivation() && !IsSameDocument() &&
         (IsInPrimaryMainFrame() || IsInPrerenderedMainFrame()) &&
         common_params_->url.SchemeIsHTTPOrHTTPS();
}

void NavigationRequest::StartNavigation() {
  TRACE_EVENT("navigation", "NavigationRequest::StartNavigation",
              perfetto::Flow::FromPointer(this));
  DCHECK(frame_tree_node_->navigation_request() == this ||
         is_synchronous_renderer_commit_);
  FrameTreeNode* frame_tree_node = frame_tree_node_;

  MaybeAssignInvalidPrerenderFrameTreeNodeId();

  // This is needed to get site URLs and assign the expected RenderProcessHost.
  // This is not always the same as |source_site_instance_|, as it only depends
  // on the current frame host, and does not depend on |entry|.
  // The |starting_site_instance_| needs to be set here instead of the
  // constructor since a navigation can be started after the constructor and
  // before here, which can set a different RenderFrameHost and a different
  // starting SiteInstance.
  starting_site_instance_ =
      frame_tree_node->current_frame_host()->GetSiteInstance();
  site_info_ = GetSiteInfoForCommonParamsURL();

  // It's important to start listening to the cookie changes before the network
  // request of the navigation begins in order to ensure the listener won't miss
  // any cookie changes that happen after the network request is sent that
  // potentially modify some cookie values that are used in this request.
  // The information of cookie modification will be used to determine if the
  // document that this navigation will load should be eligible for BFCache.
  // The listener eventually will be transferred over to the committed
  // `RenderFrameHost`.
  // The listener should receive the change events of the cookies from the
  // the domain of the main-frame navigation url.
  // If the navigation gets redirected, it will be reset with the new URL when
  // `NavigationRequest::OnRequestRedirected()` is called.
  if (ShouldAddCookieChangeListener()) {
    // The listener should receive the change events of the cookies from the
    // the domain of the main-frame navigation url.
    // If the navigation gets redirected, it will be reset with the new URL when
    // `NavigationRequest::OnRequestRedirected()` is called.
    cookie_change_listener_ =
        std::make_unique<RenderFrameHostImpl::CookieChangeListener>(
            GetStoragePartitionWithCurrentSiteInfo(), common_params_->url);
  }

  if (ShouldAddDeviceBoundSessionObserver()) {
    device_bound_session_observer_ =
        std::make_unique<RenderFrameHostImpl::DeviceBoundSessionObserver>(
            GetStoragePartitionWithCurrentSiteInfo(), common_params_->url);
  }

  // Compute the redirect chain.
  // TODO(clamy): Try to simplify this and have the redirects be part of
  // CommonNavigationParams.
  redirect_chain_.clear();
  if (!begin_params_->client_side_redirect_url.is_empty()) {
    // |begin_params_->client_side_redirect_url| will be set when the navigation
    // was triggered by a client-side redirect.
    redirect_chain_.push_back(begin_params_->client_side_redirect_url);
  } else if (!commit_params_->redirects.empty()) {
    // Redirects that were specified at NavigationRequest creation time should
    // be added to the list of redirects. In particular, if the
    // NavigationRequest was created at commit time, redirects that happened
    // during the navigation have been added to |commit_params_->redirects| and
    // should be passed to the NavigationHandle.
    for (const auto& url : commit_params_->redirects)
      redirect_chain_.push_back(url);
  }

  // Finally, add the current URL to the vector of redirects.
  // Note: for NavigationRequests created at commit time, the current URL has
  // been added to |commit_params_->redirects|, so don't add it a second time.
  if (!is_synchronous_renderer_commit_) {
    if (!common_params_->base_url_for_data_url.is_empty()) {
      // If this is a loadDataWithBaseURL/loadDataAsStringWithBaseUrl
      // navigation, use the base URL instead of the data: URL used for commit.
      redirect_chain_.push_back(common_params_->base_url_for_data_url);
    } else {
      redirect_chain_.push_back(common_params_->url);
    }
  }

  // Mirrors the logic in RenderFrameImpl::SendDidCommitProvisionalLoad.
  if (common_params_->transition & ui::PAGE_TRANSITION_CLIENT_REDIRECT) {
    // If the page contained a client redirect (meta refresh,
    // document.location), set the referrer appropriately.
    // Note that this value will stay the same, even after cross-origin
    // redirects. This means the referrer URL and policy in
    // `sanitized_referrer_` might not be the same as the actual referrer sent
    // for the final navigation request (which will be updated/re-sanitized on
    // each redirect).
    // TODO(crbug.com/40771822): Remove this special case, and also
    // `sanitized_referrer_` entirely, in favor of CommonNavigationParams'
    // `referrer`, which will be properly sanitized after each redirect.
    sanitized_referrer_ = blink::mojom::Referrer::New(
        redirect_chain_[0], Referrer::SanitizeForRequest(
                                common_params_->url, *common_params_->referrer)
                                ->policy);
  } else {
    sanitized_referrer_ = Referrer::SanitizeForRequest(
        common_params_->url, *common_params_->referrer);
  }

  // If the navigation explicitly requested for history list clearing (e.g. when
  // running layout tests), don't do a replacement (since there won't be any
  // entry to replace after the navigation).
  if (commit_params_->should_clear_history_list) {
    common_params_->should_replace_current_entry = false;
  } else if (
      ShouldReplaceCurrentEntryForSameUrlNavigation() ||
      ShouldReplaceCurrentEntryForNavigationFromInitialEmptyDocumentOrEntry()) {
    common_params_->should_replace_current_entry = true;
  }

  // Set the expected process for this navigation, if we can. The navigation
  // might not have an associated RenderFrameHost yet, which is possible if it
  // can't create a speculative RenderFrameHost when there's a pending commit
  // navigation (when navigation queueing is enabled), or it had an associated
  // RenderFrameHost when the NavigationRequest was created but another
  // navigation had committed in between that time and StartNavigation, which
  // invalidates the `associated_rfh_type_`, or it's intentionally deferred with
  // feature flag DeferSpeculativeRFHCreation. It's fine to skip setting the
  // expected process in this case, as we'll set the expected process again from
  // ReadyToCommitNavigation(), when we know the final RenderFrameHost for the
  // navigation.
  SetExpectedProcessIfAssociated();

  DCHECK(!IsNavigationStarted());
  SetState(WILL_START_REQUEST);
  is_navigation_started_ = true;

  modified_request_headers_.Clear();
  removed_request_headers_.clear();

  throttle_registry_ = std::make_unique<NavigationThrottleRegistryImpl>(this);

  // For prerendered page activation, CommitDeferringConditions have already run
  // at the beginning of the navigation, so we won't run them again.
  // ProcessSelectionDeferringConditions also don't need to run for prerendered
  // page activations because those have already selected a process.
  if (!IsPrerenderedPageActivation()) {
    commit_deferrer_ = CommitDeferringConditionRunner::Create(
        *this, CommitDeferringCondition::NavigationType::kOther,
        /*candidate_prerender_frame_tree_node_id=*/std::nullopt);
    if (base::FeatureList::IsEnabled(
            features::kProcessSelectionDeferringConditions)) {
      process_selection_deferrer_ =
          ProcessSelectionDeferringConditionRunner::Create(*this);
    }
  }

  navigation_visible_to_embedder_ = true;
#if BUILDFLAG(IS_ANDROID)
  // Once the navigation has started, fill in the details in the Java side
  // navigation handle.
  navigation_handle_proxy_->DidStart();
#endif

  if (IsInMainFrame()) {
    DCHECK(!common_params_->navigation_start.is_null());
    DCHECK(!blink::IsRendererDebugURL(common_params_->url));
    TRACE_EVENT_BEGIN("navigation", "Navigation StartToCommit",
                      perfetto::NamedTrack("StartToCommit",
                                           reinterpret_cast<uintptr_t>(this)),
                      common_params_->navigation_start, "Initial URL",
                      common_params_->url.spec());
  }

  if (IsSameDocument()) {
    EnterChildTraceEvent("Same document", this);
  }

  {
#if DCHECK_IS_ON()
    DCHECK(is_safe_to_delete_);
    base::AutoReset<bool> resetter(&is_safe_to_delete_, false);
#endif
    base::AutoReset<bool> resetter2(&ua_change_requires_reload_, false);
    GetDelegate()->DidStartNavigation(this);
  }
}

void NavigationRequest::ResetForCrossDocumentRestart() {
  DCHECK(IsSameDocument());

  // TODO(crbug.com/40055210): A same document history navigation was performed
  // but the renderer thinks there's a different document loaded. Where did
  // this navigation come from?
  if (common_params_->navigation_type ==
      blink::mojom::NavigationType::HISTORY_SAME_DOCUMENT) {
    CaptureTraceForNavigationDebugScenario(
        DebugScenario::kDebugSameDocNavigationDocIdMismatch);
  }

  // Reset the NavigationHandle, which is now incorrectly marked as
  // same-document. Ensure |loader_| does not exist as it can hold raw pointers
  // to objects owned by the handle (see the comment in the header).
  DCHECK(!loader_);

#if BUILDFLAG(IS_ANDROID)
  if (navigation_visible_to_embedder_)
    navigation_handle_proxy_->DidFinish();
#endif

  // Set this bit so the observers on `DidFinishNavigation()` are also aware of
  // the restart.
  was_reset_for_cross_document_restart_ = true;

  // It is necessary to call DidFinishNavigation before resetting
  // |navigation_handle_proxy_|. See https://crbug.com/958396.
  if (IsNavigationStarted()) {
    GetDelegate()->DidFinishNavigation(this);
    if (IsInMainFrame()) {
      // Navigation StartToCommit
      TRACE_EVENT_END("navigation",
                      perfetto::NamedTrack("StartToCommit",
                                           reinterpret_cast<uintptr_t>(this)),
                      "URL", common_params_->url.spec(), "Net Error Code",
                      net_error_);
    }
  }

  // Reset the state of the NavigationRequest, and the navigation_handle_id.
  StopCommitTimeout();
  SetState(NOT_STARTED);
  is_navigation_started_ = false;
  processing_navigation_throttle_ = false;

  navigation_visible_to_embedder_ = false;
#if BUILDFLAG(IS_ANDROID)
  if (navigation_visible_to_embedder_) {
    navigation_handle_proxy_.reset();
    navigation_handle_proxy_ = std::make_unique<NavigationHandleProxy>(this);
  }
#endif

  // Reset the previously selected RenderFrameHost. This is expected to be null
  // at the beginning of a new navigation. See https://crbug.com/936962.
  DCHECK(HasRenderFrameHost());
  render_frame_host_ = std::nullopt;

  // Convert the navigation type to the appropriate cross-document one.
  common_params_->navigation_type =
      ConvertToCrossDocumentType(common_params_->navigation_type);

  // Reset navigation handle timings.
  navigation_handle_timing_ = NavigationHandleTiming();

  policy_container_builder_->ResetForCrossDocumentRestart();
  commit_params_->soft_navigation_heuristics_task_id = std::nullopt;

  CheckSoftNavigationHeuristicsInvariants();
}

void NavigationRequest::ResetStateForSiteInstanceChange() {
  // This method should only be called when there is a dest_site_instance.
  DCHECK(dest_site_instance_);

  // When a request has a destination SiteInstance (e.g., reload or session
  // history navigation) but it changes during the navigation (e.g., due to
  // redirect or error page), it's important not to remember privileges or
  // attacker-controlled state from the original entry.

  // Reset bindings (e.g., since error pages for WebUI URLs don't get them).
  bindings_.reset();

  // Reset any existing PageState with a non-empty, clean PageState, so that old
  // attacker-controlled state is not pulled into the new process.
  blink::PageState page_state =
      blink::PageState::CreateFromEncodedData(commit_params_->page_state);
  if (page_state.IsValid())
    commit_params_->page_state =
        blink::PageState::CreateFromURL(GetURL()).ToEncodedData();

  // ISNs and DSNs are process-specific.
  frame_entry_item_sequence_number_ = -1;
  frame_entry_document_sequence_number_ = -1;
}

void NavigationRequest::RegisterSubresourceOverride(
    blink::mojom::TransferrableURLLoaderPtr transferrable_loader) {
  if (!transferrable_loader)
    return;
  if (!subresource_overrides_)
    subresource_overrides_.emplace();

  subresource_overrides_->push_back(std::move(transferrable_loader));
}

mojom::NavigationClient* NavigationRequest::GetCommitNavigationClient() {
  if (commit_navigation_client_ && commit_navigation_client_.is_bound())
    return commit_navigation_client_.get();

  // Instantiate a new NavigationClient interface.
  commit_navigation_client_ =
      GetRenderFrameHost()->GetNavigationClientFromInterfaceProvider();
  HandleInterfaceDisconnection(commit_navigation_client_);
  return commit_navigation_client_.get();
}

void NavigationRequest::SetRequiredCSP(
    network::mojom::ContentSecurityPolicyPtr csp) {
  DCHECK(!required_csp_);
  required_csp_ = std::move(csp);
  if (required_csp_)
    SetRequestHeader("Sec-Required-CSP", required_csp_->header->header_value);
}

network::mojom::ContentSecurityPolicyPtr NavigationRequest::TakeRequiredCSP() {
  return std::move(required_csp_);
}

const PolicyContainerPolicies*
NavigationRequest::GetInitiatorPolicyContainerPolicies() const {
  return policy_container_builder_->InitiatorPolicies();
}

const blink::DocumentToken& NavigationRequest::GetDocumentToken() const {
  DCHECK(!IsSameDocument());
  DCHECK_GE(state_, READY_TO_COMMIT);

  return *document_token_;
}

const PolicyContainerPolicies& NavigationRequest::GetPolicyContainerPolicies()
    const {
  DCHECK_GE(state_, READY_TO_COMMIT);

  return policy_container_builder_->FinalPolicies();
}

blink::mojom::PolicyContainerPtr
NavigationRequest::CreatePolicyContainerForBlink() {
  DCHECK_GE(state_, READY_TO_COMMIT);

  return policy_container_builder_->CreatePolicyContainerForBlink();
}
scoped_refptr<PolicyContainerHost> NavigationRequest::GetPolicyContainerHost() {
  DCHECK_GE(state_, READY_TO_COMMIT);
  // It is invalid calling this method after `TakePolicyContainerHost()`.
  CHECK(policy_container_builder_);
  return policy_container_builder_->GetPolicyContainerHost();
}

scoped_refptr<PolicyContainerHost>
NavigationRequest::TakePolicyContainerHost() {
  DCHECK_GE(state_, READY_TO_COMMIT);

  // Move the host out of the data member, then reset the member. This ensures
  // we do not use the helper after we moved its contents.
  scoped_refptr<PolicyContainerHost> host =
      std::move(*policy_container_builder_).TakePolicyContainerHost();
  policy_container_builder_ = std::nullopt;

  return host;
}

void NavigationRequest::CreateCoepReporter(
    StoragePartition* storage_partition) {
  DCHECK(!isolation_info_for_subresources_.IsEmpty());

  const PolicyContainerPolicies& policies =
      policy_container_builder_->FinalPolicies();
  coep_reporter_ = std::make_unique<CrossOriginEmbedderPolicyReporter>(
      static_cast<StoragePartitionImpl*>(storage_partition)->GetWeakPtr(),
      common_params_->url,
      policies.cross_origin_embedder_policy.reporting_endpoint,
      policies.cross_origin_embedder_policy.report_only_reporting_endpoint,
      GetRenderFrameHost()->GetFrameToken().value(),
      isolation_info_for_subresources_.network_anonymization_key());
}

std::unique_ptr<CrossOriginEmbedderPolicyReporter>
NavigationRequest::TakeCoepReporter() {
  return std::move(coep_reporter_);
}

void NavigationRequest::CreateDipReporter(StoragePartition* storage_partition) {
  DCHECK(!isolation_info_for_subresources_.IsEmpty());

  const PolicyContainerPolicies& policies =
      policy_container_builder_->FinalPolicies();
  dip_reporter_ = std::make_unique<DocumentIsolationPolicyReporter>(
      static_cast<StoragePartitionImpl*>(storage_partition)->GetWeakPtr(),
      common_params_->url,
      policies.document_isolation_policy.reporting_endpoint,
      policies.document_isolation_policy.report_only_reporting_endpoint,
      GetRenderFrameHost()->GetFrameToken().value(),
      isolation_info_for_subresources_.network_anonymization_key());
}

std::unique_ptr<DocumentIsolationPolicyReporter>
NavigationRequest::TakeDipReporter() {
  return std::move(dip_reporter_);
}

ukm::SourceId NavigationRequest::GetPreviousPageUkmSourceId() {
  return previous_page_ukm_source_id_;
}

bool NavigationRequest::ShouldClearParsedHeadersOnTestReceiveRedirect() {
  // This method is only for testing and thus must do nothing and return `false`
  // here.
  return false;
}

void NavigationRequest::OnRequestRedirected(
    const net::RedirectInfo& redirect_info,
    const net::NetworkAnonymizationKey& network_anonymization_key,
    network::mojom::URLResponseHeadPtr response_head) {
  TRACE_EVENT("navigation", "NavigationRequest::OnRequestRedirected",
              perfetto::Flow::FromPointer(this));
  ScopedCrashKeys crash_keys(*this);

  // Sanity check - this can only be set at commit time.
  DCHECK(!auth_challenge_info_);

  DCHECK(response_head);
  DCHECK(response_head->parsed_headers);
  response_head_ = std::move(response_head);
  ssl_info_ = response_head_->ssl_info;

  // Reset the page state as it can no longer be used at commit time since the
  // navigation was redirected.
  commit_params_->page_state = std::string();

  // Reset NotRestoredReasons as the reasons are for the original page and not
  // for the redirected one.
  commit_params_->not_restored_reasons = nullptr;

  // Reset the tentative origin_to_commit, as the redirected one is different.
  tentative_data_origin_to_commit_ = std::nullopt;

  // A request was made. Record it before we decide to block this response for
  // a reason or another.
  RecordAddressSpaceFeature();

#if BUILDFLAG(IS_ANDROID)
  base::WeakPtr<NavigationRequest> this_ptr(weak_factory_.GetWeakPtr());

  bool should_override_url_loading = false;
  if (!GetContentClient()->browser()->ShouldOverrideUrlLoading(
          frame_tree_node_->frame_tree_node_id(),
          commit_params_->is_browser_initiated, redirect_info.new_url,
          redirect_info.new_method,
          // Redirects are always not counted as from user gesture.
          false, true, frame_tree_node_->IsOutermostMainFrame(),
          frame_tree_node_->frame_tree().is_prerendering(),
          ui::PageTransitionFromInt(common_params_->transition),
          &should_override_url_loading)) {
    // A Java exception was thrown by the embedding application; we
    // need to return from this task. Specifically, it's not safe from
    // this point on to make any JNI calls.
    return;
  }

  // The content/ embedder might cause |this| to be deleted while
  // |ShouldOverrideUrlLoading| is called.
  // See https://crbug.com/770157.
  if (!this_ptr)
    return;

  if (should_override_url_loading) {
    net_error_ = net::ERR_ABORTED;
    error_navigation_trigger_ =
        ErrorNavigationTrigger::kShouldOverrideUrlLoading;
    common_params_->url = redirect_info.new_url;
    common_params_->method = redirect_info.new_method;
    // Update the navigation handle to point to the new url to ensure
    // AwWebContents sees the new URL and thus passes that URL to onPageFinished
    // (rather than passing the old URL).
    UpdateStateFollowingRedirect(GURL(redirect_info.new_referrer));
    frame_tree_node_->ResetNavigationRequest(
        NavigationDiscardReason::kInternalCancellation);
    return;
  }
#endif
  if (!ChildProcessSecurityPolicyImpl::GetInstance()->CanRedirectToURL(
          redirect_info.new_url)) {
    DVLOG(1) << "Denied redirect for "
             << redirect_info.new_url.possibly_invalid_spec();
    // TODO(arthursonzogni): Redirect to a javascript URL should display an
    // error page with the net::ERR_UNSAFE_REDIRECT error code. Instead, the
    // browser simply ignores the navigation, because some extensions use this
    // edge case to silently cancel navigations. See https://crbug.com/941653.
    auto completion_status =
        network::URLLoaderCompletionStatus(net::ERR_ABORTED);
    error_navigation_trigger_ = ErrorNavigationTrigger::kRedirectNotAllowed;
    OnRequestFailedInternal(completion_status, false /* skip_throttles */,
                            std::nullopt /* error_page_content */,
                            false /* collapse_frame */);
    // DO NOT ADD CODE after this. The previous call to OnRequestFailedInternal
    // has destroyed the NavigationRequest.
    return;
  }

  // For renderer-initiated navigations we need to check if the source has
  // access to the URL. Browser-initiated navigations only rely on the
  // |CanRedirectToURL| test above.
  // TODO(crbug.com/388998723): The check may unintentionally create a process
  // for the source site instance. Consider removing this potential process
  // creation while keeping the security check.
  if (!commit_params_->is_browser_initiated && GetSourceSiteInstance() &&
      !ChildProcessSecurityPolicyImpl::GetInstance()->CanRequestURL(
          GetSourceSiteInstance()
              ->GetOrCreateProcess(ProcessAllocationContext{
                  ProcessAllocationSource::kCanRequestURL})
              ->GetDeprecatedID(),
          redirect_info.new_url)) {
    DVLOG(1) << "Denied unauthorized redirect for "
             << redirect_info.new_url.possibly_invalid_spec();
    auto completion_status =
        network::URLLoaderCompletionStatus(net::ERR_ABORTED);
    error_navigation_trigger_ =
        ErrorNavigationTrigger::kRendererInitiatedCanNotRequestURL;
    // TODO(arthursonzogni): This case uses ERR_ABORTED to be consistent with
    // the javascript URL redirect case above, though ideally it would use
    // net::ERR_UNSAFE_REDIRECT and an error page. See https://crbug.com/941653.
    OnRequestFailedInternal(completion_status, false /* skip_throttles */,
                            std::nullopt /* error_page_content */,
                            false /* collapse_frame */);
    // DO NOT ADD CODE after this. The previous call to OnRequestFailedInternal
    // has destroyed the NavigationRequest.
    return;
  }

  const std::optional<network::mojom::BlockedByResponseReason>
      coop_requires_blocking =
          coop_status_.SanitizeResponse(response_head_.get());
  if (coop_requires_blocking) {
    OnRequestFailedInternal(
        network::URLLoaderCompletionStatus(*coop_requires_blocking),
        false /* skip_throttles */, std::nullopt /* error_page_content */,
        false /* collapse_frame */);
    // DO NOT ADD CODE after this. The previous call to
    // OnRequestFailedInternal has destroyed the NavigationRequest.
    return;
  }
  const url::Origin origin = GetOriginForURLLoaderFactoryUnchecked();
  coop_status_.EnforceCOOP(
      response()->parsed_headers->cross_origin_opener_policy, origin,
      network_anonymization_key);

  const std::optional<network::mojom::BlockedByResponseReason>
      coep_requires_blocking = EnforceCOEP();
  if (coep_requires_blocking) {
    OnRequestFailedInternal(
        network::URLLoaderCompletionStatus(*coep_requires_blocking),
        false /* skip_throttles */, std::nullopt /* error_page_content */,
        false /* collapse_frame */);
    // DO NOT ADD CODE after this. The previous call to
    // OnRequestFailedInternal has destroyed the NavigationRequest.
    return;
  }

  // For now, DevTools needs the POST data sent to the renderer process even if
  // it is no longer a POST after the redirect.
  if (redirect_info.new_method != "POST")
    common_params_->post_data.reset();

  const bool is_first_response = commit_params_->redirects.empty();
  UpdateNavigationHandleTimingsOnResponseReceived(/*is_redirect=*/true,
                                                  is_first_response);

  // Mark time for the Navigation Timing API.
  if (commit_params_->navigation_timing->redirect_start.is_null()) {
    commit_params_->navigation_timing->redirect_start =
        commit_params_->navigation_timing->fetch_start;
  }
  commit_params_->navigation_timing->redirect_end = base::TimeTicks::Now();
  commit_params_->navigation_timing->fetch_start = base::TimeTicks::Now();

  commit_params_->redirect_response.push_back(response_head_.Clone());
  commit_params_->redirect_infos.push_back(redirect_info);

  // TODO(rakina): This should use `GetTentativeOriginAtRequestTime()` instead
  // of the url from `common_params_`.
  const bool is_same_origin_redirect =
      url::Origin::Create(common_params_->url)
          .IsSameOriginWith(redirect_info.new_url);

  did_encounter_cross_origin_redirect_ |= !is_same_origin_redirect;

  // Only same-origin navigations without cross-origin redirects can
  // expose response details (status-code / mime-type).
  // https://github.com/whatwg/fetch/issues/1602
  if (!is_same_origin_redirect &&
      commit_params_->navigation_timing->parent_resource_timing_access ==
          blink::mojom::ParentResourceTimingAccess::
              kReportWithResponseDetails) {
    commit_params_->navigation_timing->parent_resource_timing_access =
        blink::mojom::ParentResourceTimingAccess::kReportWithoutResponseDetails;
  }

  did_receive_early_hints_before_cross_origin_redirect_ |=
      did_create_early_hints_manager_params_ && !is_same_origin_redirect;

  commit_params_->redirects.push_back(common_params_->url);
  common_params_->url = redirect_info.new_url;
  common_params_->method = redirect_info.new_method;
  common_params_->referrer->url = GURL(redirect_info.new_referrer);
  common_params_->referrer = Referrer::SanitizeForRequest(
      common_params_->url, *common_params_->referrer);

  // On redirects, the initial referrer is no longer correct, so it must
  // be updated.  (A parallel process updates the outgoing referrer in the
  // network stack.)
  commit_params_->redirect_infos.back().new_referrer =
      common_params_->referrer->url.spec();

  // When the redirection happens, the cookie_change_listener_ should be
  // re-initialized if needed.
  if (ShouldAddCookieChangeListener()) {
    cookie_change_listener_ =
        std::make_unique<RenderFrameHostImpl::CookieChangeListener>(
            GetStoragePartitionWithCurrentSiteInfo(), common_params_->url);
  } else {
    cookie_change_listener_.reset();
  }

  if (ShouldAddDeviceBoundSessionObserver()) {
    device_bound_session_observer_ =
        std::make_unique<RenderFrameHostImpl::DeviceBoundSessionObserver>(
            GetStoragePartitionWithCurrentSiteInfo(), common_params_->url);
  } else {
    device_bound_session_observer_.reset();
  }

  // Check Content Security Policy before the NavigationThrottles run. This
  // gives CSP a chance to modify requests that NavigationThrottles would
  // otherwise block.
  net::Error net_error =
      CheckContentSecurityPolicy(true /* has_followed_redirect */,
                                 redirect_info.insecure_scheme_was_upgraded,
                                 false /* is_response_check */);
  if (net_error != net::OK) {
    OnRequestFailedInternal(
        network::URLLoaderCompletionStatus(net_error), false /*skip_throttles*/,
        std::nullopt /*error_page_content*/, false /*collapse_frame*/);

    // DO NOT ADD CODE after this. The previous call to OnRequestFailedInternal
    // has destroyed the NavigationRequest.
    return;
  }

  if (CheckCredentialedSubresource() ==
      CredentialedSubresourceCheckResult::BLOCK_REQUEST) {
    auto completion_status =
        network::URLLoaderCompletionStatus(net::ERR_ABORTED);
    error_navigation_trigger_ =
        ErrorNavigationTrigger::kCredentialedSubresourceBlocked;
    OnRequestFailedInternal(completion_status, false /*skip_throttles*/,
                            std::nullopt /*error_page_content*/,
                            false /*collapse_frame*/);

    // DO NOT ADD CODE after this. The previous call to OnRequestFailedInternal
    // has destroyed the NavigationRequest.
    return;
  }

  if (process_selection_deferrer_) {
    // Start any process selection dependencies using the redirected URL.
    process_selection_deferrer_->OnRequestRedirected();
  }

  // Compute the SiteInstance to use for the redirect and pass its
  // RenderProcessHost if it has a process. Keep a reference if it has a
  // process, so that the SiteInstance and its associated process aren't deleted
  // before the navigation is ready to commit.
  scoped_refptr<SiteInstance> site_instance =
      frame_tree_node_->render_manager()->GetSiteInstanceForNavigationRequest(
          this, &browsing_context_group_swap_);
  speculative_site_instance_ =
      site_instance->HasProcess() ? site_instance : nullptr;

  // If the new site instance doesn't yet have a process, then tell the
  // SpareRenderProcessHostManager so it can decide whether to start warming up
  // the spare at this time (note that the actual behavior depends on
  // RenderProcessHostImpl::IsSpareProcessKeptAtAllTimes).
  if (!site_instance->HasProcess()) {
    RenderProcessHostImpl::NotifySpareManagerAboutRecentlyUsedSiteInstance(
        site_instance.get());
  }

  // Check what the process of the SiteInstance is. It will be passed to the
  // NavigationHandle, and informed to expect a navigation to the redirected
  // URL.
  // TODO(crbug.com/388998723): Remove the comment about the side effect
  // of GetProcess() after the full migration to GetOrCreateProcess().
  // Note: calling GetProcess on the SiteInstance can lead to the creation of a
  // new process if it doesn't have one. In this case, it should only be called
  // on a SiteInstance that already has a process.
  RenderProcessHost* expected_process =
      site_instance->HasProcess() ? site_instance->GetProcess() : nullptr;

  WillRedirectRequest(common_params_->referrer->url, expected_process);
}

base::WeakPtr<NavigationRequest> NavigationRequest::GetWeakPtr() {
  return weak_factory_.GetWeakPtr();
}

base::SafeRef<NavigationHandle> NavigationRequest::GetSafeRef() {
  return weak_factory_.GetSafeRef();
}

bool NavigationRequest::ExistingDocumentWasDiscarded() const {
  return commit_params_->was_discarded;
}

void NavigationRequest::SetContentSettings(
    blink::mojom::RendererContentSettingsPtr content_settings) {
  commit_params_->content_settings = std::move(content_settings);
}

blink::mojom::RendererContentSettingsPtr
NavigationRequest::GetContentSettingsForTesting() {
  return commit_params_->content_settings->Clone();
}

void NavigationRequest::SetIsAdTagged() {
  is_ad_tagged_ = true;
}

void NavigationRequest::CheckForIsolationOptIn(const GURL& url) {
  // Check whether an origin-keyed agent cluster is explicitly requested, either
  // opting in or out, before attempting to isolate it. If an explicit request
  // was made, then we must check if the origin has been previously
  // encountered in order to remain consistent within the isolation context
  // (BrowserContext). Note: we only do the global walk for explicit opt-outs
  // when OriginAgentCluster-by-default is enabled, but that check is made in
  // IsOriginAgentClusterOptOutRequested().
  if (!IsOriginAgentClusterOptInRequested() &&
      !IsOriginAgentClusterOptOutRequested())
    return;

  auto* policy = ChildProcessSecurityPolicyImpl::GetInstance();
  url::Origin origin = url::Origin::Create(url);
  auto* browser_context =
      frame_tree_node_->navigator().controller().GetBrowserContext();
  if (policy->UpdateOriginIsolationOptInListIfNecessary(browser_context,
                                                        origin)) {
    // This is a new request for isolating |origin|, either by explicitly opting
    // it in or out. Do a global walk of session history to find any existing
    // instances of |origin|, so that those existing BrowsingInstances can give
    // it default isolation. Only new BrowsingInstances and ones that have not
    // seen |origin| before will honor the request. We don't always have a value
    // for render_frame_host_ at this point, so we map the global-walk call onto
    // NavigatorDelegate to get it into WebContents. We definitely need to do
    // the global walk prior to deciding on the render_frame_host_ to commit to.
    // We must exclude ourselves from the global walk otherwise we may mark our
    // origin as having default isolation before it gets the change to register
    // itself as opted-in/out.
    frame_tree_node_->navigator()
        .GetDelegate()
        ->RegisterExistingOriginAsHavingDefaultIsolation(
            origin, this /* navigation_request_to_exclude */);
  }
}

void NavigationRequest::AddOriginAgentClusterStateIfNecessary(
    const IsolationContext& isolation_context) {
  std::optional<OriginAgentClusterIsolationState> oac_isolation_state;
  if (IsOriginAgentClusterOptInRequested()) {
    // Normally for explicit opt-ins the origin is tracked when we create the
    // SiteInstance, but there are two cases where that fails. (1) If process-
    // isolation for OAC is not enabled we need to track opt-in here (used for
    // origin-agent-cluster-by-default), and (2) if origin-keyed processes by
    // default is enabled, then it's possible we got here due to using a
    // speculative RenderFrameHost. In this latter case, the opt-in header had
    // not arrived when the SiteInstance was created, so the origin was not
    // tracked earlier.
    oac_isolation_state =
        OriginAgentClusterIsolationState::CreateForOriginAgentCluster(
            /*had_oac_request=*/true,
            SiteIsolationPolicy::
                IsProcessIsolationForOriginAgentClusterEnabled());
  } else if (IsOriginAgentClusterOptOutRequested()) {
    // Since opt-outs are asking not to have OAC or
    // requires_origin_keyed_process, they don't get their own SiteInstance, and
    // so we must register their opt-out here.
    oac_isolation_state =
        OriginAgentClusterIsolationState::CreateNonIsolatedByHeader();
  }

  if (!oac_isolation_state.has_value()) {
    return;
  }

  // We never register isolation state here unless it's explicitly requested.
  CHECK(oac_isolation_state->logical_oac_status() ==
            AgentClusterKey::OACStatus::kSiteKeyedByHeader ||
        oac_isolation_state->logical_oac_status() ==
            AgentClusterKey::OACStatus::kOriginKeyedByHeader);

  // Note: we don't handle IsIsolationImplied() cases here, since those only
  // occur when OAC-by-default is enabled, and in that case we only pro-actively
  // record explicit opt-ins and opt-outs. Implicitly isolated origins only end
  // up recorded if a future request from the same origin attempts to opt-in or
  // opt-out, which would trigger a normal global walk and record that the
  // origin has already been implicitly isolated in some BrowsingInstances.

  // TODO(crbug.com/40910871): investigate using one of NavigationRequest's
  // Get*Origin*() functions to compute this, instead of assuming we can just
  // convert directly from GetURL().
  url::Origin origin = url::Origin::Create(GetURL());
  // Since this origin is using a site-keyed process (either because
  // origin-keyed processes are disabled, not used for this origin, or the
  // origin has opted out), we can't rely on a newly created SiteInstance to add
  // the origin as OAC/not-OAC, so we do it manually here.
  auto* policy = ChildProcessSecurityPolicyImpl::GetInstance();
  // If there is already a state registered for `origin` in `isolation_context`,
  // then the following call does nothing.
  policy->AddOriginAgentClusterStateForBrowsingInstance(
      isolation_context, origin, oac_isolation_state.value());
}

bool NavigationRequest::IsOriginAgentClusterOptInRequested() {
  // We explicitly do not honor Origin-Agent-Cluster headers in redirects and
  // may only consider them in final responses, according to spec.
  // https://crbug.com/1329061
  if (state_ < WILL_PROCESS_RESPONSE || state_ == WILL_FAIL_REQUEST) {
    return false;
  }

  if (!response()) {
    return false;
  }

  // Do not attempt isolation if the feature is not enabled.
  if (!SiteIsolationPolicy::IsOriginAgentClusterEnabled()) {
    return false;
  }

  return response_head_->parsed_headers->origin_agent_cluster ==
         network::mojom::OriginAgentClusterValue::kTrue;
}

bool NavigationRequest::IsOriginAgentClusterOptOutRequested() {
  // We explicitly do not honor Origin-Agent-Cluster headers in redirects and
  // may only consider them in final responses, according to spec.
  // https://crbug.com/1329061
  if (state_ < WILL_PROCESS_RESPONSE || state_ == WILL_FAIL_REQUEST) {
    return false;
  }

  if (!response()) {
    return false;
  }

  // We only allow explicit opt-outs when OAC-by-default is enabled. The
  // following check will be false if IsOriginAgentClusterEnabled() is false.
  if (!SiteIsolationPolicy::AreOriginAgentClustersEnabledByDefault(
          frame_tree_node_->navigator().controller().GetBrowserContext())) {
    return false;
  }

  return response_head_->parsed_headers->origin_agent_cluster ==
         network::mojom::OriginAgentClusterValue::kFalse;
}

bool NavigationRequest::IsIsolationImplied() {
  if (!SiteIsolationPolicy::AreOriginAgentClustersEnabledByDefault(
          frame_tree_node_->navigator().controller().GetBrowserContext())) {
    return false;
  }

  return !response() || response_head_->parsed_headers->origin_agent_cluster ==
                            network::mojom::OriginAgentClusterValue::kAbsent;
}

void NavigationRequest::DetermineOriginAgentClusterEndResult() {
  DCHECK(state_ == WILL_PROCESS_RESPONSE ||
         state_ == WILL_COMMIT_WITHOUT_URL_LOADER ||
         state_ == WILL_FAIL_REQUEST || state_ == CANCELING);
  auto* policy = ChildProcessSecurityPolicyImpl::GetInstance();
  url::Origin origin = GetOriginToCommit().value();
  const IsolationContext& isolation_context =
      GetRenderFrameHost()->GetSiteInstance()->GetIsolationContext();

  OriginAgentClusterIsolationState requested_isolation_state =
      OriginAgentClusterIsolationState::CreateForDefaultIsolation(
          frame_tree_node_->navigator().controller().GetBrowserContext());

  if (IsOriginAgentClusterOptInRequested()) {
    requested_isolation_state =
        OriginAgentClusterIsolationState::CreateForOriginAgentCluster(
            /*had_oac_request=*/true,
            SiteIsolationPolicy::
                IsProcessIsolationForOriginAgentClusterEnabled());
  } else if (IsOriginAgentClusterOptOutRequested()) {
    requested_isolation_state =
        OriginAgentClusterIsolationState::CreateNonIsolatedByHeader();
  }

  const bool got_origin_agent_cluster =
      policy
          ->DetermineOriginAgentClusterIsolation(isolation_context, origin,
                                                 requested_isolation_state)
          .is_origin_agent_cluster();

  if (SiteIsolationPolicy::AreOriginAgentClustersEnabledByDefault(
          frame_tree_node_->navigator().controller().GetBrowserContext())) {
    // When OAC is enabled by default, report enum values that distinguish
    // between explicitly requesting OAC (on or off) and having no related
    // header.
    bool was_explicitly_requested =
        response_head_ &&
        response_head_->parsed_headers->origin_agent_cluster ==
            network::mojom::OriginAgentClusterValue::kTrue;
    bool was_explicitly_not_requested =
        response_head_ &&
        response_head_->parsed_headers->origin_agent_cluster ==
            network::mojom::OriginAgentClusterValue::kFalse;

    if (got_origin_agent_cluster) {
      if (was_explicitly_requested) {
        origin_agent_cluster_end_result_ =
            OriginAgentClusterEndResult::kExplicitlyRequestedAndOriginKeyed;
      } else if (was_explicitly_not_requested) {
        origin_agent_cluster_end_result_ =
            OriginAgentClusterEndResult::kExplicitlyNotRequestedButOriginKeyed;
      } else {
        origin_agent_cluster_end_result_ =
            OriginAgentClusterEndResult::kNotExplicitlyRequestedAndOriginKeyed;
      }
    } else {
      if (was_explicitly_requested) {
        origin_agent_cluster_end_result_ =
            OriginAgentClusterEndResult::kExplicitlyRequestedButNotOriginKeyed;
      } else if (was_explicitly_not_requested) {
        origin_agent_cluster_end_result_ = OriginAgentClusterEndResult::
            kExplicitlyNotRequestedAndNotOriginKeyed;
      } else {
        origin_agent_cluster_end_result_ = OriginAgentClusterEndResult::
            kNotExplicitlyRequestedButNotOriginKeyed;
      }
    }
  } else {
    // When OAC is not enabled by default, report enum values that only indicate
    // if OAC was requested or not vs whether it took effect.
    if (requested_isolation_state.logical_oac_status() ==
        AgentClusterKey::OACStatus::kOriginKeyedByHeader) {
      origin_agent_cluster_end_result_ =
          got_origin_agent_cluster
              ? OriginAgentClusterEndResult::kRequestedAndOriginKeyed
              : OriginAgentClusterEndResult::kRequestedButNotOriginKeyed;
    } else {
      origin_agent_cluster_end_result_ =
          got_origin_agent_cluster
              ? OriginAgentClusterEndResult::kNotRequestedButOriginKeyed
              : OriginAgentClusterEndResult::kNotRequestedAndNotOriginKeyed;
    }
  }

  // This needs to be computed separately from origin.opaque() because, per
  // https://crbug.com/1041376, we don't have a notion of the true origin yet.
  const bool is_opaque_origin_because_sandbox =
      (policy_container_builder_->FinalPolicies().sandbox_flags &
       network::mojom::WebSandboxFlags::kOrigin) ==
      network::mojom::WebSandboxFlags::kOrigin;

  // The origin_agent_cluster navigation commit parameter communicates to the
  // renderer about origin-keying, so it should be true for opaque origin
  // cases (e.g., for data: URLs). origin_agent_cluster_end_result_ shouldn't be
  // modified since it's used for warnings and use counters, i.e. things that
  // don't apply to this sort of "automatic" origin-keying.
  commit_params_->origin_agent_cluster = is_opaque_origin_because_sandbox ||
                                         origin.opaque() ||
                                         got_origin_agent_cluster;

  // The origin_agent_cluster_left_as_default navigation commit parameter
  // communicates to the renderer whether the origin_agent_cluster decision
  // (recorded just above) has been made based on an absent Origin-Agent-Cluster
  // http header.
  commit_params_->origin_agent_cluster_left_as_default =
      !response_head_ || response_head_->parsed_headers->origin_agent_cluster ==
                             network::mojom::OriginAgentClusterValue::kAbsent;
}

void NavigationRequest::ProcessOriginAgentClusterEndResult() {
  if (!HasCommitted() || IsErrorPage() || IsSameDocument())
    return;

  if (origin_agent_cluster_end_result_ ==
          OriginAgentClusterEndResult::kRequestedAndOriginKeyed ||
      origin_agent_cluster_end_result_ ==
          OriginAgentClusterEndResult::kRequestedButNotOriginKeyed ||
      origin_agent_cluster_end_result_ ==
          OriginAgentClusterEndResult::kExplicitlyRequestedAndOriginKeyed ||
      origin_agent_cluster_end_result_ ==
          OriginAgentClusterEndResult::kExplicitlyRequestedButNotOriginKeyed) {
    GetContentClient()->browser()->LogWebFeatureForCurrentPage(
        GetRenderFrameHost(),
        blink::mojom::WebFeature::kOriginAgentClusterHeader);
  }

  const url::Origin origin = url::Origin::Create(GetURL());

  if (origin_agent_cluster_end_result_ ==
          OriginAgentClusterEndResult::kRequestedButNotOriginKeyed ||
      origin_agent_cluster_end_result_ ==
          OriginAgentClusterEndResult::kExplicitlyRequestedButNotOriginKeyed) {
    GetRenderFrameHost()->AddMessageToConsole(
        blink::mojom::ConsoleMessageLevel::kWarning,
        base::StringPrintf(
            "The page requested an origin-keyed agent cluster using the "
            "Origin-Agent-Cluster header, but could not be origin-keyed since "
            "the origin '%s' had previously been placed in a site-keyed agent "
            "cluster. Update your headers to uniformly request origin-keying "
            "for all pages on the origin.",
            origin.Serialize().c_str()));
  }

  if (origin_agent_cluster_end_result_ ==
          OriginAgentClusterEndResult::kNotRequestedButOriginKeyed ||
      origin_agent_cluster_end_result_ ==
          OriginAgentClusterEndResult::kExplicitlyNotRequestedButOriginKeyed) {
    GetRenderFrameHost()->AddMessageToConsole(
        blink::mojom::ConsoleMessageLevel::kWarning,
        base::StringPrintf(
            "The page did not request an origin-keyed agent cluster, but was "
            "put in one anyway because the origin '%s' had previously been "
            "placed in an origin-keyed agent cluster. Update your headers to "
            "uniformly request origin-keying for all pages on the origin.",
            origin.Serialize().c_str()));
  }
}

void NavigationRequest::PopulateDocumentTokenForCrossDocumentNavigation() {
  DCHECK(!IsSameDocument());
  DCHECK_GE(state_, READY_TO_COMMIT);
  const auto* token_to_reuse =
      GetRenderFrameHost()->GetDocumentTokenForCrossDocumentNavigationReuse(
          /* passkey */ {});
  document_token_.emplace(token_to_reuse ? *token_to_reuse
                                         : blink::DocumentToken());
}

bool NavigationRequest::HasCommittingOrigin(const url::Origin& origin) {
  // We are only interested in checking requests that have been assigned a
  // SiteInstance.
  if (state() < WILL_PROCESS_RESPONSE)
    return false;

  // This origin conversion won't be correct for about:blank, but origin
  // isolation shouldn't need to care about that case because a previous
  // instance of the origin would already have determined its isolation status
  // in that BrowsingInstance.
  // TODO(crbug.com/40092527): Use the computed origin here just to be safe.
  // Note, however, that if this is done, we need to be careful to still match
  // sandboxed frame origins, which GetURL() currently accomplishes "by
  // accident" (see https://crbug.com/446157743).
  return origin == url::Origin::Create(GetURL());
}

bool NavigationRequest::ShouldRequestSiteIsolationForCOOP() {
  if (!SiteIsolationPolicy::IsSiteIsolationForCOOPEnabled())
    return false;

  // COOP headers are only served once a response is available.
  if (state_ < WILL_PROCESS_RESPONSE)
    return false;

  // COOP isolation can only be triggered from main frames.  COOP headers
  // aren't honored in subframes.
  if (!IsInMainFrame())
    return false;

  // Filter out URLs with origins that are considered invalid for being
  // isolated. Note that the origin we'll eventually attempt to isolate should
  // be based on agent_cluster_key(), so that we apply isolation to the actual
  // site rather than the effective URL in the case of hosted apps.
  url::Origin origin =
      site_info_.agent_cluster_key().IsOriginKeyed()
          ? site_info_.agent_cluster_key().GetOrigin()
          : url::Origin::Create(site_info_.agent_cluster_key().GetSite());
  if (!IsolatedOriginUtil::IsValidIsolatedOrigin(origin))
    return false;

  // Check the COOP header value. All same-origin values are considered to be
  // an implicit hint for site isolation.
  bool should_header_value_trigger_isolation = false;
  switch (coop_status_.current_coop().value) {
    case network::mojom::CrossOriginOpenerPolicyValue::kSameOrigin:
    case network::mojom::CrossOriginOpenerPolicyValue::kSameOriginPlusCoep:
    case network::mojom::CrossOriginOpenerPolicyValue::kSameOriginAllowPopups:
    case network::mojom::CrossOriginOpenerPolicyValue::kNoopenerAllowPopups:
      should_header_value_trigger_isolation = true;
      break;
    case network::mojom::CrossOriginOpenerPolicyValue::kUnsafeNone:
      should_header_value_trigger_isolation = false;
      break;
      // Don't handle the default case on purpose to force a compiler error if
      // new COOP values are added, so that they are explicitly handled here.
  }
  if (!should_header_value_trigger_isolation)
    return false;

  // There's no need for additional isolation if the site already requires a
  // dedicated process via other isolation mechanisms.  However, we still
  // return true if the site has been isolated due to COOP previously, so that
  // we can go through the COOP isolation flow to update the timestamp of when
  // the COOP isolation for this site was last used.
  //
  // Note: we can use `site_info_` here, since that has been assigned at
  // request start time and updated by redirects, but it is not (currently)
  // recomputed when response is received, so it does not include the COOP
  // isolation request (which would cause RequiresDedicatedProcess to return
  // true regardless of prior isolation). If we ever decide to update
  // `site_info_` at response time, we should revisit this and ensure that we
  // call RequiresDedicatedProcess on a SiteInfo that does not already have an
  // isolation request (enforced by DCHECK below).
  DCHECK(!site_info_.does_site_request_dedicated_process_for_coop());
  if (site_info_.RequiresDedicatedProcess(
          GetStartingSiteInstance()->GetIsolationContext())) {
    bool is_already_isolated_due_to_coop =
        ChildProcessSecurityPolicyImpl::GetInstance()->IsIsolatedSiteFromSource(
            origin,
            ChildProcessSecurityPolicy::IsolatedOriginSource::WEB_TRIGGERED);
    return is_already_isolated_due_to_coop;
  }
  return true;
}

UrlInfo NavigationRequest::GetUrlInfo() {
  // If the navigation has an OAC header, pass along an
  // OriginAgentClusterIsolationState request that represents the origin
  // isolation requested by the OAC header (either opt-in or opt-out). If there
  // is no OAC header, a final OAC state will be computed when creating the
  // SiteInfo for this URLInfo based on the default state for the chosen
  // BrowsingInstance.
  std::optional<OriginAgentClusterIsolationState> oac_header_request;
  if (IsOriginAgentClusterOptOutRequested()) {
    oac_header_request =
        OriginAgentClusterIsolationState::CreateNonIsolatedByHeader();
  } else if (IsOriginAgentClusterOptInRequested()) {
    // An origin-keyed agent cluster is used if explicitly requested by header.
    oac_header_request =
        OriginAgentClusterIsolationState::CreateForOriginAgentCluster(
            /*had_oac_request=*/true,
            SiteIsolationPolicy::
                IsProcessIsolationForOriginAgentClusterEnabled());
  }

  // Compute the CrossOriginIsolationKey for the navigation.
  std::optional<AgentClusterKey::CrossOriginIsolationKey>
      cross_origin_isolation_key = ComputeCrossOriginIsolationKey();

  // Compute the WebExposedIsolationInfo that will be bundled into UrlInfo.
  auto web_exposed_isolation_info = ComputeWebExposedIsolationInfo();

  UrlInfoInit url_info_init(GetURL());
  url_info_init.WithOACHeaderRequest(oac_header_request)
      .WithCOOPSiteIsolation(ShouldRequestSiteIsolationForCOOP())
      .WithWebExposedIsolationInfo(web_exposed_isolation_info)
      .WithCrossOriginIsolationKey(cross_origin_isolation_key)
      .WithIsPdf(is_pdf_);

  // Navigations with SiteInstances which have fixed storage partition (e.g.
  // <webview> tags) should always stay in the current StoragePartition.
  SiteInstanceImpl* current_instance =
      frame_tree_node_->current_frame_host()->GetSiteInstance();
  if (current_instance->IsFixedStoragePartition()) {
    url_info_init.WithStoragePartitionConfig(
        current_instance->GetStoragePartitionConfig());
  }

  // Child frames (including fenced frames) should always use the
  // same StoragePartition as their parent.
  RenderFrameHostImpl* parent = GetParentFrameOrOuterDocument();
  if (parent) {
    url_info_init.WithStoragePartitionConfig(
        parent->GetSiteInstance()->GetStoragePartitionConfig());
  }

  if (IsLoadDataWithBaseURL()) {
    // LoadDataWithBaseURL() navigations also need to explicitly set the origin
    // to the origin of the base URL.  This ensures that the process for this
    // navigation will eventually be locked to the right origin (i.e., origin of
    // the base URL rather than the data: URL).
    //
    // Note that while LoadDataWithBaseURL() is supported in <webview> tags on
    // desktop platforms and on Android Webview, only <webview> tags currently
    // utilize this special case when running in site-isolated mode. Android
    // Webview doesn't currently lock processes for LoadDataWithBaseURL()
    // navigations.
    url_info_init.WithOrigin(
        url::Origin::Create(common_params().base_url_for_data_url));
  } else if (GetURL().IsAboutBlank() && GetInitiatorOrigin().has_value()) {
    // about:blank inherits its origin from the initiator, so ensure that this
    // is reflected in the UrlInfo.  In the common case, this isn't needed for
    // process model decisions, since we already leave about:blank in the
    // source SiteInstance, which corresponds to the initiator (see
    // `RenderFrameHostManager::CanUseSourceSiteInstance()`). However, in
    // certain corner cases, the source SiteInstance can't be used, but we
    // will still need to assign a proper process for about:blank. In that
    // case, we should honor the initiator origin, so that about:blank ends up
    // in a process that's locked to that origin, rather than an unlocked
    // process with an unassigned SiteInstance.  The latter would be violating
    // site isolation guarantees and would be problematic for Citadel
    // enforcements in
    // ChildProcessSecurityPolicyImpl::CanAccessDataForOrigin().  See
    // https://crbug.com/1426928.
    //
    // TODO(alexmos): Consider also specifying UrlInfo::origin for about:srcdoc
    // navigations. This is not currently needed in the SiteInstance
    // and process assignment paths for srcdoc frames, but doing this might
    // simplify some of that code and would be good for consistency, since both
    // about:blank and about:srcdoc inherit the origin per spec
    // (https://html.spec.whatwg.org/multipage/document-sequences.html#determining-the-origin).
    url_info_init.WithOrigin(*GetInitiatorOrigin());
  } else {
    // Overriding the origin for a URL is dangerous and only allowed in very
    // narrow cases which are handled explicitly above.  Please think very
    // carefully about any new cases that need to do this.
    DCHECK(!url_info_init.origin().has_value());
  }

  // Propagate the tentative origin to commit value (for data: URLs that will be
  // rendered) to the UrlInfo, to make sure the nonce remains the same
  // throughout the navigation.
  if (GetURL().SchemeIs(url::kDataScheme)) {
    // The function for computing the request's origin depends on the stage of
    // the request, but the same opaque nonce value is preserved across both
    // functions for data: URLs.
    if (state_ < WILL_PROCESS_RESPONSE) {
      url_info_init.WithOrigin(GetTentativeOriginAtRequestTime());
    } else if (response_should_be_rendered_) {
      // The origin to commit is nullopt for cases that are not rendered (e.g.,
      // downloads), but the UrlInfo does not need the origin for data: URLs in
      // such cases.
      url_info_init.WithOrigin(GetOriginToCommit().value());
    }
  }

  // Determine if the request is for a sandboxed frame or not, and if so whether
  // the sandboxed frame should get a dedicated process. Setting
  // `has_origin_restricted_sandbox_flag` to true indicates it should get
  // process isolation, but only if the site/origin would have qualified for a
  // dedicated process even without the sandbox flags.
  //
  // If PolicyContainer::ComputePoliciesToCommit() has run
  // `policy_container_builder_` will be valid, but even if it hasn't, we can
  // speculatively take `commit_params_->frame_policy.sandbox_flags` if we
  // haven't received the response yet and don't have the final
  // `policy_container_builder_`, and if the state of the kOrigin flag changes,
  // we'll detect the change and recompute the target SiteInstance elsewhere.
  //
  // In general, about:blank documents should stay in their initiator's process.
  // If neither the initiator or about:blank is sandboxed, or if both are, then
  // the about:blank should stay in its parent's process, if only to avoid
  // needing an extra process that only shows the empty frame (if the parent and
  // about:blank are sandboxed, they parent cannot script the about:blank
  // frame). If the initiator is not sandboxed but the about:blank document is
  // (e.g., due to iframe attributes), then nothing else will be able to script
  // the empty about:blank document and it is safe to leave it in the same
  // process. (It is not possible for the initiator to be sandboxed and the
  // about:blank to not be sandboxed, because about:blank inherits the
  // sandboxing of its initiator.)
  bool is_eligible_for_sandboxing =
      !GetURL().IsAboutBlank() ||
      (source_site_instance_ &&
       source_site_instance_->GetSiteInfo().is_sandboxed());
  if (SiteIsolationPolicy::AreIsolatedSandboxedIframesEnabled() &&
      is_eligible_for_sandboxing) {
    // Determine if the frame has the sandbox flag or not.
    bool has_origin_restricted_sandbox_flag = false;
    if (policy_container_builder_->HasComputedPolicies()) {
      has_origin_restricted_sandbox_flag =
          (policy_container_builder_->FinalPolicies().sandbox_flags &
           network::mojom::WebSandboxFlags::kOrigin) ==
          network::mojom::WebSandboxFlags::kOrigin;
    } else {
      // Note: We'll end up here if this function is called before
      // ComputePoliciesToCommit(), such as when computing a speculative
      // RenderFrameHost's SiteInstance before receiving a response. In that
      // event we use the sandbox flags in commit_params_ as a current "best
      // estimate".
      has_origin_restricted_sandbox_flag =
          (commit_params_->frame_policy.sandbox_flags &
           network::mojom::WebSandboxFlags::kOrigin) ==
          network::mojom::WebSandboxFlags::kOrigin;
    }

    // It's possible that a sandbox attribute can disappear from a frame that
    // still contains a sandboxed initiator, meaning we won't have sandbox
    // flags here, but should still respect the sandbox of the initiator.
    bool should_inherit_initiators_sandbox =
        GetURL().IsAboutBlank() && source_site_instance_ &&
        source_site_instance_->GetSiteInfo().is_sandboxed();

    // Consider isolating sandboxed frames that won't end up as downloads or
    // 204s.
    if ((has_origin_restricted_sandbox_flag ||
         should_inherit_initiators_sandbox) &&
        response_should_be_rendered_) {
      // If the URL under consideration wouldn't qualify for a dedicated process
      // without the sandbox flags, then it shouldn't qualify even with the
      // sandbox flag. This is most likely to occur when site isolation is only
      // partial, as on Android.
      //
      // Ideally the IsolationContext would be the one used for the committed
      // RenderFrameHost at the end of the navigation, since a different set of
      // origins may require isolation if a BrowsingInstance swap occurs. This
      // isn't known at the start of the navigation, though, so we use the
      // current IsolationContext instead.
      const IsolationContext& isolation_context =
          current_instance->GetIsolationContext();
      if (SiteInfo::Create(isolation_context, UrlInfo(url_info_init))
              .RequiresDedicatedProcess(isolation_context)) {
        // Embedders can identify, via ContentBrowserClient, cases that should
        // not use isolated sandboxed frames.
        ContentBrowserClient* client = GetContentClient()->browser();
        BrowserContext* context =
            frame_tree_node_->navigator().controller().GetBrowserContext();
        url::SchemeHostPort precursor;
        if (state_ < WILL_PROCESS_RESPONSE) {
          precursor = GetTentativeOriginAtRequestTime()
                          .GetTupleOrPrecursorTupleIfOpaque();
        } else if (GetOriginToCommit()) {
          precursor = GetOriginToCommit()->GetTupleOrPrecursorTupleIfOpaque();
        } else {
          NOTREACHED() << "No origin-to-commit for sandboxed url = "
                       << GetURL();
        }

        bool client_allows_cross_process_sandboxed_frames =
            client->ShouldAllowCrossProcessSandboxedFrameForPrecursor(
                context, precursor.GetURL(), GetURL());
        if (client_allows_cross_process_sandboxed_frames) {
          url_info_init.WithSandbox(true);
          // If an isolated sandbox is required, and the "per-document" grouping
          // mode has been specified with kIsolateSandboxedIframes, then we use
          // a unique document identifier, provided by `navigation_id_`, to
          // guarantee that each sandboxed iframe gets its own SiteInstance,
          // even if two or more such documents share a site/origin. Using
          // navigation_id_ means that each new NavigationRequest (and thus each
          // document) will get a different value.
          if (blink::features::kIsolateSandboxedIframesGroupingParam.Get() ==
              blink::features::IsolateSandboxedIframesGrouping::kPerDocument) {
            url_info_init.WithUniqueSandboxId(navigation_id_);
          }
        }
      }
    }
  }

  // If a prefetch might have been affected by cross-site state, the
  // relationship with other windows should be severed to make this more
  // difficult to use to leak cross-site state.
  // https://crbug.com/1439246
  if (base::FeatureList::IsEnabled(
          features::kPrefetchStateContaminationMitigation) &&
      response_head_ &&
      response_head_->is_prefetch_with_cross_site_contamination) {
    url_info_init.WithCrossSitePrefetchContamination(true);
  }

  if (base::FeatureList::IsEnabled(
          features::kProcessSelectionDeferringConditions)) {
    url_info_init.WithProcessSelectionUserData(
        GetProcessSelectionUserData().GetSafeRef());
  }

  return UrlInfo(url_info_init);
}

const GURL& NavigationRequest::GetOriginalRequestURL() {
  // If this is a loadData navigation we should return the URL used to commit,
  // even if the navigation went through redirects. This is to preserve the
  // previous behavior where we use the redirect chain from the renderer to get
  // the original request URL. When we commit a loadDataWithBaseURL, or a
  // loadDataAsStringWithBaseUrl navigation, the redirect chain in the renderer
  // used to only contain the commit URL.
  if (IsLoadDataWithBaseURL())
    return GetURL();

  // Otherwise, return the first URL in the redirect chain. If the navigation
  // is started by a client redirect, this will be the URL of the document that
  // started the redirect. Otherwise, this will be the first destination URL
  // of the navigation, before any server redirects.
  // TODO(crbug.com/40168423): Reconsider the behavior with client
  // redirects, as all script-initiated navigations are considered client
  // redirects, which means the client redirect might not always trigger
  // immediately (or at all, if the navigation depends on user interaction)
  // if we decide to do a reload with the original URL.
  DCHECK(!redirect_chain_.empty());
  return redirect_chain_[0];
}

void NavigationRequest::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) {
  receive_response_time_ = base::TimeTicks::Now();
  const int32_t http_response_code =
      response_head->headers ? response_head->headers->response_code()
                             : -1 /* no http_response_code */;
  TRACE_EVENT(
      "navigation", "NavigationRequest::OnResponseStarted",
      perfetto::Flow::FromPointer(this), [&](perfetto::EventContext ctx) {
        auto* event = ctx.event<perfetto::protos::pbzero::ChromeTrackEvent>();
        auto* response_info = event->set_response_info();
        if (http_response_code != -1) {
          response_info->set_response_code(http_response_code);
        }
        response_info->set_was_http_cache(response_head->was_fetched_via_cache);
      });

  ScopedCrashKeys crash_keys(*this);

  // The |loader_|'s job is finished. It must not call the NavigationRequest
  // anymore from now.
  loader_.reset();
  if (is_download)
    RecordDownloadUseCountersPrePolicyCheck();
  is_download_ = is_download && download_policy().IsDownloadAllowed();
  if (is_download_)
    RecordDownloadUseCountersPostPolicyCheck();
  request_id_ = request_id;

  DCHECK(IsNavigationStarted());
  DCHECK(response_head);
  DCHECK(response_head->parsed_headers);
  EnterChildTraceEvent("OnResponseStarted", this);
  SetState(WILL_PROCESS_RESPONSE);
  response_head_ = std::move(response_head);
  response_body_ = std::move(response_body);
  ssl_info_ = response_head_->ssl_info;
  auth_challenge_info_ = response_head_->auth_challenge_info;

  // TODO(crbug.com/40218207): Store the whole EarlyHints struct instead
  // of duplicating all of its fields.
  was_resource_hints_received_ = early_hints.was_resource_hints_received;
  early_hints_manager_ = std::move(early_hints.manager);
  if (early_hints_manager_ &&
      early_hints_manager_->first_early_hints_receive_time()) {
    base::UmaHistogramTimes(
        "Navigation.EarlyHints.WillStartRequestToEarlyHintsTime",
        *early_hints_manager_->first_early_hints_receive_time() -
            will_start_request_time_);
    base::UmaHistogramTimes(
        "Navigation.EarlyHints.EarlyHintsToResponseStartTime",
        base::TimeTicks::Now() -
            *early_hints_manager_->first_early_hints_receive_time());
  }

  // A request was made. Record it before we decide to block this response for
  // a reason or another.
  RecordAddressSpaceFeature();

  const bool is_mhtml_archive = IsMhtmlMimeType(response_head_->mime_type);
  if (is_mhtml_archive)
    is_mhtml_or_subframe_ = true;

  if (CheckCSPEmbeddedEnforcement() ==
      CSPEmbeddedEnforcementResult::BLOCK_RESPONSE) {
    OnRequestFailedInternal(
        network::URLLoaderCompletionStatus(net::ERR_BLOCKED_BY_CSP),
        true /* skip_throttles */, std::nullopt /* error_page_content*/,
        false /* collapse_frame */);
    // DO NOT ADD CODE after this. The previous call to OnRequestFailedInternal
    // has destroyed the NavigationRequest.
    return;
  }

  // See https://github.com/whatwg/fetch/pull/1579
  if (!response_head_->timing_allow_passed) {
    commit_params_->navigation_timing->parent_resource_timing_access =
        blink::mojom::ParentResourceTimingAccess::kDoNotReport;
  }

  {
    const std::optional<network::mojom::BlockedByResponseReason>
        coop_requires_blocking =
            coop_status_.SanitizeResponse(response_head_.get());
    if (coop_requires_blocking) {
      // TODO(crbug.com/40166503): Investigate what must be done in case
      // of a download.
      OnRequestFailedInternal(
          network::URLLoaderCompletionStatus(*coop_requires_blocking),
          false /* skip_throttles */, std::nullopt /* error_page_content */,
          false /* collapse_frame */);
      // DO NOT ADD CODE after this. The previous call to
      // OnRequestFailedInternal has destroyed the NavigationRequest.
      return;
    }
    policy_container_builder_->SetCrossOriginOpenerPolicy(
        response_head_->parsed_headers->cross_origin_opener_policy);
  }

  ComputePoliciesToCommit();
  // After this line. The sandbox flags to commit have been computed. The origin
  // can be determined. This is needed for enforcing COOP below.

  {
    const url::Origin origin = GetOriginForURLLoaderFactoryBeforeResponse(
        policy_container_builder_->FinalPolicies().sandbox_flags);
    coop_status_.EnforceCOOP(
        policy_container_builder_->FinalPolicies().cross_origin_opener_policy,
        origin, network_anonymization_key);
  }

  // The navigation may have encountered a header that requests isolation for
  // the url's origin. Before we pick the renderer, make sure we update the
  // origin-isolation opt-ins appropriately.
  CheckForIsolationOptIn(GetURL());

  const bool is_first_response = commit_params_->redirects.empty();
  UpdateNavigationHandleTimingsOnResponseReceived(/*is_redirect=*/false,
                                                  is_first_response);

  commit_params_->http_response_code = http_response_code;

  // Update fetch start timing. While NavigationRequest updates fetch start
  // timing for redirects, it's not aware of service worker interception so
  // fetch start timing could happen earlier than worker start timing. Use
  // worker ready time if it is greater than the current value to make sure
  // fetch start timing always comes after worker start timing (if a service
  // worker intercepted the navigation).
  commit_params_->navigation_timing->fetch_start =
      std::max(commit_params_->navigation_timing->fetch_start,
               response_head_->load_timing.service_worker_ready_time);

  // A navigation is user activated if it contains a user gesture or the frame
  // received a gesture and the navigation is renderer initiated. If the
  // navigation is browser initiated, it has to come from the context menu.
  // In all cases, the previous and new URLs have to match the
  // `ShouldPropagateUserActivation` requirements (same eTLD+1).
  // There are two different checks:
  // 1. if the `frame_tree_node_` has an origin and is following the rules above
  //    with the target URL, it is used and the bit is set if the navigation is
  //    renderer initiated and the `frame_tree_node_` had a gesture. This should
  //    apply to same page navigations and is preferred over using the referrer
  //    as it can be changed.
  // 2. if referrer and the target url are following the rules above, two
  //    conditions will set the bit: navigation comes from a gesture and is
  //    renderer initiated (middle click/ctrl+click) or it is coming from a
  //    context menu. This should apply to pages that open in a new tab and we
  //    have to follow the referrer. It means that the activation might not be
  //    transmitted if it should have.
  if (commit_params_->was_activated ==
      blink::mojom::WasActivatedOption::kUnknown) {
    commit_params_->was_activated = blink::mojom::WasActivatedOption::kNo;

    if (!commit_params_->is_browser_initiated &&
        (frame_tree_node_->HasStickyUserActivation() ||
         frame_tree_node_->has_received_user_gesture_before_nav()) &&
        ShouldPropagateUserActivation(
            frame_tree_node_->current_origin(),
            url::Origin::Create(common_params_->url))) {
      commit_params_->was_activated = blink::mojom::WasActivatedOption::kYes;
      // TODO(crbug.com/41367031): the next check is relying on
      // sanitized_referrer_ but should ideally use a more reliable source for
      // the originating URL when the navigation is renderer initiated.
    } else if (((common_params_->has_user_gesture &&
                 !commit_params_->is_browser_initiated) ||
                common_params_->started_from_context_menu) &&
               ShouldPropagateUserActivation(
                   url::Origin::Create(sanitized_referrer_->url),
                   url::Origin::Create(common_params_->url))) {
      commit_params_->was_activated = blink::mojom::WasActivatedOption::kYes;
    }
  }

  // Check if the response should be sent to a renderer.
  // Regular downloads should not be rendered, but downloads with an
  // unsuccessful response code will cause an error page to be rendered.
  response_should_be_rendered_ =
      (!is_download ||
       IsFailedDownload(is_download, response_head_->headers.get())) &&
      (!response_head_->headers.get() ||
       (response_head_->headers->response_code() != net::HTTP_NO_CONTENT &&
        response_head_->headers->response_code() != net::HTTP_RESET_CONTENT &&
        !ShouldRenderFallbackContentForResponse(*response_head_->headers)));

  if (!response_should_be_rendered_) {
    net_error_ = net::ERR_ABORTED;
    error_navigation_trigger_ =
        ErrorNavigationTrigger::kShouldNotRenderResponse;
    SelectFrameHostForOnResponseStarted(std::move(url_loader_client_endpoints),
                                        is_download,
                                        std::move(subresource_loader_params));
    return;
  }

  // MHTML document can't be framed into non-MHTML document (and vice versa).
  // The full page must load from the MHTML archive or none of it.
  if (is_mhtml_archive && !IsInMainFrame()) {
    OnRequestFailedInternal(
        network::URLLoaderCompletionStatus(net::ERR_BLOCKED_BY_RESPONSE),
        false /* skip_throttles */, std::nullopt /* error_page_contnet */,
        false /* collapse_frame */);
    // DO NOT ADD CODE after this. The previous call to
    // OnRequestFailedInternal has destroyed the NavigationRequest.
    return;
  }

  const std::optional<network::mojom::BlockedByResponseReason>
      coep_requires_blocking = EnforceCOEP();
  if (coep_requires_blocking) {
    OnRequestFailedInternal(
        network::URLLoaderCompletionStatus(*coep_requires_blocking),
        false /* skip_throttles */, std::nullopt /* error_page_content */,
        false /* collapse_frame */);
    // DO NOT ADD CODE after this. The previous call to
    // OnRequestFailedInternal has destroyed the NavigationRequest.
    return;
  }

  const auto& url = common_params_->url;

  if (IsDisabledEmbedderInitiatedFencedFrameNavigation()) {
    frame_tree_node_->current_frame_host()->AddMessageToConsole(
        blink::mojom::ConsoleMessageLevel::kError,
        "Embedder-initiated navigations of fenced frames are not allowed after "
        "both the embedder and embedded fenced frame network access has been "
        "disabled.");
    auto completion_status =
        network::URLLoaderCompletionStatus(net::ERR_ABORTED);
    error_navigation_trigger_ =
        ErrorNavigationTrigger::kFencedFrameEmbedderInitiatedNavigation;
    OnRequestFailedInternal(completion_status,
                            /*skip_throttles=*/false,
                            /*error_page_content=*/std::nullopt,
                            /*collapse_frame=*/false);
    // DO NOT ADD CODE after this. The previous call to
    // OnRequestFailedInternal has destroyed the NavigationRequest.
    return;
  }

  // The fenced frame root and the nested iframes are required to have the
  // Supports-Loading-Mode HTTP response header "fenced-frame" to be able to
  // load. Otherwise a console error is emitted.
  const bool should_enforce_fenced_frame_opt_in =
      response_head_->headers && frame_tree_node_->IsInFencedFrameTree() &&
      !(url.IsAboutBlank() || url.SchemeIsBlob() ||
        url.SchemeIs(url::kDataScheme));
  if (should_enforce_fenced_frame_opt_in &&
      !IsOptedInFencedFrame(*response_head_->headers)) {
    blink::RecordFencedFrameCreationOutcome(
        blink::FencedFrameCreationOutcome::kResponseHeaderNotOptIn);
    AddDeferredConsoleMessage(
        blink::mojom::ConsoleMessageLevel::kError,
        "Supports-Loading-Mode HTTP response header 'fenced-frame' is required "
        "to load the fenced frame root and its nested iframes.");
    OnRequestFailedInternal(
        network::URLLoaderCompletionStatus(net::ERR_BLOCKED_BY_RESPONSE),
        false /* skip_throttles */, std::nullopt /* error_page_content */,
        false /* collapse_frame */);
    // DO NOT ADD CODE after this. The previous call to
    // OnRequestFailedInternal has destroyed the NavigationRequest.
    return;
  }

  // [spec]: https://html.spec.whatwg.org/C/#process-a-navigate-response
  // 4. if [...] the result of checking a navigation response's adherence to its
  // embedder policy [...], then set failure to true.
  if (!CheckResponseAdherenceToCoep(url)) {
    OnRequestFailedInternal(network::URLLoaderCompletionStatus(
                                network::mojom::BlockedByResponseReason::
                                    kCoepFrameResourceNeedsCoepHeader),
                            false /* skip_throttles */,
                            std::nullopt /* error_page_content */,
                            false /* collapse_frame */);
    // DO NOT ADD CODE after this. The previous call to
    // OnRequestFailedInternal has destroyed the NavigationRequest.
    return;
  }

  if (process_selection_deferrer_) {
    // When process selection deferral is enabled, give process selection
    // dependencies the opportunity to defer before finalizing the selected
    // process.
    process_selection_deferrer_->WillSelectFinalProcess(base::BindOnce(
        &NavigationRequest::SelectFrameHostForOnResponseStarted,
        weak_factory_.GetWeakPtr(), std::move(url_loader_client_endpoints),
        is_download, std::move(subresource_loader_params)));
  } else {
    SelectFrameHostForOnResponseStarted(std::move(url_loader_client_endpoints),
                                        is_download,
                                        std::move(subresource_loader_params));
  }
}

void NavigationRequest::SelectFrameHostForOnResponseStarted(
    network::mojom::URLLoaderClientEndpointsPtr url_loader_client_endpoints,
    bool is_download,
    SubresourceLoaderParams subresource_loader_params) {
  TRACE_EVENT("navigation",
              "NavigationRequest::SelectFrameHostForOnResponseStarted",
              perfetto::Flow::FromPointer(this));
  CHECK(!HasRenderFrameHost())
      << "`render_frame_host_` should not be set before the "
         "`NavigationRequest` starts to select the RFH.";
  ScopedCrashKeys crash_keys(*this);
  std::string rfh_selected_reason;

  // Select an appropriate renderer to commit the navigation.
  if (IsServedFromBackForwardCache()) {
    NavigationControllerImpl* controller = GetNavigationController();
    auto entry =
        controller->GetBackForwardCache().GetOrEvictEntry(nav_entry_id_);
    if (!entry.has_value() &&
        entry.error() == BackForwardCacheImpl::kEntryIneligibleAndEvicted) {
      // If the RenderFrameHost to restore has been evicted and deleted, or the
      // current navigation is being restarted due to the `GetOrEvictEntry`
      // call, we should stop processing this back/forward cache restore
      // navigation, as the navigation will soon be restarted as a normal
      // history navigation and the current NavigationRequest will be reset.
      // DO NOT ADD CODE after this. The previous call to
      // `GetOrEvictEntry()` has destroyed the NavigationRequest.
      return;
    }
    CHECK(entry.has_value() && entry.value());
    CHECK(entry.value()->render_frame_host());
    render_frame_host_ = entry.value()->render_frame_host()->GetSafeRef();
  } else if (IsPrerenderedPageActivation()) {
    // Prerendering requires changing pages starting at the root node.
    DCHECK(IsInMainFrame());

    render_frame_host_ = GetPrerenderHostRegistry()
                             .GetRenderFrameHostForReservedHost(
                                 prerender_frame_tree_node_id_.value())
                             ->GetSafeRef();
  } else if (response_should_be_rendered_) {
    std::string* reason_output =
        base::FeatureList::IsEnabled(
            features::kHoldbackDebugReasonStringRemoval)
            ? &rfh_selected_reason
            : nullptr;

    if (auto result =
            frame_tree_node_->render_manager()->GetFrameHostForNavigation(
                this, &browsing_context_group_swap_,
                ProcessAllocationContext::CreateForNavigationRequest(
                    ProcessAllocationNavigationStage::kAfterResponse,
                    navigation_id_, IsInOutermostMainFrame()),
                reason_output);
        result.has_value()) {
      render_frame_host_ = result.value()->GetSafeRef();
    } else {
      switch (result.error()) {
        case GetFrameHostForNavigationFailed::kCouldNotReinitializeMainFrame:
          // TODO(crbug.com/40250311): This was unhandled before and
          // remains explicitly unhandled. This branch may be removed in the
          // future.
          break;
        case GetFrameHostForNavigationFailed::kBlockedByPendingCommit:
          DCHECK(ShouldQueueDueToExistingPendingCommitRFH());
          // This closure is posted to the event loop, so it must use WeakPtr.
          resume_commit_closure_ = base::BindOnce(
              &NavigationRequest::SelectFrameHostForOnResponseStarted,
              weak_factory_.GetWeakPtr(),
              std::move(url_loader_client_endpoints), is_download,
              std::move(subresource_loader_params));
          frame_tree_node_->render_manager()
              ->speculative_frame_host()
              ->RecordMetricsForBlockedGetFrameHostAttempt(
                  /* commit_attempt=*/true);
          return;
      }
    }

    // GetFrameHostForNavigation() should update associated_rfh_type_, so it
    // should never be NONE here.
    DCHECK_NE(AssociatedRenderFrameHostType::NONE, associated_rfh_type_);

    CHECK(Navigator::CheckWebUIRendererDoesNotDisplayNormalURL(
        GetRenderFrameHost(), GetUrlInfo(),
        /* is_renderer_initiated_check */ false));
  } else {
    render_frame_host_ = std::nullopt;
  }
  if (!HasRenderFrameHost()) {
    DCHECK(!response_should_be_rendered_);
  }

  if (!commit_params_->is_browser_initiated && HasRenderFrameHost() &&
      GetRenderFrameHost()->GetProcess() !=
          frame_tree_node_->current_frame_host()->GetProcess()) {
    // Allow the embedder to cancel the cross-process commit if needed.
    if (!frame_tree_node_->navigator()
             .GetDelegate()
             ->ShouldAllowRendererInitiatedCrossProcessNavigation(
                 frame_tree_node_->IsOutermostMainFrame())) {
      net_error_ = net::ERR_ABORTED;
      error_navigation_trigger_ = ErrorNavigationTrigger::
          kRenderInitiatedCrossProcessNavigationNotAllowed;
      frame_tree_node_->ResetNavigationRequest(
          NavigationDiscardReason::kInternalCancellation);
      return;
    }
  }

  // Store the URLLoaderClient endpoints until checks have been processed.
  url_loader_client_endpoints_ = std::move(url_loader_client_endpoints);

  subresource_loader_params_ = std::move(subresource_loader_params);

  // Most cases where ShouldAssignSiteForUrlInfo() is false should never load
  // actual content and reach this.  Since only empty document schemes are
  // allowed to leave a SiteInstance's site unassigned, they should follow the
  // !NeedsUrlLoader() path for committing the navigation early without ever
  // making a network request, and hence they should never reach the response
  // processing code here.
  //
  // The sole exception to this is about:blank URLs, since extensions are
  // allowed to redirect to them after a regular network request/response has
  // started.  Hence, about:blank is the only possible URL which both uses
  // unassigned SiteInstances and can reach this point (via an extension
  // redirect).
  if (common_params_->url.IsAboutBlank()) {
    // TODO(alexmos): Convert to a CHECK after verifying that this doesn't
    // happen in practice.
    if (!WasServerRedirect()) {
      DVLOG(1) << "about:blank should only go through the network stack "
               << "when an extension redirects to it.";
      base::debug::DumpWithoutCrashing();
    }
  } else {
    // TODO(alexmos): Convert to a CHECK after verifying that this doesn't
    // happen in practice.
    if (!SiteInstanceImpl::ShouldAssignSiteForUrlInfo(GetUrlInfo())) {
      DVLOG(1) << "This URL was unexpectedly loaded through the network stack: "
               << common_params_->url;
      base::debug::DumpWithoutCrashing();
    }
  }

  if (HasRenderFrameHost()) {
    // Set the site URL now if it hasn't been set already. If the site requires
    // a dedicated process, this will lock the process to that site, which will
    // prevent other sites from incorrectly reusing this process. See
    // https://crbug.com/738634.
    SiteInstanceImpl* instance = GetRenderFrameHost()->GetSiteInstance();
    if (!instance->HasSite() &&
        SiteInstanceImpl::ShouldAssignSiteForUrlInfo(GetUrlInfo())) {
      instance->ConvertToDefaultOrSetSite(GetUrlInfo());
    }

    // Since we've made the final pick for the RenderFrameHost above, the picked
    // RenderFrameHost's process should be considered "tainted" for future
    // process reuse decisions. That is, a site requiring a dedicated process
    // should not reuse this process, unless it's same-site with the URL we're
    // committing.
    //
    // The process must be marked used after calling ConvertToDefaultOrSetSite,
    // because that call verifies that a SiteInstance with an unassigned site
    // (e.g., about:blank) can only be locked to a site if it is still unused.
    //
    // Note that although NavigationThrottles could still cancel the navigation
    // as part of WillProcessResponse below, we must update the process here,
    // since otherwise there could be a race if a NavigationThrottle defers the
    // navigation, and in the meantime another navigation reads the incorrect
    // IsUnused() value from the same process when making a process reuse
    // decision.
    GetRenderFrameHost()->GetProcess()->SetIsUsed();

    // Now that we know the IsolationContext for the assigned SiteInstance, we
    // opt the origin into OAC here if needed. Note that this doesn't need to
    // account for loading data URLs with a base URL, because such a base URL
    // can never opt into OAC.
    // TODO(wjmaclean): Remove this call/function when same-process
    // OriginAgentCluster moves to SiteInstanceGroup, as then all OAC origins
    // will get a SiteInstance (regardless of process isolation) and tracking
    // will be handled by the existing pathway in
    // SiteInstanceImpl::SetSiteInfoInternal().
    const IsolationContext& isolation_context = instance->GetIsolationContext();
    AddOriginAgentClusterStateIfNecessary(isolation_context);

    // TODO(wjmaclean): Once this is all working, consider combining the
    // following code into the function above.
    // If this navigation request didn't opt-in to origin isolation, we need
    // to check here in case the origin has previously requested isolation and
    // should be marked as opted-out in this SiteInstance. At this point we know
    // that |render_frame_host_|'s SiteInstance has been finalized, so it's safe
    // to use it here to get the correct |IsolationContext|.
    //
    // When loading a data URL with a base URL, use the base URL to calculate
    // the origin; otherwise, `AddDefaultIsolatedOriginIfNeeded()` will simply
    // do nothing as a data: URL has an opaque origin.
    //
    // TODO(wjmaclean): this won't handle cases like about:blank (where it
    // inherits an origin we care about).  We plan to compute the origin
    // before commit time (https://crbug.com/888079), which may make it
    // possible to compute the right origin here.
    const url::Origin origin =
        IsLoadDataWithBaseURL()
            ? url::Origin::Create(common_params_->base_url_for_data_url)
            : url::Origin::Create(common_params_->url);
    auto* policy = ChildProcessSecurityPolicyImpl::GetInstance();
    policy->AddDefaultIsolatedOriginIfNeeded(
        isolation_context, origin, false /* is_global_walk_or_frame_removal */);

    url::Origin process_lock_origin =
        url::Origin::Create(instance->GetSiteInfo().GetProcessLockURL());
    // Cache the computed v8 optimization state so that all instances of an
    // origin in a BrowsingInstance are assigned to the same process.
    policy->AddV8OptimizationDisabledStateForOriginIfNotCached(
        isolation_context.browsing_instance_id(), process_lock_origin,
        instance->GetProcess()->AreV8OptimizationsDisabled());

    // Replace the SiteInstance of the previously committed entry if it's for a
    // url that doesn't require a site assignment, if this new commit will be
    // assigning an incompatible site to the previous SiteInstance. This ensures
    // the new SiteInstance can be used with the old entry if we return to it.
    // See http://crbug.com/992198 for further context.
    NavigationEntryImpl* nav_entry =
        frame_tree_node_->navigator().controller().GetLastCommittedEntry();
    if (nav_entry && !nav_entry->GetURL().IsAboutBlank() &&
        !SiteInstance::ShouldAssignSiteForURL(nav_entry->GetURL()) &&
        SiteInstanceImpl::ShouldAssignSiteForUrlInfo(GetUrlInfo())) {
      scoped_refptr<FrameNavigationEntry> frame_entry =
          nav_entry->root_node()->frame_entry;
      scoped_refptr<SiteInstanceImpl> new_site_instance =
          base::WrapRefCounted<SiteInstanceImpl>(static_cast<SiteInstanceImpl*>(
              instance->GetRelatedSiteInstance(frame_entry->url()).get()));
      nav_entry->AddOrUpdateFrameEntry(
          frame_tree_node_, NavigationEntryImpl::UpdatePolicy::kReplace,
          frame_entry->item_sequence_number(),
          frame_entry->document_sequence_number(),
          frame_entry->navigation_api_key(), new_site_instance.get(),
          frame_entry->source_site_instance(), frame_entry->url(),
          frame_entry->committed_origin(), frame_entry->referrer(),
          frame_entry->initiator_origin(), frame_entry->initiator_base_url(),
          frame_entry->redirect_chain(), frame_entry->page_state(),
          frame_entry->method(), frame_entry->post_id(),
          frame_entry->blob_url_loader_factory(),
          frame_entry->policy_container_policies()
              ? frame_entry->policy_container_policies()->ClonePtr()
              : nullptr);
    }
  }

  devtools_instrumentation::OnNavigationResponseReceived(*this,
                                                         *response_head_);

  // The response code indicates that this is an error page, but we don't
  // know how to display the content.  We follow Firefox here and show our
  // own error page instead of intercepting the request as a stream or a
  // download.
  if (IsFailedDownload(is_download, response_head_->headers.get())) {
    OnRequestFailedInternal(
        network::URLLoaderCompletionStatus(net::ERR_INVALID_RESPONSE),
        false /* skip_throttles */, std::nullopt /* error_page_content */,
        false /* collapse_frame */);

    // DO NOT ADD CODE after this. The previous call to OnRequestFailedInternal
    // has destroyed the NavigationRequest.
    return;
  }

  net::Error net_error = CheckContentSecurityPolicy(
      was_redirected_ /* has_followed_redirect */,
      false /* url_upgraded_after_redirect */, true /* is_response_check */);
  DCHECK_NE(net_error, net::ERR_BLOCKED_BY_CLIENT);
  if (net_error != net::OK) {
    OnRequestFailedInternal(network::URLLoaderCompletionStatus(net_error),
                            false /* skip_throttles */,
                            std::nullopt /* error_page_content */,
                            false /* collapse_frame */);

    // DO NOT ADD CODE after this. The previous call to OnRequestFailedInternal
    // has destroyed the NavigationRequest.
    return;
  }

  // TODO(crbug.com/399783247): Remove
  if (base::FeatureList::IsEnabled(
          features::kHoldbackDebugReasonStringRemoval)) {
    SCOPED_CRASH_KEY_STRING256("Bug1454273", "base_host_for_data_url",
                               common_params_->base_url_for_data_url.host());
    SCOPED_CRASH_KEY_STRING1024("Bug1454273", "rfh_selected_reason",
                                rfh_selected_reason);
  }

  if (HasRenderFrameHost() &&
      !CheckPermissionsPoliciesForFencedFrames(GetOriginToCommit().value())) {
    auto completion_status =
        network::URLLoaderCompletionStatus(net::ERR_ABORTED);
    error_navigation_trigger_ =
        ErrorNavigationTrigger::kFencedFramesPermissionPolicyBlocked;
    OnRequestFailedInternal(completion_status, false /*skip_throttles*/,
                            std::nullopt /*error_page_content*/,
                            false /*collapse_frame*/);
    // DO NOT ADD CODE after this. The previous call to
    // OnRequestFailedInternal has destroyed the NavigationRequest.
    return;
  }

  // Check if the navigation should be allowed to proceed.
  WillProcessResponse();
}

void NavigationRequest::OnRequestFailed(
    const network::URLLoaderCompletionStatus& status) {
  DCHECK_NE(status.error_code, net::OK);

  OnRequestFailedInternal(
      status, false /* skip_throttles */, std::nullopt /* error_page_content */,
      status.should_collapse_initiator /* collapse_frame */);
}

std::optional<NavigationEarlyHintsManagerParams>
NavigationRequest::CreateNavigationEarlyHintsManagerParams(
    const network::mojom::EarlyHints& early_hints) {
  TRACE_EVENT("navigation",
              "NavigationRequest::CreateNavigationEarlyHintsManagerParams",
              perfetto::Flow::FromPointer(this));
  // Early Hints preloads should happen only before the final response is
  // received, and limited only in the main frame for now.
  CHECK(!HasRenderFrameHost());
  CHECK(loader_);
  CHECK_LT(state_, WILL_PROCESS_RESPONSE);
  CHECK(!IsSameDocument());
  CHECK(IsInMainFrame());
  DCHECK(!IsPageActivation());

  // Getting a RenderProcessHost from a tentative RenderFrameHost during
  // navigation is generally discouraged because it has potential performance
  // impact (the RenderProcessHost could be discarded without actually being
  // used after a cross origin redirect). However, Early Hints preloads require
  // the RenderProcessHost for the tentative RenderFrameHost to set up
  // URLLoaderFactoryParams accordingly. The performance implication should be
  // negligible for Early Hints because these are rarely followed by cross
  // origin redirects. Early Hints preloads before a cross origin redirect don't
  // make sense since such preloads are not available for the redirected page.
  // The CrossOriginRedirectAfterEarlyHints variant of
  // Navigation.MainFrame.TimeToReadyToCommit2 histogram tracks the performance
  // impacts.
  auto result = frame_tree_node_->render_manager()->GetFrameHostForNavigation(
      this, &browsing_context_group_swap_,
      ProcessAllocationContext::CreateForNavigationRequest(
          ProcessAllocationNavigationStage::kHandlingEarlyHints, navigation_id_,
          IsInOutermostMainFrame()));

  // Early hints is an optimization; if it is not possible to get a suitable
  // RenderFrameHost for any reason, just bail out.
  if (!result.has_value()) {
    return std::nullopt;
  }

  RenderProcessHost* process = result.value()->GetProcess();

  // The process is shutting down.
  if (!process->GetBrowserContext())
    return std::nullopt;

  // Compute sandbox flags. Currently just inherit from the frame.
  // TODO(crbug.com/40188470): Think about the right way the specification
  // should handle sandbox flags with Early Hints.
  network::mojom::WebSandboxFlags sandbox_flags =
      commit_params_->frame_policy.sandbox_flags;

  const url::Origin tentative_origin =
      GetOriginForURLLoaderFactoryBeforeResponse(sandbox_flags);

  mojo::PendingRemote<network::mojom::CookieAccessObserver> cookie_observer;
  cookie_observers_->Add(cookie_observer.InitWithNewPipeAndPassReceiver(),
                         CookieAccessDetails::Source::kNonNavigation);

  mojo::PendingRemote<network::mojom::TrustTokenAccessObserver>
      trust_token_observer;
  Clone(trust_token_observer.InitWithNewPipeAndPassReceiver());

  mojo::PendingRemote<network::mojom::SharedDictionaryAccessObserver>
      shared_dictionary_observer;
  Clone(shared_dictionary_observer.InitWithNewPipeAndPassReceiver());

  mojo::PendingRemote<network::mojom::DeviceBoundSessionAccessObserver>
      device_bound_session_observer;
  Clone(device_bound_session_observer.InitWithNewPipeAndPassReceiver());

  network::mojom::URLLoaderFactoryParamsPtr url_loader_factory_params =
      URLLoaderFactoryParamsHelper::CreateForEarlyHintsPreload(
          process, tentative_origin, *this, early_hints,
          std::move(cookie_observer), std::move(trust_token_observer),
          std::move(shared_dictionary_observer),
          std::move(device_bound_session_observer));

  net::IsolationInfo isolation_info = url_loader_factory_params->isolation_info;

  // TODO(crbug.com/40188470): Support DevTools instrumentation and extension's
  // WebRequest API.
  auto loader_factory = url_loader_factory::CreatePendingRemote(
      ContentBrowserClient::URLLoaderFactoryType::kEarlyHints,
      url_loader_factory::TerminalParams::ForNetworkContext(
          process->GetStoragePartition()->GetNetworkContext(),
          std::move(url_loader_factory_params)));

  did_create_early_hints_manager_params_ = true;
  return NavigationEarlyHintsManagerParams(
      tentative_origin, std::move(isolation_info),
      mojo::Remote<network::mojom::URLLoaderFactory>(
          std::move(loader_factory)));
}

void NavigationRequest::OnRequestFailedInternal(
    const network::URLLoaderCompletionStatus& status,
    bool skip_throttles,
    const std::optional<std::string>& error_page_content,
    bool collapse_frame) {
  TRACE_EVENT("navigation", "NavigationRequest::OnRequestFailedInternal",
              perfetto::Flow::FromPointer(this));
  CheckStateTransition(WILL_FAIL_REQUEST);
  DCHECK(!(status.error_code == net::ERR_ABORTED &&
           error_page_content.has_value()));
  ScopedCrashKeys crash_keys(*this);

  if (reserved_prerender_host_info_.has_value()) {
    // Prerender activation must not fail but some reports imply it can actually
    // be failing: crbug.com/411566699, crbug.com/408969974. This dump is useful
    // for debugging it.
    std::string prerender_type = GeneratePrerenderHistogramSuffix(
        GetPrerenderTriggerType(), GetPrerenderEmbedderHistogramSuffix());
    SCOPED_CRASH_KEY_STRING64("Bug411566699", "prerender_type", prerender_type);
    base::debug::DumpWithoutCrashing();
  }

  if (MaybeEvictFromBackForwardCacheBySubframeNavigation(
          frame_tree_node_->current_frame_host())) {
    // DO NOT ADD CODE AFTER THIS, as the NavigationRequest might have been
    // deleted by the previous calls.
    return;
  }

  // The request failed, the |loader_| must not call the NavigationRequest
  // anymore from now while the error page is being loaded.
  loader_.reset();

  // Reset the RenderFrameHost R1 that had been computed for committing the
  // failed navigation. This breaks the binding between the current
  // NavigationRequest and R1, so that if we create another speculative
  // RenderFrameHost R2 to commit an error page after this, deleting R1 won't
  // try to delete this NavigationRequest along with it.
  render_frame_host_ = std::nullopt;

  // Do not update ssl_info_ on HTTP_RESPONSE_CODE_FAILURE (e.g., HTTP 4xx/5xx
  // errors). In these cases, URLLoaderCompletionStatus does not have ssl_info.
  // The existing ssl_info_ should be preserved by design, so the certificate is
  // retained for error pages, ensuring correct security UI and metrics.
  if (status.error_code != net::ERR_HTTP_RESPONSE_CODE_FAILURE) {
    ssl_info_ = status.ssl_info;
  }

  devtools_instrumentation::OnNavigationRequestFailed(*this, status);

  // TODO(crbug.com/41340435): Check that ssl_info.has_value() if
  // net_error is a certificate error.
  EnterChildTraceEvent("OnRequestFailed", this, "error", status.error_code);
  SetState(WILL_FAIL_REQUEST);
  processing_navigation_throttle_ = false;

  // Ensure the pending entry also gets discarded if it has no other active
  // requests.
  pending_entry_ref_.reset();

  net_error_ = static_cast<net::Error>(status.error_code);
  extended_error_code_ = status.extended_error_code;
  resolve_error_info_ = status.resolve_error_info;
  navigation_handle_timing_.request_failed_time = base::TimeTicks::Now();

  if (MaybeCancelFailedNavigation())
    return;

  // Only notify the NavigationHandleTiming update if the navigation will commit
  // an error page (instead of getting ignored and deleted above).
  GetDelegate()->DidUpdateNavigationHandleTiming(this);

  if (collapse_frame) {
    DCHECK_EQ(net::ERR_BLOCKED_BY_CLIENT, status.error_code);
    frame_tree_node_->SetCollapsed(true);
  }

  is_mhtml_or_subframe_ = false;
  // TODO(crbug.com/40736932): Apparently, error pages inherit sandbox
  // flags from their parent/opener. Document loaded from the network
  // shouldn't have any influence over Chrome's internal error page. We should
  // define our own flags, preferably the strictest ones instead.
  ComputePoliciesToCommitForError();

  const auto origin = url::Origin();
  // Set the COOP origin in the policy container builder before FinalPolicies()
  // is called.
  coop_status_.EnforceCOOP(
      policy_container_builder_->FinalPolicies().cross_origin_opener_policy,
      origin, net::NetworkAnonymizationKey::CreateTransient());

  SelectFrameHostForOnRequestFailedInternal(status.exists_in_cache,
                                            skip_throttles, error_page_content);
}

void NavigationRequest::SelectFrameHostForOnRequestFailedInternal(
    bool exists_in_cache,
    bool skip_throttles,
    const std::optional<std::string>& error_page_content) {
  CHECK(!HasRenderFrameHost())
      << "`render_frame_host_` should not be set before the "
         "`NavigationRequest` starts to select the RFH.";

  switch (ComputeErrorPageProcess()) {
    case ErrorPageProcess::kCurrentProcess:
      // There's no way to get here with a same-document navigation, it would
      // need to be on a document that was not blocked but became blocked, but
      // same document navigations don't go to the network so it wouldn't know
      // about the change.
      CHECK(!IsSameDocument());
      break;
    case ErrorPageProcess::kIsolatedProcess:
      // In this case we are isolating the error page from the source and
      // destination process, and want it to go to a new process.
      //
      // TODO(nasko): Investigate whether GetFrameHostForNavigation can properly
      // account for clearing the expected process if it clears the speculative
      // RenderFrameHost. See https://crbug.com/793127.
      ResetExpectedProcess();
      [[fallthrough]];
    case ErrorPageProcess::kDestinationProcess:
      // A same-document navigation would normally attempt to navigate the
      // current document, but since we will be presenting an error instead and
      // there will not be a document to navigate. We always make an error here
      // into a cross-document navigation. See https://crbug.com/1018385 and
      // https://crbug.com/1125106.
      common_params_->navigation_type =
          ConvertToCrossDocumentType(common_params_->navigation_type);
      break;
    case ErrorPageProcess::kNotErrorPage:
    case ErrorPageProcess::kPostCommitErrorPage:
      NOTREACHED();
  }

  RenderFrameHostImpl* render_frame_host = nullptr;
  if (auto result =
          frame_tree_node_->render_manager()->GetFrameHostForNavigation(
              this, &browsing_context_group_swap_,
              ProcessAllocationContext::CreateForNavigationRequest(
                  ProcessAllocationNavigationStage::kAfterFailure,
                  navigation_id_, IsInOutermostMainFrame()));
      result.has_value()) {
    render_frame_host = result.value();
  } else {
    switch (result.error()) {
      case GetFrameHostForNavigationFailed::kCouldNotReinitializeMainFrame:
        // TODO(crbug.com/40250311): This was unhandled
        // before and remains explicitly unhandled. This branch may be
        // removed in the future.
        break;
      case GetFrameHostForNavigationFailed::kBlockedByPendingCommit:
        resume_commit_closure_ = base::BindOnce(
            &NavigationRequest::SelectFrameHostForOnRequestFailedInternal,
            weak_factory_.GetWeakPtr(), exists_in_cache, skip_throttles,
            error_page_content);
        frame_tree_node_->render_manager()
            ->speculative_frame_host()
            ->RecordMetricsForBlockedGetFrameHostAttempt(
                /* commit_attempt=*/true);
        return;
    }
  }

  render_frame_host_ = render_frame_host->GetSafeRef();

  // Update the associated RenderFrameHost type.
  SetAssociatedRFHType(
      GetRenderFrameHost() ==
              frame_tree_node_->render_manager()->current_frame_host()
          ? AssociatedRenderFrameHostType::CURRENT
          : AssociatedRenderFrameHostType::SPECULATIVE);

  // Set the site URL now if it hasn't been set already.  It's possible to get
  // here if we navigate to an error out of an initial "blank" SiteInstance.
  // Also mark the process as used, since it will be hosting an error page.
  SiteInstanceImpl* instance = GetRenderFrameHost()->GetSiteInstance();
  if (!instance->HasSite())
    instance->ConvertToDefaultOrSetSite(GetUrlInfo());
  GetRenderFrameHost()->GetProcess()->SetIsUsed();

  // The check for WebUI should be performed only if error page isolation is
  // enabled for this failed navigation. It is possible for subframe error page
  // to be committed in a WebUI process as shown in https://crbug.com/944086.
  if (frame_tree_node_->IsErrorPageIsolationEnabled()) {
    CHECK(Navigator::CheckWebUIRendererDoesNotDisplayNormalURL(
        GetRenderFrameHost(), GetUrlInfo(),
        /* is_renderer_initiated_check */ false));
  }

  has_stale_copy_in_cache_ = exists_in_cache;

  if (skip_throttles) {
    // The NavigationHandle shouldn't be notified about renderer-debug URLs.
    // They will be handled by the renderer process.
    PrepareToCommitErrorPage(error_page_content);
  } else {
    // Check if the navigation should be allowed to proceed.
    WillFailRequest();
  }
}

NavigationRequest::ErrorPageProcess
NavigationRequest::ComputeErrorPageProcess() {
  if (net_error_ == net::OK) {
    return ErrorPageProcess::kNotErrorPage;
  }

  if (state_ < NavigationRequest::CANCELING) {
    CHECK(browser_initiated_error_navigation_type_ !=
          BrowserInitiatedErrorNavigationType::kNone);

    if (browser_initiated_error_navigation_type_ ==
        BrowserInitiatedErrorNavigationType::kPostCommit) {
      // Post-commit error page normally goes through the "non-error page"
      // navigation path, so treat them specially here too.
      return ErrorPageProcess::kPostCommitErrorPage;
    }

    // Otherwise, this is a normal browser-initiated error navigation, which
    // should fall out of this block and use existing process selection
    // behavior.
  }

  // By policy we can isolate all error pages from both the current and
  // destination processes.
  if (frame_tree_node_->IsErrorPageIsolationEnabled())
    return ErrorPageProcess::kIsolatedProcess;

  // Decide whether to leave the error page in the original process.
  // * If this was a renderer-initiated navigation, and the request is blocked
  //   because the initiating document wasn't allowed to make the request,
  //   commit the error in the existing process. This is a strategy to to
  //   avoid creating a process for the destination, which may belong to an
  //   origin with a higher privilege level.
  // * Error pages resulting from errors like network outage, no network, or
  //   DNS error can reasonably expect that a reload at a later point in time
  //   would work. These should be allowed to transfer away from the current
  //   process: they do belong to whichever process that will host the
  //   destination URL, as a reload will end up committing in that process
  //   anyway.
  // * Error pages that arise during browser-initiated navigations to blocked
  //   URLs should be allowed to transfer away from the current process, which
  //   didn't request the navigation and may have a higher privilege level
  //   than the blocked destination.
  if (net::IsRequestBlockedError(net_error_) && !browser_initiated()) {
    return ErrorPageProcess::kCurrentProcess;
  }
  return ErrorPageProcess::kDestinationProcess;
}

void NavigationRequest::OnStartChecksComplete(
    NavigationThrottle::ThrottleCheckResult result) {
  TRACE_EVENT("navigation", "NavigationRequest::OnStartChecksComplete",
              perfetto::Flow::FromPointer(this));
  DCHECK(result.action() != NavigationThrottle::DEFER);
  DCHECK(result.action() != NavigationThrottle::BLOCK_RESPONSE);

  if (on_start_checks_complete_closure_)
    std::move(on_start_checks_complete_closure_).Run();
  // Abort the request if needed. This will destroy the NavigationRequest.
  if (result.action() == NavigationThrottle::CANCEL_AND_IGNORE ||
      result.action() == NavigationThrottle::CANCEL ||
      result.action() == NavigationThrottle::BLOCK_REQUEST ||
      result.action() == NavigationThrottle::BLOCK_REQUEST_AND_COLLAPSE) {
#if DCHECK_IS_ON()
    if (result.action() == NavigationThrottle::BLOCK_REQUEST) {
      DCHECK(net::IsRequestBlockedError(result.net_error_code()));
    } else if (result.action() == NavigationThrottle::CANCEL_AND_IGNORE) {
      // TODO(clamy): distinguish between CANCEL and CANCEL_AND_IGNORE.
      DCHECK_EQ(result.net_error_code(), net::ERR_ABORTED);
    }
#endif

    bool collapse_frame =
        result.action() == NavigationThrottle::BLOCK_REQUEST_AND_COLLAPSE;

    // If the start checks completed synchronously, which could happen if there
    // is no onbeforeunload handler or if a NavigationThrottle cancelled it,
    // then this could cause reentrancy into NavigationController. So use a
    // PostTask to avoid that.
    auto completion_status =
        network::URLLoaderCompletionStatus(result.net_error_code());
    if (result.action() == NavigationThrottle::CANCEL_AND_IGNORE ||
        result.action() == NavigationThrottle::CANCEL) {
      error_navigation_trigger_ =
          ErrorNavigationTrigger::kNavigationThrottleCancel;
    } else {
      error_navigation_trigger_ =
          ErrorNavigationTrigger::kNavigationThrottleBlock;
    }
    GetUIThreadTaskRunner({})->PostTask(
        FROM_HERE,
        base::BindOnce(&NavigationRequest::OnRequestFailedInternal,
                       weak_factory_.GetWeakPtr(), std::move(completion_status),
                       true /* skip_throttles */, result.error_page_content(),
                       collapse_frame));

    // DO NOT ADD CODE after this. The previous call to OnRequestFailedInternal
    // has destroyed the NavigationRequest.
    return;
  }

  StoragePartition* partition = GetStoragePartitionWithCurrentSiteInfo();
  DCHECK(partition);

  // |loader_| should not exist if the service worker handle
  // will be destroyed, since it holds raw pointers to it. See the
  // comment in the header for |loader_|.
  DCHECK(!loader_);

  // Only initialize the ServiceWorkerMainResourceHandle if it can be created
  // for this frame.
  bool can_create_service_worker =
      (frame_tree_node_->pending_frame_policy().sandbox_flags &
       network::mojom::WebSandboxFlags::kOrigin) !=
      network::mojom::WebSandboxFlags::kOrigin;
  if (can_create_service_worker) {
    ServiceWorkerContextWrapper* service_worker_context =
        static_cast<ServiceWorkerContextWrapper*>(
            partition->GetServiceWorkerContext());
    std::string fetch_event_client_id;
    // TODO(crbug.com/368087661): According to the spec this should be fetch
    // request's client but it is not here in the implementation.
    if (auto client = frame_tree_node_->current_frame_host()
                          ->GetLastCommittedServiceWorkerClient()) {
      fetch_event_client_id = client->client_uuid();
    }
    service_worker_handle_ = std::make_unique<ServiceWorkerMainResourceHandle>(
        service_worker_context,
        base::BindRepeating(&NavigationRequest::OnServiceWorkerAccessed,
                            weak_factory_.GetWeakPtr()),
        std::move(fetch_event_client_id));
  }

  // Mark the fetch_start (Navigation Timing API).
  commit_params_->navigation_timing->fetch_start = base::TimeTicks::Now();

  // Ensure that normal history navigations can dispatch the Navigation API's
  // navigate event as the navigation is starting. Cases without a UrlLoader
  // are handled in OnWillCommitWithoutUrlLoaderChecksComplete.
  MaybeDispatchNavigateEventForCrossDocumentTraversal();

  std::unique_ptr<NavigationUIData> navigation_ui_data;
  if (navigation_ui_data_)
    navigation_ui_data = navigation_ui_data_->Clone();

  // Give DevTools a chance to override begin params (headers, skip SW)
  // before actually loading resource.
  bool report_raw_headers = false;
  std::optional<std::vector<net::SourceStreamType>>
      devtools_accepted_stream_types;
  GURL devtools_referrer_override;
  devtools_instrumentation::ApplyNetworkRequestOverrides(
      frame_tree_node_, begin_params_.get(), &report_raw_headers,
      &devtools_accepted_stream_types, &devtools_user_agent_override_,
      &devtools_accept_language_override_, &devtools_referrer_override);

  if (!devtools_referrer_override.is_empty()) {
    // When the `Referer` header is overridden by DevTools (e.g. by CDP command
    // `Network.setExtraHTTPHeaders`), bypass referrer sanitization and set the
    // custom referrer of the navigation params to the overridden referrer
    // value. See crbug.com/437323961.
    common_params_->referrer->url = devtools_referrer_override;
  }

  devtools_instrumentation::OnNavigationRequestWillBeSent(*this);

  // Merge headers with embedder's headers.
  net::HttpRequestHeaders headers;
  headers.AddHeadersFromString(begin_params_->headers);
  headers.MergeFrom(TakeModifiedRequestHeaders());
  begin_params_->headers = headers.ToString();

  // TODO(clamy): Avoid cloning the navigation params and create the
  // ResourceRequest directly here.
  std::vector<std::unique_ptr<NavigationLoaderInterceptor>> interceptor;

  auto loader_type = NavigationURLLoader::LoaderType::kRegular;
  network::mojom::URLResponseHeadPtr cached_response_head = nullptr;
  if (IsServedFromBackForwardCache()) {
    loader_type = NavigationURLLoader::LoaderType::kNoopForBackForwardCache;
    cached_response_head = GetRenderFrameHostRestoredFromBackForwardCache()
                               ->last_response_head()
                               ->Clone();
  } else if (IsPrerenderedPageActivation()) {
    loader_type = NavigationURLLoader::LoaderType::kNoopForPrerender;
    DCHECK(prerender_frame_tree_node_id_.has_value());
    const network::mojom::URLResponseHeadPtr& last_response_head =
        GetPrerenderHostRegistry()
            .GetRenderFrameHostForReservedHost(*prerender_frame_tree_node_id_)
            ->last_response_head();
    // As PrerenderCommitDeferringCondition makes sure to finish the prerender
    // initial navigation before activation, a valid last_response_head should
    // be always stored before reaching here.
    DCHECK(last_response_head);
    cached_response_head = last_response_head->Clone();
  }

  // Sandbox flags inherited from the frame. In particular, this does not
  // include:
  // - Sandbox flags inherited from the creator via the PolicyContainer.
  // - Sandbox flags forced for MHTML documents.
  // - Sandbox flags from the future response via CSP.
  // It is used by the ExternalProtocolHandler to ensure sandboxed iframe won't
  // navigate the user toward a different application, which can be seen as a
  // main frame navigation somehow.
  network::mojom::WebSandboxFlags sandbox_flags =
      commit_params_->frame_policy.sandbox_flags;

  // Reset the compositor lock before starting the loader.
  compositor_lock_.reset();

  BrowserContext* browser_context =
      frame_tree_node_->navigator().controller().GetBrowserContext();

  // Create `PrefetchServingPageMetricsContainer` only if the initiator
  // document has its `PrefetchDocumentManager`.
  base::WeakPtr<PrefetchServingPageMetricsContainer>
      serving_page_metrics_container;
  if (!IsSameDocument() && initiator_document_token_ &&
      PrefetchDocumentManager::FromDocumentToken(initiator_process_id_,
                                                 *initiator_document_token_)) {
    serving_page_metrics_container =
        PrefetchServingPageMetricsContainer::GetOrCreateForNavigationHandle(
            *this)
            ->GetWeakPtr();
  }

  loader_ = NavigationURLLoader::Create(
      browser_context, partition,
      std::make_unique<NavigationRequestInfo>(
          common_params_->Clone(), begin_params_.Clone(), sandbox_flags,
          GetIsolationInfo(),
          frame_tree_node_->current_frame_host()->IsInPrimaryMainFrame(),
          frame_tree_node_->IsOutermostMainFrame(),
          frame_tree_node_->IsMainFrame(),
          frame_tree_node_->AreAncestorsSecure(),
          frame_tree_node_->frame_tree_node_id(), report_raw_headers,
          upgrade_if_insecure_,
          blob_url_loader_factory_ ? blob_url_loader_factory_->Clone()
                                   : nullptr,
          devtools_navigation_token(),
          frame_tree_node_->current_frame_host()->devtools_frame_token(),
          BuildClientSecurityStateForNavigationFetch(),
          devtools_accepted_stream_types, is_pdf_, GetInitiatorProcessId(),
          initiator_document_token_, GetPreviousRenderFrameHostId(),
          std::move(serving_page_metrics_container),
          allow_cookies_from_browser_, navigation_id_,
          shared_storage_writable_eligible_, is_ad_tagged_,
          force_no_https_upgrade_),
      std::move(navigation_ui_data), service_worker_handle_.get(),
      std::move(prefetched_signed_exchange_cache_), this, loader_type,
      CreateCookieAccessObserver(), CreateTrustTokenAccessObserver(),
      CreateSharedDictionaryAccessObserver(),
      static_cast<StoragePartitionImpl*>(partition)
          ->CreateURLLoaderNetworkObserverForNavigationRequest(*this),
      NetworkServiceDevToolsObserver::MakeSelfOwned(frame_tree_node_),
      CreateDeviceBoundSessionObserver(), std::move(cached_response_head),
      std::move(interceptor));
  DCHECK(!HasRenderFrameHost());

  // If needed, perform an early RenderFrameHost swap after notifying observers
  // with DidStartNavigation, after processing WillStartRequest throttle events,
  // and after creating the NavigationURLLoader above (which needs the old
  // current_frame_host()). This (1) avoids performing the early swap in case
  // the navigation gets canceled prior to getting here, and (2) ensures that
  // DidStartNavigation and WillStartRequest implementations are not disrupted
  // by the early swap and don't see a RenderFrameHostChanged event prior to a
  // navigation actually starting.
  //
  // TODO(crbug.com/40276607): Remove the `is_called_after_did_start_navigation`
  // param once all early swaps are done from here.
  frame_tree_node_->render_manager()->PerformEarlyRenderFrameHostSwapIfNeeded(
      this, /*is_called_after_did_start_navigation=*/true);

  base::UmaHistogramTimes(
      base::StrCat({"Navigation.WillStartRequestToLoaderStart.",
                    IsInMainFrame() ? "MainFrame" : "Subframe"}),
      base::TimeTicks::Now() - will_start_request_time_);
  absl::Cleanup scoped_set_now = [navigation_request =
                                      weak_factory_.GetWeakPtr()] {
    if (navigation_request) {
      navigation_request->navigation_handle_timing_.loader_start_time =
          base::TimeTicks::Now();
      navigation_request->GetDelegate()->DidUpdateNavigationHandleTiming(
          navigation_request.get());
    }
  };

  base::WeakPtr<NavigationRequest> this_ptr(weak_factory_.GetWeakPtr());
  loader_->Start();

  if (!this_ptr) {
    // `this` have been deleted by NavigationURLLoader::Start
    // DO NOT ADD CODE HERE.
    return;
  }

  // Try to create the speculative RFH after sending the network request
  // if DeferSpeculativeRFHCreation is enabled.
  // Only create the speculative RFH if it is a normal loading rather than
  // a BFCache restore or prerender activation. Otherwise `OnResponseStarted`
  // will be called instantly and the creation of the speculative RFH is
  // redundant.
  // TODO(crbug.com/394732486): All the speculative RFH creation will be skipped
  // if kDeferSpeculativeRFHWaitUntilFinalResponse is set. The behavior can
  // be more adaptive by limiting to sites that commonly use COOP.
  if (base::FeatureList::IsEnabled(features::kDeferSpeculativeRFHCreation) &&
      !kDeferSpeculativeRFHWaitUntilFinalResponse.Get() &&
      GetAssociatedRFHType() == AssociatedRenderFrameHostType::NONE) {
    if (features::kCreateSpeculativeRFHFilterRestore.Get() &&
        loader_type != NavigationURLLoader::LoaderType::kRegular) {
      return;
    }
    auto create_speculative_rfh_task = base::BindOnce(
        [](base::WeakPtr<NavigationRequest> request, int64_t navigation_id) {
          if (!request || request->state_ >= WILL_PROCESS_RESPONSE ||
              request->HasRenderFrameHost()) {
            return;
          }
          auto rfh_creation_result =
              request->frame_tree_node_->render_manager()
                  ->GetFrameHostForNavigation(
                      request.get(), &request->browsing_context_group_swap_,
                      ProcessAllocationContext::CreateForNavigationRequest(
                          ProcessAllocationNavigationStage::
                              kAfterNetworkRequest,
                          navigation_id, request->IsInOutermostMainFrame()));
          if (rfh_creation_result.has_value()) {
            request->SetExpectedProcessIfAssociated();
          }
        },
        weak_factory_.GetWeakPtr(), navigation_id_);
    int delay_ms = features::kCreateSpeculativeRFHDelayMs.Get();
    if (delay_ms > 0) {
      GetUIThreadTaskRunner()->PostDelayedTask(
          FROM_HERE, std::move(create_speculative_rfh_task),
          base::Milliseconds(delay_ms));
    } else {
      std::move(create_speculative_rfh_task).Run();
    }
  }
}

void NavigationRequest::OnServiceWorkerAccessed(
    const GURL& scope,
    AllowServiceWorkerResult allowed) {
  GetDelegate()->OnServiceWorkerAccessed(this, scope, allowed);
}

network::mojom::WebSandboxFlags NavigationRequest::SandboxFlagsInitiator() {
  return sandbox_flags_initiator_;
}

network::mojom::WebSandboxFlags NavigationRequest::SandboxFlagsInherited() {
  return commit_params_->frame_policy.sandbox_flags;
}

network::mojom::WebSandboxFlags NavigationRequest::SandboxFlagsToCommit() {
  DCHECK_GE(state_, WILL_PROCESS_RESPONSE);
  DCHECK(!IsSameDocument());
  DCHECK(!IsPageActivation());
  return policy_container_builder_->FinalPolicies().sandbox_flags;
}

void NavigationRequest::MaybeAddResourceTimingEntryForCancelledNavigation() {
  // Some navigation are cancelled even before requesting and receiving a
  // response. Those cases are not supported and the ResourceTiming is not
  // reported to the parent.
  if (!response()) {
    return;
  }

  network::URLLoaderCompletionStatus status;
  status.encoded_data_length = response()->encoded_data_length;
  status.completion_time = base::TimeTicks::Now();
  AddResourceTimingEntryForFailedSubframeNavigation(status);
}

void NavigationRequest::AddResourceTimingEntryForFailedSubframeNavigation(
    const network::URLLoaderCompletionStatus& status) {
  // For TAO-fail navigations, we would resort to fallback timing.
  // See HTMLFrameOwnerElement::ReportFallbackResourceTimingIfNeeded().
  DCHECK(response());
  if (commit_params().navigation_timing->parent_resource_timing_access ==
      blink::mojom::ParentResourceTimingAccess::kDoNotReport) {
    return;
  }

  network::mojom::URLResponseHeadPtr response_head = response()->Clone();

  bool allow_response_details =
      commit_params().navigation_timing->parent_resource_timing_access ==
      blink::mojom::ParentResourceTimingAccess::kReportWithResponseDetails;

  GetParentFrame()->AddResourceTimingEntryForFailedSubframeNavigation(
      frame_tree_node(), common_params().navigation_start,
      commit_params().navigation_timing->redirect_end,
      commit_params().original_url, common_params().url,
      std::move(response_head), allow_response_details, status);
}

void NavigationRequest::OnRedirectChecksComplete(
    NavigationThrottle::ThrottleCheckResult result) {
  TRACE_EVENT("navigation", "NavigationRequest::OnRedirectChecksComplete",
              perfetto::Flow::FromPointer(this));
  DCHECK(result.action() != NavigationThrottle::DEFER);
  DCHECK(result.action() != NavigationThrottle::BLOCK_RESPONSE);
  DCHECK(!IsPageActivation());

  bool collapse_frame =
      result.action() == NavigationThrottle::BLOCK_REQUEST_AND_COLLAPSE;

  // Abort the request if needed. This will destroy the NavigationRequest.
  if (result.action() == NavigationThrottle::CANCEL_AND_IGNORE ||
      result.action() == NavigationThrottle::CANCEL) {
    // TODO(clamy): distinguish between CANCEL and CANCEL_AND_IGNORE if needed.
    DCHECK(result.action() == NavigationThrottle::CANCEL ||
           result.net_error_code() == net::ERR_ABORTED);
    auto completion_status =
        network::URLLoaderCompletionStatus(result.net_error_code());
    error_navigation_trigger_ =
        ErrorNavigationTrigger::kNavigationThrottleCancel;
    OnRequestFailedInternal(std::move(completion_status),
                            true /* skip_throttles */,
                            result.error_page_content(), collapse_frame);

    // DO NOT ADD CODE after this. The previous call to OnRequestFailedInternal
    // has destroyed the NavigationRequest.
    return;
  }

  if (result.action() == NavigationThrottle::BLOCK_REQUEST ||
      result.action() == NavigationThrottle::BLOCK_REQUEST_AND_COLLAPSE) {
    DCHECK(net::IsRequestBlockedError(result.net_error_code()));
    auto completion_status =
        network::URLLoaderCompletionStatus(result.net_error_code());
    if (result.net_error_code() == net::ERR_ABORTED) {
      error_navigation_trigger_ =
          ErrorNavigationTrigger::kNavigationThrottleBlock;
    }
    OnRequestFailedInternal(
        network::URLLoaderCompletionStatus(result.net_error_code()),
        true /* skip_throttles */, result.error_page_content(), collapse_frame);
    // DO NOT ADD CODE after this. The previous call to OnRequestFailedInternal
    // has destroyed the NavigationRequest.
    return;
  }

  devtools_instrumentation::OnNavigationRequestWillBeSent(*this);

  net::HttpRequestHeaders modified_headers = TakeModifiedRequestHeaders();
  std::vector<std::string> removed_headers = TakeRemovedRequestHeaders();

  // The topics a request is allowed to see can change within its redirect
  // chain thus we need to recalculate them. For example, different caller
  // origins (i.e. navigation URL's origin) may receive different topics, as the
  // callers can only get the topics about the sites they were on. Besides,
  // regardless of cross-origin-ness, the timestamp can also affect the
  // candidate epochs where the topics are derived from, thus resulting in
  // different topics across redirects.
  if (topics_eligible_) {
    topics_eligible_ = false;

    // At this point we may not have a valid `GetRenderFrameHost()` if the
    // navigation is during a cross-site redirect. Thus, pass in the current/old
    // RenderFrameHost here. This is fine, because it should still give us the
    // desired IsPrimary() status and the desired top-level frame that
    // `HandleTopicsEligibleResponse()` is interested in knowing.
    HandleTopicsEligibleResponse(
        commit_params_->redirect_response.back().get()->parsed_headers,
        url::Origin::Create(commit_params_->redirects.back()),
        *frame_tree_node_->current_frame_host(),
        browsing_topics::ApiCallerSource::kIframeAttribute);
  }

  // Removes the topics header. This will effectively be a no-op if the topics
  // header wasn't sent for the previous request.
  removed_headers.push_back(kBrowsingTopicsRequestHeaderKey);

  TopicsHeaderValueResult topics_header_value_result =
      GetTopicsHeaderValueForNavigationRequest(frame_tree_node_,
                                               common_params_->url);

  topics_eligible_ = topics_header_value_result.topics_eligible;

  if (topics_header_value_result.header_value) {
    modified_headers.SetHeader(kBrowsingTopicsRequestHeaderKey,
                               *topics_header_value_result.header_value);
  }

  if (ad_auction_headers_eligible_) {
    // Redirects are ineligible for ad auction headers.
    ad_auction_headers_eligible_ = false;
    removed_headers.push_back(kAdAuctionRequestHeaderKey);
  }

  if (shared_storage_writable_opted_in_) {
    // On a redirect, the PermissionsPolicy may change the status of this
    // request's Shared Storage eligibility, so we need to re-compute it.
    bool previous_shared_storage_writable_eligible =
        shared_storage_writable_eligible_;
    shared_storage_writable_eligible_ =
        IsSharedStorageWritableEligibleForNavigationRequest(
            frame_tree_node_, common_params_->url);

    if (shared_storage_writable_eligible_ !=
        previous_shared_storage_writable_eligible) {
      if (shared_storage_writable_eligible_) {
        modified_headers.SetHeader(kSecSharedStorageWritableRequestHeaderKey,
                                   "?1");
      } else {
        removed_headers.push_back(kSecSharedStorageWritableRequestHeaderKey);
      }
    }
  }

  // Removes all Client Hints from the request, that were passed on from the
  // previous one.
  for (const auto& elem : network::GetClientHintToNameMap()) {
    const auto& header = elem.second;
    removed_headers.push_back(header);
  }

  // Add any required Client Hints to the current request.
  BrowserContext* browser_context =
      frame_tree_node_->navigator().controller().GetBrowserContext();
  ClientHintsControllerDelegate* client_hints_delegate =
      browser_context->GetClientHintsControllerDelegate();
  if (client_hints_delegate) {
    net::HttpRequestHeaders client_hints_extra_headers;
    const url::Origin& source_origin =
        url::Origin::Create(commit_params_->redirects.back());
    const network::mojom::URLResponseHead* response_head =
        commit_params_->redirect_response.back().get();
    ParseAndPersistAcceptCHForNavigation(
        source_origin, response_head->parsed_headers,
        response_head->headers.get(), browser_context, client_hints_delegate,
        frame_tree_node_);

    AddNavigationRequestClientHintsHeaders(
        GetTentativeOriginAtRequestTime(), &client_hints_extra_headers,
        browser_context, client_hints_delegate, is_overriding_user_agent(),
        frame_tree_node_, commit_params_->frame_policy.container_policy,
        common_params_->url);
    modified_headers.MergeFrom(client_hints_extra_headers);
    // On a redirect, unless devtools has overridden the User-Agent header, we
    // should send the User-Agent string based on policy.
    if (!devtools_user_agent_override_) {
      modified_headers.SetHeader(
          net::HttpRequestHeaders::kUserAgent,
          ComputeUserAgentValue(modified_headers, GetUserAgentOverride(),
                                browser_context));
    }
  }

  // Add reduced accept language header to the current request.
  // If devtools has overridden the Accept-Language header, skip reduce
  // Accept-Language header.
  if (auto reduce_accept_lang_utils =
          ReduceAcceptLanguageUtils::Create(browser_context);
      reduce_accept_lang_utils && !devtools_accept_language_override_) {
    if (!ReduceAcceptLanguageUtils::CheckDisableReduceAcceptLanguageOriginTrial(
            common_params_->url, frame_tree_node_,
            browser_context->GetOriginTrialsControllerDelegate())) {
      net::HttpRequestHeaders accept_language_headers;
      std::optional<std::string> reduced_accept_language =
          reduce_accept_lang_utils.value()
              .AddNavigationRequestAcceptLanguageHeaders(
                  url::Origin::Create(common_params_->url), frame_tree_node_,
                  &accept_language_headers);
      commit_params_->reduced_accept_language =
          reduced_accept_language.value_or("");
      modified_headers.MergeFrom(accept_language_headers);
    } else {
      // Remove the Accept-Language header passed from previous request, if any.
      removed_headers.push_back(net::HttpRequestHeaders::kAcceptLanguage);
      commit_params_->reduced_accept_language = "";
    }
  }

  loader_->FollowRedirect(std::move(removed_headers),
                          std::move(modified_headers),
                          /*modified_cors_exempt_headers=*/{});
}

void NavigationRequest::OnFailureChecksComplete(
    NavigationThrottle::ThrottleCheckResult result) {
  TRACE_EVENT("navigation", "NavigationRequest::OnFailureChecksComplete",
              perfetto::Flow::FromPointer(this));
  // This method is called as a result of getting to the end of
  // OnRequestFailedInternal(), which calls WillFailRequest(), which
  // runs the throttles, which eventually call back to this method.
  DCHECK(result.action() != NavigationThrottle::DEFER);

  // The throttle may have changed the net_error_code, so we set the
  // `net_error_` again, overriding what OnRequestFailedInternal() set.
  net::Error old_net_error = net_error_;
  ErrorPageProcess old_error_page_process = ComputeErrorPageProcess();
  net_error_ = result.net_error_code();

  // The new `net_error_` value may mean we want to cancel the navigation.
  if (MaybeCancelFailedNavigation()) {
    return;
  }

  // FIXME: Should we clear out |extended_error_code_| here?

  // Ensure that WillFailRequest() isn't changing the error code in a way that
  // switches the destination process for the error page - see
  // https://crbug.com/817881.
  // NOTE: The throttle may change the error code to cancel a navigation which
  // could lead to a failure here, and therefore this must be done after
  // `MaybeCancelFailedNavigation`.
  CHECK_EQ(old_error_page_process, ComputeErrorPageProcess())
      << " Unsupported error code change in WillFailRequest(): from "
      << old_net_error << " to " << net_error_;

  // The OnRequestFailedInternal() did not commit the error page as it
  // deferred to WillFailRequest(), which has called through to here, and
  // now we are finally ready to commit the error page. This will be committed
  // to the RenderFrameHost previously chosen in OnRequestFailedInternal().
  PrepareToCommitErrorPage(result.error_page_content());
  // DO NOT ADD CODE after this. The previous call may have caused the
  // destruction of the NavigationRequest.
}

void NavigationRequest::OnWillProcessResponseChecksComplete(
    NavigationThrottle::ThrottleCheckResult result) {
  DCHECK(result.action() != NavigationThrottle::DEFER);

  // If the NavigationThrottles allowed the navigation to continue, have the
  // processing of the response resume in the network stack.
  if (result.action() == NavigationThrottle::PROCEED) {
    // If this is a download and NavigationThrottles allowed it, intercept the
    // navigation response, pass it to DownloadManager, and cancel the
    // navigation.
    if (is_download_) {
      // TODO(arthursonzogni): Pass the real ResourceRequest. For the moment
      // only these parameters will be used, but it may evolve quickly.
      auto resource_request = std::make_unique<network::ResourceRequest>();
      resource_request->url = common_params_->url;
      resource_request->method = common_params_->method;
      resource_request->request_initiator = common_params_->initiator_origin;
      resource_request->referrer = common_params_->referrer->url;
      resource_request->has_user_gesture = common_params_->has_user_gesture;
      resource_request->mode = network::mojom::RequestMode::kNavigate;
      resource_request->transition_type = common_params_->transition;
      resource_request->trusted_params =
          network::ResourceRequest::TrustedParams();
      resource_request->trusted_params->isolation_info = GetIsolationInfo();

      BrowserContext* browser_context =
          frame_tree_node_->navigator().controller().GetBrowserContext();
      DownloadManagerImpl* download_manager = static_cast<DownloadManagerImpl*>(
          browser_context->GetDownloadManager());
      if (!response_head_->client_side_content_decoding_types.empty()) {
        CHECK(base::FeatureList::IsEnabled(
            network::features::kRendererSideContentDecoding));
        // If content decoding is required, perform the decoding in the network
        // service.

        // Attempt to create the data pipe needed for content decoding.
        auto data_pipe_pair =
            network::ContentDecodingInterceptor::CreateDataPipePair(
                network::ContentDecodingInterceptor::ClientType::kDownload);
        if (!data_pipe_pair) {
          // Handle data pipe creation failure. This is rare but can happen if
          // shared memory is exhausted. In such a situation, the page load will
          // likely fail anyway as resources cannot be properly loaded. However,
          // we should avoid crashing the browser process or attempting to
          // download the raw encoded body. Instead, just abort the navigation
          // request.
          auto completion_status =
              network::URLLoaderCompletionStatus(net::ERR_ABORTED);
          error_navigation_trigger_ =
              ErrorNavigationTrigger::kContentDecoderDataPipeCreationFailed;
          OnRequestFailedInternal(completion_status,
                                  /*skip_throttles=*/false,
                                  /*error_page_content=*/std::nullopt,
                                  /*collapse_frame=*/false);
          // DO NOT ADD CODE after this. The previous call to
          // OnRequestFailedInternal has destroyed the NavigationRequest.
          return;
        }
        network::ContentDecodingInterceptor::InterceptOnNetworkService(
            *GetNetworkService(),
            response_head_->client_side_content_decoding_types,
            url_loader_client_endpoints_, response_body_,
            std::move(*data_pipe_pair));
      }
      download_manager->InterceptNavigation(
          std::move(resource_request), redirect_chain_, response_head_.Clone(),
          std::move(response_body_), std::move(url_loader_client_endpoints_),
          ssl_info_.has_value() ? ssl_info_->cert_status : 0,
          frame_tree_node_->frame_tree_node_id(),
          from_download_cross_origin_redirect_);

      auto completion_status =
          network::URLLoaderCompletionStatus(net::ERR_ABORTED);
      error_navigation_trigger_ =
          ErrorNavigationTrigger::kShouldNotRenderResponse;
      OnRequestFailedInternal(completion_status, false /*skip_throttles*/,
                              std::nullopt /*error_page_content*/,
                              false /*collapse_frame*/);
      // DO NOT ADD CODE after this. The previous call to OnRequestFailed has
      // destroyed the NavigationRequest.
      return;
    }

    // Per https://whatwg.org/C/iframe-embed-object.html#the-object-element,
    // this implements step 4.7 from "determine what the object element
    // represents": "If the load failed (e.g. there was an HTTP 404 error, there
    // was a DNS error), fire an event named error at the element, then jump to
    // the step below labeled fallback."
    //
    // This case handles HTTP errors, which are otherwise considered a
    // "successful" navigation.
    //
    // TODO(dcheng): According to the standard, an <object> element shouldn't
    // even have a browsing context associated with it unless a successful
    // navigation would commit in it.
    if (response()->headers &&
        ShouldRenderFallbackContentForResponse(*response()->headers)) {
      // Spin up a helper to drain the response body for this navigation. The
      // helper will request fallback content (triggering completion) and report
      // the resource timing info once the entire response body is drained.
      //
      // The response body fetcher takes advantage of base::SupportsUserData to
      // ensure that the fetcher does not outlive `this`. This ensures that the
      // fallback / resource timing are only reported if the navigation request
      // is logically still pending.
      auto completion_status =
          network::URLLoaderCompletionStatus(net::ERR_ABORTED);
      error_navigation_trigger_ =
          ErrorNavigationTrigger::kShouldRenderFallbackContent;
      ObjectNavigationFallbackBodyLoader::CreateAndStart(
          *this, std::move(response_body_),
          std::move(url_loader_client_endpoints_),
          base::BindOnce(&NavigationRequest::OnRequestFailedInternal,
                         weak_factory_.GetWeakPtr(), completion_status,
                         false /* skip_throttles */,
                         std::nullopt /* error_page_content */,
                         false /* collapse_frame */));
      // Unlike the other early returns, intentionally skip calling
      // `OnRequestFailedInternal()`. This allows the response body drainer to
      // track the lifetime of `this` and skip the remaining work if `this` is
      // deleted before the response body is completely loaded.
      return;
    }
  }

  // Abort the request if needed. This includes requests that were blocked by
  // NavigationThrottles and requests that should not commit (e.g. downloads,
  // 204/205s). This will destroy the NavigationRequest.
  if (result.action() == NavigationThrottle::CANCEL_AND_IGNORE ||
      result.action() == NavigationThrottle::CANCEL ||
      !response_should_be_rendered_) {
    MaybeAddResourceTimingEntryForCancelledNavigation();

    // TODO(clamy): distinguish between CANCEL and CANCEL_AND_IGNORE.
    if (!response_should_be_rendered_) {
      auto completion_status =
          network::URLLoaderCompletionStatus(net::ERR_ABORTED);
      error_navigation_trigger_ =
          ErrorNavigationTrigger::kShouldNotRenderResponse;
      OnRequestFailedInternal(completion_status, true /* skip_throttles */,
                              std::nullopt /* error_page_content */,
                              false /* collapse_frame */);

      // DO NOT ADD CODE after this. The previous call to
      // OnRequestFailedInternal has destroyed the NavigationRequest.
      return;
    }

    DCHECK(result.action() == NavigationThrottle::CANCEL ||
           result.net_error_code() == net::ERR_ABORTED);
    auto completion_status =
        network::URLLoaderCompletionStatus(result.net_error_code());
    error_navigation_trigger_ =
        ErrorNavigationTrigger::kNavigationThrottleCancel;
    OnRequestFailedInternal(completion_status, true /* skip_throttles */,
                            result.error_page_content(),
                            false /* collapse_frame */);

    // DO NOT ADD CODE after this. The previous call to OnRequestFailedInternal
    // has destroyed the NavigationRequest.
    return;
  }

  if (result.action() == NavigationThrottle::BLOCK_RESPONSE) {
    DCHECK_EQ(net::ERR_BLOCKED_BY_RESPONSE, result.net_error_code());
    OnRequestFailedInternal(
        network::URLLoaderCompletionStatus(result.net_error_code()),
        true /* skip_throttles */, result.error_page_content(),
        false /* collapse_frame */);
    // DO NOT ADD CODE after this. The previous call to OnRequestFailedInternal
    // has destroyed the NavigationRequest.
    return;
  }

  DCHECK_EQ(result.action(), NavigationThrottle::PROCEED);

  // When this request is for prerender activation, `commit_deferrer_` has
  // already been processed.
  if (IsPrerenderedPageActivation()) {
    DCHECK(!commit_deferrer_);
    CommitNavigation();
    // DO NOT ADD CODE after this. The previous call to CommitNavigation
    // destroyed the NavigationRequest.
    return;
  }

  RunCommitDeferringConditions(base::BindOnce(
      &NavigationRequest::CommitNavigation, weak_factory_.GetWeakPtr()));
  // DO NOT ADD CODE after this. The previous call to
  // RunCommitDeferringConditions may have caused the destruction of the
  // NavigationRequest.
}

void NavigationRequest::OnWillCommitWithoutUrlLoaderChecksComplete(
    NavigationThrottle::ThrottleCheckResult result) {
  DCHECK(result.action() == NavigationThrottle::CANCEL_AND_IGNORE ||
         result.action() == NavigationThrottle::PROCEED);
  if (result.action() == NavigationThrottle::CANCEL_AND_IGNORE) {
    OnRequestFailedInternal(
        network::URLLoaderCompletionStatus(result.net_error_code()),
        /*skip_throttles=*/true, result.error_page_content(),
        /*collapse_frame=*/false);

    // DO NOT ADD CODE after this. The previous call to OnRequestFailedInternal
    // has destroyed the NavigationRequest.
    return;
  }

  // Ensure that bfcache and other non-UrlLoader history navigations can
  // dispatch the Navigation API's navigate event as the navigation is starting.
  // Cases with a UrlLoader are handled in OnStartChecksComplete.
  MaybeDispatchNavigateEventForCrossDocumentTraversal();

  InheritServiceWorkerControllerFromParentIfNeeded();

  CommitNavigation();
}

void NavigationRequest::InheritServiceWorkerControllerFromParentIfNeeded() {
  CHECK(!loader_);
  CHECK(!service_worker_handle_);
  RenderFrameHostImpl* parent = frame_tree_node()->parent();
  if (!parent || !GetURL().IsAboutSrcdoc()) {
    return;
  }
  base::WeakPtr<ServiceWorkerClient> parent_service_worker_client =
      parent->GetLastCommittedServiceWorkerClient();
  if (!parent_service_worker_client) {
    return;
  }

  if ((frame_tree_node_->pending_frame_policy().sandbox_flags &
       network::mojom::WebSandboxFlags::kOrigin) ==
      network::mojom::WebSandboxFlags::kOrigin) {
    return;
  }
  GetContentClient()->browser()->LogWebFeatureForCurrentPage(
      frame_tree_node_->current_frame_host(),
      blink::mojom::WebFeature::kAboutSrcdocToBeControlledByServiceWorker);
  if (!base::FeatureList::IsEnabled(features::kServiceWorkerSrcdocSupport) ||
      !GetContentClient()->browser()->AllowServiceWorkerToControlSrcdocIframe(
          frame_tree_node_->navigator().controller().GetBrowserContext())) {
    return;
  }

  StoragePartition* partition = GetStoragePartitionWithCurrentSiteInfo();
  auto* service_worker_context = static_cast<ServiceWorkerContextWrapper*>(
      partition->GetServiceWorkerContext());
  // As ServiceWorkerMainResourceHandle is not used for intercepting the srcdoc
  // iframe main resource, the fetch event client id is not used. Use empty
  // string as fetch_event_client_id when creating it.
  service_worker_handle_ = std::make_unique<ServiceWorkerMainResourceHandle>(
      service_worker_context, base::DoNothing(),
      /*fetch_event_client_id=*/std::string(), parent_service_worker_client);
  service_worker_handle_->set_service_worker_client(
      service_worker_context->context()
          ->service_worker_client_owner()
          .CreateServiceWorkerClientForWindow(
              frame_tree_node_->AreAncestorsSecure(),
              frame_tree_node_->frame_tree_node_id()),
      GetIsolationInfo());
  service_worker_handle_->service_worker_client()->InheritControllerFrom(
      *parent_service_worker_client, net::SimplifyUrlForRequest(GetURL()));
}

void NavigationRequest::RunCommitDeferringConditions(
    base::OnceClosure on_commit_deferring_conditions_complete_callback) {
  CHECK(!commit_deferring_conditions_complete_closure_);
  commit_deferring_conditions_complete_closure_ =
      std::move(on_commit_deferring_conditions_complete_callback);
  commit_deferrer_->RegisterDeferringConditions(*this);
  commit_deferrer_->ProcessChecks();
  // DO NOT ADD CODE after this. The previous call to ProcessChecks may have
  // caused the destruction of the NavigationRequest.
}

void NavigationRequest::OnCommitDeferringConditionChecksComplete(
    CommitDeferringCondition::NavigationType navigation_type,
    std::optional<FrameTreeNodeId> candidate_prerender_frame_tree_node_id) {
  // CommitDeferringConditions could have been triggered for prerender
  // activation, a normal navigation commit or an error page commit.
  // Running this closure will continue the commit on the appropriate path.
  CHECK(commit_deferring_conditions_complete_closure_);
  std::move(commit_deferring_conditions_complete_closure_).Run();
  // DO NOT ADD CODE after this. The previous call could cause the
  // destruction of the NavigationRequest.
}

void NavigationRequest::PrepareToCommitErrorPage(
    const std::optional<std::string>& error_page_content) {
  RunCommitDeferringConditions(
      base::BindOnce(&NavigationRequest::CommitErrorPage,
                     weak_factory_.GetWeakPtr(), error_page_content));
  //  DO NOT ADD CODE after this. The previous call may have caused the
  //  destruction of the NavigationRequest.
}

void NavigationRequest::CommitErrorPage(
    const std::optional<std::string>& error_page_content) {
  DCHECK(!IsSameDocument());

  DetermineOriginAgentClusterEndResult();

  UpdateHistoryParamsInCommitNavigationParams();

  common_params_->should_replace_current_entry =
      ShouldReplaceCurrentEntryForFailedNavigation();

  // Don't pass the base url in a failed navigation.
  common_params_->initiator_base_url = std::nullopt;

  ReuseRequestNavigationClientForCommitIfNeeded();

  topics_eligible_ = false;

  ad_auction_headers_eligible_ = false;

  base::WeakPtr<NavigationRequest> weak_self(weak_factory_.GetWeakPtr());
  ReadyToCommitNavigation(true /* is_error */);
  // The caller above might result in the deletion of `this`. Return immediately
  // if so.
  if (!weak_self) {
    return;
  }

  // Ensure the renderer does not reuse the document sequence number for
  // cross-origin navigations (which can lead to later bugs with same-document
  // navigations appearing to be cross-origin). All error pages have unique
  // opaque origins and are considered cross-origin.
  //
  // The one exception is for transitioning to or from a compatible error page,
  // which preserves state in case a temporary failure later succeeds. Here, we
  // must check for any cases where the committing error page has a valid
  // precursor that agrees with the current document, whether the current
  // document is already an error page or not. (The renderer process will narrow
  // DSN reuse further, to cases the URL is a closer match, ignoring fragments.)
  // See also CommitNavigation for the other direction.
  // TODO(crbug.com/396645697): Use a different technique for preserving history
  // item state on error pages, separate from the error page's own state.
  RenderFrameHostImpl* previous_rfh = frame_tree_node()->current_frame_host();
  const url::Origin& previous_origin = previous_rfh->GetLastCommittedOrigin();
  bool is_error_page_with_same_precursor =
      previous_origin.GetTupleOrPrecursorTupleIfOpaque().IsValid() &&
      commit_params_->origin_to_commit.GetTupleOrPrecursorTupleIfOpaque() ==
          previous_origin.GetTupleOrPrecursorTupleIfOpaque();
  if (!is_error_page_with_same_precursor) {
    commit_params_->force_new_document_sequence_number = true;
  }

  // If the outermost main frame is performing an error navigation, capture the
  // state of fenced frames rendered in the viewport before the entire FrameTree
  // is torn down. We have to do this now, because the renderer will change the
  // visibility of its frames after receiving the commit.
  if (previous_rfh->IsOutermostMainFrame() && !IsSameDocument()) {
    auto* monitor =
        PageUserData<FencedFrameViewportMonitor>::GetOrCreateForPage(
            previous_rfh->GetPage());
    if (monitor) {
      monitor->ComputeSameSiteFencedFrameMaximumBeforePrimaryPageChange();
    }
  }

  PopulateDocumentTokenForCrossDocumentNavigation();
  // Use a separate cache shard, and no cookies, for error pages.
  isolation_info_for_subresources_ =
      net::IsolationInfo::CreateTransient(/*nonce=*/std::nullopt);
  GetRenderFrameHost()->FailedNavigation(
      this, *common_params_, *commit_params_, has_stale_copy_in_cache_,
      net_error_, extended_error_code_, error_page_content, *document_token_);
  UpdateNavigationHandleTimingsOnCommitSent();

  SendDeferredConsoleMessages();
}

void NavigationRequest::AddOldPageInfoToCommitParamsIfNeeded() {
  // Add the routing ID and the updated lifecycle state of the old page if we
  // need to run pagehide and visibilitychange handlers of the old page
  // when we commit the new page.
  auto* old_frame_host =
      frame_tree_node_->render_manager()->current_frame_host();
  if (!GetRenderFrameHost()
           ->ShouldDispatchPagehideAndVisibilitychangeDuringCommit(
               old_frame_host, GetUrlInfo())) {
    return;
  }
  DCHECK(!IsSameDocument());
  // The pagehide event's "persisted" property depends on whether the old page
  // will be put into the back-forward cache or not. As we won't freeze the
  // page until after the commit finished, there is no way to know for sure
  // whether the page will actually be persisted or not after commit, but we
  // will send our best guess by checking if the page can be persisted at this
  // point.
  bool can_store_old_page_in_bfcache =
      frame_tree_node_->frame_tree()
          .controller()
          .GetBackForwardCache()
          .GetFutureBackForwardCacheEligibilityPotential(old_frame_host)
          .CanStore();
  commit_params_->old_page_info = blink::mojom::OldPageInfo::New();
  commit_params_->old_page_info->frame_token_for_old_main_frame =
      old_frame_host->GetFrameToken();
  auto* page_lifecycle_state_manager =
      old_frame_host->render_view_host()->GetPageLifecycleStateManager();
  commit_params_->old_page_info->new_lifecycle_state_for_old_page =
      page_lifecycle_state_manager->SetPagehideDispatchDuringNewPageCommit(
          can_store_old_page_in_bfcache /* persisted */);
}

bool NavigationRequest::ShouldDispatchPageSwapEvent() const {
  if (early_render_frame_host_swap_type_ !=
      EarlyRenderFrameHostSwapType::kNone) {
    return false;
  }

  if (IsSameDocument()) {
    return false;
  }

  return !did_fire_page_swap_;
}

void NavigationRequest::CommitNavigation() {
  TRACE_EVENT("navigation", "NavigationRequest::CommitNavigation",
              perfetto::Flow::FromPointer(this));
  // A navigation request should only commit once the response has been
  // processed.
  DCHECK_GE(state_, WILL_PROCESS_RESPONSE);
  // If a WebUI was created for this navigation, it must have been moved to the
  // RenderFrameHost we're about to commit in already.
  CHECK(!HasWebUI());
  CheckSoftNavigationHeuristicsInvariants();

  CoopCoepSanityCheck();

  DetermineOriginAgentClusterEndResult();

  UpdateHistoryParamsInCommitNavigationParams();
  DCHECK(NeedsUrlLoader() == !!response_head_ ||
         (was_redirected_ && common_params_->url.IsAboutBlank()));
  DCHECK(!common_params_->url.SchemeIs(url::kJavaScriptScheme));
  DCHECK(!blink::IsRendererDebugURL(common_params_->url));

  AddOldPageInfoToCommitParamsIfNeeded();
  if (ShouldDispatchPageSwapEvent()) {
    frame_tree_node_->current_frame_host()
        ->GetAssociatedLocalFrame()
        ->DispatchPageSwap(WillDispatchPageSwap());
  }

  url::Origin origin_to_commit = GetOriginToCommit().value();
  if (base::FeatureList::IsEnabled(features::kValidateCommitOriginAtCommit)) {
    ValidateCommitOrigin(origin_to_commit);
  }
  isolation_info_for_subresources_ =
      GetRenderFrameHost()->ComputeIsolationInfoForSubresourcesForPendingCommit(
          origin_to_commit, is_credentialless(), ComputeFencedFrameNonce());
  DCHECK(!isolation_info_for_subresources_.IsEmpty());

  // If this is a srcdoc document, the content comes from the parent frame, so
  // the origin must be the parent and not the initiator. In this case, do not
  // inherit the base URI from the initiator if the origins do not agree
  // (accounting for the case that the chosen origin might be opaque with a
  // precursor of the parent's origin, in a sandboxed case). There should also
  // not be an initiator base URL if there is no initiator origin, such as in a
  // browser-initiated navigation.
  if (GetURL().IsAboutSrcdoc() &&
      (!common_params().initiator_origin ||
       origin_to_commit.GetTupleOrPrecursorTupleIfOpaque() !=
           common_params()
               .initiator_origin->GetTupleOrPrecursorTupleIfOpaque())) {
    // TODO(crbug.com/40165505): Make this unreachable by blocking
    // cross-origin about:srcdoc navigations. Then enforce that the chosen
    // origin for srcdoc cases agrees with the parent frame's origin.
    common_params_->initiator_base_url = std::nullopt;
  }

  // TODO(crbug.com/40092527): The storage key's origin is ignored at the
  // moment. We will be able to use it once the browser can compute the origin
  // to commit.
  std::optional<base::UnguessableToken> nonce =
      GetRenderFrameHost()->ComputeNonce(is_credentialless(),
                                         ComputeFencedFrameNonce());

  commit_params_->storage_key = GetRenderFrameHost()->CalculateStorageKey(
      origin_to_commit, base::OptionalToPtr(nonce));

  if (topics_eligible_) {
    topics_eligible_ = false;

    if (response()) {
      HandleTopicsEligibleResponse(
          response_head_->parsed_headers, url::Origin::Create(GetURL()),
          *GetRenderFrameHost(),
          browsing_topics::ApiCallerSource::kIframeAttribute);
    }
  }

  if (ad_auction_headers_eligible_) {
    ProcessAdAuctionResponseHeaders(origin_to_commit, *GetRenderFrameHost(),
                                    response() ? response()->headers : nullptr);
  } else if (has_ad_auction_headers_attribute_) {
    RemoveAdAuctionResponseHeaders(response() ? response()->headers : nullptr);
  }

  RenderFrameHostImpl* old_frame_host =
      frame_tree_node_->render_manager()->current_frame_host();
  if (!NavigationTypeUtils::IsSameDocument(common_params_->navigation_type)) {
    // We want to record this for the frame that we are navigating away from.
    old_frame_host->RecordNavigationSuddenTerminationHandlers();
  }

  // If the outermost main frame is being navigated, capture the state of fenced
  // frames rendered in the viewport before the entire FrameTree is torn down.
  // We have to do this now, because the renderer will change the visibility of
  // its frames after receiving the commit.
  if (old_frame_host->IsOutermostMainFrame() && !IsSameDocument()) {
    auto* monitor =
        PageUserData<FencedFrameViewportMonitor>::GetOrCreateForPage(
            old_frame_host->GetPage());
    if (monitor) {
      monitor->ComputeSameSiteFencedFrameMaximumBeforePrimaryPageChange();
    }
  }

  if (IsServedFromBackForwardCache() || IsPrerenderedPageActivation()) {
    CommitPageActivation();
    return;
  }

  // For consistency, prerendering activation *should* go through this as well.
  // However, the prerender implementation based on swapping WebContents
  // introduces a number of edge cases that navigation code wouldn't normally
  // have to handle, so it's easier to simply skip this in the hopes that the
  // non-mparch implementation will be removed soon.
  base::WeakPtr<NavigationRequest> weak_self(weak_factory_.GetWeakPtr());
  ReadyToCommitNavigation(false /* is_error */);
  // The call above might block on showing a user dialog. The interaction of
  // the user with this dialog might result in the WebContents owning this
  // NavigationRequest to be destroyed. Return if this is the case.
  if (!weak_self)
    return;

  DCHECK(GetRenderFrameHost() == old_frame_host ||
         GetRenderFrameHost() ==
             frame_tree_node_->render_manager()->speculative_frame_host());

  ReuseRequestNavigationClientForCommitIfNeeded();

  CreateCoepReporter(GetRenderFrameHost()->GetProcess()->GetStoragePartition());
  coop_status_.UpdateReporterStoragePartition(
      GetRenderFrameHost()->GetProcess()->GetStoragePartition());
  CreateDipReporter(GetRenderFrameHost()->GetProcess()->GetStoragePartition());

  BrowserContext* browser_context =
      frame_tree_node_->navigator().controller().GetBrowserContext();
  ClientHintsControllerDelegate* client_hints_delegate =
      browser_context->GetClientHintsControllerDelegate();
  if (client_hints_delegate) {
    std::optional<std::vector<network::mojom::WebClientHintsType>>
        opt_in_hints_from_response;
    if (response()) {
      opt_in_hints_from_response = ParseAndPersistAcceptCHForNavigation(
          url::Origin::Create(common_params_->url), response()->parsed_headers,
          response()->headers.get(), browser_context, client_hints_delegate,
          frame_tree_node_);
    }
    commit_params_->enabled_client_hints =
        LookupAcceptCHForCommit(origin_to_commit, client_hints_delegate,
                                frame_tree_node_, common_params_->url);
  }
  // Navigation requests should use the new origin as the partition origin
  // except if embedded in an outer frame.
  url::Origin partition_origin = origin_to_commit;
  bool is_top_level = frame_tree_node()->GetParentOrOuterDocument() == nullptr;
  if (!is_top_level) {
    partition_origin = frame_tree_node()
                           ->GetParentOrOuterDocument()
                           ->GetOutermostMainFrame()
                           ->GetLastCommittedOrigin();
  }

  PersistOriginTrialsFromHeaders(origin_to_commit, partition_origin, response(),
                                 browser_context, GetNextPageUkmSourceId());

  // Clean the reduced accept-language to commit if the final response have a
  // valid deprecation origin trial token.
  if (auto reduce_accept_lang_utils =
          ReduceAcceptLanguageUtils::Create(browser_context);
      reduce_accept_lang_utils && !devtools_accept_language_override_ &&
      ReduceAcceptLanguageUtils::CheckDisableReduceAcceptLanguageOriginTrial(
          common_params_->url, frame_tree_node_,
          browser_context->GetOriginTrialsControllerDelegate()) &&
      !commit_params_->reduced_accept_language.empty()) {
    reduce_accept_lang_utils.value().RemoveReducedAcceptLanguage(
        origin_to_commit, frame_tree_node_);
    commit_params_->reduced_accept_language = "";
  }

  // Sticky user activation should only be preserved for same-site subframe
  // navigations, and same-origin top-frame navigations behind the feature flag
  // StickyUserActivationAcrossSameOriginNavigation. These checks limit newly
  // navigated documents from reusing the sticky user activation state from the
  // previously navigated document in the frame.
  //
  // - We persist user activation across same-site navigations for compatibility
  //   reasons, and this does not need to match the same-site checks used in the
  //   process model. See https://crbug.com/40527366.
  //
  //   TODO(crbug.com/40228985): Remove this once we find a way to reset
  //   activation unconditionally without breaking sites in practice.
  //
  // - The feature flag StickyUserActivationAcrossSameOriginNavigation relaxes
  //   the preservation of sticky activation to include same-origin navigations
  //   to ease multi-page app development which currently face problem with, for
  //   example, virtual keyboards.  See https://crbug.com/433729626.
  commit_params_->should_have_sticky_user_activation =
      old_frame_host->HasStickyUserActivation() &&
      ((!frame_tree_node_->IsMainFrame() &&
        net::SchemefulSite::IsSameSite(old_frame_host->GetLastCommittedOrigin(),
                                       origin_to_commit)) ||
       (base::FeatureList::IsEnabled(
            blink::features::kStickyUserActivationAcrossSameOriginNavigation) &&
        !commit_params_->is_browser_initiated &&
        frame_tree_node_->IsMainFrame() &&
        old_frame_host->GetLastCommittedOrigin() == origin_to_commit));

  // Generate a UKM source and track it on NavigationRequest. This will be
  // passed down to the blink::Document to be created, if any, and used for UKM
  // source creation when navigation has successfully committed.
  commit_params_->document_ukm_source_id = ukm::UkmRecorder::GetNewSourceID();

  blink::mojom::ServiceWorkerContainerInfoForClientPtr
      service_worker_container_info;
  blink::mojom::ControllerServiceWorkerInfoPtr controller;

  // Notify the service worker navigation handle that navigation commit is
  // about to go.
  if (service_worker_handle_ &&
      service_worker_handle_->service_worker_client()) {
    DCHECK(coep_reporter());
    DCHECK(dip_reporter());
    mojo::PendingRemote<network::mojom::CrossOriginEmbedderPolicyReporter>
        coep_reporter_remote;
    coep_reporter()->Clone(
        coep_reporter_remote.InitWithNewPipeAndPassReceiver());

    mojo::PendingRemote<network::mojom::DocumentIsolationPolicyReporter>
        dip_reporter_remote;
    dip_reporter()->Clone(dip_reporter_remote.InitWithNewPipeAndPassReceiver());

    std::tie(service_worker_container_info, controller) =
        service_worker_handle_->scoped_service_worker_client()
            ->CommitResponseAndRelease(
                GetRenderFrameHost()->GetGlobalId(),
                policy_container_builder_->FinalPolicies(),
                std::move(coep_reporter_remote), std::move(dip_reporter_remote),
                commit_params_->document_ukm_source_id);
  }

  // Determine if top-level navigation is allowed without sticky user
  // activation. This is used to fix the exploit in https://crbug.com/1251790.
  // If a child document is cross-origin with its parent, it loses its ability
  // to navigate top without user gesture. One notable exception is made if its
  // parent embeds it using sandbox="allow-top-navigation". Please note this is
  // quite unusual, because it means using sandbox brings new capabilities, as
  // opposed to new restrictions.
  using WebSandboxFlags = network::mojom::WebSandboxFlags;
  const bool embedder_allows_top_navigation_explicitly =
      ((commit_params_->frame_policy.sandbox_flags != WebSandboxFlags::kNone) &&
       (commit_params_->frame_policy.sandbox_flags &
        WebSandboxFlags::kTopNavigation) == WebSandboxFlags::kNone);
  const bool is_same_origin_to_top =
      origin_to_commit ==
      GetRenderFrameHost()->GetMainFrame()->GetLastCommittedOrigin();
  if (is_same_origin_to_top) {
    policy_container_builder_->SetAllowTopNavigationWithoutUserGesture(true);
  } else if (!IsInMainFrame() && !embedder_allows_top_navigation_explicitly) {
    policy_container_builder_->SetAllowTopNavigationWithoutUserGesture(false);
  }

  if (!IsSameDocument()) {
    commit_params_->navigation_api_history_entry_arrays =
        GetNavigationController()->GetNavigationApiHistoryEntryVectors(
            frame_tree_node_, this);
    PopulateDocumentTokenForCrossDocumentNavigation();

    // Ensure the renderer does not reuse the document sequence number for
    // cross-origin navigations (which can lead to later bugs with same-document
    // navigations appearing to be cross-origin).
    //
    // The one exception is for transitioning to or from a compatible error
    // page, which preserves state in case a temporary failure later succeeds.
    // Here, we must check for the case that the user navigates from an error
    // page to a non-error page that matches the (valid) precursor origin. See
    // also CommitErrorPage for the other direction.
    // TODO(crbug.com/396645697): Use a different technique for preserving
    // history item state on error pages, separate from the error page's own
    // state.
    RenderFrameHostImpl* previous_rfh = frame_tree_node()->current_frame_host();
    const url::Origin& previous_origin = previous_rfh->GetLastCommittedOrigin();
    bool is_cross_origin_navigation =
        !commit_params_->origin_to_commit.IsSameOriginWith(previous_origin);
    bool compatible_with_error_page =
        previous_rfh->IsErrorDocument() &&
        previous_origin.GetTupleOrPrecursorTupleIfOpaque().IsValid() &&
        commit_params_->origin_to_commit.GetTupleOrPrecursorTupleIfOpaque() ==
            previous_origin.GetTupleOrPrecursorTupleIfOpaque();
    if (is_cross_origin_navigation && !compatible_with_error_page) {
      commit_params_->force_new_document_sequence_number = true;
    }
  }

  if (early_hints_manager_) {
    commit_params_->early_hints_preloaded_resources =
        early_hints_manager_->TakePreloadedResourceURLs();
  }

  if (response_head_) {
    commit_params_->navigation_delivery_type =
        response_head_->navigation_delivery_type;
  }

  // Add our map of modified blink runtime-enabled features to
  // the commit params so they can be communicated to the renderer process.
  commit_params_->modified_runtime_features =
      runtime_feature_state_context_.GetFeatureOverrides();

  // Documents loaded from fenced frame configs can opt into allowing
  // cross-origin subframes to use their reporting metadata to send
  // `reportEvent()` beacons. The cross-origin subframes still require a
  // separate per-report opt-in.
  if (fenced_frame_properties_.has_value() && response_head_ &&
      response_head_->parsed_headers->allow_cross_origin_event_reporting) {
    fenced_frame_properties_->SetAllowCrossOriginEventReporting();
  }

  if (base::FeatureList::IsEnabled(
          blink::features::kFencedFramesSrcPermissionsPolicy)) {
    std::optional<url::Origin> mapped_origin;
    if (fenced_frame_properties_.has_value()) {
      mapped_origin = url::Origin::Create(
          fenced_frame_properties_->mapped_url()->GetValueIgnoringVisibility());
    } else if (frame_tree_node_->HasFencedFrameProperties() &&
               frame_tree_node_->GetFencedFrameProperties()->mapped_url()) {
      mapped_origin =
          url::Origin::Create(frame_tree_node_->GetFencedFrameProperties()
                                  ->mapped_url()
                                  ->GetValueIgnoringVisibility());
    }

    // Container policy allowlists are first calculated by the embedder where
    // origin of the fenced frame is opaque. Now that the mapped URL is known,
    // update the container policy allowlists so that any allowlist with
    // "matches_opaque_src=true" points to the final mapped origin. This will be
    // the container policy that is sent to the inner root to construct the
    // final permissions policy.
    if (mapped_origin.has_value()) {
      for (auto& declaration : commit_params_->frame_policy.container_policy) {
        if (declaration.matches_opaque_src) {
          CHECK(!declaration.self_if_matches.has_value());
          declaration.matches_opaque_src = false;
          declaration.self_if_matches = mapped_origin.value();
        }
      }
    }
  }

  // Create a view of the fenced frame properties from the perspective of the
  // fenced frame content, which will be sent to its renderer.
  // On each navigation commit within the fenced frame tree:
  // * If the properties have no mapped url, the browser will send the renderer
  //   the `RedactedFencedFrameProperties` unconditionally.
  // * If the properties do have a mapped url, the browser will send the
  //   renderer the `RedactedFencedFrameProperties`, redacting extra information
  //   based on whether the origin is same-origin to the urn's mapped_url (after
  //   redirects).
  // This is because we want to make fenced frame APIs available only
  // in same-origin contexts, when "same-origin" has a coherent definition.
  const auto& computed_fenced_frame_properties = ComputeFencedFrameProperties();
  if (computed_fenced_frame_properties.has_value()) {
    content::FencedFrameEntity entity =
        content::FencedFrameEntity::kSameOriginContent;
    if (computed_fenced_frame_properties->mapped_url().has_value() &&
        !origin_to_commit.IsSameOriginWith(
            computed_fenced_frame_properties->mapped_url()
                ->GetValueIgnoringVisibility())) {
      entity = content::FencedFrameEntity::kCrossOriginContent;
    }
    commit_params_->fenced_frame_properties =
        computed_fenced_frame_properties->RedactFor(entity);
  }

  commit_params_->load_with_storage_access = ShouldLoadWithStorageAccess(
      begin_params(), common_params(), frame_tree_node()->current_frame_host(),
      did_encounter_cross_origin_redirect(), GetURL(), response());

  auto common_params = common_params_->Clone();
  auto commit_params = commit_params_.Clone();
  auto response_head = response_head_.Clone();
  if (!subresource_loader_params_.prefetched_signed_exchanges.empty()) {
    commit_params->prefetched_signed_exchanges =
        std::move(subresource_loader_params_.prefetched_signed_exchanges);
  }

  // TODO(https://crbug.com/40095391): Convert to CHECK if it proves to be
  // consistently upheld condition.
  DUMP_WILL_BE_CHECK(commit_params->redirect_response.size() ==
                     commit_params->redirect_infos.size());
  // Before sending the commit parameters to the renderer process, sanitize
  // the redirect URLs to avoid leaking potentially sensitive data into
  // processes which are cross-site. There is no dependency on the
  // cross-site-ness, therefore just sanitize unilaterally.
  SanitizeRedirectsForCommit(commit_params);

  GetRenderFrameHost()->CommitNavigation(
      this, std::move(common_params), std::move(commit_params),
      std::move(response_head), std::move(response_body_),
      std::move(url_loader_client_endpoints_), std::move(controller),
      std::move(subresource_overrides_),
      std::move(service_worker_container_info), document_token_,
      devtools_navigation_token_);
  if (service_worker_handle_ &&
      service_worker_handle_->service_worker_client()) {
    service_worker_handle_->service_worker_client()->SetContainerReady();
  }

  if (base::FeatureList::IsEnabled(
          net::features::kUpdateIsMainFrameOriginRecentlyAccessed) &&
      IsInMainFrame()) {
    URLLoaderFactoryParamsHelper::OnMainFrameNavigation(origin_to_commit);
  }
  UpdateNavigationHandleTimingsOnCommitSent();

  // Give SpareRenderProcessHostManager a heads-up about the most recently used
  // BrowserContext.  This is mostly needed to make sure the spare is warmed-up
  // if it wasn't done in RenderProcessHostImpl::GetProcessHostForSiteInstance.
  RenderProcessHostImpl::NotifySpareManagerAboutRecentlyUsedSiteInstance(
      GetRenderFrameHost()->GetSiteInstance());

  SendDeferredConsoleMessages();
}

void NavigationRequest::CommitPageActivation() {
  TRACE_EVENT("navigation", "NavigationRequest::CommitPageActivation",
              perfetto::Flow::FromPointer(this));
  // An activation is either for the back-forward cache or prerendering. They
  // are mutually exclusive.
  DCHECK_NE(IsServedFromBackForwardCache(), IsPrerenderedPageActivation());

  NavigationControllerImpl* controller = GetNavigationController();

  if (IsServedFromBackForwardCache()) {
    std::unique_ptr<BackForwardCacheImpl::Entry> activated_entry;
    // Navigations served from the back-forward cache must be a history
    // navigation, and thus should have a valid |pending_history_list_index|
    // value. We will pass that value and the |current_history_list_length|
    // value to update the history index and length information saved in the
    // renderer, which might be stale.
    DCHECK_GE(commit_params_->pending_history_list_index, 0);

    auto page_restore_params = blink::mojom::PageRestoreParams::New();
    page_restore_params->navigation_start = NavigationStart();
    page_restore_params->pending_history_list_index =
        commit_params_->pending_history_list_index;
    page_restore_params->current_history_list_length =
        commit_params_->current_history_list_length;
    activated_entry = controller->GetBackForwardCache().RestoreEntry(
        nav_entry_id_, std::move(page_restore_params));
    CHECK(activated_entry);

    // Restore navigation API entries, since they will probably have changed
    // since the page entered bfcache. We must update all frames, not just the
    // top frame, because it is possible (though unlikely) that an iframe's
    // entries have changed, too.
    activated_entry->render_frame_host()->ForEachRenderFrameHostImplWithAction(
        [this, &activated_entry](RenderFrameHostImpl* rfh) {
          // |this| is given as a parameter to
          // GetNavigationApiHistoryEntryVectors() only for the frame being
          // committed (i.e., the top frame).
          auto entry_arrays =
              rfh->frame_tree()
                  ->controller()
                  .GetNavigationApiHistoryEntryVectors(
                      rfh->frame_tree_node(),
                      activated_entry->render_frame_host() == rfh ? this
                                                                  : nullptr);
          rfh->GetAssociatedLocalFrame()
              ->SetNavigationApiHistoryEntriesForRestore(
                  std::move(entry_arrays),
                  blink::mojom::NavigationApiEntryRestoreReason::kBFCache);
          return RenderFrameHost::FrameIterationAction::kContinue;
        });

    // When activating from BackForwardCache, properly set the
    // BrowsingContextGroupSwap information. This is required because we
    // otherwise do it in the RenderFrameHost selection, in
    // GetFrameHostForNavigation, which does not happen for BFCache restores.
    // TODO(crbug.com/40922919): This code assumes that pages can only be
    // stored in the BFCache if they live in a different BrowsingInstance in
    // another CoopRelatedGroup, so we enforce that invariant via a CHECK. If
    // this is not the case anymore, `browsing_context_group_swap_` should be
    // set to BrowsingContextGroupSwap::CreateRelatedCoopSwap() if the two
    // SiteInstances live in the same CoopRelatedGroup.
    SiteInstanceImpl* current_site_instance =
        frame_tree_node_->current_frame_host()->GetSiteInstance();
    SiteInstanceImpl* target_site_instance =
        activated_entry->render_frame_host()->GetSiteInstance();
    CHECK(!target_site_instance->IsRelatedSiteInstance(current_site_instance));
    browsing_context_group_swap_ =
        BrowsingContextGroupSwap::CreateSecuritySwap();

    base::WeakPtr<NavigationRequest> weak_self(weak_factory_.GetWeakPtr());
    ReadyToCommitNavigation(false /* is_error */);
    // The call above might block on showing a user dialog. The interaction of
    // the user with this dialog might result in the WebContents owning this
    // NavigationRequest to be destroyed. Return if this is the case.
    if (!weak_self)
      return;

    // Treat this as the commit start time for the activation (i.e., after the
    // ReadyToCommitNavigation call).
    page_activation_commit_time_ = base::TimeTicks::Now();

    // Use std::exchange instead of move, so that we clear out the optional on
    // the commit_params.
    activated_entry->SetViewTransitionState(
        std::exchange(commit_params_->view_transition_state, {}));

    // Move the BackForwardCacheImpl::Entry into RenderFrameHostManager, in
    // preparation for committing. This entry may be either restored from the
    // backforward cache.
    DCHECK(activated_entry);
    frame_tree_node_->render_manager()->RestorePage(
        activated_entry->TakeStoredPage());
  } else {
    std::unique_ptr<StoredPage> stored_page =
        GetPrerenderHostRegistry().ActivateReservedHost(
            prerender_frame_tree_node_id_.value(), *this);
    CHECK(stored_page);

    RenderFrameHostImpl* rfh = stored_page->render_frame_host();

    // The prerender page might have navigated. Update the URL and the redirect
    // chain, as the prerendered page might have been redirected or performed
    // a same-document navigation.
    // TODO(crbug.com/40170496): Ensure that the tests that navigate
    // MPArch activation flow do not crash. This is a hack to unblock the basic
    // MPArch activation flow for now. There are probably other parameters which
    // are out of sync, and we need to carefully think through how we can
    // activate a RenderFrameHost whose URL doesn't match the one that was
    // initially passed to NavigationRequest (or disallow subsequent navigations
    // in the main frame of the prerender frame tree).
    common_params_->url = rfh->GetLastCommittedURL();
    // TODO(crbug.com/40170496): We may have to add the entire redirect
    // chain.
    redirect_chain_.clear();
    redirect_chain_.push_back(rfh->GetLastCommittedURL());

    base::WeakPtr<NavigationRequest> weak_self(weak_factory_.GetWeakPtr());
    ReadyToCommitNavigation(false /* is_error */);
    // The call above might block on showing a user dialog. The interaction of
    // the user with this dialog might result in the WebContents owning this
    // NavigationRequest to be destroyed. Return if this is the case.
    if (!weak_self)
      return;

    // Treat this as the commit start time for the activation (i.e., after the
    // ReadyToCommitNavigation call).
    page_activation_commit_time_ = base::TimeTicks::Now();

    // Use std::exchange instead of move, so that we clear out the optional on
    // the commit_params.
    stored_page->SetViewTransitionState(
        std::exchange(commit_params_->view_transition_state, {}));

    // Update navigation API entries. A prerendered page has only a single
    // history entry, but now it has access to a full back/forward list.
    rfh->ForEachRenderFrameHostImplWithAction([this, &stored_page](
                                                  RenderFrameHostImpl* rfh) {
      // Currently, prerender activation only happens for DIFFERENT_DOCUMENT
      // navigations. If that ever changes, `reason` calculation will need to be
      // updated (and new NavigationApiEntryRestoreReason values added).
      DCHECK_EQ(common_params_->navigation_type,
                blink::mojom::NavigationType::DIFFERENT_DOCUMENT);
      blink::mojom::NavigationApiEntryRestoreReason reason =
          common_params_->should_replace_current_entry
              ? blink::mojom::NavigationApiEntryRestoreReason::
                    kPrerenderActivationReplace
              : blink::mojom::NavigationApiEntryRestoreReason::
                    kPrerenderActivationPush;
      // |this| is given as a parameter to
      // GetNavigationApiHistoryEntryVectors() only for the frame being
      // committed (i.e., the top frame).
      auto entry_arrays =
          rfh->frame_tree()->controller().GetNavigationApiHistoryEntryVectors(
              rfh->frame_tree_node(),
              stored_page->render_frame_host() == rfh ? this : nullptr);
      rfh->GetAssociatedLocalFrame()->SetNavigationApiHistoryEntriesForRestore(
          std::move(entry_arrays), reason);
      return RenderFrameHost::FrameIterationAction::kContinue;
    });

    // Move the StoredPage into RenderFrameHostManager, in
    // preparation for committing. This entry may be used for prerendering.
    frame_tree_node_->render_manager()->ActivatePrerender(
        std::move(stored_page));
  }

  // Commit the page activation. This includes committing the RenderFrameHost
  // and restoring extra state, such as proxies, etc.
  // Note that this will delete the NavigationRequest.
  GetRenderFrameHost()->DidCommitPageActivation(
      this, IsPrerenderedPageActivation()
                ? MakeDidCommitProvisionalLoadParamsForPrerenderActivation()
                : MakeDidCommitProvisionalLoadParamsForBFCacheRestore());

  // DO NOT ADD CODE AFTER THIS, as the NavigationRequest might have been
  // deleted by the previous call.
}

void NavigationRequest::SetExpectedProcess(
    RenderProcessHost* expected_process) {
  if (expected_process &&
      expected_process->GetID() == expected_render_process_host_id_) {
    // This |expected_process| has already been informed of the navigation,
    // no need to update it again.
    return;
  }

  ResetExpectedProcess();

  if (expected_process == nullptr)
    return;

  // Keep track of the speculative RenderProcessHost and tell it to expect a
  // navigation to |site_info_|.
  expected_render_process_host_id_ = expected_process->GetID();
  expected_process->AddObserver(this);
  RenderProcessHostImpl::AddExpectedNavigationToSite(
      frame_tree_node()->navigator().controller().GetBrowserContext(),
      expected_process, site_info_);
}

void NavigationRequest::SetExpectedProcessIfAssociated() {
  if (associated_rfh_type_ != AssociatedRenderFrameHostType::NONE) {
    RenderFrameHostImpl* navigating_frame_host =
        associated_rfh_type_ == AssociatedRenderFrameHostType::SPECULATIVE
            ? frame_tree_node_->render_manager()->speculative_frame_host()
            : frame_tree_node_->current_frame_host();
    SetExpectedProcess(navigating_frame_host->GetProcess());
  }
}

void NavigationRequest::ResetExpectedProcess() {
  if (expected_render_process_host_id_.is_null()) {
    // No expected process is set, nothing to update.
    return;
  }
  RenderProcessHost* process =
      RenderProcessHost::FromID(expected_render_process_host_id_);
  if (process) {
    RenderProcessHostImpl::RemoveExpectedNavigationToSite(
        frame_tree_node()->navigator().controller().GetBrowserContext(),
        process, site_info_);
    process->RemoveObserver(this);
  }
  expected_render_process_host_id_ = ChildProcessId();
}

void NavigationRequest::RenderProcessHostDestroyed(RenderProcessHost* host) {
  DCHECK_EQ(host->GetID(), expected_render_process_host_id_);
  ResetExpectedProcess();
}

void NavigationRequest::RenderProcessExited(
    RenderProcessHost* host,
    const ChildProcessTerminationInfo& info) {}

void NavigationRequest::UpdateNavigationHandleTimingsOnResponseReceived(
    bool is_redirect,
    bool is_first_response) {
  base::TimeTicks loader_callback_time = base::TimeTicks::Now();

  const base::TimeDelta domain_lookup_delay =
      response_head_->load_timing.connect_timing.domain_lookup_end -
      response_head_->load_timing.connect_timing.domain_lookup_start;
  const base::TimeDelta connect_delay =
      response_head_->load_timing.connect_timing.connect_end -
      response_head_->load_timing.connect_timing.connect_start;
  const base::TimeDelta ssl_delay =
      response_head_->load_timing.connect_timing.ssl_end -
      response_head_->load_timing.connect_timing.ssl_start;

  if (is_first_response) {
    CHECK(!navigation_handle_timing_.first_fetch_start_time.has_value());
    DCHECK(navigation_handle_timing_.first_request_start_time.is_null());
    DCHECK(navigation_handle_timing_.first_response_start_time.is_null());
    DCHECK(navigation_handle_timing_.first_loader_callback_time.is_null());

    if (!response_head_->request_start.is_null()) {
      navigation_handle_timing_.first_fetch_start_time =
          response_head_->request_start;
    }
    navigation_handle_timing_.first_request_start_time =
        response_head_->load_timing.send_start;
    navigation_handle_timing_.first_response_start_time =
        response_head_->load_timing.receive_headers_start;
    navigation_handle_timing_.first_loader_callback_time = loader_callback_time;

    navigation_handle_timing_.first_request_domain_lookup_delay =
        domain_lookup_delay;
    navigation_handle_timing_.first_request_connect_delay = connect_delay;
    navigation_handle_timing_.first_request_ssl_delay = ssl_delay;

    first_fetch_start_time_ = response_head_->request_start;
  }

  if (!is_redirect) {
    navigation_handle_timing_.non_redirected_request_start_time =
        response_head_->load_timing.send_start;
    navigation_handle_timing_.non_redirect_response_start_time =
        response_head_->load_timing.receive_headers_start;
    navigation_handle_timing_.non_redirect_response_loader_callback_time =
        loader_callback_time;
  }

  navigation_handle_timing_.final_request_start_time =
      response_head_->load_timing.send_start;
  navigation_handle_timing_.final_response_start_time =
      response_head_->load_timing.receive_headers_start;
  navigation_handle_timing_.final_non_informational_response_start_time =
      response_head_->load_timing.receive_non_informational_headers_start;
  navigation_handle_timing_.final_loader_callback_time = loader_callback_time;
  navigation_handle_timing_.final_request_domain_lookup_delay =
      domain_lookup_delay;
  navigation_handle_timing_.final_request_connect_delay = connect_delay;
  navigation_handle_timing_.final_request_ssl_delay = ssl_delay;

  if (response_head_->load_timing_internal_info) {
    navigation_handle_timing_.create_stream_delay =
        response_head_->load_timing_internal_info->create_stream_delay;
    navigation_handle_timing_.connected_callback_delay =
        response_head_->load_timing_internal_info->connected_callback_delay;
    navigation_handle_timing_.initialize_stream_delay =
        response_head_->load_timing_internal_info->initialize_stream_delay;
    navigation_handle_timing_.session_details = {
        .session_source =
            response_head_->load_timing_internal_info->session_source,
        .advertised_alt_svc_state =
            response_head_->load_timing_internal_info->advertised_alt_svc_state,
        .http_network_session_quic_enabled =
            response_head_->load_timing_internal_info
                ->http_network_session_quic_enabled,
    };
  }

  final_receive_headers_end_time_ =
      response_head_->load_timing.receive_headers_end;

  // |navigation_commit_sent_time| will be updated by
  // UpdateNavigationHandleTimingsOnCommitSent() later.
  DCHECK(navigation_handle_timing_.navigation_commit_sent_time.is_null());

  GetDelegate()->DidUpdateNavigationHandleTiming(this);
}

void NavigationRequest::UpdateNavigationHandleTimingsOnCommitSent() {
  DCHECK(navigation_handle_timing_.navigation_commit_sent_time.is_null());
  navigation_handle_timing_.navigation_commit_sent_time =
      base::TimeTicks::Now();

  GetDelegate()->DidUpdateNavigationHandleTiming(this);
}

void NavigationRequest::UpdateSiteInfo(
    RenderProcessHost* post_redirect_process) {
  ChildProcessId post_redirect_process_id;
  if (post_redirect_process) {
    post_redirect_process_id = post_redirect_process->GetID();
  }

  SiteInfo new_site_info = GetSiteInfoForCommonParamsURL();
  if (new_site_info == site_info_ &&
      post_redirect_process_id == expected_render_process_host_id_) {
    return;
  }

  // Stop expecting a navigation to the current SiteInfo in the current expected
  // process.
  ResetExpectedProcess();

  // Update the SiteInfo and the expected process.
  site_info_ = new_site_info;
  SetExpectedProcess(post_redirect_process);
}

bool NavigationRequest::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) {
  GURL url;
  // If this request was upgraded in the net stack, downgrade the URL back to
  // HTTP before checking report only policies.
  if (url_upgraded_after_redirect &&
      disposition ==
          network::CSPContext::CheckCSPDisposition::CHECK_REPORT_ONLY_CSP &&
      common_params_->url.SchemeIs(url::kHttpsScheme)) {
    GURL::Replacements replacements;
    replacements.SetSchemeStr(url::kHttpScheme);
    url = common_params_->url.ReplaceComponents(replacements);
  } else {
    url = common_params_->url;
  }
  network::CSPCheckResult result = context->IsAllowedByCsp(
      policies, directive, url, commit_params_->original_url,
      has_followed_redirect, common_params_->source_location, disposition,
      is_opaque_fenced_frame);
  if (result.WouldBlockIfWildcardDoesNotMatchWs()) {
    GetContentClient()->browser()->LogWebFeatureForCurrentPage(
        GetParentFrame(),
        blink::mojom::WebFeature::kCspWouldBlockIfWildcardDoesNotMatchWs);
  }
  return result.IsAllowed();
}

net::Error NavigationRequest::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) {
  // Following directive checks' order is important as the `error` code takes
  // only the result last set.
  net::Error error = net::OK;

  if (initiator_policies) {
    // [form-action]
    if (begin_params_->is_form_submission && !is_response_check &&
        !IsAllowedByCSPDirective(
            initiator_policies->content_security_policies, &initiator_context,
            network::mojom::CSPDirectiveName::FormAction, has_followed_redirect,
            url_upgraded_after_redirect,
            /*is_opaque_fenced_frame=*/false, disposition)) {
      // net::ERR_ABORTED is used instead of net::ERR_BLOCKED_BY_CSP. This is
      // a better user experience as the user is not presented with an error
      // page. However if other CSP directives like frame-src are violated, it
      // may be appropriate for them to use ERR_BLOCKED_BY_CSP so this can be
      // overridden by the checks below.
      error = net::ERR_ABORTED;
    }
  }

  // [frame-src] or [fenced-frame-src]
  if (parent_policies) {
    bool is_opaque_fenced_frame_root_navigation =
        frame_tree_node_->IsFencedFrameRoot() &&
        fenced_frame_properties_.has_value() &&
        fenced_frame_properties_->mapped_url().has_value() &&
        !fenced_frame_properties_->mapped_url()
             ->GetValueForEntity(FencedFrameEntity::kEmbedder)
             .has_value();
    if (!IsAllowedByCSPDirective(
            parent_policies->content_security_policies, &parent_context,
            frame_tree_node_->IsFencedFrameRoot()
                ? network::mojom::CSPDirectiveName::FencedFrameSrc
                : network::mojom::CSPDirectiveName::FrameSrc,
            has_followed_redirect, url_upgraded_after_redirect,
            is_opaque_fenced_frame_root_navigation, disposition)) {
      error = net::ERR_BLOCKED_BY_CSP;
    }
  }

  return error;
}

net::Error NavigationRequest::CheckContentSecurityPolicy(
    bool has_followed_redirect,
    bool url_upgraded_after_redirect,
    bool is_response_check) {
  DCHECK(policy_container_builder_.has_value());
  if (common_params_->url.SchemeIs(url::kAboutScheme))
    return net::OK;

  if (IsSameDocument())
    return net::OK;

  if (common_params_->should_check_main_world_csp ==
      network::mojom::CSPDisposition::DO_NOT_CHECK) {
    return net::OK;
  }

  RenderFrameHostImpl* parent = frame_tree_node()->parent();
  const PolicyContainerPolicies* parent_policies =
      policy_container_builder_->ParentPolicies();
  DCHECK(!parent == !parent_policies);
  bool set_parent_for_nested_frame_tree =
      !parent && frame_tree_node()->IsFencedFrameRoot() &&
      frame_tree_node()->render_manager()->GetOuterDelegateNode();
  if (set_parent_for_nested_frame_tree) {
    parent = frame_tree_node()
                 ->render_manager()
                 ->GetOuterDelegateNode()
                 ->current_frame_host()
                 ->GetParent();
    // TODO(antoniosartori): If we want to keep checking frame-src for fenced
    // frames, consider storing a snapshot of the parent policies in the
    // `policy_container_builder_` at the beginning of the navigation.
    parent_policies = &parent->policy_container_host()->policies();
  }

  const PolicyContainerPolicies* initiator_policies =
      policy_container_builder_->InitiatorPolicies();

  // CSP checking happens in three phases, per steps 3-5 of
  // https://fetch.spec.whatwg.org/#main-fetch:
  //
  // (1) Check report-only policies and trigger reports for any violations.
  // (2) Upgrade the request to HTTPS if necessary.
  // (3) Check enforced policies (triggering reports for any violations of those
  //     policies) and block the request if necessary.
  //
  // This sequence of events allows site owners to learn about (via step 1) any
  // requests that are upgraded in step 2.

  RenderFrameHostCSPContext parent_context(parent);

  // Note: the initiator RenderFrameHost could have been deleted by
  // now. Then this RenderFrameHostCSPContext will do nothing and we won't
  // report violations for this check.
  //
  // If the initiator frame has navigated away in between, we also use a no-op
  // `initiator_csp_context`, in order not to trigger `securitypolicyviolation`
  // events in the wrong document.
  RenderFrameHostCSPContext initiator_context(
      GetInitiatorDocumentRenderFrameHost());

  net::Error report_only_csp_status = CheckCSPDirectives(
      parent_context, parent_policies, initiator_context, initiator_policies,
      has_followed_redirect, url_upgraded_after_redirect, is_response_check,
      network::CSPContext::CHECK_REPORT_ONLY_CSP);

  // upgrade-insecure-requests is handled in the network code for redirects,
  // only do the upgrade here if this is not a redirect.
  // Note that `FrameTreeNode::IsMainFrame()` returns true for fenced frames
  // based on MPArch, but it's fine to skip the logic below as
  // `network::UpgradeInsecureRequest()` does not apply to fenced frame
  // navigation requests. (See https://github.com/WICG/fenced-frame/issues/23)
  if (!has_followed_redirect && !frame_tree_node()->IsMainFrame()) {
    DCHECK(parent_policies);
    if (parent_policies && network::ShouldUpgradeInsecureRequest(
                               parent_policies->content_security_policies)) {
      upgrade_if_insecure_ = true;
      network::UpgradeInsecureRequest(&common_params_->url);
      common_params_->referrer = Referrer::SanitizeForRequest(
          common_params_->url, *common_params_->referrer);
      commit_params_->original_url = common_params_->url;
    }
  }

  net::Error enforced_csp_status = CheckCSPDirectives(
      parent_context, parent_policies, initiator_context, initiator_policies,
      has_followed_redirect, url_upgraded_after_redirect, is_response_check,
      network::CSPContext::CHECK_ENFORCED_CSP);
  if (enforced_csp_status != net::OK)
    return enforced_csp_status;
  return report_only_csp_status;
}

NavigationRequest::CredentialedSubresourceCheckResult
NavigationRequest::CheckCredentialedSubresource() const {
  // It only applies to subframes.
  if (frame_tree_node_->IsOutermostMainFrame())
    return CredentialedSubresourceCheckResult::ALLOW_REQUEST;

  // URLs with no embedded credentials should load correctly.
  if (!common_params_->url.has_username() &&
      !common_params_->url.has_password())
    return CredentialedSubresourceCheckResult::ALLOW_REQUEST;

  // Relative URLs on top-level pages that were loaded with embedded credentials
  // should load correctly.
  RenderFrameHostImpl* parent = frame_tree_node_->GetParentOrOuterDocument();
  DCHECK(parent);
  const GURL& parent_url = parent->GetLastCommittedURL();
  if (url::IsSameOriginWith(parent_url, common_params_->url) &&
      parent_url.GetUsername() == common_params_->url.GetUsername() &&
      parent_url.GetPassword() == common_params_->url.GetPassword()) {
    return CredentialedSubresourceCheckResult::ALLOW_REQUEST;
  }

  // Warn the user about the request being blocked.
  const char* console_message =
      "Subresource requests whose URLs contain embedded credentials (e.g. "
      "`https://user:pass@host/`) are blocked. See "
      "https://www.chromestatus.com/feature/5669008342777856 for more "
      "details.";
  parent->AddMessageToConsole(blink::mojom::ConsoleMessageLevel::kWarning,
                              console_message);
  return CredentialedSubresourceCheckResult::BLOCK_REQUEST;
}

NavigationRequest::AboutSrcDocCheckResult NavigationRequest::CheckAboutSrcDoc()
    const {
  if (!common_params_->url.IsAboutSrcdoc())
    return AboutSrcDocCheckResult::ALLOW_REQUEST;

  // Loading about:srcdoc in the main frame can't have any reasonable meaning.
  // There might be a malicious website trying to exploit a bug from this. As a
  // defensive measure, do not proceed. They would have failed anyway later.
  if (frame_tree_node_->IsMainFrame())
    return AboutSrcDocCheckResult::BLOCK_REQUEST;

  // There are 4 cases where we allow a navigation to about:srcdoc:

  // 1) We allow same-document navigations from any frame.
  if (IsSameDocument()) {
    return AboutSrcDocCheckResult::ALLOW_REQUEST;
  }

  const std::optional<url::Origin>& initiator_origin =
      common_params().initiator_origin;
  // 2) Browser-initiated navigations are (temporarily) allowed for
  // about:srcdoc.
  if (!initiator_origin) {
    // TODO(https://crbug.com/40165505): for now, allow this, and land the
    // change to block it in a separate CL in case it breaks things beyond our
    // local test suites.
    return AboutSrcDocCheckResult::ALLOW_REQUEST;
  }

  // 3) An about:srcdoc frame can reload itself (even if it is cross-origin from
  // its parent due to being sandboxed).
  if (frame_tree_node()
          ->current_frame_host()
          ->GetLastCommittedURL()
          .IsAboutSrcdoc() &&
      initiator_origin->IsSameOriginWith(
          frame_tree_node()->current_frame_host()->GetLastCommittedOrigin())) {
    return AboutSrcDocCheckResult::ALLOW_REQUEST;
  }

  // 4) Setting src = 'about:srcdoc' is allowed for now as long as the
  // initiator's origin matches the origin of the srcdoc's parent. It is
  // important not to allow initiators that are cross-origin with the parent,
  // because the content comes from the parent and many places in the code
  // assume the origin comes from the initiator.
  // TODO(https://crbug.com/40165505): navigations to 'about:srcdoc' aren't
  // supposed to ever be allowed according to spec.
  if (*initiator_origin ==
      frame_tree_node()->parent()->GetLastCommittedOrigin()) {
    return AboutSrcDocCheckResult::ALLOW_REQUEST;
  }

  // Navigations with an initiator that is cross-origin to the about:srcdoc
  // parent are not allowed.
  return AboutSrcDocCheckResult::BLOCK_REQUEST;
}

void NavigationRequest::SetupCSPEmbeddedEnforcement() {
  if (IsInMainFrame())
    return;
  // TODO(https://crbug.com/11129645): MHTML iframe not supported yet.
  if (IsForMhtmlSubframe())
    return;

  // TODO(antoniosartori): Probably we should have taken a snapshot of the 'csp'
  // attribute at the beginning of the navigation and not now, since the
  // beforeunload handlers might have modified it in the meantime.
  // See pull request about the spec:
  // https://github.com/w3c/webappsec-cspee/pull/11
  network::mojom::ContentSecurityPolicyPtr frame_csp_attribute =
      frame_tree_node()->csp_attribute()
          ? frame_tree_node()->csp_attribute()->Clone()
          : nullptr;
  if (frame_csp_attribute) {
    // TODO(antoniosartori): Maybe we should revisit what 'self' means in the
    // 'csp' attribute.
    const GURL& url = GetURL();
    frame_csp_attribute->self_origin = network::mojom::CSPSource::New(
        url.GetScheme(), url.GetHost(), url.EffectiveIntPort(), "", false,
        false);
  }

  const network::mojom::ContentSecurityPolicy* parent_required_csp =
      frame_tree_node()->parent()->required_csp();

  std::vector<network::mojom::ContentSecurityPolicyPtr> frame_csp;
  frame_csp.push_back(std::move(frame_csp_attribute));
  std::string error_message;
  if (network::IsValidRequiredCSPAttr(frame_csp, parent_required_csp,
                                      error_message)) {
    // If |frame_csp| is valid then it is not null.
    SetRequiredCSP(std::move(frame_csp[0]));
    return;
  }

  if (frame_csp[0]) {
    GetParentFrame()->AddMessageToConsole(
        blink::mojom::ConsoleMessageLevel::kError,
        base::StringPrintf("The frame 'csp' attribute ('%s') is invalid and "
                           "will be discarded: %s",
                           frame_csp[0]->header->header_value.c_str(),
                           error_message.c_str()));
  }

  if (parent_required_csp) {
    SetRequiredCSP(parent_required_csp->Clone());
  }
  // TODO(antoniosartori): Consider instead blocking the navigation here,
  // since this seems to be insecure
  // (cf. https://github.com/w3c/webappsec-cspee/pull/11).
}

NavigationRequest::CSPEmbeddedEnforcementResult
NavigationRequest::CheckCSPEmbeddedEnforcement() {
  // We enforce CSPEE only for subframes.
  if (IsInMainFrame())
    return CSPEmbeddedEnforcementResult::ALLOW_RESPONSE;

  if (IsSameDocument())
    return CSPEmbeddedEnforcementResult::ALLOW_RESPONSE;

  if (!required_csp_)
    return CSPEmbeddedEnforcementResult::ALLOW_RESPONSE;

  // The |response()| can be null for navigations that do not require a
  // URLLoader (about:blank, about:srcdoc, ...)
  const network::mojom::AllowCSPFromHeaderValue* allow_csp_from =
      response() ? response()->parsed_headers->allow_csp_from.get() : nullptr;

  if (network::AllowsBlanketEnforcementOfRequiredCSP(
          GetParentFrame()->GetLastCommittedOrigin(), GetURL(), allow_csp_from,
          required_csp_)) {
    // Enforce the required CSPs on the frame by passing them down to blink.
    policy_container_builder_->AddContentSecurityPolicy(required_csp_->Clone());
    return CSPEmbeddedEnforcementResult::ALLOW_RESPONSE;
  }

  // All the URLs that do not |NeedsUrlLoader()| allows blanket enforcement of
  // CSP, Except for MHTML iframe.
  // TODO(arthursonzogni): Make MHTML response to use the normal loading path,
  // by introducing their own MHTML UrlLoader. Then CSPEE can be supported.
  if (!response()) {
    // TODO(https://crbug.com/11129645): Remove MHTML edge case, once MHTML
    // documents are handled through the standard code path with its own
    // URLLoaderFactory.
    CHECK(IsForMhtmlSubframe());
    return CSPEmbeddedEnforcementResult::ALLOW_RESPONSE;
  }

  std::string sanitized_blocked_url =
      GetRedirectChain().front().DeprecatedGetOriginAsURL().spec();
  if (allow_csp_from && allow_csp_from->is_error_message()) {
    AddDeferredConsoleMessage(
        blink::mojom::ConsoleMessageLevel::kError,
        base::StringPrintf("The value of the 'Allow-CSP-From' response header "
                           "returned by %s is invalid: %s",
                           sanitized_blocked_url.c_str(),
                           allow_csp_from->get_error_message().c_str()));
  }

  if (network::Subsumes(*required_csp_,
                        response()->parsed_headers->content_security_policy)) {
    return CSPEmbeddedEnforcementResult::ALLOW_RESPONSE;
  }

  AddDeferredConsoleMessage(
      blink::mojom::ConsoleMessageLevel::kError,
      base::StringPrintf(
          "Refused to display '%s' in a frame. The embedder requires it to "
          "enforce the following Content Security Policy: '%s'. However, the "
          "frame neither accepts that policy using the Allow-CSP-From header "
          "nor delivers a Content Security Policy which is at least as strong "
          "as that one.",
          sanitized_blocked_url.c_str(),
          required_csp_->header->header_value.c_str()));

  return CSPEmbeddedEnforcementResult::BLOCK_RESPONSE;
}

void NavigationRequest::UpdateHistoryParamsInCommitNavigationParams() {
  NavigationController& navigation_controller =
      frame_tree_node_->navigator().controller();
  commit_params_->current_history_list_index =
      navigation_controller.GetCurrentEntryIndex();
  commit_params_->current_history_list_length =
      navigation_controller.GetEntryCount();
}

void NavigationRequest::SanitizeRedirectsForCommit(
    blink::mojom::CommitNavigationParamsPtr& commit_params) {
  if (!base::FeatureList::IsEnabled(kSanitizeRedirectUrlsDuringNavigation)) {
    return;
  }
  // It is safe to convert GURL to an Origin and back in the code below because
  // we only want to discard the rest of the URL (e.g., path and params). The
  // actual underlying Origin is not needed, which could be inherited or opaque
  // in sandbox cases.
  for (GURL& redirect : commit_params->redirects) {
    redirect = redirect.DeprecatedGetOriginAsURL();
  }

  // In the redirect_infos vector, the last entry is the URL we are going to
  // commit after following all redirects. We should not be sanitizing it, as
  // we need to commit the real URL as part of the navigation.
  if (!commit_params->redirect_infos.empty()) {
    auto redirect_infos_span = base::span(commit_params->redirect_infos);
    for (net::RedirectInfo& redirect :
         redirect_infos_span.first(redirect_infos_span.size() - 1)) {
      redirect.new_url = redirect.new_url.DeprecatedGetOriginAsURL();
    }
  }
}

void NavigationRequest::RendererRequestedNavigationCancellationForTesting() {
  OnNavigationClientDisconnected(0, "");
}

void NavigationRequest::OnNavigationClientDisconnected(
    uint32_t reason,
    const std::string& description) {
  // Renderer-initiated navigation cancellations can only happen before the
  // navigation gets into the READY_TO_COMMIT state, because
  // RendererCancellationThrottle will prevent renderer-initiated navigations
  // from entering that state before the JS task that started the navigation
  // finishes. After navigation reaches READY_TO_COMMIT stage, we should
  // ignore these navigation cancellations, except for these two cases:
  // 1. It reuses the current RenderFrame(Host), because the RenderFrame expects
  // the navigation to be cancelled successfully (as the state in the renderer
  // is already updated to cancel the navigation).
  // TODO(crbug.com/40615943): This case will eventually go away with
  // RenderDocument as cross-document navigations won't reuse RenderFrameHosts
  // anymore. Fix tests that expect this behavior.
  // 2. The target renderer had crashed, so the speculative RenderFrame is not
  // live anymore, because the navigation can't commit in a crashed renderer.
  std::optional<NavigationDiscardReason> discard_reason;
  if (HasRenderFrameHost() && !GetRenderFrameHost()->IsRenderFrameLive()) {
    discard_reason = NavigationDiscardReason::kRenderProcessGone;
  } else {
    switch (static_cast<mojom::NavigationClientDisconnectReason>(reason)) {
      case mojom::NavigationClientDisconnectReason::kResetForSwap:
        // If the RenderFrame that initiated this navigation request is swapped
        // out (disconnecting its NavigationClient for this request), do not
        // treat it as a cancellation. Otherwise, if a previous navigation
        // before `this` is slow to commit, it would unexpectedly cancel `this`
        // subsequent attempt to navigate elsewhere.
        return;
      case mojom::NavigationClientDisconnectReason::kNoExplicitReason:
        error_navigation_trigger_ =
            ErrorNavigationTrigger::kNavigationClientDisconnected;
        discard_reason = NavigationDiscardReason::kInternalCancellation;
        break;
      case mojom::NavigationClientDisconnectReason::kResetForAbort:
        discard_reason = NavigationDiscardReason::kExplicitCancellation;
        break;
      case mojom::NavigationClientDisconnectReason::kResetForNewNavigation:
        discard_reason =
            NavigationDiscardReason::kNewOtherNavigationRendererInitiated;
        break;
      case mojom::NavigationClientDisconnectReason::
          kResetForDuplicateNavigation:
        discard_reason = NavigationDiscardReason::kNewDuplicateNavigation;
        break;
    }
    if (!discard_reason.has_value()) {
      // TODO(https://crbug.com/366060351): An invalid value was used. Kill
      // either the requesting or committing client's process.
      return;
    }
  }

  if (!IsWaitingToCommit()) {
    // The cancellation happens before READY_TO_COMMIT.
    frame_tree_node_->navigator().CancelNavigation(frame_tree_node_,
                                                   discard_reason.value());
  } else if (GetRenderFrameHost() ==
                 frame_tree_node_->render_manager()->current_frame_host() ||
             !GetRenderFrameHost()->IsRenderFrameLive() ||
             (base::FeatureList::IsEnabled(
                  features::kSkipRendererCancellationThrottle) &&
              commit_params_->commit_target_frame_token.has_value())) {
    // If the NavigationRequest has already reached READY_TO_COMMIT,
    // `render_frame_host_` owns `this`. Cache any needed state in stack
    // variables to avoid a use-after-free.
    FrameTreeNode* frame_tree_node = frame_tree_node_;
    GetRenderFrameHost()->NavigationRequestCancelled(this,
                                                     discard_reason.value());
    // Ensure that the speculative RFH, if any, is also cleaned up.
    frame_tree_node->render_manager()->DiscardSpeculativeRFHIfUnused(
        discard_reason.value());
  }

  // Do not add code after this, NavigationRequest might have been destroyed.
}

void NavigationRequest::ReuseRequestNavigationClientForCommitIfNeeded() {
  if (!request_navigation_client_.is_bound()) {
    return;
  }
  auto* rfh_at_construction = RenderFrameHostImpl::FromID(
      current_render_frame_host_id_at_construction_);
  if (GetRenderFrameHost() == rfh_at_construction) {
    // Reuse the request NavigationClient for commit.
    commit_navigation_client_ = std::move(request_navigation_client_);
  } else if (base::FeatureList::IsEnabled(
                 features::kSkipRendererCancellationThrottle) &&
             rfh_at_construction &&
             (rfh_at_construction == frame_tree_node_->current_frame_host()) &&
             rfh_at_construction->GetSiteInstance()->group() ==
                 GetRenderFrameHost()->GetSiteInstance()->group()) {
    // When doing a local RenderFrame swap, to ensure navigation cancellation
    // behavior is the same with what it used to be if we didn't do a
    // RenderFrame swap, reuse `request_navigation_client_` for commit.
    // This allows last-minute navigation cancellations from the requester
    // to still take effect, even if the commit is in-flight to the renderer.
    // If the navigation is not cancelled, when doing the commit in the
    // renderer, the NavigationClient that is currently owned by the old
    // RenderFrame will later be moved to be owned by the new RenderFrame.
    commit_params_->commit_target_frame_token =
        GetRenderFrameHost()->GetFrameToken();
    commit_navigation_client_ = std::move(request_navigation_client_);
    HandleInterfaceDisconnection(commit_navigation_client_);
  } else {
    // This navigation is cross-RenderFrameHost: the original document should
    // no longer be able to cancel it.
    IgnoreInterfaceDisconnection();
  }
}

void NavigationRequest::HandleInterfaceDisconnection(
    mojo::AssociatedRemote<mojom::NavigationClient>& navigation_client) {
  // `Unretained()` is safe because the `mojo::AssociatedRemote` reference only
  // refers to fields owned by `this`.
  navigation_client.set_disconnect_with_reason_handler(
      base::BindOnce(&NavigationRequest::OnNavigationClientDisconnected,
                     base::Unretained(this)));
}

void NavigationRequest::IgnoreInterfaceDisconnection() {
  return request_navigation_client_.set_disconnect_handler(base::DoNothing());
}

void NavigationRequest::IgnoreCommitInterfaceDisconnection() {
  return commit_navigation_client_.set_disconnect_handler(base::DoNothing());
}

bool NavigationRequest::IsSameDocument() const {
  return NavigationTypeUtils::IsSameDocument(common_params_->navigation_type);
}

bool NavigationRequest::IsHistory() const {
  return NavigationTypeUtils::IsHistory(common_params_->navigation_type);
}

bool NavigationRequest::IsRestore() const {
  return NavigationTypeUtils::IsRestore(common_params_->navigation_type);
}

bool NavigationRequest::IsReload() const {
  return NavigationTypeUtils::IsReload(common_params_->navigation_type);
}

void NavigationRequest::RecordDownloadUseCountersPrePolicyCheck() {
  RenderFrameHost* rfh = frame_tree_node_->current_frame_host();
  GetContentClient()->browser()->LogWebFeatureForCurrentPage(
      rfh, blink::mojom::WebFeature::kDownloadPrePolicyCheck);

  // Log UseCounters for opener navigations.
  if (download_policy().IsType(
          blink::NavigationDownloadType::kOpenerCrossOrigin)) {
    rfh->AddMessageToConsole(
        blink::mojom::ConsoleMessageLevel::kError,
        base::StringPrintf(
            "Navigating a cross-origin opener to a download (%s) is "
            "deprecated, see "
            "https://www.chromestatus.com/feature/5742188281462784.",
            common_params_->url.spec().c_str()));
    GetContentClient()->browser()->LogWebFeatureForCurrentPage(
        rfh, blink::mojom::WebFeature::kOpenerNavigationDownloadCrossOrigin);
  }

  // Log UseCounters for download in sandbox.
  if (download_policy().IsType(blink::NavigationDownloadType::kSandbox)) {
    GetContentClient()->browser()->LogWebFeatureForCurrentPage(
        rfh, blink::mojom::WebFeature::kDownloadInSandbox);
  }

  // Log UseCounters for download without user activation.
  if (download_policy().IsType(blink::NavigationDownloadType::kNoGesture)) {
    GetContentClient()->browser()->LogWebFeatureForCurrentPage(
        rfh, blink::mojom::WebFeature::kDownloadWithoutUserGesture);
  }

  // Log UseCounters for download in ad frame without user activation.
  if (download_policy().IsType(
          blink::NavigationDownloadType::kAdFrameNoGesture)) {
    GetContentClient()->browser()->LogWebFeatureForCurrentPage(
        rfh, blink::mojom::WebFeature::kDownloadInAdFrameWithoutUserGesture);
  }

  // Log UseCounters for download in ad frame.
  if (download_policy().IsType(blink::NavigationDownloadType::kAdFrame)) {
    GetContentClient()->browser()->LogWebFeatureForCurrentPage(
        rfh, blink::mojom::WebFeature::kDownloadInAdFrame);
  }
}

void NavigationRequest::RecordDownloadUseCountersPostPolicyCheck() {
  DCHECK(is_download_);
  RenderFrameHost* rfh = frame_tree_node_->current_frame_host();
  GetContentClient()->browser()->LogWebFeatureForCurrentPage(
      rfh, blink::mojom::WebFeature::kDownloadPostPolicyCheck);
}

void NavigationRequest::OnNavigationEventProcessed(
    NavigationThrottleEvent event,
    NavigationThrottle::ThrottleCheckResult result) {
  DCHECK_NE(NavigationThrottle::DEFER, result.action());
  switch (event) {
    case NavigationThrottleEvent::kNoEvent:
      DUMP_WILL_BE_NOTREACHED();
      return;
    case NavigationThrottleEvent::kWillStartRequest:
      OnWillStartRequestProcessed(result);
      return;
    case NavigationThrottleEvent::kWillRedirectRequest:
      OnWillRedirectRequestProcessed(result);
      return;
    case NavigationThrottleEvent::kWillFailRequest:
      OnWillFailRequestProcessed(result);
      return;
    case NavigationThrottleEvent::kWillProcessResponse:
      OnWillProcessResponseProcessed(result);
      return;
    case NavigationThrottleEvent::kWillCommitWithoutUrlLoader:
      OnWillCommitWithoutUrlLoaderProcessed(result);
      return;
  }
  NOTREACHED();
}

void NavigationRequest::OnWillStartRequestProcessed(
    NavigationThrottle::ThrottleCheckResult result) {
  DCHECK_EQ(WILL_START_REQUEST, state_);
  DCHECK_NE(NavigationThrottle::BLOCK_RESPONSE, result.action());
  DCHECK(processing_navigation_throttle_);
  processing_navigation_throttle_ = false;
  if (result.action() != NavigationThrottle::PROCEED)
    SetState(CANCELING);

  if (complete_callback_for_testing_ &&
      std::move(complete_callback_for_testing_).Run(result)) {
    return;
  }

  if (MaybeEvictFromBackForwardCacheBySubframeNavigation(
          frame_tree_node_->current_frame_host())) {
    // DO NOT ADD CODE AFTER THIS, as the NavigationRequest might have been
    // deleted by the previous calls.
    return;
  }

  OnStartChecksComplete(result);

  // DO NOT ADD CODE AFTER THIS, as the NavigationRequest might have been
  // deleted by the previous calls.
}

void NavigationRequest::OnWillRedirectRequestProcessed(
    NavigationThrottle::ThrottleCheckResult result) {
  DCHECK_EQ(WILL_REDIRECT_REQUEST, state_);
  DCHECK_NE(NavigationThrottle::BLOCK_RESPONSE, result.action());
  DCHECK(processing_navigation_throttle_);
  processing_navigation_throttle_ = false;
  if (result.action() == NavigationThrottle::PROCEED) {
    // Notify the delegate that a redirect was encountered and will be followed.
    if (GetDelegate()) {
#if DCHECK_IS_ON()
      DCHECK(is_safe_to_delete_);
      base::AutoReset<bool> resetter(&is_safe_to_delete_, false);
#endif
      GetDelegate()->DidRedirectNavigation(this);
    }
  } else {
    SetState(CANCELING);
  }

  if (complete_callback_for_testing_ &&
      std::move(complete_callback_for_testing_).Run(result)) {
    return;
  }
  OnRedirectChecksComplete(result);

  // DO NOT ADD CODE AFTER THIS, as the NavigationRequest might have been
  // deleted by the previous calls.
}

void NavigationRequest::OnWillFailRequestProcessed(
    NavigationThrottle::ThrottleCheckResult result) {
  DCHECK_EQ(WILL_FAIL_REQUEST, state_);
  DCHECK_NE(NavigationThrottle::BLOCK_RESPONSE, result.action());
  DCHECK(processing_navigation_throttle_);
  processing_navigation_throttle_ = false;
  if (result.action() == NavigationThrottle::PROCEED) {
    result = NavigationThrottle::ThrottleCheckResult(
        NavigationThrottle::PROCEED, net_error_);
  } else {
    SetState(CANCELING);
  }

  if (complete_callback_for_testing_ &&
      std::move(complete_callback_for_testing_).Run(result)) {
    return;
  }
  OnFailureChecksComplete(result);

  // DO NOT ADD CODE AFTER THIS, as the NavigationRequest might have been
  // deleted by the previous calls.
}

void NavigationRequest::OnWillProcessResponseProcessed(
    NavigationThrottle::ThrottleCheckResult result) {
  DCHECK_EQ(WILL_PROCESS_RESPONSE, state_);
  DCHECK_NE(NavigationThrottle::BLOCK_REQUEST, result.action());
  DCHECK_NE(NavigationThrottle::BLOCK_REQUEST_AND_COLLAPSE, result.action());
  DCHECK(processing_navigation_throttle_);
  processing_navigation_throttle_ = false;
  if (result.action() != NavigationThrottle::PROCEED) {
    SetState(CANCELING);
  }

  if (complete_callback_for_testing_ &&
      std::move(complete_callback_for_testing_).Run(result)) {
    return;
  }
  OnWillProcessResponseChecksComplete(result);

  // DO NOT ADD CODE AFTER THIS, as the NavigationRequest might have been
  // deleted by the previous calls.
}

void NavigationRequest::OnWillCommitWithoutUrlLoaderProcessed(
    NavigationThrottle::ThrottleCheckResult result) {
  DCHECK_EQ(WILL_COMMIT_WITHOUT_URL_LOADER, state_);
  DCHECK(result.action() == NavigationThrottle::CANCEL_AND_IGNORE ||
         result.action() == NavigationThrottle::PROCEED);
  DCHECK(processing_navigation_throttle_);
  processing_navigation_throttle_ = false;
  if (complete_callback_for_testing_ &&
      std::move(complete_callback_for_testing_).Run(result)) {
    return;
  }

  if (MaybeEvictFromBackForwardCacheBySubframeNavigation(
          frame_tree_node_->current_frame_host())) {
    // DO NOT ADD CODE AFTER THIS, as the NavigationRequest might have been
    // deleted by the previous calls.
    return;
  }

  OnWillCommitWithoutUrlLoaderChecksComplete(result);

  // DO NOT ADD CODE AFTER THIS, as the NavigationRequest might have been
  // deleted by the previous calls.
}

RenderFrameHostImpl*
NavigationRequest::GetRenderFrameHostRestoredFromBackForwardCache() const {
  if (IsServedFromBackForwardCache()) {
    return &*rfh_restored_from_back_forward_cache_.value();
  }
  return nullptr;
}

NavigatorDelegate* NavigationRequest::GetDelegate() const {
  return frame_tree_node()->navigator().GetDelegate();
}

void NavigationRequest::Resume(NavigationThrottle* resuming_throttle) {
  DCHECK(resuming_throttle);
  CHECK(!is_resuming_) << "This call does not support re-entrancy.";
  EnterChildTraceEvent("Resume", this);

  if (1u == throttle_registry_->GetDeferringThrottles().size()) {
    is_resuming_ = true;

    // Stop watching for response body changes to ensure that the response body
    // callback isn't called later in the throttle's lifetime with a response
    // body that is not relevant to the throttle.
    if (response_body_watcher_) {
      CHECK(response_body_callback_);
      response_body_watcher_.reset();
      base::WeakPtr<NavigationRequest> this_ptr(weak_factory_.GetWeakPtr());
      std::move(response_body_callback_).Run(std::string());
      if (this_ptr.WasInvalidated()) {
        // TODO(https://crbug.com/411238078): Replace the debug code with a
        // comment once we ensure that this is the root cause.
        SCOPED_CRASH_KEY_STRING32("Bug411238078", "throttle",
                                  resuming_throttle->GetNameForLogging());
        base::debug::DumpWithoutCrashing();
        return;
      }
    }

    is_resuming_ = false;
  }
  throttle_registry_->ResumeProcessingNavigationEvent(resuming_throttle);
  // DO NOT ADD CODE AFTER THIS, as the NavigationHandle might have been deleted
  // by the previous call.
}

void NavigationRequest::CancelDeferredNavigation(
    NavigationThrottle* cancelling_throttle,
    NavigationThrottle::ThrottleCheckResult result) {
  DCHECK(cancelling_throttle);
  DCHECK(throttle_registry_->GetDeferringThrottles().contains(
      cancelling_throttle));
  CancelDeferredNavigationInternal(result);
}

void NavigationRequest::RegisterThrottleForTesting(
    std::unique_ptr<NavigationThrottle> navigation_throttle) {
  // Throttles will already have run the first time the page was navigated, we
  // won't run them again on activation. See instead CommitDeferringCondition.
  DCHECK(!IsPageActivation())
      << "Attempted to register a NavigationThrottle for an activating "
         "navigation which will not work.";
  throttle_registry_->AddThrottle(std::move(navigation_throttle));
}
bool NavigationRequest::IsDeferredForTesting() {
  return IsDeferred();
}

bool NavigationRequest::IsMhtmlOrSubframe() {
  DCHECK(state_ >= WILL_PROCESS_RESPONSE ||
         state_ == WILL_START_REQUEST && !NeedsUrlLoader());

  return is_mhtml_or_subframe_;
}

bool NavigationRequest::IsForMhtmlSubframe() const {
  return frame_tree_node_->parent() && frame_tree_node_->frame_tree()
                                           .root()
                                           ->current_frame_host()
                                           ->is_mhtml_document();
}

void NavigationRequest::CancelDeferredNavigationInternal(
    NavigationThrottle::ThrottleCheckResult result) {
  DCHECK(processing_navigation_throttle_);
  DCHECK(result.action() == NavigationThrottle::CANCEL_AND_IGNORE ||
         result.action() == NavigationThrottle::CANCEL ||
         result.action() == NavigationThrottle::BLOCK_RESPONSE ||
         result.action() == NavigationThrottle::BLOCK_REQUEST ||
         result.action() == NavigationThrottle::BLOCK_REQUEST_AND_COLLAPSE);
  DCHECK((result.action() != NavigationThrottle::BLOCK_REQUEST_AND_COLLAPSE &&
          result.action() != NavigationThrottle::BLOCK_REQUEST) ||
         state_ == WILL_START_REQUEST || state_ == WILL_REDIRECT_REQUEST);

  EnterChildTraceEvent("CancelDeferredNavigation", this);
  NavigationState old_state = state_;
  SetState(CANCELING);
  if (complete_callback_for_testing_ &&
      std::move(complete_callback_for_testing_).Run(result)) {
    return;
  }

  switch (old_state) {
    case WILL_START_REQUEST:
      OnStartChecksComplete(result);
      return;
    case WILL_REDIRECT_REQUEST:
      OnRedirectChecksComplete(result);
      return;
    case WILL_FAIL_REQUEST:
      OnFailureChecksComplete(result);
      return;
    case WILL_PROCESS_RESPONSE:
      OnWillProcessResponseChecksComplete(result);
      return;
    case WILL_COMMIT_WITHOUT_URL_LOADER:
      OnWillCommitWithoutUrlLoaderChecksComplete(result);
      return;
    default:
      NOTREACHED();
  }
  // DO NOT ADD CODE AFTER THIS, as the NavigationRequest might have been
  // deleted by the previous calls.
}

void NavigationRequest::WillStartRequest() {
  TRACE_EVENT("navigation", "NavigationRequest::WillStartRequest",
              perfetto::Flow::FromPointer(this));
  EnterChildTraceEvent("WillStartRequest", this);
  DCHECK_EQ(state_, WILL_START_REQUEST);
  will_start_request_time_ = base::TimeTicks::Now();

  if (IsSelfReferentialURL()) {
    SetState(CANCELING);
    DVLOG(1) << "Cancelling self-referential request for " << GetURL();
    if (complete_callback_for_testing_ &&
        std::move(complete_callback_for_testing_)
            .Run(NavigationThrottle::CANCEL)) {
      return;
    }
    OnWillProcessResponseChecksComplete(NavigationThrottle::CANCEL);

    // DO NOT ADD CODE AFTER THIS, as the NavigationRequest might have been
    // deleted by the previous calls.
    return;
  }

  // Throttles will already have run the first time the page was navigated, we
  // won't run them again on activation.
  if (!IsPageActivation()) {
    base::ElapsedTimer duration;
    throttle_registry_->RegisterNavigationThrottles();
    base::UmaHistogramTimes(
        base::StrCat({"Navigation.RegisterNavigationThrottlesTime.",
                      IsInMainFrame() ? "MainFrame" : "Subframe"}),
        duration.Elapsed());
  }

  // If the content/ embedder did not pass the NavigationUIData at the beginning
  // of the navigation, ask for it now.
  if (!navigation_ui_data_) {
    navigation_ui_data_ = GetDelegate()->GetNavigationUIData(this);
  }

  processing_navigation_throttle_ = true;

  base::ScopedUmaHistogramTimer timer(base::StrCat(
      {"Navigation.ProcessNavigationThrottlesTime.WillStartRequest.",
       IsInMainFrame() ? "MainFrame" : "SubFrame"}));
  // Notify each throttle of the request.
  throttle_registry_->ProcessNavigationEvent(
      NavigationThrottleEvent::kWillStartRequest);
  // DO NOT ADD CODE AFTER THIS, as the NavigationHandle might have been deleted
  // by the previous call.
}

void NavigationRequest::WillRedirectRequest(
    const GURL& new_referrer_url,
    RenderProcessHost* post_redirect_process) {
  TRACE_EVENT("navigation", "NavigationRequest::WillRedirectRequest",
              perfetto::Flow::FromPointer(this));
  EnterChildTraceEvent("WillRedirectRequest", this, "url",
                       common_params_->url.possibly_invalid_spec());
  UpdateStateFollowingRedirect(new_referrer_url);
  UpdateSiteInfo(post_redirect_process);

  if (IsSelfReferentialURL()) {
    SetState(CANCELING);
    if (complete_callback_for_testing_ &&
        std::move(complete_callback_for_testing_)
            .Run(NavigationThrottle::CANCEL)) {
      return;
    }
    OnWillProcessResponseChecksComplete(NavigationThrottle::CANCEL);

    // DO NOT ADD CODE AFTER THIS, as the NavigationRequest might have been
    // deleted by the previous calls.
    return;
  }

  // Notify each throttle of the request.
  throttle_registry_->ProcessNavigationEvent(
      NavigationThrottleEvent::kWillRedirectRequest);
  // DO NOT ADD CODE AFTER THIS, as the NavigationHandle might have been deleted
  // by the previous call.
}

void NavigationRequest::WillFailRequest() {
  EnterChildTraceEvent("WillFailRequest", this);

  SetState(WILL_FAIL_REQUEST);
  processing_navigation_throttle_ = true;

  // Notify each throttle of the request.
  throttle_registry_->ProcessNavigationEvent(
      NavigationThrottleEvent::kWillFailRequest);
  // DO NOT ADD CODE AFTER THIS, as the NavigationHandle might have been deleted
  // by the previous call.
}

void NavigationRequest::WillProcessResponse() {
  TRACE_EVENT("navigation", "NavigationRequest::WillProcessResponse",
              perfetto::Flow::FromPointer(this));
  EnterChildTraceEvent("WillProcessResponse", this);
  DCHECK_EQ(state_, WILL_PROCESS_RESPONSE);

  processing_navigation_throttle_ = true;
  was_get_response_body_called_ = false;
  base::WeakPtr<NavigationRequest> this_ptr(weak_factory_.GetWeakPtr());

  // Notify each throttle of the response.
  throttle_registry_->ProcessNavigationEvent(
      NavigationThrottleEvent::kWillProcessResponse);

  // `this` may have been deleted by the previous call.
  if (!this_ptr) {
    // DO NOT ADD CODE HERE.
    return;
  }

  CHECK(!was_get_response_body_called_ || IsDeferred());
}

void NavigationRequest::WillCommitWithoutUrlLoader() {
  TRACE_EVENT("navigation", "NavigationRequest::WillCommitWithoutUrlLoader",
              perfetto::Flow::FromPointer(this));
  EnterChildTraceEvent("WillCommitWithoutUrlLoader", this);

  throttle_registry_->RegisterNavigationThrottlesForCommitWithoutUrlLoader();

  // `CommitNavigation()` expects to be called once the request has reached
  // at least `WILL_PROCESS_REPSONSE`. `WILL_COMMIT_WITHOUT_URL_LOADER` meets
  // that requirement, and is useful to clarify which throttles we are waiting
  // for.
  SetState(WILL_COMMIT_WITHOUT_URL_LOADER);
  processing_navigation_throttle_ = true;

  throttle_registry_->ProcessNavigationEvent(
      NavigationThrottleEvent::kWillCommitWithoutUrlLoader);
}

bool NavigationRequest::IsSelfReferentialURL() {
  // about: URLs should be exempted since they are reserved for other purposes
  // and cannot be the source of infinite recursion.
  // See https://crbug.com/341858 .
  if (common_params_->url.SchemeIs(url::kAboutScheme))
    return false;

  // Browser-triggered navigations should be exempted.
  if (browser_initiated())
    return false;

  // Some sites rely on constructing frame hierarchies where frames are loaded
  // via POSTs with the same URLs, so exempt POST requests.
  // See https://crbug.com/710008.
  if (common_params_->method == "POST")
    return false;

  // We allow one level of self-reference because some sites depend on that,
  // but we don't allow more than one.
  bool found_self_reference = false;
  for (RenderFrameHost* rfh = frame_tree_node()->parent(); rfh;
       rfh = rfh->GetParent()) {
    if (rfh->GetLastCommittedURL().EqualsIgnoringRef(common_params_->url)) {
      if (found_self_reference)
        return true;
      found_self_reference = true;
    }
  }
  return false;
}

void NavigationRequest::DidCommitNavigation(
    const mojom::DidCommitProvisionalLoadParams& params,
    bool navigation_entry_committed,
    bool did_replace_entry,
    const GURL& previous_main_frame_url) {
  TRACE_EVENT("navigation", "NavigationRequest::DidCommitNavigation",
              perfetto::Flow::FromPointer(this));
  common_params_->url = params.url;
  did_replace_entry_ = did_replace_entry;
  should_update_history_ = params.should_update_history;
  navigation_handle_timing_.navigation_commit_received_time =
      params.commit_navigation_start;
  navigation_handle_timing_.navigation_commit_reply_sent_time =
      params.commit_reply_sent;
  navigation_handle_timing_.navigation_did_commit_time = base::TimeTicks::Now();
  // A same document navigation with the same url, and no user-gesture is
  // typically the result of 'history.replaceState().' As the page is
  // controlling this, the user doesn't really think of this as a navigation
  // and it doesn't make sense to log this in history. Logging this in history
  // would lead to lots of visits to a particular page, which impacts the
  // visit count.
  // Navigations in non-primary frame trees don't appear in history.
  if ((should_update_history_ && IsSameDocument() && !HasUserGesture() &&
       params.url == previous_main_frame_url) ||
      !GetRenderFrameHost()->GetPage().IsPrimary()) {
    should_update_history_ = false;
  }
  previous_main_frame_url_ = previous_main_frame_url;

  // It should be kept in sync with the check in
  // RenderFrameHostImpl::TakeNewDocumentPropertiesFromNavigation.
  if (DidEncounterError()) {
    EnterChildTraceEvent("DidCommitNavigation: error page", this);
    SetState(DID_COMMIT_ERROR_PAGE);
  } else {
    EnterChildTraceEvent("DidCommitNavigation", this);
    SetState(DID_COMMIT);
  }
  navigation_or_document_handle_->OnNavigationCommitted(*this);

  // If the navigation committed successfully, pass ownership of ViewTransition
  // resources to the new view. This ensures that the resources are cleaned up
  // if the new renderer process terminates before taking ownership of them.
  if (view_transition_resources_ && state_ == DID_COMMIT) {
    GetRenderFrameHost()
        ->GetRenderWidgetHost()
        ->GetRenderWidgetHostViewBase()
        ->SetViewTransitionResources(std::move(view_transition_resources_));
  }

  StopCommitTimeout();

  // Switching BrowsingInstance because of COOP or top-level cross browsing
  // instance navigation resets the name of the frame. The renderer already
  // knows locally about it because we sent an empty name at frame creation
  // time. The renderer has now committed the page and we can safely enforce the
  // empty name on the browser side.
  BrowserContext* context =
      frame_tree_node_->navigator().controller().GetBrowserContext();
  bool should_clear_browsing_instance_name =
      browsing_context_group_swap().ShouldClearWindowName() ||
      (commit_params().is_cross_site_cross_browsing_context_group &&
       base::FeatureList::IsEnabled(
           features::kClearCrossSiteCrossBrowsingContextGroupWindowName) &&
       GetContentClient()
           ->browser()
           ->IsClearWindowNameForNewBrowsingContextGroupAllowed(context));

  if (should_clear_browsing_instance_name) {
    std::string name, unique_name;
    // The "swap" only affect main frames, that have an empty unique name.
    if (features::GetBrowsingContextMode() ==
        features::BrowsingContextStateImplementationType::
            kLegacyOneToOneWithFrameTreeNode) {
      DCHECK(frame_tree_node_->unique_name().empty());
      GetRenderFrameHost()->browsing_context_state()->SetFrameName(name,
                                                                   unique_name);
    }
  }

  // Record metrics for the time it took to commit the navigation if it was to
  // another document without error.
  if (!IsSameDocument() && state_ != DID_COMMIT_ERROR_PAGE) {
    ui::PageTransition transition =
        ui::PageTransitionFromInt(common_params_->transition);
    base::Process::Priority priority =
        GetRenderFrameHost()->GetProcess()->GetPriority();

    RecordStartToCommitMetrics(
        common_params_->navigation_start, transition, ready_to_commit_time_,
        priority, is_same_process_, frame_tree_node_->IsMainFrame());
  }

  DCHECK(!frame_tree_node_->IsMainFrame() || navigation_entry_committed)
      << "Only subframe navigations can get here without changing the "
      << "NavigationEntry";
  subframe_entry_committed_ = navigation_entry_committed;

  // For successful navigations, ensure the frame owner element is no longer
  // collapsed as a result of a prior navigation.
  if (state_ != DID_COMMIT_ERROR_PAGE &&
      (!frame_tree_node()->IsMainFrame() ||
       frame_tree_node()->IsFencedFrameRoot())) {
    // The last committed load in collapsed frames will be an error page with
    // |kUnreachableWebDataURL|. Same-document navigation should not be
    // possible.
    DCHECK(!IsSameDocument() || !frame_tree_node()->is_collapsed());
    frame_tree_node()->SetCollapsed(false);
  }

  if (service_worker_handle_ &&
      service_worker_handle_->service_worker_client()) {
    // Notify the service worker navigation handle that the navigation finished
    // committing.
    service_worker_handle_->service_worker_client()->OnEndNavigationCommit();
  }

  // TODO(crbug.com/40249865): consider using NavigationOrDocumentHandle
  // instead once we can get a WeakDocumentPtr from NavigationOrDocumentHandle.
  if (subresource_proxying_url_loader_service_bind_context_) {
    DCHECK(!IsSameDocument());

    subresource_proxying_url_loader_service_bind_context_
        ->OnDidCommitNavigation(GetRenderFrameHost()->GetWeakDocumentPtr());
  }
  if (keep_alive_url_loader_factory_context_) {
    DCHECK(!IsSameDocument());

    keep_alive_url_loader_factory_context_->OnDidCommitNavigation(this);
  }
  if (fetch_later_loader_factory_context_) {
    DCHECK(!IsSameDocument());

    fetch_later_loader_factory_context_->OnDidCommitNavigation(this);
  }

  // Network status of the entire frame tree needs to be updated once a
  // NavigationRequest commits. When fenced frames revoke network access by
  // calling `window.fence.disableUntrustedNetwork`, the returned promise cannot
  // be resolved until ongoing navigations in descendant frames complete.
  GetRenderFrameHost()
      ->GetOutermostMainFrame()
      ->CalculateUntrustedNetworkStatus();

  if (!pending_commit_metrics_.start_time.is_null()) {
    const bool is_for_mhtml = IsMhtmlMimeType(GetMimeType());
    base::UmaHistogramTimes(
        is_for_mhtml ? "Navigation.PendingCommit.Duration.MHTML"
                     : "Navigation.PendingCommit.Duration.Regular",
        base::TimeTicks::Now() - pending_commit_metrics_.start_time);
    const bool did_block_get_frame_host_for_navigation =
        pending_commit_metrics_.blocked_count > 0;
    base::UmaHistogramBoolean(
        is_for_mhtml
            ? "Navigation.PendingCommit.DidBlockGetFrameHostForNavigation.MHTML"
            : "Navigation.PendingCommit.DidBlockGetFrameHostForNavigation."
              "Regular",
        did_block_get_frame_host_for_navigation);
    if (did_block_get_frame_host_for_navigation) {
      base::UmaHistogramCounts100(
          is_for_mhtml ? "Navigation.PendingCommit.BlockedCount.MHTML"
                       : "Navigation.PendingCommit.BlockedCount.Regular",
          pending_commit_metrics_.blocked_count);
      base::UmaHistogramCounts100(
          is_for_mhtml ? "Navigation.PendingCommit.BlockedCommitCount.MHTML"
                       : "Navigation.PendingCommit.BlockedCommitCount.Regular",
          pending_commit_metrics_.blocked_commit_count);
    }
  }

  // DO NOT ADD CODE after this.
  // UnblockPendingSubframeNavigationRequestsIfNeeded() resumes throttles, which
  // may cause the destruction of this NavigationRequest.
  UnblockPendingSubframeNavigationRequestsIfNeeded();
}

SiteInfo NavigationRequest::GetSiteInfoForCommonParamsURL() {
  UrlInfo url_info = GetUrlInfo();

  // TODO(alexmos): Using |starting_site_instance_|'s IsolationContext may not
  // be correct for cross-BrowsingInstance redirects.
  return SiteInfo::Create(starting_site_instance_->GetIsolationContext(),
                          url_info);
}

// TODO(zetamoo): Try to merge this function inside its callers.
void NavigationRequest::UpdateStateFollowingRedirect(
    const GURL& new_referrer_url) {
  // The navigation should not redirect to a "renderer debug" url. It should be
  // blocked in NavigationRequest::OnRequestRedirected or in
  // ResourceLoader::OnReceivedRedirect.
  // Note: the |common_params_->url| below is the post-redirect URL.
  // See https://crbug.com/728398.
  CHECK(!blink::IsRendererDebugURL(common_params_->url));

  // Re-generate the feature context to ensure that the runtime-enabled features
  // have the correct state values.
  runtime_feature_state_context_ = blink::RuntimeFeatureStateContext();

  // Update the navigation parameters.
  if (!(common_params_->transition & ui::PAGE_TRANSITION_CLIENT_REDIRECT)) {
    sanitized_referrer_->url = new_referrer_url;
    sanitized_referrer_ =
        Referrer::SanitizeForRequest(common_params_->url, *sanitized_referrer_);
  }

  common_params_->referrer = sanitized_referrer_.Clone();

  was_redirected_ = true;
  redirect_chain_.push_back(common_params_->url);

  SetState(WILL_REDIRECT_REQUEST);
  processing_navigation_throttle_ = true;

#if BUILDFLAG(IS_ANDROID)
  navigation_handle_proxy_->DidRedirect();
#endif
}

void NavigationRequest::SetNavigationClient(
    mojo::PendingAssociatedRemote<mojom::NavigationClient> navigation_client) {
  DCHECK(from_begin_navigation_ ||
         common_params_->is_history_navigation_in_new_child_frame);
  DCHECK(!request_navigation_client_);
  if (!navigation_client.is_valid())
    return;

  request_navigation_client_.reset();
  request_navigation_client_.Bind(std::move(navigation_client));

  // Binds the OnAbort callback
  HandleInterfaceDisconnection(request_navigation_client_);
}

bool NavigationRequest::NeedsUrlLoader() {
#if BUILDFLAG(IS_ANDROID)
  // If the navigation is for a PDF file, Chrome on Android will render it with
  // a Java NativePage object and the navigation will always be main frame. The
  // NativePage is responsible for reading the file and thus no URLLoader is
  // needed. If NativePage is not enabled for PDF, |is_pdf_| should never be
  // true.
  if (is_pdf_) {
    return false;
  }
#endif  // BUILDFLAG(IS_ANDROID)

  bool is_mhtml_subframe_loaded_from_achive =
      IsForMhtmlSubframe() &&
      // Unlike all other MHTML subframe URLs, data-url are loaded via the
      // URL, not from the MHTML archive. See https://crbug.com/969696.
      !common_params_->url.SchemeIs(url::kDataScheme);

  return IsURLHandledByNetworkStack(common_params_->url) && !IsSameDocument() &&
         !is_mhtml_subframe_loaded_from_achive;
}

void NavigationRequest::UpdatePrivateNetworkRequestPolicy() {
  // It is useless to update this state for same-document navigations as well
  // as pages served from the back-forward cache or prerendered pages.
  DCHECK(!IsSameDocument());
  DCHECK(!IsPageActivation());
  if (GetSocketAddress().address().IsValid() &&
      GetSocketAddress().address().IsZero()) {
    web_features_to_log_.push_back(
        blink::mojom::WebFeature::kPrivateNetworkAccessNullIpAddress);
  }

  ContentBrowserClient* client = GetContentClient()->browser();
  BrowserContext* context =
      frame_tree_node_->navigator().controller().GetBrowserContext();

  url::Origin origin = GetOriginToCommit().value();
  // TODO(crbug.com/452389539): Centralize these policy overrides.
  ContentBrowserClient::PrivateNetworkRequestPolicyOverride policy_override =
      client->ShouldOverridePrivateNetworkRequestPolicy(context, origin);

  if (policy_override ==
      ContentBrowserClient::PrivateNetworkRequestPolicyOverride::kForceAllow) {
    private_network_request_policy_ =
        network::mojom::PrivateNetworkRequestPolicy::kAllow;
    return;
  }

  const PolicyContainerPolicies& policies =
      policy_container_builder_->FinalPolicies();

  // Deprecation trial is to allow http sites to run LNA requests assuming the
  // user grants the permission to the web site.
  //
  // Support for origin trial tokens in <meta> tags or programmatically are not
  // supported, for the same reasons as in the previous PNA trial:
  // https://developer.chrome.com/blog/private-network-access-update#register-deprecation-trial
  if (!policies.is_web_secure_context &&
      policies.allow_non_secure_local_network_access &&
      base::FeatureList::IsEnabled(
          network::features::kLocalNetworkAccessChecks)) {
    web_features_to_log_.push_back(
        blink::mojom::WebFeature::
            kLocalNetworkAccessNonSecureContextAllowedDeprecationTrial);
  }

  // TODO(crbug.com/433300380): The lna_secure_context_overide check needs to be
  // done in all other policy derivation points. This boolean should probably be
  // put into PolicyContainerPolicies.
  private_network_request_policy_ = DerivePrivateNetworkRequestPolicy(
      policies, PrivateNetworkRequestContext::kSubresource);

  if (policy_override ==
      ContentBrowserClient::PrivateNetworkRequestPolicyOverride::
          kBlockInsteadOfWarn) {
    private_network_request_policy_ =
        OverrideToBlockInsteadOfWarn(private_network_request_policy_);
  }

  if (policy_override ==
      ContentBrowserClient::PrivateNetworkRequestPolicyOverride::
          kWarnInsteadOfBlock) {
    private_network_request_policy_ =
        OverrideToWarnInsteadOfBlock(private_network_request_policy_);
  }
}

std::vector<blink::mojom::WebFeature>
NavigationRequest::TakeWebFeaturesToLog() {
  std::vector<blink::mojom::WebFeature> result;
  result.swap(web_features_to_log_);
  return result;
}

void NavigationRequest::set_keep_alive_url_loader_factory_context(
    base::WeakPtr<KeepAliveURLLoaderService::FactoryContext> factory_context) {
  if (did_set_keep_alive_url_loader_factory_context_for_testing_) {
    // A unit test set a fake context already. Use that instead of the passed in
    // context.
    CHECK_IS_TEST();
    CHECK(keep_alive_url_loader_factory_context_);
    CHECK_NE(keep_alive_url_loader_factory_context_.get(),
             factory_context.get());
    return;
  }
  CHECK(!keep_alive_url_loader_factory_context_);
  keep_alive_url_loader_factory_context_ = factory_context;
}

void NavigationRequest::set_fetch_later_loader_factory_context(
    base::WeakPtr<KeepAliveURLLoaderService::FactoryContext> factory_context) {
  if (did_set_fetch_later_url_loader_factory_context_for_testing_) {
    // A unit test set a fake context already. Use that instead of the passed in
    // context.
    CHECK_IS_TEST();
    CHECK(fetch_later_loader_factory_context_);
    CHECK_NE(fetch_later_loader_factory_context_.get(), factory_context.get());
    return;
  }
  fetch_later_loader_factory_context_ = factory_context;
}

void NavigationRequest::SetKeepAliveURLLoaderFactoryContextForTesting(
    base::WeakPtr<KeepAliveURLLoaderService::FactoryContext> factory_context) {
  CHECK(!keep_alive_url_loader_factory_context_);
  did_set_keep_alive_url_loader_factory_context_for_testing_ = true;
  keep_alive_url_loader_factory_context_ = factory_context;
  CHECK(keep_alive_url_loader_factory_context_);
}

void NavigationRequest::SetFetchLaterLoaderFactoryContextForTesting(
    base::WeakPtr<KeepAliveURLLoaderService::FactoryContext> factory_context) {
  CHECK(!fetch_later_loader_factory_context_);
  did_set_fetch_later_url_loader_factory_context_for_testing_ = true;
  fetch_later_loader_factory_context_ = factory_context;
  CHECK(fetch_later_loader_factory_context_);
}

void NavigationRequest::ReadyToCommitNavigation(bool is_error) {
  TRACE_EVENT("navigation", "NavigationRequest::ReadyToCommitNavigation",
              perfetto::Flow::FromPointer(this));
  EnterChildTraceEvent("ReadyToCommitNavigation", this);

  // We may come back to here asynchronously, and the renderer may be destroyed
  // in the meantime. Renderer-initiated navigations listen to mojo
  // disconnection from the renderer NavigationClient; but browser-initiated
  // navigations do not, so we must look explicitly. We should not proceed and
  // claim "ReadyToCommitNavigation" to the delegate if the renderer is gone.
  if (!GetRenderFrameHost()->IsRenderFrameLive()) {
    OnNavigationClientDisconnected(0, "");
    // DO NOT ADD CODE AFTER THIS, as the NavigationHandle has been deleted
    // by the previous call.
    return;
  }

  // Note: This marks the RenderFrameHost as loading. This is important to
  // ensure that FrameTreeNode::IsLoading() still returns correct result for
  // delegate and observer callbacks. Otherwise, there would be a period of time
  // where the FrameTreeNode has no NavigationRequest, yet the
  // RenderFrameHostImpl is not marked as loading yet, causing
  // FrameTreeNode::IsLoading() to incorrectly return false.
  frame_tree_node_->TransferNavigationRequestOwnership(GetRenderFrameHost());

  // When a speculative RenderFrameHost reaches ReadyToCommitNavigation, the
  // browser process has asked the renderer to commit the navigation and is
  // waiting for confirmation of the commit. Update the LifecycleStateImpl to
  // kPendingCommit as RenderFrameHost isn't considered speculative anymore and
  // was chosen to commit as this navigation's final RenderFrameHost.
  if (GetRenderFrameHost()->lifecycle_state() ==
      RenderFrameHostImpl::LifecycleStateImpl::kSpeculative) {
    // Only cross-RenderFrameHost navigations create speculative
    // RenderFrameHosts whereas SameDocument, BackForwardCache and
    // PrerenderedActivation navigations don't.
    DCHECK(!IsSameDocument() && !IsPageActivation());
    GetRenderFrameHost()->SetLifecycleState(
        RenderFrameHostImpl::LifecycleStateImpl::kPendingCommit);
    pending_commit_metrics_.start_time = base::TimeTicks::Now();
  }

  // Reset the source location information, which is not needed anymore. This
  // avoids leaking cross-origin data to another process in case the navigation
  // doesn't commit in the same process as the document that initiated it.
  common_params_->source_location = network::mojom::SourceLocation::New();

  SetState(READY_TO_COMMIT);
  ready_to_commit_time_ = base::TimeTicks::Now();
  RestartCommitTimeout();

  if (!IsSameDocument() && !IsPageActivation())
    UpdatePrivateNetworkRequestPolicy();

  RenderFrameHostImpl* previous_render_frame_host =
      frame_tree_node_->current_frame_host();

  // Record metrics for the time it takes to get to this state from the
  // beginning of the navigation.
  if (!IsSameDocument() && !is_error) {
    is_same_process_ =
        GetRenderFrameHost()->GetProcess()->GetDeprecatedID() ==
        previous_render_frame_host->GetProcess()->GetDeprecatedID();

    RecordReadyToCommitMetrics(
        previous_render_frame_host, GetRenderFrameHost(), *common_params_.get(),
        ready_to_commit_time_, origin_agent_cluster_end_result_,
        did_receive_early_hints_before_cross_origin_redirect_);
  }

  std::optional<url::Origin> origin_to_commit = GetOriginToCommit();
  same_origin_ = (previous_render_frame_host->GetLastCommittedOrigin() ==
                  origin_to_commit);

  SetExpectedProcess(GetRenderFrameHost()->GetProcess());

  commit_params_->is_load_data_with_base_url = IsLoadDataWithBaseURL();
  commit_params_->origin_to_commit = origin_to_commit.value();

  if (!IsSameDocument()) {
#if DCHECK_IS_ON()
    DCHECK(is_safe_to_delete_);
    base::AutoReset<bool> resetter(&is_safe_to_delete_, false);
#endif
    GetDelegate()->ReadyToCommitNavigation(this);
  }

  // View-source URLs can't be prerendered or loaded in a fenced frame.
  if (IsInPrimaryMainFrame()) {
    NavigationEntry* entry = GetNavigationEntry();
    if (entry && entry->IsViewSourceMode()) {
      // Put the renderer in view source mode.
      GetRenderFrameHost()->GetAssociatedLocalFrame()->EnableViewSourceMode();
    }
  }

  // For fenced frames, update the mapped URL to be the URL from navigation
  // commit (after redirects), because we want future same-origin checks to be
  // performed with respect to the first origin committed in the fenced frame.
  if (is_embedder_initiated_fenced_frame_navigation_) {
    // In certain circumstances, the FencedFrameProperties will not have a
    // mapped url.
    // * The initial about:blank navigation in a fenced frame.
    // In those cases, we skip this step.
    if (fenced_frame_properties_.has_value() &&
        fenced_frame_properties_->mapped_url().has_value()) {
      fenced_frame_properties_->UpdateMappedURL(GetURL());
    }

    // For fenced frames with flexible permissions, pass in information needed
    // to build a replica of the embedder's permissions policies. This does not
    // happen for URN iframes as they can get their embedder's permissions
    // policies directly in the renderer.
    if (base::FeatureList::IsEnabled(
            blink::features::kFencedFramesLocalUnpartitionedDataAccess) &&
        GetNavigatingFrameType() == FrameType::kFencedFrameRoot &&
        fenced_frame_properties_->effective_enabled_permissions().size() ==
            0u) {
      fenced_frame_properties_->UpdateParentParsedPermissionsPolicy(
          GetParentFrameOrOuterDocument()->GetPermissionsPolicy(),
          GetParentFrameOrOuterDocument()->GetLastCommittedOrigin());
    }
  }

  if (ready_to_commit_callback_for_testing_)
    std::move(ready_to_commit_callback_for_testing_).Run();
}

bool NavigationRequest::IsWaitingToCommit() {
  return state_ == READY_TO_COMMIT;
}

bool NavigationRequest::WasResourceHintsReceived() {
  DCHECK_GE(state_, WILL_PROCESS_RESPONSE)
      << "Should only be called after the response started";
  return was_resource_hints_received_;
}

bool NavigationRequest::IsPdf() {
  return is_pdf_;
}

bool NavigationRequest::IsLoadDataWithBaseURL() const {
  // A navigation is a loadDataWithBaseURL navigation if it's a successful
  // primary main frame navigation to a data: URL, and its base URL is valid.
  return IsInPrimaryMainFrame() && !DidEncounterError() &&
         common_params_->url.SchemeIs(url::kDataScheme) &&
         common_params_->base_url_for_data_url.is_valid();
}

url::Origin NavigationRequest::GetTentativeOriginAtRequestTime() {
  DCHECK_LT(state_, WILL_PROCESS_RESPONSE);
  return GetOriginForURLLoaderFactoryBeforeResponse(
      commit_params_->frame_policy.sandbox_flags);
}

std::optional<url::Origin> NavigationRequest::GetOriginToCommit() {
  return GetOriginForURLLoaderFactoryAfterResponse();
}

url::Origin NavigationRequest::GetOriginForURLLoaderFactoryBeforeResponse(
    network::mojom::WebSandboxFlags sandbox_flags) {
  // Calculate an approximation of the origin. The sandbox/csp are ignored.
  url::Origin origin = GetOriginForURLLoaderFactoryUnchecked();

  // Apply sandbox flags.
  // See https://html.spec.whatwg.org/#sandboxed-origin-browsing-context-flag
  // ```
  // The 'sandboxed origin browsing context flag' forces content into a unique
  // origin, thus preventing it from accessing other content from the same
  // origin.
  //
  // This flag also prevents script from reading from or writing to the
  // document.cookie IDL attribute, and blocks access to localStorage.
  // ```
  bool use_opaque_origin =
      (sandbox_flags & network::mojom::WebSandboxFlags::kOrigin) ==
      network::mojom::WebSandboxFlags::kOrigin;
  if (use_opaque_origin) {
    origin = origin.DeriveNewOpaqueOrigin();
  }

  return origin;
}

// TODO(crbug.com/40065692): Remove.
// Determine the relationship between the initiator and the current frame.
// `same`: they are the same frame.
// `ancestor`: the initiator is the ancestor of the navigating frame.
// `descendant`: the initiator is the descendant of the navigating frame.
// `other`: any other scenarios.
std::string DetermineInitiatorRelationship(RenderFrameHost* initiator_frame,
                                           RenderFrameHost* current_frame) {
  if (!current_frame || !initiator_frame) {
    return "other";
  }

  if (current_frame == initiator_frame) {
    return "same";
  }

  RenderFrameHost* rfh = current_frame;
  while (rfh) {
    rfh = rfh->GetParent();
    if (rfh == initiator_frame) {
      return "ancestor";
    }
  }

  rfh = initiator_frame;
  while (rfh) {
    rfh = rfh->GetParent();
    if (rfh == current_frame) {
      return "descendant";
    }
  }

  return "other";
}

std::optional<url::Origin>
NavigationRequest::GetOriginForURLLoaderFactoryAfterResponse() {
  // The origin to commit is not known until we get the final network response.
  DCHECK_GE(state_, WILL_PROCESS_RESPONSE);

  // Downloads and/or 204 responses don't commit anything - there is no frame to
  // commit in (and therefore there is no origin that will get committed and we
  // indicate this by returning `nullopt`).
  if (!response_should_be_rendered_) {
    return std::nullopt;
  }

  if (IsSameDocument() || IsPageActivation()) {
    CHECK(HasRenderFrameHost());
    return GetRenderFrameHost()->GetLastCommittedOrigin();
  }

  url::Origin origin =
      GetOriginForURLLoaderFactoryBeforeResponse(SandboxFlagsToCommit());

  SCOPED_CRASH_KEY_BOOL("Bug1454273", "is_in_main_frame", IsInMainFrame());
  SCOPED_CRASH_KEY_STRING256(
      "Bug1454273", "current_origin",
      frame_tree_node_->current_origin().GetDebugString());
  RenderFrameHostImpl* parent = frame_tree_node_->parent();
  SCOPED_CRASH_KEY_STRING256(
      "Bug1454273", "parent_origin",
      parent ? parent->GetLastCommittedOrigin().GetDebugString() : "");
  // `outer_doc` is only set when `parent` is null.
  RenderFrameHostImpl* outer_doc =
      parent ? nullptr : GetParentFrameOrOuterDocument();
  SCOPED_CRASH_KEY_STRING256(
      "Bug1454273", "outer_doc_origin",
      outer_doc ? outer_doc->GetLastCommittedOrigin().GetDebugString() : "");
  // `embedder` is only set when both `parent` and `outer_doc` are null.
  RenderFrameHostImpl* embedder =
      (parent || outer_doc)
          ? nullptr
          : frame_tree_node()->GetParentOrOuterDocumentOrEmbedder();
  SCOPED_CRASH_KEY_STRING256(
      "Bug1454273", "embedder_origin",
      embedder ? embedder->GetLastCommittedOrigin().GetDebugString() : "");

  RenderFrameHost* initiator_rfh = GetInitiatorDocumentRenderFrameHost();
  SCOPED_CRASH_KEY_STRING256(
      "Bug1454273", "initiator_origin",
      initiator_rfh ? initiator_rfh->GetLastCommittedOrigin().GetDebugString()
                    : "");
  SCOPED_CRASH_KEY_STRING32(
      "Bug1454273", "initiator_relationship",
      DetermineInitiatorRelationship(initiator_rfh,
                                     frame_tree_node_->current_frame_host()));

  // MHTML documents should commit as an opaque origin. They should not be able
  // to make network request on behalf of the real origin.
  // TODO(crbug.com/370979008): Migrate to CHECK.
  DUMP_WILL_BE_CHECK(!IsMhtmlOrSubframe() || origin.opaque());

  // If the target of this navigation will be rendered in a RenderFrameHost,
  // then verify that the chosen origin is allowed to be accessed from that
  // process.
  //
  // Note that GetRenderFrameHost() only allows retrieving the RenderFrameHost
  // once it has been set for this navigation. This happens either at
  // WillProcessResponse time for regular navigations or at WillFailRequest time
  // for error pages.
  //
  // There are some exceptions where this check must be skipped:
  // * Some error pages may commit in an error process that allows many origins.
  // * MHTML iframes can load documents from any origin, no matter the current
  //   policy of the process being used. This is because the content is loaded
  //   from the MHTML archive within the process. There are no data loaded from
  //   the network.
  if (HasRenderFrameHost() &&
      !GetRenderFrameHost()->ShouldBypassSecurityChecksForErrorPage(this) &&
      !IsForMhtmlSubframe()) {
    int process_id = GetRenderFrameHost()->GetProcess()->GetDeprecatedID();
    auto* policy = ChildProcessSecurityPolicyImpl::GetInstance();
    CHECK(policy->CanAccessOrigin(
        process_id, origin,
        ChildProcessSecurityPolicyImpl::AccessType::kCanCommitNewOrigin));
  }

  return origin;
}

void NavigationRequest::WriteIntoTrace(
    perfetto::TracedProto<TraceProto> ctx) const {
  ctx->set_navigation_id(navigation_id_);
  ctx->set_has_committed(HasCommitted());
  ctx->set_is_error_page(IsErrorPage());
  ctx.Set(TraceProto::kFrameTreeNode, frame_tree_node_);
  if (state_ >= WILL_PROCESS_RESPONSE)
    ctx.Set(TraceProto::kRenderFrameHost, GetRenderFrameHost());

  perfetto::TracedDictionary dict = std::move(ctx).AddDebugAnnotations();
  dict.Add("url", common_params_->url);
  dict.Add("net_error", net_error_);
  dict.Add("browser_initiated", commit_params_->is_browser_initiated);
  dict.Add("from_begin_navigation", from_begin_navigation_);
  dict.Add("is_synchronous_renderer_commit", is_synchronous_renderer_commit_);
  dict.Add("reload_type", reload_type_);
  dict.Add("state", state_);
  dict.Add("navigation_type", common_params_->navigation_type);

  if (IsServedFromBackForwardCache()) {
    dict.Add("served_from_bfcache", true);
    dict.Add("rfh_restored_from_bfcache",
             GetRenderFrameHostRestoredFromBackForwardCache());
  }

  if (prerender_frame_tree_node_id_.has_value()) {
    dict.Add("prerender_frame_tree_node_id",
             prerender_frame_tree_node_id_.value());
  }
}

bool NavigationRequest::SetNavigationTimeout(base::TimeDelta timeout) {
  // Setting a navigation-level timeout isn't implemented yet for other states,
  // as the `loader_` must already be created. This means that callers like
  // NavigationThrottles should only call SetNavigationTimeout from
  // WillRedirectRequest(). If other use cases come up that need to set this
  // timeout at other points in the NavigationRequest lifecycle, one possible
  // solution could be to have the NavigationRequest hold the timeout value
  // temporarily until it creates the `loader_` in OnStartChecksCompleted().
  DCHECK_EQ(state_, WILL_REDIRECT_REQUEST);
  if (loader_)
    return loader_->SetNavigationTimeout(timeout);
  return false;
}

void NavigationRequest::CancelNavigationTimeout() {
  if (loader_) {
    loader_->CancelNavigationTimeout();
  }
}

void NavigationRequest::SetAllowCookiesFromBrowser(
    bool allow_cookies_from_browser) {
  allow_cookies_from_browser_ = allow_cookies_from_browser;
}

void NavigationRequest::GetResponseBody(ResponseBodyCallback callback) {
  CHECK_GE(state_, WILL_PROCESS_RESPONSE)
      << "The response body should only be requested after the response body "
         "data pipe is received from the network stack.";
  CHECK(processing_navigation_throttle_ || IsDeferred());
  CHECK(response_body_callback_.is_null());
  CHECK(callback);
  response_body_callback_ = std::move(callback);
  was_get_response_body_called_ = true;

  CHECK(!response_body_watcher_);
  response_body_watcher_ = std::make_unique<mojo::SimpleWatcher>(
      FROM_HERE, mojo::SimpleWatcher::ArmingPolicy::MANUAL,
      base::SequencedTaskRunner::GetCurrentDefault());
  response_body_watcher_->Watch(
      response_body(),
      MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED,
      base::BindRepeating(&NavigationRequest::OnResponseBodyReady,
                          weak_factory_.GetWeakPtr()));
  response_body_watcher_->ArmOrNotify();
}

void NavigationRequest::RenderProcessBlockedStateChanged(bool blocked) {
  if (blocked)
    StopCommitTimeout();
  else
    RestartCommitTimeout();
}

void NavigationRequest::StopCommitTimeout() {
  commit_timeout_timer_.Stop();
  render_process_blocked_state_changed_subscription_ = {};
  GetRenderFrameHost()->GetRenderWidgetHost()->RendererIsResponsive();
}

void NavigationRequest::RestartCommitTimeout() {
  commit_timeout_timer_.Stop();
  if (state_ >= DID_COMMIT)
    return;

  RenderProcessHost* renderer_host =
      GetRenderFrameHost()->GetRenderWidgetHost()->GetProcess();
  if (!render_process_blocked_state_changed_subscription_) {
    render_process_blocked_state_changed_subscription_ =
        renderer_host->RegisterBlockStateChangedCallback(base::BindRepeating(
            &NavigationRequest::RenderProcessBlockedStateChanged,
            base::Unretained(this)));
  }
  if (!renderer_host->IsBlocked()) {
    commit_timeout_timer_.Start(
        FROM_HERE, g_commit_timeout,
        base::BindOnce(&NavigationRequest::OnCommitTimeout,
                       weak_factory_.GetWeakPtr()));
  }
}

void NavigationRequest::OnCommitTimeout() {
  DCHECK_EQ(READY_TO_COMMIT, state_);
  render_process_blocked_state_changed_subscription_ = {};

  GetRenderFrameHost()->GetRenderWidgetHost()->RendererIsUnresponsive(
      RenderWidgetHostImpl::RendererIsUnresponsiveReason::
          kNavigationRequestCommitTimeout,
      base::BindRepeating(&NavigationRequest::RestartCommitTimeout,
                          weak_factory_.GetWeakPtr()));
}

// static
void NavigationRequest::SetCommitTimeoutForTesting(
    const base::TimeDelta& timeout) {
  if (timeout.is_zero())
    g_commit_timeout = kDefaultCommitTimeout;
  else
    g_commit_timeout = timeout;
}

void NavigationRequest::SetPrerenderActivationNavigationState(
    std::unique_ptr<NavigationEntryImpl> prerender_navigation_entry,
    const blink::mojom::FrameReplicationState& replication_state) {
  DCHECK(IsPrerenderedPageActivation());
  if (!prerender_navigation_state_) {
    prerender_navigation_state_.emplace();
  }
  prerender_navigation_state_->prerender_navigation_entry =
      std::move(prerender_navigation_entry);

  // Store the replication state of the prerender main frame to copy the
  // necessary parameters from it during activation commit and compare with the
  // final replication state after activation to ensure it hasn't changed.
  // TODO(crbug.com/40192974): This will need to be removed when the
  // Browsing Instance Frame State is implemented.
  prerender_navigation_state_->prerender_main_frame_replication_state =
      replication_state;
}

void NavigationRequest::RemoveRequestHeader(const std::string& header_name) {
  DCHECK(state_ == WILL_REDIRECT_REQUEST);
  removed_request_headers_.push_back(header_name);
}

void NavigationRequest::SetRequestHeader(const std::string& header_name,
                                         const std::string& header_value) {
  DCHECK(state_ == WILL_START_REQUEST || state_ == WILL_REDIRECT_REQUEST);
  modified_request_headers_.SetHeader(header_name, header_value);
}

void NavigationRequest::SetLCPPNavigationHint(
    const blink::mojom::LCPCriticalPathPredictorNavigationTimeHint& hint) {
  DCHECK(WILL_START_REQUEST == state_ || WILL_REDIRECT_REQUEST == state_)
      << state_;
  commit_params_->lcpp_hint = hint.Clone();
}

const blink::mojom::LCPCriticalPathPredictorNavigationTimeHintPtr&
NavigationRequest::GetLCPPNavigationHint() {
  return commit_params_->lcpp_hint;
}

const net::HttpResponseHeaders* NavigationRequest::GetResponseHeaders() {
  return response_head_.get() ? response_head_->headers.get() : nullptr;
}

mojom::DidCommitProvisionalLoadParamsPtr
NavigationRequest::MakeDidCommitProvisionalLoadParamsForActivation() {
  // Use the DidCommitProvisionalLoadParams last used to commit the frame being
  // restored as a starting point.
  mojom::DidCommitProvisionalLoadParamsPtr params =
      GetRenderFrameHost()->GetPage().TakeLastCommitParams();

  // Params must have been set when the RFH being restored from the cache last
  // navigated.
  CHECK(params);

  if (IsPrerenderedPageActivation()) {
    CHECK(!prerender_navigation_utils::IsDisallowedHttpResponseCode(
        params->http_status_code));
  } else {
    DCHECK_EQ(params->http_status_code, net::HTTP_OK);
  }
  DCHECK_EQ(params->url_is_unreachable, false);

  DCHECK_EQ(params->post_id, -1);
  params->navigation_token = commit_params().navigation_token;
  DCHECK_EQ(params->url, common_params().url);
  params->should_update_history = true;
  DCHECK_EQ(params->method, common_params().method);
  params->item_sequence_number = frame_entry_item_sequence_number_;
  params->document_sequence_number = frame_entry_document_sequence_number_;
  params->transition = ui::PageTransitionFromInt(common_params().transition);
  params->history_list_was_cleared = false;
  params->request_id = GetGlobalRequestID().request_id;

  return params;
}

mojom::DidCommitProvisionalLoadParamsPtr
NavigationRequest::MakeDidCommitProvisionalLoadParamsForBFCacheRestore() {
  // Start with the provisional load parameters shared between all page
  // activation types.
  mojom::DidCommitProvisionalLoadParamsPtr params =
      MakeDidCommitProvisionalLoadParamsForActivation();

  // Add bfcache-specific provisional load params:
  params->did_create_new_entry = false;
  params->page_state =
      blink::PageState::CreateFromEncodedData(commit_params().page_state);
  return params;
}

mojom::DidCommitProvisionalLoadParamsPtr
NavigationRequest::MakeDidCommitProvisionalLoadParamsForPrerenderActivation() {
  DCHECK(IsPrerenderedPageActivation());

  // Start with the provisional load parameters shared between all page
  // activation types.
  mojom::DidCommitProvisionalLoadParamsPtr params =
      MakeDidCommitProvisionalLoadParamsForActivation();
  // TODO(crbug.com/40169536): Investigate when a new entry should
  // replace an old one when prerendering a page.
  params->did_create_new_entry = true;

  FrameNavigationEntry* frame_entry =
      prerender_navigation_state_->prerender_navigation_entry->GetFrameEntry(
          frame_tree_node());

  // Prerendering already has a navigation entry which has correct PageState.
  // Set params->page_state accordingly to ensure that DCHECKs expecting them to
  // match are happy.
  // Note: |params| are using last commit params as a basis (via
  // TakeLastCommitParams call), which have a page state from the last commit,
  // but the page state might have been updated since the last commit.
  params->page_state = frame_entry->page_state();

  if (base::FeatureList::IsEnabled(kPrerenderFixSequenceNumbers)) {
    // These sequence numbers should also be copied from the prerendering
    // navigation entry.
    CHECK_NE(frame_entry->item_sequence_number(), -1);
    CHECK_NE(frame_entry->document_sequence_number(), -1);
    params->item_sequence_number = frame_entry->item_sequence_number();
    params->document_sequence_number = frame_entry->document_sequence_number();
  }

  // insecure_request_policy field of the replication state is set during the
  // navigation commit based on DidCommitProvisionalLoadParams. As prerendering
  // activates existing page, copy its main frame replication state to ensure
  // that the effective replication state doesn't change after activation.
  // TODO(crbug.com/40192974): replication state should belong to the Browsing
  // Instance Frame State.
  params->insecure_request_policy =
      prerender_navigation_state_->prerender_main_frame_replication_state
          .insecure_request_policy;
  return params;
}

bool NavigationRequest::IsExternalProtocol() {
  return !GetContentClient()->browser()->IsHandledURL(common_params_->url);
}

bool NavigationRequest::IsSignedExchangeInnerResponse() {
  return response() && response()->is_signed_exchange_inner_response;
}

net::IPEndPoint NavigationRequest::GetSocketAddress() {
  DCHECK_GE(state_, WILL_PROCESS_RESPONSE);
  return response() ? response()->remote_endpoint : net::IPEndPoint();
}

bool NavigationRequest::HasCommitted() const {
  return state_ == DID_COMMIT || state_ == DID_COMMIT_ERROR_PAGE;
}

bool NavigationRequest::IsErrorPage() const {
  return state_ == DID_COMMIT_ERROR_PAGE;
}

bool NavigationRequest::DidEncounterError() const {
  return net_error_ != net::OK;
}

net::HttpConnectionInfo NavigationRequest::GetConnectionInfo() {
  return response() ? response()->connection_info : net::HttpConnectionInfo();
}

bool NavigationRequest::IsInMainFrame() const {
  return frame_tree_node()->IsMainFrame();
}

RenderFrameHostImpl* NavigationRequest::GetParentFrame() {
  return IsInMainFrame() ? nullptr : frame_tree_node()->parent();
}

RenderFrameHostImpl* NavigationRequest::GetParentFrameOrOuterDocument() {
  return frame_tree_node()->GetParentOrOuterDocument();
}

bool NavigationRequest::IsInPrimaryMainFrame() const {
  return GetNavigatingFrameType() == FrameType::kPrimaryMainFrame;
}

bool NavigationRequest::IsInOutermostMainFrame() const {
  switch (GetNavigatingFrameType()) {
    case FrameType::kPrimaryMainFrame:
    case FrameType::kPrerenderMainFrame:
    case FrameType::kGuestMainFrame:
      return true;
    case FrameType::kSubframe:
    case FrameType::kFencedFrameRoot:
      return false;
  }
}

bool NavigationRequest::IsInPrerenderedMainFrame() const {
  return GetNavigatingFrameType() == FrameType::kPrerenderMainFrame;
}

bool NavigationRequest::IsPrerenderedPageActivation() const {
  CHECK(prerender_frame_tree_node_id_.has_value());
  return !prerender_frame_tree_node_id_.value().is_null();
}

bool NavigationRequest::IsInFencedFrameTree() const {
  return frame_tree_node()->IsInFencedFrameTree();
}

bool NavigationRequest::IsGuestViewMainFrame() const {
  return GetNavigatingFrameType() == content::FrameType::kGuestMainFrame;
}

FrameType NavigationRequest::GetNavigatingFrameType() const {
  return frame_tree_node()->GetFrameType();
}

FrameTreeNodeId NavigationRequest::GetFrameTreeNodeId() {
  return frame_tree_node()->frame_tree_node_id();
}

bool NavigationRequest::WasResponseCached() {
  return response() && response()->was_fetched_via_cache;
}

bool NavigationRequest::NetworkAccessed() {
  return response() && response()->network_accessed;
}

bool NavigationRequest::HasPrefetchedAlternativeSubresourceSignedExchange() {
  return !commit_params_->prefetched_signed_exchanges.empty();
}

int64_t NavigationRequest::GetNavigationId() const {
  return navigation_id_;
}

ukm::SourceId NavigationRequest::GetNextPageUkmSourceId() {
  // If the navigation is restoring from back-forward cache, the UKM id
  // will get restored, too.
  if (IsServedFromBackForwardCache()) {
    return GetRenderFrameHostRestoredFromBackForwardCache()
        ->GetPageUkmSourceId();
  }

  // If this is the same document or a subframe navigation (i.e. iframe or
  // fenced frame), the UKM id will not change from it.
  if (IsSameDocument() || !IsInMainFrame() || IsInFencedFrameTree())
    return previous_page_ukm_source_id_;

  return ukm::ConvertToSourceId(navigation_id_,
                                ukm::SourceIdObj::Type::NAVIGATION_ID);
}

const GURL& NavigationRequest::GetURL() {
  return common_params().url;
}

SiteInstanceImpl* NavigationRequest::GetStartingSiteInstance() {
  return starting_site_instance_.get();
}

SiteInstanceImpl* NavigationRequest::GetSourceSiteInstance() {
  return source_site_instance_.get();
}

bool NavigationRequest::IsRendererInitiated() {
  return !commit_params_->is_browser_initiated;
}

blink::mojom::NavigationInitiatorActivationAndAdStatus
NavigationRequest::GetNavigationInitiatorActivationAndAdStatus() {
  return begin_params_->initiator_activation_and_ad_status;
}

bool NavigationRequest::IsSameOrigin() {
  DCHECK(HasCommitted());
  return same_origin_;
}

bool NavigationRequest::WasServerRedirect() {
  return was_redirected_;
}

const std::vector<GURL>& NavigationRequest::GetRedirectChain() {
  return redirect_chain_;
}

base::TimeTicks NavigationRequest::NavigationStart() {
  return common_params().navigation_start;
}

base::TimeTicks NavigationRequest::NavigationInputStart() {
  return common_params().input_start;
}

const NavigationHandleTiming& NavigationRequest::GetNavigationHandleTiming() {
  return navigation_handle_timing_;
}

bool NavigationRequest::IsPost() {
  return common_params().method == "POST";
}

std::string NavigationRequest::GetRequestMethod() {
  return request_method_;
}

const blink::mojom::Referrer& NavigationRequest::GetReferrer() {
  return *sanitized_referrer_;
}

void NavigationRequest::SetReferrer(blink::mojom::ReferrerPtr referrer) {
  DCHECK(state_ == WILL_START_REQUEST || state_ == WILL_REDIRECT_REQUEST);
  sanitized_referrer_ =
      Referrer::SanitizeForRequest(common_params_->url, *referrer);
  common_params_->referrer = sanitized_referrer_.Clone();
}

bool NavigationRequest::HasUserGesture() {
  return common_params().has_user_gesture;
}

ui::PageTransition NavigationRequest::GetPageTransition() {
  return ui::PageTransitionFromInt(common_params().transition);
}

NavigationUIData* NavigationRequest::GetNavigationUIData() {
  return navigation_ui_data_.get();
}

net::Error NavigationRequest::GetNetErrorCode() {
  return net_error_;
}

int NavigationRequest::GetNetExtendedErrorCode() {
  return extended_error_code_;
}

std::optional<ErrorNavigationTrigger>
NavigationRequest::GetErrorNavigationTrigger() {
  return error_navigation_trigger_;
}

// The RenderFrameHost that will commit the navigation or an error page.
// This is computed when the response is received, or when the navigation
// fails and error page should be displayed.
RenderFrameHostImpl* NavigationRequest::GetRenderFrameHost() const {
  // Only allow the RenderFrameHost to be retrieved once it has been set for
  // this navigation. This will happens either at WillProcessResponse time for
  // regular navigations or at WillFailRequest time for error pages.
  // NavigationRequests created for synchronous renderer commits (see
  // documentation for |is_synchronous_renderer_commit_|) have a
  // RenderFrameHost available from the start.
  if (!is_synchronous_renderer_commit()) {
    CHECK_GE(state_, WILL_PROCESS_RESPONSE)
        << "This accessor should only be called after a RenderFrameHost has "
           "been picked for this navigation.";
  }
  static_assert(WILL_FAIL_REQUEST > WILL_PROCESS_RESPONSE,
                "WillFailRequest state should come after WillProcessResponse");
  if (HasRenderFrameHost()) {
    return &*render_frame_host_.value();
  }
  return nullptr;
}

NavigationRequest::AssociatedRenderFrameHostType
NavigationRequest::GetAssociatedRFHType() const {
  // `associated_rfh_type_` might not be accurate after the navigation had
  // moved to the RFH. This is because if another navigation had committed and
  // committed a new RFH that replaces the current RFH, the
  // `associated_rfh_type_` might be stale and needs to be updated. However,
  // we only update the value for non-pending commit navigations (i.e. the
  // NavigationRequest owned by the FrameTreeNode). See the comments in
  // `RenderFrameHostManager::CommitPendingIfNecessary()` for more details.
  CHECK(state_ < READY_TO_COMMIT || state_ == WILL_FAIL_REQUEST)
      << "Use GetRenderFrameHost() instead when the final RenderFrameHost "
         "for the navigation has been picked";
  return associated_rfh_type_;
}

void NavigationRequest::SetAssociatedRFHType(
    AssociatedRenderFrameHostType type) {
  if (associated_rfh_type_ != AssociatedRenderFrameHostType::NONE &&
      type == AssociatedRenderFrameHostType::NONE) {
    // If we're transitioning to "NONE" when the previous state was not "NONE",
    // we might have called SetExpectedProcess() before, so reset it now.
    ResetExpectedProcess();
  }
  associated_rfh_type_ = type;
}

const net::HttpRequestHeaders& NavigationRequest::GetRequestHeaders() {
  if (!request_headers_) {
    request_headers_.emplace();
    request_headers_->AddHeadersFromString(begin_params_->headers);
  }
  return *request_headers_;
}

const std::optional<net::SSLInfo>& NavigationRequest::GetSSLInfo() {
  return ssl_info_;
}

const std::optional<net::AuthChallengeInfo>&
NavigationRequest::GetAuthChallengeInfo() {
  return auth_challenge_info_;
}

net::ResolveErrorInfo NavigationRequest::GetResolveErrorInfo() {
  return resolve_error_info_;
}

net::IsolationInfo NavigationRequest::GetIsolationInfo() {
  if (isolation_info_)
    return isolation_info_.value();

  // TODO(crbug.com/40634002): Consider changing this code to copy an origin
  // instead of creating one from a URL which lacks opacity information.
  return frame_tree_node_->current_frame_host()
      ->ComputeIsolationInfoForNavigation(
          common_params_->url, is_credentialless(), ComputeFencedFrameNonce());
}

bool NavigationRequest::HasSubframeNavigationEntryCommitted() {
  DCHECK(!frame_tree_node_->IsMainFrame());
  DCHECK(state_ == DID_COMMIT || state_ == DID_COMMIT_ERROR_PAGE);
  return subframe_entry_committed_;
}

bool NavigationRequest::DidReplaceEntry() {
  DCHECK(state_ == DID_COMMIT || state_ == DID_COMMIT_ERROR_PAGE);
  return did_replace_entry_;
}

bool NavigationRequest::ShouldUpdateHistory() {
  DCHECK(state_ == DID_COMMIT || state_ == DID_COMMIT_ERROR_PAGE);
  return should_update_history_;
}

const GURL& NavigationRequest::GetPreviousPrimaryMainFrameURL() {
  DCHECK(IsInPrimaryMainFrame() ||
         GetParentFrame() && GetParentFrame()->GetPage().IsPrimary());
  return GetPreviousMainFrameURL();
}

const GURL& NavigationRequest::GetPreviousMainFrameURL() const {
  DCHECK(state_ == DID_COMMIT || state_ == DID_COMMIT_ERROR_PAGE);
  return previous_main_frame_url_;
}

bool NavigationRequest::WasStartedFromContextMenu() {
  return common_params().started_from_context_menu;
}

const GURL& NavigationRequest::GetSearchableFormURL() {
  return begin_params().searchable_form_url;
}

const std::string& NavigationRequest::GetSearchableFormEncoding() {
  return begin_params().searchable_form_encoding;
}

ReloadType NavigationRequest::GetReloadType() const {
  return reload_type_;
}

RestoreType NavigationRequest::GetRestoreType() const {
  return restore_type_;
}

const GURL& NavigationRequest::GetBaseURLForDataURL() {
  return common_params().base_url_for_data_url;
}

const GlobalRequestID& NavigationRequest::GetGlobalRequestID() {
  DCHECK_GE(state_, WILL_PROCESS_RESPONSE);
  return request_id_;
}

bool NavigationRequest::IsDownload() {
  return is_download_;
}

bool NavigationRequest::IsFormSubmission() {
  return begin_params().is_form_submission;
}

bool NavigationRequest::WasInitiatedByLinkClick() {
  return begin_params().was_initiated_by_link_click;
}

const std::string& NavigationRequest::GetHrefTranslate() {
  return common_params().href_translate;
}

const std::optional<blink::Impression>& NavigationRequest::GetImpression() {
  return begin_params().impression;
}

const std::optional<blink::LocalFrameToken>&
NavigationRequest::GetInitiatorFrameToken() {
  return initiator_frame_token_;
}

int NavigationRequest::GetInitiatorProcessId() {
  return initiator_process_id_;
}

const std::optional<url::Origin>& NavigationRequest::GetInitiatorOrigin() {
  return common_params().initiator_origin;
}

const std::optional<GURL>& NavigationRequest::GetInitiatorBaseUrl() {
  return common_params().initiator_base_url;
}

const std::vector<std::string>& NavigationRequest::GetDnsAliases() {
  static const base::NoDestructor<std::vector<std::string>> emptyvector_result;
  return response_head_ ? response_head_->dns_aliases : *emptyvector_result;
}

bool NavigationRequest::IsSameProcess() {
  return is_same_process_;
}

NavigationEntry* NavigationRequest::GetNavigationEntry() const {
  if (nav_entry_id_ == 0)
    return nullptr;

  return GetNavigationController()->GetEntryWithUniqueIDIncludingPending(
      nav_entry_id_);
}

int NavigationRequest::GetNavigationEntryOffset() const {
  return navigation_entry_offset_;
}

GlobalRenderFrameHostId NavigationRequest::GetPreviousRenderFrameHostId() {
  if (previous_render_frame_host_id_ != GlobalRenderFrameHostId()) {
    CHECK_GE(state_, READY_TO_COMMIT);
    // If `previous_render_frame_host_id_` is set to a non-default value, then
    // the navigation had committed and potentially replaced the previous
    // "current RenderFrameHost", so we return the saved value of that previous
    // RenderFrameHost's ID here.
    return previous_render_frame_host_id_;
  }

  // The navigation hasn't committed yet, so the previous RenderFrameHost is
  // still the current RenderFrameHost. Note that this might be different from
  // the current RFH at NavigationRequest construction time (whose FTN id value
  // is saved in `current_render_frame_host_id_at_construction_`), if another
  // navigation caused a new RenderFrameHost to be committed while this
  // navigation is in progress.
  if (frame_tree_node_->current_frame_host()) {
    return frame_tree_node_->current_frame_host()->GetGlobalId();
  } else {
    // It's possible for `frame_tree_node_->current_frame_host()` to be null if
    // we're in the middle of destructing the navigating FrameTreeNode. In this
    // case, just return `current_render_frame_host_id_at_construction_`.
    return current_render_frame_host_id_at_construction_;
  }
}

ChildProcessId NavigationRequest::GetExpectedRenderProcessHostId() {
  DCHECK_LT(state_, READY_TO_COMMIT);
  return expected_render_process_host_id_;
}

void NavigationRequest::SetIsOverridingUserAgent(bool override_ua) {
  // Only add specific headers when creating a NavigationRequest before the
  // network request is made, not at commit time.
  if (is_synchronous_renderer_commit_)
    return;

  // This code assumes it is only called from DidStartNavigation().
  DCHECK(!ua_change_requires_reload_);

  commit_params_->is_overriding_user_agent = override_ua;
  // The new document, created by this navigation, will be honoring the new
  // value. It will be reflected into its NavigationEntry's when committing the
  // new document at DidCommitNavigation time.

  net::HttpRequestHeaders headers;
  headers.AddHeadersFromString(begin_params_->headers);
  BrowserContext* browser_context =
      frame_tree_node_->navigator().controller().GetBrowserContext();
  ClientHintsControllerDelegate* client_hints_delegate =
      browser_context->GetClientHintsControllerDelegate();
  if (client_hints_delegate) {
    UpdateNavigationRequestClientUaHeaders(
        GetTentativeOriginAtRequestTime(), client_hints_delegate,
        is_overriding_user_agent(), frame_tree_node_, &headers,
        common_params_->url);
  }
  headers.SetHeader(
      net::HttpRequestHeaders::kUserAgent,
      ComputeUserAgentValue(headers, GetUserAgentOverride(), browser_context));
  begin_params_->headers = headers.ToString();
  // |request_headers_| comes from |begin_params_|. Clear |request_headers_| now
  // so that if |request_headers_| are needed, they will be updated.
  request_headers_.reset();
}

void NavigationRequest::SetSilentlyIgnoreErrors() {
  silently_ignore_errors_ = true;
}

void NavigationRequest::SetVisitedLinkSalt(uint64_t salt) {
  commit_params_->visited_link_salt = salt;
}

// static
NavigationRequest* NavigationRequest::From(NavigationHandle* handle) {
  return static_cast<NavigationRequest*>(handle);
}

// static
ReloadType NavigationRequest::NavigationTypeToReloadType(
    blink::mojom::NavigationType type) {
  if (type == blink::mojom::NavigationType::RELOAD)
    return ReloadType::NORMAL;
  if (type == blink::mojom::NavigationType::RELOAD_BYPASSING_CACHE)
    return ReloadType::BYPASSING_CACHE;
  return ReloadType::NONE;
}

bool NavigationRequest::IsNavigationStarted() const {
  return is_navigation_started_;
}

bool NavigationRequest::RequiresInitiatorBasedSourceSiteInstance() const {
  // Browser-initiated navigations can supply an initiator origin without having
  // an associated source SiteInstance (e.g. Android intents handled by Chrome).
  // However, the context menu is a case in which we should have one, so it
  // should still require a source SiteInstance.
  if (commit_params_->is_browser_initiated &&
      !common_params().started_from_context_menu) {
    return false;
  }

  // data: URLs, about:blank and empty URL (which are treated the same as
  // about:blank) navigations that have initiator origins require a source
  // SiteInstance.
  const bool is_data_or_about_or_empty =
      common_params_->url.SchemeIs(url::kDataScheme) ||
      common_params_->url.IsAboutBlank() || common_params_->url.is_empty();

  const bool has_valid_initiator =
      common_params_->initiator_origin &&
      common_params_->initiator_origin->GetTupleOrPrecursorTupleIfOpaque()
          .IsValid();

  return is_data_or_about_or_empty && has_valid_initiator &&
         !dest_site_instance_;
}

void NavigationRequest::SetSourceSiteInstanceToInitiatorIfNeeded() {
  if (source_site_instance_ || !RequiresInitiatorBasedSourceSiteInstance())
    return;

  // TODO(crbug.com/349972037): Reconsider source SiteInstance usage. E.g. if
  // the initiator is sandboxed, the source SiteInstance we get here isn't and
  // they don't technically match.
  const auto tuple =
      common_params_->initiator_origin->GetTupleOrPrecursorTupleIfOpaque();
  source_site_instance_ = static_cast<SiteInstanceImpl*>(
      frame_tree_node_->current_frame_host()
          ->GetSiteInstance()
          ->GetRelatedSiteInstance(tuple.GetURL())
          .get());
}

void NavigationRequest::ForceEnableOriginTrials(
    const std::vector<std::string>& trials) {
  DCHECK(!HasCommitted());
  commit_params_->force_enabled_origin_trials = trials;
}

network::CrossOriginEmbedderPolicy
NavigationRequest::ComputeCrossOriginEmbedderPolicy() {
  const auto& url = common_params_->url;
  // Fenced Frames should respect the outer frame's COEP.
  RenderFrameHostImpl* const parent = GetParentFrameOrOuterDocument();
  bool is_fenced_frame_from_local_scheme =
      GetNavigatingFrameType() == FrameType::kFencedFrameRoot &&
      (url.SchemeIsBlob() || url.SchemeIs(url::kDataScheme));

  // Some special URLs not loaded using the network inherit the
  // Cross-Origin-Embedder-Policy header from their parent.
  if (parent && (GetContentClient()
                     ->browser()
                     ->ShouldInheritCrossOriginEmbedderPolicyImplicitly(url) ||
                 is_fenced_frame_from_local_scheme)) {
    return parent->cross_origin_embedder_policy();
  }

  // Compute "topLevelCreationURL" for COEP and secure context.
  //
  // [spec]: https://html.spec.whatwg.org/C/#initialise-the-document-object
  // 3. Let creationURL be navigationParams's response's URL.
  // 5. If browsingContext is still on its initial about:blank Document [...]
  // 6. Otherwise:
  // 6.6. Let topLevelCreationURL be creationURL.
  // 6.8. If browsingContext is not a top-level browsing context, then:
  // 6.8.2. Set topLevelCreationURL to parentEnvironment's top-level creation
  //        URL.
  //
  // TODO(arthursonzogni): It would be good to clarify what
  // |topLevelCreationURL| means when loading FencedFrame//GuestView, and how it
  // should affect COEP.
  // Tracking bug:
  // - FencedFrame: https://crbug.com/1277430
  // - GuestView: XXX or slightly related https://crbug.com/1260747
  const GURL& top_level_creation_url = GetParentFrameOrOuterDocument()
                                           ? GetParentFrameOrOuterDocument()
                                                 ->GetOutermostMainFrame()
                                                 ->GetLastCommittedURL()
                                           : url;
  // [spec]: https://html.spec.whatwg.org/C/#obtain-an-embedder-policy
  //
  // 1. Let policy be a new embedder policy.
  // 2. If environment is a non-secure context, then return policy.
  if (network::IsUrlPotentiallyTrustworthy(top_level_creation_url)) {
    if (response_head_) {
      return response_head_->parsed_headers->cross_origin_embedder_policy;
    }
  }
  return network::CrossOriginEmbedderPolicy();
}

NavigationRequest::IntegrityPolicies
NavigationRequest::ComputeIntegrityPolicies() {
  IntegrityPolicies policies;
  if (!base::FeatureList::IsEnabled(
          network::features::kIntegrityPolicyScript)) {
    return policies;
  }
  if (response_head_ && response_head_->parsed_headers) {
    policies.enforced = response_head_->parsed_headers->integrity_policy;
    policies.report_only =
        response_head_->parsed_headers->integrity_policy_report_only;
  }
  return policies;
}

// [spec]:
// https://html.spec.whatwg.org/C/#check-a-navigation-response's-adherence-to-its-embedder-policy
//
// Return whether the child's |coep| is compatible with its parent's COEP. It
// also sends COEP reports if needed.
bool NavigationRequest::CheckResponseAdherenceToCoep(const GURL& url) {
  const auto& coep =
      policy_container_builder_->FinalPolicies().cross_origin_embedder_policy;

  // Fenced Frames should respect the outer frame's COEP.
  RenderFrameHostImpl* const parent = GetParentFrameOrOuterDocument();

  // [spec]: 1. If target is not a child browsing context, then return true.
  if (!parent)
    return true;

  // [spec]: 2. Let parentPolicy be target's container document's policy
  //            container's embedder policy.
  const auto& parent_coep = parent->cross_origin_embedder_policy();
  CrossOriginEmbedderPolicyReporter* parent_coep_reporter =
      parent->coep_reporter();

  // [spec]: 3. If parentPolicy's report-only value is compatible with
  // cross-origin isolation and responsePolicy's value is not, then queue a
  // cross-origin embedder policy inheritance violation [...].
  if (CoepBlockIframe(parent_coep.report_only_value, coep.value,
                      is_credentialless())) {
    if (parent_coep_reporter) {
      parent_coep_reporter->QueueNavigationReport(redirect_chain_[0],
                                                  /*report_only=*/true);
    }
  }

  // [spec]: 4. If parentPolicy's value is not compatible with cross-origin
  // isolation or responsePolicy's value is compatible with cross-origin
  // isolation, then return true.
  if (!CoepBlockIframe(parent_coep.value, coep.value, is_credentialless()))
    return true;

  // [spec]: 5 Queue a cross-origin embedder policy inheritance violation with
  // response, "navigation", parentPolicy's reporting endpoint, "enforce", and
  // target's container document's relevant settings object.
  if (parent_coep_reporter) {
    parent_coep_reporter->QueueNavigationReport(redirect_chain_[0],
                                                /*report_only=*/false);
  }

  // [spec]: 6. Return false.
  return false;
}

std::optional<network::mojom::BlockedByResponseReason>
NavigationRequest::EnforceCOEP() {
  // https://html.spec.whatwg.org/C/#check-a-navigation-response's-adherence-to-its-embedder-policy
  // Spec should be updated:
  // https://github.com/shivanigithub/fenced-frame/issues/11

  // Fenced frames should be treated as an embedded frame, thus COEP must apply.
  RenderFrameHostImpl* const parent_frame = GetParentFrameOrOuterDocument();
  if (!parent_frame) {
    return std::nullopt;
  }
  if (is_credentialless()) {
    return std::nullopt;
  }
  const auto& url = common_params_->url;
  // Some special URLs not loaded using the network are inheriting the
  // Cross-Origin-Embedder-Policy header from their parent.
  if (url.SchemeIsBlob() || url.SchemeIs(url::kDataScheme)) {
    return std::nullopt;
  }
  return network::CrossOriginResourcePolicy::IsNavigationBlocked(
      url, redirect_chain_[0], parent_frame->GetLastCommittedOrigin(),
      *response_head_, request_destination(),
      parent_frame->cross_origin_embedder_policy(),
      parent_frame->coep_reporter());
}

void NavigationRequest::CoopCoepSanityCheck() {
  // Same-document navigations simply reuse the current document and do not use
  // the PolicyContainer, which may contain erroneous information. For example
  // in pushState/popState history navigations. See https://crbug.com/1413081.
  if (IsSameDocument()) {
    return;
  }

  // Credentialless iframes allow frames to be crossOriginIsolated without ever
  // setting COEP, so the below check does not apply.
  if (is_credentialless_) {
    return;
  }

  const PolicyContainerPolicies& policies =
      policy_container_builder_->FinalPolicies();
  // Use GetParentFrameOrOuterDocument() to respect the outer frame's COEP for
  // now.
  network::mojom::CrossOriginOpenerPolicyValue coop_value =
      GetParentFrameOrOuterDocument()
          ? GetRenderFrameHost()
                ->GetOutermostMainFrame()
                ->cross_origin_opener_policy()
                .value
          : policies.cross_origin_opener_policy.value;

  if (coop_value ==
          network::mojom::CrossOriginOpenerPolicyValue::kSameOriginPlusCoep &&
      !CompatibleWithCrossOriginIsolated(
          policies.cross_origin_embedder_policy)) {
    NOTREACHED();
  }
}

bool NavigationRequest::IsFencedFrameRequiredPolicyFeatureAllowed(
    const url::Origin& origin,
    const network::mojom::PermissionsPolicyFeature feature) {
  const network::PermissionsPolicyFeatureList& feature_list =
      network::GetPermissionsPolicyFeatureList(origin);

  // Check if the outer document's permissions policies allow all of the
  // required policies.
  std::optional<const network::PermissionsPolicy::Allowlist>
      embedder_allowlist = GetParentFrameOrOuterDocument()
                               ->GetPermissionsPolicy()
                               ->GetAllowlistForFeatureIfExists(feature);
  if (embedder_allowlist && !embedder_allowlist->MatchesAll()) {
    return false;
  }

  // Check if the container policies to be committed allow all of the required
  // policies for `origin`. This means that the policy must be either
  // explicitly enabled for `origin`, or the policy must by default
  // be enabled for all origins. Note: because the policies have not been
  // read into a RenderFrameHost's permissions_policy_ yet, we need to check
  // the network::ParsedPermissionsPolicyDeclaration object directly.
  auto policy_iter = std::find_if(
      commit_params_->frame_policy.container_policy.begin(),
      commit_params_->frame_policy.container_policy.end(),
      [feature](const network::ParsedPermissionsPolicyDeclaration& d) {
        return d.feature == feature;
      });
  if (policy_iter == commit_params_->frame_policy.container_policy.end()) {
    return feature_list.at(feature) ==
           network::PermissionsPolicyFeatureDefault::EnableForAll;
  }

  return policy_iter->Contains(origin);
}

bool NavigationRequest::CheckPermissionsPoliciesForFencedFrames(
    const url::Origin& origin) {
  // These checks only apply to fenced frames.
  if (!frame_tree_node_->IsFencedFrameRoot())
    return true;

  const std::optional<FencedFrameProperties>& computed_fenced_frame_properties =
      ComputeFencedFrameProperties();

  // Permissions policies only need to be checked for fenced frames created from
  // an API like FLEDGE or Shared Storage.
  if (!computed_fenced_frame_properties) {
    return true;
  }

  // Check that all of the required policies for a new document with origin
  // `origin` in the fenced frame are allowed. This looks at the outer
  // document's policies and the "allow" attribute. Note that the document will
  // eventually only use the required policies without policy inheritance, so
  // extra policies defined in the outer document/"allow" attribute won't have
  // any effect.
  for (const network::mojom::PermissionsPolicyFeature feature :
       computed_fenced_frame_properties->effective_enabled_permissions()) {
    if (!IsFencedFrameRequiredPolicyFeatureAllowed(origin, feature)) {
      const blink::PermissionsPolicyFeatureToNameMap& feature_to_name_map =
          blink::GetPermissionsPolicyFeatureToNameMap();
      const std::string feature_string(feature_to_name_map.at(feature));
      frame_tree_node_->current_frame_host()->AddMessageToConsole(
          blink::mojom::ConsoleMessageLevel::kError,
          base::StringPrintf(
              "Refused to frame '%s' as a fenced frame because permissions "
              "policy '%s' is not allowed for the frame's origin.",
              origin.Serialize().c_str(), feature_string.c_str()));
      return false;
    }
  }
  return true;
}

std::unique_ptr<viz::PeakGpuMemoryTracker>
NavigationRequest::TakePeakGpuMemoryTracker() {
  return std::move(loading_mem_tracker_);
}

std::unique_ptr<NavigationEarlyHintsManager>
NavigationRequest::TakeEarlyHintsManager() {
  return std::move(early_hints_manager_);
}

network::mojom::ClientSecurityStatePtr
NavigationRequest::BuildClientSecurityStateForNavigationFetch() {
  switch (GetNavigatingFrameType()) {
    // The client [1] of the navigation fetch request is the navigation
    // initiator, so use the initiator's policies to set the
    // `ClientSecurityState`.
    //
    // [1] https://fetch.spec.whatwg.org/#concept-request-client
    //
    // The `kPrimaryMainFrame` case also covers guest views
    // (https://crbug.com/1261928) when the MPArch implementation is not being
    // used.
    //
    // TODO(crbug.com/40258826): Determine how to treat guest views.
    case FrameType::kPrimaryMainFrame:
    case FrameType::kGuestMainFrame: {
      if (!policy_container_builder_->InitiatorPolicies()) {
        return nullptr;
      }

      network::mojom::ClientSecurityStatePtr state = DeriveClientSecurityState(
          *policy_container_builder_->InitiatorPolicies(),
          PrivateNetworkRequestContext::kMainFrameNavigation);

      // Remove the initiator's COEP, it is unused. For iframes, the parent's
      // COEP should be used: that is checked in `EnforceCOEP()`. The value
      // in `ClientSecurityState` is used for subresources only, in which case
      // the network service performs the check on behalf of the client.
      state->cross_origin_embedder_policy =
          network::CrossOriginEmbedderPolicy();

      return state;
    }
    case FrameType::kSubframe: {
      if (!policy_container_builder_->InitiatorPolicies()) {
        return nullptr;
      }

      network::mojom::ClientSecurityStatePtr state = DeriveClientSecurityState(
          *policy_container_builder_->InitiatorPolicies(),
          PrivateNetworkRequestContext::kSubframeNavigation);

      // Check for policy overrides on LNA. For subframe navigations, we apply
      // policy overrides based on the initiator.
      // TODO(crbug.com/452389539): Centralize these policy overrides.
      if (GetInitiatorOrigin()) {
        ContentBrowserClient* client = GetContentClient()->browser();
        BrowserContext* context =
            frame_tree_node_->navigator().controller().GetBrowserContext();
        url::Origin origin = GetInitiatorOrigin().value();
        ContentBrowserClient::PrivateNetworkRequestPolicyOverride
            policy_override = client->ShouldOverridePrivateNetworkRequestPolicy(
                context, origin);
        state->private_network_request_policy =
            OverrideLocalNetworkAccessPolicy(
                state->private_network_request_policy, policy_override);
      }

      // Remove the initiator's COEP, it is unused. For iframes, the parent's
      // COEP should be used: that is checked in `EnforceCOEP()`. The value
      // in `ClientSecurityState` is used for subresources only, in which case
      // the network service performs the check on behalf of the client.
      state->cross_origin_embedder_policy =
          network::CrossOriginEmbedderPolicy();

      return state;
    }

    // Fenced frames can only be navigated in two ways:
    //
    // 1. By the embedder document, via the fencedframe.config attribute.
    //    The implementation uses the parent policies directly, because
    //    initiator policies are not currently plumbed in this case. This is
    //    correct anyway because the initiator is the parent.
    //    Note: contrary to an iframe, the navigation can never happens at
    //    distance, using e.g. `window.open(url, target)` or `<a target>`.
    //
    // 2. By a document in the <fencedframe> frame tree. In this case the
    //    initiator policies are properly plumbed and should be used.
    //
    // TODO(crbug.com/40258851): Use the initiator policies. On can use
    // `is_embedder_initiated_fenced_frame_navigation_` to discriminate (1) from
    // (2).
    //
    // NOTE: Fenced frames always have an outer document,
    // `GetParentFrameOrOuterDocument()` is never nullptr.
    case FrameType::kFencedFrameRoot: {
      auto client_security_state =
          GetParentFrameOrOuterDocument()->BuildClientSecurityState();

      // TODO(crbug.com/40258851): Remove COEP from
      // `client_security_state`, see the reasoning for subframes above.
      client_security_state->private_network_request_policy =
          DerivePrivateNetworkRequestPolicy(
              client_security_state->ip_address_space,
              client_security_state->is_web_secure_context, false,
              PrivateNetworkRequestContext::kFencedFrameNavigation);

      return client_security_state;
    }

    // TODO(crbug.com/40258824): Determine how to treat prerendered
    // main frames.
    case FrameType::kPrerenderMainFrame:
      return nullptr;
  }
}

network::mojom::ClientSecurityStatePtr
NavigationRequest::BuildClientSecurityStateForCommittedDocument() {
  const PolicyContainerPolicies& policies =
      policy_container_builder_->FinalPolicies();

  return network::mojom::ClientSecurityState::New(
      policies.cross_origin_embedder_policy, policies.is_web_secure_context,
      policies.ip_address_space, private_network_request_policy_,
      policies.document_isolation_policy);
}

std::string NavigationRequest::GetUserAgentOverride() {
  return is_overriding_user_agent()
             ? frame_tree_node_->navigator()
                   .GetDelegate()
                   ->GetUserAgentOverride(frame_tree_node_->frame_tree())
                   .ua_string_override
             : std::string();
}

NavigationControllerImpl* NavigationRequest::GetNavigationController() const {
  return &frame_tree_node_->navigator().controller();
}

PrerenderHostRegistry& NavigationRequest::GetPrerenderHostRegistry() {
  PrerenderHostRegistry* registry = frame_tree_node_->current_frame_host()
                                        ->delegate()
                                        ->GetPrerenderHostRegistry();
  CHECK(registry);
  return *registry;
}

mojo::PendingRemote<network::mojom::CookieAccessObserver>
NavigationRequest::CreateCookieAccessObserver() {
  mojo::PendingRemote<network::mojom::CookieAccessObserver> remote;
  cookie_observers_->Add(remote.InitWithNewPipeAndPassReceiver(),
                         CookieAccessDetails::Source::kNavigation);
  return remote;
}

mojo::PendingRemote<network::mojom::TrustTokenAccessObserver>
NavigationRequest::CreateTrustTokenAccessObserver() {
  mojo::PendingRemote<network::mojom::TrustTokenAccessObserver> remote;
  trust_token_observers_.Add(this, remote.InitWithNewPipeAndPassReceiver());
  return remote;
}

mojo::PendingRemote<network::mojom::SharedDictionaryAccessObserver>
NavigationRequest::CreateSharedDictionaryAccessObserver() {
  mojo::PendingRemote<network::mojom::SharedDictionaryAccessObserver> remote;
  shared_dictionary_observers_.Add(this,
                                   remote.InitWithNewPipeAndPassReceiver());
  return remote;
}

mojo::PendingRemote<network::mojom::DeviceBoundSessionAccessObserver>
NavigationRequest::CreateDeviceBoundSessionObserver() {
  mojo::PendingRemote<network::mojom::DeviceBoundSessionAccessObserver> remote;
  device_bound_session_observers_.Add(this,
                                      remote.InitWithNewPipeAndPassReceiver());
  return remote;
}

void NavigationRequest::NotifyCookiesAccessed(
    std::vector<network::mojom::CookieAccessDetailsPtr> details_vector,
    CookieAccessDetails::Source source) {
  TRACE_EVENT("navigation", "NavigationRequest::NotifyCookiesAccessed",
              perfetto::Flow::FromPointer(this));
  std::optional<base::ElapsedTimer> timer;
  if (base::ShouldRecordSubsampledMetric(0.01)) {
    timer.emplace();
  }
  for (auto& details : details_vector) {
    // TODO(crbug.com/40520047): We should not send information to the current
    // frame about (potentially unrelated) ongoing navigation, but at the moment
    // we don't have another way to add messages to DevTools console.
    EmitCookieWarningsAndMetrics(frame_tree_node()->current_frame_host(),
                                 details);

    CookieAccessDetails allowed;
    CookieAccessDetails blocked;
    SplitCookiesIntoAllowedAndBlocked(details, source, &allowed, &blocked);
    if (!allowed.cookie_access_result_list.empty()) {
      GetDelegate()->OnCookiesAccessed(this, allowed);
    }
    if (!blocked.cookie_access_result_list.empty()) {
      GetDelegate()->OnCookiesAccessed(this, blocked);
    }

    // When determining the BFCache eligibility, we explicitly ignore the cookie
    // changes from the navigation itself because we want the
    // `CookieChangeListener` to only track the cookie changes that potentially
    // make the document initially rendered by the navigation request outdated.
    if (allowed.type == CookieAccessDetails::Type::kChange) {
      uint64_t cookie_modification_count =
          allowed.cookie_access_result_list.size();
      uint64_t http_only_cookie_modification_count = 0u;
      for (const net::CookieWithAccessResult& cookie_with_access_result :
           allowed.cookie_access_result_list) {
        if (cookie_with_access_result.cookie.IsHttpOnly()) {
          http_only_cookie_modification_count++;
        }
      }
      if (cookie_change_listener_) {
        cookie_change_listener_->RemoveNavigationCookieModificationCount(
            base::PassKey<NavigationRequest>(), cookie_modification_count,
            http_only_cookie_modification_count);
      }
    }
  }
  if (timer) {
    base::UmaHistogramCustomMicrosecondsTimes(
        "Browser.CookieAccessObserver.NavigationRequest.Duration.Subsampled",
        timer->Elapsed(), base::Microseconds(1), base::Seconds(1), 100);
  }
}

std::vector<
    std::pair<mojo::PendingReceiver<network::mojom::CookieAccessObserver>,
              CookieAccessDetails::Source>>
NavigationRequest::TakeCookieObservers() {
  return cookie_observers_->TakeReceiversWithContext();
}

void NavigationRequest::OnTrustTokensAccessed(
    network::mojom::TrustTokenAccessDetailsPtr details) {
  GetDelegate()->OnTrustTokensAccessed(this, TrustTokenAccessDetails(details));
}

void NavigationRequest::Clone(
    mojo::PendingReceiver<network::mojom::TrustTokenAccessObserver> observer) {
  trust_token_observers_.Add(this, std::move(observer));
}

std::vector<mojo::PendingReceiver<network::mojom::TrustTokenAccessObserver>>
NavigationRequest::TakeTrustTokenObservers() {
  return trust_token_observers_.TakeReceivers();
}

void NavigationRequest::OnSharedDictionaryAccessed(
    network::mojom::SharedDictionaryAccessDetailsPtr details) {
  GetDelegate()->OnSharedDictionaryAccessed(this, *details);
}

void NavigationRequest::Clone(
    mojo::PendingReceiver<network::mojom::SharedDictionaryAccessObserver>
        observer) {
  shared_dictionary_observers_.Add(this, std::move(observer));
}

void NavigationRequest::OnDeviceBoundSessionAccessed(
    const net::device_bound_sessions::SessionAccess& access) {
  GetDelegate()->OnDeviceBoundSessionAccessed(this, access);
}
void NavigationRequest::Clone(
    mojo::PendingReceiver<network::mojom::DeviceBoundSessionAccessObserver>
        observer) {
  device_bound_session_observers_.Add(this, std::move(observer));
}

std::vector<
    mojo::PendingReceiver<network::mojom::SharedDictionaryAccessObserver>>
NavigationRequest::TakeSharedDictionaryAccessObservers() {
  return shared_dictionary_observers_.TakeReceivers();
}

std::vector<
    mojo::PendingReceiver<network::mojom::DeviceBoundSessionAccessObserver>>
NavigationRequest::TakeDeviceBoundSessionAccessObservers() {
  return device_bound_session_observers_.TakeReceivers();
}

RenderFrameHostImpl* NavigationRequest::GetInitiatorDocumentRenderFrameHost() {
  return initiator_document_token_
             ? RenderFrameHostImpl::FromDocumentToken(
                   initiator_process_id_, *initiator_document_token_)
             : nullptr;
}

void NavigationRequest::RecordAddressSpaceFeature() {
  DCHECK(response_head_);
  DCHECK(policy_container_builder_);

  RenderFrameHostImpl* initiator_render_frame_host =
      GetInitiatorDocumentRenderFrameHost();
  if (!initiator_render_frame_host) {
    // The initiator document is no longer available, so we cannot log a feature
    // use against it. This case may result in a slight undercounting, but is
    // expected to be rare enough that it should not matter for compat risk
    // evaluation.
    return;
  }

  // If there is an initiator document, then `initiator_frame_token_` should
  // have a value, and thus there should be initiator policies.
  const PolicyContainerPolicies* initiator_policies =
      policy_container_builder_->InitiatorPolicies();
  DCHECK(initiator_policies);
  if (!initiator_policies) {
    base::debug::DumpWithoutCrashing();  // Just in case.
    return;
  }

  std::optional<blink::mojom::WebFeature> optional_feature =
      blink::AddressSpaceFeature(blink::FetchType::kNavigation,
                                 initiator_policies->ip_address_space,
                                 initiator_policies->is_web_secure_context,
                                 response_head_->response_address_space);
  if (!optional_feature.has_value()) {
    return;
  }

  ContentBrowserClient* client = GetContentClient()->browser();
  client->LogWebFeatureForCurrentPage(initiator_render_frame_host,
                                      *optional_feature);
  client->LogWebFeatureForCurrentPage(
      initiator_render_frame_host,
      IsInOutermostMainFrame()
          ? blink::mojom::WebFeature::kPrivateNetworkAccessFetchedTopFrame
          : blink::mojom::WebFeature::kPrivateNetworkAccessFetchedSubFrame);
}

void NavigationRequest::ComputePoliciesToCommit() {
  const auto& url = common_params_->url;

  network::mojom::IPAddressSpace response_address_space =
      CalculateIPAddressSpace(url, response_head_.get(),
                              GetContentClient()->browser());
  policy_container_builder_->SetIPAddressSpace(response_address_space);

  // Deprecation trial is to allow http sites to run LNA requests assuming the
  // user grants the permission to the web site.
  //
  // We don't set the use counter here yet because we only want to count the
  // number of times this is actually included on a non-secure context, and
  // whether a context is secure or not is computed later.
  if (base::FeatureList::IsEnabled(
          network::features::kLocalNetworkAccessChecks) &&
      // If there is no response or no headers in the response, there are
      // definitely no trial token headers.
      response_head_ && response_head_->headers &&
      blink::TrialTokenValidator().RequestEnablesDeprecatedFeature(
          common_params_->url, response_head_->headers.get(),
          "LocalNetworkAccessNonSecureContextAllowed", base::Time::Now())) {
    policy_container_builder_->SetLocalNetworkAccessNonSecureContextAllowed(
        true);
  }

  if (response_head_) {
    CHECK(base::FeatureList::IsEnabled(
              network::features::kConnectionAllowlists) ||
          (!response_head_->parsed_headers->connection_allowlists.enforced
                .has_value() &&
           !response_head_->parsed_headers->connection_allowlists.report_only
                .has_value()));
    policy_container_builder_->SetConnectionAllowlists(
        std::move(response_head_->parsed_headers->connection_allowlists));
  }

  if (!devtools_instrumentation::ShouldBypassCSP(*this)) {
    if (response_head_) {
      policy_container_builder_->AddContentSecurityPolicies(
          mojo::Clone(response_head_->parsed_headers->content_security_policy));
    }
  }

  // Use the unchecked / non-sandboxed origin to calculate potential
  // trustworthiness. Indeed, the potential trustworthiness check should apply
  // to the origin of the creation URL, prior to opaquification.
  policy_container_builder_->SetIsOriginPotentiallyTrustworthy(
      network::IsOriginPotentiallyTrustworthy(
          GetOriginForURLLoaderFactoryUnchecked()));

  policy_container_builder_->SetCrossOriginEmbedderPolicy(
      ComputeCrossOriginEmbedderPolicy());

  IntegrityPolicies integrity_policies = ComputeIntegrityPolicies();
  policy_container_builder_->SetIntegrityPolicy(
      std::move(integrity_policies.enforced));
  policy_container_builder_->SetIntegrityPolicyReportOnly(
      std::move(integrity_policies.report_only));

  // If the navigation is the result of a network response, set DIP to the
  // one in the network response. Otherwise, DIP should follow normal rules of
  // policy inheritance, which should be handled by the policy container.
  if (response_head_) {
    SanitizeDocumentIsolationPolicyHeader();
    policy_container_builder_->SetDocumentIsolationPolicy(
        response_head_->parsed_headers->document_isolation_policy);
  }

  DCHECK(commit_params_);
  DCHECK(!HasCommitted());
  DCHECK(!IsErrorPage());

  policy_container_builder_->ComputePolicies(
      this, IsMhtmlOrSubframe(), commit_params_->frame_policy.sandbox_flags,
      is_credentialless());
}

void NavigationRequest::ComputePoliciesToCommitForError() {
  CHECK(!IsMhtmlOrSubframe());
  policy_container_builder_->ComputePoliciesForError();
}

void NavigationRequest::CheckStateTransition(NavigationState state) const {
#if DCHECK_IS_ON()
  // See
  // https://chromium.googlesource.com/chromium/src/+/HEAD/docs/navigation-request-navigation-state.png
  // clang-format off
  static const base::NoDestructor<base::StateTransitions<NavigationState>>
      transitions(base::StateTransitions<NavigationState>({
          {NOT_STARTED, {
              WAITING_FOR_RENDERER_RESPONSE,
              WILL_START_NAVIGATION,
              WILL_START_REQUEST,
          }},
          {WAITING_FOR_RENDERER_RESPONSE, {
              WILL_START_NAVIGATION,
              WILL_START_REQUEST,
          }},
          {WILL_START_NAVIGATION, {
              WILL_START_REQUEST,
              WILL_FAIL_REQUEST,
          }},
          {WILL_START_REQUEST, {
              WILL_REDIRECT_REQUEST,
              WILL_PROCESS_RESPONSE,
              WILL_COMMIT_WITHOUT_URL_LOADER,
              READY_TO_COMMIT,
              DID_COMMIT,
              CANCELING,
              WILL_FAIL_REQUEST,
              DID_COMMIT_ERROR_PAGE,
          }},
          {WILL_REDIRECT_REQUEST, {
              WILL_REDIRECT_REQUEST,
              WILL_PROCESS_RESPONSE,
              CANCELING,
              WILL_FAIL_REQUEST,
          }},
          {WILL_PROCESS_RESPONSE, {
              READY_TO_COMMIT,
              CANCELING,
              WILL_FAIL_REQUEST,
          }},
          {WILL_COMMIT_WITHOUT_URL_LOADER, {
              READY_TO_COMMIT,
              CANCELING,
              WILL_FAIL_REQUEST,
          }},
          {READY_TO_COMMIT, {
              NOT_STARTED,
              DID_COMMIT,
              DID_COMMIT_ERROR_PAGE,
          }},
          {CANCELING, {
              READY_TO_COMMIT,
              WILL_FAIL_REQUEST,
          }},
          {WILL_FAIL_REQUEST, {
              READY_TO_COMMIT,
              CANCELING,
              WILL_FAIL_REQUEST,
          }},
          {DID_COMMIT, {}},
          {DID_COMMIT_ERROR_PAGE, {}},
      }));
  // clang-format on
  DCHECK_STATE_TRANSITION(transitions, state_, state);
#endif  // DCHECK_IS_ON()
}

void NavigationRequest::SetState(NavigationState state) {
  CheckStateTransition(state);
  state_ = state;
}

bool NavigationRequest::MaybeCancelFailedNavigation() {
  // TODO(crbug.com/41349746): Maybe take `ThrottleCheckResult::action()` into
  // account as well.
  std::optional<ErrorNavigationTrigger> error_reason;

  // If the request was canceled by the user, do not show an error page.
  if (net::ERR_ABORTED == net_error_) {
    error_reason = ErrorNavigationTrigger::kFailedWithSilentErrorOnNetAborted;
  }

  // Some embedders suppress error pages to allow custom error handling.
  if (silently_ignore_errors_) {
    error_reason = ErrorNavigationTrigger::kFailedWithSilentErrorOnIgnore;
  }

  // <webview> guests suppress net::ERR_BLOCKED_BY_CLIENT.
  if (net::ERR_BLOCKED_BY_CLIENT == net_error_ &&
      silently_ignore_blocked_by_client_) {
    error_reason =
        ErrorNavigationTrigger::kFailedWithSilentErrorOnBlockedByClient;
  }

  if (error_reason.has_value()) {
    error_navigation_trigger_ = error_reason;
    frame_tree_node_->ResetNavigationRequest(
        NavigationDiscardReason::kInternalCancellation);
    return true;
  }

  // Per https://whatwg.org/C/iframe-embed-object.html#the-object-element,
  // this implements step 4.7 from "determine what the object element
  // represents": "If the load failed (e.g. there was an HTTP 404 error, there
  // was a DNS error), fire an event named error at the element, then jump to
  // the step below labeled fallback."
  //
  // This case handles navigation failure, e.g. due to the navigation being
  // blocked by WebRequest, DNS errors, et cetera.
  if (frame_tree_node()->frame_owner_element_type() ==
      blink::FrameOwnerElementType::kObject) {
    error_navigation_trigger_ =
        ErrorNavigationTrigger::kNavigationOfObjectFailed;
    RenderFallbackContentForObjectTag();
    frame_tree_node_->ResetNavigationRequest(
        NavigationDiscardReason::kInternalCancellation);
    return true;
  }

  return false;
}

bool NavigationRequest::ShouldRenderFallbackContentForResponse(
    const net::HttpResponseHeaders& http_headers) const {
  return frame_tree_node()->frame_owner_element_type() ==
             blink::FrameOwnerElementType::kObject &&
         !network::IsSuccessfulStatus(http_headers.response_code());
}

// https://html.spec.whatwg.org/multipage/browsing-the-web.html#navigating-across-documents:hh-replace
bool NavigationRequest::ShouldReplaceCurrentEntryForSameUrlNavigation() const {
  DCHECK_LE(state_, WILL_START_NAVIGATION);

  // Not a same-url navigation. Note that this is comparing against the "last
  // loading URL" since this is what was used in the renderer check that was
  // moved here. This means for error pages we should compare against the URL
  // that failed to load (the last committed URL), while for other navigations
  // we should compare against the last document URL, which might be different
  // from the last committed URL due to document.open() changing the URL.
  if (common_params_->url !=
      GetLastLoadingURLInRendererForNavigationReplacement(
          frame_tree_node_->current_frame_host())) {
    return false;
  }

  if (IsLoadDataWithBaseURL()) {
    // Preserve old behavior of loadDataWithBaseURL() navigations, which almost
    // never does same-URL replacement when the (data) URL is the same, since it
    // used to compare the data URL against the "history URL", which in almost
    // all cases wouldn't match the data: URL (in most cases it's either the
    // same as the base/document URL, or about:blank [the default value], see
    // https://crbug.com/1244746#c1 for more details).
    return false;
  }

  // Never replace if there is no NavigationEntry to replace.
  if (!frame_tree_node_->navigator().controller().GetEntryCount())
    return false;

  // The NavigationAPI allows a page to request a navigation that pushes even in
  // situations where the browser would implicitly convert the navigation to
  // a replace.
  if (begin_params_->force_history_push ==
      blink::mojom::ForceHistoryPush::kYes) {
    return false;
  }

  // Only (1) cross-document navigations and (2) same-document navigations from
  // browser UI (e.g., address bar or bookmark) need to consider replacing the
  // entry for same URL cases. Reloads and history navigations have special
  // handling and don't need to. Note that same-document navigations with
  // fragments from browser UI are not treated as reloads.
  // Note that for same document navigation, even though the navigation request
  // starts with should_replace_current_entry, no new history entry is created.
  // With the logic in RenderFrameImpl::MakeDidCommitProvisionalLoadParams, we
  // scroll to the fragment without change to navigation history.
  // LocalFrame::ShouldReplaceForSameUrlNavigation also returns true for
  // renderer initiated same url navigation within the same document.
  const ui::PageTransition transition =
      ui::PageTransitionFromInt(common_params_->transition);
  const bool is_same_document_navigation_from_browser_ui =
      (common_params_->navigation_type ==
       blink::mojom::NavigationType::SAME_DOCUMENT) &&
      ((transition & ui::PAGE_TRANSITION_FROM_ADDRESS_BAR) ||
       PageTransitionCoreTypeIs(transition, ui::PAGE_TRANSITION_AUTO_BOOKMARK));
  if (!is_same_document_navigation_from_browser_ui &&
      (common_params_->navigation_type !=
       blink::mojom::NavigationType::DIFFERENT_DOCUMENT)) {
    return false;
  }
  // Form submissions to the same url should not replace.
  if (begin_params_->is_form_submission)
    return false;

  // If the initiating frame is cross-origin to the target frame, do not
  // replace. Replacing in this case can be used to guess the exact current url
  // of a cross-origin frame, see https://crbug.com/1208614. Exempt error pages
  // from this rule so that we don't leave an error page in the back/forward
  // list if a cross-origin iframe happens to successfully re-naivgate a frame
  // that had previously failed.
  if (!frame_tree_node_->current_frame_host()->IsErrorDocument() &&
      common_params_->initiator_origin &&
      !common_params_->initiator_origin->IsSameOriginWith(
          frame_tree_node_->current_origin())) {
    return false;
  }

  // Otherwise, replace current entry.
  return true;
}

bool NavigationRequest::
    ShouldReplaceCurrentEntryForNavigationFromInitialEmptyDocumentOrEntry()
        const {
  DCHECK_LE(state_, WILL_START_NAVIGATION);
  // Never replace if there is no NavigationEntry to replace.
  if (!frame_tree_node_->navigator().controller().GetEntryCount())
    return false;

  if (common_params_->navigation_type !=
          blink::mojom::NavigationType::SAME_DOCUMENT &&
      common_params_->navigation_type !=
          blink::mojom::NavigationType::DIFFERENT_DOCUMENT) {
    // History navigations, session restore, and reloads shouldn't do
    // replacement.
    return false;
  }

  // Check the "initial NavigationEntry" status and the "initial empty document"
  // status.

  if (frame_tree_node_->navigator()
          .controller()
          .GetLastCommittedEntry()
          ->IsInitialEntry()) {
    // Initial NavigationEntry must always be replaced, to ensure that as long
    // as the NavigationEntry exists, it will be the only NavigationEntry in
    // the session history list, making history navigations to initial
    // NavigationEntry possible. See the comment for `is_initial_entry_` in
    // NavigationEntryImpl for more details.
    return true;
  }

  // For non-initial NavigationEntries, the initial empty document should also
  // be replaced in subframes and non-outermost main frames (fenced frames).
  // For outermost main frames, the initial empty document will usually only
  // exist when on the initial NavigationEntry, but it can also exist in a
  // restored or cloned NavigationController before the first commit. It is
  // important not to replace one of the restored entries in that case. See
  // https://crbug.com/1284566 and https://crbug.com/1295723.
  return frame_tree_node_->is_on_initial_empty_document() &&
         frame_tree_node_->GetParentOrOuterDocument();
}

bool NavigationRequest::ShouldReplaceCurrentEntryForFailedNavigation() const {
  DCHECK(state_ == CANCELING || state_ == WILL_FAIL_REQUEST);

  if (common_params_->should_replace_current_entry)
    return true;

  // Never replace if there is no NavigationEntry to replace.
  if (!frame_tree_node_->navigator().controller().GetEntryCount())
    return false;

  auto page_state =
      blink::PageState::CreateFromEncodedData(commit_params_->page_state);
  // Failed history navigations with valid PageState should not do replacement.
  if (page_state.IsValid())
    return false;

  bool is_reload_or_history =
      NavigationTypeUtils::IsReload(common_params_->navigation_type) ||
      NavigationTypeUtils::IsHistory(common_params_->navigation_type);
  // Otherwise, these navigations should do replacement:
  // - Failed history/reloads with invalid PageState (e.g. same-URL navigations
  //   that got converted to a reload).
  // - Same-URL navigations. Note that even though we had a same-URL check
  //   earlier in the navigation's lifetime (which would convert same-URL
  //   navigations to reload or replacement), those compare against the initial
  //   URL instead of the final URL, which is what we're using here. Also, this
  //   is using the "loading URL", since that is the URL that was used in the
  //   renderer before we moved the replacement conversion here.
  // TODO(crbug.com/40755155): Reconsider whether these two cases should
  // do replacement or not, since we're just preserving old behavior here.
  return is_reload_or_history ||
         (common_params_->url ==
          GetLastLoadingURLInRendererForNavigationReplacement(
              frame_tree_node_->current_frame_host()));
}

const std::optional<FencedFrameProperties>&
NavigationRequest::ComputeFencedFrameProperties(
    FencedFramePropertiesNodeSource node_source) const {
  if (node_source == FencedFramePropertiesNodeSource::kFrameTreeRoot &&
      !frame_tree_node_->IsFencedFrameRoot()) {
    // Sometimes nodes other than the frame tree root (urn iframes) have
    // FencedFrameProperties in their navigation requests. When the node source
    // is kFrameTreeRoot and this navigation request is not for the frame tree
    // root, get the properties from the frame tree root.
    return frame_tree_node_->GetFencedFrameProperties(node_source);
  }

  if (fenced_frame_properties_) {
    return fenced_frame_properties_;
  }

  return frame_tree_node_->GetFencedFrameProperties(node_source);
}

const std::optional<base::UnguessableToken>
NavigationRequest::ComputeFencedFrameNonce() const {
  // For partition nonce, all nested frame inside a fenced frame tree should
  // operate on the partition nonce of the frame tree root.
  const std::optional<FencedFrameProperties>& computed_fenced_frame_properties =
      ComputeFencedFrameProperties(
          /*node_source=*/FencedFramePropertiesNodeSource::kFrameTreeRoot);
  if (!computed_fenced_frame_properties.has_value()) {
    return std::nullopt;
  }
  if (!computed_fenced_frame_properties->partition_nonce().has_value()) {
    // It is only possible for there to be `FencedFrameProperties` but no
    // partition nonce in urn iframes (which could indeed be nested inside a
    // fenced frame).
    CHECK(blink::features::IsAllowURNsInIframeEnabled());
    return std::nullopt;
  }
  return computed_fenced_frame_properties->partition_nonce()
      ->GetValueIgnoringVisibility();
}

void NavigationRequest::RenderFallbackContentForObjectTag() {
  // https://whatwg.org/C/iframe-embed-object.html#the-object-element:fallback-content-5:
  // Fallback content is represented by the children of the <object> tag, so it
  // will be rendered in the process of the parent's document.
  DCHECK_EQ(blink::FrameOwnerElementType::kObject,
            frame_tree_node_->frame_owner_element_type());
  if (RenderFrameProxyHost* proxy =
          frame_tree_node_->render_manager()->GetProxyToParent()) {
    if (proxy->is_render_frame_proxy_live()) {
      proxy->GetAssociatedRemoteFrame()->RenderFallbackContent();
    }
  } else {
    frame_tree_node_->current_frame_host()
        ->GetAssociatedLocalFrame()
        ->RenderFallbackContent();
  }
}

std::optional<base::UnguessableToken>
NavigationRequest::GetNavigationTokenForDeferringSubframes() {
  DCHECK(IsInMainFrame());
  if (!IsSameDocument() ||
      !NavigationTypeUtils::IsHistory(common_params_->navigation_type)) {
    return std::nullopt;
  }
  RenderFrameHostImpl* current_frame_host =
      frame_tree_node_->current_frame_host();
  if (!current_frame_host->has_navigate_event_handler()) {
    return std::nullopt;
  }
  if (commit_params_->is_browser_initiated &&
      !current_frame_host->IsHistoryUserActivationActive()) {
    return std::nullopt;
  }
  return commit_params_->navigation_token;
}

void NavigationRequest::AddDeferredSubframeNavigationThrottle(
    base::WeakPtr<SubframeHistoryNavigationThrottle> throttle) {
  DCHECK(IsInMainFrame());
  subframe_history_navigation_throttles_.push_back(throttle);
}

void NavigationRequest::UnblockPendingSubframeNavigationRequestsIfNeeded() {
  // After a main frame same-document history navigation completes successfully,
  // we can resume any corresponding subframe history navigations that were
  // blocked on it.
  base::WeakPtr<NavigationRequest> self = GetWeakPtr();
  for (auto& throttle : subframe_history_navigation_throttles_) {
    if (throttle) {
      throttle->Resume();
      if (!self) {
        return;
      }
    }
  }
  subframe_history_navigation_throttles_.clear();
}

void NavigationRequest::MaybeDispatchNavigateEventForCrossDocumentTraversal() {
  // If this is a cross-document history navigation, notify the renderer to
  // fire the navigate event now that we know which frames are navigating and
  // whether the navigation is same-origin. Note that while the navigate event
  // can normally intercept or cancel a navigation, it has neither of those
  // powers for a cross-document history navigation, and therefore can be
  // dispatched without waiting for a result. The worst it can do is detach the
  // frame asynchronously, which javascript could do at any time anyway.
  if (common_params_->navigation_type !=
      blink::mojom::NavigationType::HISTORY_DIFFERENT_DOCUMENT) {
    return;
  }
  // Only fire the navigate event if the destination is same-origin. Because
  // this check is performed at navigation start time, `destination_origin` is
  // based on the pre-redirect URL, which is consistent with the renderer
  // process logic for firing the navigate event for non-history navigations.
  url::Origin destination_origin = url::Origin::Resolve(
      common_params_->url,
      common_params_->initiator_origin.value_or(url::Origin()));
  if (!frame_tree_node_->current_origin().IsSameOriginWith(
          destination_origin)) {
    return;
  }
  frame_tree_node_->current_frame_host()
      ->GetAssociatedLocalFrame()
      ->DispatchNavigateEventForCrossDocumentTraversal(
          common_params_->url, commit_params_->page_state,
          commit_params_->is_browser_initiated);
}

bool NavigationRequest::IsServedFromBackForwardCache() const {
  return is_back_forward_cache_restore_;
}

bool NavigationRequest::IsPageActivation() const {
  return const_cast<NavigationRequest*>(this)->IsPrerenderedPageActivation() ||
         IsServedFromBackForwardCache();
}

std::unique_ptr<NavigationEntryImpl>
NavigationRequest::TakePrerenderNavigationEntry() {
  DCHECK(IsPrerenderedPageActivation());
  return std::move(prerender_navigation_state_->prerender_navigation_entry);
}

bool NavigationRequest::IsWaitingForBeforeUnload() {
  return state_ < WILL_START_NAVIGATION;
}

void NavigationRequest::AddDeferredConsoleMessage(
    blink::mojom::ConsoleMessageLevel level,
    std::string message) {
  DCHECK_LE(state_, READY_TO_COMMIT);
  console_messages_.push_back(ConsoleMessage{level, std::move(message)});
}

void NavigationRequest::SendDeferredConsoleMessages() {
  for (auto& message : console_messages_) {
    // TODO(crbug.com/40520047): We should have a way of sending console
    // messaged to devtools without going through the renderer.
    GetRenderFrameHost()->AddMessageToConsole(message.level,
                                              std::move(message.message));
  }
  console_messages_.clear();
}

std::optional<AgentClusterKey::CrossOriginIsolationKey>
NavigationRequest::ComputeCrossOriginIsolationKey() {
  // If the navigation doesn't have an origin, we cannot create a
  // CrossOriginIsolationKey for it, since it must be tied to an origin.
  url::Origin origin;
  if (state_ < WILL_PROCESS_RESPONSE) {
    origin = GetTentativeOriginAtRequestTime();
  } else {
    std::optional<url::Origin> origin_to_commit = GetOriginToCommit();
    if (!origin_to_commit.has_value()) {
      return std::nullopt;
    }
    origin = origin_to_commit.value();
  }

  // If the final security policies have not been computed yet, return our best
  // guess of what the final CrossOriginIsolationKey will be. This is because
  // we cannot compute the proper CrossOriginIsolationKey for the navigation
  // yet. However, if we return an empty CrossOriginIsolationKey, we might
  // create a spurious speculative RFH due to CrossOriginIsolationKey
  // differences. To avoid this, we return the current CrossOriginIsolationKey
  // if the navigation is same-origin.
  if (!policy_container_builder_->HasComputedPolicies()) {
    if (origin.IsSameOriginWith(frame_tree_node_->current_origin())) {
      return frame_tree_node_->current_frame_host()
          ->GetSiteInstance()
          ->GetSiteInfo()
          .agent_cluster_key()
          .GetCrossOriginIsolationKey();
    }
    return std::nullopt;
  }

  // If the navigation does not have a Document-Isolation-Policy, return an
  // empty CrossOriginIsolationKey.
  // TODO(crbug.com/342365083): Use a CrossOriginIsolationKey when the
  // navigation has COOP and COEP, or happens in cross-origin isolated
  // BrowsingInstance.
  if (policy_container_builder_->FinalPolicies()
          .document_isolation_policy.value ==
      network::mojom::DocumentIsolationPolicyValue::kNone) {
    return std::nullopt;
  }

  // The document we're navigating to has a DocumentIsolationPolicy of
  // "isolate-and-require-corp" or "isolate-and-credentialless". This means that
  // the document requested crossOriginIsolation, so return a cross-origin
  // isolation key with the current origin. Its cross-origin isolation mode
  // depends on the capabilities of the platform.  Currently, we only support a
  // cross-origin isolation mode of kConcrete and platforms with full Site
  // Isolation.
  // TODO(crbug.com/342364564): Support platforms that do not
  // support OOPIF and return an AgentClusterKey with a CrossOriginIsolationKey
  // that has a kLogical cross-origin isolation mode.
  CHECK(policy_container_builder_->FinalPolicies()
                .document_isolation_policy.value ==
            network::mojom::DocumentIsolationPolicyValue::
                kIsolateAndRequireCorp ||
        policy_container_builder_->FinalPolicies()
                .document_isolation_policy.value ==
            network::mojom::DocumentIsolationPolicyValue::
                kIsolateAndCredentialless);

  // Inform the PolicyContainer that DocumentIsolationPolicy has enabled
  // crossOriginIsolation for the document.
  policy_container_builder_->SetCrossOriginIsolationEnabledByDIP();

  return AgentClusterKey::CrossOriginIsolationKey(
      origin, CrossOriginIsolationMode::kConcrete);
}

std::optional<WebExposedIsolationInfo>
NavigationRequest::ComputeWebExposedIsolationInfo() {
  // If we are in an iframe, we inherit the isolation state of the top level
  // frame. This can be inferred from the main frame SiteInstance. Note that
  // Iframes have to pass COEP tests in |OnResponseStarted| before being loaded
  // and inheriting this cross-origin isolated state.
  //
  // Embedded content that cannot always provide a separate process (Fenced
  // frames) should use the crossOriginIsolated state of their
  // parent. Therefore we use IsOutermostMainFrame.
  //
  // TODO(crbug.com/40180791): This may change as we work out the model for
  // isolation mechanisms beyond "cross-origin isolation".
  if (!frame_tree_node_->IsOutermostMainFrame()) {
    return frame_tree_node_->current_frame_host()
        ->GetMainFrame()
        ->GetSiteInstance()
        ->GetWebExposedIsolationInfo();
  }

  // This accommodates for web tests that use COOP. They expect an about:blank
  // page to stay in process, and hang otherwise. In general, it is safe to
  // allow about:blank pages to stay in process, since scriptability is limited
  // to the BrowsingInstance and all pages with the same web-exposed isolation
  // level are trusted.
  if (common_params_->url.IsAboutBlank())
    return std::nullopt;

  // If we haven't yet received a definitive network response, it is too early
  // to guess the isolation state.
  if (state_ < WILL_PROCESS_RESPONSE)
    return std::nullopt;

  // We consider navigations to be cross-origin isolated if the response
  // asserts proper COOP and COEP headers.
  if ((coop_status().current_coop().value !=
       network::mojom::CrossOriginOpenerPolicyValue::kSameOriginPlusCoep)) {
    return WebExposedIsolationInfo::CreateNonIsolated();
  }

  const GURL& url = common_params().url;

  // TODO(https://crbug.com/415943168): This should take into account Sandbox
  // Flags. However, we can only do so when the CrossOriginOpenerPolicyStatus
  // also take them into account. Because the CrossOriginOpenerPolicyStatus does
  // not take into account sandbox flags, it does not mandate a BrowsingInstance
  // switch when navigating between two same-origin pages where one of the pages
  // has sandox flags that make its origin opaque. So the two pages are going to
  // commit in the same BrowsingInstance. If we use an opaque origin here, we
  // would end up with a mismatch between the WebExposedIsolationInfo for the
  // navigation and that of the BrowsingInstance it is set to commit into.
  const url::Origin origin = GetOriginForURLLoaderFactoryUnchecked();

  return SiteIsolationPolicy::ShouldUrlUseApplicationIsolationLevel(
             GetNavigationController()->GetBrowserContext(), url)
             ? WebExposedIsolationInfo::CreateIsolatedApplication(origin)
             : WebExposedIsolationInfo::CreateIsolated(origin);
}

void NavigationRequest::MaybeAssignInvalidPrerenderFrameTreeNodeId() {
  if (!prerender_frame_tree_node_id_.has_value()) {
    // This navigation won't activate a prerendered page. Otherwise,
    // `prerender_frame_tree_node_id_` should have already been set before this
    // in OnPrerenderingActivationChecksComplete().
    prerender_frame_tree_node_id_ = FrameTreeNodeId();
  }
}

void NavigationRequest::RendererCancellationWindowEnded() {
  // The renderer had indicated that the navigation cancellation window had
  // ended, so the navigation can resume if it is currently waiting for this
  // signal.
  renderer_cancellation_window_ended_ = true;
  renderer_cancellation_listener_.reset();
  if (renderer_cancellation_window_ended_callback_) {
    std::move(renderer_cancellation_window_ended_callback_).Run();
    // DO NOT ADD CODE after this. The callback triggers
    // RendererCancellationThrottle::NavigationCancellationWindowEnded() and
    // eventually NavigationThrottle::Resume(), which might have destroyed the
    // NavigationRequest.
  }
}

bool NavigationRequest::ShouldWaitForRendererCancellationWindowToEnd() {
  return renderer_cancellation_listener_.is_bound() &&
         !renderer_cancellation_window_ended_;
}

NavigationRequest::ScopedCrashKeys::ScopedCrashKeys(
    NavigationRequest& navigation_request)
    : initiator_origin_(
          GetNavigationRequestInitiatorCrashKey(),
          base::OptionalToPtr(navigation_request.GetInitiatorOrigin())),
      url_(GetNavigationRequestUrlCrashKey(), navigation_request.GetURL()),
      is_same_document_(
          GetNavigationRequestIsSameDocumentCrashKey(),
          navigation_request.IsSameDocument() ? "same-doc" : "cross-doc") {}

NavigationRequest::ScopedCrashKeys::~ScopedCrashKeys() = default;

PreloadingTriggerType NavigationRequest::GetPrerenderTriggerType() {
  DCHECK(reserved_prerender_host_info_.has_value());
  return reserved_prerender_host_info_->trigger_type;
}

std::string NavigationRequest::GetPrerenderEmbedderHistogramSuffix() {
  DCHECK(reserved_prerender_host_info_.has_value());
  return reserved_prerender_host_info_->embedder_histogram_suffix;
}

bool NavigationRequest::IsPrerenderHostReused() {
  DCHECK(reserved_prerender_host_info_.has_value());
  return reserved_prerender_host_info_->is_prerender_host_reused;
}

#if BUILDFLAG(IS_ANDROID)
const base::android::JavaRef<jobject>&
NavigationRequest::GetJavaNavigationHandle() {
  return navigation_handle_proxy_->java_navigation_handle();
}
#endif

void NavigationRequest::SetViewTransitionState(
    std::unique_ptr<ScopedViewTransitionResources> resources,
    blink::ViewTransitionState view_transition_state) {
  commit_params_->view_transition_state = std::move(view_transition_state);
  CHECK(resources);
  view_transition_resources_ = std::move(resources);
}

void NavigationRequest::ResetViewTransitionState() {
  if (!commit_params_->view_transition_state) {
    CHECK(!view_transition_resources_);
    return;
  }

  CHECK(view_transition_resources_);
  commit_params_->view_transition_state.reset();
  view_transition_resources_.reset();

  // If we cached a view transition for the old Document and the transition
  // has been aborted, inform the old Document to discard the pending
  // ViewTransition.
  //
  // Note: If the transition is aborted before the renderer acks the
  // snapshot IPC, we won't have any resources here. The
  // ViewTransitionCommitDeferringCondition is responsible for discarding the
  // pending transition in this case.
  if (auto* previous_rfh =
          RenderFrameHostImpl::FromID(GetPreviousRenderFrameHostId())) {
    previous_rfh->GetAssociatedLocalFrame()
        ->NotifyViewTransitionAbortedToOldDocument();
  }
}

bool NavigationRequest::IsDisabledEmbedderInitiatedFencedFrameNavigation() {
  // The untrusted network access check only applies to embedder-initiated
  // fenced frame root navigations. Note that
  // `is_embedder_initiated_fenced_frame_navigation_` being true includes fenced
  // frame and urn iframe embedder initiated navigations, so we need the
  // additional `IsFencedFrameRoot` check.
  if (frame_tree_node_->IsFencedFrameRoot() &&
      is_embedder_initiated_fenced_frame_navigation_ &&
      base::FeatureList::IsEnabled(
          blink::features::kFencedFramesLocalUnpartitionedDataAccess)) {
    const std::optional<FencedFrameProperties>&
        embedder_fenced_frame_properties = GetParentFrameOrOuterDocument()
                                               ->frame_tree_node()
                                               ->GetFencedFrameProperties();
    const std::optional<FencedFrameProperties>& target_fenced_frame_properties =
        frame_tree_node_->GetFencedFrameProperties(
            FencedFramePropertiesNodeSource::kFrameTreeRoot);

    if (target_fenced_frame_properties.has_value() &&
        target_fenced_frame_properties
            ->HasDisabledNetworkForCurrentFrameTree() &&
        embedder_fenced_frame_properties.has_value() &&
        embedder_fenced_frame_properties
            ->HasDisabledNetworkForCurrentFrameTree()) {
      // Navigation should be aborted if:
      // 1. The nested fenced frame has disabled the untrusted network access.
      // 2. The embedder fenced frame has disabled the untrusted network access
      // after the navigation starts.
      //
      // Note: The navigation is allowed if only embedder fenced frame has
      // disabled the untrusted network access. This allows the fenced frame
      // to navigate its nested fenced frame to a nested config while the parent
      // fenced frame disables its own network.
      //
      // After top-level FF disables its network, the nested FF's navigation
      // may not have committed yet. Top-level FF has no way of knowing when it
      // is safe to disable network for nested FF (and it would be a privacy
      // violation for it to know), so nested FF has to disable network for
      // itself if it wants to get shared storage access.
      //
      // For top-level FF, it does not have shared storage access until all
      // its descendants have also disabled network.
      return true;
    }
  }

  return false;
}

blink::RuntimeFeatureStateContext&
NavigationRequest::GetMutableRuntimeFeatureStateContext() {
  // runtime_feature_state_context_ shouldn't be modified after READY_TO_COMMIT
  // as its state has already been sent to the renderer.
  DCHECK_LE(state_, NavigationState::READY_TO_COMMIT);
  return runtime_feature_state_context_;
}

const blink::RuntimeFeatureStateContext&
NavigationRequest::GetRuntimeFeatureStateContext() {
  return runtime_feature_state_context_;
}

ProcessSelectionUserData& NavigationRequest::GetProcessSelectionUserData() {
  return process_selection_user_data_;
}

// The NavigationDownloadPolicy is currently computed by the renderer process.
// The problem: not every navigation are initiated from the renderer. Most
// fields from the bitfield can be computed from the browser process. This
// function is a partial attempt at doing it.
void NavigationRequest::ComputeDownloadPolicy() {
  // [ViewSource]
  if (GetNavigationEntry() && GetNavigationEntry()->IsViewSourceMode()) {
    download_policy().SetDisallowed(blink::NavigationDownloadType::kViewSource);
  }

  // [Sandbox]
  if ((commit_params_->frame_policy.sandbox_flags &
       network::mojom::WebSandboxFlags::kDownloads) ==
      network::mojom::WebSandboxFlags::kDownloads) {
    download_policy().SetDisallowed(blink::NavigationDownloadType::kSandbox);
  }

  // TODO(arthursonzogni): Check if the following fields from the
  // NavigationDownloadPolicy could be computed here from the browser process
  // instead:
  //
  // [NoGesture]
  // [OpenerCrossOrigin]
  // [AdFrameNoGesture]
  // [AdFrame]
  // [Interstitial]
}

bool NavigationRequest::ShouldQueueDueToExistingPendingCommitRFH() const {
  CHECK_EQ(this, frame_tree_node_->navigation_request());
  CHECK(state_ < READY_TO_COMMIT || state_ == WILL_FAIL_REQUEST);

  if (RenderFrameHostImpl* speculative_rfh =
          frame_tree_node_->render_manager()->speculative_frame_host()) {
    // Queue the navigation if there is a pending commit RenderFrameHost.
    return speculative_rfh->HasPendingCommitForCrossDocumentNavigation();
  }
  return false;
}

void NavigationRequest::RecordMetricsForBlockedGetFrameHostAttempt(
    bool commit_attempt) {
  DCHECK(!pending_commit_metrics_.start_time.is_null());
  ++pending_commit_metrics_.blocked_count;
  if (commit_attempt) {
    ++pending_commit_metrics_.blocked_commit_count;
  }
}

void NavigationRequest::PostResumeCommitTask() {
  DCHECK(ShouldAvoidRedundantNavigationCancellations());
  DCHECK(!ShouldQueueDueToExistingPendingCommitRFH());
  // TODO(crbug.com/40186427): Add some metrics for how often:
  // - this is run
  // - how long navigations remain queued
  // - how often it ends up having to simply re-queue itself
  if (resume_commit_closure_) {
    // Post a task so that we resume the navigation asynchronously. Note
    // that we're guaranteed to not have a new RFH get into a pending commit
    // stage in between the time we post this task and the time we run it.
    // `this` is the previously-queued NavigationRequest and is still owned by
    // the `FrameTreeNode`. If a new `NavigationRequest` is created, it will
    // replace and delete `this` and the resume callback for `this` will be
    // skipped.
    base::SequencedTaskRunner::GetCurrentDefault()->PostNonNestableTask(
        FROM_HERE, std::move(resume_commit_closure_));
  }
}

void NavigationRequest::CheckSoftNavigationHeuristicsInvariants() {
  if (!commit_params_->soft_navigation_heuristics_task_id) {
    return;
  }
  // TODO(crbug.com/40283341): Checking for a restore here, to
  // accommodate for restored same document navigations. They are currently
  // NOT executed as same-document. The task ID is cleared to ensure it never
  // leak toward a different document.
  if (IsRestore()) {
    DCHECK(!IsSameDocument());
    commit_params_->soft_navigation_heuristics_task_id = {};
    return;
  }

  // In NavigationControllerImpl::NavigateToExistingPendingEntry we're verifying
  // that the task ID is only passed along if the initiator RFH is the same as
  // the navigated RFH.
  DCHECK(IsSameDocument());
  DCHECK(IsInMainFrame());
  DCHECK(!frame_tree_node()->IsFencedFrameRoot());
}

StoragePartition* NavigationRequest::GetStoragePartitionWithCurrentSiteInfo() {
  // `site_info_`'s StoragePartitionConfig should refer to the correct
  // `StoragePartition` for this navigation.
  return frame_tree_node_->navigator()
      .controller()
      .GetBrowserContext()
      ->GetStoragePartition(site_info_.storage_partition_config());
}

void NavigationRequest::CreateWebUIIfNeeded(RenderFrameHostImpl* frame_host) {
  TRACE_EVENT("content", "NavigationRequest::CreateWebUI", "url", GetURL());

  WebUI::TypeID new_web_ui_type =
      WebUIControllerFactoryRegistry::GetInstance()->GetWebUIType(
          frame_tree_node_->navigator().controller().GetBrowserContext(),
          GetURL());
  if (new_web_ui_type == WebUI::kNoWebUI) {
    // The navigation doesn't need a WebUI.
    return;
  }
  CHECK(!web_ui_);

  // We reuse WebUI on navigations with the same WebUI type where we use the
  // same RFH, so don't create a new one if there is already an existing WebUI
  // in `frame_host`. However, it is useful to verify that its type hasn't
  // changed. Site isolation guarantees that RenderFrameHostImpl will be changed
  // if the WebUI type differs.
  if (frame_host && frame_host->web_ui()) {
    CHECK_EQ(new_web_ui_type, frame_host->web_ui_type());
    return;
  }

  web_ui_ = std::make_unique<WebUIImpl>(this);
  std::unique_ptr<WebUIController> controller(
      WebUIControllerFactoryRegistry::GetInstance()
          ->CreateWebUIControllerForURL(web_ui_.get(), GetURL()));

  // If we have assigned (zero or more) bindings to the NavigationEntry in
  // the past, make sure we're not granting it different bindings than it
  // had before. If so, note it and don't give it any bindings, to avoid a
  // potential privilege escalation.
  if (bindings().has_value() && bindings().value() != web_ui_->GetBindings()) {
    RecordAction(base::UserMetricsAction("ProcessSwapBindingsMismatch_RVHM"));
    base::WeakPtr<NavigationRequest> self = GetWeakPtr();
    // Reset `controller` first before resetting `web_ui_`, since the controller
    // still has a pointer to `web_ui_`, to avoid referencing to the already
    // deleted  `web_ui_` object from `controller`'s destructor. See also
    // https://crbug.com/345640549.
    controller.reset();
    web_ui_.reset();
    // Resetting the WebUI may indirectly call content's embedders and delete
    // `this`. There are no known occurrences of it, so we assume this never
    // happen and crash immediately if it does, because there are no easy ways
    // to recover.
    CHECK(self);
    return;
  }

  web_ui_->SetController(std::move(controller));
}

bool NavigationRequest::IsDeferred() {
  return !throttle_registry_->GetDeferringThrottles().empty();
}

void NavigationRequest::OnResponseBodyReady(MojoResult) {
  size_t available_bytes = 0;
  MojoResult result = response_body().ReadData(
      MOJO_READ_DATA_FLAG_QUERY, base::span<uint8_t>(), available_bytes);
  CHECK_EQ(result, MOJO_RESULT_OK);

  std::string response_body_contents(available_bytes, '\0');
  size_t actually_read_bytes = 0;
  result = response_body().ReadData(
      MOJO_READ_DATA_FLAG_PEEK,
      base::as_writable_byte_span(response_body_contents), actually_read_bytes);
  switch (result) {
    case MOJO_RESULT_OK:
      // The watcher is reset before calling the callback since the callback may
      // resume the throttle. If the watcher is still active, resumption via
      // callback results in running the OnceCallback twice.
      response_body_watcher_.reset();
      response_body_contents.resize(actually_read_bytes);
      std::move(response_body_callback_).Run(std::move(response_body_contents));
      break;
    case MOJO_RESULT_SHOULD_WAIT:
      response_body_watcher_->ArmOrNotify();
      break;
    default:
      // The watcher is reset before calling the callback since the callback may
      // resume the throttle. If the watcher is still active, resumption via
      // callback results in running the OnceCallback twice.
      response_body_watcher_.reset();
      // The client throttle may be waiting for the response body before
      // resuming navigation, so call the callback with an empty response body
      // to unblock the throttle.
      std::move(response_body_callback_).Run(std::string());
      break;
  }
}

void NavigationRequest::RecordEarlyRenderFrameHostSwapMetrics() {
  base::UmaHistogramEnumeration("Navigation.EarlyRenderFrameHostSwapType",
                                early_render_frame_host_swap_type_);
  if (early_render_frame_host_swap_type_ !=
      NavigationRequest::EarlyRenderFrameHostSwapType::kNone) {
    base::UmaHistogramBoolean(
        "Navigation.EarlyRenderFrameHostSwap.HasCommitted", HasCommitted());
    base::UmaHistogramBoolean(
        "Navigation.EarlyRenderFrameHostSwap.IsInOutermostMainFrame",
        IsInOutermostMainFrame());
  }
}

url::Origin NavigationRequest::GetOriginForURLLoaderFactoryUnchecked() {
  if (DidEncounterError()) {
    // Error pages commit in an opaque origin in the renderer process. If this
    // NavigationRequest resulted in committing an error page, return an
    // opaque origin that has precursor information consistent with the URL
    // being requested.  Note: this is intentionally done first; cases like
    // errors in srcdoc frames need not inherit the parent's origin for errors.
    return url::Origin::Create(common_params().url).DeriveNewOpaqueOrigin();
  }

  // Check if this is loadDataWithBaseUrl (which needs special treatment).
  if (IsLoadDataWithBaseURL()) {
    // A (potentially attacker-controlled) renderer process should not be able
    // to use loadDataWithBaseUrl code path to initiate fetches on behalf of a
    // victim origin (fetches controlled by attacker-provided
    // |common_params.url| data: URL in a victim's origin from the
    // attacker-provided |common_params.base_url_for_data_url|).  Browser
    // process should verify that |common_params.base_url_for_data_url| is empty
    // for all renderer-initiated navigations (e.g. see
    // VerifyBeginNavigationCommonParams), but as a defense-in-depth this is
    // also asserted below.
    // History navigations are exempt from this rule because, although they can
    // be renderer-initaited via the js history API, the renderer does not
    // choose the url being navigated to. A renderer-initiated history
    // navigation may therefore navigate back to a previous browser-initiated
    // loadDataWithBaseUrl.
    CHECK(browser_initiated() ||
          NavigationTypeUtils::IsHistory(common_params().navigation_type));

    // loadDataWithBaseUrl submits a data: |common_params.url| (which has a
    // opaque origin), but commits that URL as if it came from
    // |common_params.base_url_for_data_url|.  See also
    // https://crbug.com/976253.
    return url::Origin::Create(common_params().base_url_for_data_url);
  }

  // Use the cached tentative data origin to commit in the data: URL case. When
  // there are multiple data: URLs in the same SiteInstanceGroup, we can rely on
  // the nonce from the origin and that of the site URL to match, which will let
  // us uniquely identify the correct data: SiteInstance.
  if (common_params().url.SchemeIs(url::kDataScheme) &&
      tentative_data_origin_to_commit_.has_value()) {
    return tentative_data_origin_to_commit_.value();
  }

  // Srcdoc subframes need to inherit their origin from their parent frame.
  if (GetURL().IsAboutSrcdoc()) {
    RenderFrameHostImpl* parent = frame_tree_node()->parent();

    if (parent) {
      return parent->GetLastCommittedOrigin();
    } else {
      // The only path for `parent` to be missing for a srcdoc navigation is if
      // a mainframe renderer executes `location = "about:srcdoc` instead of
      // embedding an <iframe srcdoc="..."></iframe> element; this is covered by
      // NavigationBrowserTest.BlockedSrcDoc* tests. While this will result in
      // an error page, we might still get here via GetURLInfo if the navigation
      // encounters a COOP header. In that case we return the origin of the
      // page that executed the script, knowing that the navigation will fail
      // anyways.
      return frame_tree_node()->current_frame_host()->GetLastCommittedOrigin();
    }
  }

  if (GetURL().SchemeIsBlob()) {
    // Blob URLs either have the origin embedded within the URL, or have a
    // URL -> origin mapping for it saved in the BlobURLRegistry.
    std::optional<int> target_rph_id;
    if (HasRenderFrameHost() && GetRenderFrameHost()->GetProcess()) {
      target_rph_id = GetRenderFrameHost()->GetProcess()->GetDeprecatedID();
    }
    return static_cast<StoragePartitionImpl*>(
               GetStoragePartitionWithCurrentSiteInfo())
        ->GetBlobUrlRegistry()
        ->GetOriginForNavigation(
            GetURL(), common_params().initiator_origin.value_or(url::Origin()),
            target_rph_id);
  }

  // In cases not covered above, URLLoaderFactory should be associated with the
  // origin of |common_params.url| and/or |common_params.initiator_origin|.
  url::Origin resolved_origin = url::Origin::Resolve(
      common_params().url,
      common_params().initiator_origin.value_or(url::Origin()));

  if (common_params().url.SchemeIs(url::kDataScheme)) {
    // Cache the origin for data: URLs, so that its nonce remains stable.
    tentative_data_origin_to_commit_ = resolved_origin;
  }

  return resolved_origin;
}

bool NavigationRequest::HasLoader() const {
  return loader_.get() != nullptr;
}

blink::mojom::PageSwapEventParamsPtr NavigationRequest::WillDispatchPageSwap() {
  CHECK(ShouldDispatchPageSwapEvent());

  did_fire_page_swap_ = true;

  if (did_encounter_cross_origin_redirect_) {
    return nullptr;
  }

  // The `pageswap` event is fired on the old Document to provide information
  // about the new Document. The information shared must be restricted to
  // same-origin Documents.
  const bool is_same_origin =
      frame_tree_node_->current_origin().IsSameOriginWith(
          is_running_potential_prerender_activation_checks_
              ? GetTentativeOriginAtRequestTime()
              : *GetOriginToCommit());
  if (!is_same_origin) {
    return nullptr;
  }

  auto page_swap_event_params = blink::mojom::PageSwapEventParams::New();
  page_swap_event_params->url = common_params_->url;

  switch (common_params_->navigation_type) {
    case blink::mojom::NavigationType::RELOAD:
    case blink::mojom::NavigationType::RELOAD_BYPASSING_CACHE:
      page_swap_event_params->navigation_type =
          blink::mojom::NavigationTypeForNavigationApi::kReload;
      break;

    case blink::mojom::NavigationType::RESTORE:
    case blink::mojom::NavigationType::RESTORE_WITH_POST:
      // When traversing to a restored entry, we use these navigation types.
      // Process them same as traverse navigations.
    case blink::mojom::NavigationType::HISTORY_DIFFERENT_DOCUMENT:
      page_swap_event_params->navigation_type =
          blink::mojom::NavigationTypeForNavigationApi::kTraverse;
      page_swap_event_params->page_state = commit_params_->page_state;
      break;

    case blink::mojom::NavigationType::DIFFERENT_DOCUMENT:
      page_swap_event_params->navigation_type =
          common_params_->should_replace_current_entry
              ? blink::mojom::NavigationTypeForNavigationApi::kReplace
              : blink::mojom::NavigationTypeForNavigationApi::kPush;
      break;

    case blink::mojom::NavigationType::HISTORY_SAME_DOCUMENT:
    case blink::mojom::NavigationType::SAME_DOCUMENT:
      NOTREACHED() << "Same-document navigations shouldn't fire pageswap";
  }

  return page_swap_event_params;
}

std::optional<NavigationDiscardReason>
NavigationRequest::GetNavigationDiscardReason() {
  return navigation_discard_reason_;
}

NavigationDiscardReason NavigationRequest::GetTypeForNavigationDiscardReason() {
  if (NavigationTypeUtils::IsReload(common_params_->navigation_type)) {
    return NavigationDiscardReason::kNewReloadNavigation;
  }

  if (NavigationTypeUtils::IsHistory(common_params_->navigation_type)) {
    return NavigationDiscardReason::kNewHistoryNavigation;
  }

  if (IsRendererInitiated()) {
    return NavigationDiscardReason::kNewOtherNavigationRendererInitiated;
  }
  return NavigationDiscardReason::kNewOtherNavigationBrowserInitiated;
}

std::optional<ukm::builders::NavigationTimeline>
NavigationRequest::GetNavigationTimelineUkmBuilder() {
  if (ShouldRecordNavigationTimelineUkm() && IsInMainFrame() &&
      // UKM data is sampled at a frequency of `kUkmSamplingRate`.
      base::RandDouble() < kUkmSamplingRate) {
    return ukm::builders::NavigationTimeline(GetNextPageUkmSourceId());
  }
  return std::nullopt;
}

bool NavigationRequest::ShouldRecordNavigationTimelineUkm() const {
  return !IsSameDocument() && !IsRestore() &&
         !NavigationTypeUtils::IsHistory(common_params_->navigation_type) &&
         !NavigationTypeUtils::IsReload(common_params_->navigation_type) &&
         common_params_->url.SchemeIsHTTPOrHTTPS() &&
         !IsPrerenderedPageActivation();
}

void NavigationRequest::MaybeRecordTraceEventsAndHistograms() {
  if (navigation_handle_timing_.navigation_commit_sent_time.is_null()) {
    return;
  }

  bool record_metrics = ShouldRecordNavigationTimelineUkm();

  DCHECK(!blink::IsRendererDebugURL(common_params_->url));
  base::TimeTicks navigation_start_time = common_params_->navigation_start;
  DCHECK(!navigation_start_time.is_null());
  const auto trace_id =
      perfetto::NamedTrack("NavigationBreakdown", navigation_id_);
  const base::TimeTicks loader_start_time =
      navigation_handle_timing_.loader_start_time;
  const base::TimeTicks first_request_start_time =
      navigation_handle_timing_.first_request_start_time;
  const base::TimeTicks navigation_commit_sent_time =
      navigation_handle_timing_.navigation_commit_sent_time;

#define MAYBE_RECORD_TRACE_AND_HISTOGRAM0(name, begin_time, end_time) \
  do {                                                                \
    if (!begin_time.is_null() && !end_time.is_null() &&               \
        navigation_start_time <= begin_time &&                        \
        end_time <= navigation_commit_sent_time) {                    \
      TRACE_EVENT_BEGIN("navigation", name, trace_id, begin_time);    \
      TRACE_EVENT_END("navigation", trace_id, end_time);              \
      if (record_metrics) {                                           \
        base::UmaHistogramTimes(                                      \
            "Navigation.MainFrame.NewNavigation.IgnoreRestore."       \
            "IsHTTPOrHTTPS." name ".Time2",                           \
            end_time - begin_time);                                   \
      }                                                               \
    }                                                                 \
  } while (0)

#define MAYBE_RECORD_TRACE_AND_HISTOGRAM1(name, begin_time, end_time,        \
                                          arg1_name, arg1_val)               \
  do {                                                                       \
    if (!begin_time.is_null() && !end_time.is_null() &&                      \
        navigation_start_time <= begin_time &&                               \
        end_time <= navigation_commit_sent_time) {                           \
      TRACE_EVENT_BEGIN("navigation", name, trace_id, begin_time, arg1_name, \
                        arg1_val);                                           \
      TRACE_EVENT_END("navigation", trace_id, end_time);                     \
      if (record_metrics) {                                                  \
        base::UmaHistogramTimes(                                             \
            "Navigation.MainFrame.NewNavigation.IgnoreRestore."              \
            "IsHTTPOrHTTPS." name ".Time2",                                  \
            end_time - begin_time);                                          \
      }                                                                      \
    }                                                                        \
  } while (0)

  MAYBE_RECORD_TRACE_AND_HISTOGRAM0("NavigationStartToBeginNavigation",
                                    navigation_start_time,
                                    begin_navigation_time_);
  MAYBE_RECORD_TRACE_AND_HISTOGRAM0("BeginNavigationToLoaderStart",
                                    begin_navigation_time_, loader_start_time);
  MAYBE_RECORD_TRACE_AND_HISTOGRAM1("LoaderStartToReceiveResponse",
                                    loader_start_time, receive_response_time_,
                                    "URL", common_params_->url.spec());

  // `first_fetch_start_time_` can be earlier than
  // `loader_start_time` when Prefetch or Prerendering
  // is enabled. The following UMAs are not recorded in such cases because it
  // will skew the data. Also the following trace events are not recorded in
  // such cases because such traces will not be rendered correctly.
  if (loader_start_time <= first_fetch_start_time_) {
    MAYBE_RECORD_TRACE_AND_HISTOGRAM0(
        "LoaderStartToFetchStart", loader_start_time, first_fetch_start_time_);
    MAYBE_RECORD_TRACE_AND_HISTOGRAM0("FetchStart", first_fetch_start_time_,
                                      first_request_start_time);
    MAYBE_RECORD_TRACE_AND_HISTOGRAM0("ReceiveHeaders",
                                      first_request_start_time,
                                      final_receive_headers_end_time_);
    MAYBE_RECORD_TRACE_AND_HISTOGRAM0("ReceiveHeadersToReceiveResponse",
                                      final_receive_headers_end_time_,
                                      receive_response_time_);
  }

  MAYBE_RECORD_TRACE_AND_HISTOGRAM0("ReceiveResponseToCommitNavigation",
                                    receive_response_time_,
                                    navigation_commit_sent_time);

  // UKM data is sampled at a frequency of `kUkmSamplingRate`.
  if (record_metrics && base::RandDouble() < kUkmSamplingRate &&
      !navigation_start_time.is_null() && !begin_navigation_time_.is_null() &&
      !loader_start_time.is_null() && !receive_response_time_.is_null() &&
      navigation_start_time <= begin_navigation_time_ &&
      begin_navigation_time_ <= loader_start_time &&
      loader_start_time <= receive_response_time_ &&
      receive_response_time_ <= navigation_commit_sent_time) {
    ukm::builders::NavigationRequestBreakDown ukm(GetNextPageUkmSourceId());
    ukm.SetNavigationStartToBeginNavigation(
           (begin_navigation_time_ - navigation_start_time).InMilliseconds())
        .SetBeginNavigationToLoaderStart(
            (loader_start_time - begin_navigation_time_).InMilliseconds())
        .SetLoaderStartToReceiveResponse(
            (receive_response_time_ - loader_start_time).InMilliseconds())
        .SetReceiveResponseToCommitNavigation(
            (navigation_commit_sent_time - receive_response_time_)
                .InMilliseconds());

    // To avoid affecting other metrics, we check the following conditions
    // separately. These conditions should usually be true, but there can be
    // uncommon error cases.
    if (!first_fetch_start_time_.is_null() &&
        !first_request_start_time.is_null() &&
        loader_start_time <= first_fetch_start_time_ &&
        first_fetch_start_time_ <= first_request_start_time) {
      ukm.SetLoaderStartToFetchStart(
             (first_fetch_start_time_ - loader_start_time).InMilliseconds())
          .SetFetchStartToRequestStart(
              (first_request_start_time - first_fetch_start_time_)
                  .InMilliseconds());
    }

    ukm.Record(ukm::UkmRecorder::Get());
  }

#undef MAYBE_RECORD_TRACE_AND_HISTOGRAM0
#undef MAYBE_RECORD_TRACE_AND_HISTOGRAM1
}

void NavigationRequest::MaybeRecordNavigationStartAdjustments() {
  // Only record metrics if we have a navigation start time.
  if (common_params().navigation_start.is_null()) {
    return;
  }

  if (IsSameDocument()) {
    // No adjustments are made for same-document navigations.
    CHECK(original_navigation_start_.is_null());
    return;
  }

  // Some navigations do not adjust the start time, in which case
  // `original_navigation_start_` is left as null.
  if (original_navigation_start_.is_null()) {
    base::UmaHistogramEnumeration("Navigation.StartAdjustment.AllFrames",
                                  NavigationStartAdjustmentType::kNone);
    if (IsInPrimaryMainFrame()) {
      base::UmaHistogramEnumeration("Navigation.StartAdjustment.MainFrameOnly",
                                    NavigationStartAdjustmentType::kNone);
    }
    return;
  }

  // Compute the adjustment made and what percentage of the total navigation
  // time it includes (approximating now as the end of the navigation).
  base::TimeDelta adjustment =
      common_params().navigation_start - original_navigation_start_;
  base::TimeDelta original_start_to_finish =
      base::TimeTicks::Now() - original_navigation_start_;
  // Note that in unit tests, all timestamps can be the same. Skip recording
  // duration metrics if no time has elapsed during the navigation.
  if (original_start_to_finish.is_zero()) {
    return;
  }

  // Report the adjustment in UMA metrics specific to the case that occurred.
  NavigationStartAdjustmentType adjustment_type =
      NavigationStartAdjustmentType::kNone;
  std::string histogram_name = "Navigation.StartAdjustment";
  if (navigation_start_adjustment_for_legacy_) {
    // No beforeunload handlers actually run in legacy mode.
    CHECK(!beforeunload_dialog_shown_);
    adjustment_type = NavigationStartAdjustmentType::kLegacyPostTask;
    histogram_name += ".LegacyPostTask";
  } else if (!beforeunload_dialog_shown_) {
    adjustment_type = NavigationStartAdjustmentType::kBeforeUnloadHandlers;
    histogram_name += ".BeforeUnloadHandlers";
  } else {
    adjustment_type = NavigationStartAdjustmentType::kBeforeUnloadDialog;
    histogram_name += ".BeforeUnloadDialog";
  }
  base::UmaHistogramEnumeration("Navigation.StartAdjustment.AllFrames",
                                adjustment_type);
  if (IsInPrimaryMainFrame()) {
    base::UmaHistogramEnumeration("Navigation.StartAdjustment.MainFrameOnly",
                                  adjustment_type);
  }

  // It is currently possible for the adjustment to be negative, due to a bug
  // where the updated start time from an earlier navigation is applied to the
  // current NavigationRequest. See https://crbug.com/385170155.
  if (adjustment.is_negative()) {
    // In this case, report the absolute value of the adjustment in a different
    // per-type metric, without reporting the (ill-defined) percentage or trying
    // to create a trace event.
    histogram_name += ".Negative";
    base::UmaHistogramTimes(histogram_name, adjustment.magnitude());
    return;
  }

  // The duration of the navigation should never be negative. For now, return
  // early if that happens, after reporting a DumpWithoutCrashing. Upgrade this
  // to a CHECK failure if no reports are received by M135.
  if (original_start_to_finish.is_negative()) {
    NOTREACHED() << original_start_to_finish;
  }

  base::UmaHistogramTimes(histogram_name, adjustment);
  size_t percentage = 100 * adjustment / original_start_to_finish;
  base::UmaHistogramPercentage(histogram_name + ".Percentage", percentage);

  // Show trace events indicating where the adjustment occurred in time.
  const auto trace_id =
      perfetto::NamedTrack("NavigationStartAdjustment", navigation_id_);
  TRACE_EVENT_BEGIN("navigation", "NavigationStartAdjustment", trace_id,
                    original_navigation_start_, "Percentage", percentage);
  TRACE_EVENT_END("navigation", trace_id, common_params().navigation_start);
}

void NavigationRequest::WillStartBeforeUnload() {
  SetWaitingForRendererResponse();
  beforeunload_phase2_start_time_ = base::TimeTicks().Now();
}

NavigationRequest::Timeline::Timeline() = default;
NavigationRequest::Timeline::Timeline(
    const NavigationRequest::Timeline& timeline) = default;
NavigationRequest::Timeline::~Timeline() = default;

void NavigationRequest::Timeline::MarkFinish() {
  finish = base::TimeTicks().Now();
}

NavigationRequest::Timeline
NavigationRequest::GenerateNavigationTimelineForMetrics(
    const mojom::DidCommitProvisionalLoadParams& params,
    const base::TimeTicks& did_commit_ipc_received_time) {
  NavigationRequest::Timeline timeline;

  if (is_synchronous_renderer_commit()) {
    // For synchronous renderer commits, the start time in the renderer process
    // should be provided in `actual_navigation_start`.
    if (!common_params().actual_navigation_start.is_null()) {
      timeline.start = common_params().actual_navigation_start;
    } else {
      // If `actual_navigation_start` is unexpectedly missing, fall back to the
      // time this IPC was received.
      timeline.start = did_commit_ipc_received_time;
    }
  } else if (!common_params().actual_navigation_start.is_null()) {
    // Use the actual start time if it is provided, and record how long was
    // spent on beforeunload phase 1 in the initiating renderer (if any).
    timeline.start = common_params().actual_navigation_start;
    if (!begin_params().before_unload_start.is_null()) {
      timeline.beforeunload_phase1_start = begin_params().before_unload_start;
      timeline.beforeunload_phase1_end = begin_params().before_unload_end;
    }
  } else {
    // For any legacy cases where the actual start time isn't provided, fall
    // back to the `navigation_start` used by web-exposed metrics. However, if
    // the navigation start time was adjusted due to beforeunload processing,
    // use the original timestamp to ensure that the trace event start time is
    // still accurate.
    //
    // TODO(alexmos): examine whether these timestamps, as well as their other
    // uses, should use InterProcessTimeTicksConverter since they may come from
    // the renderer process.
    timeline.start = !original_navigation_start_.is_null()
                         ? original_navigation_start_
                         : common_params().navigation_start;
  }

  timeline.navigation_request_creation = creation_time_;
  if (!beforeunload_phase2_start_time_.is_null()) {
    timeline.beforeunload_phase2_start = beforeunload_phase2_start_time_;
    timeline.beforeunload_phase2_end = beforeunload_phase2_end_time_;
  }
  timeline.common_params_start = common_params().navigation_start;
  timeline.begin_navigation = begin_navigation_time_;
  timeline.loader_start = navigation_handle_timing_.loader_start_time;
  if (!IsPageActivation()) {
    // Prerender and bfcache activations should not use the stale loader values
    // from the original commit. (Note: `loader_start` and `receive_response`
    // are both set to fresh values for page activations.)
    timeline.loader_fetch_start = first_fetch_start_time_;
    timeline.loader_receive_headers = final_receive_headers_end_time_;
  }
  timeline.receive_response = receive_response_time_;
  timeline.commit_ipc_sent =
      !IsPageActivation()
          ? navigation_handle_timing_.navigation_commit_sent_time
          : page_activation_commit_time_;

  // Note that we can't use NavigationRequest's
  // navigation_handle_timing_.navigation_commit_received_time because it's
  // not populated yet when this function is called.
  if (!IsPageActivation()) {
    timeline.renderer_commit_ipc_received = params.commit_navigation_start;
    timeline.renderer_did_commit_ipc_sent = params.commit_reply_sent;
    timeline.did_commit_ipc_received = did_commit_ipc_received_time;
  } else {
    // Page activations don't send a commit IPC, so use a zero size interval.
    timeline.did_commit_ipc_received = timeline.commit_ipc_sent;
  }

  return timeline;
}

void NavigationRequest::SanitizeDocumentIsolationPolicyHeader() {
  if (!response_head_) {
    return;
  }

  // If the DocumentIsolationPolicy feature is not enabled, set its
  // DocumentIsolationPolicy to its default value.
  if (!base::FeatureList::IsEnabled(
          network::features::kDocumentIsolationPolicy)) {
    response_head_->parsed_headers->document_isolation_policy =
        network::DocumentIsolationPolicy();
    return;
  }

  // DocumentIsolationPolicy is only supported in strict SiteIsolation mode for
  // now. Set it to its default value if the platform does not support strict
  // SiteIsolation.
  if (!SiteIsolationPolicy::UseDedicatedProcessesForAllSites()) {
    response_head_->parsed_headers->document_isolation_policy =
        network::DocumentIsolationPolicy();
    return;
  }

  network::DocumentIsolationPolicy& dip =
      response_head_->parsed_headers->document_isolation_policy;
  bool has_dip_header =
      dip.value != network::mojom::DocumentIsolationPolicyValue::kNone ||
      dip.report_only_value !=
          network::mojom::DocumentIsolationPolicyValue::kNone ||
      dip.reporting_endpoint || dip.report_only_reporting_endpoint;

  // DocumentIsolationPolicy should only be used by secure contexts.
  if (!network::IsUrlPotentiallyTrustworthy(GetURL()) && has_dip_header) {
    response_head_->parsed_headers->document_isolation_policy =
        network::DocumentIsolationPolicy();
    AddDeferredConsoleMessage(
        blink::mojom::ConsoleMessageLevel::kError,
        "The Document-Isolation-Policy header has been ignored because "
        "the URL's origin was untrustworthy. Please deliver the response using "
        "the HTTPS protocol. You can also use the 'localhost' origin "
        "instead. See "
        "https://www.w3.org/TR/powerful-features/"
        "#potentially-trustworthy-origin.");
  }
}

void NavigationRequest::ValidateCommitOrigin(
    const url::Origin& origin_to_commit) {
  NavigationEntryImpl* nav_entry =
      static_cast<NavigationEntryImpl*>(GetNavigationEntry());
  if (!nav_entry) {
    return;
  }

  FrameNavigationEntry* frame_entry =
      nav_entry->GetFrameEntry(frame_tree_node_);
  if (!frame_entry || !frame_entry->committed_origin().has_value()) {
    return;
  }

  const url::Origin& expected_origin = frame_entry->committed_origin().value();
  bool origins_match = false;
  // Current weakened check: allows precursor tuple comparison if *either*
  // origin is opaque. This is a temporary workaround because sandbox
  // navigations do not currently clear PageState properly.
  //
  // TODO(crbug.com/421948889): After this bug is fixed, tighten this check
  // to only allow precursor tuple comparison if *both* origins are opaque.
  if (expected_origin.opaque() || origin_to_commit.opaque()) {
    // Both origins are opaque — compare by their precursor tuples.
    origins_match = expected_origin.GetTupleOrPrecursorTupleIfOpaque() ==
                    origin_to_commit.GetTupleOrPrecursorTupleIfOpaque();
  } else {
    // If either is non-opaque, use regular strict comparison.
    origins_match = expected_origin.IsSameOriginWith(origin_to_commit);
  }

  if (!origins_match) {
    // TODO(crbug.com/420965165): In redirects or other origin-changing
    // cases (e.g., CSP), FrameNavigationEntry may retain a stale
    // committed_origin(). We should clear it when the origin changes, so
    // that if it exists at commit time, it can be trusted to match.
    //
    // In the meantime, it’s safe for a stale committed_origin() to stick
    // around **only** if there’s no origin-related state (e.g., PageState)
    // being sent in commit_params_.
    CHECK(commit_params_->page_state.empty(), base::NotFatalUntil::M140)
        << "PageState wasn't cleared after a commit origin mismatch."
        << "expected_origin: " << expected_origin
        << ", origin_to_commit: " << origin_to_commit;
  }
}

PrerenderHostId NavigationRequest::GetPrerenderHostId() const {
  return prerender_host_id_;
}

}  // namespace content
