// Copyright 2021 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/public/test/prerender_test_util.h"

#include <tuple>

#include "base/functional/callback_helpers.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "base/test/bind.h"
#include "base/trace_event/typed_macros.h"
#include "base/types/cxx23_to_underlying.h"
#include "content/browser/preloading/prerender/prerender_features.h"
#include "content/browser/preloading/prerender/prerender_final_status.h"
#include "content/browser/preloading/prerender/prerender_handle_impl.h"
#include "content/browser/preloading/prerender/prerender_host.h"
#include "content/browser/preloading/prerender/prerender_host_registry.h"
#include "content/browser/renderer_host/frame_tree.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/browser_thread.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/common/isolated_world_ids.h"
#include "content/public/test/browser_test_utils.h"
#include "content/public/test/test_navigation_observer.h"
#include "net/test/embedded_test_server/embedded_test_server.h"
#include "third_party/blink/public/common/features.h"

namespace content {
namespace test {
namespace {

constexpr char kAddSpeculationRuleScript[] = R"({
    const script = document.createElement('script');
    script.type = 'speculationrules';
    script.text = `{
      "prerender": [{ $1 }]
    }`;
    document.head.appendChild(script);
  })";

constexpr char kAddSpeculationRuleWithRulesetTagScript[] = R"({
    const script = document.createElement('script');
    script.type = 'speculationrules';
    script.text = `{
      "tag": "$1",
      "prerender": [{ $2 }]
    }`;
    document.head.appendChild(script);
  })";

std::string ConvertEagernessToString(
    blink::mojom::SpeculationEagerness eagerness) {
  switch (eagerness) {
    case blink::mojom::SpeculationEagerness::kImmediate:
      return "immediate";
    case blink::mojom::SpeculationEagerness::kEager:
      return "eager";
    case blink::mojom::SpeculationEagerness::kModerate:
      return "moderate";
    case blink::mojom::SpeculationEagerness::kConservative:
      return "conservative";
  }
}

// Builds <script type="speculationrules"> element for prerendering.
std::string BuildScriptElementSpeculationRules(
    const std::vector<GURL>& prerendering_urls,
    std::optional<blink::mojom::SpeculationEagerness> eagerness,
    std::optional<std::string> no_vary_search_hint,
    const std::string& target_hint,
    std::optional<std::string> ruleset_tag) {
  std::stringstream ss;

  // Add source filed.
  ss << R"("source": "list", )";

  // Concatenate the given URLs with a comma separator.
  std::stringstream urls_ss;
  for (size_t i = 0; i < prerendering_urls.size(); i++) {
    // Wrap the url with double quotes.
    urls_ss << base::StringPrintf(R"("%s")",
                                  prerendering_urls[i].spec().c_str());
    if (i + 1 < prerendering_urls.size()) {
      urls_ss << ", ";
    }
  }
  // Add urls fields.
  ss << base::StringPrintf(R"("urls": [ %s ])", urls_ss.str().c_str());

  // Add eagerness field.
  if (eagerness.has_value()) {
    ss << base::StringPrintf(
        R"(, "eagerness": "%s")",
        ConvertEagernessToString(eagerness.value()).c_str());
  }
  if (no_vary_search_hint.has_value()) {
    ss << base::StringPrintf(R"(, "expects_no_vary_search": "%s")",
                             no_vary_search_hint.value().c_str());
  }

  // Add target_hint field.
  if (!target_hint.empty()) {
    ss << base::StringPrintf(R"(, "target_hint": "%s")", target_hint.c_str());
  }

  return ruleset_tag.has_value()
             ? base::ReplaceStringPlaceholders(
                   kAddSpeculationRuleWithRulesetTagScript,
                   {ruleset_tag.value(), ss.str()}, nullptr)
             : base::ReplaceStringPlaceholders(kAddSpeculationRuleScript,
                                               {ss.str()}, nullptr);
}

// TODO(crbug.com/428500219): Move these patterns to preloading_test_util.cc,
// and merge them to BuildScriptElementSpeculationRules.
constexpr char kAddSpeculationRulePrerenderUntilScriptScript[] = R"({
    const script = document.createElement('script');
    script.type = 'speculationrules';
    script.text = `{
      "prerender_until_script": [{
        "source": "list",
        "urls": [$1],
        "eagerness": $2
      }]
    }`;
    document.head.appendChild(script);
  })";

constexpr char kAddSpeculationRulePrefetchScript[] = R"({
    const script = document.createElement('script');
    script.type = 'speculationrules';
    script.text = `{
      "prefetch": [{
        "source": "list",
        "urls": [$1]
      }]
    }`;
    document.head.appendChild(script);
  })";

PrerenderHostRegistry& GetPrerenderHostRegistry(WebContents* web_contents) {
  EXPECT_TRUE(content::BrowserThread::CurrentlyOn(BrowserThread::UI));
  return *static_cast<WebContentsImpl*>(web_contents)
              ->GetPrerenderHostRegistry();
}

PrerenderHost* GetPrerenderHostById(WebContents* web_contents,
                                    FrameTreeNodeId host_id) {
  auto& registry = GetPrerenderHostRegistry(web_contents);
  return registry.FindNonReservedHostById(host_id);
}

PrerenderHost* GetPrerenderHostByUrl(WebContents* web_contents,
                                     const GURL& url) {
  auto& registry = GetPrerenderHostRegistry(web_contents);
  return registry.FindHostByUrlForTesting(url);
}

PrerenderHost::LoadingOutcome WaitForPrerenderLoadingOutcome(
    WebContents& web_contents,
    const GURL& url) {
  TRACE_EVENT("test", "PrerenderTestHelper::WaitForPrerenderLoadingOutcome",
              "web_contents", web_contents, "url", url);
  PrerenderHostRegistry& registry = GetPrerenderHostRegistry(&web_contents);
  PrerenderHost* host = registry.FindHostByUrlForTesting(url);
  // Wait for the host to be created if it hasn't yet.
  if (!host) {
    PrerenderHostRegistryObserver observer(web_contents);
    observer.WaitForTrigger(url);
    host = registry.FindHostByUrlForTesting(url);
    CHECK_NE(host, nullptr);
  }
  return host->WaitForLoadStopForTesting();
}

}  // namespace

class PrerenderHostRegistryObserverImpl
    : public PrerenderHostRegistry::Observer {
 public:
  explicit PrerenderHostRegistryObserverImpl(WebContents& web_contents) {
    observation_.Observe(&GetPrerenderHostRegistry(&web_contents));
  }

  void WaitForTrigger(const GURL& url) {
    ASSERT_FALSE(waiting_.contains(url));
    if (triggered_.contains(url)) {
      return;
    }
    base::RunLoop loop;
    waiting_[url] = loop.QuitClosure();
    loop.Run();
  }

  GURL WaitForNextTrigger() {
    EXPECT_FALSE(waiting_next_);
    GURL triggered_url;
    base::RunLoop loop;
    waiting_next_ =
        base::BindLambdaForTesting([&triggered_url, &loop](const GURL& url) {
          triggered_url = url;
          loop.Quit();
        });
    loop.Run();
    return triggered_url;
  }

  void NotifyOnTrigger(const GURL& url, base::OnceClosure callback) {
    ASSERT_FALSE(waiting_.contains(url));
    if (triggered_.contains(url)) {
      std::move(callback).Run();
      return;
    }
    waiting_[url] = std::move(callback);
  }

  base::flat_set<GURL> GetTriggeredUrls() const { return triggered_; }

  void OnTrigger(const GURL& url) override {
    if (triggered_.contains(url)) {
      ASSERT_FALSE(waiting_.contains(url));
      return;
    }
    triggered_.insert(url);

    if (waiting_next_) {
      std::move(waiting_next_).Run(url);
    }

    auto iter = waiting_.find(url);
    if (iter != waiting_.end()) {
      auto callback = std::move(iter->second);
      waiting_.erase(iter);
      std::move(callback).Run();
    }
  }

  void OnRegistryDestroyed() override {
    EXPECT_TRUE(waiting_.empty());
    observation_.Reset();
  }

  base::ScopedObservation<PrerenderHostRegistry,
                          PrerenderHostRegistry::Observer>
      observation_{this};

  base::flat_map<GURL, base::OnceClosure> waiting_;
  base::OnceCallback<void(const GURL&)> waiting_next_;

  // Set when prerendering is triggered. Doesn't yet support the case where
  // prerendering is triggered, canceled, and then re-triggered for the same
  // URL.
  base::flat_set<GURL> triggered_;
};

PrerenderHostRegistryObserver::PrerenderHostRegistryObserver(
    WebContents& web_contents)
    : impl_(std::make_unique<PrerenderHostRegistryObserverImpl>(web_contents)) {
}

PrerenderHostRegistryObserver::~PrerenderHostRegistryObserver() = default;

void PrerenderHostRegistryObserver::WaitForTrigger(const GURL& url) {
  TRACE_EVENT("test", "PrerenderHostRegistryObserver::WaitForTrigger", "url",
              url);
  impl_->WaitForTrigger(url);
}

GURL PrerenderHostRegistryObserver::WaitForNextTrigger() {
  TRACE_EVENT("test", "PrerenderHostRegistryObserver::WaitForNextTrigger");
  return impl_->WaitForNextTrigger();
}

void PrerenderHostRegistryObserver::NotifyOnTrigger(
    const GURL& url,
    base::OnceClosure callback) {
  TRACE_EVENT("test", "PrerenderHostRegistryObserver::NotifyOnTrigger", "url",
              url);
  impl_->NotifyOnTrigger(url, std::move(callback));
}

base::flat_set<GURL> PrerenderHostRegistryObserver::GetTriggeredUrls() const {
  return impl_->GetTriggeredUrls();
}

class PrerenderHostObserverImpl : public PrerenderHost::Observer {
 public:
  PrerenderHostObserverImpl(WebContents& web_contents,
                            FrameTreeNodeId host_id) {
    PrerenderHost* host = GetPrerenderHostById(&web_contents, host_id);
    DCHECK(host)
        << "A PrerenderHost with the given id does not, or no longer, exists.";
    StartObserving(*host);
  }

  PrerenderHostObserverImpl(WebContents& web_contents, const GURL& url) {
    registry_observer_ =
        std::make_unique<PrerenderHostRegistryObserver>(web_contents);
    if (PrerenderHost* host = GetPrerenderHostRegistry(&web_contents)
                                  .FindHostByUrlForTesting(url)) {
      StartObserving(*host);
    } else {
      registry_observer_->NotifyOnTrigger(
          url,
          base::BindOnce(&PrerenderHostObserverImpl::OnTrigger,
                         base::Unretained(this), std::ref(web_contents), url));
    }
  }

  void OnActivated() override {
    was_activated_ = true;
    if (waiting_for_activation_)
      std::move(waiting_for_activation_).Run();
  }

  void OnHeadersReceived(NavigationHandle& navigation_handle) override {
    received_headers_ = true;
    if (waiting_for_headers_) {
      std::move(waiting_for_headers_).Run();
    }
  }

  void OnHostDestroyed(PrerenderFinalStatus final_status) override {
    observation_.Reset();
    last_status_ = final_status;
    if (waiting_for_destruction_) {
      std::move(waiting_for_destruction_).Run();
    }
    EXPECT_FALSE(waiting_for_activation_)
        << "A prerender was destroyed, with status "
        << base::to_underlying(final_status)
        << ", while waiting for activation.";
  }

  void WaitForActivation() {
    if (was_activated_)
      return;
    EXPECT_FALSE(waiting_for_activation_);

    EXPECT_FALSE(did_observe_ && !observation_.IsObserving())
        << "A prerender was destroyed, with status "
        << base::to_underlying(
               last_status_.value_or(PrerenderFinalStatus::kDestroyed))
        << ", before waiting for activation.";

    base::RunLoop loop;
    waiting_for_activation_ = loop.QuitClosure();
    loop.Run();

    EXPECT_TRUE(did_observe_) << "No prerender was triggered.";
  }

  void WaitForHeaders() {
    if (received_headers_) {
      return;
    }
    EXPECT_FALSE(waiting_for_headers_);

    EXPECT_FALSE(did_observe_ && !observation_.IsObserving())
        << "A prerender was destroyed, with status "
        << base::to_underlying(
               last_status_.value_or(PrerenderFinalStatus::kDestroyed))
        << ", before waiting for headers.";

    base::RunLoop loop;
    waiting_for_headers_ = loop.QuitClosure();
    loop.Run();

    EXPECT_TRUE(did_observe_) << "No prerender was triggered.";
  }

  void WaitForDestroyed() {
    if (did_observe_ && !observation_.IsObserving())
      return;
    EXPECT_FALSE(waiting_for_destruction_);
    base::RunLoop loop;
    waiting_for_destruction_ = loop.QuitClosure();
    loop.Run();
  }

  bool was_activated() const { return was_activated_; }

  bool WasHostReused() const {
    return last_status_ == PrerenderFinalStatus::kPrerenderHostReused;
  }

 private:
  void OnTrigger(WebContents& web_contents, const GURL& url) {
    PrerenderHost* host =
        GetPrerenderHostRegistry(&web_contents).FindHostByUrlForTesting(url);
    DCHECK(host) << "Attempted to trigger a prerender for [" << url << "] "
                 << "but canceled before a PrerenderHost was created.";
    StartObserving(*host);
  }
  void StartObserving(PrerenderHost& host) {
    did_observe_ = true;
    observation_.Observe(&host);

    // This method may be bound and called from |registry_observer_| so don't
    // add code below the reset.
    registry_observer_.reset();
  }

  base::ScopedObservation<PrerenderHost, PrerenderHost::Observer> observation_{
      this};
  base::OnceClosure waiting_for_activation_;
  base::OnceClosure waiting_for_headers_;
  base::OnceClosure waiting_for_destruction_;
  std::unique_ptr<PrerenderHostRegistryObserver> registry_observer_;
  bool was_activated_ = false;
  bool received_headers_ = false;
  bool did_observe_ = false;
  std::optional<PrerenderFinalStatus> last_status_;
};

PrerenderHostObserver::PrerenderHostObserver(WebContents& web_contents,
                                             FrameTreeNodeId prerender_host)
    : impl_(std::make_unique<PrerenderHostObserverImpl>(web_contents,
                                                        prerender_host)) {}

PrerenderHostObserver::PrerenderHostObserver(WebContents& web_contents,
                                             const GURL& url)
    : impl_(std::make_unique<PrerenderHostObserverImpl>(web_contents, url)) {}

PrerenderHostObserver::~PrerenderHostObserver() = default;

void PrerenderHostObserver::WaitForActivation() {
  TRACE_EVENT("test", "PrerenderHostObserver::WaitForActivation");
  impl_->WaitForActivation();
}

void PrerenderHostObserver::WaitForHeaders() {
  TRACE_EVENT("test", "PrerenderHostObserver::WaitForHeaders");
  impl_->WaitForHeaders();
}

void PrerenderHostObserver::WaitForDestroyed() {
  TRACE_EVENT("test", "PrerenderHostObserver::WaitForDestroyed");
  impl_->WaitForDestroyed();
}

bool PrerenderHostObserver::was_activated() const {
  return impl_->was_activated();
}

bool PrerenderHostObserver::WasHostReused() const {
  return impl_->WasHostReused();
}

PrerenderHostCreationWaiter::PrerenderHostCreationWaiter() {
  PrerenderHost::SetHostCreationCallbackForTesting(
      base::BindLambdaForTesting([&](FrameTreeNodeId host_id) {
        created_host_id_ = host_id;
        run_loop_.QuitClosure().Run();
      }));
}

FrameTreeNodeId PrerenderHostCreationWaiter::Wait() {
  EXPECT_TRUE(created_host_id_.is_null());
  run_loop_.Run();
  EXPECT_TRUE(created_host_id_);
  return created_host_id_;
}

ScopedPrerenderFeatureList::ScopedPrerenderFeatureList()
    : ScopedPrerenderFeatureList(/*force_disable_prerender2_fallback=*/true) {}

ScopedPrerenderFeatureList::ScopedPrerenderFeatureList(
    bool force_disable_prerender2_fallback) {
  std::vector<base::test::FeatureRef> enabled_features;
  std::vector<base::test::FeatureRef> disabled_features;

  // Disable the memory requirement of Prerender2
  // so the test can run on any bot.
  disabled_features.push_back(blink::features::kPrerender2MemoryControls);

  // In addition, disable `kPrerender2FallbackPrefetchSpecRules` if the user
  // of `PrerenderTestHelper` is not ready for it as it changes
  // `PrerenderFinalStatus` to `PrerenderFailedDuringPrefetch`, so that we
  // enable it in fieldtrial testing config and then fix them one by one.
  if (force_disable_prerender2_fallback) {
    disabled_features.push_back(features::kPrerender2FallbackPrefetchSpecRules);
  }

  feature_list_.InitWithFeatures(enabled_features, disabled_features);
}

PrerenderTestHelper::PrerenderTestHelper(const WebContents::Getter& fn)
    : feature_list_(ScopedPrerenderFeatureList(
          /*force_disable_prerender2_fallback=*/true)),
      get_web_contents_fn_(fn) {}

PrerenderTestHelper::PrerenderTestHelper(const WebContents::Getter& fn,
                                         bool force_disable_prerender2_fallback)
    : feature_list_(
          ScopedPrerenderFeatureList(force_disable_prerender2_fallback)),
      get_web_contents_fn_(fn) {}

PrerenderTestHelper::~PrerenderTestHelper() = default;

void PrerenderTestHelper::RegisterServerRequestMonitor(
    net::test_server::EmbeddedTestServer* http_server) {
  EXPECT_FALSE(http_server->Started());
  http_server->RegisterRequestMonitor(base::BindRepeating(
      &PrerenderTestHelper::MonitorResourceRequest, base::Unretained(this)));
}
void PrerenderTestHelper::RegisterServerRequestMonitor(
    net::test_server::EmbeddedTestServer& test_server) {
  EXPECT_FALSE(test_server.Started());
  test_server.RegisterRequestMonitor(base::BindRepeating(
      &PrerenderTestHelper::MonitorResourceRequest, base::Unretained(this)));
}

// static
FrameTreeNodeId PrerenderTestHelper::GetHostForUrl(WebContents& web_contents,
                                                   const GURL& url) {
  auto* host =
      GetPrerenderHostRegistry(&web_contents).FindHostByUrlForTesting(url);
  return host ? host->frame_tree_node_id() : FrameTreeNodeId();
}

FrameTreeNodeId PrerenderTestHelper::GetHostForUrl(const GURL& url) {
  return GetHostForUrl(*GetWebContents(), url);
}

// static
FrameTreeNodeId PrerenderTestHelper::GetPrewarmSearchResultHost(
    WebContents& web_contents,
    const GURL& prewarm_url) {
  auto* host = GetPrerenderHostRegistry(&web_contents)
                   .FindPrewarmSearchResultHostForTesting(prewarm_url);
  return host ? host->frame_tree_node_id() : FrameTreeNodeId();
}

FrameTreeNodeId PrerenderTestHelper::GetPrewarmSearchResultHost(
    const GURL& url) {
  return GetPrewarmSearchResultHost(*GetWebContents(), url);
}

bool PrerenderTestHelper::HasNewTabHandle(FrameTreeNodeId host_id) {
  PrerenderHostRegistry& registry = GetPrerenderHostRegistry(GetWebContents());
  return registry.HasNewTabHandleByIdForTesting(host_id);
}

void PrerenderTestHelper::WaitForPrerenderLoadCompletion(
    FrameTreeNodeId host_id) {
  TRACE_EVENT("test", "PrerenderTestHelper::WaitForPrerenderLoadCompletion",
              "host_id", host_id);
  auto* host = GetPrerenderHostById(GetWebContents(), host_id);
  ASSERT_NE(host, nullptr);
  auto status = host->WaitForLoadStopForTesting();
  EXPECT_EQ(status, PrerenderHost::LoadingOutcome::kLoadingCompleted);
}

// static
void PrerenderTestHelper::WaitForPrerenderLoadCompletion(
    WebContents& web_contents,
    const GURL& url) {
  auto status = WaitForPrerenderLoadingOutcome(web_contents, url);
  EXPECT_EQ(status, PrerenderHost::LoadingOutcome::kLoadingCompleted);
}

void PrerenderTestHelper::WaitForPrerenderLoadCompletion(const GURL& url) {
  WaitForPrerenderLoadCompletion(*GetWebContents(), url);
}

// static
void PrerenderTestHelper::WaitForPrerenderLoadCancellation(
    WebContents& web_contents,
    const GURL& url) {
  auto status = WaitForPrerenderLoadingOutcome(web_contents, url);
  EXPECT_EQ(status, PrerenderHost::LoadingOutcome::kPrerenderingCancelled);
}

void PrerenderTestHelper::WaitForPrerenderLoadCancellation(const GURL& url) {
  WaitForPrerenderLoadCancellation(*GetWebContents(), url);
}

FrameTreeNodeId PrerenderTestHelper::AddPrerender(const GURL& prerendering_url,
                                                  int32_t world_id) {
  return AddPrerender(prerendering_url, /*eagerness=*/std::nullopt,
                      /*target_hint=*/"", world_id);
}

FrameTreeNodeId PrerenderTestHelper::AddPrerender(
    const GURL& prerendering_url,
    std::optional<blink::mojom::SpeculationEagerness> eagerness,
    const std::string& target_hint,
    int32_t world_id) {
  return AddPrerender(prerendering_url, eagerness,
                      /*no_vary_search_hint=*/std::nullopt, target_hint,
                      /*ruleset_tag=*/std::nullopt, world_id);
}

FrameTreeNodeId PrerenderTestHelper::AddPrerender(
    const GURL& prerendering_url,
    std::optional<blink::mojom::SpeculationEagerness> eagerness,
    std::optional<std::string> no_vary_search_hint,
    const std::string& target_hint,
    std::optional<std::string> ruleset_tag,
    int32_t world_id) {
  TRACE_EVENT("test", "PrerenderTestHelper::AddPrerender", "prerendering_url",
              prerendering_url);
  EXPECT_TRUE(content::BrowserThread::CurrentlyOn(BrowserThread::UI));

  WebContents* prerender_web_contents = nullptr;
  if (target_hint == "_blank") {
    // Wait until AddPrerendersAsync() creates a new WebContents for
    // prerendering.
    base::RunLoop run_loop;
    auto creation_subscription = content::RegisterWebContentsCreationCallback(
        base::BindLambdaForTesting([&](content::WebContents* web_contents) {
          prerender_web_contents = web_contents;
          run_loop.QuitClosure().Run();
        }));
    AddPrerendersAsync({prerendering_url}, eagerness, no_vary_search_hint,
                       target_hint, ruleset_tag, world_id);
    run_loop.Run();
  } else {
    // For other target hints, the initiator's WebContents will host a
    // prerendered page.
    prerender_web_contents = GetWebContents();
    AddPrerendersAsync({prerendering_url}, eagerness, no_vary_search_hint,
                       target_hint, ruleset_tag, world_id);
  }

  WaitForPrerenderLoadCompletion(*prerender_web_contents, prerendering_url);
  FrameTreeNodeId host_id =
      GetHostForUrl(*prerender_web_contents, prerendering_url);
  EXPECT_TRUE(host_id);
  return host_id;
}

void PrerenderTestHelper::AddPrerenderAsync(const GURL& prerendering_url,
                                            int32_t world_id) {
  AddPrerendersAsync({prerendering_url}, /*eagerness=*/std::nullopt,
                     /*target_hint=*/std::string(), world_id);
}

void PrerenderTestHelper::AddPrerendersAsync(
    const std::vector<GURL>& prerendering_urls,
    std::optional<blink::mojom::SpeculationEagerness> eagerness,
    const std::string& target_hint,
    int32_t world_id) {
  AddPrerendersAsync(prerendering_urls, eagerness,
                     /*no_vary_search_hint=*/std::nullopt, target_hint,
                     /*ruleset_tag=*/std::nullopt, world_id);
}

void PrerenderTestHelper::AddPrerendersAsync(
    const std::vector<GURL>& prerendering_urls,
    std::optional<blink::mojom::SpeculationEagerness> eagerness,
    std::optional<std::string> no_vary_search_hint,
    const std::string& target_hint,
    std::optional<std::string> ruleset_tag,
    int32_t world_id) {
  TRACE_EVENT(
      "test", "PrerenderTestHelper::AddPrerendersAsync", "prerendering_urls",
      prerendering_urls, "eagerness",
      eagerness.has_value() ? ConvertEagernessToString(eagerness.value())
                            : "(empty)",
      "expected_no_vary_search",
      no_vary_search_hint.has_value() ? no_vary_search_hint.value() : "(empty)",
      "target_hint", target_hint.empty() ? "(empty)" : target_hint);
  EXPECT_TRUE(content::BrowserThread::CurrentlyOn(BrowserThread::UI));
  std::string script = BuildScriptElementSpeculationRules(
      prerendering_urls, eagerness, no_vary_search_hint, target_hint,
      ruleset_tag);

  if (world_id == ISOLATED_WORLD_ID_GLOBAL) {
    // Have to use ExecuteJavaScriptForTests instead of ExecJs/EvalJs here,
    // because some test pages have ContentSecurityPolicy and EvalJs cannot work
    // with it. See the quick migration guide for EvalJs for more information.
    GetWebContents()->GetPrimaryMainFrame()->ExecuteJavaScriptForTests(
        base::UTF8ToUTF16(script), base::NullCallback(), world_id);
  } else {
    GetWebContents()->GetPrimaryMainFrame()->ExecuteJavaScriptInIsolatedWorld(
        base::UTF8ToUTF16(script), base::NullCallback(), world_id);
  }
}

void PrerenderTestHelper::AddPrerenderUntilScriptAsync(
    const GURL& url,
    blink::mojom::SpeculationEagerness eagerness) {
  EXPECT_TRUE(content::BrowserThread::CurrentlyOn(BrowserThread::UI));
  std::string script = JsReplace(kAddSpeculationRulePrerenderUntilScriptScript,
                                 url, ConvertEagernessToString(eagerness));

  // Have to use ExecuteJavaScriptForTests instead of ExecJs/EvalJs here,
  // because some test pages have ContentSecurityPolicy and EvalJs cannot work
  // with it. See the quick migration guide for EvalJs for more information.
  GetWebContents()->GetPrimaryMainFrame()->ExecuteJavaScriptForTests(
      base::UTF8ToUTF16(script), base::NullCallback(),
      ISOLATED_WORLD_ID_GLOBAL);
}

void PrerenderTestHelper::AddPrefetchAsync(const GURL& prefetch_url) {
  EXPECT_TRUE(content::BrowserThread::CurrentlyOn(BrowserThread::UI));
  std::string script =
      JsReplace(kAddSpeculationRulePrefetchScript, prefetch_url);

  // Have to use ExecuteJavaScriptForTests instead of ExecJs/EvalJs here,
  // because some test pages have ContentSecurityPolicy and EvalJs cannot work
  // with it. See the quick migration guide for EvalJs for more information.
  GetWebContents()->GetPrimaryMainFrame()->ExecuteJavaScriptForTests(
      base::UTF8ToUTF16(script), base::NullCallback(),
      ISOLATED_WORLD_ID_GLOBAL);
}

std::unique_ptr<PrerenderHandle>
PrerenderTestHelper::AddEmbedderTriggeredPrerenderAsync(
    WebContents& web_contents,
    const GURL& prerendering_url,
    PreloadingTriggerType trigger_type,
    const std::string& embedder_histogram_suffix,
    ui::PageTransition page_transition) {
  TRACE_EVENT("test", "PrerenderTestHelper::AddEmbedderTriggeredPrerenderAsync",
              "prerendering_url", prerendering_url, "trigger_type",
              trigger_type, "embedder_histogram_suffix",
              embedder_histogram_suffix, "page_transition", page_transition);
  if (!content::BrowserThread::CurrentlyOn(BrowserThread::UI))
    return nullptr;

  return web_contents.StartPrerendering(
      prerendering_url, trigger_type, embedder_histogram_suffix,
      /*additional_headers=*/net::HttpRequestHeaders(),
      /*no_vary_search_hint=*/std::nullopt, page_transition,
      /*should_warm_up_compositor=*/false,
      /*should_prepare_paint_tree=*/false,
      PreloadingHoldbackStatus::kUnspecified,
      PreloadPipelineInfo::Create(
          /*planned_max_preloading_type=*/PreloadingType::kPrerender),
      /*preloading_attempt=*/nullptr, /*url_match_predicate=*/{},
      /*prerender_navigation_handle_callback=*/{},
      /*allow_reuse=*/false);
}

std::unique_ptr<PrerenderHandle>
PrerenderTestHelper::AddEmbedderTriggeredPrerenderAsync(
    const GURL& prerendering_url,
    PreloadingTriggerType trigger_type,
    const std::string& embedder_histogram_suffix,
    ui::PageTransition page_transition) {
  return AddEmbedderTriggeredPrerenderAsync(
      *GetWebContents(), prerendering_url, trigger_type,
      embedder_histogram_suffix, page_transition);
}

void PrerenderTestHelper::NavigatePrerenderedPage(FrameTreeNodeId host_id,
                                                  const GURL& url) {
  TRACE_EVENT("test", "PrerenderTestHelper::NavigatePrerenderedPage", "host_id",
              host_id, "url", url);

  // Take RenderFrameHost corresponding to the main frame of the prerendered
  // page.
  auto* prerender_web_contents = WebContents::FromFrameTreeNodeId(host_id);
  auto* prerender_host = GetPrerenderHostById(prerender_web_contents, host_id);
  ASSERT_NE(prerender_host, nullptr);
  RenderFrameHostImpl* prerender_render_frame_host =
      prerender_host->GetPrerenderedMainFrameHost();

  // Navigate the RenderFrameHost to the URL.
  //
  // Ignore the result of ExecJs() to avoid unexpected execution failure.
  // Navigation from the prerendered page could cancel prerendering and destroy
  // the prerendered frame before ExecJs() gets a result from that. This results
  // in execution failure even when the execution succeeded.
  // See https://crbug.com/1186584 for details.
  std::ignore =
      ExecJs(prerender_render_frame_host, JsReplace("location = $1", url));
}

void PrerenderTestHelper::CancelPrerenderedPage(FrameTreeNodeId host_id) {
  PrerenderHostRegistry& registry = GetPrerenderHostRegistry(GetWebContents());
  registry.CancelHost(host_id, PrerenderFinalStatus::kDestroyed);
}

// static
std::unique_ptr<content::TestNavigationObserver>
PrerenderTestHelper::NavigatePrimaryPageAsync(WebContents& web_contents,
                                              const GURL& url,
                                              ui::PageTransition transition) {
  TRACE_EVENT("test", "PrerenderTestHelper::NavigatePrimaryPage",
              "web_contents", web_contents, "url", url);
  const bool is_renderer_initiated =
      PageTransitionCoreTypeIs(transition, ui::PAGE_TRANSITION_LINK);
  if (is_renderer_initiated && web_contents.IsLoading()) {
    // Ensure that any ongoing navigation is complete prior to the construction
    // of |observer| below (this navigation may complete while executing ExecJs
    // machinery).
    // Skip this wait when testing browser initiated navigations which don't
    // expect this wait.
    content::TestNavigationObserver initial_observer(&web_contents);
    initial_observer.set_wait_event(
        content::TestNavigationObserver::WaitEvent::kLoadStopped);
    initial_observer.Wait();
  }

  EXPECT_TRUE(content::BrowserThread::CurrentlyOn(BrowserThread::UI));
  std::unique_ptr<content::TestNavigationObserver> observer =
      std::make_unique<content::TestNavigationObserver>(&web_contents);
  observer->set_wait_event(
      content::TestNavigationObserver::WaitEvent::kLoadStopped);
  if (is_renderer_initiated) {
    // Ignore the result of ExecJs().
    //
    // Depending on timing, activation could destroy a navigating frame before
    // ExecJs() gets a result from the frame. This results in execution failure
    // even when the navigation succeeded.
    std::ignore = ExecJs(web_contents.GetPrimaryMainFrame(),
                         JsReplace("location = $1", url));
  } else {
    web_contents.OpenURL(
        OpenURLParams(url, Referrer(), WindowOpenDisposition::CURRENT_TAB,
                      transition, is_renderer_initiated),
        /*navigation_handle_callback=*/{});
  }
  return observer;
}

std::unique_ptr<content::TestNavigationObserver>
PrerenderTestHelper::NavigatePrimaryPageAsync(const GURL& url,
                                              ui::PageTransition transition) {
  return NavigatePrimaryPageAsync(*GetWebContents(), url, transition);
}

// static
void PrerenderTestHelper::NavigatePrimaryPage(WebContents& web_contents,
                                              const GURL& url,
                                              ui::PageTransition transition) {
  NavigatePrimaryPageAsync(web_contents, url, transition)->Wait();
}

void PrerenderTestHelper::NavigatePrimaryPage(const GURL& url,
                                              ui::PageTransition transition) {
  NavigatePrimaryPage(*GetWebContents(), url, transition);
}

void PrerenderTestHelper::OpenNewWindowWithoutOpener(WebContents& web_contents,
                                                     const GURL& url) {
  std::string script = R"(window.open($1, "_blank", "noopener");)";
  EXPECT_TRUE(ExecJs(&web_contents, JsReplace(script, url.spec())));
}

void PrerenderTestHelper::SetHoldback(PreloadingType preloading_type,
                                      PreloadingPredictor predictor,
                                      bool holdback) {
  preloading_config_override_.SetHoldback(preloading_type, predictor, holdback);
}

void PrerenderTestHelper::SetHoldback(std::string_view preloading_type,
                                      std::string_view predictor,
                                      bool holdback) {
  preloading_config_override_.SetHoldback(preloading_type, predictor, holdback);
}

::testing::AssertionResult PrerenderTestHelper::VerifyPrerenderingState(
    const GURL& url) {
  PrerenderHostRegistry& registry = GetPrerenderHostRegistry(GetWebContents());
  PrerenderHost* prerender_host = registry.FindHostByUrlForTesting(url);
  RenderFrameHostImpl* prerendered_render_frame_host =
      prerender_host->GetPrerenderedMainFrameHost();
  std::vector<RenderFrameHost*> frames =
      CollectAllRenderFrameHosts(prerendered_render_frame_host);
  for (auto* frame : frames) {
    auto* rfhi = static_cast<RenderFrameHostImpl*>(frame);
    // All the subframes should be in LifecycleStateImpl::kPrerendering state
    // before activation.
    if (rfhi->lifecycle_state() !=
        RenderFrameHostImpl::LifecycleStateImpl::kPrerendering) {
      return ::testing::AssertionFailure() << "subframe in incorrect state";
    }
  }

  // Make sure that all the PrerenderHost frame trees are prerendering.
  const std::vector<FrameTree*> prerender_frame_trees =
      registry.GetPrerenderFrameTrees();
  std::for_each(std::begin(prerender_frame_trees),
                std::end(prerender_frame_trees), [](auto const& frame_tree) {
                  ASSERT_TRUE(frame_tree->is_prerendering());
                });

  return ::testing::AssertionSuccess();
}

// static
RenderFrameHost* PrerenderTestHelper::GetPrerenderedMainFrameHost(
    WebContents& web_contents,
    FrameTreeNodeId host_id) {
  auto* prerender_host = GetPrerenderHostById(&web_contents, host_id);
  EXPECT_NE(prerender_host, nullptr);
  return prerender_host->GetPrerenderedMainFrameHost();
}

// static
RenderFrameHost* PrerenderTestHelper::GetPrerenderedMainFrameHost(
    WebContents& web_contents,
    const GURL& url) {
  auto* prerender_host = GetPrerenderHostByUrl(&web_contents, url);
  EXPECT_NE(prerender_host, nullptr);
  return prerender_host->GetPrerenderedMainFrameHost();
}

RenderFrameHost* PrerenderTestHelper::GetPrerenderedMainFrameHost(
    FrameTreeNodeId host_id) {
  return GetPrerenderedMainFrameHost(*GetWebContents(), host_id);
}

RenderFrameHost* PrerenderTestHelper::GetPrerenderedMainFrameHost(
    const GURL& url) {
  return GetPrerenderedMainFrameHost(*GetWebContents(), url);
}

int PrerenderTestHelper::GetRequestCount(const GURL& url) {
  EXPECT_TRUE(content::BrowserThread::CurrentlyOn(BrowserThread::UI));
  base::AutoLock auto_lock(lock_);
  return request_count_by_path_[url.PathForRequest()];
}

net::test_server::HttpRequest::HeaderMap PrerenderTestHelper::GetRequestHeaders(
    const GURL& url) {
  EXPECT_TRUE(content::BrowserThread::CurrentlyOn(BrowserThread::UI));
  base::AutoLock auto_lock(lock_);
  std::string path = url.PathForRequest();
  DCHECK(base::Contains(request_headers_by_path_, path)) << path;
  return request_headers_by_path_[path];
}

void PrerenderTestHelper::WaitForRequest(const GURL& url, int count) {
  TRACE_EVENT("test", "PrerenderTestHelper::WaitForRequest", "url", url,
              "count", count);
  for (;;) {
    base::RunLoop run_loop;
    {
      base::AutoLock auto_lock(lock_);
      if (request_count_by_path_[url.PathForRequest()] >= count)
        return;
      monitor_callback_ = run_loop.QuitClosure();
    }
    run_loop.Run();
  }
}

void PrerenderTestHelper::MonitorResourceRequest(
    const net::test_server::HttpRequest& request) {
  // This should be called on `EmbeddedTestServer::io_thread_`.
  EXPECT_FALSE(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
  base::AutoLock auto_lock(lock_);
  request_count_by_path_[request.GetURL().PathForRequest()]++;
  request_headers_by_path_.emplace(request.GetURL().PathForRequest(),
                                   request.headers);
  if (monitor_callback_)
    std::move(monitor_callback_).Run();
}

WebContents* PrerenderTestHelper::GetWebContents() {
  return get_web_contents_fn_.Run();
}

std::string PrerenderTestHelper::GenerateHistogramName(
    const std::string& histogram_base_name,
    content::PreloadingTriggerType trigger_type,
    const std::string& embedder_suffix) {
  switch (trigger_type) {
    case content::PreloadingTriggerType::kSpeculationRule:
      DCHECK(embedder_suffix.empty());
      return std::string(histogram_base_name) + ".SpeculationRule";
    case content::PreloadingTriggerType::kSpeculationRuleFromIsolatedWorld:
      DCHECK(embedder_suffix.empty());
      return std::string(histogram_base_name) +
             ".SpeculationRuleFromIsolatedWorld";
    case content::PreloadingTriggerType::
        kSpeculationRuleFromAutoSpeculationRules:
      DCHECK(embedder_suffix.empty());
      return std::string(histogram_base_name) +
             ".SpeculationRuleFromAutoSpeculationRules";
    case content::PreloadingTriggerType::kEmbedder:
      DCHECK(!embedder_suffix.empty());
      return std::string(histogram_base_name) + ".Embedder_" + embedder_suffix;
  }
  NOTREACHED();
}

ScopedPrerenderWebContentsDelegate::ScopedPrerenderWebContentsDelegate(
    WebContents& web_contents)
    : web_contents_(web_contents.GetWeakPtr()) {
  web_contents_->SetDelegate(this);
}

ScopedPrerenderWebContentsDelegate::~ScopedPrerenderWebContentsDelegate() {
  if (web_contents_)
    web_contents_.get()->SetDelegate(nullptr);
}

PreloadingEligibility ScopedPrerenderWebContentsDelegate::IsPrerender2Supported(
    WebContents& web_contents,
    PreloadingTriggerType trigger_type) {
  return PreloadingEligibility::kEligible;
}

MockLinkPreviewWebContentsDelegate::MockLinkPreviewWebContentsDelegate() =
    default;

MockLinkPreviewWebContentsDelegate::~MockLinkPreviewWebContentsDelegate() =
    default;

}  // namespace test

}  // namespace content
