blob: a10ad771e92022f371e13b3ac821067ad9ca6daa [file] [log] [blame]
// Copyright 2022 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "content/browser/preloading/prefetch/prefetch_container.h"
#include "base/test/metrics/histogram_tester.h"
#include "content/browser/preloading/prefetch/prefetch_status.h"
#include "content/browser/preloading/prefetch/prefetch_type.h"
#include "content/browser/preloading/prefetch/prefetched_mainframe_response_container.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/global_routing_id.h"
#include "content/public/browser/storage_partition.h"
#include "content/public/test/test_renderer_host.h"
#include "net/base/isolation_info.h"
#include "services/network/public/mojom/cookie_manager.mojom.h"
#include "services/network/public/mojom/network_context.mojom.h"
#include "services/network/public/mojom/url_response_head.mojom.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace content {
namespace {
class PrefetchContainerTest : public RenderViewHostTestHarness {
public:
PrefetchContainerTest()
: RenderViewHostTestHarness(
base::test::TaskEnvironment::TimeSource::MOCK_TIME) {}
void SetUp() override {
RenderViewHostTestHarness::SetUp();
browser_context()
->GetDefaultStoragePartition()
->GetNetworkContext()
->GetCookieManager(cookie_manager_.BindNewPipeAndPassReceiver());
}
network::mojom::CookieManager* cookie_manager() {
return cookie_manager_.get();
}
bool SetCookie(const GURL& url, const std::string& value) {
std::unique_ptr<net::CanonicalCookie> cookie(net::CanonicalCookie::Create(
url, value, base::Time::Now(), /*server_time=*/absl::nullopt,
/*cookie_partition_key=*/absl::nullopt));
EXPECT_TRUE(cookie.get());
bool result = false;
base::RunLoop run_loop;
net::CookieOptions options;
options.set_include_httponly();
options.set_same_site_cookie_context(
net::CookieOptions::SameSiteCookieContext::MakeInclusive());
cookie_manager_->SetCanonicalCookie(
*cookie.get(), url, options,
base::BindOnce(
[](bool* result, base::RunLoop* run_loop,
net::CookieAccessResult set_cookie_access_result) {
*result = set_cookie_access_result.status.IsInclude();
run_loop->Quit();
},
&result, &run_loop));
// This will run until the cookie is set.
run_loop.Run();
// This will run until the cookie listener is updated.
base::RunLoop().RunUntilIdle();
return result;
}
private:
mojo::Remote<network::mojom::CookieManager> cookie_manager_;
};
TEST_F(PrefetchContainerTest, CreatePrefetchContainer) {
PrefetchContainer prefetch_container(
GlobalRenderFrameHostId(1234, 5678), GURL("https://test.com"),
PrefetchType(/*use_isolated_network_context=*/true,
/*use_prefetch_proxy=*/true),
nullptr);
EXPECT_EQ(prefetch_container.GetReferringRenderFrameHostId(),
GlobalRenderFrameHostId(1234, 5678));
EXPECT_EQ(prefetch_container.GetURL(), GURL("https://test.com"));
EXPECT_EQ(prefetch_container.GetPrefetchType(),
PrefetchType(/*use_isolated_network_context=*/true,
/*use_prefetch_proxy=*/true));
EXPECT_EQ(prefetch_container.GetPrefetchContainerKey(),
std::make_pair(GlobalRenderFrameHostId(1234, 5678),
GURL("https://test.com")));
}
TEST_F(PrefetchContainerTest, PrefetchStatus) {
PrefetchContainer prefetch_container(
GlobalRenderFrameHostId(1234, 5678), GURL("https://test.com"),
PrefetchType(/*use_isolated_network_context=*/true,
/*use_prefetch_proxy=*/true),
nullptr);
EXPECT_FALSE(prefetch_container.HasPrefetchStatus());
prefetch_container.SetPrefetchStatus(PrefetchStatus::kPrefetchNotStarted);
EXPECT_TRUE(prefetch_container.HasPrefetchStatus());
EXPECT_EQ(prefetch_container.GetPrefetchStatus(),
PrefetchStatus::kPrefetchNotStarted);
}
TEST_F(PrefetchContainerTest, IsDecoy) {
PrefetchContainer prefetch_container(
GlobalRenderFrameHostId(1234, 5678), GURL("https://test.com"),
PrefetchType(/*use_isolated_network_context=*/true,
/*use_prefetch_proxy=*/true),
nullptr);
EXPECT_FALSE(prefetch_container.IsDecoy());
prefetch_container.SetIsDecoy(true);
EXPECT_TRUE(prefetch_container.IsDecoy());
}
TEST_F(PrefetchContainerTest, ValidResponse) {
PrefetchContainer prefetch_container(
GlobalRenderFrameHostId(1234, 5678), GURL("https://test.com"),
PrefetchType(/*use_isolated_network_context=*/true,
/*use_prefetch_proxy=*/true),
nullptr);
prefetch_container.TakePrefetchedResponse(
std::make_unique<PrefetchedMainframeResponseContainer>(
net::IsolationInfo(), network::mojom::URLResponseHead::New(),
std::make_unique<std::string>("test body")));
task_environment()->FastForwardBy(base::Minutes(2));
EXPECT_FALSE(prefetch_container.HasValidPrefetchedResponse(base::Minutes(1)));
EXPECT_TRUE(prefetch_container.HasValidPrefetchedResponse(base::Minutes(3)));
}
TEST_F(PrefetchContainerTest, CookieListener) {
PrefetchContainer prefetch_container(
GlobalRenderFrameHostId(1234, 5678), GURL("https://test.com"),
PrefetchType(/*use_isolated_network_context=*/true,
/*use_prefetch_proxy=*/true),
nullptr);
EXPECT_FALSE(prefetch_container.HaveDefaultContextCookiesChanged());
prefetch_container.RegisterCookieListener(cookie_manager());
EXPECT_FALSE(prefetch_container.HaveDefaultContextCookiesChanged());
ASSERT_TRUE(SetCookie(GURL("https://test.com"), "test-cookie"));
EXPECT_TRUE(prefetch_container.HaveDefaultContextCookiesChanged());
}
TEST_F(PrefetchContainerTest, CookieCopy) {
base::HistogramTester histogram_tester;
PrefetchContainer prefetch_container(
GlobalRenderFrameHostId(1234, 5678), GURL("https://test.com"),
PrefetchType(/*use_isolated_network_context=*/true,
/*use_prefetch_proxy=*/true),
nullptr);
prefetch_container.RegisterCookieListener(cookie_manager());
EXPECT_FALSE(prefetch_container.IsIsolatedCookieCopyInProgress());
prefetch_container.OnIsolatedCookieCopyStart();
EXPECT_TRUE(prefetch_container.IsIsolatedCookieCopyInProgress());
// Once the cookie copy process has started, we should stop the cookie
// listener.
ASSERT_TRUE(SetCookie(GURL("https://test.com"), "test-cookie"));
EXPECT_FALSE(prefetch_container.HaveDefaultContextCookiesChanged());
task_environment()->FastForwardBy(base::Milliseconds(10));
prefetch_container.OnIsolatedCookiesReadCompleteAndWriteStart();
task_environment()->FastForwardBy(base::Milliseconds(20));
bool callback_called = false;
prefetch_container.SetOnCookieCopyCompleteCallback(
base::BindOnce([](bool* callback_called) { *callback_called = true; },
&callback_called));
prefetch_container.OnIsolatedCookieCopyComplete();
EXPECT_FALSE(prefetch_container.IsIsolatedCookieCopyInProgress());
EXPECT_TRUE(callback_called);
histogram_tester.ExpectUniqueTimeSample(
"PrefetchProxy.AfterClick.Mainframe.CookieReadTime",
base::Milliseconds(10), 1);
histogram_tester.ExpectUniqueTimeSample(
"PrefetchProxy.AfterClick.Mainframe.CookieWriteTime",
base::Milliseconds(20), 1);
histogram_tester.ExpectUniqueTimeSample(
"PrefetchProxy.AfterClick.Mainframe.CookieCopyTime",
base::Milliseconds(30), 1);
}
} // namespace
} // namespace content