blob: 97270c53ec6d94fddedde4105a19f1ff904fee64 [file] [log] [blame]
// Copyright 2025 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/code_cache_host_impl.h"
#include "base/containers/span.h"
#include "base/files/scoped_temp_dir.h"
#include "base/functional/bind.h"
#include "base/functional/callback_forward.h"
#include "base/run_loop.h"
#include "base/task/sequenced_task_runner.h"
#include "base/test/bind.h"
#include "base/test/scoped_feature_list.h"
#include "content/browser/child_process_security_policy_impl.h"
#include "content/browser/code_cache/generated_code_cache_context.h"
#include "content/browser/process_lock.h"
#include "content/browser/site_instance_impl.h"
#include "content/public/test/browser_task_environment.h"
#include "content/public/test/test_browser_context.h"
#include "mojo/public/cpp/base/big_buffer.h"
#include "net/base/features.h"
#include "net/http/http_cache.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/public/common/features.h"
namespace content {
class CodeCacheHostImplTest : public testing::Test {
public:
CodeCacheHostImplTest() {
feature_list_.InitWithFeatures(
{blink::features::kUsePersistentCacheForCodeCache,
net::features::kSplitCacheByNetworkIsolationKey},
{});
CHECK(temp_dir_.CreateUniqueTempDir());
generated_code_cache_context_ =
base::MakeRefCounted<GeneratedCodeCacheContext>();
generated_code_cache_context_->Initialize(temp_dir_.GetPath(), 0);
}
~CodeCacheHostImplTest() override {
generated_code_cache_context_->Shutdown();
}
void SetupRendererWithLock(int process_id, const GURL& url) {
ChildProcessSecurityPolicyImpl* p =
ChildProcessSecurityPolicyImpl::GetInstance();
p->AddForTesting(process_id, &browser_context_);
scoped_refptr<SiteInstanceImpl> site_instance =
SiteInstanceImpl::CreateForTesting(&browser_context_, url);
ChildProcessSecurityPolicyImpl::GetInstance()->LockProcess(
site_instance->GetIsolationContext(), process_id, false,
ProcessLock::FromSiteInfo(site_instance->GetSiteInfo()));
}
protected:
BrowserTaskEnvironment task_environment_;
TestBrowserContext browser_context_;
base::test::ScopedFeatureList feature_list_;
base::ScopedTempDir temp_dir_;
scoped_refptr<GeneratedCodeCacheContext> generated_code_cache_context_;
};
#if !BUILDFLAG(IS_FUCHSIA)
TEST_F(CodeCacheHostImplTest, PersistentCacheWriteAndRead) {
#else
// PersistentCache is not supported on Fuchsia.
TEST_F(CodeCacheHostImplTest, DISABLED_PersistentCacheWriteAndRead) {
#endif
const base::Time response_time = base::Time::Now();
const std::string data_str = "some data";
const mojo_base::BigBuffer data(base::as_byte_span(data_str));
const GURL original_resource_url("http://example.com/script.js");
// Storing and retrieving for from the same isolation context works.
{
base::RunLoop runloop;
auto quit_closure = runloop.QuitClosure();
GURL url = original_resource_url;
GURL origin_lock("http://example.com");
net::NetworkIsolationKey nik(net::SchemefulSite{url},
net::SchemefulSite{url});
const int process_id = 12;
SetupRendererWithLock(process_id, url);
GeneratedCodeCacheContext::RunOrPostTask(
generated_code_cache_context_.get(), FROM_HERE,
base::BindLambdaForTesting([&]() {
CodeCacheHostImpl host(process_id, generated_code_cache_context_, nik,
blink::StorageKey::CreateFirstParty(
url::Origin::Create(origin_lock)));
host.DidGenerateCacheableMetadata(
blink::mojom::CodeCacheType::kJavascript, url, response_time,
data.Clone());
host.FetchCachedCode(
blink::mojom::CodeCacheType::kJavascript, url,
base::BindOnce(
[&](base::Time expected_response_time,
const std::string& expected_data,
base::OnceClosure quit_closure, base::Time response_time,
mojo_base::BigBuffer data) {
EXPECT_EQ(expected_response_time, response_time);
EXPECT_EQ(
expected_data,
std::string(reinterpret_cast<const char*>(data.data()),
data.size()));
std::move(quit_closure).Run();
},
response_time, data_str, quit_closure));
}));
runloop.Run();
}
// Attempting to retrieve code for `original_resource_url` from a different
// isolation context does not work and instead returns default values.
{
base::RunLoop runloop;
auto quit_closure = runloop.QuitClosure();
GURL url("http://other.com/script.js");
GURL origin_lock("http://other.com");
net::NetworkIsolationKey nik(net::SchemefulSite{url},
net::SchemefulSite{url});
const int process_id = 24;
SetupRendererWithLock(process_id, url);
GeneratedCodeCacheContext::RunOrPostTask(
generated_code_cache_context_.get(), FROM_HERE,
base::BindLambdaForTesting([&]() {
CodeCacheHostImpl host(process_id, generated_code_cache_context_, nik,
blink::StorageKey::CreateFirstParty(
url::Origin::Create(origin_lock)));
host.FetchCachedCode(
blink::mojom::CodeCacheType::kJavascript, original_resource_url,
base::BindOnce(
[&](base::OnceClosure quit_closure, base::Time response_time,
mojo_base::BigBuffer data) {
EXPECT_EQ(response_time, base::Time());
EXPECT_EQ(data.byte_span(),
mojo_base::BigBuffer().byte_span());
std::move(quit_closure).Run();
},
quit_closure));
}));
runloop.Run();
}
}
} // namespace content