// 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/fingerprinting_protection/canvas_noise_token_data.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/renderer_host/system_entropy_utils.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) {
  // Experimental: Storage Access API Headers
  // (https://github.com/cfredric/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_params->navigation_timing->system_entropy_at_navigation_start =
      SystemEntropyUtils::ComputeSystemEntropyForFrameTreeNode(
          frame_tree_node, blink::mojom::SystemEntropy::kNormal);

  // 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());
  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->commit_params_->navigation_timing
      ->system_entropy_at_navigation_start =
      SystemEntropyUtils::ComputeSystemEntropyForFrameTreeNode(
          frame_tree_node, blink::mojom::SystemEntropy::kNormal);
  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->is_hidden() && 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_));

  // 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.
  base::SequencedTaskRunner::GetCurrentDefault()->PostNonNestableTask(
      FROM_HERE,
      base::BindOnce(&NavigationRequest::RunCommitDeferringConditions,
                     weak_factory_.GetWeakPtr()));
  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() {
  // The `CookieChangeListener` will only be set up 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 cookie change information will only be
  // used to determined 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();
}

bool NavigationRequest::ShouldAddDeviceBoundSessionObserver() {
  // Device bound session expiry should evict pages from the BFCache in
  // the exact same circumstances as cookie expiry.
  return ShouldAddCookieChangeListener();
}

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`.
  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);
  }

  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.
    CommitErrorPage(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;
  net::HttpRequestHeaders cors_exempt_headers;
  std::swap(cors_exempt_headers, cors_exempt_request_headers_);

  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(),
          std::move(cors_exempt_headers),
          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 = "";
    }
  }

  net::HttpRequestHeaders cors_exempt_headers;
  std::swap(cors_exempt_headers, cors_exempt_request_headers_);
  loader_->FollowRedirect(std::move(removed_headers),
                          std::move(modified_headers),
                          std::move(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().
  CommitErrorPage(result.error_page_content());
  // DO NOT ADD CODE after this. The previous call to CommitErrorPage()
  // 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();
  // 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() {
  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) {
  switch (navigation_type) {
    case CommitDeferringCondition::NavigationType::kPrerenderedPageActivation:
      OnPrerenderingActivationChecksComplete(
          navigation_type, candidate_prerender_frame_tree_node_id);
      // DO NOT ADD CODE after this. The previous call to
      // OnPrerenderingActivationChecksComplete caused the destruction of the
      // NavigationRequest.
      return;
    case CommitDeferringCondition::NavigationType::kOther:
      DCHECK_LT(state_, READY_TO_COMMIT);
      CommitNavigation();
      // DO NOT ADD CODE after this. The previous call to CommitNavigation
      // caused the destruction of the NavigationRequest.
      return;
  }
}

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;

  if (request_navigation_client_.is_bound()) {
    if (GetRenderFrameHost() ==
        RenderFrameHostImpl::FromID(
            current_render_frame_host_id_at_construction_)) {
      // Reuse the request NavigationClient for commit.
      commit_navigation_client_ = std::move(request_navigation_client_);
    } else {
      // This navigation is cross-RenderFrameHost: the original document should
      // no longer be able to cancel it.
      IgnoreInterfaceDisconnection();
    }
  }

  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());

  if (request_navigation_client_.is_bound()) {
    if (GetRenderFrameHost() ==
        RenderFrameHostImpl::FromID(
            current_render_frame_host_id_at_construction_)) {
      // Reuse the request NavigationClient for commit.
      commit_navigation_client_ = std::move(request_navigation_client_);
    } else {
      // This navigation is cross-RenderFrameHost: the original document should
      // no longer be able to cancel it.
      IgnoreInterfaceDisconnection();
    }
  }

  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,
      begin_params_->is_form_submission, 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()) {
    // 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::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();
  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());
    }
  }

  // Populate the canvas noise token if this is a main frame navigation. Canvas
  // noise tokens should be generated based on the resolved origin, which is
  // available at |ReadyToCommit| time. Eventually, prior to commit, this value
  // will be used to sync blink::Pages with this token value, and subsequent
  // subframe navigations will inherit this token to populate their
  // blink::Pages.
  if (IsInMainFrame()) {
    BrowserContext* browser_context =
        frame_tree_node()->navigator().controller().GetBrowserContext();
    canvas_noise_token_ =
        GetContentClient()->browser()->ShouldEnableCanvasNoise(
            browser_context, origin_to_commit->GetURL())
            ? std::optional(CanvasNoiseTokenData::GetToken(
                  browser_context, origin_to_commit.value()))
            : std::nullopt;
  }

  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::SetCorsExemptRequestHeader(
    const std::string& header_name,
    const std::string& header_value) {
  DCHECK(state_ == WILL_START_REQUEST || state_ == WILL_REDIRECT_REQUEST);
  cors_exempt_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);

      // 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 (!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_;
}

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