| // Copyright 2023 The Chromium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "content/browser/renderer_host/browsing_context_group_swap.h" |
| |
| #include <optional> |
| |
| #include "base/strings/stringprintf.h" |
| #include "base/test/scoped_feature_list.h" |
| #include "content/browser/renderer_host/navigation_request.h" |
| #include "content/public/browser/web_contents_observer.h" |
| #include "content/public/common/content_features.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/content_browser_test.h" |
| #include "content/public/test/content_browser_test_utils.h" |
| #include "content/public/test/content_mock_cert_verifier.h" |
| #include "content/shell/browser/shell.h" |
| #include "content/test/render_document_feature.h" |
| #include "net/dns/mock_host_resolver.h" |
| #include "net/test/embedded_test_server/default_handlers.h" |
| #include "net/test/embedded_test_server/embedded_test_server.h" |
| |
| namespace content { |
| |
| namespace { |
| |
| class BrowsingContextGroupSwapBrowserTest |
| : public ContentBrowserTest, |
| public ::testing::WithParamInterface<std::tuple<std::string, bool>> { |
| public: |
| BrowsingContextGroupSwapBrowserTest() |
| : https_server_(net::EmbeddedTestServer::TYPE_HTTPS) { |
| // Enable RenderDocument: |
| InitAndEnableRenderDocumentFeature(&feature_list_for_render_document_, |
| std::get<0>(GetParam())); |
| // Enable BackForwardCache: |
| if (IsBackForwardCacheEnabled()) { |
| feature_list_for_back_forward_cache_.InitWithFeaturesAndParameters( |
| GetDefaultEnabledBackForwardCacheFeaturesForTesting( |
| /*ignore_outstanding_network_request=*/false), |
| GetDefaultDisabledBackForwardCacheFeaturesForTesting()); |
| } else { |
| feature_list_for_back_forward_cache_.InitWithFeatures( |
| {}, {features::kBackForwardCache}); |
| } |
| } |
| |
| // Provides meaningful param names instead of /0, /1, ... |
| static std::string DescribeParams( |
| const testing::TestParamInfo<ParamType>& info) { |
| auto [render_document_level, enable_back_forward_cache] = info.param; |
| return base::StringPrintf( |
| "%s_%s", |
| GetRenderDocumentLevelNameForTestParams(render_document_level).c_str(), |
| enable_back_forward_cache ? "BFCacheEnabled" : "BFCacheDisabled"); |
| } |
| |
| bool IsBackForwardCacheEnabled() { return std::get<1>(GetParam()); } |
| |
| net::EmbeddedTestServer* https_server() { return &https_server_; } |
| |
| protected: |
| void SetUpOnMainThread() override { |
| ContentBrowserTest::SetUpOnMainThread(); |
| mock_cert_verifier_.mock_cert_verifier()->set_default_result(net::OK); |
| host_resolver()->AddRule("*", "127.0.0.1"); |
| https_server()->ServeFilesFromSourceDirectory(GetTestDataFilePath()); |
| SetupCrossSiteRedirector(https_server()); |
| net::test_server::RegisterDefaultHandlers(&https_server_); |
| ASSERT_TRUE(https_server()->Start()); |
| } |
| |
| private: |
| void SetUpCommandLine(base::CommandLine* command_line) override { |
| mock_cert_verifier_.SetUpCommandLine(command_line); |
| } |
| |
| void SetUpInProcessBrowserTestFixture() override { |
| ContentBrowserTest::SetUpInProcessBrowserTestFixture(); |
| mock_cert_verifier_.SetUpInProcessBrowserTestFixture(); |
| } |
| |
| void TearDownInProcessBrowserTestFixture() override { |
| ContentBrowserTest::TearDownInProcessBrowserTestFixture(); |
| mock_cert_verifier_.TearDownInProcessBrowserTestFixture(); |
| } |
| |
| content::ContentMockCertVerifier mock_cert_verifier_; |
| base::test::ScopedFeatureList feature_list_for_render_document_; |
| base::test::ScopedFeatureList feature_list_for_back_forward_cache_; |
| net::EmbeddedTestServer https_server_; |
| }; |
| |
| class BrowsingContextGroupSwapObserver : public WebContentsObserver { |
| public: |
| explicit BrowsingContextGroupSwapObserver(WebContents* web_contents) |
| : WebContentsObserver(web_contents), latest_swap_(std::nullopt) {} |
| |
| void DidFinishNavigation(NavigationHandle* navigation_handle) override { |
| latest_swap_ = NavigationRequest::From(navigation_handle) |
| ->browsing_context_group_swap(); |
| } |
| |
| BrowsingContextGroupSwap GetLatestBrowsingContextGroupSwap() { |
| return latest_swap_.value(); |
| } |
| |
| private: |
| std::optional<BrowsingContextGroupSwap> latest_swap_; |
| }; |
| |
| IN_PROC_BROWSER_TEST_P(BrowsingContextGroupSwapBrowserTest, Basic_Navigation) { |
| GURL regular_page_1(https_server()->GetURL("a.test", "/title1.html")); |
| GURL regular_page_2(https_server()->GetURL("a.test", "/title2.html")); |
| |
| BrowsingContextGroupSwapObserver swap_observer(shell()->web_contents()); |
| ASSERT_TRUE(NavigateToURL(shell(), regular_page_1)); |
| ASSERT_TRUE(NavigateToURL(shell(), regular_page_2)); |
| |
| BrowsingContextGroupSwap observed_swap = |
| swap_observer.GetLatestBrowsingContextGroupSwap(); |
| EXPECT_EQ(observed_swap.type(), |
| IsBackForwardCacheEnabled() |
| ? BrowsingContextGroupSwapType::kProactiveSwap |
| : BrowsingContextGroupSwapType::kNoSwap); |
| } |
| |
| IN_PROC_BROWSER_TEST_P(BrowsingContextGroupSwapBrowserTest, Coop_Navigation) { |
| GURL regular_page(https_server()->GetURL("a.test", "/title1.html")); |
| GURL coop_page(https_server()->GetURL( |
| "a.test", "/set-header?Cross-Origin-Opener-Policy: same-origin")); |
| |
| BrowsingContextGroupSwapObserver swap_observer(shell()->web_contents()); |
| ASSERT_TRUE(NavigateToURL(shell(), regular_page)); |
| ASSERT_TRUE(NavigateToURL(shell(), coop_page)); |
| |
| BrowsingContextGroupSwap observed_swap = |
| swap_observer.GetLatestBrowsingContextGroupSwap(); |
| EXPECT_EQ(observed_swap.type(), BrowsingContextGroupSwapType::kCoopSwap); |
| } |
| |
| IN_PROC_BROWSER_TEST_P(BrowsingContextGroupSwapBrowserTest, |
| Security_Navigation) { |
| GURL regular_page(https_server()->GetURL("a.test", "/title1.html")); |
| GURL webui_page("chrome://ukm"); |
| |
| BrowsingContextGroupSwapObserver swap_observer(shell()->web_contents()); |
| ASSERT_TRUE(NavigateToURL(shell(), regular_page)); |
| ASSERT_TRUE(NavigateToURL(shell(), webui_page)); |
| |
| BrowsingContextGroupSwap observed_swap = |
| swap_observer.GetLatestBrowsingContextGroupSwap(); |
| EXPECT_EQ(observed_swap.type(), BrowsingContextGroupSwapType::kSecuritySwap); |
| } |
| |
| static auto kTestParams = |
| testing::Combine(testing::ValuesIn(RenderDocumentFeatureLevelValues()), |
| testing::Bool()); |
| INSTANTIATE_TEST_SUITE_P(All, |
| BrowsingContextGroupSwapBrowserTest, |
| kTestParams, |
| BrowsingContextGroupSwapBrowserTest::DescribeParams); |
| |
| } // namespace |
| |
| } // namespace content |