chromium/chrome/browser/chrome_back_forward_cache_browsertest.cc

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

#include <array>
#include <string_view>

#include "base/command_line.h"
#include "base/functional/callback.h"
#include "base/strings/strcat.h"
#include "base/test/bind.h"
#include "base/test/mock_callback.h"
#include "base/test/scoped_feature_list.h"
#include "base/test/scoped_logging_settings.h"
#include "build/build_config.h"
#include "build/chromeos_buildflags.h"
#include "chrome/browser/content_settings/host_content_settings_map_factory.h"
#include "chrome/browser/content_settings/mixed_content_settings_tab_helper.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/task_manager/task_manager_tester.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/browser_content_setting_bubble_model_delegate.h"
#include "chrome/browser/ui/content_settings/content_setting_bubble_model.h"
#include "chrome/browser/ui/tabs/tab_strip_model.h"
#include "chrome/grit/generated_resources.h"
#include "chrome/test/base/in_process_browser_test.h"
#include "chrome/test/base/ui_test_utils.h"
#include "components/content_settings/core/browser/host_content_settings_map.h"
#include "components/content_settings/core/common/content_settings.h"
#include "components/content_settings/core/common/content_settings_types.h"
#include "components/metrics/content/subprocess_metrics_provider.h"
#include "components/network_session_configurator/common/network_switches.h"
#include "components/page_load_metrics/browser/observers/core/uma_page_load_metrics_observer.h"
#include "components/permissions/permission_manager.h"
#include "content/public/browser/permission_controller.h"
#include "content/public/browser/permission_request_description.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/common/content_features.h"
#include "content/public/common/content_switches.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/test_navigation_observer.h"
#include "content/public/test/test_utils.h"
#include "net/dns/mock_host_resolver.h"
#include "net/test/embedded_test_server/embedded_test_server.h"
#include "pdf/buildflags.h"
#include "third_party/blink/public/common/permissions/permission_utils.h"
#include "third_party/blink/public/common/scheduler/web_scheduler_tracked_feature.h"
#include "third_party/blink/public/mojom/webshare/webshare.mojom.h"
#include "ui/base/l10n/l10n_util.h"

#if BUILDFLAG(ENABLE_PDF)
#include <tuple>
#include <variant>

#include "chrome/browser/pdf/pdf_extension_test_util.h"
#include "chrome/browser/pdf/test_pdf_viewer_stream_manager.h"
#include "pdf/pdf_features.h"

namespace {
struct ChromeBackForwardCacheBrowserWithEmbedPdfTestPassToString {};
}  // namespace
#endif  // BUILDFLAG(ENABLE_PDF)

namespace {
constexpr std::array<std::string_view, 2>
    kChromeBackForwardCacheBrowserWithEmbedTestValues =;
}  // namespace

class ChromeBackForwardCacheBrowserTest : public InProcessBrowserTest {};

IN_PROC_BROWSER_TEST_F(ChromeBackForwardCacheBrowserTest, Basic) {}

IN_PROC_BROWSER_TEST_F(ChromeBackForwardCacheBrowserTest, BasicIframe) {}

IN_PROC_BROWSER_TEST_F(ChromeBackForwardCacheBrowserTest,
                       PermissionContextBase) {}

IN_PROC_BROWSER_TEST_F(ChromeBackForwardCacheBrowserTest,
                       DoesNotCacheIfPictureInPicture) {}

#if BUILDFLAG(IS_ANDROID)
IN_PROC_BROWSER_TEST_F(ChromeBackForwardCacheBrowserTest,
                       DoesNotCacheIfWebShare) {
  // HTTPS needed for WebShare permission.
  net::EmbeddedTestServer https_server(net::EmbeddedTestServer::TYPE_HTTPS);
  https_server.AddDefaultHandlers(GetChromeTestDataDir());
  https_server.SetSSLConfig(net::EmbeddedTestServer::CERT_TEST_NAMES);
  ASSERT_TRUE(https_server.Start());

  GURL url_a(https_server.GetURL("a.test", "/title1.html"));
  GURL url_b(https_server.GetURL("b.test", "/title1.html"));

  // 1) Navigate to A.
  EXPECT_TRUE(content::NavigateToURL(web_contents(), url_a));
  content::RenderFrameHostWrapper rfh_a(current_frame_host());

  // Use the WebShare feature on the empty page.
  EXPECT_EQ("success", content::EvalJs(current_frame_host(), R"(
    new Promise(resolve => {
      navigator.share({title: 'the title'})
        .then(m => { resolve("success"); })
        .catch(error => { resolve(error.message); });
    });
  )"));

  // 2) Navigate away.
  EXPECT_TRUE(content::NavigateToURL(web_contents(), url_b));

  // The page uses WebShare so it must be evicted from the cache and deleted.
  ASSERT_TRUE(rfh_a.WaitUntilRenderFrameDeleted());

  // 3) Go back.
  web_contents()->GetController().GoBack();
  EXPECT_TRUE(content::WaitForLoadStop(web_contents()));
}

IN_PROC_BROWSER_TEST_F(ChromeBackForwardCacheBrowserTest,
                       DoesNotCacheIfWebNfc) {
  // HTTPS needed for WebNfc permission.
  net::EmbeddedTestServer https_server(net::EmbeddedTestServer::TYPE_HTTPS);
  https_server.AddDefaultHandlers(GetChromeTestDataDir());
  https_server.SetSSLConfig(net::EmbeddedTestServer::CERT_TEST_NAMES);
  ASSERT_TRUE(https_server.Start());

  GURL url_a(https_server.GetURL("a.test", "/title1.html"));
  GURL url_b(https_server.GetURL("b.test", "/title1.html"));

  // 1) Navigate to A.
  EXPECT_TRUE(content::NavigateToURL(web_contents(), url_a));
  content::RenderFrameHostWrapper rfh_a(current_frame_host());

  // Use the WebNfc feature on the empty page.
  EXPECT_EQ("success", content::EvalJs(current_frame_host(), R"(
    const ndef = new NDEFReader();
    new Promise(async resolve => {
      try {
        await ndef.write("Hello");
        resolve('success');
      } catch (error) {
        resolve(error.message);
      }
    });
  )"));

  // 2) Navigate away.
  EXPECT_TRUE(content::NavigateToURL(web_contents(), url_b));

  // The page uses WebNfc so it must be evicted from the cache and deleted.
  ASSERT_TRUE(rfh_a.WaitUntilRenderFrameDeleted());

  // 3) Go back.
  web_contents()->GetController().GoBack();
  EXPECT_TRUE(content::WaitForLoadStop(web_contents()));
}
#endif  // BUILDFLAG(IS_ANDROID)

IN_PROC_BROWSER_TEST_F(ChromeBackForwardCacheBrowserTest,
                       RestoresMixedContentSettings) {}

class MetricsChromeBackForwardCacheBrowserTest
    : public ChromeBackForwardCacheBrowserTest,
      public ::testing::WithParamInterface<std::string> {};

// Flaky https://crbug.com/1224780
IN_PROC_BROWSER_TEST_P(MetricsChromeBackForwardCacheBrowserTest,
                       DISABLED_FirstInputDelay) {}

std::vector<std::string> MetricsChromeBackForwardCacheBrowserTestValues() {}

INSTANTIATE_TEST_SUITE_P();

// Ensure that BackForwardCache RenderFrameHosts are shown in the Task Manager.
IN_PROC_BROWSER_TEST_F(ChromeBackForwardCacheBrowserTest,
                       ShowMainFrameInTaskManager) {}

// Ensure that BackForwardCache cross-site subframes are shown in the Task
// Manager.
IN_PROC_BROWSER_TEST_F(ChromeBackForwardCacheBrowserTest,
                       ShowCrossSiteOOPIFInTaskManager) {}

// Ensure that BackForwardCache same-site subframes are not shown in the Task
// Manager.
IN_PROC_BROWSER_TEST_F(ChromeBackForwardCacheBrowserTest,
                       DoNotShowSameSiteSubframeInTaskManager) {}

class ChromeBackForwardCacheBrowserWithEmbedTestBase
    : public ChromeBackForwardCacheBrowserTest {};

class ChromeBackForwardCacheBrowserWithEmbedTest
    : public ChromeBackForwardCacheBrowserWithEmbedTestBase,
      public ::testing::WithParamInterface<std::string_view> {};

INSTANTIATE_TEST_SUITE_P();

#if BUILDFLAG(ENABLE_PDF)
class ChromeBackForwardCacheBrowserWithEmbedPdfTest
    : public ChromeBackForwardCacheBrowserWithEmbedTestBase,
      public ::testing::WithParamInterface<std::tuple<std::string_view, bool>> {};

INSTANTIATE_TEST_SUITE_P();
#endif  // BUILDFLAG(ENABLE_PDF)

// TODO(crbug.com/40285326): This fails with the field trial testing config.
class ChromeBackForwardCacheBrowserWithEmbedTestNoTestingConfig
    : public ChromeBackForwardCacheBrowserWithEmbedTest {};

INSTANTIATE_TEST_SUITE_P();

#if BUILDFLAG(ENABLE_PDF)
class ChromeBackForwardCacheBrowserWithEmbedPdfTestNoTestingConfig
    : public ChromeBackForwardCacheBrowserWithEmbedPdfTest {};

INSTANTIATE_TEST_SUITE_P();
#endif  // BUILDFLAG(ENABLE_PDF)

IN_PROC_BROWSER_TEST_P(
    ChromeBackForwardCacheBrowserWithEmbedTestNoTestingConfig,
    DoesNotCachePageWithEmbeddedPlugin) {}

#if BUILDFLAG(ENABLE_PDF)
IN_PROC_BROWSER_TEST_P(
    ChromeBackForwardCacheBrowserWithEmbedPdfTestNoTestingConfig,
    DoesNotCachePageWithEmbeddedPdf) {}

// Flaky: crbug.com/40935990
#if BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
#define MAYBE_DoesNotCachePageWithEmbeddedPdfAppendedOnPageLoaded
#else
#define MAYBE_DoesNotCachePageWithEmbeddedPdfAppendedOnPageLoaded
#endif
IN_PROC_BROWSER_TEST_P(ChromeBackForwardCacheBrowserWithEmbedPdfTest,
                       MAYBE_DoesNotCachePageWithEmbeddedPdfAppendedOnPageLoaded) {}
#endif  // BUILDFLAG(ENABLE_PDF)

IN_PROC_BROWSER_TEST_P(ChromeBackForwardCacheBrowserWithEmbedTest,
                       DoesCachePageWithEmbeddedHtml) {}

#if BUILDFLAG(ENABLE_PDF)
// Flaky: crbug.com/40935990
#if BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
#define MAYBE_DoesNotCachePageWithEmbeddedHtmlMutatedIntoPdf
#else
#define MAYBE_DoesNotCachePageWithEmbeddedHtmlMutatedIntoPdf
#endif
IN_PROC_BROWSER_TEST_P(ChromeBackForwardCacheBrowserWithEmbedPdfTest,
                       MAYBE_DoesNotCachePageWithEmbeddedHtmlMutatedIntoPdf) {}

IN_PROC_BROWSER_TEST_P(ChromeBackForwardCacheBrowserWithEmbedPdfTest,
                       DoesCachePageWithEmbeddedPdfMutatedIntoHtml) {}
#endif  // BUILDFLAG(ENABLE_PDF)