chromium/chrome/browser/preloading/prefetch/no_state_prefetch/prerender_nostate_prefetch_browsertest.cc

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

#include <string>

#include "base/command_line.h"
#include "base/containers/contains.h"
#include "base/functional/bind.h"
#include "base/functional/callback_helpers.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/ref_counted.h"
#include "base/metrics/statistics_recorder.h"
#include "base/run_loop.h"
#include "base/strings/escape.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_split.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "base/test/bind.h"
#include "base/test/scoped_feature_list.h"
#include "base/test/simple_test_tick_clock.h"
#include "base/threading/platform_thread.h"
#include "base/timer/elapsed_timer.h"
#include "base/values.h"
#include "build/build_config.h"
#include "chrome/browser/browser_features.h"
#include "chrome/browser/browsing_data/chrome_browsing_data_remover_constants.h"
#include "chrome/browser/history/history_service_factory.h"
#include "chrome/browser/history/history_test_utils.h"
#include "chrome/browser/predictors/autocomplete_action_predictor.h"
#include "chrome/browser/predictors/autocomplete_action_predictor_factory.h"
#include "chrome/browser/preloading/chrome_preloading.h"
#include "chrome/browser/preloading/prefetch/no_state_prefetch/no_state_prefetch_test_utils.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/task_manager/task_manager_browsertest_util.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/browser_commands.h"
#include "chrome/browser/ui/browser_list.h"
#include "chrome/browser/ui/browser_window.h"
#include "chrome/browser/ui/location_bar/location_bar.h"
#include "chrome/browser/ui/tabs/tab_strip_model.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/test/base/ui_test_utils.h"
#include "components/content_settings/core/browser/cookie_settings.h"
#include "components/content_settings/core/common/features.h"
#include "components/content_settings/core/common/pref_names.h"
#include "components/embedder_support/switches.h"
#include "components/no_state_prefetch/browser/no_state_prefetch_handle.h"
#include "components/no_state_prefetch/browser/no_state_prefetch_manager.h"
#include "components/omnibox/browser/omnibox_edit_model.h"
#include "components/omnibox/browser/omnibox_view.h"
#include "components/prefs/pref_service.h"
#include "components/ukm/test_ukm_recorder.h"
#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/browsing_data_remover.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/browser/storage_partition.h"
#include "content/public/browser/web_contents.h"
#include "content/public/browser/web_contents_observer.h"
#include "content/public/common/content_features.h"
#include "content/public/common/content_switches.h"
#include "content/public/common/isolated_world_ids.h"
#include "content/public/common/result_codes.h"
#include "content/public/common/url_constants.h"
#include "content/public/test/back_forward_cache_util.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/fenced_frame_test_util.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/url_loader_interceptor.h"
#include "content/public/test/url_loader_monitor.h"
#include "net/base/features.h"
#include "net/base/load_flags.h"
#include "net/base/request_priority.h"
#include "net/cookies/cookie_store.h"
#include "net/dns/mock_host_resolver.h"
#include "net/test/embedded_test_server/request_handler_util.h"
#include "net/test/scoped_mutually_exclusive_feature_list.h"
#include "services/metrics/public/cpp/ukm_builders.h"
#include "services/network/public/cpp/features.h"
#include "services/network/public/mojom/cookie_manager.mojom.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/public/common/chrome_debug_urls.h"
#include "third_party/blink/public/common/features.h"

namespace {

const char kExpectedPurposeHeaderOnPrefetch[] =;
UkmEntry;
DestructionWaiter;
TestPrerender;
WaitForTaskManagerRows;
Preloading_Attempt;

std::string CreateServerRedirect(const std::string& dest_url) {}

// This is the public key of tools/origin_trials/eftest.key, used to validate
// origin trial tokens generated by tools/origin_trials/generate_token.py.
static constexpr char kOriginTrialPublicKeyForTesting[] =;

enum class SplitCacheTestCase {};

const struct {} kTestCaseToFeatureMapping[] =;

}  // namespace

namespace prerender {

const char k302RedirectPage[] =;
const char kPrefetchCookiePage[] =;
const char kPrefetchFromSubframe[] =;
const char kPrefetchImagePage[] =;
const char kPrefetchJpeg[] =;
const char kPrefetchLoaderPath[] =;
const char kPrefetchLoopPage[] =;
const char kPrefetchMetaCSP[] =;
const char kPrefetchNostorePage[] =;
const char kPrefetchPage[] =;
const char kPrefetchPageWithFragment[] =;
const char kPrefetchPage2[] =;
const char kPrefetchPageBigger[] =;
const char kPrefetchPageMultipleResourceTypes[] =;
const char kPrefetchPng[] =;
const char kPrefetchPng2[] =;
const char kPrefetchPngRedirect[] =;
const char kPrefetchRecursePage[] =;
const char kPrefetchResponseHeaderCSP[] =;
const char kPrefetchScript[] =;
const char kPrefetchScript2[] =;
const char kPrefetchCss[] =;
const char kPrefetchFont[] =;
const char kPrefetchDownloadFile[] =;
const char kPrefetchSubresourceRedirectPage[] =;
const char kServiceWorkerLoader[] =;
const char kHungPrerenderPage[] =;

// A navigation observer to wait on either a new load or a swap of a
// WebContents. On swap, if the new WebContents is still loading, wait for that
// load to complete as well. Note that the load must begin after the observer is
// attached.
class NavigationOrSwapObserver : public content::WebContentsObserver,
                                 public TabStripModelObserver {};

content::PreloadingFailureReason ToPreloadingFailureReasonFromFinalStatus(
    FinalStatus status) {}

// Waits for a new tab to open and a navigation or swap in it.
class NewTabNavigationOrSwapObserver : public TabStripModelObserver,
                                       public BrowserListObserver {};

class NoStatePrefetchBrowserTest
    : public test_utils::PrerenderInProcessBrowserTest {};

class NoStatePrefetchBrowserTestHttpCache
    : public NoStatePrefetchBrowserTest,
      public testing::WithParamInterface<SplitCacheTestCase> {};

class NoStatePrefetchBrowserTestHttpCacheDefaultAndAppendFrameOrigin
    : public NoStatePrefetchBrowserTest {};

// Test that the network isolation key is correctly populated during a prefetch.
IN_PROC_BROWSER_TEST_F(
    NoStatePrefetchBrowserTestHttpCacheDefaultAndAppendFrameOrigin,
    PrefetchTwoCrossOriginFrames) {}

// Checks that a page is correctly prefetched in the case of a
// <link rel=prerender> tag and the JavaScript on the page is not executed.
IN_PROC_BROWSER_TEST_F(NoStatePrefetchBrowserTest, PrefetchSimple) {}

// Checks that prefetching is not stopped forever by aggressive background load
// limits.
IN_PROC_BROWSER_TEST_F(NoStatePrefetchBrowserTest, PrefetchBigger) {}

NoStatePrefetchBrowserTestHttpCacheDefaultAndDoubleKeyed;

// Checks that a page load following a prefetch reuses preload-scanned resources
// and link rel 'prerender' main resource from cache without failing over to
// network.
IN_PROC_BROWSER_TEST_P(NoStatePrefetchBrowserTestHttpCacheDefaultAndDoubleKeyed,
                       LoadAfterPrefetch) {}

// Checks that a page load following a cross origin prefetch reuses
// preload-scanned resources and link rel 'prerender' main resource
// from cache without failing over to network.
IN_PROC_BROWSER_TEST_P(NoStatePrefetchBrowserTestHttpCacheDefaultAndDoubleKeyed,
                       LoadAfterPrefetchCrossOrigin) {}

IN_PROC_BROWSER_TEST_P(NoStatePrefetchBrowserTestHttpCacheDefaultAndDoubleKeyed,
                       LoadAfterPrefetchCrossOriginRendererInitiated) {}

INSTANTIATE_TEST_SUITE_P();

// Checks that the expected resource types are fetched via NoState Prefetch.
IN_PROC_BROWSER_TEST_F(NoStatePrefetchBrowserTest, PrefetchAllResourceTypes) {}

// Test and Test Class for lightweight prefetch under the HTML configuration.
class HTMLOnlyNoStatePrefetchBrowserTest : public NoStatePrefetchBrowserTest {};

// Checks that the expected resource types are fetched via NoState Prefetch.
IN_PROC_BROWSER_TEST_F(HTMLOnlyNoStatePrefetchBrowserTest, PrefetchHTMLOnly) {}

// Test and Test Class for lightweight prefetch under the HTML+CSS
// configuration.
class HTMLCSSNoStatePrefetchBrowserTest : public NoStatePrefetchBrowserTest {};

// Checks that the expected resource types are fetched via NoState Prefetch.
IN_PROC_BROWSER_TEST_F(HTMLCSSNoStatePrefetchBrowserTest, PrefetchHTMLCSS) {}

// Test and Test Class for lightweight prefetch under the HTML+CSS+SyncScript
// configuration.
class HTMLCSSSyncScriptNoStatePrefetchBrowserTest
    : public NoStatePrefetchBrowserTest {};

// Checks that the expected resource types are fetched via NoState Prefetch.
IN_PROC_BROWSER_TEST_F(HTMLCSSSyncScriptNoStatePrefetchBrowserTest,
                       PrefetchHTMLCSSSyncScript) {}

// Test and Test Class for lightweight prefetch under the
// HTML+CSS+SyncScript+Font configuration.
class HTMLCSSSyncScriptFontNoStatePrefetchBrowserTest
    : public NoStatePrefetchBrowserTest {};

// Checks that the expected resource types are fetched via NoState Prefetch.
IN_PROC_BROWSER_TEST_F(HTMLCSSSyncScriptFontNoStatePrefetchBrowserTest,
                       PrefetchHTMLCSSSyncScript) {}

// Test and Test Class for lightweight prefetch under the HTML+CSS+Script
// configuration.
class HTMLCSSScriptNoStatePrefetchBrowserTest
    : public NoStatePrefetchBrowserTest {};

// Checks that the expected resource types are fetched via NoState Prefetch.
IN_PROC_BROWSER_TEST_F(HTMLCSSScriptNoStatePrefetchBrowserTest,
                       PrefetchHTMLCSSScript) {}

void GetCookieCallback(base::RepeatingClosure callback,
                       const net::CookieAccessResultList& cookie_list,
                       const net::CookieAccessResultList& excluded_cookies) {}

// Check cookie loading for prefetched pages.
IN_PROC_BROWSER_TEST_F(NoStatePrefetchBrowserTest, PrefetchCookie) {}

// Check cookie loading for a cross-domain prefetched pages.
IN_PROC_BROWSER_TEST_F(NoStatePrefetchBrowserTest, PrefetchCookieCrossDomain) {}

// Check cookie loading for a cross-domain prefetched pages.
IN_PROC_BROWSER_TEST_P(NoStatePrefetchBrowserTestHttpCacheDefaultAndDoubleKeyed,
                       PrefetchCookieCrossDomainSameSiteStrict) {}

// Check cookie loading for a same-domain prefetched pages.
IN_PROC_BROWSER_TEST_P(NoStatePrefetchBrowserTestHttpCacheDefaultAndDoubleKeyed,
                       PrefetchCookieSameDomainSameSiteStrict) {}

// Check that the LOAD_PREFETCH flag is set.
IN_PROC_BROWSER_TEST_F(NoStatePrefetchBrowserTest, PrefetchLoadFlag) {}

// Check that prefetched resources and subresources set the 'Purpose: prefetch'
// header.
IN_PROC_BROWSER_TEST_F(NoStatePrefetchBrowserTest, PurposeHeaderIsSet) {}

// Check that on normal navigations the 'Purpose: prefetch' header is not set.
IN_PROC_BROWSER_TEST_F(NoStatePrefetchBrowserTest,
                       PurposeHeaderNotSetWhenNotPrefetching) {}

// Checks the prefetch of an img tag.
IN_PROC_BROWSER_TEST_F(NoStatePrefetchBrowserTest, PrefetchImage) {}

// Checks that a cross-domain prefetching works correctly.
IN_PROC_BROWSER_TEST_F(NoStatePrefetchBrowserTest, PrefetchCrossDomain) {}

// Checks that prefetching from a cross-domain subframe works correctly.
IN_PROC_BROWSER_TEST_F(NoStatePrefetchBrowserTest,
                       PrefetchFromCrossDomainSubframe) {}

// Checks that response header CSP is respected.
IN_PROC_BROWSER_TEST_F(NoStatePrefetchBrowserTest, ResponseHeaderCSP) {}

// Checks that CSP in the meta tag cancels the prefetch.
// TODO(mattcary): probably this behavior should be consistent with
// response-header CSP. See crbug/656581.
IN_PROC_BROWSER_TEST_F(NoStatePrefetchBrowserTest, MetaTagCSP) {}

// Checks that the second prefetch request succeeds. This test waits for
// Prerender Stop before starting the second request.
IN_PROC_BROWSER_TEST_F(NoStatePrefetchBrowserTest, PrefetchMultipleRequest) {}

// Checks that a second prefetch request, started before the first stops,
// succeeds.
IN_PROC_BROWSER_TEST_F(NoStatePrefetchBrowserTest, PrefetchSimultaneous) {}

// Checks that a prefetch does not recursively prefetch.
IN_PROC_BROWSER_TEST_F(NoStatePrefetchBrowserTest, NoPrefetchRecursive) {}

// Checks a prefetch to a nonexisting page.
IN_PROC_BROWSER_TEST_F(NoStatePrefetchBrowserTest, PrefetchNonexisting) {}

// Checks that a 301 redirect is followed.
IN_PROC_BROWSER_TEST_F(NoStatePrefetchBrowserTest, Prefetch301Redirect) {}

// Checks that non-HTTP(S) main resource redirects are marked as unsupported
// scheme.
IN_PROC_BROWSER_TEST_F(NoStatePrefetchBrowserTest,
                       PrefetchRedirectUnsupportedScheme) {}

// Checks that a 302 redirect is followed.
IN_PROC_BROWSER_TEST_F(NoStatePrefetchBrowserTest, Prefetch302Redirect) {}

// Checks that the load flags are set correctly for all resources in a 301
// redirect chain.
IN_PROC_BROWSER_TEST_F(NoStatePrefetchBrowserTest, Prefetch301LoadFlags) {}

// Checks that a subresource 301 redirect is followed.
IN_PROC_BROWSER_TEST_F(NoStatePrefetchBrowserTest, Prefetch301Subresource) {}

// Checks a client redirect is not followed.
IN_PROC_BROWSER_TEST_F(NoStatePrefetchBrowserTest, PrefetchClientRedirect) {}

// Prefetches a page that contains an automatic download triggered through an
// iframe. The request to download should not reach the server.
IN_PROC_BROWSER_TEST_F(NoStatePrefetchBrowserTest, PrefetchDownloadIframe) {}

IN_PROC_BROWSER_TEST_F(NoStatePrefetchBrowserTest,
                       PrefetchDownloadViaClientRedirect) {}

IN_PROC_BROWSER_TEST_F(NoStatePrefetchBrowserTest, PrefetchPageWithFragment) {}

// Checks that a prefetch of a CRX will result in a cancellation due to
// download.
IN_PROC_BROWSER_TEST_F(NoStatePrefetchBrowserTest, PrefetchCrx) {}

IN_PROC_BROWSER_TEST_F(NoStatePrefetchBrowserTest, PrefetchHttps) {}

// Checks that an SSL error prevents prefetch.
IN_PROC_BROWSER_TEST_F(NoStatePrefetchBrowserTest, SSLError) {}

// Checks that a subresource failing SSL does not prevent prefetch on the rest
// of the page.
IN_PROC_BROWSER_TEST_F(NoStatePrefetchBrowserTest, SSLSubresourceError) {}

IN_PROC_BROWSER_TEST_F(NoStatePrefetchBrowserTest, Loop) {}

// Crashes on Win.  http://crbug.com/1516892
#if BUILDFLAG(IS_WIN)
#define MAYBE_RendererCrash
#else
#define MAYBE_RendererCrash
#endif
IN_PROC_BROWSER_TEST_F(NoStatePrefetchBrowserTest, MAYBE_RendererCrash) {}

// Checks that the prefetch of png correctly loads the png.
IN_PROC_BROWSER_TEST_F(NoStatePrefetchBrowserTest, Png) {}

// Checks that the prefetch of jpeg correctly loads the jpeg.
IN_PROC_BROWSER_TEST_F(NoStatePrefetchBrowserTest, Jpeg) {}

// If the main resource is unsafe, the whole prefetch is cancelled.
IN_PROC_BROWSER_TEST_F(NoStatePrefetchBrowserTest,
                       PrerenderSafeBrowsingTopLevel) {}

// Ensures that server redirects to a malware page will cancel prerenders.
IN_PROC_BROWSER_TEST_F(NoStatePrefetchBrowserTest, ServerRedirect) {}

// Checks that prefetching a page does not add it to browsing history.
IN_PROC_BROWSER_TEST_F(NoStatePrefetchBrowserTest, HistoryUntouchedByPrefetch) {}

// Checks that prefetch requests have net::IDLE priority.
IN_PROC_BROWSER_TEST_F(NoStatePrefetchBrowserTest, IssuesIdlePriorityRequests) {}

// Checks that a registered ServiceWorker (SW) that is not currently running
// will intercepts a prefetch request.
IN_PROC_BROWSER_TEST_F(NoStatePrefetchBrowserTest, ServiceWorkerIntercept) {}

class NoStatePrefetchIncognitoBrowserTest : public NoStatePrefetchBrowserTest {};

// Checks that prerendering works in incognito mode.
IN_PROC_BROWSER_TEST_F(NoStatePrefetchIncognitoBrowserTest,
                       PrerenderIncognito) {}

// Checks that prerenders are aborted when an incognito profile is closed.
// TODO(crbug.com/41476151): The test is crashing on multiple platforms.
IN_PROC_BROWSER_TEST_F(NoStatePrefetchIncognitoBrowserTest,
                       DISABLED_PrerenderIncognitoClosed) {}

// Checks that when the history is cleared, NoStatePrefetch history is cleared.
IN_PROC_BROWSER_TEST_F(NoStatePrefetchBrowserTest, ClearHistory) {}

// Checks that when the cache is cleared, NoStatePrefetch history is not
// cleared.
IN_PROC_BROWSER_TEST_F(NoStatePrefetchBrowserTest, ClearCache) {}

IN_PROC_BROWSER_TEST_F(NoStatePrefetchBrowserTest, CancelAll) {}

// Cancels the prerender of a page with its own prerender.  The second prerender
// should never be started.
IN_PROC_BROWSER_TEST_F(NoStatePrefetchBrowserTest,
                       CancelPrerenderWithPrerender) {}

// Checks shutdown code while a prerender is active.
IN_PROC_BROWSER_TEST_F(NoStatePrefetchBrowserTest, PrerenderQuickQuit) {}

IN_PROC_BROWSER_TEST_F(NoStatePrefetchBrowserTest, PrerenderClickNewWindow) {}

IN_PROC_BROWSER_TEST_F(NoStatePrefetchBrowserTest,
                       PrerenderClickNewForegroundTab) {}

// Checks that renderers using excessive memory will be terminated.
IN_PROC_BROWSER_TEST_F(NoStatePrefetchBrowserTest, PrerenderExcessiveMemory) {}

IN_PROC_BROWSER_TEST_F(NoStatePrefetchBrowserTest, OpenTaskManager) {}

// Renders a page that contains a prerender link to a page that contains an
// img with a source that requires http authentication. This should not
// prerender successfully.
IN_PROC_BROWSER_TEST_F(NoStatePrefetchBrowserTest,
                       PrerenderHttpAuthentication) {}

// Checks that the referrer is not set when prerendering and the source page is
// HTTPS.
IN_PROC_BROWSER_TEST_F(NoStatePrefetchBrowserTest, PrerenderNoSSLReferrer) {}

// Test class to verify speculation hints for non-private same origin no state
// prefetches.
class SpeculationNoStatePrefetchBrowserTest
    : public NoStatePrefetchBrowserTest {};

IN_PROC_BROWSER_TEST_F(SpeculationNoStatePrefetchBrowserTest,
                       SpeculationPrefetch) {}

IN_PROC_BROWSER_TEST_F(SpeculationNoStatePrefetchBrowserTest,
                       SpeculationDisallowsCrossOriginRedirect) {}

IN_PROC_BROWSER_TEST_F(SpeculationNoStatePrefetchBrowserTest,
                       SpeculationAllowsSameOriginRedirectBlocked) {}

IN_PROC_BROWSER_TEST_F(SpeculationNoStatePrefetchBrowserTest,
                       HungSpeculationTimedOutByNavigation) {}

class NoStatePrefetchMPArchBrowserTest : public NoStatePrefetchBrowserTest {};

class NoStatePrefetchPrerenderBrowserTest
    : public NoStatePrefetchMPArchBrowserTest {};

IN_PROC_BROWSER_TEST_F(NoStatePrefetchPrerenderBrowserTest,
                       ShouldNotRecordNavigation) {}

class NoStatePrefetchFencedFrameBrowserTest
    : public NoStatePrefetchMPArchBrowserTest {};

IN_PROC_BROWSER_TEST_F(NoStatePrefetchFencedFrameBrowserTest,
                       ShouldNotRecordNavigation) {}

}  // namespace prerender