// Copyright 2020 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#define TODO_BASE_FEATURE_MACROS_NEED_MIGRATION

#include "content/browser/preloading/prerender/prerender_host.h"

#include <memory>
#include <optional>

#include "base/check_is_test.h"
#include "base/feature_list.h"
#include "base/metrics/histogram_functions.h"
#include "base/notreached.h"
#include "base/observer_list.h"
#include "base/run_loop.h"
#include "base/strings/string_util.h"
#include "base/task/thread_pool.h"
#include "base/time/time.h"
#include "base/trace_event/named_trigger.h"
#include "base/trace_event/typed_macros.h"
#include "content/browser/client_hints/client_hints.h"
#include "content/browser/devtools/devtools_instrumentation.h"
#include "content/browser/preloading/prefetch/no_vary_search_helper.h"
#include "content/browser/preloading/preloading_attempt_impl.h"
#include "content/browser/preloading/preloading_trigger_type_impl.h"
#include "content/browser/preloading/prerender/devtools_prerender_attempt.h"
#include "content/browser/preloading/prerender/prerender_features.h"
#include "content/browser/preloading/prerender/prerender_final_status.h"
#include "content/browser/preloading/prerender/prerender_host_registry.h"
#include "content/browser/preloading/prerender/prerender_metrics.h"
#include "content/browser/preloading/prerender/prerender_navigation_utils.h"
#include "content/browser/preloading/speculation_rules/speculation_rules_util.h"
#include "content/browser/renderer_host/frame_tree.h"
#include "content/browser/renderer_host/frame_tree_node.h"
#include "content/browser/renderer_host/navigation_controller_impl.h"
#include "content/browser/renderer_host/navigation_entry_restore_context_impl.h"
#include "content/browser/renderer_host/navigation_request.h"
#include "content/browser/renderer_host/render_frame_host_impl.h"
#include "content/browser/web_contents/web_contents_impl.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/navigation_controller.h"
#include "content/public/browser/preloading_trigger_type.h"
#include "content/public/browser/web_contents_delegate.h"
#include "content/public/common/referrer.h"
#include "net/base/load_flags.h"
#include "net/http/http_request_headers.h"
#include "third_party/blink/public/common/client_hints/enabled_client_hints.h"
#include "third_party/blink/public/common/navigation/preloading_headers.h"
#include "url/origin.h"

#if BUILDFLAG(IS_ANDROID)
#include "base/strings/stringprintf.h"
#endif

namespace content {

namespace {

base::OnceCallback<void(FrameTreeNodeId)>& GetHostCreationCallback() {
  static base::NoDestructor<base::OnceCallback<void(FrameTreeNodeId)>>
      host_creation_callback;
  return *host_creation_callback;
}

void CheckPrerenderAttributes(const PrerenderAttributes& attributes) {
  // If the prerendering is browser-initiated, it is expected to have no
  // initiator. All initiator related information should be null or invalid. On
  // the other hand, renderer-initiated prerendering should have valid initiator
  // information.
  if (attributes.IsBrowserInitiated()) {
    CHECK(!attributes.initiator_origin.has_value());
    CHECK(!attributes.initiator_frame_token.has_value());
    CHECK_EQ(attributes.initiator_process_id,
             ChildProcessHost::kInvalidUniqueID);
    CHECK_EQ(attributes.initiator_ukm_id, ukm::kInvalidSourceId);
    CHECK(attributes.initiator_frame_tree_node_id.is_null());
  } else {
    CHECK(attributes.initiator_origin.has_value());
    CHECK(attributes.initiator_frame_token.has_value());
    CHECK_NE(attributes.initiator_process_id,
             ChildProcessHost::kInvalidUniqueID);
    CHECK_NE(attributes.initiator_ukm_id, ukm::kInvalidSourceId);
    CHECK(attributes.initiator_frame_tree_node_id);
  }
}

#if BUILDFLAG(IS_ANDROID)
// This is similar to `HttpRequestHeaders::ToString()` but the headers are
// separated by "\n", not "\r\n", as
// `NavigationController::LoadURLParams::extra_headers` requires the format.
std::string SerializeHttpRequestHeaders(
    const net::HttpRequestHeaders& headers) {
  CHECK(!headers.IsEmpty());
  std::string output;
  for (const auto& header : headers.GetHeaderVector()) {
    base::StringAppendF(&output, "%s: %s\n", header.key.c_str(),
                        header.value.c_str());
  }
  // Add the trailing `\n`.
  output.append("\n");
  return output;
}
#endif  // BUILDFLAG(IS_ANDROID)

PrerenderHostId NextPrerenderHostId() {
  static PrerenderHostId::Generator generator;
  return generator.GenerateNextId();
}

}  // namespace

PrerenderHost::PrerenderFrameTreeDelegate::PrerenderFrameTreeDelegate(
    BrowserContext* browser_context,
    WebContentsImpl& web_contents,
    PrerenderHost& prerender_host)
    : prerender_host_(prerender_host),
      frame_tree_(
          std::make_unique<FrameTree>(browser_context,
                                      /*delegate=*/this,
                                      /*navigation_controller_delegate=*/this,
                                      /*navigator_delegate=*/&web_contents,
                                      /*render_frame_delegate=*/&web_contents,
                                      /*render_view_delegate=*/&web_contents,
                                      /*render_widget_delegate=*/&web_contents,
                                      /*manager_delegate=*/&web_contents,
                                      /*page_delegate=*/&web_contents,
                                      FrameTree::Type::kPrerender)) {}

void PrerenderHost::PrerenderFrameTreeDelegate::DidStopLoading() {
  if (on_wait_loading_finished_) {
    std::move(on_wait_loading_finished_).Run(LoadingOutcome::kLoadingCompleted);
  }
}

bool PrerenderHost::PrerenderFrameTreeDelegate::IsHidden() {
  return true;
}

FrameTree* PrerenderHost::PrerenderFrameTreeDelegate::LoadingTree() {
  // For prerendering loading tree is the same as its frame tree as loading is
  // done at a frame tree level in the background, unlike the loading visible
  // to the user where we account for nested frame tree loading state.
  return frame_tree_.get();
}

FrameTreeNodeId
PrerenderHost::PrerenderFrameTreeDelegate::GetOuterDelegateFrameTreeNodeId() {
  // A prerendered FrameTree is not "inner to" or "nested inside" another
  // FrameTree; it exists in parallel to the primary FrameTree of the current
  // WebContents. Therefore, it must not attempt to access the primary
  // FrameTree in the sense of an "outer delegate" relationship, so we return
  // the invalid ID here.
  return FrameTreeNodeId();
}

RenderFrameHostImpl*
PrerenderHost::PrerenderFrameTreeDelegate::GetProspectiveOuterDocument() {
  // A prerendered FrameTree never has an outer document.
  return nullptr;
}

void PrerenderHost::PrerenderFrameTreeDelegate::SetFocusedFrame(
    FrameTreeNode* node,
    SiteInstanceGroup* source) {
  // `node` can only become focused when `node`'s current RenderFrameHost is
  // active.
  NOTREACHED();
}

FrameTree*
PrerenderHost::PrerenderFrameTreeDelegate::GetOwnedPictureInPictureFrameTree() {
  return nullptr;
}

FrameTree* PrerenderHost::PrerenderFrameTreeDelegate::
    GetPictureInPictureOpenerFrameTree() {
  return nullptr;
}

bool PrerenderHost::PrerenderFrameTreeDelegate::
    OnRenderFrameProxyVisibilityChanged(
        RenderFrameProxyHost* render_frame_proxy_host,
        blink::mojom::FrameVisibility visibility) {
  return false;
}

void PrerenderHost::PrerenderFrameTreeDelegate::
    ActivateAndShowRepostFormWarningDialog() {
  // Not supported, cancel pending reload.
  frame_tree_->controller().CancelPendingReload();
}

bool PrerenderHost::PrerenderFrameTreeDelegate::ShouldPreserveAbortedURLs() {
  return false;
}

PrerenderHost::LoadingOutcome
PrerenderHost::PrerenderFrameTreeDelegate::WaitForLoadStopForTesting() {
  LoadingOutcome status = LoadingOutcome::kLoadingCompleted;

  if (!frame_tree_->IsLoadingIncludingInnerFrameTrees() &&
      prerender_host_->GetInitialNavigationId().has_value()) {
    return status;
  }

  base::RunLoop loop;
  on_wait_loading_finished_ = base::BindOnce(
      [](base::OnceClosure on_close, LoadingOutcome* result,
         LoadingOutcome status) {
        *result = status;
        std::move(on_close).Run();
      },
      loop.QuitClosure(), &status);
  loop.Run();
  // Reset callback to null in case if loop is quit by timeout.
  //
  // This `if` body causes SEGV for `kPrerenderingCancelled` case because the
  // callback is called in dtor and `this` is already destructed here.
  //
  // TODO(crbug.com/372691377): Split setup and wait parts and make the wait
  // part `static`.
  if (status != PrerenderHost::LoadingOutcome::kPrerenderingCancelled) {
    on_wait_loading_finished_.Reset();
  }
  return status;
}

PrerenderHost::PrerenderFrameTreeDelegate::~PrerenderFrameTreeDelegate() {
  if (frame_tree_) {
    frame_tree_->Shutdown();
  }
  // If we are still waiting on test loop, we can assume the page loading step
  // has been cancelled and the PrerenderHost is being discarded without
  // completing loading the page.
  if (on_wait_loading_finished_) {
    std::move(on_wait_loading_finished_)
        .Run(PrerenderHost::LoadingOutcome::kPrerenderingCancelled);
  }
}

// static
PrerenderHost* PrerenderHost::GetFromFrameTreeNodeIfPrerendering(
    FrameTreeNode& frame_tree_node) {
  if (!frame_tree_node.frame_tree().is_prerendering()) {
    return nullptr;
  }
  return &GetFromFrameTreeNode(frame_tree_node);
}

// static
PrerenderHost& PrerenderHost::GetFromFrameTreeNode(
    FrameTreeNode& frame_tree_node) {
  return GetFromFrameTree(&frame_tree_node.frame_tree());
}

// static
PrerenderHost& PrerenderHost::GetFromFrameTree(FrameTree* frame_tree) {
  CHECK(frame_tree);
  CHECK(frame_tree->is_prerendering());
  return *(static_cast<PrerenderHost::PrerenderFrameTreeDelegate*>(
               frame_tree->delegate())
               ->prerender_host_);
}

// static
bool PrerenderHost::AreHttpRequestHeadersCompatible(
    const std::string& potential_activation_headers_str,
#if BUILDFLAG(IS_ANDROID)
    const net::HttpRequestHeaders& potential_activation_additional_headers,
#endif  // BUILDFLAG(IS_ANDROID)
    const std::string& prerender_headers_str,
    PreloadingTriggerType trigger_type,
    const std::string& histogram_suffix,
    bool allow_x_header_mismatch,
    PrerenderCancellationReason& reason) {
  net::HttpRequestHeaders prerender_headers;
  prerender_headers.AddHeadersFromString(prerender_headers_str);

  net::HttpRequestHeaders potential_activation_headers;
  potential_activation_headers.AddHeadersFromString(
      potential_activation_headers_str);
#if BUILDFLAG(IS_ANDROID)
  potential_activation_headers.MergeFrom(
      potential_activation_additional_headers);

#endif  // BUILDFLAG(IS_ANDROID)

  // `prerender_headers` contains the "Purpose: prefetch" and "Sec-Purpose:
  // prefetch;prerender" to notify servers of prerender requests, while
  // `potential_activation_headers` doesn't contain it. Remove "Purpose" and
  // "Sec-Purpose" matching from consideration so that activation works with the
  // header.
  prerender_headers.RemoveHeader(blink::kPurposeHeaderName);
  potential_activation_headers.RemoveHeader(blink::kPurposeHeaderName);
  prerender_headers.RemoveHeader(blink::kSecPurposeHeaderName);
  potential_activation_headers.RemoveHeader(blink::kSecPurposeHeaderName);
  // Ditto for "Sec-Speculation-Tags".
  prerender_headers.RemoveHeader(blink::kSecSpeculationTagsHeaderName);
  CHECK(!potential_activation_headers.HasHeader(
      blink::kSecSpeculationTagsHeaderName));

  prerender_headers.RemoveHeader("RTT");
  potential_activation_headers.RemoveHeader("RTT");
  prerender_headers.RemoveHeader("Downlink");
  potential_activation_headers.RemoveHeader("Downlink");

  // TODO(crbug.com/40244149): Instead of handling headers added by
  // embedders specifically, prerender should expose an interface to embedders
  // to set url parameters.
#if BUILDFLAG(IS_ANDROID)
  // Used by Android devices only.
  if (trigger_type == PreloadingTriggerType::kEmbedder) {
    prerender_headers.RemoveHeader("X-Geo");
    potential_activation_headers.RemoveHeader("X-Geo");
  }
#endif  // BUILDFLAG(IS_ANDROID)

  // Remove the viewport headers as the viewport size of the initiator page can
  // be changed during prerendering. See also https://crbug.com/1401244.
  prerender_headers.RemoveHeader("viewport-width");
  potential_activation_headers.RemoveHeader("viewport-width");
  prerender_headers.RemoveHeader("sec-ch-viewport-width");
  potential_activation_headers.RemoveHeader("sec-ch-viewport-width");
  // Don't need to handle "viewport-height" as it is not defined in the specs.
  prerender_headers.RemoveHeader("sec-ch-viewport-height");
  potential_activation_headers.RemoveHeader("sec-ch-viewport-height");

  // Allow mismatches on `X-` headers. Currently this is allowed only on the
  // WebView.
  // TODO(crbug.com/40244149): Expand this to other platforms and non-x-headers.
  if (allow_x_header_mismatch) {
    std::set<std::string> headers_to_be_removed;
    for (net::HttpRequestHeaders::Iterator it(prerender_headers);
         it.GetNext();) {
      if (it.name().starts_with("X-") || it.name().starts_with("x-")) {
        headers_to_be_removed.insert(it.name());
      }
    }
    for (net::HttpRequestHeaders::Iterator it(potential_activation_headers);
         it.GetNext();) {
      if (it.name().starts_with("X-") || it.name().starts_with("x-")) {
        headers_to_be_removed.insert(it.name());
      }
    }
    for (const std::string& name : headers_to_be_removed) {
      prerender_headers.RemoveHeader(name);
      potential_activation_headers.RemoveHeader(name);
    }
  }

  return PrerenderHost::IsActivationHeaderMatch(potential_activation_headers,
                                                prerender_headers, reason);
}

// static
void PrerenderHost::SetHostCreationCallbackForTesting(
    base::OnceCallback<void(FrameTreeNodeId host_id)> callback) {
  GetHostCreationCallback() = std::move(callback);
}

PrerenderHost::PrerenderHost(
    std::unique_ptr<PrerenderHost> reuse_host,
    const PrerenderAttributes& attributes,
    WebContentsImpl& web_contents,
    base::WeakPtr<PreloadingAttempt> attempt,
    std::unique_ptr<DevToolsPrerenderAttempt> devtools_attempt)
    : attributes_(attributes),
      prerender_host_id_(NextPrerenderHostId()),
      metric_suffix_(
          GeneratePrerenderHistogramSuffix(trigger_type(),
                                           embedder_histogram_suffix())),
      attempt_(std::move(attempt)),
      devtools_attempt_(std::move(devtools_attempt)),
      web_contents_(web_contents),
      host_reused_(reuse_host) {
#if BUILDFLAG(IS_ANDROID)
  if (trigger_type() == PreloadingTriggerType::kSpeculationRule) {
    base::trace_event::EmitNamedTrigger("sp-prerender-start");
  }
#endif  // BUILDFLAG(IS_ANDROID)

  CheckPrerenderAttributes(attributes_);
  SetTriggeringOutcome(PreloadingTriggeringOutcome::kTriggeredButPending);

  if (reuse_host) {
    reuse_host->RecordFailedFinalStatusImpl(PrerenderCancellationReason(
        PrerenderFinalStatus::kPrerenderHostReused));
    if (reuse_host->frame_tree_delegate_->on_wait_loading_finished_) {
      std::move(reuse_host->frame_tree_delegate_->on_wait_loading_finished_)
          .Run(PrerenderHost::LoadingOutcome::kPrerenderingCancelled);
    }
    frame_tree_delegate_ = std::move(reuse_host->frame_tree_delegate_);
    // Reset the NavigationRequest if there is an on-going one in the frame tree
    // since the navigation is no longer needed. If there is no on-going
    // NavigationRequest, the function call will be no-op.
    GetFrameTree()->root()->ResetNavigationRequest(
        NavigationDiscardReason::kExplicitCancellation);
    frame_tree_delegate_->prerender_host_ = *this;
  } else {
    frame_tree_delegate_ = std::make_unique<PrerenderFrameTreeDelegate>(
        web_contents.GetBrowserContext(), web_contents, *this);
    scoped_refptr<SiteInstanceImpl> site_instance =
        SiteInstanceImpl::Create(web_contents.GetBrowserContext());
    GetFrameTree()->Init(site_instance.get(),
                         /*renderer_initiated_creation=*/false,
                         /*main_frame_name=*/"", /*opener_for_origin=*/nullptr,
                         /*frame_policy=*/blink::FramePolicy(),
                         base::UnguessableToken::Create());

    // Use the same SessionStorageNamespace as the primary page for the
    // prerendering page.
    GetFrameTree()->controller().SetSessionStorageNamespace(
        site_instance->GetStoragePartitionConfig(),
        web_contents_->GetPrimaryFrameTree()
            .controller()
            .GetSessionStorageNamespace(
                site_instance->GetStoragePartitionConfig()));

    // TODO(crbug.com/40177940): This should be moved to FrameTree::Init
    web_contents_->NotifySwappedFromRenderManager(
        /*old_frame=*/nullptr,
        GetFrameTree()->root()->render_manager()->current_frame_host());
  }

  frame_tree_node_id_ = GetFrameTree()->root()->frame_tree_node_id();

  if (GetHostCreationCallback()) {
    CHECK_IS_TEST();
    std::move(GetHostCreationCallback()).Run(frame_tree_node_id_);
  }
}

// static
bool PrerenderHost::IsActivationHeaderMatch(
    const net::HttpRequestHeaders& potential_activation_headers,
    const net::HttpRequestHeaders& prerender_headers,
    PrerenderCancellationReason& reason) {
  // Normalize the headers.
  using HeaderPair = net::HttpRequestHeaders::HeaderKeyValuePair;
  auto cmp = [](const HeaderPair& a, const HeaderPair& b) {
    return a.key < b.key;
  };
  auto lower_case = [](HeaderPair& x) { x.key = base::ToLowerASCII(x.key); };
  auto same_predicate = [](const HeaderPair& a, const HeaderPair& b) {
    return a.key == b.key && base::EqualsCaseInsensitiveASCII(a.value, b.value);
  };

  std::vector<HeaderPair> potential_header_list(
      potential_activation_headers.GetHeaderVector());
  std::vector<HeaderPair> prerender_header_list(
      prerender_headers.GetHeaderVector());
  std::for_each(potential_header_list.begin(), potential_header_list.end(),
                lower_case);
  std::for_each(prerender_header_list.begin(), prerender_header_list.end(),
                lower_case);
  std::sort(potential_header_list.begin(), potential_header_list.end(), cmp);
  std::sort(prerender_header_list.begin(), prerender_header_list.end(), cmp);

  std::unique_ptr<std::vector<PrerenderMismatchedHeaders>> mismatched_headers =
      std::make_unique<std::vector<PrerenderMismatchedHeaders>>();

  auto prerender_header_list_it = prerender_header_list.begin();
  auto potential_header_list_it = potential_header_list.begin();

  while (prerender_header_list_it != prerender_header_list.end() &&
         potential_header_list_it != potential_header_list.end()) {
    if (same_predicate(*prerender_header_list_it, *potential_header_list_it)) {
      prerender_header_list_it++;
      potential_header_list_it++;
    } else if (prerender_header_list_it->key == potential_header_list_it->key) {
      mismatched_headers->emplace_back(prerender_header_list_it->key,
                                       prerender_header_list_it->value,
                                       potential_header_list_it->value);
      prerender_header_list_it++;
      potential_header_list_it++;
    } else if (prerender_header_list_it->key < potential_header_list_it->key) {
      mismatched_headers->emplace_back(prerender_header_list_it->key,
                                       prerender_header_list_it->value,
                                       std::nullopt);
      prerender_header_list_it++;
    } else {
      mismatched_headers->emplace_back(potential_header_list_it->key,
                                       std::nullopt,
                                       potential_header_list_it->value);
      potential_header_list_it++;
    }
  }

  while (prerender_header_list_it != prerender_header_list.end()) {
    mismatched_headers->emplace_back(prerender_header_list_it->key,
                                     prerender_header_list_it->value,
                                     std::nullopt);
    prerender_header_list_it++;
  }

  while (potential_header_list_it != potential_header_list.end()) {
    mismatched_headers->emplace_back(potential_header_list_it->key,
                                     std::nullopt,
                                     potential_header_list_it->value);
    potential_header_list_it++;
  }
  if (mismatched_headers->empty()) {
    return true;
  }
  reason.SetPrerenderMismatchedHeaders(std::move(mismatched_headers));
  return false;
}

PrerenderHost::~PrerenderHost() {
  if (!final_status_.has_value()) {
    RecordFailedFinalStatusImpl(
        PrerenderCancellationReason(PrerenderFinalStatus::kDestroyed));
  }
  for (auto& observer : observers_) {
    observer.OnHostDestroyed(final_status_.value());
  }
}

// TODO(crbug.com/40150744): Inspect diffs from the current
// no-state-prefetch implementation. See PrerenderContents::StartPrerendering()
// for example.
bool PrerenderHost::StartPrerendering() {
  TRACE_EVENT0("navigation", "PrerenderHost::StartPrerendering");

  // Since prerender started we mark it as eligible and set it to running.
  SetTriggeringOutcome(PreloadingTriggeringOutcome::kRunning);

  // Start prerendering navigation.
  NavigationController::LoadURLParams load_url_params(
      attributes_.prerendering_url);
  load_url_params.initiator_origin = attributes_.initiator_origin;
  load_url_params.initiator_process_id = attributes_.initiator_process_id;
  load_url_params.initiator_frame_token = attributes_.initiator_frame_token;
#if BUILDFLAG(IS_ANDROID)
  if (!attributes_.additional_headers.IsEmpty()) {
    load_url_params.extra_headers =
        SerializeHttpRequestHeaders(attributes_.additional_headers);
  }
#endif  // BUILDFLAG(IS_ANDROID)
  load_url_params.is_renderer_initiated = !attributes_.IsBrowserInitiated();
  load_url_params.transition_type =
      ui::PageTransitionFromInt(attributes_.transition_type);

  // Just use the referrer from attributes, as NoStatePrefetch does.
  load_url_params.referrer = attributes_.referrer;

  load_url_params.override_user_agent =
      web_contents_->GetDelegate()->ShouldOverrideUserAgentForPrerender2(
          attributes_.prerendering_url);

  // TODO(https://crbug.com/1406149, https://crbug.com/1378921): Set
  // `override_user_agent` for Android. This field is determined on the Java
  // side based on the URL and we should mimic Java code and set it to the
  // correct value. After fixing this, we can remove the check for UA headers
  // upon activation.

  // TODO(crbug.com/40150744): Set up other fields of `load_url_params`
  // as well, and add tests for them.
  base::WeakPtr<NavigationHandle> created_navigation_handle =
      GetNavigationController().LoadURLWithParams(load_url_params);

  if (!created_navigation_handle) {
    return false;
  }

  if (attributes_.prerender_navigation_handle_callback) {
    attributes_.prerender_navigation_handle_callback.Run(
        *created_navigation_handle);
  }

  // Even when LoadURLWithParams() returns a valid navigation handle, navigation
  // can fail during navigation start, for example, due to prerendering a
  // non-supported URL scheme that is filtered out in
  // PrerenderNavigationThrottle.
  if (final_status_.has_value()) {
    return false;
  }

  NavigationRequest* navigation_request =
      NavigationRequest::From(created_navigation_handle.get());

  // In usual code path, `initial_navigation_id_` should be set by
  // PrerenderNavigationThrottle during `LoadURLWithParams` above.
  if (initial_navigation_id_.has_value()) {
    CHECK_EQ(*initial_navigation_id_,
             created_navigation_handle->GetNavigationId());
    CHECK(begin_params_);
    CHECK(common_params_);
  } else if (navigation_request->state() ==
             NavigationRequest::WAITING_FOR_RENDERER_RESPONSE) {
    // If a same-site prerender host is reused, the BeforeUnload handler maybe
    // called and thus to cause the NavigationRequest::BeginNavigation to be
    // delayed. The NavigationRequest state will be
    // NavigationRequest::WAITING_FOR_RENDERER_RESPONSE in this case. This is
    // not an error so we will wait for the SetInitialNavigation to be called
    // afterwards.
    CHECK(!begin_params_);
    CHECK(!common_params_);
  } else {
    // Prerender navigation failed before reaching the throttle for some reason.
    // For example, `ContentBrowserClient::ShouldOverrideUrlLoading()` may block
    // navigation.
    return false;
  }

  CHECK_GE(navigation_request->state(),
           NavigationRequest::WAITING_FOR_RENDERER_RESPONSE);
  return true;
}

void PrerenderHost::DidStartNavigation(NavigationHandle* navigation_handle) {
  auto* navigation_request = NavigationRequest::From(navigation_handle);
  CHECK(navigation_request->IsInPrerenderedMainFrame());

  // Do nothing for the initial navigation.
  if (IsInitialNavigation(*navigation_request)) {
    return;
  }

  // Reset `is_ready_for_activation_` since it can be set to true more than once
  // and CHECK will fail when the main frame navigation happens in a
  // prerendered page and PrerenderHost::DidFinishNavigation is called multiple
  // times.
  is_ready_for_activation_ = false;
}

void PrerenderHost::ReadyToCommitNavigation(
    NavigationHandle* navigation_handle) {
  CHECK(navigation_handle);
  // For the initial navigation, set No-Vary-Search if there is a
  // No-Vary-Search header.
  auto* navigation_request = NavigationRequest::From(navigation_handle);
  CHECK(navigation_request->IsInPrerenderedMainFrame());
  // Prerender frame tree node is alive, see:
  // `PrerenderHostRegistry::ReadyToCommitNavigation`.
  CHECK(GetFrameTree());
  CHECK_EQ(GetFrameTree(),
           &navigation_request->frame_tree_node()->frame_tree());

  if (!IsInitialNavigation(*navigation_request)) {
    return;
  }

  if (navigation_request->response() &&
      navigation_request->response()->parsed_headers &&
      navigation_request->response()
          ->parsed_headers->no_vary_search_with_parse_error) {
    MaybeSetNoVarySearch(
        *navigation_request->response()
             ->parsed_headers->no_vary_search_with_parse_error);
  } else {
    CHECK(!no_vary_search_.has_value());
    CHECK(!no_vary_search_parse_error_.has_value());
  }

  // ReadyToCommitNavigation is called when the headers are received.
  were_headers_received_ = true;
  for (auto& observer : observers_) {
    observer.OnHeadersReceived(*navigation_handle);
  }
}

void PrerenderHost::DidFinishNavigation(NavigationHandle* navigation_handle) {
  auto* navigation_request = NavigationRequest::From(navigation_handle);

  // Observe navigation only in the prerendering frame tree.
  CHECK_EQ(&(navigation_request->frame_tree_node()->frame_tree()),
           GetFrameTree());
  CHECK(navigation_request->GetPrerenderHostId());

  // TODO(crbug.com/434826191): Remove after fully migrating to PrerenderHostId.
  // The if clause is added for filtering the DidCommitNavigation
  // callback called after reusing a PrerenderHost. Currently the
  // PrerenderHostRegistry finds the PrerenderHost by the FrameTreeNodeId, this
  // will cause the DidFinishNavigation callback of the previous PrerenderHost
  // to be sent to the new PrerenderHost.
  if (prerender_host_id_ != navigation_request->GetPrerenderHostId()) {
    return;
  }

  if (PreloadServingMetrics::IsEnabled()) {
    // If `DidFinishNavigation()` is called multiple times, ignore
    // `PreloadServingMetrics` of that navigation and keep the first one.
    if (!prerender_initial_preload_serving_metrics_) {
      // Take `PreloadServingMetrics` of prerender initial navigation.
      auto& initial_preload_serving_metrics_holder =
          *PreloadServingMetricsHolder::GetOrCreateForNavigationHandle(
              *navigation_handle);
      prerender_initial_preload_serving_metrics_ =
          initial_preload_serving_metrics_holder.Take();
    }
  }

  const bool is_prerender_main_frame =
      navigation_request->GetFrameTreeNodeId() == frame_tree_node_id_;

  // Cancel prerendering on navigation request failure.
  //
  // Check net::Error here rather than PrerenderNavigationThrottle as CSP
  // blocking occurs before NavigationThrottles so cannot be observed in
  // NavigationThrottle::WillFailRequest().
  net::Error net_error = navigation_request->GetNetErrorCode();

  std::optional<PrerenderFinalStatus> status;
  if (net_error == net::Error::ERR_BLOCKED_BY_CSP) {
    status = PrerenderFinalStatus::kNavigationRequestBlockedByCsp;
  } else if (net_error == net::Error::ERR_BLOCKED_BY_CLIENT) {
    status = PrerenderFinalStatus::kBlockedByClient;
  } else if (is_prerender_main_frame && net_error != net::Error::OK) {
    status = PrerenderFinalStatus::kNavigationRequestNetworkError;
  } else if (is_prerender_main_frame && !navigation_request->HasCommitted()) {
    status = PrerenderFinalStatus::kNavigationNotCommitted;
  }
  if (status.has_value()) {
    Cancel(*status);
    return;
  }

  // The prerendered contents are considered ready for activation when the
  // main frame navigation reaches DidFinishNavigation and the prerender host
  // has not been canceled yet.
  if (is_prerender_main_frame && !final_status_) {
    CHECK(!is_ready_for_activation_);
    is_ready_for_activation_ = true;

    // Prerender is ready to activate. Set the status to kReady.
    SetTriggeringOutcome(PreloadingTriggeringOutcome::kReady);
  }
}

std::unique_ptr<StoredPage> PrerenderHost::Activate(
    NavigationRequest& navigation_request) {
  TRACE_EVENT1("navigation", "PrerenderHost::Activate", "navigation_request",
               &navigation_request);

  CHECK(is_ready_for_activation_);
  is_ready_for_activation_ = false;

  FrameTree& target_frame_tree = web_contents_->GetPrimaryFrameTree();

  // There should be no ongoing main-frame navigation during activation.
  // TODO(crbug.com/40174232): Make sure sub-frame navigations are
  // fine.
  CHECK(!GetFrameTree()->root()->HasNavigation());

  // Before the root's current_frame_host is cleared, collect the subframes of
  // `frame_tree_` whose FrameTree will need to be updated.
  FrameTree::NodeRange node_range = GetFrameTree()->Nodes();
  std::vector<FrameTreeNode*> subframe_nodes(std::next(node_range.begin()),
                                             node_range.end());

  // Before the root's current_frame_host is cleared, collect the replication
  // state so that it can be used for post-activation validation.
  blink::mojom::FrameReplicationState prior_replication_state =
      GetFrameTree()->root()->current_replication_state();

  // Update FrameReplicationState::has_received_user_gesture_before_nav of the
  // prerendered page.
  //
  // On regular navigation, it is updated via a renderer => browser IPC
  // (RenderFrameHostImpl::HadStickyUserActivationBeforeNavigationChanged),
  // which is sent from blink::DocumentLoader::CommitNavigation. However,
  // this doesn't happen on prerender page activation, so the value is not
  // correctly updated without this treatment.
  //
  // The updated value will be sent to the renderer on
  // blink::mojom::Page::ActivatePrerenderedPage.
  prior_replication_state.has_received_user_gesture_before_nav =
      navigation_request.frame_tree_node()
          ->has_received_user_gesture_before_nav();

  // frame_tree_->root(). Do not add any code between here and
  // frame_tree_.reset() that calls into observer functions to minimize the
  // duration of current_frame_host being null.
  std::unique_ptr<StoredPage> page =
      GetFrameTree()->root()->render_manager()->TakePrerenderedPage();

  NavigationEntryRestoreContextImpl context;
  std::unique_ptr<NavigationEntryImpl> nav_entry =
      GetNavigationController()
          .GetEntryWithUniqueID(page->render_frame_host()->nav_entry_id())
          ->CloneWithoutSharing(&context);

  navigation_request.SetPrerenderActivationNavigationState(
      std::move(nav_entry), prior_replication_state);

  CHECK_EQ(&target_frame_tree,
           &navigation_request.frame_tree_node()->frame_tree());

  // We support activating the prerendered page only to the topmost
  // RenderFrameHost.
  CHECK(!page->render_frame_host()->GetParentOrOuterDocumentOrEmbedder());

  page->render_frame_host()->SetFrameTreeNode(*(target_frame_tree.root()));
  page->render_frame_host()->SetRenderFrameHostOwner(target_frame_tree.root());

  // Copy frame name into the replication state of the primary main frame to
  // ensure that the replication state of the primary main frame after
  // activation matches the replication state stored in the renderer.
  // TODO(crbug.com/40192974): Copying frame name here is suboptimal
  // and ideally we'd do this at the same time when transferring the proxies
  // from the StoredPage into RenderFrameHostManager. However, this is a
  // temporary solution until we move this into BrowsingContextState,
  // along with RenderFrameProxyHost.
  page->render_frame_host()->frame_tree_node()->set_frame_name_for_activation(
      prior_replication_state.unique_name, prior_replication_state.name);
  for (auto& it : page->proxy_hosts()) {
    it.second->set_frame_tree_node(*(target_frame_tree.root()));
  }

  // Iterate over the root RenderFrameHost's subframes and update the
  // associated frame tree. Note that subframe proxies don't need their
  // FrameTrees independently updated, since their FrameTreeNodes don't
  // change, and FrameTree references in those FrameTreeNodes will be updated
  // through RenderFrameHosts.
  //
  // TODO(crbug.com/40177949): Need to investigate if and how
  // pending delete RenderFrameHost objects should be handled if prerendering
  // runs all of the unload handlers; they are not currently handled here.
  // This is because pending delete RenderFrameHosts can still receive and
  // process some messages while the RenderFrameHost FrameTree and
  // FrameTreeNode are stale.
  for (FrameTreeNode* subframe_node : subframe_nodes) {
    subframe_node->SetFrameTree(target_frame_tree);
  }

  frame_tree_delegate_.reset();

  page->render_frame_host()->ForEachRenderFrameHostImplIncludingSpeculative(
      [this](RenderFrameHostImpl* rfh) {
        // The visibility state of the prerendering page has not been
        // updated by
        // WebContentsImpl::UpdateVisibilityAndNotifyPageAndView(). So
        // updates the visibility state using the PageVisibilityState of
        // `web_contents`.
        rfh->render_view_host()->SetFrameTreeVisibility(
            web_contents_->GetPageVisibilityState());
      });

  for (auto& observer : observers_) {
    observer.OnActivated();
  }

  // The activated page is on the primary tree now. It can propagate the client
  // hints to the global settings.
  BrowserContext* browser_context =
      target_frame_tree.controller().GetBrowserContext();
  ClientHintsControllerDelegate* client_hints_delegate =
      browser_context->GetClientHintsControllerDelegate();
  if (client_hints_delegate) {
    for (auto& [origin, client_hint] : client_hints_type_) {
      PersistAcceptCH(origin, *(target_frame_tree.root()),
                      client_hints_delegate, client_hint);
    }
  }

  // Associate `PreloadServingMetrics` of prerender initial navigation to ones
  // of activation.
  if (PreloadServingMetrics::IsEnabled()) {
    auto& activation_preload_serving_metrics_holder =
        *PreloadServingMetricsHolder::GetOrCreateForNavigationHandle(
            navigation_request);
    activation_preload_serving_metrics_holder
        .SetPrerenderInitialPreloadServingMetrics(
            std::move(prerender_initial_preload_serving_metrics_));
  }

  RecordActivation(navigation_request);

  // Prerender is activated. Set the status to kSuccess.
  SetTriggeringOutcome(PreloadingTriggeringOutcome::kSuccess);
  devtools_instrumentation::DidActivatePrerender(
      navigation_request, initiator_devtools_navigation_token());
  return page;
}

// Ensure that the frame policies are compatible between primary main frame and
// prerendering main frame:
// a) primary main frame's pending_frame_policy would normally apply to the new
// document during its creation. However, for prerendering we can't apply it as
// the document is already created.
// b) prerender main frame's pending_frame_policy can't be transferred to the
// primary main frame, we should not activate if it's non-zero.
// c) Existing  document can't change the frame_policy it is affected by, so we
// can't transfer RenderFrameHosts between FrameTreeNodes with different frame
// policies.
//
// Usually frame policy for the main frame is empty as in the most common case a
// parent document sets a policy on the child iframe.
bool PrerenderHost::IsFramePolicyCompatibleWithPrimaryFrameTree() {
  FrameTreeNode* prerender_root_ftn = GetFrameTree()->root();
  FrameTreeNode* primary_root_ftn = web_contents_->GetPrimaryFrameTree().root();

  // Ensure that the pending frame policy is not set on the main frames, as it
  // is usually set on frames by their parent frames.
  if (prerender_root_ftn->pending_frame_policy() != blink::FramePolicy()) {
    return false;
  }

  if (primary_root_ftn->pending_frame_policy() != blink::FramePolicy()) {
    return false;
  }

  if (prerender_root_ftn->current_replication_state().frame_policy !=
      primary_root_ftn->current_replication_state().frame_policy) {
    return false;
  }

  return true;
}

bool PrerenderHost::AreInitialPrerenderNavigationParamsCompatibleWithNavigation(
    NavigationRequest& navigation_request,
    PrerenderCancellationReason& reason) {
  // TODO(crbug.com/40170513): compare the rest of the navigation parameters. We
  // should introduce compile-time parameter checks as well, to ensure how new
  // fields should be compared for compatibility.

  // As the initial prerender navigation is a) limited to HTTP(s) URLs and b)
  // initiated by the PrerenderHost, we do not expect some navigation parameters
  // connected to certain navigation types to be set and the CHECKS below
  // enforce that.
  // The parameters of the potential activation, however, are coming from the
  // renderer and we mostly don't have any guarantees what they are, so we
  // should not CHECK them. Instead, by default we compare them with initial
  // prerender activation parameters and fail to activate when they differ.
  // Note: some of those parameters should be never set (or should be ignored)
  // for main-frame / HTTP(s) navigations, but we still compare them here as a
  // defence-in-depth measure.
  CHECK(navigation_request.IsInPrimaryMainFrame());

  // Check `common_params_` and `begin_params_` here as these can be nullptr
  // if LoadURLWithParams failed without running PrerenderNavigationThrottle.
  if (!common_params_ || !begin_params_) {
    return false;
  }

  // Relaxes checks for initiator, transition type, and headers. This logic is
  // intended to be used for WebView, as WebView is intended to host
  // embedder-trusted contests.
  bool allow_partial_mismatch =
      web_contents_->GetDelegate()->ShouldAllowPartialParamMismatchOfPrerender2(
          navigation_request);
  // Compare BeginNavigationParams.
  ActivationNavigationParamsMatch result =
      AreBeginNavigationParamsCompatibleWithNavigation(
          navigation_request.common_params().url,
          navigation_request.begin_params(), allow_partial_mismatch, reason);
  if (result != ActivationNavigationParamsMatch::kOk) {
    RecordPrerenderActivationNavigationParamsMatch(result,
                                                   GetHistogramSuffix());
    return false;
  }

  // Compare CommonNavigationParams.
  result = AreCommonNavigationParamsCompatibleWithNavigation(
      navigation_request.common_params(), allow_partial_mismatch);
  if (result != ActivationNavigationParamsMatch::kOk) {
    RecordPrerenderActivationNavigationParamsMatch(result,
                                                   GetHistogramSuffix());
    return false;
  }

  RecordPrerenderActivationNavigationParamsMatch(
      ActivationNavigationParamsMatch::kOk, GetHistogramSuffix());
  return true;
}

#if BUILDFLAG(IS_ANDROID)
// The flag below is provided in case the workaround had a bug. Use the flag to
// revert back to the previous behavior.
// TODO(crbug.com/399478939): Remove the workaround and this flag.
BASE_FEATURE(PrerenderActivationMismatchWebViewWorkaround,
             base::FEATURE_ENABLED_BY_DEFAULT);
#endif

PrerenderHost::ActivationNavigationParamsMatch
PrerenderHost::AreBeginNavigationParamsCompatibleWithNavigation(
    const GURL& potential_activation_url,
    const blink::mojom::BeginNavigationParams& potential_activation,
    bool allow_partial_mismatch,
    PrerenderCancellationReason& reason) {
  CHECK(begin_params_);

  // TODO(https://crbug.com/340416082): Check details of security properties,
  // update the check to appropriate form and remove differences among all
  // platforms.
  if (!allow_partial_mismatch && (potential_activation.initiator_frame_token !=
                                  begin_params_->initiator_frame_token)) {
    return ActivationNavigationParamsMatch::kInitiatorFrameToken;
  }

#if BUILDFLAG(IS_ANDROID)
  net::HttpRequestHeaders activation_additional_headers;
  bool workaround_enabled = base::FeatureList::IsEnabled(
      kPrerenderActivationMismatchWebViewWorkaround);
  if (!workaround_enabled || !IsSpeculationRuleType(trigger_type())) {
    activation_additional_headers =
        web_contents_->GetBrowserContext()->GetExtraHeadersForUrl(
            potential_activation_url);
  }
#endif  // BUILDFLAG(IS_ANDROID)
  if (!AreHttpRequestHeadersCompatible(potential_activation.headers,
#if BUILDFLAG(IS_ANDROID)
                                       activation_additional_headers,
#endif  // BUILDFLAG(IS_ANDROID)
                                       begin_params_->headers, trigger_type(),
                                       GetHistogramSuffix(),
                                       allow_partial_mismatch, reason)) {
    return ActivationNavigationParamsMatch::kHttpRequestHeader;
  }

  // Don't activate a prerendered page if the potential activation request
  // requires validation or bypass of the browser cache, as the prerendered page
  // is a kind of caches.
  // TODO(crbug.com/40183588): Instead of checking the load flags on
  // activation, we should cancel prerendering when the prerender initial
  // navigation has the flags.
  int cache_load_flags = net::LOAD_VALIDATE_CACHE | net::LOAD_BYPASS_CACHE |
                         net::LOAD_DISABLE_CACHE;
  if (potential_activation.load_flags & cache_load_flags) {
    return ActivationNavigationParamsMatch::kCacheLoadFlags;
  }
  if (potential_activation.load_flags != begin_params_->load_flags) {
    return ActivationNavigationParamsMatch::kLoadFlags;
  }

  if (potential_activation.skip_service_worker !=
      begin_params_->skip_service_worker) {
    return ActivationNavigationParamsMatch::kSkipServiceWorker;
  }

  if (potential_activation.mixed_content_context_type !=
      begin_params_->mixed_content_context_type) {
    return ActivationNavigationParamsMatch::kMixedContentContextType;
  }

  // Initial prerender navigation cannot be a form submission.
  CHECK(!begin_params_->is_form_submission);
  if (potential_activation.is_form_submission !=
      begin_params_->is_form_submission) {
    return ActivationNavigationParamsMatch::kIsFormSubmission;
  }

  if (potential_activation.searchable_form_url !=
      begin_params_->searchable_form_url) {
    return ActivationNavigationParamsMatch::kSearchableFormUrl;
  }

  if (potential_activation.searchable_form_encoding !=
      begin_params_->searchable_form_encoding) {
    return ActivationNavigationParamsMatch::kSearchableFormEncoding;
  }

  // Trust token params can be set only on subframe navigations, so both values
  // should be null here.
  CHECK(!begin_params_->trust_token_params);
  if (potential_activation.trust_token_params !=
      begin_params_->trust_token_params) {
    return ActivationNavigationParamsMatch::kTrustTokenParams;
  }

  // Don't require equality for request_context_type because link clicks
  // (HYPERLINK) should be allowed for activation, whereas prerender always has
  // type LOCATION.
  CHECK_EQ(begin_params_->request_context_type,
           blink::mojom::RequestContextType::LOCATION);
  switch (potential_activation.request_context_type) {
    case blink::mojom::RequestContextType::HYPERLINK:
    case blink::mojom::RequestContextType::LOCATION:
      break;
    default:
      return ActivationNavigationParamsMatch::kRequestContextType;
  }

  // Since impression should not be set, no need to compare contents.
  CHECK(!begin_params_->impression);
  if (potential_activation.impression.has_value()) {
    return ActivationNavigationParamsMatch::kImpressionHasValue;
  }

  // No need to test for devtools_initiator because this field is used for
  // tracking what triggered a network request, and prerender activation will
  // not use network requests.

  return ActivationNavigationParamsMatch::kOk;
}

PrerenderHost::ActivationNavigationParamsMatch
PrerenderHost::AreCommonNavigationParamsCompatibleWithNavigation(
    const blink::mojom::CommonNavigationParams& potential_activation,
    bool allow_partial_mismatch) {
  // The CommonNavigationParams::url field is expected to match both initial and
  // activation prerender navigations, as the PrerenderHost selection would have
  // already checked for matching values. Adding a CHECK here to be safe.
  CHECK(common_params_);
  if (attributes_.url_match_predicate) {
    // TODO(crbug.com/41494389): Figure out what we need to pass here as a
    // web_url_match result instead of std::nullopt.
    CHECK(attributes_.url_match_predicate.Run(potential_activation.url,
                                              std::nullopt));
  } else if (no_vary_search_.has_value()) {
    CHECK(no_vary_search_->AreEquivalent(potential_activation.url,
                                         common_params_->url));
  } else if (no_vary_search_hint().has_value()) {
    CHECK(no_vary_search_hint()->AreEquivalent(potential_activation.url,
                                               common_params_->url));
  } else {
    CHECK_EQ(potential_activation.url, common_params_->url);
  }

  // TODO(https://crbug.com/340416082): Check details of security properties,
  // update the check to appropriate form and remove differences among all
  // platforms.
  if (!allow_partial_mismatch && (potential_activation.initiator_origin !=
                                  common_params_->initiator_origin)) {
    return ActivationNavigationParamsMatch::kInitiatorOrigin;
  }

  // The transition must match with the exception of the client redirect flag.
  // The renderer may add the client redirect flag when it has enough
  // information to be certain that this navigation would replace the current
  // history entry (e.g., a renderer-initiated navigation to the current URL).
  int32_t potential_activation_transition =
      potential_activation.transition & ~ui::PAGE_TRANSITION_CLIENT_REDIRECT;
  if (!allow_partial_mismatch &&
      (potential_activation_transition != common_params_->transition)) {
    RecordPrerenderActivationTransition(potential_activation_transition,
                                        GetHistogramSuffix());
    return ActivationNavigationParamsMatch::kTransition;
  }

  CHECK_EQ(common_params_->navigation_type,
           blink::mojom::NavigationType::DIFFERENT_DOCUMENT);
  if (potential_activation.navigation_type != common_params_->navigation_type) {
    return ActivationNavigationParamsMatch::kNavigationType;
  }

  // We don't check download_policy as it affects whether the download triggered
  // by the NavigationRequest is allowed to proceed (or logs metrics) and
  // doesn't affect the behaviour of the document created by a non-download
  // navigation after commit (e.g. it doesn't affect future downloads in child
  // frames). PrerenderNavigationThrottle has already ensured that the initial
  // prerendering navigation isn't a download and as prerendering activation
  // won't reach out to the network, it won't turn into a navigation as well.

  CHECK(common_params_->base_url_for_data_url.is_empty());
  if (potential_activation.base_url_for_data_url !=
      common_params_->base_url_for_data_url) {
    return ActivationNavigationParamsMatch::kBaseUrlForDataUrl;
  }

  // The method parameter is compared only by CHECK_EQ because that change is
  // detected earlier by checking the HTTP request headers changes.
  CHECK_EQ(potential_activation.method, common_params_->method);

  // Initial prerender navigation can't be a form submission.
  CHECK(!common_params_->post_data);
  if (potential_activation.post_data != common_params_->post_data) {
    return ActivationNavigationParamsMatch::kPostData;
  }

  // No need to compare source_location, as it's only passed to the DevTools for
  // debugging purposes and does not impact the properties of the document
  // created by this navigation.

  CHECK(!common_params_->started_from_context_menu);
  if (potential_activation.started_from_context_menu !=
      common_params_->started_from_context_menu) {
    return ActivationNavigationParamsMatch::kStartedFromContextMenu;
  }

  // has_user_gesture doesn't affect any of the security properties of the
  // document created by navigation, so equality of the values is not required.
  // TODO(crbug.com/40191309): ensure that the user activation status is
  // propagated to the activated document.

  // text_fragment_token doesn't affect any of the security properties of the
  // document created by navigation, so equality of the values is not required.
  // TODO(crbug.com/40191311): ensure the activated document consumes
  // text_fragment_token and scrolls to the corresponding viewport.

  // No need to compare should_check_main_world_csp, as if the CSP blocks the
  // initial navigation, it cancels prerendering, and we don't reach here for
  // matching. So regardless of the activation's capability to bypass the main
  // world CSP, the prerendered page is eligible for the activation. This also
  // permits content scripts to activate the page.

  if (potential_activation.initiator_origin_trial_features !=
      common_params_->initiator_origin_trial_features) {
    return ActivationNavigationParamsMatch::kInitiatorOriginTrialFeature;
  }

  if (potential_activation.href_translate != common_params_->href_translate) {
    return ActivationNavigationParamsMatch::kHrefTranslate;
  }

  // Initial prerender navigation can't be a history navigation.
  CHECK(!common_params_->is_history_navigation_in_new_child_frame);
  if (potential_activation.is_history_navigation_in_new_child_frame !=
      common_params_->is_history_navigation_in_new_child_frame) {
    return ActivationNavigationParamsMatch::kIsHistoryNavigationInNewChildFrame;
  }

  // We intentionally don't check referrer or referrer->policy. See spec
  // discussion at https://github.com/WICG/nav-speculation/issues/18.

  if (potential_activation.request_destination !=
      common_params_->request_destination) {
    return ActivationNavigationParamsMatch::kRequestDestination;
  }

  return ActivationNavigationParamsMatch::kOk;
}

RenderFrameHostImpl* PrerenderHost::GetPrerenderedMainFrameHost() {
  CHECK(GetFrameTree());
  CHECK(GetFrameTree()->root()->current_frame_host());
  return GetFrameTree()->root()->current_frame_host();
}

FrameTree& PrerenderHost::GetPrerenderFrameTree() {
  CHECK(GetFrameTree());
  return *GetFrameTree();
}

void PrerenderHost::RecordFailedFinalStatus(
    base::PassKey<PrerenderHostRegistry>,
    const PrerenderCancellationReason& reason) {
  RecordFailedFinalStatusImpl(reason);
}

void PrerenderHost::RecordFailedFinalStatusImpl(
    const PrerenderCancellationReason& reason) {
  CHECK(!final_status_);
  CHECK_NE(reason.final_status(), PrerenderFinalStatus::kActivated);
  final_status_ = reason.final_status();
  RecordFailedPrerenderFinalStatus(reason, attributes_);

  // Set failure reason for this PreloadingAttempt specific to the
  // FinalStatus.
  SetFailureReason(reason);

  for (auto& observer : observers_) {
    observer.OnFailed(final_status_.value());
  }
}

void PrerenderHost::RecordActivation(NavigationRequest& navigation_request) {
  CHECK(!final_status_);
  final_status_ = PrerenderFinalStatus::kActivated;

  // TODO(crbug.com/40215894): Replace
  // `navigation_request.GetNextPageUkmSourceId()` with prerendered page's UKM
  // source ID.
  ReportSuccessActivation(attributes_,
                          navigation_request.GetNextPageUkmSourceId());
}

PrerenderHost::LoadingOutcome PrerenderHost::WaitForLoadStopForTesting() {
  return frame_tree_delegate_->WaitForLoadStopForTesting();  // IN-TEST
}

const GURL& PrerenderHost::GetInitialUrl() const {
  return attributes_.prerendering_url;
}

void PrerenderHost::AddObserver(Observer* observer) {
  observers_.AddObserver(observer);
}

void PrerenderHost::RemoveObserver(Observer* observer) {
  observers_.RemoveObserver(observer);
}

std::optional<int64_t> PrerenderHost::GetInitialNavigationId() const {
  return initial_navigation_id_;
}

void PrerenderHost::SetInitialNavigation(NavigationRequest* navigation) {
  CHECK(!initial_navigation_id_.has_value());
  initial_navigation_id_ = navigation->GetNavigationId();
  begin_params_ = navigation->begin_params().Clone();
  common_params_ = navigation->common_params().Clone();

  // The prerendered page should be checked by the main world CSP. See also
  // relevant comments in AreCommonNavigationParamsCompatibleWithNavigation().
  CHECK_EQ(common_params_->should_check_main_world_csp,
           network::mojom::CSPDisposition::CHECK);
}

void PrerenderHost::SetTriggeringOutcome(PreloadingTriggeringOutcome outcome) {
  if (attempt_) {
    attempt_->SetTriggeringOutcome(outcome);
  }

  if (devtools_attempt_) {
    devtools_attempt_->SetTriggeringOutcome(attributes_, outcome);
  }
}

void PrerenderHost::SetFailureReason(
    const PrerenderCancellationReason& reason) {
  switch (reason.final_status()) {
    // When adding a new failure reason, consider whether it should be
    // propagated to `attempt_`. Most values should be propagated, but we
    // explicitly do not propagate failure reasons if:
    // 1. prerender was successfully prepared but then destroyed because it
    //    wasn't needed for a subsequent navigation (kTriggerDestroyed and
    //    kPrerenderHostReused).
    // 2. the prerender was still pending for its initial navigation when it was
    //    activated (kActivatedBeforeStarted).
    case PrerenderFinalStatus::kTriggerDestroyed:
    case PrerenderFinalStatus::kActivatedBeforeStarted:
    case PrerenderFinalStatus::kTabClosedByUserGesture:
    case PrerenderFinalStatus::kTabClosedWithoutUserGesture:
    case PrerenderFinalStatus::kSpeculationRuleRemoved:
    case PrerenderFinalStatus::kOtherPrerenderedPageActivated:
    case PrerenderFinalStatus::kPrerenderHostReused:
      return;
    case PrerenderFinalStatus::kDestroyed:
    case PrerenderFinalStatus::kLowEndDevice:
    case PrerenderFinalStatus::kInvalidSchemeRedirect:
    case PrerenderFinalStatus::kInvalidSchemeNavigation:
    case PrerenderFinalStatus::kNavigationRequestBlockedByCsp:
    case PrerenderFinalStatus::kMojoBinderPolicy:
    case PrerenderFinalStatus::kRendererProcessCrashed:
    case PrerenderFinalStatus::kRendererProcessKilled:
    case PrerenderFinalStatus::kDownload:
    case PrerenderFinalStatus::kNavigationNotCommitted:
    case PrerenderFinalStatus::kNavigationBadHttpStatus:
    case PrerenderFinalStatus::kClientCertRequested:
    case PrerenderFinalStatus::kNavigationRequestNetworkError:
    case PrerenderFinalStatus::kCancelAllHostsForTesting:
    case PrerenderFinalStatus::kDidFailLoad:
    case PrerenderFinalStatus::kStop:
    case PrerenderFinalStatus::kSslCertificateError:
    case PrerenderFinalStatus::kLoginAuthRequested:
    case PrerenderFinalStatus::kUaChangeRequiresReload:
    case PrerenderFinalStatus::kBlockedByClient:
    case PrerenderFinalStatus::kMixedContent:
    case PrerenderFinalStatus::kTriggerBackgrounded:
    case PrerenderFinalStatus::kMemoryLimitExceeded:
    case PrerenderFinalStatus::kDataSaverEnabled:
    case PrerenderFinalStatus::kTriggerUrlHasEffectiveUrl:
    case PrerenderFinalStatus::kInactivePageRestriction:
    case PrerenderFinalStatus::kStartFailed:
    case PrerenderFinalStatus::kTimeoutBackgrounded:
    case PrerenderFinalStatus::kCrossSiteNavigationInInitialNavigation:
    case PrerenderFinalStatus::kCrossSiteRedirectInInitialNavigation:
    case PrerenderFinalStatus::
        kSameSiteCrossOriginRedirectNotOptInInInitialNavigation:
    case PrerenderFinalStatus::
        kSameSiteCrossOriginNavigationNotOptInInInitialNavigation:
    case PrerenderFinalStatus::kActivationNavigationParameterMismatch:
    case PrerenderFinalStatus::kActivatedInBackground:
    case PrerenderFinalStatus::kActivationNavigationDestroyedBeforeSuccess:
    case PrerenderFinalStatus::kPrimaryMainFrameRendererProcessCrashed:
    case PrerenderFinalStatus::kPrimaryMainFrameRendererProcessKilled:
    case PrerenderFinalStatus::kActivationFramePolicyNotCompatible:
    case PrerenderFinalStatus::kPreloadingDisabled:
    case PrerenderFinalStatus::kBatterySaverEnabled:
    case PrerenderFinalStatus::kActivatedDuringMainFrameNavigation:
    case PrerenderFinalStatus::kPreloadingUnsupportedByWebContents:
    case PrerenderFinalStatus::
        kSameSiteCrossOriginNavigationNotOptInInMainFrameNavigation:
    case PrerenderFinalStatus::
        kSameSiteCrossOriginRedirectNotOptInInMainFrameNavigation:
    case PrerenderFinalStatus::kCrossSiteNavigationInMainFrameNavigation:
    case PrerenderFinalStatus::kCrossSiteRedirectInMainFrameNavigation:
    case PrerenderFinalStatus::kMemoryPressureOnTrigger:
    case PrerenderFinalStatus::kMemoryPressureAfterTriggered:
    case PrerenderFinalStatus::kPrerenderingDisabledByDevTools:
    case PrerenderFinalStatus::kActivatedWithAuxiliaryBrowsingContexts:
    case PrerenderFinalStatus::kMaxNumOfRunningImmediatePrerendersExceeded:
    case PrerenderFinalStatus::kMaxNumOfRunningNonImmediatePrerendersExceeded:
    case PrerenderFinalStatus::kMaxNumOfRunningEmbedderPrerendersExceeded:
    case PrerenderFinalStatus::kPrerenderingUrlHasEffectiveUrl:
    case PrerenderFinalStatus::kRedirectedPrerenderingUrlHasEffectiveUrl:
    case PrerenderFinalStatus::kActivationUrlHasEffectiveUrl:
    case PrerenderFinalStatus::kJavaScriptInterfaceAdded:
    case PrerenderFinalStatus::kJavaScriptInterfaceRemoved:
    case PrerenderFinalStatus::kAllPrerenderingCanceled:
    case PrerenderFinalStatus::kWindowClosed:
    case PrerenderFinalStatus::kSlowNetwork:
    case PrerenderFinalStatus::kPrerenderFailedDuringPrefetch:
    case PrerenderFinalStatus::kBrowsingDataRemoved:
      if (attempt_) {
        attempt_->SetFailureReason(
            ToPreloadingFailureReason(reason.final_status()));
        // We reset the attempt to ensure we don't update once we have reported
        // it as failure or accidentally use it for any other prerender attempts
        // as PrerenderHost deletion is async.
        attempt_.reset();
      }

      if (devtools_attempt_) {
        devtools_attempt_->SetFailureReason(attributes_, reason);
        devtools_attempt_.reset();
      }

      return;
    case PrerenderFinalStatus::kActivated:
      // The activation path does not call this method, so it should never reach
      // this case.
      NOTREACHED();
  }
}

std::optional<UrlMatchType> PrerenderHost::IsUrlMatch(const GURL& url) const {
  // Triggers are not allowed to treat a cross-origin url as a matched url. It
  // would cause security risks.
  if (!url::IsSameOriginWith(attributes_.prerendering_url, url)) {
    return std::nullopt;
  }

  std::optional<UrlMatchType> result;

  if (GetInitialUrl() == url) {
    result = UrlMatchType::kExact;
  }

  // Check No-Vary-Search header and try and match.
  if (!result && no_vary_search_.has_value() &&
      no_vary_search_->AreEquivalent(GetInitialUrl(), url)) {
    result = UrlMatchType::kNoVarySearch;
  }

  if (!attributes_.url_match_predicate) {
    return result;
  }

  // Override the result of default url match logic with the result
  // from the custom url matching predicate call.
  if (attributes_.url_match_predicate.Run(url, result)) {
    return UrlMatchType::kURLPredicateMatch;
  }

  return std::nullopt;
}

bool PrerenderHost::IsNoVarySearchHintUrlMatch(const GURL& url) const {
  // Triggers are not allowed to treat a cross-origin url as a matched url. It
  // would cause security risks.
  if (!url::IsSameOriginWith(attributes_.prerendering_url, url)) {
    return false;
  }

  // We don't care about url_match_predicate here because it is applied only
  // if we know for sure url is a match. This is a "potential"
  // match depending on the No-Vary-Search header that will be received.
  if (attributes_.url_match_predicate) {
    return false;
  }
  // The same as above. We also don't care about the exact match.
  if (GetInitialUrl() == url) {
    return false;
  }

  // Let's check if this PrerenderHost would match by
  // No-Vary-Search hint. We need to check if the headers were already received.
  if (!were_headers_received()) {
    if (no_vary_search_hint().has_value() &&
        no_vary_search_hint()->AreEquivalent(GetInitialUrl(), url)) {
      return true;
    }
  }

  return false;
}

bool PrerenderHost::IsUrlSameOrigin(const GURL& url) const {
  return url::IsSameOriginWith(GetInitialUrl(), url);
}

bool PrerenderHost::IsUrlSameSite(const GURL& url) const {
  return prerender_navigation_utils::IsSameSite(
      url, url::Origin::Create(GetInitialUrl()));
}

void PrerenderHost::OnAcceptClientHintChanged(
    const url::Origin& origin,
    const std::vector<network::mojom::WebClientHintsType>& client_hints_type) {
  client_hints_type_[origin] = client_hints_type;
}

void PrerenderHost::GetAllowedClientHintsOnPage(
    const url::Origin& origin,
    blink::EnabledClientHints* client_hints) const {
  if (!client_hints_type_.contains(origin)) {
    return;
  }
  for (const auto& hint : client_hints_type_.at(origin)) {
    client_hints->SetIsEnabled(hint, true);
  }
}

std::string PrerenderHost::GetHistogramSuffix() const {
  return metric_suffix_;
}

void PrerenderHost::Cancel(PrerenderFinalStatus status) {
  TRACE_EVENT("navigation", "PrerenderHost::Cancel", "final_status", status);
  // Already cancelled.
  if (final_status_) {
    return;
  }

  RenderFrameHostImpl* host = PrerenderHost::GetPrerenderedMainFrameHost();
  CHECK(host);
  PrerenderHostRegistry* registry =
      host->delegate()->GetPrerenderHostRegistry();
  CHECK(registry);
  registry->CancelHost(frame_tree_node_id_, status);
}

void PrerenderHost::MaybeSetNoVarySearch(
    network::mojom::NoVarySearchWithParseError&
        no_vary_search_with_parse_error) {
  CHECK(!no_vary_search_);
  CHECK(!no_vary_search_parse_error_);
  if (no_vary_search_with_parse_error.is_parse_error()) {
    no_vary_search_parse_error_ =
        no_vary_search_with_parse_error.get_parse_error();
    return;
  }
  CHECK(no_vary_search_with_parse_error.is_no_vary_search());
  net::HttpNoVarySearchData no_vary_search =
      no_vary_search::ParseHttpNoVarySearchDataFromMojom(
          no_vary_search_with_parse_error.get_no_vary_search());
  if (attempt_) {
    static_cast<PreloadingAttemptImpl*>(attempt_.get())
        ->SetNoVarySearchMatchPredicate(base::BindRepeating(
            [](net::HttpNoVarySearchData no_vary_search, const GURL& a,
               const GURL& b) { return no_vary_search.AreEquivalent(a, b); },
            no_vary_search, GetInitialUrl()));
  }
  no_vary_search_ = std::move(no_vary_search);
}

bool PrerenderHost::IsInitialNavigation(
    const NavigationRequest& navigation_request) const {
  return GetInitialNavigationId() == navigation_request.GetNavigationId();
}

base::TimeDelta PrerenderHost::WaitUntilHeadTimeout() {
  int timeout_in_milliseconds = 0;
  if (IsSpeculationRuleType(attributes_.trigger_type)) {
    CHECK(eagerness().has_value());
    switch (eagerness().value()) {
      // Currently, `kImmediate` and `kEager` behaves the same.
      // TODO(crbug.com/40287486): Separate these behaviors.
      case blink::mojom::SpeculationEagerness::kImmediate:
      case blink::mojom::SpeculationEagerness::kEager:
        timeout_in_milliseconds =
            features::kPrerender2NoVarySearchWaitForHeadersTimeoutEagerPrerender
                .Get();
        break;
      case blink::mojom::SpeculationEagerness::kModerate:
        timeout_in_milliseconds =
            features::
                kPrerender2NoVarySearchWaitForHeadersTimeoutModeratePrerender
                    .Get();
        break;
      case blink::mojom::SpeculationEagerness::kConservative:
        timeout_in_milliseconds =
            features::
                kPrerender2NoVarySearchWaitForHeadersTimeoutConservativePrerender
                    .Get();
        break;
    }
  } else {
    timeout_in_milliseconds =
        features::kPrerender2NoVarySearchWaitForHeadersTimeoutForEmbedders
            .Get();
  }
  return base::Milliseconds(timeout_in_milliseconds);
}

void PrerenderHost::OnWaitingForHeadersStarted(
    NavigationHandle& navigation_handle,
    WaitingForHeadersStartedReason reason) {
  // Prerender frame tree is alive. This check is also done by the caller.
  CHECK(GetFrameTree());
  for (auto& observer : observers_) {
    observer.OnWaitingForHeadersStarted(navigation_handle, reason);
  }
}

void PrerenderHost::OnWaitingForHeadersFinished(
    WaitingForHeadersFinishedReason reason) {
  // Prerender frame tree is alive. This check is also done by the caller.
  CHECK(GetFrameTree());

  base::UmaHistogramEnumeration(
      "Prerender.Experimental.WaitingForHeadersFinishedReason" +
          GetHistogramSuffix(),
      reason);

  for (auto& observer : observers_) {
    observer.OnWaitingForHeadersFinished(reason);
  }
}

bool PrerenderHost::ShouldAbortNavigationBecausePrefetchUnavailable() const {
  CHECK(features::UsePrefetchPrerenderIntegration());

  auto is_prefetch_used =
      [](const std::optional<PrefetchStatus>& prefetch_status) -> bool {
    if (!prefetch_status.has_value()) {
      return false;
    }

    switch (prefetch_status.value()) {
      case PrefetchStatus::kPrefetchResponseUsed:
        return true;
      case PrefetchStatus::kPrefetchNotUsedProbeFailed:
      case PrefetchStatus::kPrefetchNotStarted:
      case PrefetchStatus::kPrefetchIneligibleUserHasCookies:
      case PrefetchStatus::kPrefetchIneligibleUserHasServiceWorker:
      case PrefetchStatus::
          kPrefetchIneligibleUserHasServiceWorkerNoFetchHandler:
      case PrefetchStatus::kPrefetchIneligibleRedirectFromServiceWorker:
      case PrefetchStatus::kPrefetchIneligibleRedirectToServiceWorker:
      case PrefetchStatus::kPrefetchIneligibleSchemeIsNotHttps:
      case PrefetchStatus::kPrefetchIneligibleNonDefaultStoragePartition:
      case PrefetchStatus::kPrefetchNotFinishedInTime:
      case PrefetchStatus::kPrefetchFailedNetError:
      case PrefetchStatus::kPrefetchFailedNon2XX:
      case PrefetchStatus::kPrefetchFailedMIMENotSupported:
      case PrefetchStatus::kPrefetchSuccessful:
      case PrefetchStatus::kPrefetchIneligibleRetryAfter:
      case PrefetchStatus::kPrefetchIneligiblePrefetchProxyNotAvailable:
      case PrefetchStatus::kPrefetchIsPrivacyDecoy:
      case PrefetchStatus::kPrefetchIsStale:
      case PrefetchStatus::kPrefetchNotUsedCookiesChanged:
      case PrefetchStatus::kPrefetchIneligibleHostIsNonUnique:
      case PrefetchStatus::kPrefetchIneligibleDataSaverEnabled:
      case PrefetchStatus::kPrefetchIneligibleExistingProxy:
      case PrefetchStatus::kPrefetchHeldback:
      case PrefetchStatus::kPrefetchFailedInvalidRedirect:
      case PrefetchStatus::kPrefetchFailedIneligibleRedirect:
      case PrefetchStatus::
          kPrefetchIneligibleSameSiteCrossOriginPrefetchRequiredProxy:
      case PrefetchStatus::kPrefetchIneligibleBatterySaverEnabled:
      case PrefetchStatus::kPrefetchIneligiblePreloadingDisabled:
      case PrefetchStatus::kPrefetchEvictedAfterCandidateRemoved:
      case PrefetchStatus::kPrefetchEvictedForNewerPrefetch:
      case PrefetchStatus::kPrefetchEvictedAfterBrowsingDataRemoved:
        return false;
    }
  };
  auto is_ineligibility_admissible =
      [](PreloadingEligibility prefetch_eligibility) -> bool {
    switch (prefetch_eligibility) {
      // Prefetch is not available if SW exists, but prerender is.
      case PreloadingEligibility::kUserHasServiceWorker:
      case PreloadingEligibility::kUserHasServiceWorkerNoFetchHandler:
      case PreloadingEligibility::kRedirectFromServiceWorker:
      case PreloadingEligibility::kRedirectToServiceWorker:
        // Prefetch is not available for HTTP, but prerender is available
        // for HTTPS/HTTP.
      case PreloadingEligibility::kSchemeIsNotHttps:
        return true;
      case PreloadingEligibility::kEligible:
      case PreloadingEligibility::kUnspecified:
      case PreloadingEligibility::kPreloadingDisabled:
      case PreloadingEligibility::kHidden:
      case PreloadingEligibility::kCrossOrigin:
      case PreloadingEligibility::kLowMemory:
      case PreloadingEligibility::kJavascriptDisabled:
      case PreloadingEligibility::kDataSaverEnabled:
      case PreloadingEligibility::kHasEffectiveUrl:
      case PreloadingEligibility::kSingleProcess:
      case PreloadingEligibility::kLinkRelNext:
      case PreloadingEligibility::kThirdPartyCookies:
      case PreloadingEligibility::kPreloadingInvokedWithinTimelimit:
      case PreloadingEligibility::kRendererProcessLimitExceeded:
      case PreloadingEligibility::kBatterySaverEnabled:
      case PreloadingEligibility::kPreloadingUnsupportedByWebContents:
      case PreloadingEligibility::kMemoryPressure:
      case PreloadingEligibility::kPreloadingDisabledByDevTools:
      case PreloadingEligibility::kHttpsOnly:
      case PreloadingEligibility::kHttpOrHttpsOnly:
      case PreloadingEligibility::kSlowNetwork:
      case PreloadingEligibility::kUserHasCookies:
      case PreloadingEligibility::kNonDefaultStoragePartition:
      case PreloadingEligibility::kRetryAfter:
      case PreloadingEligibility::kPrefetchProxyNotAvailable:
      case PreloadingEligibility::kHostIsNonUnique:
      case PreloadingEligibility::kExistingProxy:
      case PreloadingEligibility::kSameSiteCrossOriginPrefetchRequiredProxy:
      case PreloadingEligibility::kPreloadingEligibilityContentEnd:
      case PreloadingEligibility::kPreloadingEligibilityContentStart2:
      case PreloadingEligibility::kPreloadingEligibilityContentEnd2:
        return false;
    }
  };
  // If a prerender navigation reached to `PrefetchURLLoaderInterceptor`, it is
  // blocked by `PrefetchMatchResolver` and prefetch ahead of prerender. So, we
  // should've got prefetch eligibility when it reached to
  // `PrerenderURLLoaderThrottle`. Therefore, if prefetch eligibility is
  // `PreloadingEligibility::kUnspecified`, it implies that the navigation is
  // handled by other `NavigationLoaderInterceptor` earlier than
  // `PrefetchURLLoaderInterceptor`. In this case, the interceptor already
  // decided to serve a resource for the navigation. So, we don't need to abort
  // this prerender.
  //
  // For example, if a service worker is installed to the given URL,
  // `ServiceWorkerMainResourceLoaderInterceptor` intercepts the navigation.
  // `PrefetchService` may or may not report prefetch eligibility at this
  // timing, but eventually reports
  // `PreloadingEligibility::kUserHasServiceWorker`. So, continuing the
  // navigation is reasonable.
  auto nav_is_likely_handled_by_earlier_interceptor =
      [](PreloadingEligibility prefetch_eligibility) -> bool {
    return prefetch_eligibility == PreloadingEligibility::kUnspecified;
  };

  // Use a prefetch (in many cases, aheaf of prerender) if it is about to be
  // used.
  if (is_prefetch_used(attributes_.preload_pipeline_info->prefetch_status())) {
    return false;
  }

  // Fallback to normal navigation if the prefetch was ineligible that is
  // admissible.
  if (is_ineligibility_admissible(
          attributes_.preload_pipeline_info->prefetch_eligibility())) {
    return false;
  }

  // Continue if the navigation is handled by an earlier interceptor.
  if (nav_is_likely_handled_by_earlier_interceptor(
          attributes_.preload_pipeline_info->prefetch_eligibility())) {
    return false;
  }

  // Otherwise, abort this prerender.
  return true;
}

void PrerenderHost::AddAdditionalRequestHeaders(
    net::HttpRequestHeaders& headers,
    FrameTreeNode& navigating_frame_tree_node) {
  // The given FrameTreeNode should be in the same prerendering FrameTree.
  CHECK_EQ(&navigating_frame_tree_node.frame_tree(), &GetPrerenderFrameTree());

  // Add the "Sec-Purpose: prefetch;prerender" header to prerender navigations
  // including subframe navigations. Add "Purpose: prefetch" as well for
  // compatibility concerns (See
  // https://github.com/WICG/nav-speculation/issues/133).
  headers.SetHeader(blink::kSecPurposeHeaderName,
                    blink::kSecPurposePrefetchPrerenderHeaderValue);
  if (!base::FeatureList::IsEnabled(
          blink::features::kRemovePurposeHeaderForPrefetch)) {
    headers.SetHeader(blink::kPurposeHeaderName,
                      blink::kSecPurposePrefetchHeaderValue);
  }

  // Add the "Sec-Speculation-Tags" header to main frame initial prerender
  // navigation.
  // https://wicg.github.io/nav-speculation/prefetch.html#sec-speculation-tags-header
  std::optional<SpeculationRulesTags> tags = attributes_.GetTags();
  if (navigating_frame_tree_node.IsMainFrame() &&
      !GetInitialNavigationId().has_value() && tags.has_value()) {
    headers.SetHeader(blink::kSecSpeculationTagsHeaderName,
                      tags->ConvertStringToHeaderString().value());
  }
}

void PrerenderHost::NotifyReused() {
  for (auto& observer : observers_) {
    observer.OnHostReused();
  }
}

void PrerenderHost::OnWillBeCancelled(
    const PrerenderCancellationReason& reason) {
  if (!PreloadServingMetrics::IsEnabled()) {
    return;
  }

  [&]() {
    // There are two cases:
    //
    // 1. `DidFinishNavigation()` is already called and then prerender is
    //    cancelled.
    // 2. Cancelled before `DidFinishNavigation()`. (E.g.
    //    `PrerenderURLLoaderThrottle`.)
    //
    // In the case 1, `prerender_initial_preload_serving_metrics_` is already
    // set. So, nothing to do and return.
    if (prerender_initial_preload_serving_metrics_) {
      return;
    }

    // We believe that `NavigationRequest` exist in this case, but some tests
    // fails If we use `CHECK` for `frame_tree_node` and `navigation_request`.
    // (We don't check which causes the failure.) Give up to record metrics in
    // such case.
    //
    // TODO(crbug.com/360094997): Investigate why and Use `CHECK` instead if
    // possible.
    auto* frame_tree_node =
        FrameTreeNode::GloballyFindByID(frame_tree_node_id_);
    if (!frame_tree_node) {
      return;
    }

    NavigationRequest* navigation_request =
        frame_tree_node->navigation_request();
    if (!navigation_request) {
      // Cancellation can be occur in prerender initial navigation or after
      // `DidFinishNavigation()`. `!navigation_request` implies that the latter
      // case, but it is handled in `DidFinishNavigation()` and already taken
      // the log.
      //
      // TODO(crbug.com/360094997): Ditto. Investigate test failure. Use
      // `DUMP_WILL_BE_NOTREACHED` instead.
      // TODO(crbug.com/360094997): Use `CHECK` instead once we checked the
      // safety by `DUMP_WILL_BE_NOTREACHED`.
      return;
    }

    // Take `PreloadServingMetrics` of prerender initial navigation.
    auto& initial_preload_serving_metrics_holder =
        *PreloadServingMetricsHolder::GetOrCreateForNavigationHandle(
            *navigation_request);
    prerender_initial_preload_serving_metrics_ =
        initial_preload_serving_metrics_holder.Take();
  }();

  if (prerender_initial_preload_serving_metrics_) {
    prerender_initial_preload_serving_metrics_
        ->RecordMetricsForPrerenderInitialNavigationFailed();
  }
}

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

}  // namespace content
