chromium/content/browser/preloading/prerender/prerender_browsertest.cc

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

#include <cstdint>
#include <optional>
#include <tuple>

#include "base/barrier_closure.h"
#include "base/base_switches.h"
#include "base/command_line.h"
#include "base/containers/flat_map.h"
#include "base/containers/flat_set.h"
#include "base/files/file_util.h"
#include "base/files/scoped_temp_dir.h"
#include "base/functional/callback_forward.h"
#include "base/functional/callback_helpers.h"
#include "base/memory/memory_pressure_monitor.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/metrics/metrics_hashes.h"
#include "base/run_loop.h"
#include "base/scoped_observation.h"
#include "base/strings/escape.h"
#include "base/strings/string_util.h"
#include "base/synchronization/lock.h"
#include "base/task/single_thread_task_runner.h"
#include "base/test/bind.h"
#include "base/test/gtest_util.h"
#include "base/test/run_until.h"
#include "base/test/scoped_feature_list.h"
#include "base/test/test_mock_time_task_runner.h"
#include "base/test/test_timeouts.h"
#include "base/thread_annotations.h"
#include "base/values.h"
#include "build/build_config.h"
#include "build/chromeos_buildflags.h"
#include "cc/base/features.h"
#include "components/input/render_widget_host_input_event_router.h"
#include "components/services/storage/public/mojom/storage_service.mojom.h"
#include "components/services/storage/public/mojom/test_api.test-mojom.h"
#include "components/ukm/test_ukm_recorder.h"
#include "content/browser/back_forward_cache_test_util.h"
#include "content/browser/preloading/prefetch/prefetch_features.h"
#include "content/browser/preloading/prefetch/prefetch_service.h"
#include "content/browser/preloading/prefetch/prefetch_test_util_internal.h"
#include "content/browser/preloading/preloading.h"
#include "content/browser/preloading/preloading_attempt_impl.h"
#include "content/browser/preloading/preloading_data_impl.h"
#include "content/browser/preloading/preloading_decider.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.h"
#include "content/browser/preloading/prerender/prerender_host_registry.h"
#include "content/browser/preloading/prerender/prerender_metrics.h"
#include "content/browser/preloading/prerender/prerender_no_vary_search_hint_commit_deferring_condition.h"
#include "content/browser/renderer_host/back_forward_cache_impl.h"
#include "content/browser/renderer_host/frame_tree_node.h"
#include "content/browser/renderer_host/navigation_request.h"
#include "content/browser/renderer_host/navigation_type.h"
#include "content/browser/renderer_host/render_frame_host_impl.h"
#include "content/browser/renderer_host/render_process_host_impl.h"
#include "content/browser/storage_partition_impl.h"
#include "content/browser/web_contents/web_contents_impl.h"
#include "content/common/content_navigation_policy.h"
#include "content/common/features.h"
#include "content/common/input/synthetic_tap_gesture.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/disallow_activation_reason.h"
#include "content/public/browser/document_user_data.h"
#include "content/public/browser/global_routing_id.h"
#include "content/public/browser/navigation_handle.h"
#include "content/public/browser/prerender_web_contents_delegate.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/common/content_switches.h"
#include "content/public/common/isolated_world_ids.h"
#include "content/public/test/back_forward_cache_util.h"
#include "content/public/test/background_color_change_waiter.h"
#include "content/public/test/browser_test.h"
#include "content/public/test/browser_test_utils.h"
#include "content/public/test/browsing_data_remover_test_util.h"
#include "content/public/test/content_browser_test.h"
#include "content/public/test/content_browser_test_content_browser_client.h"
#include "content/public/test/content_browser_test_utils.h"
#include "content/public/test/file_system_chooser_test_helpers.h"
#include "content/public/test/mock_client_hints_controller_delegate.h"
#include "content/public/test/mock_web_contents_observer.h"
#include "content/public/test/mojo_capability_control_test_interfaces.mojom.h"
#include "content/public/test/mojo_capability_control_test_util.h"
#include "content/public/test/navigation_handle_observer.h"
#include "content/public/test/no_renderer_crashes_assertion.h"
#include "content/public/test/preloading_test_util.h"
#include "content/public/test/prerender_test_util.h"
#include "content/public/test/scoped_accessibility_mode_override.h"
#include "content/public/test/test_navigation_observer.h"
#include "content/public/test/test_navigation_throttle.h"
#include "content/public/test/test_utils.h"
#include "content/public/test/theme_change_waiter.h"
#include "content/public/test/url_loader_interceptor.h"
#include "content/shell/browser/shell.h"
#include "content/shell/browser/shell_browser_context.h"
#include "content/test/content_browser_test_utils_internal.h"
#include "content/test/mock_commit_deferring_condition.h"
#include "content/test/render_document_feature.h"
#include "mojo/public/cpp/bindings/receiver_set.h"
#include "mojo/public/cpp/bindings/remote_set.h"
#include "mojo/public/cpp/system/functions.h"
#include "net/dns/mock_host_resolver.h"
#include "net/test/embedded_test_server/controllable_http_response.h"
#include "net/test/embedded_test_server/default_handlers.h"
#include "net/test/embedded_test_server/embedded_test_server.h"
#include "net/test/embedded_test_server/http_request.h"
#include "net/test/embedded_test_server/http_response.h"
#include "net/test/embedded_test_server/request_handler_util.h"
#include "services/metrics/public/cpp/metrics_utils.h"
#include "services/metrics/public/cpp/ukm_builders.h"
#include "services/network/public/cpp/web_sandbox_flags.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "third_party/blink/public/common/features.h"
#include "third_party/blink/public/common/loader/loader_constants.h"
#include "third_party/blink/public/mojom/browser_interface_broker.mojom.h"
#include "third_party/blink/public/mojom/frame/fullscreen.mojom.h"
#include "third_party/blink/public/mojom/page/display_cutout.mojom.h"
#include "ui/events/base_event_utils.h"
#include "ui/shell_dialogs/select_file_dialog.h"
#include "ui/shell_dialogs/select_file_dialog_factory.h"
#include "url/gurl.h"
#include "url/url_constants.h"

#if BUILDFLAG(ENABLE_PLUGINS)
#include "content/common/pepper_plugin.mojom.h"
#endif  // BUILDFLAG(ENABLE_PLUGINS)

Exactly;

namespace content {
namespace  // namespace

// Test that the timer is enabled and cleared appropriately when navigating to
// a No-Vary-Search hint matched prerender successfully.
IN_PROC_BROWSER_TEST_F(
    NoVarySearchPrerenderBrowserTest,
    EagerTimerWorksCorrectlyForHeadersThatArriveBeforeTimeout) {}

// Test that the timer is enabled and cleared appropriately when navigating to
// a No-Vary-Search hint matched prerender with timeout waiting for headers.
IN_PROC_BROWSER_TEST_F(
    NoVarySearchPrerenderBrowserTest,
    EagerTimerWorksCorrectlyForHeadersThatArriveAfterTimeout) {}

// Helper function to test cases where `no_vary_search_header` that does not
// match the No-Vary-Search hint is served and results in activation mismatch.
void NoVarySearchPrerenderBrowserTest::TestNoVarySearchHeaderFailure(
    const std::string& no_vary_search_header,
    FinishedReason expected_finished_reason) {}

// Test that a No-Vary-Search header is malformed.
IN_PROC_BROWSER_TEST_F(NoVarySearchPrerenderBrowserTest,
                       MalformedNoVarySearchHeader) {}

// Test that a No-Vary-Search header is default value.
IN_PROC_BROWSER_TEST_F(NoVarySearchPrerenderBrowserTest,
                       NoVarySearchHeaderWithDefaultValue) {}

// Test that a No-Vary-Search header is not served.
IN_PROC_BROWSER_TEST_F(NoVarySearchPrerenderBrowserTest, NoNoVarySearchHeader) {}

// Test that a No-Vary-Search header is received but does not match.
IN_PROC_BROWSER_TEST_F(NoVarySearchPrerenderBrowserTest,
                       UnmatchedNoVarySearchHeader) {}

// Test that activation is successful when navigating to an inexact URL
// before No-Vary-Search header is back from the server, if the No-Vary-Search
// header is matching when it is received.
IN_PROC_BROWSER_TEST_F(NoVarySearchPrerenderBrowserTest,
                       HintActivationSuccessful) {}

// Test that activation is not successful when navigating to an inexact URL
// before No-Vary-Search header is back from the server if the No-Vary-Search
// header is not matching when it is received.
IN_PROC_BROWSER_TEST_F(NoVarySearchPrerenderBrowserTest,
                       HintActivationUnsuccessful) {}

// Test that activation is successful when navigating to an exact URL before
// No-Vary-Search header is back from the server.
IN_PROC_BROWSER_TEST_F(NoVarySearchPrerenderBrowserTest,
                       HintActivationSuccessful_ExactUrl) {}

// Test that activation is successful when 2 matchable PrerenderHosts exist.
IN_PROC_BROWSER_TEST_F(NoVarySearchPrerenderBrowserTest,
                       MultipleMatchableHosts) {}

// Tests that the speculationrules No-Vary-Search hint is populated for the
// PrerenderHost.
IN_PROC_BROWSER_TEST_F(NoVarySearchPrerenderBrowserTest, HintIsPopulated) {}

// Tests that the speculationrules trigger works in the presence of
// No-Vary-Search for same URL.
IN_PROC_BROWSER_TEST_F(NoVarySearchPrerenderBrowserTest, ExactUrlMatch) {}

// Tests that the speculationrules trigger works in the presence of
// No-Vary-Search.
IN_PROC_BROWSER_TEST_F(NoVarySearchPrerenderBrowserTest, InexactUrlMatch) {}

// Tests that the speculationrules trigger works in the presence of
// No-Vary-Search for same URL in the presence of redirection.
IN_PROC_BROWSER_TEST_F(NoVarySearchPrerenderBrowserTest,
                       ExactMatchWithUrlRedirection) {}

// Tests that the speculationrules trigger works in the presence of
// No-Vary-Search for inexact URL in the presence of redirection.
IN_PROC_BROWSER_TEST_F(NoVarySearchPrerenderBrowserTest,
                       InexactMatchWithUrlRedirection) {}

// Tests that the speculationrules No-Vary-Search hint is not populated for the
// PrerenderHost if kPrerender2NoVarySearch feature is not enabled.
IN_PROC_BROWSER_TEST_F(DisabledNoVarySearchPrerenderBrowserTest,
                       NoVarySearchHintIsNotPopulated) {}

// Tests that the speculationrules trigger works in the presence of
// No-Vary-Search for inexact URL in the presence of main frame navigation.
IN_PROC_BROWSER_TEST_F(NoVarySearchPrerenderBrowserTest,
                       InexactUrlMatchWithMainFrameNavigation) {}

// Test that activation is unsuccessful when navigating to an inexact URL
// before No-Vary-Search header is back from the server, even if the
// No-Vary-Search header is matching when it is received.
IN_PROC_BROWSER_TEST_F(DisabledNoVarySearchPrerenderBrowserTest,
                       NoVarySearchHintActivationUnsuccessful) {}

// Tests that the speculationrules trigger works.
IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, SpeculationRulesPrerender) {}

// Used for running tests that should commonly pass regardless of target hints.
class PrerenderTargetAgnosticBrowserTest
    : public PrerenderBrowserTest,
      public testing::WithParamInterface<std::string> {};

INSTANTIATE_TEST_SUITE_P(All,
                         PrerenderTargetAgnosticBrowserTest,
                         testing::Values("_self", "_blank"),
                         [](const testing::TestParamInfo<std::string>& info) {};

class AutoSpeculationRulesPrerenderBrowserTest : public PrerenderBrowserTest {};

class AutoSpeculationRulesPrerenderBrowserTestWithHoldback
    : public AutoSpeculationRulesPrerenderBrowserTest {};

IN_PROC_BROWSER_TEST_F(AutoSpeculationRulesPrerenderBrowserTest, Metrics) {}

IN_PROC_BROWSER_TEST_F(AutoSpeculationRulesPrerenderBrowserTestWithHoldback,
                       Metrics) {}

enum class PrerenderingResult {};
enum class BodySize {};

class PrerenderAndPrefetchBrowserTest
    : public PrerenderBrowserTest,
      public testing::WithParamInterface<
          std::tuple<PrerenderingResult, BodySize, PrefetchReusableForTests>> {};

IN_PROC_BROWSER_TEST_P(PrerenderAndPrefetchBrowserTest,
                       SpeculationRulesPrefetchThenPrerender) {}

INSTANTIATE_TEST_SUITE_P();

// Tests that the speculationrules-triggered prerender would be destroyed after
// its initiator navigates away.
IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, SpeculationInitiatorNavigateAway) {}

// Tests that clicking a link can activate a prerender.
IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, ActivateOnLinkClick) {}

// Tests that clicking a link annotated with "target=_blank" cannot activate a
// prerender.
IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, ActivateOnLinkClick_TargetBlank) {}

// Tests that clicking a link annotated with "target=_blank" can activate a
// prerender whose target_hint is "_blank".
IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest,
                       ActivateOnLinkClick_TargetBlank_WithTargetHintBlank) {}

// Tests that clicking a link annotated with "target=_blank" can activate a
// prerender whose target_hint is "_blank" where the initiator page is in the
// background when the speculation rules were added.
IN_PROC_BROWSER_TEST_F(
    PrerenderBrowserTest,
    BackgroundedPage_ActivateOnLinkClick_TargetBlank_WithTargetHintBlank) {}

// Tests that the prerendering started by a hidden initiator page will be
// canceled after timeout.
IN_PROC_BROWSER_TEST_F(
    PrerenderBrowserTest,
    BackgroundedPageTimeout_TargetBlank_WithTargetHintBlank) {}

IN_PROC_BROWSER_TEST_F(
    PrerenderBrowserTest,
    PrerenderWhenInitiatorInBackground_Queue_Processing_WithTargetHint) {}

// Tests that clicking a link annotated with "target=_blank rel=noopener" cannot
// activate a prerender.
IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest,
                       ActivateOnLinkClick_TargetBlankWithNoopener) {}

// Tests that clicking a link annotated with "target=_blank rel=noopener" can
// activate a prerender whose target_hint is "_blank".
IN_PROC_BROWSER_TEST_F(
    PrerenderBrowserTest,
    ActivateOnLinkClick_TargetBlankWithNoopener_WithTargetHintBlank) {}

// Tests that clicking a link annotated with "target=_blank rel=opener" cannot
// activate a prerender.
IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest,
                       ActivateOnLinkClick_TargetBlankWithOpener) {}

// Tests that clicking a link annotated with "target=_blank rel=opener" cannot
// activate a prerender whose target_hint is "_blank".
IN_PROC_BROWSER_TEST_F(
    PrerenderBrowserTest,
    ActivateOnLinkClick_TargetBlankWithOpener_WithTargetHintBlank) {}

// Tests that window.open() annotated with "_blank" and "noopener" can activate
// a prerender whose target_hint is "_blank".
IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, ActivateOnWindowOpen) {}

// TODO(crbug.com/40234240): Add more test cases for prerender-in-new-tab:
// - Multiple prerendering requests with the same URL but different target hint.
// - Navigation in a new tab to the prerendering URL multiple times. Only the
//   first navigation should activate the prerendered page.

IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, ResponseHeaders) {}

// Tests that cancelling a prerender-into-new-tab trigger by invoking
// CancelHosts on initiator WebContents's PrerenderHostRegistry will
// eventually destruct corresponding PrerenderNewTabHandle and its WebContents
// created for the new-tab trigger.
IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest,
                       NewTabPrerenderCancellationOnInitiatorPHR) {}

// Tests that cancelling a prerender-into-new-tab trigger by invoking
// CancelHosts on PrerenderHostRegistry of WebContents created by new-tab
// triggers will eventually destruct corresponding PrerenderNewTabHandle on
// initiator's PHR and that WebContents created for the new-tab trigger.
IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest,
                       NewTabPrerenderCancellationOnNewTabPHR) {}

// Tests that closing initiator's WebContents will eventually destruct
// corresponding PrerenderNewTabHandle WebContents created for the new-tab
// trigger without crashing.
IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest,
                       NewTabPrerenderCancellationByInitiatorWCClosure) {}

// Tests that prerendering is cancelled if a network request for the
// navigation results in an empty response with 404 status.
IN_PROC_BROWSER_TEST_P(PrerenderTargetAgnosticBrowserTest,
                       PrerenderCancelledOnEmptyBody404) {}

// Tests that prerendering is cancelled if a network request for the
// navigation results in an non-empty response with 404 status.
IN_PROC_BROWSER_TEST_P(PrerenderTargetAgnosticBrowserTest,
                       PrerenderCancelledOnNonEmptyBody404) {}

// Tests that prerendering is cancelled if a network request for the
// navigation results in an non-empty response with 500 status.
IN_PROC_BROWSER_TEST_P(PrerenderTargetAgnosticBrowserTest,
                       PrerenderCancelledOn500Page) {}

IN_PROC_BROWSER_TEST_P(PrerenderTargetAgnosticBrowserTest,
                       PrerenderCancelledOn204Page) {}

IN_PROC_BROWSER_TEST_P(PrerenderTargetAgnosticBrowserTest,
                       PrerenderCancelledOn205Page) {}

namespace {

// Tests that an iframe navigation whose response has either 204 or 205 doesn't
// cancel prerendering.
// This is also a regression test for https://crbug.com/1362818.
void PrerenderBrowserTest::TestPrerenderAllowedOnIframeWithStatusCode(
    OriginType origin_type,
    std::string status_code) {}

}  // namespace

IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest,
                       PrerenderAllowedOnIframe_204_SameOrigin) {}

IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest,
                       PrerenderAllowedOnIframe_204_SameSiteCrossOrigin) {}

IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest,
                       PrerenderAllowedOnIframe_204_CrossSite) {}

IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest,
                       PrerenderAllowedOnIframe_205_SameOrigin) {}

IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest,
                       PrerenderAllowedOnIframe_205_SameSiteCrossOrigin) {}

IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest,
                       PrerenderAllowedOnIframe_205_CrossSite) {}

IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, CancelOnAuthRequested) {}

IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, CancelOnAuthRequestedSubframe) {}

IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, CancelOnAuthRequestedSubResource) {}

IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest,
                       CancelOnSpeculationCandidateRemoved) {}

// Tests removing speculation rules whose target_hint is "_blank" (i.e.,
// prerender into new tab).
IN_PROC_BROWSER_TEST_F(
    PrerenderBrowserTest,
    CancelOnSpeculationCandidateRemoved_WithTargetHintBlank) {}

IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest,
                       DontCancelOnSpeculationUpdateIfStillEligible) {}

IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest,
                       CanStartSecondPrerenderWhenCancellingFirst) {}

IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, RetriggerPrerenderAfterRemoval) {}

// Tests that prerendering triggered by prerendered pages is deferred until
// activation.
IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderChain) {}

// Tests that sub-frames cannot trigger prerendering.
IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, IgnoreSubFrameInitiatedPrerender) {}

// Regression test for https://crbug.com/1194865.
IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, CloseOnPrerendering) {}

namespace {

class RedirectChainObserver : public WebContentsObserver {};

}  // namespace

IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, SameOriginRedirection) {}

IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, CrossSiteRedirection) {}

// Makes sure that activation on navigation for an iframes doesn't happen.
IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, Activation_iFrame) {}

// Make sure that the prerendering browsing context has an isolated trivial
// session history. history.length should be limited to 1 in the prerendering
// browsing context.
//
// Explainer:
// https://github.com/jeremyroman/alternate-loading-modes/blob/main/browsing-context.md#session-history
IN_PROC_BROWSER_TEST_F(
    PrerenderBrowserTest,
    SessionHistoryShouldHaveSingleNavigationEntryInPrerender) {}

// Make sure that activation appends the prerendering page's single navigation
// entry to the initiator page's joint session history. We can go back or
// forward after activation.
IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, SessionHistoryAfterActivation) {}

class PrerenderOopsifBrowserTest : public PrerenderBrowserTest {};

// Test for crbug.com/1470312.
// Prior to the CL that introduced this test, if IsolatedSandboxedIframes are
// enabled, and an isolated frame sends the parent a postMessage, then the
// proxies were attached to the active page and not the prerendered  mainframe.
// These were proxies that were created on demand when processing the
// postMessage. (to ensure the recipient can reply to the sender frame, or to a
// frame that the sender could reach). This led to a CHECK failure in
// ~BrowsingContextInstance(). This test verifies that problem has been
// resolved.
IN_PROC_BROWSER_TEST_F(PrerenderOopsifBrowserTest,
                       OopsifSrcdocSandboxIframeWithPostmessage) {}

// Makes sure that cross-origin subframe navigations are deferred during
// prerendering.
IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest,
                       DeferCrossOriginSubframeNavigation) {}

// Makes sure that subframe navigations are deferred if cross-origin redirects
// are observed in a prerendering page.
IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest,
                       DeferCrossOriginRedirectsOnSubframeNavigation) {}

// Tests for main frame navigation in a prerendered page.
class PrerenderMainFrameNavigationBrowserTest
    : public testing::WithParamInterface<PreloadingTriggerType>,
      public PrerenderBrowserTest {};

INSTANTIATE_TEST_SUITE_P(
    All,
    PrerenderMainFrameNavigationBrowserTest,
    testing::Values(PreloadingTriggerType::kSpeculationRule,
                    PreloadingTriggerType::kSpeculationRuleFromIsolatedWorld,
                    PreloadingTriggerType::kEmbedder),
    [](const testing::TestParamInfo<PreloadingTriggerType>& info) {};

IN_PROC_BROWSER_TEST_P(PrerenderMainFrameNavigationBrowserTest, SameOrigin) {}

IN_PROC_BROWSER_TEST_P(PrerenderMainFrameNavigationBrowserTest,
                       SameSiteCrossOriginWithOptIn) {}

IN_PROC_BROWSER_TEST_P(PrerenderMainFrameNavigationBrowserTest,
                       SameSiteCrossOrigin) {}

IN_PROC_BROWSER_TEST_P(PrerenderMainFrameNavigationBrowserTest, CrossSite) {}

IN_PROC_BROWSER_TEST_P(PrerenderMainFrameNavigationBrowserTest,
                       SameSiteCrossOriginWithOptIn_SameOrigin) {}

IN_PROC_BROWSER_TEST_P(
    PrerenderMainFrameNavigationBrowserTest,
    SameSiteCrossOriginWithOptIn_SameSiteCrossOriginWithOptIn) {}

IN_PROC_BROWSER_TEST_P(PrerenderMainFrameNavigationBrowserTest,
                       SameSiteCrossOriginWithOptIn_SameSiteCrossOrigin) {}

IN_PROC_BROWSER_TEST_P(PrerenderMainFrameNavigationBrowserTest,
                       SameSiteCrossOrigin_CrossSite) {}

IN_PROC_BROWSER_TEST_P(PrerenderMainFrameNavigationBrowserTest,
                       Redirection_SameOrigin_SameOrigin) {}

IN_PROC_BROWSER_TEST_P(PrerenderMainFrameNavigationBrowserTest,
                       Redirection_SameOrigin_SameSiteCrossOriginWithOptIn) {}

IN_PROC_BROWSER_TEST_P(PrerenderMainFrameNavigationBrowserTest,
                       Redirection_SameOrigin_SameSiteCrossOrigin) {}

IN_PROC_BROWSER_TEST_P(PrerenderMainFrameNavigationBrowserTest,
                       Redirection_SameOrigin_CrossSite) {}

IN_PROC_BROWSER_TEST_P(PrerenderMainFrameNavigationBrowserTest,
                       Redirection_SameSiteCrossOriginWithOptIn_SameOrigin) {}

IN_PROC_BROWSER_TEST_P(
    PrerenderMainFrameNavigationBrowserTest,
    Redirection_SameSiteCrossOriginWithOptIn_SameSiteCrossOriginWithOptIn) {}

IN_PROC_BROWSER_TEST_P(
    PrerenderMainFrameNavigationBrowserTest,
    Redirection_SameSiteCrossOriginWithOptIn_SameSiteCrossOrigin) {}

IN_PROC_BROWSER_TEST_P(PrerenderMainFrameNavigationBrowserTest,
                       Redirection_SameSiteCrossOriginWithOptIn_CrossSite) {}

IN_PROC_BROWSER_TEST_P(
    PrerenderMainFrameNavigationBrowserTest,
    Redirection_SameOrigin_SameSiteCrossOriginWithOptIn_SameOrigin) {}

IN_PROC_BROWSER_TEST_P(
    PrerenderMainFrameNavigationBrowserTest,
    Redirection_SameOrigin_SameSiteCrossOriginWithOptIn_SameSiteCrossOriginWithOptIn) {}

IN_PROC_BROWSER_TEST_P(
    PrerenderMainFrameNavigationBrowserTest,
    Redirection_SameOrigin_SameSiteCrossOriginWithOptIn_SameSiteCrossOrigin) {}

IN_PROC_BROWSER_TEST_P(
    PrerenderMainFrameNavigationBrowserTest,
    Redirection_SameOrigin_SameSiteCrossOriginWithOptIn_CrossSite) {}

IN_PROC_BROWSER_TEST_P(
    PrerenderMainFrameNavigationBrowserTest,
    Redirection_SameSiteCrossOriginWithOptIn_SameOrigin_SameOrigin) {}

IN_PROC_BROWSER_TEST_P(
    PrerenderMainFrameNavigationBrowserTest,
    Redirection_SameSiteCrossOriginWithOptIn_SameOrigin_SameSiteCrossOriginWithOptIn) {}

IN_PROC_BROWSER_TEST_P(
    PrerenderMainFrameNavigationBrowserTest,
    Redirection_SameSiteCrossOriginWithOptIn_SameOrigin_SameSiteCrossOrigin) {}

IN_PROC_BROWSER_TEST_P(
    PrerenderMainFrameNavigationBrowserTest,
    Redirection_SameSiteCrossOriginWithOptIn_SameOrigin_CrossSite) {}

IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, MainFrameNavigation_NonHttpUrl) {}

// Regression test for https://crbug.com/1198051
IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, MainFrameFragmentNavigation) {}

// Makes sure that activation on navigation for a pop-up window doesn't happen.
IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, Activation_PopUpWindow) {}

// Makes sure that activation on navigation for a page that has a pop-up window
// doesn't happen.
IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, Activation_PageWithPopUpWindow) {}

// Tests that all RenderFrameHostImpls in the prerendering page know the
// prerendering state.
IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderIframe) {}

// Blank <iframe> is a special case. Tests that the blank iframe knows the
// prerendering state as well.
IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderBlankIframe) {}

PrerenderBrowserDeathTest;

// Tests that an inner WebContents cannot be attached in a prerendered page.
// See https://crbug.com/40191159 for details.
IN_PROC_BROWSER_TEST_F(PrerenderBrowserDeathTest,
                       PrerenderCannotHaveInnerContents) {}

// Ensure that whether or not a NavigationRequest is for a prerender activation
// is available in WebContentsObserver::DidStartNavigation.
class IsActivationObserver : public WebContentsObserver {};

IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest,
                       NavigationRequestIsPrerenderedPageActivation) {}

IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, ActivationDoesntRunThrottles) {}

// Ensures that if we attempt to open a URL while prerendering with a window
// disposition other than CURRENT_TAB, we fail.
IN_PROC_BROWSER_TEST_P(PrerenderTargetAgnosticBrowserTest, SuppressOpenURL) {}

// Tests that |RenderFrameHost::ForEachRenderFrameHost| and
// |WebContents::ForEachRenderFrameHost| behave correctly when prerendering.
IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, ForEachRenderFrameHost) {}

// Tests that a prerendering page cannot change the visible URL of the
// corresponding WebContentsImpl instance before activation.
IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, TabVisibleURL) {}

// Tests that prerendering will be cancelled if a prerendering page wants to set
// a WebContents-level preferred size.
IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, CancelOnPreferredSizeChanged) {}

// Tests that prerendering cannot request the browser to create a popup widget.
IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, NoPopupWidget) {}

// This throttle cancels prerendering on subframe navigation in prerendered
// pages. The subframe navigation itself will keep proceeding.
class TestPrerenderCancellerSubframeNavigationThrottle
    : public NavigationThrottle {};

// Regression test for https://crbug.com/1323309.
// Tests that subframe navigation in prerendered pages starting while
// PrerenderHost is being destroyed should not crash.
IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest,
                       SubframeNavigationWhilePrerenderHostIsBeingDestroyed) {}

class MojoCapabilityControlTestContentBrowserClient
    : public ContentBrowserTestContentBrowserClient,
      public test::MojoCapabilityControlTestHelper {};

// Tests that binding requests are handled according to MojoBinderPolicyMap
// during prerendering.
IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, MojoCapabilityControl) {}

// Tests that mojo capability control will cancel prerendering if the main frame
// receives a request for a kCancel interface.
IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest,
                       MojoCapabilityControl_CancelMainFrame) {}

// Tests that mojo capability control will cancel prerendering if child frames
// receive a request for a kCancel interface.
IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest,
                       MojoCapabilityControl_CancelIframe) {}

// Tests that mojo capability control will crash the prerender if the browser
// process receives a kUnexpected interface.
IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest,
                       MojoCapabilityControl_HandleUnexpected) {}

// Regression test for https://crbug.com/1268714 and https://crbug.com/1424250.
IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, MojoCapabilityControl_LoosenMode) {}

// Test that prerenders triggered by speculation rules are canceled when a
// background timeout timer is fired.
void PrerenderBrowserTest::TestCancelPrerendersWhenTimeout(
    std::vector<Visibility> visibility_transitions) {}

IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest,
                       CancelPrerendersWhenTimeout_Hidden) {}

IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest,
                       CancelPrerendersWhenTimeout_Occluded) {}

IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest,
                       CancelPrerendersWhenTimeout_OccludedHidden) {}

IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest,
                       CancelPrerendersWhenTimeout_OccludedVisibleHidden) {}

// Test that a PrerenderHost triggered by embedder is canceled when it times out
// in the background.
void PrerenderBrowserTest::TestCancelOnlyEmbedderTriggeredPrerenderWhenTimeout(
    std::vector<Visibility> visibility_transitions) {}

IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest,
                       CancelOnlyEmbedderTriggeredPrerenderWhenTimeout_Hidden) {}

IN_PROC_BROWSER_TEST_F(
    PrerenderBrowserTest,
    CancelOnlyEmbedderTriggeredPrerenderWhenTimeout_Occluded) {}

IN_PROC_BROWSER_TEST_F(
    PrerenderBrowserTest,
    CancelOnlyEmbedderTriggeredPrerenderWhenTimeout_OccludedHidden) {}

IN_PROC_BROWSER_TEST_F(
    PrerenderBrowserTest,
    CancelOnlyEmbedderTriggeredPrerenderWhenTimeout_OccludedVisibleHidden) {}

// Test that the timers for PrerenderHost timeout is reset when the
// hidden/occluded page gets visible.
void PrerenderBrowserTest::TestTimerResetWhenPageGoBackToForeground(
    Visibility visibility) {}

IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest,
                       TimerResetWhenPageGoBackToForeground_Hidden) {}

IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest,
                       TimerResetWhenPageGoBackToForeground_Occluded) {}

// Test that a PrerenderHost in a triggered by speculation rules with
// "target=_blank" are canceled when it times out in the background .
void PrerenderBrowserTest::TestCancelPrerenderWithTargetBlankWhenTimeout(
    Visibility visibility) {}

IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest,
                       CancelPrerenderWithTargetBlankWhenTimeout_Hidden) {}

IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest,
                       CancelPrerenderWithTargetBlankWhenTimeout_Occluded) {}

enum class SSLPrerenderTestErrorBlockType {};

std::string SSLPrerenderTestErrorBlockTypeToString(
    const testing::TestParamInfo<SSLPrerenderTestErrorBlockType>& info) {}

class SSLPrerenderBrowserTest
    : public testing::WithParamInterface<SSLPrerenderTestErrorBlockType>,
      public PrerenderBrowserTest {};

INSTANTIATE_TEST_SUITE_P();

// For a prerendering navigation request, if the server requires a client
// certificate or responds to the request with an invalid certificate, the
// prernedering should be canceled.
IN_PROC_BROWSER_TEST_P(SSLPrerenderBrowserTest,
                       CertificateValidation_Navigation) {}

// For a prerendering subresource request, if the server requires a client
// certificate or responds to the request with an invalid certificate, the
// prernedering should be canceled.
IN_PROC_BROWSER_TEST_P(SSLPrerenderBrowserTest,
                       CertificateValidation_Subresource) {}

// Tests that prerendering will be cancelled if the server asks for client
// certificates or responds with an expired certificate, even if the main
// resource request is intercepted and sent by a service worker.
IN_PROC_BROWSER_TEST_P(SSLPrerenderBrowserTest,
                       CertificateValidation_SWMainResource) {}

// Tests that prerendering will be cancelled if the server asks for client
// certificates or responds with an expired certificate, even if the subresource
// request is intercepted by a service worker.
IN_PROC_BROWSER_TEST_P(SSLPrerenderBrowserTest,
                       CertificateValidation_SWSubResource) {}

// Tests for feature restrictions in prerendered pages =========================

// Tests that window.open() in a prerendering page fails.
IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, FeatureRestriction_WindowOpen) {}

IN_PROC_BROWSER_TEST_P(PrerenderTargetAgnosticBrowserTest,
                       RenderFrameHostLifecycleState) {}

// Test that prerender activation is deferred and resumed after the ongoing
// (in-flight) main-frame navigation in the prerendering frame tree commits.
IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest,
                       SupportActivationWithOngoingMainFrameNavigation) {}

// TODO(crbug.com/40170624): Now the File System Access API is not
// supported on Android. Enable this browser test after
// https://crbug.com/1011535 is fixed.
#if BUILDFLAG(IS_ANDROID)
#define MAYBE_DeferPrivateOriginFileSystem
#else
#define MAYBE_DeferPrivateOriginFileSystem
#endif

// Tests that access to the origin private file system via the File System
// Access API is deferred until activating the prerendered page.
IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest,
                       MAYBE_DeferPrivateOriginFileSystem) {}

// Tests that DocumentUserData object is not cleared on activating a
// prerendered page.
IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, DocumentUserData) {}

// Tests that executing the GamepadMonitor API on a prerendering before
// navigating to the prerendered page causes cancel prerendering.
// This test cannot be a web test because web tests handles the GamepadMonitor
// interface on the renderer side. See GamepadController::Install().
IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, GamepadMonitorCancelPrerendering) {}

// TODO(crbug.com/40178939) LaCrOS binds the HidManager interface, which
// might be required by Gamepad Service, in a different way. Disable this test
// before figuring out how to set the test context correctly.
#if !BUILDFLAG(IS_CHROMEOS_LACROS)
// Tests that requesting to bind the GamepadMonitor interface after the
// prerenderingchange event dispatched does not cancel prerendering.
// This test cannot be a web test because web tests handles the GamepadMonitor
// interface on the renderer side. See GamepadController::Install().
IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, GamepadMonitorAfterNavigation) {}
#endif  // !BUILDFLAG(IS_CHROMEOS_LACROS)

// Tests that accessing the clipboard via the execCommand API fails because the
// page does not has any user activation.
IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, ClipboardByExecCommandFail) {}

void LoadAndWaitForPrerenderDestroyed(test::PrerenderTestHelper* helper,
                                      const GURL prerendering_url,
                                      const std::string& target_hint) {}

#if BUILDFLAG(ENABLE_PPAPI)
// Tests that we will cancel the prerendering if the prerendering page attempts
// to use plugins.
//
// TODO(crbug.com/40180674): This does not cover embedders that override
// `ContentRendererClient::OverrideCreatePlugin()` (such as for Chrome's PDF
// viewer), as cancellation depends on the renderer attempting to bind
// `content::mojom::PepperHost`.
IN_PROC_BROWSER_TEST_P(PrerenderTargetAgnosticBrowserTest,
                       PluginsCancelPrerendering) {
  const GURL kInitialUrl = GetUrl("/empty.html");

  // Navigate to an initial page.
  ASSERT_TRUE(NavigateToURL(shell(), kInitialUrl));

  LoadAndWaitForPrerenderDestroyed(
      prerender_helper(), GetUrl("/prerender/page-with-embedded-plugin.html"),
      GetTargetHint());
  ExpectFinalStatusForSpeculationRule(PrerenderFinalStatus::kMojoBinderPolicy);
  histogram_tester().ExpectUniqueSample(
      "Prerender.Experimental.PrerenderCancelledInterface.SpeculationRule",
      PrerenderCancelledInterface::kUnknown, 1);
  histogram_tester().ExpectUniqueSample(
      "Prerender.Experimental.PrerenderCancelledUnknownInterface."
      "SpeculationRule",
      InterfaceNameHasher(mojom::PepperHost::Name_), 1);

  LoadAndWaitForPrerenderDestroyed(
      prerender_helper(), GetUrl("/prerender/page-with-object-plugin.html"),
      GetTargetHint());
  histogram_tester().ExpectUniqueSample(
      "Prerender.Experimental.PrerenderHostFinalStatus.SpeculationRule",
      PrerenderFinalStatus::kMojoBinderPolicy, 2);
  histogram_tester().ExpectUniqueSample(
      "Prerender.Experimental.PrerenderCancelledInterface.SpeculationRule",
      PrerenderCancelledInterface::kUnknown, 2);
  histogram_tester().ExpectUniqueSample(
      "Prerender.Experimental.PrerenderCancelledUnknownInterface."
      "SpeculationRule",
      InterfaceNameHasher(mojom::PepperHost::Name_), 2);

  // Run JavaScript code to inject a new iframe to load a page, and see if it
  // correctly runs and results in making a navigation request in the iframe. If
  // the initiator is still working normally after prerendering cancellation,
  // this request should arrive.
  RenderFrameHostImpl* main_frame_host = current_frame_host();
  EXPECT_TRUE(AddTestUtilJS(main_frame_host));
  EXPECT_TRUE(ExecJs(main_frame_host, "add_iframe_async('/title1.html')",
                     EvalJsOptions::EXECUTE_SCRIPT_NO_RESOLVE_PROMISES));
  WaitForRequest(GetUrl("/title1.html"), 1);
}
#endif  // BUILDFLAG(ENABLE_PPAPI)

#if BUILDFLAG(IS_ANDROID)
// On Android the Notification constructor throws an exception regardless of
// whether the page is being prerendered.
// Tests that we will get the exception from the prerendering if the
// prerendering page attempts to use notification.
IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, NotificationConstructorAndroid) {
  const GURL kInitialUrl = GetUrl("/empty.html");
  const GURL kPrerenderingUrl = GetUrl("/empty.html?prerender");

  // Navigate to an initial page.
  ASSERT_TRUE(NavigateToURL(shell(), kInitialUrl));

  // Make a prerendered page.
  int host_id = AddPrerender(kPrerenderingUrl);
  auto* prerender_render_frame_host = GetPrerenderedMainFrameHost(host_id);

  // Create the Notification and fail.
  EXPECT_EQ(false, EvalJs(prerender_render_frame_host, R"(
    (() => {
      try { new Notification('My Notification'); return true;
      } catch(e) { return false; }
    })();
  )"));
}
#endif  // BUILDFLAG(IS_ANDROID)

// TODO(crbug.com/40184233): Make a WPT when we have a stable way to wait
// cancellation runs.
IN_PROC_BROWSER_TEST_P(PrerenderTargetAgnosticBrowserTest, DownloadByScript) {}

IN_PROC_BROWSER_TEST_P(PrerenderTargetAgnosticBrowserTest,
                       DownloadInMainFrame) {}

IN_PROC_BROWSER_TEST_P(PrerenderTargetAgnosticBrowserTest, DownloadInSubframe) {}

// The viewport meta tag is only enabled on Android.
#if BUILDFLAG(IS_ANDROID)
namespace {

// Used to observe the viewport change in the WebContents.
class TestViewportWebContentsObserver : public WebContentsObserver {
 public:
  TestViewportWebContentsObserver(WebContents* web_contents,
                                  blink::mojom::ViewportFit wanted_value)
      : WebContentsObserver(web_contents), wanted_value_(wanted_value) {}

  TestViewportWebContentsObserver(const TestViewportWebContentsObserver&) =
      delete;
  TestViewportWebContentsObserver& operator=(
      const TestViewportWebContentsObserver&) = delete;

  // WebContentsObserver implementation.
  void ViewportFitChanged(blink::mojom::ViewportFit value) override {
    value_ = value;
    if (waiting_for_wanted_value_ && value == wanted_value_) {
      std::move(waiting_for_wanted_value_).Run();
    }
  }

  void WaitForWantedValue() {
    if (value_.has_value() && value_.value() == wanted_value_) {
      return;
    }
    base::RunLoop loop;
    waiting_for_wanted_value_ = loop.QuitClosure();
    loop.Run();
  }

 private:
  base::OnceClosure waiting_for_wanted_value_;
  std::optional<blink::mojom::ViewportFit> value_;
  const blink::mojom::ViewportFit wanted_value_;
};

}  // namespace

// Tests that the viewport-fit property works well on prerendering page:
// * The property in prerendering page shouldn't affect the primary page.
// * After activating the prerendered page, WebContents's viewport property can
//   be updated.
IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, ViewportFit) {
  const GURL kInitialUrl = GetUrl("/prerender/viewport.html");
  const GURL kPrerenderingUrl = GetUrl("/prerender/viewport.html?prerendering");

  // Navigate to an initial page.
  ASSERT_TRUE(NavigateToURL(shell(), kInitialUrl));
  int host_id = AddPrerender(kPrerenderingUrl);
  test::PrerenderHostObserver host_observer(*web_contents(), host_id);
  RenderFrameHostImpl* prerender_rfh = GetPrerenderedMainFrameHost(host_id);
  RenderFrameHostImpl* primary_rfh = web_contents_impl()->GetPrimaryMainFrame();

  {
    // Set viewport-fit property in the primary page and the prerendering page.
    // Prerendering shouldn't be cancelled, nor should its property affect the
    // corresponding WebContents's property.
    TestViewportWebContentsObserver observer(web_contents_impl(),
                                             blink::mojom::ViewportFit::kCover);
    EXPECT_TRUE(ExecJs(prerender_rfh, "setViewportFit('contain')"));
    EXPECT_TRUE(ExecJs(primary_rfh, "setViewportFit('cover')"));
    web_contents_impl()->FullscreenStateChanged(
        primary_rfh, true, blink::mojom::FullscreenOptions::New());
    observer.WaitForWantedValue();
  }
  {
    // After the prerendering page is activated, the WebContents's property
    // should be updated.
    TestViewportWebContentsObserver observer(
        web_contents_impl(), blink::mojom::ViewportFit::kContain);
    prerender_helper()->NavigatePrimaryPage(kPrerenderingUrl);
    web_contents_impl()->FullscreenStateChanged(
        prerender_rfh, true, blink::mojom::FullscreenOptions::New());
    observer.WaitForWantedValue();
  }
  EXPECT_TRUE(host_observer.was_activated());
}
#endif  // BUILDFLAG(IS_ANDROID)

// End: Tests for feature restrictions in prerendered pages ====================

// Tests prerendering for low-end devices.
class PrerenderLowMemoryBrowserTest : public PrerenderBrowserTest {};

// Tests that prerendering doesn't run for low-end devices.
IN_PROC_BROWSER_TEST_F(PrerenderLowMemoryBrowserTest, NoPrerender) {}

class PrerenderSequentialPrerenderingBrowserTest : public PrerenderBrowserTest {};

namespace {

// Records all the navigation start and finish events until the navigation to
// `target_url` finished.
class SequentialPrerenderObserver : public WebContentsObserver {};

}  // namespace

// Tests that multiple prerenderings should be enqueued and the pending request
// starts right after the previous prerender calls DidFinishNavigation.
IN_PROC_BROWSER_TEST_F(PrerenderSequentialPrerenderingBrowserTest,
                       SequentialPrerendering) {}

// Tests that a cancelled request in the pending queue is skipped and the next
// prerender starts.
IN_PROC_BROWSER_TEST_F(PrerenderSequentialPrerenderingBrowserTest,
                       SkipCancelledPrerenderAndStartNextPrerender) {}

// Test to make sure that the completion of iframe navigation in a prerendering
// page doesn't start another pending prerender request.
IN_PROC_BROWSER_TEST_F(
    PrerenderSequentialPrerenderingBrowserTest,
    IframeNavigationFinishDontDisruptPrerenderNavigationFinish) {}

// Tests that if PrerenderHostRegistry is attempting to activate a pending
// prerender host, it will be successfully canceled with the final status of
// `kActivatedBeforeStarted`.
IN_PROC_BROWSER_TEST_F(PrerenderSequentialPrerenderingBrowserTest,
                       ActivateBeforePrerenderStarts) {}

// Test that if the 5 URLs are specified in the speculation rule while only 4
// prerenders are allowed, the 5th prerender should be cancelled.
IN_PROC_BROWSER_TEST_F(PrerenderSequentialPrerenderingBrowserTest,
                       ExceedTheRequestNumberLimit) {}

// Test that the requests from embedder are handled immediately regardless of
// the requests from speculation rules.
IN_PROC_BROWSER_TEST_F(PrerenderSequentialPrerenderingBrowserTest,
                       EmbedderPrerenderHandledImmediately) {}

// Test that hosts in the embedder blocklist are not prerendered.
IN_PROC_BROWSER_TEST_F(PrerenderSequentialPrerenderingBrowserTest,
                       EmbedderHostBlocklisted) {}

// Tests that if the running prerender is cancelled by
// PrerenderHostRegistry::CancelHost(), the next pending prerender starts its
// navigation.
IN_PROC_BROWSER_TEST_F(PrerenderSequentialPrerenderingBrowserTest,
                       RunningHostCancellationStartPendingPrerender) {}

// Tests that if the running prerender is cancelled by
// PrerenderHostRegistry::CancelHosts(), the next pending prerender
// starts its navigation.
IN_PROC_BROWSER_TEST_F(PrerenderSequentialPrerenderingBrowserTest,
                       SpeculationRulesUpdateStartPendingPrerender) {}

// Test that a pending prerender should have the
// `PreloadingTriggeringOutcome::kTriggeredButPending`.
IN_PROC_BROWSER_TEST_F(PrerenderSequentialPrerenderingBrowserTest,
                       PreloadingTriggeringOutcomeForPendingPrerender) {}

// Test that when the running prerender is destroyed due to the activation of
// another already prerendered page, other pending prerender's outcome is
// recorded as `kTriggeredButPending`.
IN_PROC_BROWSER_TEST_F(
    PrerenderSequentialPrerenderingBrowserTest,
    PreloadingTriggeringOutcomeForStartingPrerenderBeforeDestruction) {}

// Test that all the prerender hosts except the one to be activated are
// cancelled regardless of their status right after the PrerenderHostRegistry
// receives the activation request.
IN_PROC_BROWSER_TEST_F(PrerenderSequentialPrerenderingBrowserTest,
                       CancelAllPrerenderUponActivationRequestArrival) {}

// Tests that prerendering in a new tab multiple times and activating one of
// them succeed.
IN_PROC_BROWSER_TEST_F(PrerenderSequentialPrerenderingBrowserTest,
                       MultipleNewTabPrerendering) {}

// Test that the prerender request is handled and stored regardless of the
// initial visibility of the current tab, and when the current tab goes
// background (in the cases where HIDDEN or OCCLUDED is specified by
// `next_visibility`) then the prerender sequence is terminated, and when
// the current tab gets visible then we start the next prerender if we have some
// pending prerender hosts. Note that if the initial visibility is background,
// there is still one prerender allowed to be running.
void PrerenderSequentialPrerenderingBrowserTest::
    TestSequentialPrerenderingVisibilityStateTransition(
        Visibility initial_visibility,
        Visibility next_visibility) {}

IN_PROC_BROWSER_TEST_F(PrerenderSequentialPrerenderingBrowserTest,
                       PrerenderInBackground_InitialyVisible_Hidden) {}

IN_PROC_BROWSER_TEST_F(PrerenderSequentialPrerenderingBrowserTest,
                       PrerenderInBackground_InitialyVisible_Occluded) {}

IN_PROC_BROWSER_TEST_F(PrerenderSequentialPrerenderingBrowserTest,
                       PrerenderInBackground_InitialyOccluded_Hidden) {}

IN_PROC_BROWSER_TEST_F(PrerenderSequentialPrerenderingBrowserTest,
                       PrerenderInBackground_InitialyOccluded_Occluded) {}

IN_PROC_BROWSER_TEST_F(PrerenderSequentialPrerenderingBrowserTest,
                       PrerenderInBackground_InitialyHidden_Hidden) {}

IN_PROC_BROWSER_TEST_F(PrerenderSequentialPrerenderingBrowserTest,
                       PrerenderInBackground_InitialyHidden_Occluded) {}

IN_PROC_BROWSER_TEST_F(PrerenderSequentialPrerenderingBrowserTest,
                       PrerenderInBackground_InitialyHidden_Visible) {}

IN_PROC_BROWSER_TEST_F(PrerenderSequentialPrerenderingBrowserTest,
                       PrerenderWhenInitiatorInBackground_Queue_Processing) {}

IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest,
                       IsInactiveAndDisallowActivationCancelsPrerendering) {}

// Make sure input events are routed to the primary FrameTree not the prerender
// one. See https://crbug.com/1197136
IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, InputRoutedToPrimaryFrameTree) {}

IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, VisibilityWhilePrerendering) {}

// Tests that prerendering doesn't affect WebContents::GetTitle().
IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, TitleWhilePrerendering) {}

// Tests that WebContentsObserver::TitleWasSet is not dispatched when title is
// set during prerendering, but is later dispatched after activation.
IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, TitleWasSetWithPrerendering) {}

// Test that the prerender request from embedder to non-HTTP(S) scheme URL
// should fail because `PrerenderNavigationThrottle` discards the request. This
// is a regression test for https://crbug.com/1361210.
IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, EmbedderPrerenderToNonHttpUrl) {}

// Ensures WebContents::OpenURL targeting a frame in a prerendered host will
// successfully navigate that frame.
IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, OpenURLInPrerenderingFrame) {}

// Ensure that WebContentsObserver::DidFailLoad is not invoked and cancels
// prerendering when invoked on the prerendering main frame.
IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, DidFailLoadCancelsPrerendering) {}

class DidFailLoadWebContentsObserver : public WebContentsObserver {};

// Ensure that RenderFrameHost::DidFailLoad on subframes don't cancel
// prerendering. This happens when JavaScript calls `window.stop()` in a
// frame, for instance.
IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest,
                       DidFailLoadSubframesDoesNotCancelPrerendering) {}

// Ensure that RenderFrameHost::DidFailLoad on the main frame cancels
// prerendering. This happens when JavaScript calls `window.stop()` in the
// main frame, for instance.
IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest,
                       DidFailLoadMainFrameCancelsPrerendering) {}

// Ensures WebContents::OpenURL with a cross-origin URL targeting a frame in a
// prerendered host will successfully navigate that frame, though it should be
// deferred until activation.
IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest,
                       OpenURLCrossOriginInPrerenderingFrame) {}

// Test that the main frame navigation after the initial prerender navigation
// when the activation has already started doesn't cancel an ongoing
// prerendering.
// Testing steps:
// 1. prerender navigation starts/finishes
// 2. activation starts and suspends on CommitDeferringCondition
// 3. navigation in the prerendered page starts
// 4. navigation in the prerendered page finishes
// 5. activation resumes/finishes
IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest,
                       MainFrameNavigationDuringActivation) {}

// Test that a main frame navigation after the initial prerender navigation
// doesn't cancel an ongoing prerendering. The main frame navigation runs
// concurrent with the activation.
// 1. prerender navigation starts/finishes
// 2. activation starts and suspends on CommitDeferringCondition
// 3. navigation in the prerendered page starts
// 4. activation resumes
// 5. navigation in the prerendered page finishes
// 6. activation finishes
IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest,
                       MainFrameNavigationConcurrentWithActivation) {}

// Test that a main frame navigation after the initial prerender navigation and
// the activation is resumed cancels prerendering. This is the edge case that
// PrerenderCommitDeferringCondition posts a task to resume activation
// (https://source.chromium.org/chromium/chromium/src/+/main:content/browser/preloading/prerender/prerender_commit_deferring_condition.cc;l=105-106;drc=86ba45ef0be48fc81656da31dd4952857963485c)
// and a main frame navigation starts before activation is completed.
// 1. prerender navigation starts/finishes
// 2. activation starts and suspends on CommitDeferringCondition
// 3. navigation in the prerendered page starts
// 4. activation resumes
// 5. navigation in the prerendered page finishes
// 6. another navigation in the prerendered page starts but the server never
//    respond to the navigation
// 7. activation is canceled
IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest,
                       MainFrameNavigationAfterActivationIsResumed) {}

// Test the following scenario: a prerender initial navigation is pending and an
// activation navigation is deferred due to that, and then if prerender is
// canceled, the activation navigation will fall back to a normal navigation
// with no crash and hang.
IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest,
                       CancelPrerenderWhenDeferringActivationNavigation) {}

// Test that WebContentsObserver::DidFinishLoad is not invoked when the page
// gets loaded while prerendering but it is deferred and invoked on prerender
// activation.
IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest,
                       DidFinishLoadInvokedAfterActivation) {}

// Test that WebContentsObserver::DidFinishLoad is not invoked when the page
// gets loaded while prerendering but it is deferred and invoked on prerender
// activation for both main and sub-frames.
IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest,
                       DidFinishLoadInvokedAfterActivationWithSubframes) {}

// Test that WebContentsObserver::DOMContentLoaded is not invoked while
// prerendering but it is deferred and invoked on prerender activation for both
// main and sub-frames.
IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest,
                       DOMContentLoadedInvokedAfterActivationWithSubframes) {}

// Test that WebContentsObserver::DocumentOnLoadCompletedInPrimaryMainFrame is
// not invoked when the page gets loaded while prerendering but it is deferred
// and invoked on prerender activation.
IN_PROC_BROWSER_TEST_F(
    PrerenderBrowserTest,
    DocumentOnLoadCompletedInPrimaryMainFrameInvokedAfterActivation) {}

// Test that WebContentsObserver::PrimaryMainDocumentElementAvailable is not
// invoked when the page gets loaded while prerendering but it is deferred and
// invoked on prerender activation.
IN_PROC_BROWSER_TEST_F(
    PrerenderBrowserTest,
    PrimaryMainDocumentElementAvailableInvokedAfterActivation) {}

// Test that WebContentsObserver::LoadProgressChanged is not invoked when the
// page gets loaded while prerendering but is invoked on prerender activation.
// Check that LoadProgressChanged is only called once for
// blink::kFinalLoadProgress if the prerender page completes loading on
// activation.
IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest,
                       LoadProgressChangedInvokedOnActivation) {}

// Test the dispatch order of various load events on prerender activation.
IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, OrderingOfDifferentLoadEvents) {}

// Tests that cross-origin subframe navigations in a prerendered page are
// deferred even if they start after the a navigation starts that will
// attempt to activate the prerendered page.
//
// Regression test for https://crbug.com/1190262.
IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest,
                       CrossOriginSubframeNavigationDuringActivation) {}

// Tests WebContents::OpenURL to a frame in a prerendered page when a
// navigation that will attempt to activate the page has already started. The
// subframe navigation should succeed.
IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest,
                       OpenURLInSubframeDuringActivation) {}

// Tests that loading=lazy doesn't prevent image load in a prerendered page.
IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, LazyLoading) {}

IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest,
                       SessionStorageAfterBackNavigation_NoProcessReuse) {}

IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest,
                       SessionStorageAfterBackNavigation_KeepInitialProcess) {}

// Tests that prerender whose target_hint is "_blank" is using the same session
// storage across prerender navigations, and the initiator doesn't share the
// same storage.
IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest,
                       SessionStorage_TargetBlank_WithTargetHintBlank) {}

// Test if the host is abandoned when the renderer page crashes.
IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, AbandonIfRendererProcessCrashes) {}

// Test if the host is abandoned when the renderer page is killed.
IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, AbandonIfRendererProcessIsKilled) {}

// Test if the host is abandoned when the primary main page that triggers a
// prerendering is killed.
IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest,
                       AbandonIfPrimaryMainFrameRendererProcessIsKilled) {}

class PrerenderBackForwardCacheBrowserTest : public PrerenderBrowserTest {};

IN_PROC_BROWSER_TEST_F(PrerenderBackForwardCacheBrowserTest,
                       SessionStorageAfterBackNavigation) {}

#if !BUILDFLAG(IS_ANDROID)
// The out-of-process StorageService is not implemented on Android. Also as
// commented below, test_api->CrashNow() won't work on x86 and x86_64 Android.

class PrerenderRestartStorageServiceBrowserTest : public PrerenderBrowserTest {};

IN_PROC_BROWSER_TEST_F(PrerenderRestartStorageServiceBrowserTest,
                       RestartStorageServiceBeforePrerendering) {}

IN_PROC_BROWSER_TEST_F(PrerenderRestartStorageServiceBrowserTest,
                       RestartStorageServiceWhilePrerendering) {}
#endif

// Make sure that we can deal with the speculative RFH that is created during
// the activation navigation.
// TODO(crbug.com/40174053): We should try to avoid creating the
// speculative RFH (redirects allowing). Once that is done we should either
// change this test (if redirects allowed) or remove it completely.
IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, SpeculationRulesScript) {}

class PrerenderEagernessBrowserTest : public PrerenderBrowserTest {};

namespace {

class PreloadingDeciderObserverForPrerenderTesting
    : public PreloadingDeciderObserverForTesting {};

}  // namespace

// Tests speculation rules prerendering where the eagerness is "eager".
// The default eagerness of list rules is "eager", so its behavior should be
// same to normal speculation rules prerendering.
IN_PROC_BROWSER_TEST_F(PrerenderEagernessBrowserTest, kEager) {}

// Tests speculation rules prerendering where the eagerness is "moderate".
IN_PROC_BROWSER_TEST_F(PrerenderEagernessBrowserTest, kModerate) {}

// Tests speculation rules prerendering where the eagerness is "conservative".
IN_PROC_BROWSER_TEST_F(PrerenderEagernessBrowserTest, kConservative) {}

// TODO(crbug.com/40275452): These tests are turned off on Fuchsia and iOS
// tentatively because pointer simulation on them doesn't work properly on this
// test.
#if !BUILDFLAG(IS_FUCHSIA) && !BUILDFLAG(IS_IOS)
// Tests the metrics
// Prerender.Experimental.ReceivedPrerendersPerPrimaryPageChangedCount2
// correctly records the number of prerenders by each category per primary page
// changed.
IN_PROC_BROWSER_TEST_F(PrerenderEagernessBrowserTest,
                       ReceivedPrerendersPerPrimaryPageChangedCount) {}

IN_PROC_BROWSER_TEST_F(PrerenderEagernessBrowserTest,
                       NonEagerPrerendersCanBeRetriggeredAfterTimeout) {}

class PrerenderNewLimitAndSchedulerBrowserTest
    : public PrerenderEagernessBrowserTest,
      public testing::WithParamInterface<std::string> {};

INSTANTIATE_TEST_SUITE_P(All,
                         PrerenderNewLimitAndSchedulerBrowserTest,
                         testing::Values("_self", "_blank"),
                         [](const testing::TestParamInfo<std::string>& info) {};

IN_PROC_BROWSER_TEST_P(PrerenderNewLimitAndSchedulerBrowserTest,
                       ResetForNonEagerPrerener) {}
#endif  // !BUILDFLAG(IS_FUCHSIA) && !BUILDFLAG(IS_IOS)

class PrerenderWithBackForwardCacheBrowserTest
    : public PrerenderBrowserTest,
      public testing::WithParamInterface<BackForwardCacheType> {};

INSTANTIATE_TEST_SUITE_P();

// Tests that history navigation works after activation. This runs with variaous
// BFCache configurations that may modify behavior of history navigation.
// This is a regression test for https://crbug.com/1201914.
IN_PROC_BROWSER_TEST_P(PrerenderWithBackForwardCacheBrowserTest,
                       HistoryNavigationAfterActivation) {}

// Tests that a trigger page destroys a prerendered page when it navigates
// forward and goes into the back/forward cache.
IN_PROC_BROWSER_TEST_P(PrerenderWithBackForwardCacheBrowserTest,
                       CancelOnAfterTriggerIsStoredInBackForwardCache_Forward) {}

// Tests that a trigger page destroys a prerendered page when it navigates back
// and goes into the BFCache.
IN_PROC_BROWSER_TEST_P(PrerenderWithBackForwardCacheBrowserTest,
                       CancelOnAfterTriggerIsStoredInBackForwardCache_Back) {}

class PrerenderBackForwardCacheRestorationBrowserTest
    : public PrerenderEagernessBrowserTest,
      public BackForwardCacheMetricsTestMatcher,
      public testing::WithParamInterface<blink::mojom::SpeculationEagerness> {};

INSTANTIATE_TEST_SUITE_P(
    All,
    PrerenderBackForwardCacheRestorationBrowserTest,
    testing::Values(blink::mojom::SpeculationEagerness::kEager,
                    blink::mojom::SpeculationEagerness::kModerate,
                    blink::mojom::SpeculationEagerness::kConservative),
    [](const testing::TestParamInfo<blink::mojom::SpeculationEagerness>& info) {};

// Test whether speculation rules prerendering is processed again on pages
// restored from BFCache via forward navigation.
// When the eagerness is kEager(default), speculation rules prerendering will no
// longer be processed after restoration.
// For non-eager cases (kModerate, kConservative), candidates are stored between
// restoration unless they were triggered by user action (This test scenario
// reproduces only this case). However, once after processed by user action,
// then they will not be processed again until they are retriggered
// (crbug.com/1449163 for more information).
IN_PROC_BROWSER_TEST_P(PrerenderBackForwardCacheRestorationBrowserTest,
                       RestoredViaForwardNavigation) {}

// Test whether speculation rules prerendering is processed again on pages
// restored from BFCache via backward navigation.
// When the eagerness is kEager(default), speculation rules prerendering will no
// longer be processed after restoration.
// For non-eager cases (kModerate, kConservative), candidates are stored between
// restoration unless they were triggered by user action. However, once after
// processed by user action, then they will not be processed again until they
// are retriggered (crbug.com/1449163 for more information).
IN_PROC_BROWSER_TEST_P(PrerenderBackForwardCacheRestorationBrowserTest,
                       RestoredViaBackwardNavigation) {}

// Tests that PrerenderHostRegistry can hold up to two prerendering for the
// prerender embedders it receives.
IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, StartByEmbeddersMultipleTimes) {}

// Tests that PrerenderHostRegistry can hold up to two prerendering for the
// prerender speculation rule and prerender embedders in total.
IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest,
                       StartByEmbeddersAndSpeculationRulesMultipleTimes) {}

class MultiplePrerendersBrowserTest : public PrerenderBrowserTest {};

class MultiplePrerendersWithLimitedMemoryBrowserTest
    : public MultiplePrerendersBrowserTest {};

// Tests that moderate-level memory pressure doesn't cancel prerendering on
// trigger.
IN_PROC_BROWSER_TEST_F(MultiplePrerendersBrowserTest,
                       MemoryPressureOnTrigger_Moderate) {}

// Tests that critical-level memory pressure cancels prerendering on trigger.
IN_PROC_BROWSER_TEST_F(MultiplePrerendersBrowserTest,
                       MemoryPressureOnTrigger_Critical) {}

// Tests that moderate-level memory pressure doesn't cancel prerendering after
// triggered.
IN_PROC_BROWSER_TEST_F(MultiplePrerendersBrowserTest,
                       MemoryPressureAfterTriggered_Moderate) {}

// Tests that critical-level memory pressure cancels prerendering after
// triggered.
IN_PROC_BROWSER_TEST_F(MultiplePrerendersBrowserTest,
                       MemoryPressureAfterTriggered_Critical) {}

// Tests that PrerenderHostRegistry only starts prerender speculation rules
// up to `max_num_of_running_speculation_rules` defined by a Finch param.
IN_PROC_BROWSER_TEST_F(MultiplePrerendersBrowserTest,
                       AddSpeculationRulesMultipleTimes) {}

// Tests that PrerenderHostRegistry can start prerendering when the DevTools is
// open even if the acceptable percent of the system memory is set to 0.
IN_PROC_BROWSER_TEST_F(MultiplePrerendersWithLimitedMemoryBrowserTest,
                       DevToolsOverride) {}

// Tests that cross-site urls cannot be prerendered.
IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, SkipCrossSitePrerender) {}

// Tests that same-site cross-origin navigation by speculation rules is not
// allowed with the feature enabled but without opt-in.
IN_PROC_BROWSER_TEST_F(
    PrerenderBrowserTest,
    SameSiteCrossOriginNavigationSpeculationRulesWithoutOptInHeader) {}

// Tests that same-site cross-origin redirection by speculation rules with the
// feature enabled but without opt-in.
IN_PROC_BROWSER_TEST_F(
    PrerenderBrowserTest,
    SameSiteCrossOriginRedirectionSpeculationRulesWithoutOptInHeader) {}

// Tests that same-site cross-origin redirection with credentialed prerender by
// speculation rules with the feature enabled but the redirected page without
// opt-in. This test verifies a case which is a.test -> a.test (credentialed
// prerender) -> b.a.test (no credentialed prerender).
IN_PROC_BROWSER_TEST_F(
    PrerenderBrowserTest,
    SameSiteCrossOriginCredentialedPrerenderRedirectionSpeculationRulesWithoutOptInHeader) {}

// Tests that same-site cross-origin redirection with credentialed prerender by
// speculation rules with the feature enabled but the redirected page without
// opt-in. This test verifies a case which is a.test -> b.a.test (credentialed
// prerender) -> b.a.test (no credentialed prerender)
IN_PROC_BROWSER_TEST_F(
    PrerenderBrowserTest,
    SameSiteCrossOriginCredentialedPrerenderRedirectionSpeculationRulesWithoutOptInHeader2) {}

// Tests that same-site cross-origin navigation redirecting back to same-origin
// without opt-in.
IN_PROC_BROWSER_TEST_F(
    PrerenderBrowserTest,
    SameSiteCrossOriginNavigationBackToSameOriginWithoutOptInHeader) {}

// Tests that cross-origin redirection in multiple redirections by speculation
// rules should be canceled.
IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest,
                       CrossSiteMultipleRedirectionSpeculationRules) {}

// Tests that same-site cross-origin navigation by speculation rules can be
// prerendered with the feature enabled.
IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest,
                       CheckSameSiteCrossOriginSpeculationRulesPrerender) {}

// Tests that same-site cross-origin redirection by speculation rules is
// allowed.
IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest,
                       SameSiteCrossOriginSpeculationRulesRedirection) {}

// Tests that multiple same-site cross-origin redirections by speculation rules
// is allowed, and only the terminal one is checked for the opt in header.
IN_PROC_BROWSER_TEST_F(
    PrerenderBrowserTest,
    SameSiteCrossOriginSpeculationRulesMultipleRedirections) {}

void PrerenderBrowserTest::TestEmbedderTriggerWithUnsupportedScheme(
    const GURL& prerendering_url) {}

IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest,
                       EmbedderTrigger_UnsupportedScheme_ViewSource) {}

IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest,
                       EmbedderTrigger_UnsupportedScheme_DataUrl) {}

IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest,
                       EmbedderTrigger_SameOriginRedirection) {}

// If there is a cross-origin url in the redirection chain, tests prerender
// should be canceled.
IN_PROC_BROWSER_TEST_F(
    PrerenderBrowserTest,
    EmbedderTrigger_CancelIfCrossOriginUrlInRedirectionChain) {}

std::unique_ptr<PrerenderHandle>
PrerenderEmbedderTriggeredCrossOriginRedirectionPage(
    WebContentsImpl& web_contents,
    const GURL& prerendering_url,
    const GURL& cross_origin_url) {}

namespace {

class FrameDisplayStateChangedObserver : public WebContentsObserver {};

}  // namespace

// Tests that FrameOwnerProperties are in sync after activation.
IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, FrameOwnerPropertiesDisplayNone) {}

IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, TriggeredPrerenderUkm) {}

// Tests that background color in a prerendered page does not affect
// the primary page.
IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, ColorSchemeDarkInNonPrimaryPage) {}

// TODO(b/335786567): Flaky on win-asan.
#if (BUILDFLAG(IS_WIN) && defined(ADDRESS_SANITIZER))
#define MAYBE_ThemeColorSchemeChangeInNonPrimaryPage
#else
#define MAYBE_ThemeColorSchemeChangeInNonPrimaryPage
#endif
// Tests that theme color in a prerendered page does not affect
// the primary page.
IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest,
                       MAYBE_ThemeColorSchemeChangeInNonPrimaryPage) {}

// Tests that text autosizer works per page.
IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest,
                       TextAutosizerInfoChangeInNonPrimaryPage) {}

// Check that the prerendered page window.name is maintained after activation.
IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest,
                       VerifyFrameNameMaintainedAfterActivation) {}

IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, ActivateWhileReloadingSubframe) {}

// Check that the inactive RFH shouldn't update UserActivation.
IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, DoNotUpdateUserActivationState) {}

// Tests that prerendering is cancelled when a mixed content subframe is
// detected.
IN_PROC_BROWSER_TEST_P(PrerenderTargetAgnosticBrowserTest, MixedContent) {}

IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, PrerenderBlockedByCspNavigateTo) {}

// Check that the Content-Security-Policy set via HTTP header applies after the
// activation. This test verifies that that the web sandbox flags value is none.
IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest,
                       ActivatePageWithCspHeaderFrameSrc) {}

// Check that the Content-Security-Policy set via HTTP header applies after the
// activation. This test verifies that that the web sandbox flags value is set
// to allow scripts.
IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest,
                       ActivatePageWithCspHeaderSandboxFlags) {}

IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, VerifyPrerenderProcessVisibility) {}

class PrerenderPurposePrefetchBrowserTest : public PrerenderBrowserTest {};

// Tests that a request for the initial prerender navigation has the
// "Purpose: prefetch" header.
// TODO(nhiroki): Move this test to WPT.
IN_PROC_BROWSER_TEST_F(PrerenderPurposePrefetchBrowserTest, InitialNavigation) {}

// Tests that a redirected request for the initial prerender navigation has the
// "Purpose: prefetch" header.
// TODO(nhiroki): Move this test to WPT.
IN_PROC_BROWSER_TEST_F(PrerenderPurposePrefetchBrowserTest,
                       RedirectionOnInitialNavigation) {}

// Tests that requests from a prerendered page have the "Purpose: prefetch"
// header.
// TODO(nhiroki): Move this test to WPT.
IN_PROC_BROWSER_TEST_F(PrerenderPurposePrefetchBrowserTest, ResourceRequests) {}

IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, EnterFullscreen) {}

namespace {
class TestJavaScriptDialogManager : public JavaScriptDialogManager,
                                    public WebContentsDelegate {};

class PrerenderWithRenderDocumentBrowserTest : public PrerenderBrowserTest {};
}  // namespace

IN_PROC_BROWSER_TEST_F(
    PrerenderWithRenderDocumentBrowserTest,
    ModalDialogShouldNotBeDismissedAfterPrerenderSubframeNavigation) {}

// Tests that NavigationHandle::GetNavigatingFrameType() returns the correct
// type in prerendering and after activation.
IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, NavigationHandleFrameType) {}

// Tests that NavigationHandle::IsRendererInitiated() returns RendererInitiated
// = true correctly.
IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest,
                       NavigationHandleIsRendererInitiatedTrue) {}

// Tests that FrameTreeNode::has_received_user_gesture_before_nav_ is not set on
// the prerendered main frame or the activated main frame when the primary main
// frame doesn't have it.
IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest,
                       HasReceivedUserGestureBeforeNavigation) {}

// Tests that FrameTreeNode::has_received_user_gesture_before_nav_ is not
// propagated from the primary main frame to the prerendered main frame but it
// is propagated to the activated main frame.
IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest,
                       HasReceivedUserGestureBeforeNavigation_Propagation) {}

IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest,
                       CancelPrerenderWhenIsOverridingUserAgentDiffers) {}

class PrerenderSpeculationRulesHoldbackBrowserTest
    : public PrerenderBrowserTest {};

IN_PROC_BROWSER_TEST_F(PrerenderSpeculationRulesHoldbackBrowserTest,
                       PrerenderHoldbackTest) {}

class PrerenderFencedFrameBrowserTest : public PrerenderBrowserTest {};

// Test that creating a fenced frame in a prerendered page is deferred until
// activation.
IN_PROC_BROWSER_TEST_F(PrerenderFencedFrameBrowserTest,
                       CreateFencedFrameInPrerenderedPage) {}

// Test that prerendering triggered by fenced frames with speculation rules is
// blocked.
IN_PROC_BROWSER_TEST_F(PrerenderFencedFrameBrowserTest,
                       PrerenderFromFencedFrame_SpeculationRules) {}

// Test that prerendering triggered by fenced frames with speculation rules
// header is blocked.
IN_PROC_BROWSER_TEST_F(PrerenderFencedFrameBrowserTest,
                       PrerenderFromFencedFrame_LinkSpeculationRules) {}

namespace {

class PrerenderWithSiteIsolationDisabledBrowserTest
    : public PrerenderBrowserTest {};

}  // namespace

// This test sets up a scenario where we swap SiteInstances during a prerender
// page's first navigation. Full site isolation is disabled for this test, but
// we dynamically isolate "b.test". The max process count is also set to 1.
//
// We initially start off with navigating the primary main frame to b.test,
// which will be assigned to a process P1.
//
// P1 ----- b.test
//
// We then add an a.test iframe, which will be assigned to a different process
// P2. This is because P1 currently hosts content from b.test, and b.test has
// been configured to require isolation from other sites.
//
// P1 ------ b.test
// P2 ------ a.test
//
// We then start prerendering b.test. This happens in two steps. In the first
// step we initialize the FrameTree and create an empty main frame that hasn't
// been navigated. This empty main frame has an empty SiteInstance (prerenders
// use an empty SiteInfo for this currently) which is assigned to P2 (in normal
// circumstances, it would be assigned to a new process but because we're above
// the process limit, it tries to reuse an existing process, and P2 is eligible
// as it currently only has the a.test iframe and a.test does not need to be
// isolated).
//
// P1 ------ b.test
// P2 ------ a.test, <empty prerender>
//
// In the second step, we navigate the prerender main frame to the prerender
// url, which is b.test. Now b.test is configured to be in an isolated process,
// so we can't reuse the current SiteInstance (as it is assigned to P1 which has
// content from a.test), and have to move it to a new process (and therefore
// have to swap the SiteInstance).
//
// P1 ------ b.test (primary), b.test (prerender)
// P2 ------ a.test
IN_PROC_BROWSER_TEST_F(PrerenderWithSiteIsolationDisabledBrowserTest,
                       ForceSiteInstanceSwapForInitialPrerenderNavigation) {}

class PrerenderClientHintsBrowserTest : public PrerenderBrowserTest {};

IN_PROC_BROWSER_TEST_F(PrerenderClientHintsBrowserTest,
                       PrerenderResponseChangesClientHintsLocally) {}

IN_PROC_BROWSER_TEST_F(PrerenderClientHintsBrowserTest,
                       ChangesToClientHintsAreDiscardIfNoActivation) {}

IN_PROC_BROWSER_TEST_F(PrerenderClientHintsBrowserTest,
                       PrimaryResponsesDoNotResetPrenderSettings) {}

// Test that changes on the viewport width of the initiator page between when to
// trigger prerendering and when to activate don't fail activation params match.
IN_PROC_BROWSER_TEST_F(PrerenderClientHintsBrowserTest, ViewPort_Width) {}

// Test that changes on the viewport height of the initiator page between when
// to trigger prerendering and when to activate don't fail activation params
// match.
IN_PROC_BROWSER_TEST_F(PrerenderClientHintsBrowserTest, ViewPort_Height) {}

void CheckExpectedCrossOriginMetrics(
    const base::HistogramTester& histogram_tester,
    PrerenderCrossOriginRedirectionMismatch mismatch_type,
    std::optional<PrerenderCrossOriginRedirectionProtocolChange>
        protocol_change) {}

// Tests PrerenderCrossOriginRedirectionMismatch.kSchemeHostPortMismatch was
// recorded when a prerendering navigaton was redireted to another origin with
// different scheme, host and port.
IN_PROC_BROWSER_TEST_F(
    PrerenderBrowserTest,
    EmbedderTrigger_CrossOriginRedirection_SchemeHostPortMismatch) {}

// Tests a prerendering navigaton goes with HTTP protocol, and being redirected
// to upgrade its protocol to HTTPS.
IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest,
                       EmbedderTrigger_CrossOriginRedirection_ProtocolUpgrade) {}

// Similar to
// CancelEmbedderTriggeredPrerenderingCrossOriginRedirection_ProtocolUpgrade,
// tests a prerendering navigaton goes with HTTPS protocol, and being redirected
// to upgrade its protocol to HTTPS.
IN_PROC_BROWSER_TEST_F(
    PrerenderBrowserTest,
    EmbedderTrigger_CrossOriginRedirection_ProtocolDowngrade) {}

// Tests that embedder triggered prerender can be redirected to the subdomain
// because they are same-site.
IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest,
                       EmbedderTrigger_CrossOriginRedirection_ToSubdomain) {}

// Tests that embedder triggered prerender can be redirected to the same site.
IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest,
                       EmbedderTrigger_CrossOriginRedirection_FromSubdomain) {}

// Tests PrerenderCrossOriginRedirectionMismatch.kHostMismatch is recorded
// when the prerendering navigation is redirected to a different domain.
IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest,
                       EmbedderTrigger_CrossOriginRedirection_DifferentDomain) {}

// Tests that prerender works with accessibility.
IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest,
                       PrerenderWithAccessibilityEnabled) {}

class UpdateTargetURLDelegate : public WebContentsDelegate {};

// Tests that text autosizer works per page.
IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, FocusChangeInPrerenderedPage) {}

// Tests that an unused RenderWidgetHost (that is owned by a RenderViewHostImpl)
// created by a prerendering FrameTree points to the primary frame tree after
// activation. Regression test for crbug.com/1324149.
IN_PROC_BROWSER_TEST_F(
    PrerenderBrowserTest,
    UnusedRenderWidgetHostFrameTreePointerUpdatedOnActivation) {}

// Tests that window.close() can cancel speculation rules.
IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, WindowClosedSpeculationRules) {}

// Tests that window.close() can cancel speculation rules whose target_hint is
// "_blank" (i.e., prerender into new tab).
IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest,
                       WindowClosedSpeculationRules_WithTargetHintBlank) {}

// Tests that Prerender is suppressed by slow network.
IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, SlowNetwork) {}

// Many of these tests navigate away from a page and then test whether the back
// navigation entry can be prerendered. This is parameterized on whether the
// navigation away from the original page is browser or renderer initiated.
class PrerenderSessionHistoryBrowserTest
    : public PrerenderBrowserTest,
      public testing::WithParamInterface<bool> {};

INSTANTIATE_TEST_SUITE_P();

// Other tests in `PrerenderSessionHistoryBrowserTest` explicitly trigger the
// prediction and the navigation. For this test, we actually simulate the back
// button press events.
IN_PROC_BROWSER_TEST_P(PrerenderSessionHistoryBrowserTest,
                       BackButtonNavigation) {}

IN_PROC_BROWSER_TEST_P(PrerenderSessionHistoryBrowserTest,
                       PredictionForEligibleBackNavigation) {}

IN_PROC_BROWSER_TEST_P(PrerenderSessionHistoryBrowserTest,
                       NoPredictionDueToBfcache) {}

IN_PROC_BROWSER_TEST_P(PrerenderSessionHistoryBrowserTest,
                       RendererNavigationAfterBackPrediction) {}

IN_PROC_BROWSER_TEST_P(PrerenderSessionHistoryBrowserTest,
                       NotEligibleForSameDocument) {}

IN_PROC_BROWSER_TEST_P(PrerenderSessionHistoryBrowserTest,
                       NotEligibleForSameSite) {}

IN_PROC_BROWSER_TEST_P(PrerenderSessionHistoryBrowserTest,
                       NotEligibleForUncached) {}

IN_PROC_BROWSER_TEST_P(PrerenderSessionHistoryBrowserTest,
                       NotEligibleForPostMethod) {}

IN_PROC_BROWSER_TEST_P(PrerenderSessionHistoryBrowserTest,
                       NotEligibleForFailedNavigation) {}

IN_PROC_BROWSER_TEST_P(PrerenderSessionHistoryBrowserTest,
                       NotEligibleForNonHttpScheme) {}

// Returns whether the two given windows can script each other.
// Assumes `opener` has a variable named `newWindow` which refers to `openee`.
bool IsScriptable(WebContentsImpl* opener, WebContentsImpl* openee) {}

IN_PROC_BROWSER_TEST_P(PrerenderSessionHistoryBrowserTest,
                       NotEligibleForRelatedActiveContents) {}

IN_PROC_BROWSER_TEST_P(PrerenderSessionHistoryBrowserTest,
                       PredictAfterOpeneeDestroyed) {}

IN_PROC_BROWSER_TEST_P(PrerenderSessionHistoryBrowserTest,
                       BackNavigationOfCloneWebContents) {}

IN_PROC_BROWSER_TEST_P(
    PrerenderSessionHistoryBrowserTest,
    BackNavigationOfClonedWebContentsWithOriginalAtTargetEntry) {}

// PrerenderHosts created through speculation rules are not suitable for use in
// session history navigations. In particular, the SiteInstances would be
// mismatched.
IN_PROC_BROWSER_TEST_P(
    PrerenderSessionHistoryBrowserTest,
    BackButtonNavigationDoesNotUseSpeculationRulePrerenders) {}

class PrerenderWarmUpCompositorBrowserTest
    : public PrerenderBrowserTest,
      public testing::WithParamInterface<std::tuple<bool, bool, std::string>> {};

INSTANTIATE_TEST_SUITE_P();

// Test that the prerendering page does not crash when enabling compositor
// warming up features.
// TODO(crbug.com/41496019): Check whether the warming up is actually happening.
IN_PROC_BROWSER_TEST_P(PrerenderWarmUpCompositorBrowserTest,
                       WarmingUpCCDoesntInvokeCrashes) {}

}  // namespace content