// Copyright 2017 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/loader/navigation_url_loader_impl.h"

#include <map>
#include <memory>
#include <optional>
#include <string_view>
#include <utility>

#include "base/check_is_test.h"
#include "base/command_line.h"
#include "base/containers/contains.h"
#include "base/debug/crash_logging.h"
#include "base/debug/dump_without_crashing.h"
#include "base/feature_list.h"
#include "base/functional/bind.h"
#include "base/functional/callback_helpers.h"
#include "base/memory/scoped_refptr.h"
#include "base/metrics/histogram_functions.h"
#include "base/metrics/histogram_macros.h"
#include "base/strings/strcat.h"
#include "base/strings/string_number_conversions.h"
#include "base/task/common/task_annotator.h"
#include "base/trace_event/trace_event.h"
#include "build/build_config.h"
#include "components/download/public/common/download_stats.h"
#include "content/browser/about_url_loader_factory.h"
#include "content/browser/attribution_reporting/attribution_manager.h"
#include "content/browser/blob_storage/chrome_blob_storage_context.h"
#include "content/browser/client_hints/client_hints.h"
#include "content/browser/data_url_loader_factory.h"
#include "content/browser/devtools/devtools_instrumentation.h"
#include "content/browser/file_system/file_system_url_loader_factory.h"
#include "content/browser/loader/file_url_loader_factory.h"
#include "content/browser/loader/navigation_early_hints_manager.h"
#include "content/browser/loader/navigation_loader_interceptor.h"
#include "content/browser/loader/navigation_url_loader_delegate.h"
#include "content/browser/loader/response_head_update_params.h"
#include "content/browser/loader/subresource_proxying_url_loader_service.h"
#include "content/browser/loader/url_loader_factory_utils.h"
#include "content/browser/navigation_subresource_loader_params.h"
#include "content/browser/preloading/prefetch/prefetch_features.h"
#include "content/browser/preloading/prefetch/prefetch_url_loader_interceptor.h"
#include "content/browser/renderer_host/frame_tree_node.h"
#include "content/browser/renderer_host/navigation_request.h"
#include "content/browser/renderer_host/navigation_request_info.h"
#include "content/browser/service_worker/service_worker_client.h"
#include "content/browser/service_worker/service_worker_main_resource_handle.h"
#include "content/browser/service_worker/service_worker_main_resource_loader_interceptor.h"
#include "content/browser/storage_partition_impl.h"
#include "content/browser/url_loader_factory_params_helper.h"
#include "content/browser/web_contents/web_contents_impl.h"
#include "content/browser/web_package/prefetched_signed_exchange_cache.h"
#include "content/browser/web_package/signed_exchange_consts.h"
#include "content/browser/web_package/signed_exchange_request_handler.h"
#include "content/browser/web_package/signed_exchange_utils.h"
#include "content/browser/webui/url_data_manager_backend.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/client_hints.h"
#include "content/public/browser/client_hints_controller_delegate.h"
#include "content/public/browser/content_browser_client.h"
#include "content/public/browser/download_utils.h"
#include "content/public/browser/frame_accept_header.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/shared_cors_origin_access_list.h"
#include "content/public/browser/ssl_status.h"
#include "content/public/browser/url_loader_request_interceptor.h"
#include "content/public/browser/url_loader_throttles.h"
#include "content/public/browser/web_ui_url_loader_factory.h"
#include "content/public/common/buildflags.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/referrer.h"
#include "content/public/common/url_constants.h"
#include "content/public/common/url_utils.h"
#include "content/public/common/webplugininfo.h"
#include "media/media_buildflags.h"
#include "mojo/public/cpp/bindings/receiver.h"
#include "mojo/public/cpp/bindings/remote.h"
#include "net/base/features.h"
#include "net/base/load_flags.h"
#include "net/base/load_timing_info.h"
#include "net/cert/sct_status_flags.h"
#include "net/cert/signed_certificate_timestamp_and_status.h"
#include "net/cookies/cookie_setting_override.h"
#include "net/http/http_content_disposition.h"
#include "net/http/http_request_headers.h"
#include "net/http/http_status_code.h"
#include "net/ssl/ssl_info.h"
#include "net/traffic_annotation/network_traffic_annotation.h"
#include "net/url_request/redirect_util.h"
#include "services/metrics/public/cpp/metrics_utils.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/constants.h"
#include "services/network/public/cpp/features.h"
#include "services/network/public/cpp/parsed_headers.h"
#include "services/network/public/cpp/request_destination.h"
#include "services/network/public/cpp/url_loader_completion_status.h"
#include "services/network/public/cpp/url_loader_factory_builder.h"
#include "services/network/public/cpp/url_util.h"
#include "services/network/public/cpp/web_sandbox_flags.h"
#include "services/network/public/cpp/wrapper_shared_url_loader_factory.h"
#include "services/network/public/mojom/network_context.mojom-forward.h"
#include "services/network/public/mojom/network_service.mojom.h"
#include "third_party/blink/public/common/features.h"
#include "third_party/blink/public/common/loader/mime_sniffing_throttle.h"
#include "third_party/blink/public/common/loader/record_load_histograms.h"
#include "third_party/blink/public/common/loader/throttling_url_loader.h"
#include "third_party/blink/public/common/mime_util/mime_util.h"
#include "third_party/blink/public/common/storage_key/storage_key.h"
#include "third_party/blink/public/mojom/service_worker/service_worker_router_rule.mojom.h"
#include "url/origin.h"

#if BUILDFLAG(IS_ANDROID)
#include "content/browser/android/content_url_loader_factory.h"
#endif

#if BUILDFLAG(ENABLE_PLUGINS)
#include "content/public/browser/plugin_service.h"
#endif

namespace content {

namespace {

class NavigationLoaderInterceptorBrowserContainer
    : public NavigationLoaderInterceptor {
 public:
  explicit NavigationLoaderInterceptorBrowserContainer(
      std::unique_ptr<URLLoaderRequestInterceptor> browser_interceptor)
      : browser_interceptor_(std::move(browser_interceptor)) {}

  ~NavigationLoaderInterceptorBrowserContainer() override = default;

  void MaybeCreateLoader(
      const network::ResourceRequest& tentative_resource_request,
      BrowserContext* browser_context,
      LoaderCallback callback,
      FallbackCallback fallback_callback) override {
    browser_interceptor_->MaybeCreateLoader(
        tentative_resource_request, browser_context,
        base::BindOnce(
            [](LoaderCallback callback,
               URLLoaderRequestInterceptor::RequestHandler handler) {
              if (handler) {
                std::move(callback).Run(NavigationLoaderInterceptor::Result(
                    base::MakeRefCounted<
                        network::SingleRequestURLLoaderFactory>(
                        std::move(handler)),
                    /*subresource_loader_params=*/{}));
              } else {
                std::move(callback).Run(std::nullopt);
              }
            },
            std::move(callback)));
  }

  bool MaybeCreateLoaderForResponse(
      const network::URLLoaderCompletionStatus& status,
      const network::ResourceRequest& request,
      network::mojom::URLResponseHeadPtr* response_head,
      mojo::ScopedDataPipeConsumerHandle* response_body,
      mojo::PendingRemote<network::mojom::URLLoader>* loader,
      mojo::PendingReceiver<network::mojom::URLLoaderClient>* client_receiver,
      blink::ThrottlingURLLoader* url_loader,
      bool* skip_other_interceptors) override {
    return browser_interceptor_->MaybeCreateLoaderForResponse(
        status, request, response_head, response_body, loader, client_receiver,
        url_loader);
  }

 private:
  std::unique_ptr<URLLoaderRequestInterceptor> browser_interceptor_;
};

class NavigationTimingThrottle : public blink::URLLoaderThrottle {
 public:
  NavigationTimingThrottle(bool is_outermost_main_frame, base::TimeTicks start)
      : is_outermost_main_frame_(is_outermost_main_frame), start_(start) {}

  void WillStartRequest(network::ResourceRequest* request,
                        bool* defer) override {
    base::UmaHistogramTimes(
        base::StrCat({"Navigation.LoaderCreateToRequestStart.",
                      is_outermost_main_frame_ ? "MainFrame" : "Subframe"}),
        base::TimeTicks::Now() - start_);
  }

 private:
  bool is_outermost_main_frame_;
  base::TimeTicks start_;
};

const net::NetworkTrafficAnnotationTag kNavigationUrlLoaderTrafficAnnotation =
    net::DefineNetworkTrafficAnnotation("navigation_url_loader", R"(
      semantics {
        sender: "Navigation URL Loader"
        description:
          "This request is issued by a main frame navigation to fetch the "
          "content of the page that is being navigated to."
        trigger:
          "Navigating Chrome (by clicking on a link, bookmark, history item, "
          "using session restore, etc)."
        data:
          "Arbitrary site-controlled data can be included in the URL, HTTP "
          "headers, and request body. Requests may include cookies and "
          "site-specific credentials."
        destination: WEBSITE
      }
      policy {
        cookies_allowed: YES
        cookies_store: "user"
        setting: "This feature cannot be disabled."
        chrome_policy {
          URLBlocklist {
            URLBlocklist: { entries: '*' }
          }
        }
        chrome_policy {
          URLAllowlist {
            URLAllowlist { }
          }
        }
      }
      comments:
        "Chrome would be unable to navigate to websites without this type of "
        "request. Using either URLBlocklist or URLAllowlist policies (or a "
        "combination of both) limits the scope of these requests."
      )");

std::unique_ptr<network::ResourceRequest> CreateResourceRequest(
    const NavigationRequestInfo& request_info,
    FrameTreeNode* frame_tree_node,
    ClientHintsControllerDelegate* client_hints_controller_delegate,
    mojo::PendingRemote<network::mojom::CookieAccessObserver> cookie_observer,
    mojo::PendingRemote<network::mojom::TrustTokenAccessObserver>
        trust_token_observer,
    mojo::PendingRemote<network::mojom::SharedDictionaryAccessObserver>
        shared_dictionary_observer,
    mojo::PendingRemote<network::mojom::URLLoaderNetworkServiceObserver>
        url_loader_network_observer,
    mojo::PendingRemote<network::mojom::DevToolsObserver> devtools_observer,
    mojo::PendingRemote<network::mojom::DeviceBoundSessionAccessObserver>
        device_bound_session_observer,
    mojo::PendingRemote<network::mojom::AcceptCHFrameObserver>
        accept_ch_frame_observer) {
  auto new_request = CreateResourceRequestForNavigation(
      request_info.common_params->method, request_info.common_params->url,
      request_info.common_params->request_destination,
      *request_info.common_params->referrer, request_info.isolation_info,
      std::move(devtools_observer), /*priority=*/net::HIGHEST,
      request_info.is_main_frame);

  new_request->trusted_params->cookie_observer = std::move(cookie_observer);
  new_request->trusted_params->trust_token_observer =
      std::move(trust_token_observer);
  new_request->trusted_params->shared_dictionary_observer =
      std::move(shared_dictionary_observer);
  new_request->trusted_params->url_loader_network_observer =
      std::move(url_loader_network_observer);
  new_request->trusted_params->device_bound_session_observer =
      std::move(device_bound_session_observer);
  new_request->trusted_params->client_security_state =
      request_info.client_security_state.Clone();
  new_request->trusted_params->accept_ch_frame_observer =
      std::move(accept_ch_frame_observer);
  new_request->trusted_params->allow_cookies_from_browser =
      request_info.allow_cookies_from_browser;
  new_request->is_outermost_main_frame = request_info.is_outermost_main_frame;
  new_request->request_initiator = request_info.common_params->initiator_origin;
  new_request->headers.AddHeadersFromString(request_info.begin_params->headers);
  new_request->cors_exempt_headers = request_info.cors_exempt_headers;
  new_request->devtools_accepted_stream_types =
      request_info.devtools_accepted_stream_types;
  // For ResourceType purposes, fenced frames are considered a kSubFrame.
  new_request->resource_type =
      static_cast<int>(request_info.is_outermost_main_frame
                           ? blink::mojom::ResourceType::kMainFrame
                           : blink::mojom::ResourceType::kSubFrame);

  int load_flags = request_info.begin_params->load_flags;
  if (request_info.is_outermost_main_frame) {
    load_flags |= net::LOAD_MAIN_FRAME_DEPRECATED;
    load_flags |= net::LOAD_CAN_USE_RESTRICTED_PREFETCH_FOR_MAIN_FRAME;
  }

  if (URLLoaderFactoryParamsHelper::IsMainFrameOriginRecentlyAccessed(
          request_info.isolation_info)) {
    load_flags |= net::LOAD_IS_MAIN_FRAME_ORIGIN_RECENTLY_ACCESSED;
  }

  // Sync loads should have maximum priority and should be the only
  // requests that have the ignore limits flag set.
  DCHECK(!(load_flags & net::LOAD_IGNORE_LIMITS));

  new_request->load_flags = load_flags;

  new_request->request_body = request_info.common_params->post_data.get();
  new_request->has_user_gesture = request_info.common_params->has_user_gesture;

  if (ui::PageTransitionIsWebTriggerable(
          ui::PageTransitionFromInt(request_info.common_params->transition))) {
    new_request->trusted_params->has_user_activation =
        request_info.common_params->has_user_gesture;
  } else {
    new_request->trusted_params->has_user_activation = true;
  }

  new_request->upgrade_if_insecure = request_info.upgrade_if_insecure;
  new_request->throttling_profile_id = request_info.devtools_frame_token;
  new_request->transition_type = request_info.common_params->transition;
  devtools_instrumentation::MaybeAssignResourceRequestId(
      frame_tree_node, request_info.devtools_navigation_token.ToString(),
      *new_request);
  if (request_info.begin_params->trust_token_params) {
    new_request->trust_token_params =
        *request_info.begin_params->trust_token_params;
  }

  new_request->storage_access_api_status =
      request_info.begin_params->storage_access_api_status;

  WebContentsImpl* web_contents = static_cast<WebContentsImpl*>(
      WebContents::FromFrameTreeNodeId(frame_tree_node->frame_tree_node_id()));
  new_request->attribution_reporting_support =
      web_contents ? web_contents->GetAttributionSupport()
                   : AttributionManager::GetAttributionSupport(
                         /*client_os_disabled=*/false);

  new_request->attribution_reporting_eligibility =
      request_info.begin_params->impression.has_value()
          ? network::mojom::AttributionReportingEligibility::kNavigationSource
          : network::mojom::AttributionReportingEligibility::kUnset;

  new_request->shared_storage_writable_eligible =
      request_info.shared_storage_writable_eligible;
  new_request->is_ad_tagged = request_info.is_ad_tagged;

  new_request->skip_service_worker =
      request_info.begin_params->skip_service_worker;

  // TODO(crbug.com/382291442): Remove feature guarding once launched.
  if (base::FeatureList::IsEnabled(
          network::features::kPopulatePermissionsPolicyOnRequest) &&
      frame_tree_node && frame_tree_node->current_frame_host() &&
      frame_tree_node->current_frame_host()->GetPermissionsPolicy()) {
    new_request->permissions_policy =
        *frame_tree_node->current_frame_host()->GetPermissionsPolicy();
  }

  base::UmaHistogramBoolean(
      "Navigation.URLLoader.HasClientHintsControllerDelegate",
      client_hints_controller_delegate != nullptr);
  if (base::FeatureList::IsEnabled(
          network::features::kOffloadAcceptCHFrameCheck) &&
      client_hints_controller_delegate) {
    new_request->trusted_params->enabled_client_hints = GetEnabledClientHints(
        url::Origin::Create(new_request->url), frame_tree_node,
        client_hints_controller_delegate);
  }

  return new_request;
}

// Called for requests that we don't have a URLLoaderFactory for.
void UnknownSchemeCallback(
    bool handled_externally,
    const network::ResourceRequest& /* resource_request */,
    mojo::PendingReceiver<network::mojom::URLLoader> receiver,
    mojo::PendingRemote<network::mojom::URLLoaderClient> client) {
  mojo::Remote<network::mojom::URLLoaderClient>(std::move(client))
      ->OnComplete(network::URLLoaderCompletionStatus(
          handled_externally ? net::ERR_ABORTED : net::ERR_UNKNOWN_URL_SCHEME));
}

void LogQueueTimeHistogram(std::string_view name,
                           bool is_outermost_main_frame) {
  auto* task = base::TaskAnnotator::CurrentTaskForThread();
  // Only log for non-delayed tasks with a valid queue_time.
  if (!task || task->queue_time.is_null() ||
      !task->delayed_run_time.is_null()) {
    return;
  }

  base::UmaHistogramTimes(
      base::StrCat(
          {name, is_outermost_main_frame ? ".MainFrame" : ".Subframe"}),
      base::TimeTicks::Now() - task->queue_time);
}

void LogAcceptCHFrameStatus(AcceptCHFrameRestart status) {
  base::UmaHistogramEnumeration("ClientHints.AcceptCHFrame", status);
}

void RecordEnabledClientHintsMismatchHistograms(
    const network::ResourceRequest::TrustedParams::EnabledClientHints&
        old_hints,
    const network::ResourceRequest::TrustedParams::EnabledClientHints&
        new_hints) {
  constexpr std::string_view kEnabledClientHintsMatch =
      "Navigation.URLLoader.OnAcceptCHFrameReceived.EnabledClientHintsMatch";

  const bool enabled_client_hints_match = (new_hints == old_hints);
  base::UmaHistogramBoolean(kEnabledClientHintsMatch,
                            enabled_client_hints_match);

  if (enabled_client_hints_match) {
    return;
  }

  base::UmaHistogramBoolean(base::StrCat({kEnabledClientHintsMatch, ".Origin"}),
                            new_hints.origin == old_hints.origin);
  base::UmaHistogramBoolean(
      base::StrCat({kEnabledClientHintsMatch, ".IsOutermostMainFrame"}),
      new_hints.is_outermost_main_frame == old_hints.is_outermost_main_frame);

  // See services/network/public/mojom/web_client_hints_types.mojom for the
  // full list of client hints. As of 2025-08-19, there are 23 non-deprecated
  // entries.
  std::vector<network::mojom::WebClientHintsType> old_hints_vector =
      old_hints.hints;
  std::vector<network::mojom::WebClientHintsType> new_hints_vector =
      new_hints.hints;
  std::sort(old_hints_vector.begin(), old_hints_vector.end());
  std::sort(new_hints_vector.begin(), new_hints_vector.end());

  const bool are_equal = (old_hints_vector == new_hints_vector);
  base::UmaHistogramBoolean(base::StrCat({kEnabledClientHintsMatch, ".Hints"}),
                            are_equal);

  if (are_equal) {
    return;
  }

  std::vector<network::mojom::WebClientHintsType> diff;
  std::set_symmetric_difference(
      old_hints_vector.begin(), old_hints_vector.end(),
      new_hints_vector.begin(), new_hints_vector.end(),
      std::back_inserter(diff));
  for (const auto& hint : diff) {
    base::UmaHistogramEnumeration(
        "Navigation.URLLoader.OnAcceptCHFrameReceived.HintsMismatch", hint);
  }
}

bool IsSameOriginRedirect(const std::vector<GURL>& url_chain) {
  if (url_chain.size() < 2) {
    return false;
  }

  auto previous_origin = url::Origin::Create(url_chain[url_chain.size() - 2]);
  return previous_origin.IsSameOriginWith(url_chain[url_chain.size() - 1]);
}

// Return whether the inherited frame policy or iframe sandbox attribute
// contains the 'allow-same-site-none-cookies' value and the override should be
// applied as the frame's ancestors are all same-site.
bool ShouldAllowSameSiteNoneCookiesInSandbox(FrameTreeNode& frame_tree_node) {
  if (frame_tree_node.IsInFencedFrameTree()) {
    return false;
  }

  RenderFrameHostImpl* frame = frame_tree_node.current_frame_host();
  return frame &&
         frame->active_sandbox_flags() !=
             network::mojom::WebSandboxFlags::kNone &&
         !frame->IsSandboxed(
             network::mojom::WebSandboxFlags::kAllowSameSiteNoneCookies) &&
         frame->IsSandboxed(network::mojom::WebSandboxFlags::kOrigin) &&
         frame->AncestorsAllowSameSiteNoneCookiesOverride(
             frame_tree_node.navigation_request()
                 ->GetTentativeOriginAtRequestTime());
}

// TODO(https://crbug.com/346000235) there is a known failure with extensions
// See test: ExtensionWebRequestApiTestWithContextType.HSTSUpgradeAfterRedirect
// We still want to check this in debug mode to avoid further regressions, but
// because it was affecting to many developers with DCHECK_IS_ON() this was
// downgraded as a DEBUG only check.
// After getting the approval to rewrite the CSP parser in Rust, we should be
// able to remove "pre-parsing" of CSP in the network process and directly
// parse them later in the browser process. This will make this check to become
// unnecessary.
#ifndef NDEBUG
void CheckParsedHeadersEquals(const network::mojom::ParsedHeadersPtr& lhs,
                              const network::mojom::ParsedHeadersPtr& rhs,
                              const GURL& url) {
  // If we're running this function it means we're re-parsing the headers from
  // cache and checking if they equal the prior parsing results. As the
  // Clear-Site-Data header isn't cached we want to be sure not to fail just
  // because the two parsing results mismatch in this expected way.
  network::mojom::ParsedHeadersPtr adjusted_lhs = lhs->Clone();
  if (rhs->client_hints_ignored_due_to_clear_site_data_header) {
    CHECK(!rhs->accept_ch);
    CHECK(!rhs->critical_ch);
    adjusted_lhs->accept_ch = std::nullopt;
    adjusted_lhs->critical_ch = std::nullopt;
    adjusted_lhs->client_hints_ignored_due_to_clear_site_data_header = true;
  }
  if (mojo::Equals(adjusted_lhs, rhs)) {
    return;
  }

  // TODO(crbug.com/40864513) Remove this instrumentation once fixed.
  auto to_string = [](const auto& policies) {
    std::string out;
    for (const auto& csp : policies) {
      out += csp->header->header_value + " | ";
    }
    return out;
  };
  SCOPED_CRASH_KEY_STRING256("bug1362779", "csp_adjusted_lhs",
                             to_string(adjusted_lhs->content_security_policy));
  SCOPED_CRASH_KEY_STRING256("bug1362779", "csp_rhs",
                             to_string(rhs->content_security_policy));
  SCOPED_CRASH_KEY_STRING32("bug1362779", "url", url.possibly_invalid_spec());

  CHECK(mojo::Equals(adjusted_lhs->content_security_policy,
                     rhs->content_security_policy));
  CHECK(mojo::Equals(adjusted_lhs->allow_csp_from, rhs->allow_csp_from));
  CHECK(mojo::Equals(adjusted_lhs->cross_origin_embedder_policy,
                     rhs->cross_origin_embedder_policy));
  CHECK(mojo::Equals(adjusted_lhs->cross_origin_opener_policy,
                     rhs->cross_origin_opener_policy));
  CHECK(mojo::Equals(adjusted_lhs->document_isolation_policy,
                     rhs->document_isolation_policy));
  CHECK(mojo::Equals(adjusted_lhs->origin_agent_cluster,
                     rhs->origin_agent_cluster));
  CHECK(mojo::Equals(adjusted_lhs->accept_ch, rhs->accept_ch));
  CHECK(mojo::Equals(adjusted_lhs->critical_ch, rhs->critical_ch));
  CHECK_EQ(adjusted_lhs->xfo, rhs->xfo);
  CHECK(mojo::Equals(adjusted_lhs->link_headers, rhs->link_headers));
  CHECK(mojo::Equals(adjusted_lhs->timing_allow_origin,
                     rhs->timing_allow_origin));
  CHECK(mojo::Equals(adjusted_lhs->supports_loading_mode,
                     rhs->supports_loading_mode));
  CHECK(mojo::Equals(adjusted_lhs->reporting_endpoints,
                     rhs->reporting_endpoints));
  CHECK(mojo::Equals(adjusted_lhs->cookie_indices, rhs->cookie_indices));
  CHECK(mojo::Equals(adjusted_lhs->avail_language, rhs->avail_language));
  CHECK(mojo::Equals(adjusted_lhs->content_language, rhs->content_language));
  CHECK(mojo::Equals(adjusted_lhs->no_vary_search_with_parse_error,
                     rhs->no_vary_search_with_parse_error));
  CHECK(mojo::Equals(adjusted_lhs->observe_browsing_topics,
                     rhs->observe_browsing_topics));
  CHECK(mojo::Equals(adjusted_lhs->allow_cross_origin_event_reporting,
                     rhs->allow_cross_origin_event_reporting));
  NOTREACHED() << "The parsed headers don't match, but we don't know which "
                  "field does not match. Please add a DCHECK before this one "
                  "checking for the missing field.";
}
#endif  // NDEBUG

}  // namespace

std::unique_ptr<network::ResourceRequest> CreateResourceRequestForNavigation(
    const std::string& method,
    const GURL& url,
    network::mojom::RequestDestination destination,
    const blink::mojom::Referrer& referrer,
    const net::IsolationInfo& isolation_info,
    mojo::PendingRemote<network::mojom::DevToolsObserver> devtools_observer,
    net::RequestPriority priority,
    bool is_main_frame) {
  auto new_request = std::make_unique<network::ResourceRequest>();

  // - Step 3 of
  // https://html.spec.whatwg.org/multipage/browsing-the-web.html#create-navigation-params-by-fetching
  // - Step 2 of
  // https://wicg.github.io/nav-speculation/prefetch.html#create-a-navigation-request

  // url: entry's URL [spec text]
  new_request->url = url;
  new_request->navigation_redirect_chain.push_back(new_request->url);

  // client: sourceSnapshotParams's fetch client [spec text]

  // destination: "document" [spec text]
  new_request->destination = destination;

  // credentials mode: "include" [spec text]
  new_request->credentials_mode = network::mojom::CredentialsMode::kInclude;

  // use-URL-credentials flag: set [spec text]

  // redirect mode: "manual" [spec text]
  new_request->redirect_mode = network::mojom::RedirectMode::kManual;

  // replaces client id: navigable's active document's relevant settings
  // object's id [spec text]
  // Not implemented (https://crbug.com/40287592).

  // mode: "navigate"  [spec text]
  new_request->mode = network::mojom::RequestMode::kNavigate;

  // referrer: entry's document state's request referrer [spec text]
  new_request->referrer = referrer.url;

  // referrer policy: entry's document state's request referrer policy [spec
  // text]
  new_request->referrer_policy =
      Referrer::ReferrerPolicyForUrlRequest(referrer.policy);

  new_request->method = method;

  new_request->site_for_cookies = isolation_info.site_for_cookies();

  new_request->trusted_params = network::ResourceRequest::TrustedParams();
  new_request->trusted_params->isolation_info = isolation_info;
  new_request->trusted_params->devtools_observer = std::move(devtools_observer);

  new_request->priority = priority;

  if (is_main_frame) {
    // When set, `update_first_party_url_on_redirect` will cause a
    // server-redirect to update the URL used to determine if cookies are
    // first-party. Since fenced frames are main frames in terms of cookie
    // partitioning, this needs to be `is_main_frame` rather than
    // `is_outermost_main_frame`.
    new_request->update_first_party_url_on_redirect = true;

    // Navigation responses for the top-level document are able to be used as
    // compression dictionaries.
    new_request->shared_dictionary_writer_enabled = true;
  }

  new_request->enable_load_timing = true;

  if (base::FeatureList::IsEnabled(
          network::features::kRendererSideContentDecoding) &&
      network::features::kRendererSideContentDecodingForNavigation.Get()) {
    new_request->client_side_content_decoding_enabled = true;
  }

  return new_request;
}

// TODO(kinuko): Fix the method ordering and move these methods after the ctor.
NavigationURLLoaderImpl::~NavigationURLLoaderImpl() {
  TRACE_EVENT_WITH_FLOW0("navigation",
                         "NavigationURLLoaderImpl::~NavigationURLLoaderImpl",
                         TRACE_ID_LOCAL(this), TRACE_EVENT_FLAG_FLOW_IN);
  // If neither OnCompleted nor OnReceivedResponse has been invoked, the
  // request was canceled before receiving a response, so log a cancellation.
  // Results after receiving a non-error response are logged in the renderer,
  // if the request is passed to one. If it's a download, or not passed to a
  // renderer for some other reason, results will not be logged for the
  // request. The net::OK check may not be necessary - the case where OK is
  // received without receiving any headers looks broken, anyways.
  if (!received_response_ && (!status_ || status_->error_code != net::OK)) {
    blink::RecordLoadHistograms(
        url::Origin::Create(url_), resource_request_->destination,
        status_ ? status_->error_code : net::ERR_ABORTED);
  }
}

void NavigationURLLoaderImpl::Start() {
  TRACE_EVENT_WITH_FLOW0("navigation", "NavigationURLLoaderImpl::Start",
                         TRACE_ID_LOCAL(this),
                         TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT);
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  DCHECK(!started_);
  started_ = true;

  resource_request_->headers.SetHeader(
      net::HttpRequestHeaders::kAccept,
      FrameAcceptHeaderValue(/*allow_sxg_responses=*/true, browser_context_));

  // If not performing a PDF navigation, allow certain schemes to create loaders
  // directly, bypassing interceptors. (In the case of PDF navigation,
  // interception is required, but these loaders are not; see crbug.com/1253314
  // and crbug.com/1253984.)
  //
  // TODO(crbug.com/40794764): Consider getting rid of these exceptions.
  if (!request_info_->is_pdf) {
    // Requests to WebUI scheme won't get redirected to/from other schemes
    // or be intercepted, so we just let it go here.
    std::string scheme = request_info_->common_params->url.GetScheme();
    if (base::Contains(URLDataManagerBackend::GetWebUISchemes(), scheme)) {
      FrameTreeNode* frame_tree_node =
          FrameTreeNode::GloballyFindByID(frame_tree_node_id_);
      CHECK(frame_tree_node);
      CHECK(frame_tree_node->navigation_request());

      CreateThrottlingLoaderAndStart(
          url_loader_factory::Create(
              ContentBrowserClient::URLLoaderFactoryType::kNavigation,
              url_loader_factory::TerminalParams::ForNonNetwork(
                  CreateWebUIURLLoaderFactory(
                      frame_tree_node->current_frame_host(), scheme, {}),
                  network::mojom::kBrowserProcessId),
              url_loader_factory::ContentClientParams(
                  browser_context_, frame_tree_node->current_frame_host(),
                  frame_tree_node->current_frame_host()
                      ->GetProcess()
                      ->GetDeprecatedID(),
                  resource_request_->request_initiator.value_or(url::Origin()),
                  net::IsolationInfo(),
                  ukm::SourceIdObj::FromInt64(ukm_source_id_),
                  /*bypass_redirect_checks=*/nullptr,
                  frame_tree_node->navigation_request()->GetNavigationId(),
                  GetUIThreadTaskRunner(
                      {BrowserTaskType::kNavigationNetworkResponse}))),
          /*additional_throttles=*/{});
      return;
    }

    // Requests to Blob scheme won't get redirected to/from other schemes or be
    // intercepted, so we just let it go here.
    if (request_info_->common_params->url.SchemeIsBlob() &&
        request_info_->blob_url_loader_factory) {
      CreateThrottlingLoaderAndStart(
          network::SharedURLLoaderFactory::Create(
              std::move(request_info_->blob_url_loader_factory)),
          /*additional_throttles=*/{});
      return;
    }
  }

  CreateInterceptors();
  Restart();
}

void NavigationURLLoaderImpl::CreateInterceptors() {
  TRACE_EVENT_WITH_FLOW0("navigation",
                         "NavigationURLLoaderImpl::CreateInterceptors",
                         TRACE_ID_LOCAL(this),
                         TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT);
  if (prefetched_signed_exchange_cache_) {
    std::unique_ptr<NavigationLoaderInterceptor>
        prefetched_signed_exchange_interceptor =
            prefetched_signed_exchange_cache_->MaybeCreateInterceptor(
                url_, frame_tree_node_id_,
                resource_request_->trusted_params->isolation_info);
    prefetched_signed_exchange_cache_.reset();
    if (prefetched_signed_exchange_interceptor) {
      interceptors_.push_back(
          std::move(prefetched_signed_exchange_interceptor));
    }
  }

  // Set up an interceptor for service workers.
  if (service_worker_handle_) {
    auto service_worker_interceptor =
        ServiceWorkerMainResourceLoaderInterceptor::CreateForNavigation(
            resource_request_->url, service_worker_handle_->AsWeakPtr(),
            *request_info_);
    // The interceptor may not be created in certain cases (e.g., the origin
    // is not secure).
    if (service_worker_interceptor) {
      if (features::IsPrefetchServiceWorkerEnabled(browser_context_)) {
        // Set up an interceptor for ServiceWorker-controlled prefetches. This
        // is needed before the ServiceWorkerMainResourceLoaderInterceptor which
        // would also intercept the request for ServiceWorker-controlled URLs.
        // See the design docs at https://crbug.com/40947546.
        interceptors_.push_back(std::make_unique<PrefetchURLLoaderInterceptor>(
            PrefetchServiceWorkerState::kControlled,
            service_worker_handle_->AsWeakPtr(), frame_tree_node_id_,
            request_info_->initiator_document_token,
            request_info_->prefetch_serving_page_metrics_container));
      }

      interceptors_.push_back(std::move(service_worker_interceptor));
    }
  }

  // Set-up an interceptor for SignedExchange handling if it is enabled.
  if (signed_exchange_utils::IsSignedExchangeHandlingEnabled(
          browser_context_)) {
    interceptors_.push_back(CreateSignedExchangeRequestHandler(
        *request_info_, network_loader_factory_));
  }

  // Set up an interceptor for prefetch.
  // When `features::kPrefetchServiceWorker` is enabled, we intentionally add
  // two `PrefetchURLLoaderInterceptor`s, one for ServiceWorker-controlled
  // prefetches above, and one for non-ServiceWorker-controlled prefetches here.
  // See the design docs at https://crbug.com/40947546.
  interceptors_.push_back(std::make_unique<PrefetchURLLoaderInterceptor>(
      PrefetchServiceWorkerState::kDisallowed,
      /*service_worker_handle=*/nullptr, frame_tree_node_id_,
      request_info_->initiator_document_token,
      request_info_->prefetch_serving_page_metrics_container));

  // See if embedders want to add interceptors.
  std::vector<std::unique_ptr<URLLoaderRequestInterceptor>>
      browser_interceptors =
          GetContentClient()->browser()->WillCreateURLLoaderRequestInterceptors(
              navigation_ui_data_.get(), frame_tree_node_id_,
              request_info_->navigation_id,
              request_info_->force_no_https_upgrade,
              GetUIThreadTaskRunner(
                  {BrowserTaskType::kNavigationNetworkResponse}));
  if (!browser_interceptors.empty()) {
    for (auto& browser_interceptor : browser_interceptors) {
      interceptors_.push_back(
          std::make_unique<NavigationLoaderInterceptorBrowserContainer>(
              std::move(browser_interceptor)));
    }
  }
}

void NavigationURLLoaderImpl::Restart() {
  TRACE_EVENT_WITH_FLOW0("navigation", "NavigationURLLoaderImpl::Restart",
                         TRACE_ID_LOCAL(this),
                         TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT);
  // Cancel all inflight early hints preloads except for same origin redirects.
  if (!IsSameOriginRedirect(resource_request_->navigation_redirect_chain)) {
    early_hints_manager_.reset();
  }

  // Clear `url_loader_` if it's not the default one (network). This allows
  // the restarted request to use a new loader, instead of, e.g., reusing the
  // service worker loader. For an optimization, we keep and reuse
  // the default url loader if the all `interceptors_` doesn't handle the
  // redirected request. If the network service is enabled, reset the loader
  // if the redirected URL's scheme and the previous URL scheme don't match in
  // their use or disuse of the network service loader.
  if (!default_loader_used_ ||
      (resource_request_->navigation_redirect_chain.size() > 1 &&
       network::IsURLHandledByNetworkService(
           resource_request_->navigation_redirect_chain
               [resource_request_->navigation_redirect_chain.size() - 1]) !=
           network::IsURLHandledByNetworkService(
               resource_request_->navigation_redirect_chain
                   [resource_request_->navigation_redirect_chain.size() -
                    2]))) {
    loader_holder_.ResetForFollowRedirect(*resource_request_.get());
  }
  received_response_ = false;
  head_update_params_ = ResponseHeadUpdateParams();
  loader_holder_.OnExclusiveTaskStarted(
      LoaderHolder::ExclusiveTaskType::kInterceptor);
  MaybeStartLoader(/*next_interceptor_index=*/0,
                   /*interceptor_result=*/std::nullopt);
}

void NavigationURLLoaderImpl::MaybeStartLoader(
    size_t next_interceptor_index,
    std::optional<NavigationLoaderInterceptor::Result> interceptor_result) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  DCHECK(started_);

  if (loader_holder_.ShouldCancelExclusiveTask(
          LoaderHolder::ExclusiveTaskType::kInterceptor)) {
    return;
  }

  if (interceptor_result) {
    subresource_loader_params_ =
        std::move(interceptor_result->subresource_loader_params);
    if (!interceptor_result->single_request_factory) {
      // Skip the subsequent interceptors and start with the default behavior.
      //
      // Here `subresource_loader_params_` can still have non-default values
      // e.g. when there's a controlling service worker that doesn't have a
      // fetch event handler so it doesn't intercept requests.
      StartNonInterceptedRequest(
          std::move(interceptor_result->response_head_update_params));
      return;
    }

    // Intercept the request with `interceptor_result->single_request_factory`.
    StartInterceptedRequest(
        std::move(interceptor_result->single_request_factory));
    return;
  }

  subresource_loader_params_ = {};

  if (next_interceptor_index >= interceptors_.size()) {
    // All interceptors have been checked and none has elected to handle the
    // request. Start with the default behavior.
    StartNonInterceptedRequest(ResponseHeadUpdateParams());
    return;
  }

  // Fallback to the next interceptor.
  auto* next_interceptor = interceptors_[next_interceptor_index].get();
  next_interceptor->MaybeCreateLoader(
      *resource_request_, browser_context_,
      base::BindOnce(&NavigationURLLoaderImpl::MaybeStartLoader,
                     weak_factory_.GetWeakPtr(), next_interceptor_index + 1),
      base::BindOnce(&NavigationURLLoaderImpl::FallbackToNonInterceptedRequest,
                     weak_factory_.GetWeakPtr()));
}

void NavigationURLLoaderImpl::StartInterceptedRequest(
    scoped_refptr<network::SharedURLLoaderFactory> single_request_factory) {
  loader_holder_.OnExclusiveTaskCompleted(
      LoaderHolder::ExclusiveTaskType::kInterceptor);

  std::vector<std::unique_ptr<blink::URLLoaderThrottle>> additional_throttles;
  // Intercepted requests need MimeSniffingThrottle to do mime sniffing.
  // Non-intercepted requests usually go through the regular network
  // URLLoader, which does mime sniffing.
  additional_throttles.push_back(std::make_unique<blink::MimeSniffingThrottle>(
      GetUIThreadTaskRunner({BrowserTaskType::kNavigationNetworkResponse})));

  default_loader_used_ = false;

  // The receiver should be already reset at `Restart()`.
  // TODO(https://crbug.com/434182226): Remove DUMP_WILL_BE_.
  DUMP_WILL_BE_CHECK(!loader_holder_.receiver_is_bound_for_check());

  // If `url_loader_` already exists, this means we are following a redirect
  // using an interceptor. In this case we should make sure to reset the
  // loader, similar to what is done in Restart().
  loader_holder_.ResetForFollowRedirect(*resource_request_.get());

  CreateThrottlingLoaderAndStart(std::move(single_request_factory),
                                 std::move(additional_throttles));
}

NavigationURLLoaderImpl::LoaderHolder::LoaderHolder(
    network::mojom::URLLoaderClient* receiver)
    : response_loader_receiver_(receiver) {}

NavigationURLLoaderImpl::LoaderHolder::~LoaderHolder() = default;

void NavigationURLLoaderImpl::LoaderHolder::ResetInternal() {
  CheckState();

  response_loader_receiver_.reset();
  url_loader_.reset();
  modified_headers_on_redirect_.reset();

  state_ = State::kNone;
  CheckState();
}

void NavigationURLLoaderImpl::LoaderHolder::Reset() {
  switch (exclusive_task_state_) {
    case ExclusiveTaskState::kNoExclusiveTask:
      break;
    case ExclusiveTaskState::kHasExclusiveTask:
      // If there can be any possible exclusive tasks, the (possibly indirect)
      // caller of `Reset()` should check `HasExclusiveTask()` and call
      // `ResetForFailure()` and make the loading fail instead, if any exclusive
      // tasks. This can't be done here, because we have to cancel the whole
      // loading (including the new operation that triggers `Reset()`), not only
      // cancalling the exclusive tasks.
      // TODO(https://crbug.com/434182226): Remove DUMP_WILL_BE_.
      DUMP_WILL_BE_NOTREACHED();
      break;
    case ExclusiveTaskState::kCancelExclusiveTask:
      // It's harmless to reach here, because the issues related to exclusive
      // tasks should be already handled when transitioned
      // `kCancelExclusiveTask` (i.e. by the caller of `ResetForFailure()`).
      // TODO(https://crbug.com/434182226): Remove DUMP_WILL_BE_.
      DUMP_WILL_BE_NOTREACHED();
      break;
  }

  ResetInternal();
}

void NavigationURLLoaderImpl::LoaderHolder::ResetForFailure() {
  exclusive_task_state_ = ExclusiveTaskState::kCancelExclusiveTask;
  ResetInternal();
}

void NavigationURLLoaderImpl::LoaderHolder::OnExclusiveTaskStarted(
    ExclusiveTaskType exclusive_task_type) {
  switch (exclusive_task_state_) {
    case ExclusiveTaskState::kNoExclusiveTask:
      exclusive_task_state_ = ExclusiveTaskState::kHasExclusiveTask;
      current_exclusive_task_type_ = exclusive_task_type;
      break;
    case ExclusiveTaskState::kHasExclusiveTask:
      // exclusive tasks shouldn't be started while there is already another
      // exclusive task.
      // TODO(https://crbug.com/434182226): Remove DUMP_WILL_BE_.
      DUMP_WILL_BE_NOTREACHED();
      break;
    case ExclusiveTaskState::kCancelExclusiveTask:
      // exclusive tasks shouldn't be started if exclusive task is to be
      // cancelled.
      // TODO(https://crbug.com/434182226): Remove DUMP_WILL_BE_.
      DUMP_WILL_BE_NOTREACHED();
      break;
  }
}

void NavigationURLLoaderImpl::LoaderHolder::OnExclusiveTaskCompleted(
    ExclusiveTaskType exclusive_task_type) {
  switch (exclusive_task_state_) {
    case ExclusiveTaskState::kHasExclusiveTask:
      // TODO(https://crbug.com/434182226): Remove DUMP_WILL_BE_.
      DUMP_WILL_BE_CHECK(current_exclusive_task_type_);
      DUMP_WILL_BE_CHECK_EQ(*current_exclusive_task_type_, exclusive_task_type);
      exclusive_task_state_ = ExclusiveTaskState::kNoExclusiveTask;
      current_exclusive_task_type_.reset();
      break;
    case ExclusiveTaskState::kNoExclusiveTask:
      // TODO(https://crbug.com/434182226): Remove DUMP_WILL_BE_.
      DUMP_WILL_BE_NOTREACHED();
      break;
    case ExclusiveTaskState::kCancelExclusiveTask:
      // TODO(https://crbug.com/434182226): Remove DUMP_WILL_BE_.
      DUMP_WILL_BE_NOTREACHED();
      break;
  }
}

bool NavigationURLLoaderImpl::LoaderHolder::HasExclusiveTask() const {
  switch (exclusive_task_state_) {
    case ExclusiveTaskState::kNoExclusiveTask:
      return false;
    case ExclusiveTaskState::kHasExclusiveTask:
    case ExclusiveTaskState::kCancelExclusiveTask:
      return true;
  }
}

bool NavigationURLLoaderImpl::LoaderHolder::ShouldCancelExclusiveTask(
    ExclusiveTaskType exclusive_task_type) const {
  switch (exclusive_task_state_) {
    case ExclusiveTaskState::kNoExclusiveTask:
      // TODO(https://crbug.com/434182226): Remove DUMP_WILL_BE_.
      DUMP_WILL_BE_NOTREACHED();
      return false;
    case ExclusiveTaskState::kHasExclusiveTask:
      // TODO(https://crbug.com/434182226): Remove DUMP_WILL_BE_.
      DUMP_WILL_BE_CHECK(current_exclusive_task_type_);
      DUMP_WILL_BE_CHECK_EQ(*current_exclusive_task_type_, exclusive_task_type);
      return false;
    case ExclusiveTaskState::kCancelExclusiveTask:
      // TODO(https://crbug.com/434182226): Remove DUMP_WILL_BE_.
      DUMP_WILL_BE_CHECK(current_exclusive_task_type_);
      DUMP_WILL_BE_CHECK_EQ(*current_exclusive_task_type_, exclusive_task_type);
      return true;
  }
}

void NavigationURLLoaderImpl::LoaderHolder::BindReceiver(
    mojo::PendingReceiver<network::mojom::URLLoaderClient> pending_receiver,
    scoped_refptr<base::SequencedTaskRunner> task_runner) {
  // TODO(https://crbug.com/434182226): Remove DUMP_WILL_BE_.
  DUMP_WILL_BE_CHECK(!modified_headers_on_redirect_);
  DUMP_WILL_BE_CHECK_EQ(state_, State::kLoadingViaLoader);
  CheckState();

  response_loader_receiver_.reset();
  response_loader_receiver_.Bind(std::move(pending_receiver),
                                 std::move(task_runner));
  url_loader_.reset();

  state_ = State::kLoadingViaReceiver;
  CheckState();
}

void NavigationURLLoaderImpl::LoaderHolder::SetLoader(
    std::unique_ptr<blink::ThrottlingURLLoader> url_loader) {
  // TODO(https://crbug.com/434182226): Remove DUMP_WILL_BE_.
  DUMP_WILL_BE_CHECK(!modified_headers_on_redirect_);
  DUMP_WILL_BE_CHECK_EQ(state_, State::kNone);
  CheckState();

  url_loader_ = std::move(url_loader);

  state_ = State::kLoadingViaLoader;
  CheckState();
}

network::mojom::URLLoaderClientEndpointsPtr
NavigationURLLoaderImpl::LoaderHolder::Unbind() {
  CheckState();

  if (url_loader_) {
    // TODO(https://crbug.com/434182226): Turn this to `CHECK()`.
    DUMP_WILL_BE_CHECK_EQ(state_, State::kLoadingViaLoader);
    state_ = State::kUnbound;
    // Even after this point `url_loader_` should be alive and accessed via
    // `url_loader()`.
    // TODO(https://crbug.com/40251638): Clean up this behavior if needed.
    return url_loader_->Unbind();
  } else {
    // TODO(https://crbug.com/434182226): Turn this to `CHECK()`.
    DUMP_WILL_BE_CHECK_EQ(state_, State::kLoadingViaReceiver);
    state_ = State::kUnbound;
    return network::mojom::URLLoaderClientEndpoints::New(
        std::move(response_url_loader_), response_loader_receiver_.Unbind());
  }
}

void NavigationURLLoaderImpl::LoaderHolder::CheckState() const {
  // TODO(https://crbug.com/434182226): Turn `DUMP_WILL_BE_CHECK()`s to
  // `CHECK()`.
  switch (state_) {
    case State::kNone:
      DUMP_WILL_BE_CHECK(!response_loader_receiver_.is_bound());
      DUMP_WILL_BE_CHECK(!url_loader_);
      break;
    case State::kLoadingViaLoader:
      DUMP_WILL_BE_CHECK(!response_loader_receiver_.is_bound());
      DUMP_WILL_BE_CHECK(url_loader_);
      break;
    case State::kLoadingViaReceiver:
      DUMP_WILL_BE_CHECK(response_loader_receiver_.is_bound());
      DUMP_WILL_BE_CHECK(!url_loader_);
      break;
    case State::kUnbound:
      // `LoaderHolder` shouldn't be touched after `Unbind()`.
      DUMP_WILL_BE_NOTREACHED();
  }
}

NavigationURLLoaderImpl::LoaderHolder::ModifiedHeadersOnRedirect::
    ModifiedHeadersOnRedirect(
        std::vector<std::string> removed_headers,
        net::HttpRequestHeaders modified_headers,
        net::HttpRequestHeaders modified_cors_exempt_headers)
    : removed_headers_(std::move(removed_headers)),
      modified_headers_(std::move(modified_headers)),
      modified_cors_exempt_headers_(std::move(modified_cors_exempt_headers)) {}

NavigationURLLoaderImpl::LoaderHolder::ModifiedHeadersOnRedirect::
    ~ModifiedHeadersOnRedirect() = default;

void NavigationURLLoaderImpl::LoaderHolder::SetModifiedHeadersOnRedirect(
    std::vector<std::string> removed_headers,
    net::HttpRequestHeaders modified_headers,
    net::HttpRequestHeaders modified_cors_exempt_headers) {
  // TODO(https://crbug.com/434182226): Remove DUMP_WILL_BE_.
  DUMP_WILL_BE_CHECK(!modified_headers_on_redirect_);
  modified_headers_on_redirect_.emplace(
      std::move(removed_headers), std::move(modified_headers),
      std::move(modified_cors_exempt_headers));
}

void NavigationURLLoaderImpl::LoaderHolder::ResetForFollowRedirect(
    network::ResourceRequest& resource_request) {
  if (url_loader_) {
    CHECK(modified_headers_on_redirect_);
    url_loader_->ResetForFollowRedirect(
        resource_request, modified_headers_on_redirect_->removed_headers_,
        modified_headers_on_redirect_->modified_headers_,
        modified_headers_on_redirect_->modified_cors_exempt_headers_);
  }
  Reset();
}

void NavigationURLLoaderImpl::LoaderHolder::FollowRedirect() {
  CHECK(url_loader_);
  CHECK(modified_headers_on_redirect_);
  url_loader_->FollowRedirect(
      std::move(modified_headers_on_redirect_->removed_headers_),
      std::move(modified_headers_on_redirect_->modified_headers_),
      std::move(modified_headers_on_redirect_->modified_cors_exempt_headers_));
  modified_headers_on_redirect_.reset();
}

bool NavigationURLLoaderImpl::LoaderHolder::receiver_is_bound_for_check()
    const {
  return response_loader_receiver_.is_bound();
}

void NavigationURLLoaderImpl::StartNonInterceptedRequest(
    ResponseHeadUpdateParams head_update_params) {
  loader_holder_.OnExclusiveTaskCompleted(
      LoaderHolder::ExclusiveTaskType::kInterceptor);

  // If we already have the default `url_loader_` we must come here after a
  // redirect. No interceptors wanted to intercept the redirected request,
  // so let the loader just follow the redirect.
  if (loader_holder_.url_loader()) {
    DCHECK(!redirect_info_.new_url.is_empty());
    // TODO(https://crbug.com/434182226): Turn this to `CHECK()`.
    DUMP_WILL_BE_CHECK_EQ(loader_holder_.state(),
                          LoaderHolder::State::kLoadingViaLoader);
    loader_holder_.FollowRedirect();
    return;
  }

  // The previous loader should be already reset at
  // `NavigationURLLoaderImpl::Restart()` and we start a new loader below.
  // TODO(https://crbug.com/434182226): Turn this to `CHECK()`.
  DUMP_WILL_BE_CHECK_EQ(loader_holder_.state(), LoaderHolder::State::kNone);

  head_update_params_ = std::move(head_update_params);
  scoped_refptr<network::SharedURLLoaderFactory> factory;
  if (network::IsURLHandledByNetworkService(resource_request_->url)) {
    factory = network_loader_factory_;
    default_loader_used_ = true;
  } else {
    factory = GetOrCreateNonNetworkLoaderFactory();
  }

  loader_holder_.Reset();
  CreateThrottlingLoaderAndStart(std::move(factory),
                                 /*additional_throttles=*/{});
}

network::mojom::URLLoaderFactory*
NavigationURLLoaderImpl::FallbackToNonInterceptedRequest(
    base::WeakPtr<NavigationURLLoaderImpl> self,
    ResponseHeadUpdateParams head_update_params) {
  if (!self) {
    return nullptr;
  }

  self->head_update_params_ = std::move(head_update_params);
  if (network::IsURLHandledByNetworkService(self->resource_request_->url)) {
    // `NavigationURLLoaderImpl::default_loader_used_` is NOT set to true here,
    // because the underlying URLLoaderFactory of
    // `NavigationURLLoaderImpl::url_loader_` is still ServiceWorker-provided
    // one (that finally delegates to `network_loader_factory_` though) and thus
    // isn't e.g. unsafe to reuse after redirects.
    return self->network_loader_factory_.get();
  } else {
    return self->GetOrCreateNonNetworkLoaderFactory().get();
  }
}

scoped_refptr<network::SharedURLLoaderFactory>
NavigationURLLoaderImpl::GetOrCreateNonNetworkLoaderFactory() {
  scoped_refptr<network::SharedURLLoaderFactory>& cached_factory =
      non_network_url_loader_factories_[resource_request_->url.GetScheme()];

  if (cached_factory) {
    return cached_factory;
  }

  auto [is_cacheable, factory] = CreateNonNetworkLoaderFactory(
      browser_context_, storage_partition_,
      FrameTreeNode::GloballyFindByID(frame_tree_node_id_),
      ukm::SourceIdObj::FromInt64(ukm_source_id_), navigation_ui_data_.get(),
      *request_info_, web_contents_getter_, *resource_request_);

  if (is_cacheable) {
    cached_factory = factory;
  }

  return factory;
}

// static
std::pair</*is_cacheable=*/bool, scoped_refptr<network::SharedURLLoaderFactory>>
NavigationURLLoaderImpl::CreateNonNetworkLoaderFactory(
    BrowserContext* browser_context,
    StoragePartitionImpl* storage_partition,
    FrameTreeNode* frame_tree_node,
    const ukm::SourceIdObj& ukm_id,
    NavigationUIData* navigation_ui_data,
    const NavigationRequestInfo& request_info,
    base::RepeatingCallback<WebContents*()> web_contents_getter,
    const network::ResourceRequest& resource_request) {
  CHECK(frame_tree_node);
  CHECK(frame_tree_node->navigation_request());

  // First, check known schemes.
  if (mojo::PendingRemote<network::mojom::URLLoaderFactory> terminal =
          CreateTerminalNonNetworkLoaderFactory(
              browser_context, storage_partition, frame_tree_node,
              resource_request.url)) {
    auto* frame = frame_tree_node->current_frame_host();

    // TODO(lukasza, jam): It is unclear why FileURLLoaderFactory is the only
    // non-http factory that allows DevTools interception. For comparison all
    // non-WebUI cases in RFHI::CommitNavigation allow DevTools interception.
    // Let's try to be more consistent / less ad-hoc.
    std::optional<devtools_instrumentation::WillCreateURLLoaderFactoryParams>
        devtools_params =
            resource_request.url.SchemeIs(url::kFileScheme)
                ? std::make_optional(
                      devtools_instrumentation::
                          WillCreateURLLoaderFactoryParams::ForFrame(frame))
                : std::nullopt;
    return std::make_pair(
        /*is_cacheable=*/true,
        url_loader_factory::Create(
            ContentBrowserClient::URLLoaderFactoryType::kNavigation,
            url_loader_factory::TerminalParams::ForNonNetwork(
                std::move(terminal), network::mojom::kBrowserProcessId),
            url_loader_factory::ContentClientParams(
                frame->GetSiteInstance()->GetBrowserContext(), frame,
                frame->GetProcess()->GetDeprecatedID(), url::Origin(),
                net::IsolationInfo(), ukm_id,
                /*bypass_redirect_checks=*/nullptr,
                frame_tree_node->navigation_request()->GetNavigationId(),
                GetUIThreadTaskRunner(
                    {BrowserTaskType::kNavigationNetworkResponse})),
            devtools_params));
  }

  // Second, check external protocols.
  std::optional<url::Origin> initiating_origin;
  if (resource_request.navigation_redirect_chain.size() > 1) {
    // The last URL in `navigation_redirect_chain` is an external-protocol URL
    // (if handled by `HandleExternalProtocol`), and the second-to-last URL is
    // the URL that initiated the redirect to the external-protocol URL.
    initiating_origin = url::Origin::Create(
        resource_request.navigation_redirect_chain
            [resource_request.navigation_redirect_chain.size() - 2]);
  } else {
    initiating_origin = resource_request.request_initiator;
  }
  mojo::PendingRemote<network::mojom::URLLoaderFactory>
      terminal_external_protocol;
  bool handled = GetContentClient()->browser()->HandleExternalProtocol(
      resource_request.url, std::move(web_contents_getter),
      frame_tree_node->frame_tree_node_id(), navigation_ui_data,
      request_info.is_primary_main_frame,
      frame_tree_node->IsInFencedFrameTree(), request_info.sandbox_flags,
      static_cast<ui::PageTransition>(resource_request.transition_type),
      resource_request.has_user_gesture, initiating_origin,
      request_info.initiator_document_token
          ? RenderFrameHostImpl::FromDocumentToken(
                request_info.initiator_process_id,
                *request_info.initiator_document_token)
          : nullptr,
      request_info.isolation_info, &terminal_external_protocol);
  if (terminal_external_protocol) {
    return std::make_pair(
        /*is_cacheable=*/false,
        url_loader_factory::Create(
            ContentBrowserClient::URLLoaderFactoryType::kNavigation,
            url_loader_factory::TerminalParams::ForNonNetwork(
                std::move(terminal_external_protocol),
                network::mojom::kBrowserProcessId)));
  }

  // Finally handle as an unknown scheme.
  return std::make_pair(
      /*is_cacheable=*/false,
      url_loader_factory::Create(
          ContentBrowserClient::URLLoaderFactoryType::kNavigation,
          url_loader_factory::TerminalParams::ForNonNetwork(
              base::MakeRefCounted<network::SingleRequestURLLoaderFactory>(
                  base::BindOnce(UnknownSchemeCallback, handled)),
              network::mojom::kBrowserProcessId)));
}

void NavigationURLLoaderImpl::CreateThrottlingLoaderAndStart(
    scoped_refptr<network::SharedURLLoaderFactory> factory,
    std::vector<std::unique_ptr<blink::URLLoaderThrottle>>
        additional_throttles) {
  TRACE_EVENT_WITH_FLOW0(
      "navigation", "NavigationURLLoaderImpl::CreateThrottlingLoaderAndStart",
      TRACE_ID_LOCAL(this),
      TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT);
  // TODO(https://crbug.com/434182226): Turn this to `CHECK()`.
  DUMP_WILL_BE_CHECK_EQ(loader_holder_.state(), LoaderHolder::State::kNone);
  CHECK(!loader_holder_.url_loader());

  std::vector<std::unique_ptr<blink::URLLoaderThrottle>> throttles =
      CreateURLLoaderThrottles();
  for (auto&& throttle : additional_throttles) {
    throttles.push_back(std::move(throttle));
  }

  uint32_t options =
      GetURLLoaderOptions(resource_request_->is_outermost_main_frame);

  loader_holder_.SetLoader(blink::ThrottlingURLLoader::CreateLoader(
      std::move(throttles), /*client=*/this,
      kNavigationUrlLoaderTrafficAnnotation,
      /*client_receiver_delegate=*/nullptr));
  loader_holder_.url_loader()->Start(
      std::move(factory), global_request_id_.request_id, options,
      resource_request_.get(),
      GetUIThreadTaskRunner({BrowserTaskType::kNavigationNetworkResponse}),
      /*cors_exempt_header_list=*/std::nullopt,
      &request_info_->common_params->initiator_origin_trial_features);
}

const network::ResourceRequest&
NavigationURLLoaderImpl::GetResourceRequestForTesting() const {
  return *resource_request_;
}

void NavigationURLLoaderImpl::OnReceiveEarlyHints(
    network::mojom::EarlyHintsPtr early_hints) {
  // Early Hints should not come after actual response.
  DCHECK(!received_response_);
  DCHECK_NE(early_hints->ip_address_space,
            network::mojom::IPAddressSpace::kUnknown);

  // Ignore Early Hints for embed and object destination.
  if (request_info_->common_params->request_destination ==
          network::mojom::RequestDestination::kEmbed ||
      request_info_->common_params->request_destination ==
          network::mojom::RequestDestination::kObject) {
    return;
  }

  FrameTreeNode* frame_tree_node =
      FrameTreeNode::GloballyFindByID(frame_tree_node_id_);

  // Allow Early Hints preload only for outermost main frames. Calculating
  // appropriate parameters to create URLLoaderFactory for subframes and fenced
  // frames are complicated and not supported yet.
  if (frame_tree_node->GetParentOrOuterDocument()) {
    return;
  }

  if (!early_hints_manager_) {
    std::optional<NavigationEarlyHintsManagerParams> params =
        delegate_->CreateNavigationEarlyHintsManagerParams(*early_hints);
    if (!params) {
      return;
    }
    early_hints_manager_ = std::make_unique<NavigationEarlyHintsManager>(
        *browser_context_, *storage_partition_, frame_tree_node_id_,
        std::move(*params));
  }

  early_hints_manager_->HandleEarlyHints(std::move(early_hints),
                                         *resource_request_.get());
}

void NavigationURLLoaderImpl::OnReceiveResponse(
    network::mojom::URLResponseHeadPtr head,
    mojo::ScopedDataPipeConsumerHandle response_body,
    std::optional<mojo_base::BigBuffer> cached_metadata) {
  DCHECK(!cached_metadata);
  // TODO(https://crbug.com/434182226): Remove DUMP_WILL_BE_.
  DUMP_WILL_BE_CHECK(!loader_holder_.HasExclusiveTask());
  LogQueueTimeHistogram("Navigation.QueueTime.OnReceiveResponse",
                        resource_request_->is_outermost_main_frame);

  // Early Hints preloads should not be committed for PDF.
  // See https://github.com/whatwg/html/issues/7823
  if (head->mime_type == "application/pdf" || head->mime_type == "text/pdf") {
    early_hints_manager_.reset();
  }

  //  TODO(crbug.com/40496584):Resolved an issue where creating RPHI would cause
  //  a crash when the browser context was shut down. We are actively exploring
  //  the appropriate long-term solution. Please remove this condition once the
  //  final fix is implemented.
  if (browser_context_->ShutdownStarted()) {
    return;
  }

  if (!response_body) {
    return;
  }

  response_body_ = std::move(response_body);
  received_response_ = true;

  if (!head_update_params_.load_timing_info.service_worker_start_time
           .is_null()) {
    head->load_timing.service_worker_start_time =
        head_update_params_.load_timing_info.service_worker_start_time;
    head->load_timing.service_worker_ready_time =
        head_update_params_.load_timing_info.service_worker_ready_time;
  }
  if (head_update_params_.initial_service_worker_status.has_value()) {
    head->initial_service_worker_status =
        head_update_params_.initial_service_worker_status;
  }
  if (!head_update_params_.router_info.is_null()) {
    head->service_worker_router_info =
        std::move(head_update_params_.router_info);
  }
  if (!head_update_params_.load_timing_info
           .service_worker_router_evaluation_start.is_null()) {
    head->load_timing.service_worker_router_evaluation_start =
        head_update_params_.load_timing_info
            .service_worker_router_evaluation_start;
  }
  if (head_update_params_.is_synthetic_response_dry_run_mode) {
    head->from_synthetic_response = true;
  }

  // If the default loader (network) was used to handle the URL load request
  // we need to see if the interceptors want to potentially create a new
  // loader for the response. e.g. service workers.
  //
  // As the navigation request has received a response, the URLLoader has
  // completed without any network errors. Some interceptors may still wish
  // to handle the response.
  auto status = network::URLLoaderCompletionStatus(net::OK);
  if (MaybeCreateLoaderForResponse(status, &head)) {
    return;
  }

  // 304 responses should abort the navigation, rather than display the page.
  if (head->headers &&
      head->headers->response_code() == net::HTTP_NOT_MODIFIED) {
    // Call CancelWithError instead of OnComplete so that if there is an
    // intercepting URLLoaderFactory it gets notified.
    loader_holder_.url_loader()->CancelWithError(
        net::ERR_ABORTED,
        std::string_view(base::NumberToString(net::ERR_ABORTED)));
    return;
  }

  network::mojom::URLLoaderClientEndpointsPtr url_loader_client_endpoints =
      loader_holder_.Unbind();

  bool must_download = download_utils::MustDownload(
      browser_context_, url_, head->headers.get(), head->mime_type);
  bool known_mime_type = blink::IsSupportedMimeType(head->mime_type);

#if BUILDFLAG(ENABLE_PLUGINS)
  if (!head->intercepted_by_plugin && !must_download && !known_mime_type) {
    // No plugin throttles intercepted the response. Ask if the plugin
    // registered to PluginService wants to handle the request.
    CheckPluginAndContinueOnReceiveResponse(
        std::move(head), std::move(url_loader_client_endpoints),
        /*is_download_if_not_handled_by_plugin=*/true,
        std::vector<WebPluginInfo>());
    return;
  }
#endif

  // When a plugin intercepted the response, we don't want to download it.
  bool is_download =
      !head->intercepted_by_plugin && (must_download || !known_mime_type);

  CallOnReceivedResponse(std::move(head),
                         std::move(url_loader_client_endpoints), is_download);
}

#if BUILDFLAG(ENABLE_PLUGINS)
void NavigationURLLoaderImpl::CheckPluginAndContinueOnReceiveResponse(
    network::mojom::URLResponseHeadPtr head,
    network::mojom::URLLoaderClientEndpointsPtr url_loader_client_endpoints,
    bool is_download_if_not_handled_by_plugin,
    const std::vector<WebPluginInfo>& plugins) {
  bool stale;
  WebPluginInfo plugin;
  bool has_plugin = PluginService::GetInstance()->GetPluginInfo(
      browser_context_, resource_request_->url, head->mime_type,
      /*allow_wildcard=*/false, &stale, &plugin, nullptr);

  if (stale) {
    // Refresh the plugins asynchronously.
    PluginService::GetInstance()->GetPlugins(base::BindOnce(
        &NavigationURLLoaderImpl::CheckPluginAndContinueOnReceiveResponse,
        weak_factory_.GetWeakPtr(), std::move(head),
        std::move(url_loader_client_endpoints),
        is_download_if_not_handled_by_plugin));
    return;
  }

  bool is_download = !has_plugin && is_download_if_not_handled_by_plugin;
  CallOnReceivedResponse(std::move(head),
                         std::move(url_loader_client_endpoints), is_download);
}
#endif

void NavigationURLLoaderImpl::CallOnReceivedResponse(
    network::mojom::URLResponseHeadPtr head,
    network::mojom::URLLoaderClientEndpointsPtr url_loader_client_endpoints,
    bool is_download) {
  // Record navigation loader response metrics.  We don't want to record the
  // metrics for requests that had redirects to avoid adding noise to the
  // latency measurements.
  if (resource_request_->is_outermost_main_frame &&
      resource_request_->navigation_redirect_chain.size() == 1) {
    RecordReceivedResponseUkmForOutermostMainFrame();
  }

  // Record ServiceWorker and the Static Routing API metrics.
  MaybeRecordServiceWorkerMainResourceInfo(head);

  auto on_receive_response = base::BindOnce(
      &NavigationURLLoaderImpl::NotifyResponseStarted,
      weak_factory_.GetWeakPtr(), std::move(url_loader_client_endpoints),
      std::move(response_body_), global_request_id_, is_download);

  ParseHeaders(url_, std::move(head), std::move(on_receive_response),
               /*clear_parsed_headers_for_testing=*/false);
}

void NavigationURLLoaderImpl::OnReceiveRedirect(
    const net::RedirectInfo& redirect_info,
    network::mojom::URLResponseHeadPtr head) {
  // TODO(https://crbug.com/434182226): Remove DUMP_WILL_BE_.
  DUMP_WILL_BE_CHECK(!loader_holder_.HasExclusiveTask());
  LogQueueTimeHistogram("Navigation.QueueTime.OnReceiveRedirect",
                        resource_request_->is_outermost_main_frame);
  net::Error error = net::OK;

  bool bypass_redirect_checks =
      base::FeatureList::IsEnabled(features::kBypassRedirectChecksPerRequest)
          ? head->bypass_redirect_checks
          : bypass_redirect_checks_;

  if (!bypass_redirect_checks &&
      !IsSafeRedirectTarget(url_, redirect_info.new_url)) {
    error = net::ERR_UNSAFE_REDIRECT;
  } else if (--redirect_limit_ == 0) {
    error = net::ERR_TOO_MANY_REDIRECTS;
    if (redirect_info.is_signed_exchange_fallback_redirect) {
      UMA_HISTOGRAM_BOOLEAN("SignedExchange.FallbackRedirectLoop", true);
    }
  }
  if (error != net::OK) {
    if (loader_holder_.url_loader()) {
      // TODO(https://crbug.com/434182226): Turn this to `CHECK()`.
      DUMP_WILL_BE_CHECK_EQ(loader_holder_.state(),
                            LoaderHolder::State::kLoadingViaLoader);
      // Call CancelWithError instead of OnComplete so that if there is an
      // intercepting URLLoaderFactory (created through the embedder's
      // ContentBrowserClient::WillCreateURLLoaderFactory) it gets notified.
      loader_holder_.url_loader()->CancelWithError(
          error, std::string_view(base::NumberToString(error)));
    } else {
      // TODO(https://crbug.com/434182226): Turn this to `CHECK()`.
      DUMP_WILL_BE_CHECK_EQ(loader_holder_.state(),
                            LoaderHolder::State::kLoadingViaReceiver);
      // TODO(crbug.com/40118809): Make sure ResetWithReason() is called
      // on the original `url_loader_`.
      OnComplete(network::URLLoaderCompletionStatus(error));
    }
    return;
  }

  // Store the redirect_info for later use in FollowRedirect where we give
  // our interceptors_ a chance to intercept the request for the new location.
  redirect_info_ = redirect_info;

  GURL previous_url = url_;
  url_ = redirect_info.new_url;

  loader_holder_.OnExclusiveTaskStarted(
      LoaderHolder::ExclusiveTaskType::kRedirect);

  auto on_receive_redirect =
      base::BindOnce(&NavigationURLLoaderImpl::NotifyRequestRedirected,
                     weak_factory_.GetWeakPtr(), redirect_info);
  const bool clear_parsed_headers_for_testing =
      delegate_->ShouldClearParsedHeadersOnTestReceiveRedirect();
  if (clear_parsed_headers_for_testing) {
    CHECK_IS_TEST();
  }
  ParseHeaders(previous_url, std::move(head), std::move(on_receive_redirect),
               clear_parsed_headers_for_testing);
}

void NavigationURLLoaderImpl::OnUploadProgress(
    int64_t current_position,
    int64_t total_size,
    OnUploadProgressCallback callback) {
  NOTREACHED();
}

void NavigationURLLoaderImpl::OnTransferSizeUpdated(
    int32_t transfer_size_diff) {
  network::RecordOnTransferSizeUpdatedUMA(
      network::OnTransferSizeUpdatedFrom::kNavigationURLLoaderImpl);
}

void NavigationURLLoaderImpl::OnComplete(
    const network::URLLoaderCompletionStatus& status) {
  // Successful load must have used OnResponseStarted first. In this case, the
  // URLLoaderClient has already been transferred to the renderer process and
  // OnComplete is not expected to be called here.
  if (status.error_code == net::OK) {
    SCOPED_CRASH_KEY_STRING256("NavigationURLLoader_Complete", "url",
                               url_.spec());
    base::debug::DumpWithoutCrashing();
    return;
  }

  // If the default loader (network) was used to handle the URL load request
  // we need to see if the interceptors want to potentially create a new
  // loader for the response. e.g. service worker.
  //
  // Note: Despite having received a response, the HTTP_NOT_MODIFIED(304) ones
  //       are ignored using OnComplete(net::ERR_ABORTED). No interceptor must
  //       be used in this case.
  //
  // We also skip interceptors and force the loading to fail when there are
  // exclusive tasks, because we can't gracefully cancel the exclusive tasks and
  // switch to the interceptor-induced redirects.
  if (!received_response_ && !loader_holder_.HasExclusiveTask()) {
    auto response = network::mojom::URLResponseHead::New();
    if (MaybeCreateLoaderForResponse(status, &response)) {
      return;
    }
  }

  // Cancel all loading operations to avoid further URLLoaderClient calls.
  loader_holder_.ResetForFailure();

  status_ = status;
  GetUIThreadTaskRunner({})->PostTask(
      FROM_HERE, base::BindOnce(&NavigationURLLoaderImpl::NotifyRequestFailed,
                                weak_factory_.GetWeakPtr(), status));
}

namespace {

// These values are persisted to logs. Entries should not be renumbered and
// numeric values should never be reused.
// LINT.IfChange(OnAcceptCHFrameReceivedReturnLocation)
enum class OnAcceptCHFrameReceivedReturnLocation {
  kUnknown = 0,
  kNotEnabled = 1,
  kNoClientHintDelegate = 2,
  kNoCriticalHintsMissing = 3,
  kNoRestart = 4,
  kTooManyRestart = 5,
  kSendingErrorAborted = 6,
  kDuringExclusiveTask = 7,
  kMaxValue = kDuringExclusiveTask,
};
// LINT.ThenChange(//tools/metrics/histograms/metadata/navigation/enums.xml:OnAcceptCHFrameReceivedReturnLocation)

void RecordOnAcceptCHFrameReceivedReturnLocation(
    OnAcceptCHFrameReceivedReturnLocation location,
    bool is_off_the_record) {
  base::UmaHistogramEnumeration(
      "Navigation.URLLoader.OnAcceptCHFrameReceived.ReturnLocation", location);
  if (is_off_the_record) {
    base::UmaHistogramEnumeration(
        "Navigation.URLLoader.OnAcceptCHFrameReceived.ReturnLocation."
        "OffTheRecord",
        location);
  }
}

void RecordCriticalHintsMissingStatus(CriticalHintsMissingStatus status) {
  base::UmaHistogramEnumeration(
      "Navigation.URLLoader.OnAcceptCHFrameReceived.CriticalHintsMissingStatus",
      status);
}

}  // namespace

void NavigationURLLoaderImpl::OnAcceptCHFrameReceived(
    const url::Origin& origin,
    const std::vector<network::mojom::WebClientHintsType>& accept_ch_frame,
    OnAcceptCHFrameReceivedCallback callback) {
  LogQueueTimeHistogram("Navigation.QueueTime.OnAcceptCHFrameReceived",
                        resource_request_->is_outermost_main_frame);
  base::ScopedUmaHistogramTimer timer(
      "Navigation.URLLoader.OnAcceptCHFrameReceived.ExecutionTime",
      base::ScopedUmaHistogramTimer::ScopedHistogramTiming::kMicrosecondTimes);
  TRACE_EVENT("navigation", "NavigationURLLoaderImpl::OnAcceptCHFrameReceived");
  received_accept_ch_frame_ = true;
  const bool is_off_the_record = browser_context_->IsOffTheRecord();
  if (!base::FeatureList::IsEnabled(network::features::kAcceptCHFrame)) {
    std::move(callback).Run(net::OK);
    RecordOnAcceptCHFrameReceivedReturnLocation(
        OnAcceptCHFrameReceivedReturnLocation::kNotEnabled, is_off_the_record);
    return;
  }

  LogAcceptCHFrameStatus(AcceptCHFrameRestart::kFramePresent);

  // Given that this is happening in the middle of navigation, there should
  // always be an owning frame tree node
  FrameTreeNode* frame_tree_node =
      FrameTreeNode::GloballyFindByID(frame_tree_node_id_);
  DCHECK(frame_tree_node);
  // Log each hint requested via an ACCEPT_CH Frame whether or not this caused
  // the connection to be restarted.
  auto* ukm_recorder = ukm::UkmRecorder::Get();
  for (const auto& hint : accept_ch_frame) {
    ukm::builders::ClientHints_AcceptCHFrameUsage(ukm_source_id_)
        .SetType(static_cast<int64_t>(hint))
        .Record(ukm_recorder->Get());
  }

  ClientHintsControllerDelegate* client_hint_delegate =
      browser_context_->GetClientHintsControllerDelegate();

  if (!client_hint_delegate) {
    std::move(callback).Run(net::OK);
    RecordOnAcceptCHFrameReceivedReturnLocation(
        OnAcceptCHFrameReceivedReturnLocation::kNoClientHintDelegate,
        is_off_the_record);
    return;
  }

  if (resource_request_->trusted_params->enabled_client_hints) {
    network::ResourceRequest::TrustedParams::EnabledClientHints
        current_hints_obj = GetEnabledClientHints(origin, frame_tree_node,
                                                  client_hint_delegate);
    network::ResourceRequest::TrustedParams::EnabledClientHints& old_hints_obj =
        *resource_request_->trusted_params->enabled_client_hints;
    RecordEnabledClientHintsMismatchHistograms(old_hints_obj,
                                               current_hints_obj);
  }

  // Filter out hints that are disabled by features and the like.
  blink::EnabledClientHints filtered_enabled_hints;
  for (const auto& hint : accept_ch_frame) {
    filtered_enabled_hints.SetIsEnabled(hint, true);
  }
  const std::vector<network::mojom::WebClientHintsType>& filtered_hints =
      filtered_enabled_hints.GetEnabledHints();

  CriticalHintsMissingStatus status = GetCriticalHintsMissingStatus(
      origin, frame_tree_node, client_hint_delegate, filtered_hints);
  RecordCriticalHintsMissingStatus(status);

  if (status != CriticalHintsMissingStatus::kMissing) {
    std::move(callback).Run(net::OK);
    // This block is entered if GetCriticalHintsMissingStatus returns that
    // hints are not missing, meaning either all critical hints were already
    // present, or some were not allowed by the permissions policy.
    RecordOnAcceptCHFrameReceivedReturnLocation(
        OnAcceptCHFrameReceivedReturnLocation::kNoCriticalHintsMissing,
        is_off_the_record);
    return;
  }

  net::HttpRequestHeaders modified_headers;
  client_hint_delegate->SetAdditionalClientHints(filtered_hints);
  AddNavigationRequestClientHintsHeaders(
      origin, &modified_headers, browser_context_, client_hint_delegate,
      frame_tree_node->navigation_request()->is_overriding_user_agent(),
      frame_tree_node,
      frame_tree_node->navigation_request()
          ->commit_params()
          .frame_policy.container_policy);
  client_hint_delegate->ClearAdditionalClientHints();

  LogAcceptCHFrameStatus(AcceptCHFrameRestart::kNavigationRestarted);

  // Only restart if new headers are actually added. Given that header values
  // can be changed via the navigation interceptors or previous restarts, the
  // header values are ignored and only the presence of header names are
  // checked.
  bool restart = false;
  net::HttpRequestHeaders::Iterator header_iter(modified_headers);
  while (header_iter.GetNext()) {
    if (!resource_request_->headers.HasHeader(header_iter.name())) {
      restart = true;
      break;
    }
  }

  if (!restart) {
    std::move(callback).Run(net::OK);
    RecordOnAcceptCHFrameReceivedReturnLocation(
        OnAcceptCHFrameReceivedReturnLocation::kNoRestart, is_off_the_record);
    return;
  }

  // While not a true redirect, a redirect loop can be simulated by repeatedly
  // closing the socket and presenting a different ALPS setting with each new
  // handshake.
  if (--accept_ch_restart_limit_ == 0) {
    LogAcceptCHFrameStatus(AcceptCHFrameRestart::kRedirectOverflow);
    OnComplete(network::URLLoaderCompletionStatus(
        net::ERR_TOO_MANY_ACCEPT_CH_RESTARTS));
    std::move(callback).Run(net::ERR_TOO_MANY_ACCEPT_CH_RESTARTS);
    RecordOnAcceptCHFrameReceivedReturnLocation(
        OnAcceptCHFrameReceivedReturnLocation::kTooManyRestart,
        is_off_the_record);
    return;
  }

  if (loader_holder_.HasExclusiveTask()) {
    // `OnAcceptCHFrameReceived()` is called unexpectedly during another
    // exclusive task (typically `NavigationLoaderInterceptor`) is running.
    // Cancel the navigation.
    // TODO(https://crbug.com/436046316): Investigate why and fix this.
    OnComplete(network::URLLoaderCompletionStatus(net::ERR_ABORTED));
    std::move(callback).Run(net::ERR_ABORTED);
    RecordOnAcceptCHFrameReceivedReturnLocation(
        OnAcceptCHFrameReceivedReturnLocation::kDuringExclusiveTask,
        is_off_the_record);
    return;
  }

  std::move(callback).Run(net::ERR_ABORTED);
  RecordOnAcceptCHFrameReceivedReturnLocation(
      OnAcceptCHFrameReceivedReturnLocation::kSendingErrorAborted,
      is_off_the_record);

  // If the request is restarted, all of the client hints should be replaced
  // the "original"/non-edited values.
  resource_request_->headers.MergeFrom(modified_headers);

  // Calling `OnAcceptCHFrameReceived()` implies the loading is ongoing via
  // `url_loader_` and thus the receiver should be unbound.
  // TODO(https://crbug.com/434182226): Remove DUMP_WILL_BE_.
  DUMP_WILL_BE_CHECK(!loader_holder_.receiver_is_bound_for_check());

  loader_holder_.Reset();
  Restart();
}

void NavigationURLLoaderImpl::Clone(
    mojo::PendingReceiver<network::mojom::AcceptCHFrameObserver> listener) {
  // Use |kNavigationNetworkResponse| thread runner. Messages received related
  // to AcceptCHFrame are not order dependent and can restart the navigation,
  // blocking navigation when they do.
  accept_ch_frame_observers_.Add(
      this, std::move(listener),
      GetUIThreadTaskRunner({BrowserTaskType::kNavigationNetworkResponse}));
}

// Returns true if an interceptor wants to handle the response, i.e. return a
// different response, e.g. service workers.
bool NavigationURLLoaderImpl::MaybeCreateLoaderForResponse(
    const network::URLLoaderCompletionStatus& status,
    network::mojom::URLResponseHeadPtr* response) {
  if (!default_loader_used_) {
    return false;
  }
  for (auto& interceptor : interceptors_) {
    mojo::PendingReceiver<network::mojom::URLLoaderClient>
        response_client_receiver;
    bool skip_other_interceptors = false;
    // The `MaybeCreateLoaderForResponse()` call here seems to have been
    // implicitly assuming the url_loader is non-null since before, because
    // `SignedExchangeRequestHandler::MaybeCreateLoaderForResponse()` requires a
    // non-null url_loader. This should hold because:
    // - `MaybeCreateLoaderForResponse()` is called from the URLLoaderClient
    //   override methods, so the loading is ongoing.
    // - `default_loader_used_` is true here, so the state can't be
    //   `kLoadingViaReceiver` and thus it should be `kLoadingViaLoader`.
    // TODO(https://crbug.com/434182226): Turn this to `CHECK()`.
    DUMP_WILL_BE_CHECK_EQ(loader_holder_.state(),
                          LoaderHolder::State::kLoadingViaLoader);

    if (interceptor->MaybeCreateLoaderForResponse(
            status, *resource_request_, response, &response_body_,
            loader_holder_.response_url_loader(), &response_client_receiver,
            loader_holder_.url_loader(), &skip_other_interceptors)) {
      loader_holder_.BindReceiver(
          std::move(response_client_receiver),
          GetUIThreadTaskRunner({BrowserTaskType::kNavigationNetworkResponse}));
      default_loader_used_ = false;
      response_body_.reset();  // Consumed above.
      if (skip_other_interceptors) {
        std::vector<std::unique_ptr<NavigationLoaderInterceptor>>
            new_interceptors;
        new_interceptors.push_back(std::move(interceptor));
        new_interceptors.swap(interceptors_);
        // Reset the state of ServiceWorkerClient.
        // Currently we don't support Service Worker in Signed Exchange
        // pages. The page will not be controlled by service workers. And
        // Service Worker related APIs will fail with NoDocumentURL error.
        // TODO(https://crbug/898733): Support SignedExchange loading and
        // Service Worker integration. Properly populate all params below, and
        // storage key in particular, when we want to support it.
        if (service_worker_handle_) {
          base::WeakPtr<ServiceWorkerClient> service_worker_client =
              service_worker_handle_->service_worker_client();
          if (service_worker_client) {
            service_worker_client->SetControllerRegistration(
                nullptr, /*notify_controllerchange=*/false);
            service_worker_client->UpdateUrls(GURL(), std::nullopt,
                                              blink::StorageKey());
          }
        }
      }
      return true;
    }
  }
  return false;
}

std::vector<std::unique_ptr<blink::URLLoaderThrottle>>
NavigationURLLoaderImpl::CreateURLLoaderThrottles() {
  TRACE_EVENT_WITH_FLOW0("navigation",
                         "NavigationURLLoaderImpl::CreateURLLoaderThrottles",
                         TRACE_ID_LOCAL(this),
                         TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT);
  auto throttles = CreateContentBrowserURLLoaderThrottles(
      *resource_request_, browser_context_, web_contents_getter_,
      navigation_ui_data_.get(), frame_tree_node_id_,
      request_info_->navigation_id);
  throttles.push_back(std::make_unique<NavigationTimingThrottle>(
      resource_request_->is_outermost_main_frame, loader_creation_time_));
  return throttles;
}

std::unique_ptr<SignedExchangeRequestHandler>
NavigationURLLoaderImpl::CreateSignedExchangeRequestHandler(
    const NavigationRequestInfo& request_info,
    scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory) {
  // It is safe to pass the callback of CreateURLLoaderThrottles with the
  // unretained `this`, because the passed callback will be used by a
  // SignedExchangeHandler which is indirectly owned by `this` until its
  // header is verified and parsed, that's where the getter is used.
  return std::make_unique<SignedExchangeRequestHandler>(
      GetURLLoaderOptions(request_info.is_outermost_main_frame),
      request_info.frame_tree_node_id, request_info.devtools_navigation_token,
      std::move(url_loader_factory),
      base::BindRepeating(&NavigationURLLoaderImpl::CreateURLLoaderThrottles,
                          base::Unretained(this)),
      GetContentClient()->browser()->GetAcceptLangs(browser_context_));
}

void NavigationURLLoaderImpl::ParseHeaders(
    const GURL& url,
    network::mojom::URLResponseHeadPtr head,
    base::OnceCallback<void(network::mojom::URLResponseHeadPtr)> continuation,
    bool clear_parsed_headers_for_testing) {
  // As an optimization, when we know the parsed headers will be empty, we can
  // skip the network process roundtrip.
  // TODO(arthursonzogni): If there are any performance issues, consider
  // checking the `head->headers` contains at least one header to be parsed.
  if (!head->headers) {
    head->parsed_headers = network::mojom::ParsedHeaders::New();
  }

  // If the network service is running in process, skip unnecessary thread hops.
  if (IsInProcessNetworkService() && !head->parsed_headers) {
    base::ScopedUmaHistogramTimer in_process(
        "Navigation.URLLoader.ParseHeaders.InProcessTime",
        base::ScopedUmaHistogramTimer::ScopedHistogramTiming::
            kMicrosecondTimes);
    head->parsed_headers =
        network::PopulateParsedHeaders(head->headers.get(), url);
  }

  if (clear_parsed_headers_for_testing) {
    CHECK_IS_TEST();
    head->parsed_headers.reset();
  }

  // The main path:
  // --------------
  // The ParsedHeaders are already provided. No more work needed.
  //
  // Currently used when the response is coming from:
  // - Network
  // - ServiceWorker
  // - WebUI
  base::UmaHistogramBoolean("Navigation.URLLoader.InMainPath",
                            static_cast<bool>(head->parsed_headers));
  if (head->parsed_headers) {
#ifndef NDEBUG
    // In debug mode, force reparsing the headers and check that they match.
    auto check = [](base::OnceCallback<void(network::mojom::URLResponseHeadPtr)>
                        continuation,
                    network::mojom::URLResponseHeadPtr head, GURL url,
                    base::TimeTicks call_time,
                    network::mojom::ParsedHeadersPtr parsed_headers) {
      base::UmaHistogramMicrosecondsTimes(
          "Navigation.URLLoader.ParseHeaders.RoundTripTimeForVerify",
          base::TimeTicks::Now() - call_time);
      CheckParsedHeadersEquals(parsed_headers, head->parsed_headers, url);
      std::move(continuation).Run(std::move(head));
    };
    scoped_refptr<net::HttpResponseHeaders> headers = head->headers;
    GetNetworkService()->ParseHeaders(
        url, std::move(headers),
        base::BindOnce(check, std::move(continuation), std::move(head), url,
                       base::TimeTicks::Now()));
#else   // NDEBUG
    std::move(continuation).Run(std::move(head));
#endif  // NDEBUG
    return;
  }

  auto assign = [](base::OnceCallback<void(network::mojom::URLResponseHeadPtr)>
                       continuation,
                   network::mojom::URLResponseHeadPtr head,
                   base::TimeTicks call_time,
                   network::mojom::ParsedHeadersPtr parsed_headers) {
    base::UmaHistogramMicrosecondsTimes(
        "Navigation.URLLoader.ParseHeaders.RoundTripTimeForNonNetworkResponse",
        base::TimeTicks::Now() - call_time);
    head->parsed_headers = std::move(parsed_headers);
    std::move(continuation).Run(std::move(head));
  };

  scoped_refptr<net::HttpResponseHeaders> headers = head->headers;
  GetNetworkService()->ParseHeaders(
      url, std::move(headers),
      base::BindOnce(assign, std::move(continuation), std::move(head),
                     base::TimeTicks::Now()));
}

// TODO(crbug.com/40552600): pass `navigation_ui_data` along with the
// request so that it could be modified.
NavigationURLLoaderImpl::NavigationURLLoaderImpl(
    BrowserContext* browser_context,
    StoragePartition* storage_partition,
    std::unique_ptr<NavigationRequestInfo> request_info,
    std::unique_ptr<NavigationUIData> navigation_ui_data,
    ServiceWorkerMainResourceHandle* service_worker_handle,
    scoped_refptr<PrefetchedSignedExchangeCache>
        prefetched_signed_exchange_cache,
    NavigationURLLoaderDelegate* delegate,
    mojo::PendingRemote<network::mojom::CookieAccessObserver> cookie_observer,
    mojo::PendingRemote<network::mojom::TrustTokenAccessObserver>
        trust_token_observer,
    mojo::PendingRemote<network::mojom::SharedDictionaryAccessObserver>
        shared_dictionary_observer,
    mojo::PendingRemote<network::mojom::URLLoaderNetworkServiceObserver>
        url_loader_network_observer,
    mojo::PendingRemote<network::mojom::DevToolsObserver> devtools_observer,
    mojo::PendingRemote<network::mojom::DeviceBoundSessionAccessObserver>
        device_bound_session_observer,
    std::vector<std::unique_ptr<NavigationLoaderInterceptor>>
        initial_interceptors)
    : delegate_(delegate),
      browser_context_(browser_context),
      storage_partition_(static_cast<StoragePartitionImpl*>(storage_partition)),
      service_worker_handle_(service_worker_handle),
      request_info_(std::move(request_info)),
      url_(request_info_->common_params->url),
      frame_tree_node_id_(request_info_->frame_tree_node_id),
      global_request_id_(GlobalRequestID::MakeBrowserInitiated()),
      web_contents_getter_(
          base::BindRepeating(&WebContents::FromFrameTreeNodeId,
                              frame_tree_node_id_)),
      navigation_ui_data_(std::move(navigation_ui_data)),
      interceptors_(std::move(initial_interceptors)),
      prefetched_signed_exchange_cache_(
          std::move(prefetched_signed_exchange_cache)),
      loader_creation_time_(base::TimeTicks::Now()),
      ukm_source_id_(FrameTreeNode::GloballyFindByID(frame_tree_node_id_)
                         ->navigation_request()
                         ->GetNextPageUkmSourceId()) {
  TRACE_EVENT_WITH_FLOW0("navigation",
                         "NavigationURLLoaderImpl::NavigationURLLoaderImpl",
                         TRACE_ID_LOCAL(this), TRACE_EVENT_FLAG_FLOW_OUT);
  DCHECK_CURRENTLY_ON(BrowserThread::UI);

  TRACE_EVENT_BEGIN("navigation", "Navigation timeToResponseStarted",
                    perfetto::Track::FromPointer(this),
                    request_info_->common_params->navigation_start,
                    "FrameTreeNode id", frame_tree_node_id_);

  mojo::PendingRemote<network::mojom::AcceptCHFrameObserver>
      accept_ch_frame_observer;
  // Use |kNavigationNetworkResponse| thread runner. Messages received related
  // to AcceptCHFrame are not order dependent and can restart the navigation,
  // blocking navigation when they do.
  accept_ch_frame_observers_.Add(
      this, accept_ch_frame_observer.InitWithNewPipeAndPassReceiver(),
      GetUIThreadTaskRunner({BrowserTaskType::kNavigationNetworkResponse}));

  FrameTreeNode* frame_tree_node =
      FrameTreeNode::GloballyFindByID(frame_tree_node_id_);
  DCHECK(frame_tree_node);
  DCHECK(frame_tree_node->navigation_request());

  resource_request_ = CreateResourceRequest(
      *request_info_, frame_tree_node,
      browser_context_->GetClientHintsControllerDelegate(),
      std::move(cookie_observer), std::move(trust_token_observer),
      std::move(shared_dictionary_observer),
      std::move(url_loader_network_observer), std::move(devtools_observer),
      std::move(device_bound_session_observer),
      std::move(accept_ch_frame_observer));

  network_loader_factory_ = CreateNetworkLoaderFactory(
      browser_context_, storage_partition_, frame_tree_node,
      ukm::SourceIdObj::FromInt64(ukm_source_id_), &bypass_redirect_checks_);
}

// static
mojo::PendingRemote<network::mojom::URLLoaderFactory>
NavigationURLLoaderImpl::CreateTerminalNonNetworkLoaderFactory(
    BrowserContext* browser_context,
    StoragePartitionImpl* storage_partition,
    FrameTreeNode* frame_tree_node,
    const GURL& url) {
  // Use `ContentBrowserClient`-supplied factory if non-null, to allow the
  // embedder to override the default factories below.
  if (auto factory_from_client =
          GetContentClient()
              ->browser()
              ->CreateNonNetworkNavigationURLLoaderFactory(
                  url.GetScheme(), frame_tree_node->frame_tree_node_id())) {
    return factory_from_client;
  }

  if (url.GetScheme() == url::kFileSystemScheme) {
    bool is_nav_allowed =
        base::FeatureList::IsEnabled(
            blink::features::kFileSystemUrlNavigationForChromeAppsOnly) &&
        GetContentClient()->browser()->IsFileSystemURLNavigationAllowed(
            storage_partition->browser_context(), url);
    if (is_nav_allowed ||
        base::FeatureList::IsEnabled(
            blink::features::kFileSystemUrlNavigation) ||
        !frame_tree_node->navigation_request()->IsRendererInitiated()) {
      // TODO(crbug.com/40323778): Once DevTools has support for
      // sandboxed file system inspection there isn't much reason anymore to
      // support browser initiated filesystem: navigations, so remove this
      // entirely at that point.

      // Navigations in to filesystem: URLs are deprecated entirely for
      // renderer-initiated navigations except for those explicitly allowed by
      // the embedder. The logic below is appropriate for browser-initiated
      // navigations, but it is incorrect to always use first-party
      // StorageKeys for renderer-initiated navigations when third party
      // storage partitioning is enabled.
      const std::string storage_domain;
      return CreateFileSystemURLLoaderFactory(
          ChildProcessHost::kInvalidUniqueID,
          frame_tree_node->frame_tree_node_id(),
          storage_partition->GetFileSystemContext(), storage_domain,
          blink::StorageKey::CreateFirstParty(url::Origin::Create(url)));
    }

    return {};
  }

  if (url.GetScheme() == url::kAboutScheme) {
    return AboutURLLoaderFactory::Create();
  }
  if (url.GetScheme() == url::kDataScheme) {
    return DataURLLoaderFactory::Create();
  }

  if (url.GetScheme() == url::kFileScheme) {
    // USER_BLOCKING because this scenario is exactly one of the examples
    // given by the doc comment for USER_BLOCKING:
    // Loading and rendering a web page after the user clicks a link.
    base::TaskPriority file_factory_priority =
        base::TaskPriority::USER_BLOCKING;
    return FileURLLoaderFactory::Create(
        browser_context->GetPath(),
        browser_context->GetSharedCorsOriginAccessList(),
        file_factory_priority);
  }

#if BUILDFLAG(IS_ANDROID)
  if (url.GetScheme() == url::kContentScheme) {
    return ContentURLLoaderFactory::Create();
  }
#endif

  return {};
}

scoped_refptr<network::SharedURLLoaderFactory>
NavigationURLLoaderImpl::CreateNetworkLoaderFactory(
    BrowserContext* browser_context,
    StoragePartitionImpl* storage_partition,
    FrameTreeNode* frame_tree_node,
    const ukm::SourceIdObj& ukm_id,
    bool* bypass_redirect_checks) {
  mojo::PendingRemote<network::mojom::TrustedURLLoaderHeaderClient>
      header_client;

  // The embedder may want to proxy all network-bound URLLoaderFactory
  // receivers that it can. If it elects to do so, those proxies will be
  // connected when loader is created if the request type supports proxying.
  network::URLLoaderFactoryBuilder factory_builder;
  // Here we give nullptr for `factory_override`, because CORS is no-op for
  // navigations.
  GetContentClient()->browser()->WillCreateURLLoaderFactory(
      browser_context, frame_tree_node->current_frame_host(),
      frame_tree_node->current_frame_host()->GetProcess()->GetDeprecatedID(),
      ContentBrowserClient::URLLoaderFactoryType::kNavigation, url::Origin(),
      net::IsolationInfo(),
      frame_tree_node->navigation_request()->GetNavigationId(), ukm_id,
      factory_builder, &header_client, bypass_redirect_checks,
      /*disable_secure_dns=*/nullptr, /*factory_override=*/nullptr,
      GetUIThreadTaskRunner({BrowserTaskType::kNavigationNetworkResponse}));

  auto devtools_params =
      devtools_instrumentation::WillCreateURLLoaderFactoryParams::ForFrame(
          frame_tree_node->current_frame_host());
  devtools_params.Run(/*is_navigation=*/true,
                      /*is_download=*/false, factory_builder,
                      /*factory_override=*/nullptr);
  net::CookieSettingOverrides devtools_cookie_overrides;
  devtools_instrumentation::ApplyNetworkCookieControlsOverrides(
      devtools_params.agent_host(), devtools_cookie_overrides);

  net::CookieSettingOverrides cookie_overrides;
  if (ShouldAllowSameSiteNoneCookiesInSandbox(*frame_tree_node)) {
    // Include a CookieSettingOverride in the UrlLoaderFactoryParams for the
    // frame's SharedURLLoaderFactory if the frame contains the
    // `allow-same-site-none-cookies` value in its sandbox policy.
    cookie_overrides.Put(
        net::CookieSettingOverride::kAllowSameSiteNoneCookiesInSandbox);
  }

  if (header_client) {
    return base::MakeRefCounted<network::WrapperSharedURLLoaderFactory>(
        CreateURLLoaderFactoryWithHeaderClient(
            std::move(header_client), std::move(factory_builder),
            storage_partition, std::move(devtools_cookie_overrides),
            std::move(cookie_overrides)));
  } else {
    if (!devtools_cookie_overrides.empty() || !cookie_overrides.empty()) {
      network::mojom::URLLoaderFactoryParamsPtr params =
          storage_partition->CreateURLLoaderFactoryParams();
      params->devtools_cookie_setting_overrides =
          std::move(devtools_cookie_overrides);
      params->cookie_setting_overrides = std::move(cookie_overrides);
      return std::move(factory_builder)
          .Finish(storage_partition->GetNetworkContext(), std::move(params));
    }
    return std::move(factory_builder)
        .Finish(storage_partition->GetURLLoaderFactoryForBrowserProcess());
  }
}

void NavigationURLLoaderImpl::FollowRedirect(
    std::vector<std::string> removed_headers,
    net::HttpRequestHeaders modified_headers,
    net::HttpRequestHeaders modified_cors_exempt_headers) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  DCHECK(!redirect_info_.new_url.is_empty());

  if (loader_holder_.ShouldCancelExclusiveTask(
          LoaderHolder::ExclusiveTaskType::kRedirect)) {
    return;
  }
  loader_holder_.OnExclusiveTaskCompleted(
      LoaderHolder::ExclusiveTaskType::kRedirect);

  // Don't send Accept: application/signed-exchange for fallback redirects.
  // This is also applied to `resource_request_->headers` via
  // `net::RedirectUtil::UpdateHttpRequest()`.
  if (redirect_info_.is_signed_exchange_fallback_redirect) {
    modified_headers.SetHeader(
        net::HttpRequestHeaders::kAccept,
        FrameAcceptHeaderValue(/*allow_sxg_responses=*/false,
                               browser_context_));
  }

  // Update `resource_request_` and call Restart to give our `interceptors_` a
  // chance at handling the new location. If no interceptor wants to take
  // over, we'll use the existing url_loader to follow the redirect, see
  // MaybeStartLoader.
  // TODO(michaeln): This is still WIP and is based on URLRequest::Redirect,
  // there likely remains more to be done.
  // a. For subframe navigations, the Origin header may need to be modified
  //    differently?

  bool should_clear_upload = false;
  net::RedirectUtil::UpdateHttpRequest(
      resource_request_->url, resource_request_->method, redirect_info_,
      removed_headers, modified_headers, &resource_request_->headers,
      &should_clear_upload);
  if (should_clear_upload) {
    // The request body is no longer applicable.
    resource_request_->request_body.reset();
  }

  const GURL previous_url = resource_request_->url;
  resource_request_->url = redirect_info_.new_url;
  resource_request_->method = redirect_info_.new_method;
  resource_request_->site_for_cookies = redirect_info_.new_site_for_cookies;

  // See if navigation network isolation key needs to be updated.
  resource_request_->trusted_params->isolation_info =
      resource_request_->trusted_params->isolation_info.CreateForRedirect(
          url::Origin::Create(resource_request_->url));

  resource_request_->referrer = GURL(redirect_info_.new_referrer);
  resource_request_->referrer_policy = redirect_info_.new_referrer_policy;
  resource_request_->navigation_redirect_chain.push_back(
      redirect_info_.new_url);

  if (base::FeatureList::IsEnabled(
          network::features::kOffloadAcceptCHFrameCheck)) {
    const url::Origin new_origin = url::Origin::Create(resource_request_->url);
    const url::Origin old_origin = url::Origin::Create(previous_url);
    if (!new_origin.IsSameOriginWith(old_origin)) {
      // For cross-origin redirects, the existing client hints are invalid.
      // Clear them to avoid sending unintentional hints.
      resource_request_->trusted_params->enabled_client_hints.reset();

      if (network::features::kAcceptCHOffloadWithRedirect.Get()) {
        FrameTreeNode* frame_tree_node =
            FrameTreeNode::GloballyFindByID(frame_tree_node_id_);
        ClientHintsControllerDelegate* client_hints_controller_delegate =
            browser_context_->GetClientHintsControllerDelegate();
        if (client_hints_controller_delegate && frame_tree_node) {
          resource_request_->trusted_params->enabled_client_hints =
              GetEnabledClientHints(new_origin, frame_tree_node,
                                    client_hints_controller_delegate);
        }
      }
    }
  }

  // Need to cache modified headers for `url_loader_` since it doesn't use
  // `resource_request_` during redirect.
  loader_holder_.SetModifiedHeadersOnRedirect(
      std::move(removed_headers), std::move(modified_headers),
      std::move(modified_cors_exempt_headers));

  Restart();
}

bool NavigationURLLoaderImpl::SetNavigationTimeout(base::TimeDelta timeout) {
  // If the timer has already been started, don't change it.
  if (timeout_timer_.IsRunning()) {
    return false;
  }

  // Fail the navigation with error code ERR_TIMED_OUT if the timer triggers
  // before the navigation commits. (This triggers OnComplete() rather than
  // NotifyRequestFailed() to make sure that any NavigationLoaderInterceptors
  // can handle the result if needed.)
  timeout_timer_.Start(
      FROM_HERE, timeout,
      base::BindOnce(&NavigationURLLoaderImpl::OnComplete,
                     base::Unretained(this),
                     network::URLLoaderCompletionStatus(net::ERR_TIMED_OUT)));
  return true;
}

void NavigationURLLoaderImpl::CancelNavigationTimeout() {
  timeout_timer_.Stop();
}

void NavigationURLLoaderImpl::TriggerTimeoutForTesting() {
  timeout_timer_.FireNow();
}

void NavigationURLLoaderImpl::NotifyResponseStarted(
    network::mojom::URLLoaderClientEndpointsPtr url_loader_client_endpoints,
    mojo::ScopedDataPipeConsumerHandle response_body,
    const GlobalRequestID& global_request_id,
    bool is_download,
    network::mojom::URLResponseHeadPtr response_head) {
  // End "Navigation timeToResponseStarted" trace event.
  TRACE_EVENT_END("navigation", perfetto::Track::FromPointer(this),
                  "&NavigationURLLoaderImpl", static_cast<void*>(this),
                  "success", true);

  NavigationURLLoaderDelegate::EarlyHints early_hints;
  if (early_hints_manager_) {
    early_hints.was_resource_hints_received =
        early_hints_manager_->WasResourceHintsReceived();

    // Make Early Hints manager outlive this loader only when the response
    // headers are available. Dropping the manager cancels inflight preloads.
    if (response_head && response_head->headers) {
      early_hints.manager = std::move(early_hints_manager_);
    }
  }

  // TODO(scottmg): This needs to do more of what
  // NavigationResourceHandler::OnResponseStarted() does.
  delegate_->OnResponseStarted(
      std::move(url_loader_client_endpoints), std::move(response_head),
      std::move(response_body), global_request_id, is_download,
      resource_request_->trusted_params->isolation_info
          .network_anonymization_key(),
      std::move(subresource_loader_params_), std::move(early_hints));
}

void NavigationURLLoaderImpl::NotifyRequestRedirected(
    net::RedirectInfo redirect_info,
    network::mojom::URLResponseHeadPtr response_head) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);

  if (loader_holder_.ShouldCancelExclusiveTask(
          LoaderHolder::ExclusiveTaskType::kRedirect)) {
    return;
  }

  delegate_->OnRequestRedirected(
      redirect_info,
      resource_request_->trusted_params->isolation_info
          .network_anonymization_key(),
      std::move(response_head));
}

void NavigationURLLoaderImpl::NotifyRequestFailed(
    const network::URLLoaderCompletionStatus& status) {
  // End "Navigation timeToResponseStarted" trace event.
  TRACE_EVENT_END("navigation", perfetto::Track::FromPointer(this),
                  "&NavigationURLLoaderImpl", static_cast<void*>(this),
                  "success", false);
  delegate_->OnRequestFailed(status);
}

// static
mojo::PendingRemote<network::mojom::URLLoaderFactory>
NavigationURLLoaderImpl::CreateURLLoaderFactoryWithHeaderClient(
    mojo::PendingRemote<network::mojom::TrustedURLLoaderHeaderClient>
        header_client,
    network::URLLoaderFactoryBuilder factory_builder,
    StoragePartitionImpl* partition,
    std::optional<net::CookieSettingOverrides> devtools_cookie_overrides,
    std::optional<net::CookieSettingOverrides> cookie_overrides) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);

  if (url_loader_factory::GetTestingInterceptor()) {
    url_loader_factory::GetTestingInterceptor().Run(
        network::mojom::kBrowserProcessId, factory_builder);
  }

  network::mojom::URLLoaderFactoryParamsPtr params =
      network::mojom::URLLoaderFactoryParams::New();
  params->header_client = std::move(header_client);
  params->process_id = network::mojom::kBrowserProcessId;
  params->is_trusted = true;
  params->is_orb_enabled = false;
  params->disable_web_security =
      base::CommandLine::ForCurrentProcess()->HasSwitch(
          switches::kDisableWebSecurity);
  if (devtools_cookie_overrides.has_value()) {
    params->devtools_cookie_setting_overrides =
        std::move(devtools_cookie_overrides.value());
  }
  if (cookie_overrides.has_value()) {
    params->cookie_setting_overrides = std::move(cookie_overrides.value());
  }
  return std::move(factory_builder)
      .Finish<mojo::PendingRemote<network::mojom::URLLoaderFactory>>(
          partition->GetNetworkContext(), std::move(params));
}

void NavigationURLLoaderImpl::RecordReceivedResponseUkmForOutermostMainFrame() {
  FrameTreeNode* frame_tree_node =
      FrameTreeNode::GloballyFindByID(frame_tree_node_id_);
  DCHECK(frame_tree_node);

  auto* ukm_recorder = ukm::UkmRecorder::Get();
  ukm::builders::Navigation_ReceivedResponse builder(ukm_source_id_);
  base::TimeDelta latency = base::TimeTicks::Now() - loader_creation_time_;
  builder.SetHasAcceptCHFrame(received_accept_ch_frame_)
      .SetNavigationFirstResponseLatency(latency.InMilliseconds());
  builder.Record(ukm_recorder->Get());

  // Reset whether the ACCEPT_CH frame was received for the navigation.
  received_accept_ch_frame_ = false;
}

void NavigationURLLoaderImpl::MaybeRecordServiceWorkerMainResourceInfo(
    const network::mojom::URLResponseHeadPtr& head) {
  CHECK(head);
  if (!head->initial_service_worker_status.has_value() &&
      !head->service_worker_router_info) {
    return;
  }

  ukm::builders::ServiceWorker_MainResourceLoadCompleted builder(
      ukm_source_id_);

  CHECK(head->initial_service_worker_status.has_value());
  builder.SetInitialWorkerStatus(
      static_cast<int64_t>(head->initial_service_worker_status.value()));

  if (head->service_worker_router_info) {
    network::mojom::ServiceWorkerRouterInfo* router_info =
        head->service_worker_router_info.get();
    if (router_info->evaluation_worker_status.has_value()) {
      builder.SetWorkerStatusOnEvaluation(
          static_cast<int64_t>(router_info->evaluation_worker_status.value()));
    }
    // Check if `matched_source_type` and `actual_source_type` exists. If
    // `matched_source_type` exists, `actual_source_type` should also exist.
    // Likewise, if `matched_source_type` does not exist, `actual_source_type`
    // should also not exist.
    CHECK_EQ(router_info->matched_source_type.has_value(),
             router_info->actual_source_type.has_value());
    if (router_info->matched_source_type) {
      builder.SetMatchedFirstRouterSourceType(
          static_cast<int64_t>(*router_info->matched_source_type));
      if (router_info->matched_source_type ==
          network::mojom::ServiceWorkerRouterSourceType::kCache) {
        builder.SetCacheLookupTime(
            router_info->cache_lookup_time.InMilliseconds());
      }
    }
    if (router_info->actual_source_type) {
      builder.SetActualRouterSourceType(
          static_cast<int64_t>(*router_info->actual_source_type));
    }
    builder
        .SetRouterRuleCount(ukm::GetExponentialBucketMinForCounts1000(
            router_info->route_rule_num))
        .SetRouterEvaluationTime(
            router_info->router_evaluation_time.InMicroseconds());
  }
  builder.Record(ukm::UkmRecorder::Get());
}

}  // namespace content
