#include <set>
#include <string>
#include "base/files/file_path.h"
#include "base/functional/callback_helpers.h"
#include "base/logging.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/ref_counted.h"
#include "base/ranges/algorithm.h"
#include "base/synchronization/waitable_event.h"
#include "base/test/bind.h"
#include "base/test/gtest_util.h"
#include "base/test/mock_log.h"
#include "base/test/scoped_command_line.h"
#include "base/test/scoped_feature_list.h"
#include "build/build_config.h"
#include "content/browser/child_process_security_policy_impl.h"
#include "content/browser/isolated_origin_util.h"
#include "content/browser/origin_agent_cluster_isolation_state.h"
#include "content/browser/process_lock.h"
#include "content/browser/site_info.h"
#include "content/browser/site_instance_impl.h"
#include "content/common/content_navigation_policy.h"
#include "content/common/features.h"
#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/site_isolation_policy.h"
#include "content/public/common/bindings_policy.h"
#include "content/public/common/content_client.h"
#include "content/public/common/content_features.h"
#include "content/public/common/content_switches.h"
#include "content/public/common/url_constants.h"
#include "content/public/test/browser_task_environment.h"
#include "content/public/test/test_browser_context.h"
#include "content/public/test/test_utils.h"
#include "content/test/storage_partition_test_helpers.h"
#include "content/test/test_content_browser_client.h"
#include "storage/browser/file_system/file_permission_policy.h"
#include "storage/browser/file_system/file_system_url.h"
#include "storage/browser/file_system/isolated_context.h"
#include "storage/common/file_system/file_system_types.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/public/common/storage_key/storage_key.h"
#include "url/gurl.h"
#include "url/origin.h"
namespace content {
namespace {
using IsolatedOriginSource = ChildProcessSecurityPolicy::IsolatedOriginSource;
const int kRendererID = 42;
#if defined(FILE_PATH_USES_DRIVE_LETTERS)
#define TEST_PATH(x) FILE_PATH_LITERAL("c:") FILE_PATH_LITERAL(x)
#else
#define TEST_PATH(x) FILE_PATH_LITERAL(x)
#endif
class ChildProcessSecurityPolicyTestBrowserClient
: public TestContentBrowserClient {
public:
ChildProcessSecurityPolicyTestBrowserClient() {}
bool IsHandledURL(const GURL& url) override {
return schemes_.find(url.scheme()) != schemes_.end();
}
void ClearSchemes() {
schemes_.clear();
}
void AddScheme(const std::string& scheme) {
schemes_.insert(scheme);
}
private:
std::set<std::string> schemes_;
};
bool IsCitadelProtectionEnabled() {
return base::FeatureList::IsEnabled(kSiteIsolationCitadelEnforcement);
}
void LockProcessIfNeeded(int process_id,
BrowserContext* browser_context,
const GURL& url) {
scoped_refptr<SiteInstanceImpl> site_instance =
SiteInstanceImpl::CreateForTesting(browser_context, url);
if (site_instance->RequiresDedicatedProcess() &&
site_instance->GetSiteInfo().ShouldLockProcessToSite(
site_instance->GetIsolationContext())) {
ChildProcessSecurityPolicyImpl::GetInstance()->LockProcess(
site_instance->GetIsolationContext(), process_id, false,
ProcessLock::FromSiteInfo(site_instance->GetSiteInfo()));
}
}
}
enum class ChildProcessSecurityPolicyTestCase {
kCitadelDisabled,
kCitadelEnabled,
};
class ChildProcessSecurityPolicyTest
: public testing::Test,
public ::testing::WithParamInterface<ChildProcessSecurityPolicyTestCase> {
public:
ChildProcessSecurityPolicyTest()
: task_environment_(BrowserTaskEnvironment::REAL_IO_THREAD),
old_browser_client_(nullptr) {
feature_list_.InitWithFeatureState(
kSiteIsolationCitadelEnforcement,
GetParam() == ChildProcessSecurityPolicyTestCase::kCitadelEnabled);
}
static std::string DescribeParams(
const testing::TestParamInfo<ParamType>& info) {
return info.param == ChildProcessSecurityPolicyTestCase::kCitadelEnabled
? "CitadelEnabled"
: "CitadelDisabled";
}
void SetUp() override {
old_browser_client_ = SetBrowserClientForTesting(&test_browser_client_);
test_browser_client_.AddScheme(kChromeUIScheme);
test_browser_client_.AddScheme(url::kFileScheme);
SiteIsolationPolicy::DisableFlagCachingForTesting();
auto* policy = ChildProcessSecurityPolicyImpl::GetInstance();
{
base::AutoLock lock(policy->lock_);
EXPECT_EQ(0u, policy->security_state_.size())
<< "ChildProcessSecurityPolicy should not be tracking any processes "
<< "at test startup. Some other test probably forgot to call "
<< "Remove() at the end.";
}
}
void TearDown() override {
auto* policy = ChildProcessSecurityPolicyImpl::GetInstance();
{
base::AutoLock lock(policy->lock_);
EXPECT_EQ(0u, policy->security_state_.size())
<< "ChildProcessSecurityPolicy should not be tracking any processes "
<< "at test shutdown. Did you forget to call Remove() at the end of "
<< "a test?";
}
test_browser_client_.ClearSchemes();
SetBrowserClientForTesting(old_browser_client_);
}
using IsolatedOriginEntry =
ChildProcessSecurityPolicyImpl::IsolatedOriginEntry;
auto GetIsolatedOriginEntry(BrowsingInstanceId browsing_instance_id,
const url::Origin& origin,
bool isolate_all_subdomains = false) {
return std::pair<GURL, std::vector<IsolatedOriginEntry>>(
SiteInfo::GetSiteForOrigin(origin),
{IsolatedOriginEntry(
origin, true ,
browsing_instance_id, nullptr, nullptr, isolate_all_subdomains,
IsolatedOriginSource::TEST)});
}
auto GetIsolatedOriginEntry(int browsing_instance_id,
const url::Origin& origin,
bool isolate_all_subdomains = false) {
return GetIsolatedOriginEntry(BrowsingInstanceId(browsing_instance_id),
origin, isolate_all_subdomains);
}
auto GetIsolatedOriginEntry(BrowserContext* browser_context,
bool applies_to_future_browsing_instances,
BrowsingInstanceId browsing_instance_id,
const url::Origin& origin) {
return std::pair<GURL, std::vector<IsolatedOriginEntry>>(
SiteInfo::GetSiteForOrigin(origin),
{IsolatedOriginEntry(
origin, applies_to_future_browsing_instances, browsing_instance_id,
browser_context,
browser_context ? browser_context->GetResourceContext() : nullptr,
false , IsolatedOriginSource::TEST)});
}
auto GetIsolatedOriginEntry(const url::Origin& origin,
bool isolate_all_subdomains = false) {
return GetIsolatedOriginEntry(SiteInstanceImpl::NextBrowsingInstanceId(),
origin, isolate_all_subdomains);
}
auto GetIsolatedOriginEntry(const url::Origin& origin1,
const url::Origin& origin2,
bool origin1_isolate_all_subdomains = false,
bool origin2_isolate_all_subdomains = false) {
EXPECT_EQ(SiteInfo::GetSiteForOrigin(origin1),
SiteInfo::GetSiteForOrigin(origin2));
return std::pair<GURL, std::vector<IsolatedOriginEntry>>(
SiteInfo::GetSiteForOrigin(origin1),
{IsolatedOriginEntry(
origin1, true ,
SiteInstanceImpl::NextBrowsingInstanceId(), nullptr, nullptr,
origin1_isolate_all_subdomains, IsolatedOriginSource::TEST),
IsolatedOriginEntry(
origin2, true ,
SiteInstanceImpl::NextBrowsingInstanceId(), nullptr, nullptr,
origin2_isolate_all_subdomains, IsolatedOriginSource::TEST)});
}
bool IsIsolatedOrigin(BrowserContext* context,
int browsing_instance_id,
const url::Origin& origin) {
return IsIsolatedOrigin(context, BrowsingInstanceId(browsing_instance_id),
origin);
}
bool IsIsolatedOrigin(BrowserContext* context,
BrowsingInstanceId browsing_instance_id,
const url::Origin& origin) {
ChildProcessSecurityPolicyImpl* p =
ChildProcessSecurityPolicyImpl::GetInstance();
return p->IsIsolatedOrigin(
IsolationContext(browsing_instance_id, context,
false, false),
origin, false );
}
int GetIsolatedOriginEntryCount(const url::Origin& origin) {
ChildProcessSecurityPolicyImpl* p =
ChildProcessSecurityPolicyImpl::GetInstance();
GURL key(SiteInfo::GetSiteForOrigin(origin));
base::AutoLock isolated_origins_lock(p->isolated_origins_lock_);
auto origins_for_key = p->isolated_origins_[key];
return base::ranges::count(origins_for_key, origin,
&IsolatedOriginEntry::origin);
}
void CheckGetSiteForURL(BrowserContext* context,
std::map<GURL, GURL> to_test) {
for (const auto& entry : to_test) {
auto site_info =
SiteInfo::CreateForTesting(IsolationContext(context), entry.first);
EXPECT_EQ(site_info.site_url(), entry.second);
}
}
protected:
void RegisterTestScheme(const std::string& scheme) {
test_browser_client_.AddScheme(scheme);
}
void GrantPermissionsForFile(ChildProcessSecurityPolicyImpl* p,
int child_id,
const base::FilePath& file,
int permissions) {
p->GrantPermissionsForFile(child_id, file, permissions);
}
void CheckHasNoFileSystemPermission(ChildProcessSecurityPolicyImpl* p,
const std::string& child_id) {
EXPECT_FALSE(p->CanReadFileSystem(kRendererID, child_id));
EXPECT_FALSE(p->CanReadWriteFileSystem(kRendererID, child_id));
EXPECT_FALSE(p->CanCopyIntoFileSystem(kRendererID, child_id));
EXPECT_FALSE(p->CanDeleteFromFileSystem(kRendererID, child_id));
}
void CheckHasNoFileSystemFilePermission(ChildProcessSecurityPolicyImpl* p,
const base::FilePath& file,
const storage::FileSystemURL& url) {
EXPECT_FALSE(p->CanReadFile(kRendererID, file));
EXPECT_FALSE(p->CanCreateReadWriteFile(kRendererID, file));
EXPECT_FALSE(p->CanReadFileSystemFile(kRendererID, url));
EXPECT_FALSE(p->CanWriteFileSystemFile(kRendererID, url));
EXPECT_FALSE(p->CanCreateFileSystemFile(kRendererID, url));
EXPECT_FALSE(p->CanCreateReadWriteFileSystemFile(kRendererID, url));
EXPECT_FALSE(p->CanCopyIntoFileSystemFile(kRendererID, url));
EXPECT_FALSE(p->CanDeleteFileSystemFile(kRendererID, url));
auto handle = p->CreateHandle(kRendererID);
EXPECT_FALSE(handle.CanReadFile(file));
EXPECT_FALSE(handle.CanReadFileSystemFile(url));
}
BrowserContext* browser_context() { return &browser_context_; }
private:
BrowserTaskEnvironment task_environment_;
TestBrowserContext browser_context_;
ChildProcessSecurityPolicyTestBrowserClient test_browser_client_;
raw_ptr<ContentBrowserClient> old_browser_client_;
base::test::ScopedFeatureList feature_list_;
};
TEST_P(ChildProcessSecurityPolicyTest, ChildID) {
ChildProcessSecurityPolicyImpl* p =
ChildProcessSecurityPolicyImpl::GetInstance();
p->AddForTesting(kRendererID, browser_context());
auto handle = p->CreateHandle(kRendererID);
EXPECT_EQ(handle.child_id(), kRendererID);
p->Remove(kRendererID);
}
TEST_P(ChildProcessSecurityPolicyTest, IsWebSafeSchemeTest) {
ChildProcessSecurityPolicyImpl* p =
ChildProcessSecurityPolicyImpl::GetInstance();
EXPECT_TRUE(p->IsWebSafeScheme(url::kHttpScheme));
EXPECT_TRUE(p->IsWebSafeScheme(url::kHttpsScheme));
EXPECT_TRUE(p->IsWebSafeScheme(url::kDataScheme));
EXPECT_TRUE(p->IsWebSafeScheme(url::kBlobScheme));
EXPECT_TRUE(p->IsWebSafeScheme(url::kFileSystemScheme));
EXPECT_FALSE(p->IsWebSafeScheme("registered-web-safe-scheme"));
p->RegisterWebSafeScheme("registered-web-safe-scheme");
EXPECT_TRUE(p->IsWebSafeScheme("registered-web-safe-scheme"));
EXPECT_FALSE(p->IsWebSafeScheme(kChromeUIScheme));
p->ClearRegisteredSchemeForTesting("registered-web-safe-scheme");
}
TEST_P(ChildProcessSecurityPolicyTest, IsPseudoSchemeTest) {
ChildProcessSecurityPolicyImpl* p =
ChildProcessSecurityPolicyImpl::GetInstance();
EXPECT_TRUE(p->IsPseudoScheme(url::kAboutScheme));
EXPECT_TRUE(p->IsPseudoScheme(url::kJavaScriptScheme));
EXPECT_TRUE(p->IsPseudoScheme(kViewSourceScheme));
EXPECT_TRUE(p->IsPseudoScheme(kGoogleChromeScheme));
EXPECT_FALSE(p->IsPseudoScheme("registered-pseudo-scheme"));
p->RegisterPseudoScheme("registered-pseudo-scheme");
EXPECT_TRUE(p->IsPseudoScheme("registered-pseudo-scheme"));
EXPECT_FALSE(p->IsPseudoScheme(kChromeUIScheme));
p->ClearRegisteredSchemeForTesting("registered-pseudo-scheme");
}
TEST_P(ChildProcessSecurityPolicyTest, StandardSchemesTest) {
ChildProcessSecurityPolicyImpl* p =
ChildProcessSecurityPolicyImpl::GetInstance();
p->AddForTesting(kRendererID, browser_context());
auto handle = p->CreateHandle(kRendererID);
EXPECT_TRUE(p->CanRequestURL(kRendererID, GURL("http://www.google.com/")));
EXPECT_TRUE(p->CanRequestURL(kRendererID, GURL("https://www.paypal.com/")));
EXPECT_TRUE(p->CanRequestURL(kRendererID, GURL("data:text/html,<b>Hi</b>")));
EXPECT_TRUE(p->CanRequestURL(
kRendererID, GURL("filesystem:http://localhost/temporary/a.gif")));
EXPECT_TRUE(p->CanRedirectToURL(GURL("http://www.google.com/")));
EXPECT_TRUE(p->CanRedirectToURL(GURL("https://www.paypal.com/")));
EXPECT_TRUE(p->CanRedirectToURL(GURL("data:text/html,<b>Hi</b>")));
EXPECT_TRUE(
p->CanRedirectToURL(GURL("filesystem:http://localhost/temporary/a.gif")));
const std::vector<std::string> kCommitURLs({
"http://www.google.com/",
"https://www.paypal.com/",
"data:text/html,<b>Hi</b>",
"filesystem:http://localhost/temporary/a.gif",
});
for (const auto& url_string : kCommitURLs) {
const GURL commit_url(url_string);
if (AreAllSitesIsolatedForTesting() && IsCitadelProtectionEnabled()) {
EXPECT_FALSE(p->CanCommitURL(kRendererID, commit_url)) << commit_url;
EXPECT_FALSE(handle.CanCommitURL(commit_url)) << commit_url;
} else {
EXPECT_TRUE(p->CanCommitURL(kRendererID, commit_url)) << commit_url;
EXPECT_TRUE(handle.CanCommitURL(commit_url)) << commit_url;
}
}
EXPECT_FALSE(p->CanRequestURL(kRendererID,
GURL("file:///etc/passwd")));
EXPECT_FALSE(p->CanRequestURL(kRendererID, GetWebUIURL("foo/bar")));
EXPECT_FALSE(p->CanRequestURL(kRendererID,
GURL("view-source:http://www.google.com/")));
EXPECT_TRUE(p->CanRedirectToURL(GURL("file:///etc/passwd")));
EXPECT_TRUE(p->CanRedirectToURL(GetWebUIURL("foo/bar")));
EXPECT_FALSE(p->CanRedirectToURL(GURL("view-source:http://www.google.com/")));
EXPECT_FALSE(p->CanRedirectToURL(GURL(kUnreachableWebDataURL)));
const std::vector<std::string> kFailedCommitURLs(
{"file:///etc/passwd", "view-source:http://www.google.com/",
kUnreachableWebDataURL, GetWebUIURL("foo/bar").spec()});
for (const auto& url_string : kFailedCommitURLs) {
const GURL commit_url(url_string);
EXPECT_FALSE(p->CanCommitURL(kRendererID, commit_url)) << commit_url;
EXPECT_FALSE(handle.CanCommitURL(commit_url)) << commit_url;
}
p->Remove(kRendererID);
}
TEST_P(ChildProcessSecurityPolicyTest, BlobSchemeTest) {
ChildProcessSecurityPolicyImpl* p =
ChildProcessSecurityPolicyImpl::GetInstance();
GURL localhost_url("http://localhost/");
p->AddForTesting(kRendererID, browser_context());
LockProcessIfNeeded(kRendererID, browser_context(), localhost_url);
EXPECT_TRUE(
p->CanRequestURL(kRendererID, GURL("blob:http://localhost/some-guid")));
EXPECT_TRUE(p->CanRequestURL(kRendererID, GURL("blob:null/some-guid")));
EXPECT_TRUE(
p->CanRequestURL(kRendererID, GURL("blob:http://localhost/some-guid")));
EXPECT_TRUE(p->CanRequestURL(kRendererID, GURL("blob:NulL/some-guid")));
EXPECT_TRUE(
p->CanRequestURL(kRendererID, GURL("blob:NulL/some-guid#fragment")));
EXPECT_TRUE(p->CanRequestURL(kRendererID, GURL("blob:NulL/some-guid?query")));
EXPECT_FALSE(p->CanRequestURL(
kRendererID, GURL("blob:http://username@localhost/some-guid")));
EXPECT_FALSE(p->CanRequestURL(
kRendererID, GURL("blob:http://username @localhost/some-guid")));
EXPECT_FALSE(p->CanRequestURL(kRendererID, GURL("blob:blob:some-guid")));
EXPECT_FALSE(p->CanRequestURL(kRendererID, GURL("blob:some-guid")));
EXPECT_FALSE(p->CanRequestURL(kRendererID,
GURL("blob:filesystem:http://localhost/path")));
EXPECT_FALSE(p->CanRequestURL(kRendererID,
GURL("filesystem:blob:http://localhost/guid")));
EXPECT_TRUE(p->CanRedirectToURL(GURL("blob:http://localhost/some-guid")));
EXPECT_TRUE(p->CanRedirectToURL(GURL("blob:null/some-guid")));
EXPECT_TRUE(p->CanRedirectToURL(GURL("blob:http://localhost/some-guid")));
EXPECT_TRUE(p->CanRedirectToURL(GURL("blob:NulL/some-guid")));
EXPECT_TRUE(p->CanRedirectToURL(GURL("blob:NulL/some-guid#fragment")));
EXPECT_TRUE(p->CanRedirectToURL(GURL("blob:NulL/some-guid?query")));
EXPECT_TRUE(
p->CanRedirectToURL(GURL("blob:http://username@localhost/some-guid")));
EXPECT_TRUE(p->CanRedirectToURL(
GURL("blob:http://username @localhost/some-guid")));
EXPECT_TRUE(p->CanRedirectToURL(GURL("blob:blob:some-guid")));
EXPECT_TRUE(p->CanRedirectToURL(GURL("blob:some-guid")));
EXPECT_TRUE(
p->CanRedirectToURL(GURL("blob:filesystem:http://localhost/path")));
EXPECT_FALSE(
p->CanRedirectToURL(GURL("filesystem:blob:http://localhost/guid")));
EXPECT_TRUE(
p->CanCommitURL(kRendererID, GURL("blob:http://localhost/some-guid")));
EXPECT_TRUE(p->CanCommitURL(kRendererID, GURL("blob:null/some-guid")));
EXPECT_TRUE(
p->CanCommitURL(kRendererID, GURL("blob:http://localhost/some-guid")));
EXPECT_TRUE(p->CanCommitURL(kRendererID, GURL("blob:NulL/some-guid")));
EXPECT_TRUE(
p->CanCommitURL(kRendererID, GURL("blob:NulL/some-guid#fragment")));
EXPECT_FALSE(p->CanCommitURL(
kRendererID, GURL("blob:http://username@localhost/some-guid")));
EXPECT_FALSE(p->CanCommitURL(
kRendererID, GURL("blob:http://username @localhost/some-guid")));
EXPECT_FALSE(p->CanCommitURL(kRendererID, GURL("blob:blob:some-guid")));
EXPECT_FALSE(p->CanCommitURL(kRendererID, GURL("blob:some-guid")));
EXPECT_FALSE(p->CanCommitURL(kRendererID,
GURL("blob:filesystem:http://localhost/path")));
EXPECT_FALSE(p->CanCommitURL(kRendererID,
GURL("filesystem:blob:http://localhost/guid")));
p->Remove(kRendererID);
}
TEST_P(ChildProcessSecurityPolicyTest, AboutTest) {
ChildProcessSecurityPolicyImpl* p =
ChildProcessSecurityPolicyImpl::GetInstance();
p->AddForTesting(kRendererID, browser_context());
EXPECT_TRUE(p->CanRequestURL(kRendererID, GURL("about:blank")));
EXPECT_FALSE(p->CanRequestURL(kRendererID, GURL("about:BlAnK")));
EXPECT_FALSE(p->CanRequestURL(kRendererID, GURL("aBouT:BlAnK")));
EXPECT_TRUE(p->CanRequestURL(kRendererID, GURL("aBouT:blank")));
EXPECT_TRUE(p->CanRedirectToURL(GURL("about:blank")));
EXPECT_FALSE(p->CanRedirectToURL(GURL("about:BlAnK")));
EXPECT_FALSE(p->CanRedirectToURL(GURL("aBouT:BlAnK")));
EXPECT_TRUE(p->CanRedirectToURL(GURL("aBouT:blank")));
EXPECT_TRUE(p->CanCommitURL(kRendererID, GURL("about:blank")));
EXPECT_FALSE(p->CanCommitURL(kRendererID, GURL("about:BlAnK")));
EXPECT_FALSE(p->CanCommitURL(kRendererID, GURL("aBouT:BlAnK")));
EXPECT_TRUE(p->CanCommitURL(kRendererID, GURL("aBouT:blank")));
EXPECT_TRUE(p->CanRequestURL(kRendererID, GURL("about:srcdoc")));
EXPECT_FALSE(p->CanRedirectToURL(GURL("about:srcdoc")));
EXPECT_TRUE(p->CanCommitURL(kRendererID, GURL("about:srcdoc")));
EXPECT_FALSE(p->CanRequestURL(kRendererID, GURL("about:SRCDOC")));
EXPECT_FALSE(p->CanCommitURL(kRendererID, GURL("about:SRCDOC")));
EXPECT_FALSE(p->CanRequestURL(kRendererID, GURL("about:crash")));
EXPECT_FALSE(p->CanRequestURL(kRendererID, GURL("about:cache")));
EXPECT_FALSE(p->CanRequestURL(kRendererID, GURL("about:hang")));
EXPECT_FALSE(p->CanRequestURL(kRendererID, GURL("about:version")));
EXPECT_FALSE(p->CanRedirectToURL(GURL("about:crash")));
EXPECT_FALSE(p->CanRedirectToURL(GURL("about:cache")));
EXPECT_FALSE(p->CanRedirectToURL(GURL("about:hang")));
EXPECT_FALSE(p->CanRedirectToURL(GURL("about:version")));
EXPECT_FALSE(p->CanCommitURL(kRendererID, GURL("about:crash")));
EXPECT_FALSE(p->CanCommitURL(kRendererID, GURL("about:cache")));
EXPECT_FALSE(p->CanCommitURL(kRendererID, GURL("about:hang")));
EXPECT_FALSE(p->CanCommitURL(kRendererID, GURL("about:version")));
EXPECT_FALSE(p->CanRequestURL(kRendererID, GURL("aBoUt:version")));
EXPECT_FALSE(p->CanRequestURL(kRendererID, GURL("about:CrASh")));
EXPECT_FALSE(p->CanRequestURL(kRendererID, GURL("abOuT:cAChe")));
EXPECT_FALSE(p->CanRedirectToURL(GURL("aBoUt:version")));
EXPECT_FALSE(p->CanRedirectToURL(GURL("about:CrASh")));
EXPECT_FALSE(p->CanRedirectToURL(GURL("abOuT:cAChe")));
EXPECT_FALSE(p->CanCommitURL(kRendererID, GURL("aBoUt:version")));
EXPECT_FALSE(p->CanCommitURL(kRendererID, GURL("about:CrASh")));
EXPECT_FALSE(p->CanCommitURL(kRendererID, GURL("abOuT:cAChe")));
EXPECT_FALSE(p->CanCommitURL(kRendererID, GURL("aBoUt:version")));
p->GrantCommitURL(kRendererID, GURL("about:crash"));
EXPECT_FALSE(p->CanRequestURL(kRendererID, GURL("about:crash")));
EXPECT_FALSE(p->CanRedirectToURL(GURL("about:crash")));
EXPECT_FALSE(p->CanCommitURL(kRendererID, GURL("about:crash")));
p->Remove(kRendererID);
}
TEST_P(ChildProcessSecurityPolicyTest, JavaScriptTest) {
ChildProcessSecurityPolicyImpl* p =
ChildProcessSecurityPolicyImpl::GetInstance();
p->AddForTesting(kRendererID, browser_context());
EXPECT_FALSE(p->CanRequestURL(kRendererID, GURL("javascript:alert('xss')")));
EXPECT_FALSE(p->CanRedirectToURL(GURL("javascript:alert('xss')")));
EXPECT_FALSE(p->CanCommitURL(kRendererID, GURL("javascript:alert('xss')")));
p->GrantCommitURL(kRendererID, GURL("javascript:alert('xss')"));
EXPECT_FALSE(p->CanRequestURL(kRendererID, GURL("javascript:alert('xss')")));
EXPECT_FALSE(p->CanRedirectToURL(GURL("javascript:alert('xss')")));
EXPECT_FALSE(p->CanCommitURL(kRendererID, GURL("javascript:alert('xss')")));
p->Remove(kRendererID);
}
TEST_P(ChildProcessSecurityPolicyTest, RegisterWebSafeSchemeTest) {
ChildProcessSecurityPolicyImpl* p =
ChildProcessSecurityPolicyImpl::GetInstance();
p->AddForTesting(kRendererID, browser_context());
EXPECT_TRUE(p->CanRequestURL(kRendererID, GURL("asdf:rockers")));
EXPECT_TRUE(p->CanRedirectToURL(GURL("asdf:rockers")));
EXPECT_FALSE(p->CanCommitURL(kRendererID, GURL("asdf:rockers")));
RegisterTestScheme("asdf");
EXPECT_FALSE(p->CanRequestURL(kRendererID, GURL("asdf:rockers")));
EXPECT_TRUE(p->CanRedirectToURL(GURL("asdf:rockers")));
EXPECT_FALSE(p->CanCommitURL(kRendererID, GURL("asdf:rockers")));
p->RegisterWebSafeScheme("asdf");
EXPECT_TRUE(p->CanRequestURL(kRendererID, GURL("asdf:rockers")));
EXPECT_TRUE(p->CanRedirectToURL(GURL("asdf:rockers")));
if (AreAllSitesIsolatedForTesting() && IsCitadelProtectionEnabled()) {
EXPECT_FALSE(p->CanCommitURL(kRendererID, GURL("asdf:rockers")));
LockProcessIfNeeded(kRendererID, browser_context(), GURL("asdf:rockers"));
EXPECT_TRUE(p->CanCommitURL(kRendererID, GURL("asdf:rockers")));
} else {
EXPECT_TRUE(p->CanCommitURL(kRendererID, GURL("asdf:rockers")));
}
p->Remove(kRendererID);
p->ClearRegisteredSchemeForTesting("asdf");
}
TEST_P(ChildProcessSecurityPolicyTest, CanServiceCommandsTest) {
ChildProcessSecurityPolicyImpl* p =
ChildProcessSecurityPolicyImpl::GetInstance();
GURL file_url("file:///etc/passwd");
p->AddForTesting(kRendererID, browser_context());
LockProcessIfNeeded(kRendererID, browser_context(), file_url);
EXPECT_FALSE(p->CanRequestURL(kRendererID, GURL("file:///etc/passwd")));
EXPECT_TRUE(p->CanRedirectToURL(GURL("file:///etc/passwd")));
EXPECT_FALSE(p->CanCommitURL(kRendererID, GURL("file:///etc/passwd")));
p->GrantCommitURL(kRendererID, GURL("file:///etc/passwd"));
EXPECT_TRUE(p->CanRequestURL(kRendererID, GURL("file:///etc/passwd")));
EXPECT_TRUE(p->CanRedirectToURL(GURL("file:///etc/passwd")));
EXPECT_TRUE(p->CanCommitURL(kRendererID, GURL("file:///etc/passwd")));
p->Remove(kRendererID);
p->AddForTesting(kRendererID, browser_context());
EXPECT_FALSE(p->CanRequestURL(kRendererID, GURL("file:///etc/passwd")));
EXPECT_TRUE(p->CanRedirectToURL(GURL("file:///etc/passwd")));
EXPECT_FALSE(p->CanCommitURL(kRendererID, GURL("file:///etc/passwd")));
p->Remove(kRendererID);
}
TEST_P(ChildProcessSecurityPolicyTest, ViewSource) {
ChildProcessSecurityPolicyImpl* p =
ChildProcessSecurityPolicyImpl::GetInstance();
p->AddForTesting(kRendererID, browser_context());
EXPECT_FALSE(p->CanRequestURL(kRendererID,
GURL("view-source:http://www.google.com/")));
EXPECT_FALSE(p->CanRequestURL(kRendererID,
GURL("view-source:file:///etc/passwd")));
EXPECT_FALSE(p->CanRequestURL(kRendererID, GURL("file:///etc/passwd")));
EXPECT_FALSE(p->CanRequestURL(
kRendererID, GURL("view-source:view-source:http://www.google.com/")));
EXPECT_FALSE(p->CanRedirectToURL(GURL("view-source:http://www.google.com/")));
EXPECT_FALSE(p->CanRedirectToURL(GURL("view-source:file:///etc/passwd")));
EXPECT_TRUE(p->CanRedirectToURL(GURL("file:///etc/passwd")));
EXPECT_FALSE(p->CanRedirectToURL(
GURL("view-source:view-source:http://www.google.com/")));
EXPECT_FALSE(p->CanCommitURL(kRendererID,
GURL("view-source:http://www.google.com/")));
EXPECT_FALSE(p->CanCommitURL(kRendererID,
GURL("view-source:file:///etc/passwd")));
EXPECT_FALSE(p->CanCommitURL(kRendererID, GURL("file:///etc/passwd")));
EXPECT_FALSE(p->CanCommitURL(
kRendererID, GURL("view-source:view-source:http://www.google.com/")));
p->GrantCommitURL(kRendererID, GURL("view-source:file:///etc/passwd"));
EXPECT_FALSE(p->CanRequestURL(kRendererID, GURL("file:///etc/passwd")));
EXPECT_TRUE(p->CanRedirectToURL(GURL("file:///etc/passwd")));
EXPECT_FALSE(p->CanCommitURL(kRendererID, GURL("file:///etc/passwd")));
EXPECT_FALSE(
p->CanRequestURL(kRendererID, GURL("view-source:file:///etc/passwd")));
EXPECT_FALSE(p->CanRedirectToURL(GURL("view-source:file:///etc/passwd")));
EXPECT_FALSE(p->CanCommitURL(kRendererID,
GURL("view-source:file:///etc/passwd")));
p->Remove(kRendererID);
}
TEST_P(ChildProcessSecurityPolicyTest, GoogleChromeScheme) {
ChildProcessSecurityPolicyImpl* p =
ChildProcessSecurityPolicyImpl::GetInstance();
p->AddForTesting(kRendererID, browser_context());
GURL test_url("googlechrome://whatever");
EXPECT_FALSE(p->CanRequestURL(kRendererID, test_url));
EXPECT_FALSE(p->CanRedirectToURL(test_url));
EXPECT_FALSE(p->CanCommitURL(kRendererID, test_url));
p->Remove(kRendererID);
}
TEST_P(ChildProcessSecurityPolicyTest, GrantCommitURLToNonStandardScheme) {
ChildProcessSecurityPolicyImpl* p =
ChildProcessSecurityPolicyImpl::GetInstance();
const GURL url("httpxml://awesome");
const GURL url2("httpxml://also-awesome");
ASSERT_TRUE(url::Origin::Create(url).opaque());
ASSERT_TRUE(url::Origin::Create(url2).opaque());
RegisterTestScheme("httpxml");
p->AddForTesting(kRendererID, browser_context());
LockProcessIfNeeded(kRendererID, browser_context(), url);
EXPECT_FALSE(p->CanRequestURL(kRendererID, url));
EXPECT_FALSE(p->CanRequestURL(kRendererID, url2));
EXPECT_TRUE(p->CanRedirectToURL(url));
EXPECT_TRUE(p->CanRedirectToURL(url2));
EXPECT_FALSE(p->CanCommitURL(kRendererID, url));
EXPECT_FALSE(p->CanCommitURL(kRendererID, url2));
p->GrantCommitURL(kRendererID, url);
EXPECT_TRUE(p->CanRequestURL(kRendererID, url));
EXPECT_TRUE(p->CanRequestURL(kRendererID, url2));
EXPECT_TRUE(p->CanRedirectToURL(url));
EXPECT_TRUE(p->CanRedirectToURL(url2));
EXPECT_TRUE(p->CanCommitURL(kRendererID, url));
EXPECT_TRUE(p->CanCommitURL(kRendererID, url2));
p->Remove(kRendererID);
}
TEST_P(ChildProcessSecurityPolicyTest, SpecificFile) {
ChildProcessSecurityPolicyImpl* p =
ChildProcessSecurityPolicyImpl::GetInstance();
GURL icon_url("file:///tmp/foo.png");
GURL sensitive_url("file:///etc/passwd");
p->AddForTesting(kRendererID, browser_context());
LockProcessIfNeeded(kRendererID, browser_context(), sensitive_url);
EXPECT_FALSE(p->CanRequestURL(kRendererID, icon_url));
EXPECT_FALSE(p->CanRequestURL(kRendererID, sensitive_url));
EXPECT_TRUE(p->CanRedirectToURL(icon_url));
EXPECT_TRUE(p->CanRedirectToURL(sensitive_url));
EXPECT_FALSE(p->CanCommitURL(kRendererID, icon_url));
EXPECT_FALSE(p->CanCommitURL(kRendererID, sensitive_url));
p->GrantRequestSpecificFileURL(kRendererID, icon_url);
EXPECT_TRUE(p->CanRequestURL(kRendererID, icon_url));
EXPECT_FALSE(p->CanRequestURL(kRendererID, sensitive_url));
EXPECT_TRUE(p->CanRedirectToURL(icon_url));
EXPECT_TRUE(p->CanRedirectToURL(sensitive_url));
EXPECT_TRUE(p->CanCommitURL(kRendererID, icon_url));
EXPECT_FALSE(p->CanCommitURL(kRendererID, sensitive_url));
p->GrantCommitURL(kRendererID, icon_url);
EXPECT_TRUE(p->CanRequestURL(kRendererID, icon_url));
EXPECT_TRUE(p->CanRequestURL(kRendererID, sensitive_url));
EXPECT_TRUE(p->CanRedirectToURL(icon_url));
EXPECT_TRUE(p->CanRedirectToURL(sensitive_url));
EXPECT_TRUE(p->CanCommitURL(kRendererID, icon_url));
EXPECT_TRUE(p->CanCommitURL(kRendererID, sensitive_url));
p->Remove(kRendererID);
}
TEST_P(ChildProcessSecurityPolicyTest, FileSystemGrantsTest) {
ChildProcessSecurityPolicyImpl* p =
ChildProcessSecurityPolicyImpl::GetInstance();
p->AddForTesting(kRendererID, browser_context());
std::string read_id =
storage::IsolatedContext::GetInstance()->RegisterFileSystemForVirtualPath(
storage::kFileSystemTypeTest, "read_filesystem", base::FilePath());
std::string read_write_id =
storage::IsolatedContext::GetInstance()->RegisterFileSystemForVirtualPath(
storage::kFileSystemTypeTest,
"read_write_filesystem",
base::FilePath());
std::string copy_into_id =
storage::IsolatedContext::GetInstance()->RegisterFileSystemForVirtualPath(
storage::kFileSystemTypeTest,
"copy_into_filesystem",
base::FilePath());
std::string delete_from_id =
storage::IsolatedContext::GetInstance()->RegisterFileSystemForVirtualPath(
storage::kFileSystemTypeTest,
"delete_from_filesystem",
base::FilePath());
CheckHasNoFileSystemPermission(p, read_id);
CheckHasNoFileSystemPermission(p, read_write_id);
CheckHasNoFileSystemPermission(p, copy_into_id);
CheckHasNoFileSystemPermission(p, delete_from_id);
p->GrantReadFileSystem(kRendererID, read_id);
EXPECT_TRUE(p->CanReadFileSystem(kRendererID, read_id));
EXPECT_FALSE(p->CanReadWriteFileSystem(kRendererID, read_id));
EXPECT_FALSE(p->CanCopyIntoFileSystem(kRendererID, read_id));
EXPECT_FALSE(p->CanDeleteFromFileSystem(kRendererID, read_id));
p->GrantReadFileSystem(kRendererID, read_write_id);
p->GrantWriteFileSystem(kRendererID, read_write_id);
EXPECT_TRUE(p->CanReadFileSystem(kRendererID, read_write_id));
EXPECT_TRUE(p->CanReadWriteFileSystem(kRendererID, read_write_id));
EXPECT_FALSE(p->CanCopyIntoFileSystem(kRendererID, read_write_id));
EXPECT_FALSE(p->CanDeleteFromFileSystem(kRendererID, read_write_id));
p->GrantCopyIntoFileSystem(kRendererID, copy_into_id);
EXPECT_FALSE(p->CanReadFileSystem(kRendererID, copy_into_id));
EXPECT_FALSE(p->CanReadWriteFileSystem(kRendererID, copy_into_id));
EXPECT_TRUE(p->CanCopyIntoFileSystem(kRendererID, copy_into_id));
EXPECT_FALSE(p->CanDeleteFromFileSystem(kRendererID, copy_into_id));
p->GrantDeleteFromFileSystem(kRendererID, delete_from_id);
EXPECT_FALSE(p->CanReadFileSystem(kRendererID, delete_from_id));
EXPECT_FALSE(p->CanReadWriteFileSystem(kRendererID, delete_from_id));
EXPECT_FALSE(p->CanCopyIntoFileSystem(kRendererID, delete_from_id));
EXPECT_TRUE(p->CanDeleteFromFileSystem(kRendererID, delete_from_id));
p->Remove(kRendererID);
CheckHasNoFileSystemPermission(p, read_id);
CheckHasNoFileSystemPermission(p, read_write_id);
CheckHasNoFileSystemPermission(p, copy_into_id);
CheckHasNoFileSystemPermission(p, delete_from_id);
p->AddForTesting(kRendererID, browser_context());
CheckHasNoFileSystemPermission(p, read_id);
CheckHasNoFileSystemPermission(p, read_write_id);
CheckHasNoFileSystemPermission(p, copy_into_id);
CheckHasNoFileSystemPermission(p, delete_from_id);
p->Remove(kRendererID);
storage::IsolatedContext::GetInstance()->RevokeFileSystem(read_id);
storage::IsolatedContext::GetInstance()->RevokeFileSystem(read_write_id);
storage::IsolatedContext::GetInstance()->RevokeFileSystem(copy_into_id);
storage::IsolatedContext::GetInstance()->RevokeFileSystem(delete_from_id);
}
TEST_P(ChildProcessSecurityPolicyTest, FilePermissionGrantingAndRevoking) {
ChildProcessSecurityPolicyImpl* p =
ChildProcessSecurityPolicyImpl::GetInstance();
p->RegisterFileSystemPermissionPolicy(
storage::kFileSystemTypeTest,
storage::FILE_PERMISSION_USE_FILE_PERMISSION);
p->AddForTesting(kRendererID, browser_context());
LockProcessIfNeeded(kRendererID, browser_context(), GURL("http://foo/"));
base::FilePath file(TEST_PATH("/dir/testfile"));
file = file.NormalizePathSeparators();
storage::FileSystemURL url = storage::FileSystemURL::CreateForTest(
blink::StorageKey::CreateFromStringForTesting("http://foo/"),
storage::kFileSystemTypeTest, file);
CheckHasNoFileSystemFilePermission(p, file, url);
p->GrantReadFile(kRendererID, file);
EXPECT_TRUE(p->CanReadFile(kRendererID, file));
EXPECT_FALSE(p->CanCreateReadWriteFile(kRendererID, file));
EXPECT_TRUE(p->CanReadFileSystemFile(kRendererID, url));
EXPECT_FALSE(p->CanWriteFileSystemFile(kRendererID, url));
EXPECT_FALSE(p->CanCreateFileSystemFile(kRendererID, url));
EXPECT_FALSE(p->CanCreateReadWriteFileSystemFile(kRendererID, url));
EXPECT_FALSE(p->CanCopyIntoFileSystemFile(kRendererID, url));
EXPECT_FALSE(p->CanDeleteFileSystemFile(kRendererID, url));
p->RevokeAllPermissionsForFile(kRendererID, file);
CheckHasNoFileSystemFilePermission(p, file, url);
p->GrantCreateReadWriteFile(kRendererID, file);
EXPECT_TRUE(p->CanReadFile(kRendererID, file));
EXPECT_TRUE(p->CanCreateReadWriteFile(kRendererID, file));
EXPECT_TRUE(p->CanReadFileSystemFile(kRendererID, url));
EXPECT_TRUE(p->CanWriteFileSystemFile(kRendererID, url));
EXPECT_TRUE(p->CanCreateFileSystemFile(kRendererID, url));
EXPECT_TRUE(p->CanCreateReadWriteFileSystemFile(kRendererID, url));
EXPECT_TRUE(p->CanCopyIntoFileSystemFile(kRendererID, url));
EXPECT_TRUE(p->CanDeleteFileSystemFile(kRendererID, url));
p->RevokeAllPermissionsForFile(kRendererID, file);
CheckHasNoFileSystemFilePermission(p, file, url);
p->GrantCreateReadWriteFile(kRendererID, file);
EXPECT_TRUE(p->CanReadFile(kRendererID, file));
EXPECT_TRUE(p->CanCreateReadWriteFile(kRendererID, file));
EXPECT_TRUE(p->CanReadFileSystemFile(kRendererID, url));
EXPECT_TRUE(p->CanWriteFileSystemFile(kRendererID, url));
EXPECT_TRUE(p->CanCreateFileSystemFile(kRendererID, url));
EXPECT_TRUE(p->CanCreateReadWriteFileSystemFile(kRendererID, url));
EXPECT_TRUE(p->CanCopyIntoFileSystemFile(kRendererID, url));
EXPECT_TRUE(p->CanDeleteFileSystemFile(kRendererID, url));
p->Remove(kRendererID);
CheckHasNoFileSystemFilePermission(p, file, url);
p->AddForTesting(kRendererID, browser_context());
CheckHasNoFileSystemFilePermission(p, file, url);
LockProcessIfNeeded(kRendererID, browser_context(), GURL("http://foo/"));
CheckHasNoFileSystemFilePermission(p, file, url);
p->Remove(kRendererID);
}
TEST_P(ChildProcessSecurityPolicyTest, FilePermissions) {
base::FilePath granted_file = base::FilePath(TEST_PATH("/home/joe"));
base::FilePath sibling_file = base::FilePath(TEST_PATH("/home/bob"));
base::FilePath child_file = base::FilePath(TEST_PATH("/home/joe/file"));
base::FilePath parent_file = base::FilePath(TEST_PATH("/home"));
base::FilePath parent_slash_file = base::FilePath(TEST_PATH("/home/"));
base::FilePath child_traversal1 =
base::FilePath(TEST_PATH("/home/joe/././file"));
base::FilePath child_traversal2 = base::FilePath(
TEST_PATH("/home/joe/file/../otherfile"));
base::FilePath evil_traversal1 =
base::FilePath(TEST_PATH("/home/joe/../../etc/passwd"));
base::FilePath evil_traversal2 = base::FilePath(
TEST_PATH("/home/joe/./.././../etc/passwd"));
base::FilePath self_traversal =
base::FilePath(TEST_PATH("/home/joe/../joe/file"));
base::FilePath relative_file = base::FilePath(FILE_PATH_LITERAL("home/joe"));
ChildProcessSecurityPolicyImpl* p =
ChildProcessSecurityPolicyImpl::GetInstance();
p->AddForTesting(kRendererID, browser_context());
EXPECT_FALSE(p->HasPermissionsForFile(kRendererID, granted_file,
base::File::FLAG_OPEN));
GrantPermissionsForFile(p, kRendererID, granted_file,
base::File::FLAG_OPEN |
base::File::FLAG_OPEN_TRUNCATED |
base::File::FLAG_READ |
base::File::FLAG_WRITE);
EXPECT_TRUE(p->HasPermissionsForFile(kRendererID, granted_file,
base::File::FLAG_OPEN |
base::File::FLAG_OPEN_TRUNCATED |
base::File::FLAG_READ |
base::File::FLAG_WRITE));
EXPECT_TRUE(p->HasPermissionsForFile(kRendererID, granted_file,
base::File::FLAG_OPEN |
base::File::FLAG_READ));
EXPECT_FALSE(p->HasPermissionsForFile(kRendererID, granted_file,
base::File::FLAG_CREATE));
EXPECT_FALSE(p->HasPermissionsForFile(kRendererID, granted_file, 0));
EXPECT_FALSE(p->HasPermissionsForFile(kRendererID, granted_file,
base::File::FLAG_CREATE |
base::File::FLAG_OPEN_TRUNCATED |
base::File::FLAG_READ |
base::File::FLAG_WRITE));
EXPECT_FALSE(p->HasPermissionsForFile(kRendererID, sibling_file,
base::File::FLAG_OPEN |
base::File::FLAG_READ));
EXPECT_FALSE(p->HasPermissionsForFile(kRendererID, parent_file,
base::File::FLAG_OPEN |
base::File::FLAG_READ));
EXPECT_TRUE(p->HasPermissionsForFile(kRendererID, child_file,
base::File::FLAG_OPEN |
base::File::FLAG_READ));
EXPECT_TRUE(p->HasPermissionsForFile(kRendererID, child_traversal1,
base::File::FLAG_OPEN |
base::File::FLAG_READ));
EXPECT_TRUE(p->HasPermissionsForFile(kRendererID, child_traversal2,
base::File::FLAG_OPEN |
base::File::FLAG_READ));
EXPECT_FALSE(p->HasPermissionsForFile(kRendererID, evil_traversal1,
base::File::FLAG_OPEN |
base::File::FLAG_READ));
EXPECT_FALSE(p->HasPermissionsForFile(kRendererID, evil_traversal2,
base::File::FLAG_OPEN |
base::File::FLAG_READ));
EXPECT_FALSE(p->HasPermissionsForFile(kRendererID, self_traversal,
base::File::FLAG_OPEN |
base::File::FLAG_READ));
p->Remove(kRendererID);
p->AddForTesting(kRendererID, browser_context());
EXPECT_FALSE(p->HasPermissionsForFile(kRendererID, granted_file,
base::File::FLAG_OPEN));
GrantPermissionsForFile(p, kRendererID, parent_file,
base::File::FLAG_OPEN |
base::File::FLAG_READ);
EXPECT_TRUE(p->HasPermissionsForFile(kRendererID, granted_file,
base::File::FLAG_OPEN));
EXPECT_FALSE(p->HasPermissionsForFile(kRendererID, granted_file,
base::File::FLAG_READ |
base::File::FLAG_WRITE));
p->Remove(kRendererID);
p->AddForTesting(kRendererID, browser_context());
EXPECT_FALSE(p->HasPermissionsForFile(kRendererID, granted_file,
base::File::FLAG_OPEN));
GrantPermissionsForFile(p, kRendererID, parent_slash_file,
base::File::FLAG_OPEN |
base::File::FLAG_READ);
EXPECT_TRUE(p->HasPermissionsForFile(kRendererID, granted_file,
base::File::FLAG_OPEN));
EXPECT_FALSE(p->HasPermissionsForFile(kRendererID, granted_file,
base::File::FLAG_READ |
base::File::FLAG_WRITE));
GrantPermissionsForFile(p, kRendererID, granted_file,
base::File::FLAG_WIN_TEMPORARY);
EXPECT_FALSE(p->HasPermissionsForFile(kRendererID, granted_file,
base::File::FLAG_OPEN));
EXPECT_TRUE(p->HasPermissionsForFile(kRendererID, granted_file,
base::File::FLAG_WIN_TEMPORARY));
p->RevokeAllPermissionsForFile(kRendererID, granted_file);
EXPECT_TRUE(p->HasPermissionsForFile(kRendererID, granted_file,
base::File::FLAG_OPEN |
base::File::FLAG_READ));
EXPECT_FALSE(p->HasPermissionsForFile(kRendererID, granted_file,
base::File::FLAG_WIN_TEMPORARY));
p->Remove(kRendererID);
p->AddForTesting(kRendererID, browser_context());
GrantPermissionsForFile(p, kRendererID, relative_file,
base::File::FLAG_OPEN);
EXPECT_FALSE(p->HasPermissionsForFile(kRendererID, relative_file,
base::File::FLAG_OPEN));
p->Remove(kRendererID);
}
TEST_P(ChildProcessSecurityPolicyTest, CanServiceWebUIBindings) {
ChildProcessSecurityPolicyImpl* p =
ChildProcessSecurityPolicyImpl::GetInstance();
const GURL url(GetWebUIURL("thumb/http://www.google.com/"));
const GURL other_url(GetWebUIURL("not-thumb/"));
const url::Origin origin = url::Origin::Create(url);
{
p->AddForTesting(kRendererID, browser_context());
LockProcessIfNeeded(kRendererID, browser_context(), url);
EXPECT_FALSE(p->HasWebUIBindings(kRendererID));
EXPECT_FALSE(p->CanRequestURL(kRendererID, url));
EXPECT_FALSE(p->CanCommitURL(kRendererID, url));
EXPECT_TRUE(p->CanRedirectToURL(url));
EXPECT_FALSE(p->CanRequestURL(kRendererID, other_url));
EXPECT_FALSE(p->CanCommitURL(kRendererID, other_url));
EXPECT_TRUE(p->CanRedirectToURL(other_url));
p->GrantWebUIBindings(kRendererID, BINDINGS_POLICY_WEB_UI);
EXPECT_TRUE(p->HasWebUIBindings(kRendererID));
EXPECT_FALSE(p->CanRequestURL(kRendererID, url));
EXPECT_FALSE(p->CanCommitURL(kRendererID, url));
EXPECT_TRUE(p->CanRedirectToURL(url));
EXPECT_FALSE(p->CanRequestURL(kRendererID, other_url));
EXPECT_FALSE(p->CanCommitURL(kRendererID, other_url));
EXPECT_TRUE(p->CanRedirectToURL(other_url));
p->GrantCommitOrigin(kRendererID, origin);
EXPECT_TRUE(p->CanRequestURL(kRendererID, url));
EXPECT_TRUE(p->CanCommitURL(kRendererID, url));
EXPECT_TRUE(p->CanRedirectToURL(url));
EXPECT_FALSE(p->CanRequestURL(kRendererID, other_url));
EXPECT_FALSE(p->CanCommitURL(kRendererID, other_url));
EXPECT_TRUE(p->CanRedirectToURL(other_url));
p->Remove(kRendererID);
}
{
p->AddForTesting(kRendererID, browser_context());
LockProcessIfNeeded(kRendererID, browser_context(), url);
EXPECT_FALSE(p->HasWebUIBindings(kRendererID));
EXPECT_FALSE(p->CanRequestURL(kRendererID, url));
EXPECT_FALSE(p->CanCommitURL(kRendererID, url));
EXPECT_TRUE(p->CanRedirectToURL(url));
EXPECT_FALSE(p->CanRequestURL(kRendererID, other_url));
EXPECT_FALSE(p->CanCommitURL(kRendererID, other_url));
EXPECT_TRUE(p->CanRedirectToURL(other_url));
p->GrantWebUIBindings(kRendererID, BINDINGS_POLICY_MOJO_WEB_UI);
EXPECT_TRUE(p->HasWebUIBindings(kRendererID));
EXPECT_FALSE(p->CanRequestURL(kRendererID, url));
EXPECT_FALSE(p->CanCommitURL(kRendererID, url));
EXPECT_TRUE(p->CanRedirectToURL(url));
EXPECT_FALSE(p->CanRequestURL(kRendererID, other_url));
EXPECT_FALSE(p->CanCommitURL(kRendererID, other_url));
EXPECT_TRUE(p->CanRedirectToURL(other_url));
p->GrantCommitOrigin(kRendererID, origin);
EXPECT_TRUE(p->CanRequestURL(kRendererID, url));
EXPECT_TRUE(p->CanCommitURL(kRendererID, url));
EXPECT_TRUE(p->CanRedirectToURL(url));
EXPECT_FALSE(p->CanRequestURL(kRendererID, other_url));
EXPECT_FALSE(p->CanCommitURL(kRendererID, other_url));
EXPECT_TRUE(p->CanRedirectToURL(other_url));
p->Remove(kRendererID);
}
{
p->AddForTesting(kRendererID, browser_context());
LockProcessIfNeeded(kRendererID, browser_context(), url);
EXPECT_FALSE(p->HasWebUIBindings(kRendererID));
EXPECT_FALSE(p->CanRequestURL(kRendererID, url));
EXPECT_FALSE(p->CanCommitURL(kRendererID, url));
EXPECT_TRUE(p->CanRedirectToURL(url));
EXPECT_FALSE(p->CanRequestURL(kRendererID, other_url));
EXPECT_FALSE(p->CanCommitURL(kRendererID, other_url));
EXPECT_TRUE(p->CanRedirectToURL(other_url));
p->GrantWebUIBindings(kRendererID,
BINDINGS_POLICY_WEB_UI | BINDINGS_POLICY_MOJO_WEB_UI);
EXPECT_TRUE(p->HasWebUIBindings(kRendererID));
EXPECT_FALSE(p->CanRequestURL(kRendererID, url));
EXPECT_FALSE(p->CanCommitURL(kRendererID, url));
EXPECT_TRUE(p->CanRedirectToURL(url));
EXPECT_FALSE(p->CanRequestURL(kRendererID, other_url));
EXPECT_FALSE(p->CanCommitURL(kRendererID, other_url));
EXPECT_TRUE(p->CanRedirectToURL(other_url));
p->GrantCommitOrigin(kRendererID, origin);
EXPECT_TRUE(p->CanRequestURL(kRendererID, url));
EXPECT_TRUE(p->CanCommitURL(kRendererID, url));
EXPECT_TRUE(p->CanRedirectToURL(url));
EXPECT_FALSE(p->CanRequestURL(kRendererID, other_url));
EXPECT_FALSE(p->CanCommitURL(kRendererID, other_url));
EXPECT_TRUE(p->CanRedirectToURL(other_url));
p->Remove(kRendererID);
}
}
TEST_P(ChildProcessSecurityPolicyTest, RemoveRace) {
ChildProcessSecurityPolicyImpl* p =
ChildProcessSecurityPolicyImpl::GetInstance();
GURL url("file:///etc/passwd");
base::FilePath file(TEST_PATH("/etc/passwd"));
p->AddForTesting(kRendererID, browser_context());
p->GrantCommitURL(kRendererID, url);
p->GrantReadFile(kRendererID, file);
p->GrantWebUIBindings(kRendererID,
BINDINGS_POLICY_WEB_UI | BINDINGS_POLICY_MOJO_WEB_UI);
EXPECT_TRUE(p->CanRequestURL(kRendererID, url));
EXPECT_TRUE(p->CanRedirectToURL(url));
EXPECT_TRUE(p->CanReadFile(kRendererID, file));
EXPECT_TRUE(p->HasWebUIBindings(kRendererID));
p->Remove(kRendererID);
EXPECT_FALSE(p->CanRequestURL(kRendererID, url));
EXPECT_TRUE(p->CanRedirectToURL(url));
EXPECT_FALSE(p->CanReadFile(kRendererID, file));
EXPECT_FALSE(p->HasWebUIBindings(kRendererID));
}
TEST_P(ChildProcessSecurityPolicyTest, RemoveRace_CanAccessDataForOrigin) {
if (ShouldRestrictCanAccessDataForOriginToUIThread()) {
return;
}
ChildProcessSecurityPolicyImpl* p =
ChildProcessSecurityPolicyImpl::GetInstance();
GURL url("file:///etc/passwd");
p->AddForTesting(kRendererID, browser_context());
LockProcessIfNeeded(kRendererID, browser_context(), url);
base::WaitableEvent ready_for_remove_event;
base::WaitableEvent remove_called_event;
base::WaitableEvent pending_remove_complete_event;
bool io_before_remove = false;
bool io_while_io_task_pending = false;
bool io_after_io_task_completed = false;
bool ui_before_remove = false;
bool ui_while_io_task_pending = false;
bool ui_after_io_task_completed = false;
GetIOThreadTaskRunner({})->PostTask(
FROM_HERE, base::BindLambdaForTesting([&]() {
io_before_remove =
p->CanAccessDataForOrigin(kRendererID, url::Origin::Create(url));
ready_for_remove_event.Signal();
remove_called_event.Wait();
io_while_io_task_pending =
p->CanAccessDataForOrigin(kRendererID, url::Origin::Create(url));
}));
ready_for_remove_event.Wait();
ui_before_remove =
p->CanAccessDataForOrigin(kRendererID, url::Origin::Create(url));
p->Remove(kRendererID);
GetIOThreadTaskRunner({})->PostTask(
FROM_HERE, base::BindLambdaForTesting([&]() {
io_after_io_task_completed =
p->CanAccessDataForOrigin(kRendererID, url::Origin::Create(url));
pending_remove_complete_event.Signal();
}));
ui_while_io_task_pending =
p->CanAccessDataForOrigin(kRendererID, url::Origin::Create(url));
remove_called_event.Signal();
pending_remove_complete_event.Wait();
ui_after_io_task_completed =
p->CanAccessDataForOrigin(kRendererID, url::Origin::Create(url));
base::RunLoop run_loop;
run_loop.RunUntilIdle();
bool ui_after_remove_complete =
p->CanAccessDataForOrigin(kRendererID, url::Origin::Create(url));
bool io_after_remove_complete = false;
base::WaitableEvent after_remove_complete_event;
GetIOThreadTaskRunner({})->PostTask(
FROM_HERE, base::BindLambdaForTesting([&]() {
io_after_remove_complete =
p->CanAccessDataForOrigin(kRendererID, url::Origin::Create(url));
after_remove_complete_event.Signal();
}));
after_remove_complete_event.Wait();
EXPECT_TRUE(io_before_remove);
EXPECT_TRUE(io_while_io_task_pending);
EXPECT_FALSE(io_after_io_task_completed);
EXPECT_TRUE(ui_before_remove);
EXPECT_FALSE(ui_while_io_task_pending);
EXPECT_FALSE(ui_after_io_task_completed);
EXPECT_FALSE(ui_after_remove_complete);
EXPECT_FALSE(io_after_remove_complete);
}
TEST_P(ChildProcessSecurityPolicyTest, HandleExtendsSecurityStateLifetime) {
if (ShouldRestrictCanAccessDataForOriginToUIThread()) {
return;
}
ChildProcessSecurityPolicyImpl* p =
ChildProcessSecurityPolicyImpl::GetInstance();
GURL url("file:///etc/passwd");
p->AddForTesting(kRendererID, browser_context());
LockProcessIfNeeded(kRendererID, browser_context(), url);
auto handle = p->CreateHandle(kRendererID);
base::WaitableEvent ready_for_remove_event;
base::WaitableEvent remove_called_event;
base::WaitableEvent ready_for_handle_invalidation_event;
bool io_before_remove = false;
bool io_after_remove = false;
bool ui_before_remove = false;
bool ui_after_remove = false;
GetIOThreadTaskRunner({})->PostTask(
FROM_HERE, base::BindLambdaForTesting([&]() {
io_before_remove =
handle.CanAccessDataForOrigin(url::Origin::Create(url));
ready_for_remove_event.Signal();
}));
ready_for_remove_event.Wait();
ui_before_remove = handle.CanAccessDataForOrigin(url::Origin::Create(url));
p->Remove(kRendererID);
ui_after_remove = handle.CanAccessDataForOrigin(url::Origin::Create(url));
GetIOThreadTaskRunner({})->PostTask(
FROM_HERE, base::BindLambdaForTesting([&]() {
io_after_remove =
handle.CanAccessDataForOrigin(url::Origin::Create(url));
ready_for_handle_invalidation_event.Signal();
}));
ready_for_handle_invalidation_event.Wait();
handle = ChildProcessSecurityPolicyImpl::Handle();
bool ui_after_handle_invalidation =
handle.CanAccessDataForOrigin(url::Origin::Create(url));
bool io_after_handle_invalidation = false;
base::WaitableEvent after_invalidation_complete_event;
GetIOThreadTaskRunner({})->PostTask(
FROM_HERE, base::BindLambdaForTesting([&]() {
io_after_handle_invalidation =
handle.CanAccessDataForOrigin(url::Origin::Create(url));
after_invalidation_complete_event.Signal();
}));
after_invalidation_complete_event.Wait();
EXPECT_TRUE(io_before_remove);
EXPECT_TRUE(ui_before_remove);
EXPECT_TRUE(io_after_remove);
EXPECT_TRUE(ui_after_remove);
EXPECT_FALSE(io_after_handle_invalidation);
EXPECT_FALSE(ui_after_handle_invalidation);
}
TEST_P(ChildProcessSecurityPolicyTest, HandleDuplicate) {
ChildProcessSecurityPolicyImpl* p =
ChildProcessSecurityPolicyImpl::GetInstance();
GURL url("file:///etc/passwd");
p->AddForTesting(kRendererID, browser_context());
LockProcessIfNeeded(kRendererID, browser_context(), url);
auto handle = p->CreateHandle(kRendererID);
EXPECT_TRUE(handle.CanAccessDataForOrigin(url::Origin::Create(url)));
auto duplicate_handle = handle.Duplicate();
EXPECT_TRUE(duplicate_handle.is_valid());
EXPECT_TRUE(
duplicate_handle.CanAccessDataForOrigin(url::Origin::Create(url)));
p->Remove(kRendererID);
EXPECT_TRUE(handle.CanAccessDataForOrigin(url::Origin::Create(url)));
EXPECT_TRUE(
duplicate_handle.CanAccessDataForOrigin(url::Origin::Create(url)));
auto duplicate_handle2 = handle.Duplicate();
EXPECT_TRUE(duplicate_handle2.is_valid());
EXPECT_TRUE(
duplicate_handle2.CanAccessDataForOrigin(url::Origin::Create(url)));
EXPECT_FALSE(p->CreateHandle(kRendererID).is_valid());
handle = ChildProcessSecurityPolicyImpl::Handle();
EXPECT_FALSE(handle.CanAccessDataForOrigin(url::Origin::Create(url)));
EXPECT_TRUE(
duplicate_handle.CanAccessDataForOrigin(url::Origin::Create(url)));
EXPECT_TRUE(
duplicate_handle2.CanAccessDataForOrigin(url::Origin::Create(url)));
}
TEST_P(ChildProcessSecurityPolicyTest, CanAccessDataForOrigin_URL) {
ChildProcessSecurityPolicyImpl* p =
ChildProcessSecurityPolicyImpl::GetInstance();
GURL file_url("file:///etc/passwd");
GURL foo_http_url("http://foo.com/index.html");
GURL foo_blob_url("blob:http://foo.com/43d75119-d7af-4471-a293-07c6b3d7e61a");
GURL foo_filesystem_url("filesystem:http://foo.com/temporary/test.html");
GURL bar_http_url("http://bar.com/index.html");
const std::vector<GURL> kAllTestUrls = {file_url, foo_http_url, foo_blob_url,
foo_filesystem_url, bar_http_url};
auto handle = p->CreateHandle(kRendererID);
for (auto url : kAllTestUrls) {
EXPECT_FALSE(
p->CanAccessDataForOrigin(kRendererID, url::Origin::Create(url)))
<< url;
EXPECT_FALSE(
handle.CanAccessDataForOrigin(url::Origin::Create(bar_http_url)))
<< url;
}
TestBrowserContext browser_context;
p->AddForTesting(kRendererID, &browser_context);
handle = p->CreateHandle(kRendererID);
for (auto url : kAllTestUrls) {
if (AreAllSitesIsolatedForTesting() && IsCitadelProtectionEnabled()) {
EXPECT_FALSE(
p->CanAccessDataForOrigin(kRendererID, url::Origin::Create(url)))
<< url;
EXPECT_FALSE(handle.CanAccessDataForOrigin(url::Origin::Create(url)))
<< url;
} else {
EXPECT_TRUE(
p->CanAccessDataForOrigin(kRendererID, url::Origin::Create(url)))
<< url;
EXPECT_TRUE(handle.CanAccessDataForOrigin(url::Origin::Create(url)))
<< url;
}
}
p->AddFutureIsolatedOrigins({url::Origin::Create(foo_http_url)},
IsolatedOriginSource::TEST, &browser_context);
scoped_refptr<SiteInstanceImpl> foo_instance =
SiteInstanceImpl::CreateForTesting(&browser_context, foo_http_url);
EXPECT_FALSE(foo_instance->IsDefaultSiteInstance());
LockProcessIfNeeded(kRendererID, &browser_context, foo_http_url);
EXPECT_FALSE(
p->CanAccessDataForOrigin(kRendererID, url::Origin::Create(file_url)));
EXPECT_TRUE(p->CanAccessDataForOrigin(kRendererID,
url::Origin::Create(foo_http_url)));
EXPECT_TRUE(p->CanAccessDataForOrigin(kRendererID,
url::Origin::Create(foo_blob_url)));
EXPECT_TRUE(p->CanAccessDataForOrigin(
kRendererID, url::Origin::Create(foo_filesystem_url)));
EXPECT_FALSE(p->CanAccessDataForOrigin(kRendererID,
url::Origin::Create(bar_http_url)));
EXPECT_FALSE(handle.CanAccessDataForOrigin(url::Origin::Create(file_url)));
EXPECT_TRUE(handle.CanAccessDataForOrigin(url::Origin::Create(foo_http_url)));
EXPECT_TRUE(handle.CanAccessDataForOrigin(url::Origin::Create(foo_blob_url)));
EXPECT_TRUE(
handle.CanAccessDataForOrigin(url::Origin::Create(foo_filesystem_url)));
EXPECT_FALSE(
handle.CanAccessDataForOrigin(url::Origin::Create(bar_http_url)));
handle = ChildProcessSecurityPolicyImpl::Handle();
p->Remove(kRendererID);
base::RunLoop run_loop;
GetIOThreadTaskRunner({})->PostTaskAndReply(FROM_HERE, base::DoNothing(),
run_loop.QuitClosure());
run_loop.Run();
for (auto url : kAllTestUrls) {
EXPECT_FALSE(
p->CanAccessDataForOrigin(kRendererID, url::Origin::Create(url)))
<< url;
EXPECT_FALSE(handle.CanAccessDataForOrigin(url::Origin::Create(url)))
<< url;
}
}
TEST_P(ChildProcessSecurityPolicyTest, CanAccessDataForOrigin_Origin) {
ChildProcessSecurityPolicyImpl* p =
ChildProcessSecurityPolicyImpl::GetInstance();
const std::vector<const char*> foo_urls = {
"http://foo.com/index.html",
"blob:http://foo.com/43d75119-d7af-4471-a293-07c6b3d7e61a",
"filesystem:http://foo.com/temporary/test.html",
"http://foo.com:1234/index.html",
"blob:http://foo.com:1234/43d75119-d7af-4471-a293-07c6b3d7e61a",
"filesystem:http://foo.com:1234/temporary/test.html",
"data:text/html,Hello!"};
const std::vector<const char*> non_foo_urls = {
"file:///etc/passwd",
"http://bar.com/index.html",
"blob:http://bar.com/43d75119-d7af-4471-a293-07c6b3d7e61a",
"filesystem:http://bar.com/temporary/test.html",
"https://foo.com/index.html",
"blob:https://foo.com/43d75119-d7af-4471-a293-07c6b3d7e61a",
"filesystem:https://foo.com/temporary/test.html"};
std::vector<url::Origin> foo_origins;
std::vector<url::Origin> non_foo_origins;
std::vector<url::Origin> all_origins;
for (auto* url : foo_urls) {
auto origin = url::Origin::Create(GURL(url));
foo_origins.push_back(origin);
all_origins.push_back(origin);
}
auto foo_origin = url::Origin::Create(GURL("http://foo.com"));
auto opaque_with_foo_precursor = foo_origin.DeriveNewOpaqueOrigin();
foo_origins.push_back(opaque_with_foo_precursor);
all_origins.push_back(opaque_with_foo_precursor);
for (auto* url : non_foo_urls) {
auto origin = url::Origin::Create(GURL(url));
non_foo_origins.push_back(origin);
all_origins.push_back(origin);
}
url::Origin opaque_origin_without_precursor;
foo_origins.push_back(opaque_origin_without_precursor);
all_origins.push_back(opaque_origin_without_precursor);
auto opaque_with_bar_precursor =
url::Origin::Create(GURL("http://bar.com")).DeriveNewOpaqueOrigin();
non_foo_origins.push_back(opaque_with_bar_precursor);
all_origins.push_back(opaque_with_bar_precursor);
for (const auto& origin : all_origins)
EXPECT_FALSE(p->CanAccessDataForOrigin(kRendererID, origin)) << origin;
TestBrowserContext browser_context;
p->AddForTesting(kRendererID, &browser_context);
for (const auto& origin : all_origins) {
if (AreAllSitesIsolatedForTesting() && IsCitadelProtectionEnabled()) {
if (origin.opaque() &&
!origin.GetTupleOrPrecursorTupleIfOpaque().IsValid()) {
EXPECT_TRUE(p->CanAccessDataForOrigin(kRendererID, origin)) << origin;
} else {
EXPECT_FALSE(p->CanAccessDataForOrigin(kRendererID, origin)) << origin;
}
} else {
EXPECT_TRUE(p->CanAccessDataForOrigin(kRendererID, origin)) << origin;
}
}
p->AddFutureIsolatedOrigins({foo_origin}, IsolatedOriginSource::TEST,
&browser_context);
scoped_refptr<SiteInstanceImpl> foo_instance =
SiteInstanceImpl::CreateForTesting(&browser_context, foo_origin.GetURL());
EXPECT_FALSE(foo_instance->IsDefaultSiteInstance());
LockProcessIfNeeded(kRendererID, &browser_context, foo_origin.GetURL());
for (const auto& origin : foo_origins)
EXPECT_TRUE(p->CanAccessDataForOrigin(kRendererID, origin)) << origin;
for (const auto& origin : non_foo_origins)
EXPECT_FALSE(p->CanAccessDataForOrigin(kRendererID, origin)) << origin;
p->Remove(kRendererID);
base::RunLoop run_loop;
GetIOThreadTaskRunner({})->PostTaskAndReply(FROM_HERE, base::DoNothing(),
run_loop.QuitClosure());
run_loop.Run();
for (const auto& origin : all_origins)
EXPECT_FALSE(p->CanAccessDataForOrigin(kRendererID, origin)) << origin;
}
TEST_P(ChildProcessSecurityPolicyTest, OriginGranting) {
ChildProcessSecurityPolicyImpl* p =
ChildProcessSecurityPolicyImpl::GetInstance();
GURL url_foo1(GetWebUIURL("foo/resource1"));
GURL url_foo2(GetWebUIURL("foo/resource2"));
GURL url_bar(GetWebUIURL("bar/resource3"));
p->AddForTesting(kRendererID, browser_context());
LockProcessIfNeeded(kRendererID, browser_context(), url_foo1);
EXPECT_FALSE(p->CanRequestURL(kRendererID, url_foo1));
EXPECT_FALSE(p->CanRequestURL(kRendererID, url_foo2));
EXPECT_FALSE(p->CanRequestURL(kRendererID, url_bar));
EXPECT_TRUE(p->CanRedirectToURL(url_foo1));
EXPECT_TRUE(p->CanRedirectToURL(url_foo2));
EXPECT_TRUE(p->CanRedirectToURL(url_bar));
EXPECT_FALSE(p->CanCommitURL(kRendererID, url_foo1));
EXPECT_FALSE(p->CanCommitURL(kRendererID, url_foo2));
EXPECT_FALSE(p->CanCommitURL(kRendererID, url_bar));
p->GrantRequestOrigin(kRendererID, url::Origin::Create(url_foo1));
EXPECT_TRUE(p->CanRequestURL(kRendererID, url_foo1));
EXPECT_TRUE(p->CanRequestURL(kRendererID, url_foo2));
EXPECT_FALSE(p->CanRequestURL(kRendererID, url_bar));
EXPECT_TRUE(p->CanRedirectToURL(url_foo1));
EXPECT_TRUE(p->CanRedirectToURL(url_foo2));
EXPECT_TRUE(p->CanRedirectToURL(url_bar));
EXPECT_FALSE(p->CanCommitURL(kRendererID, url_foo1));
EXPECT_FALSE(p->CanCommitURL(kRendererID, url_foo2));
EXPECT_FALSE(p->CanCommitURL(kRendererID, url_bar));
p->GrantCommitOrigin(kRendererID, url::Origin::Create(url_foo1));
EXPECT_TRUE(p->CanRequestURL(kRendererID, url_foo1));
EXPECT_TRUE(p->CanRequestURL(kRendererID, url_foo2));
EXPECT_FALSE(p->CanRequestURL(kRendererID, url_bar));
EXPECT_TRUE(p->CanRedirectToURL(url_foo1));
EXPECT_TRUE(p->CanRedirectToURL(url_foo2));
EXPECT_TRUE(p->CanRedirectToURL(url_bar));
EXPECT_TRUE(p->CanCommitURL(kRendererID, url_foo1));
EXPECT_TRUE(p->CanCommitURL(kRendererID, url_foo2));
EXPECT_FALSE(p->CanCommitURL(kRendererID, url_bar));
p->GrantRequestOrigin(kRendererID, url::Origin::Create(url_foo1));
EXPECT_TRUE(p->CanRequestURL(kRendererID, url_foo1));
EXPECT_TRUE(p->CanRequestURL(kRendererID, url_foo2));
EXPECT_FALSE(p->CanRequestURL(kRendererID, url_bar));
EXPECT_TRUE(p->CanRedirectToURL(url_foo1));
EXPECT_TRUE(p->CanRedirectToURL(url_foo2));
EXPECT_TRUE(p->CanRedirectToURL(url_bar));
EXPECT_TRUE(p->CanCommitURL(kRendererID, url_foo1));
EXPECT_TRUE(p->CanCommitURL(kRendererID, url_foo2));
EXPECT_FALSE(p->CanCommitURL(kRendererID, url_bar));
p->Remove(kRendererID);
}
#define LOCKED_EXPECT_THAT(lock, value, matcher) \
do { \
base::AutoLock auto_lock(lock); \
EXPECT_THAT(value, matcher); \
} while (0);
TEST_P(ChildProcessSecurityPolicyTest, AddFutureIsolatedOrigins) {
url::Origin foo = url::Origin::Create(GURL("https://foo.com/"));
url::Origin bar = url::Origin::Create(GURL("https://bar.com/"));
url::Origin baz = url::Origin::Create(GURL("https://baz.com/"));
url::Origin quxfoo = url::Origin::Create(GURL("https://qux.foo.com/"));
url::Origin baz_http = url::Origin::Create(GURL("http://baz.com/"));
url::Origin baz_http_8000 = url::Origin::Create(GURL("http://baz.com:8000/"));
url::Origin baz_https_8000 =
url::Origin::Create(GURL("https://baz.com:8000/"));
url::Origin invalid_etld = url::Origin::Create(GURL("https://gov/"));
ChildProcessSecurityPolicyImpl* p =
ChildProcessSecurityPolicyImpl::GetInstance();
LOCKED_EXPECT_THAT(p->isolated_origins_lock_, p->isolated_origins_,
testing::IsEmpty());
p->AddFutureIsolatedOrigins({foo, bar, bar}, IsolatedOriginSource::TEST);
LOCKED_EXPECT_THAT(
p->isolated_origins_lock_, p->isolated_origins_,
testing::UnorderedElementsAre(GetIsolatedOriginEntry(foo),
GetIsolatedOriginEntry(bar)));
p->AddFutureIsolatedOrigins({baz}, IsolatedOriginSource::TEST);
LOCKED_EXPECT_THAT(
p->isolated_origins_lock_, p->isolated_origins_,
testing::UnorderedElementsAre(GetIsolatedOriginEntry(foo),
GetIsolatedOriginEntry(bar),
GetIsolatedOriginEntry(baz)));
p->AddFutureIsolatedOrigins({foo}, IsolatedOriginSource::TEST);
LOCKED_EXPECT_THAT(
p->isolated_origins_lock_, p->isolated_origins_,
testing::UnorderedElementsAre(GetIsolatedOriginEntry(foo),
GetIsolatedOriginEntry(bar),
GetIsolatedOriginEntry(baz)));
p->AddFutureIsolatedOrigins({baz, baz_http_8000, baz_https_8000},
IsolatedOriginSource::TEST);
LOCKED_EXPECT_THAT(
p->isolated_origins_lock_, p->isolated_origins_,
testing::UnorderedElementsAre(
GetIsolatedOriginEntry(foo), GetIsolatedOriginEntry(bar),
GetIsolatedOriginEntry(baz), GetIsolatedOriginEntry(baz_http)));
{
base::test::MockLog mock_log;
EXPECT_CALL(mock_log,
Log(::logging::LOG_ERROR, testing::_, testing::_, testing::_,
testing::HasSubstr(invalid_etld.Serialize())))
.Times(1);
mock_log.StartCapturingLogs();
p->AddFutureIsolatedOrigins({quxfoo, invalid_etld},
IsolatedOriginSource::TEST);
LOCKED_EXPECT_THAT(
p->isolated_origins_lock_, p->isolated_origins_,
testing::UnorderedElementsAre(
GetIsolatedOriginEntry(foo, quxfoo), GetIsolatedOriginEntry(bar),
GetIsolatedOriginEntry(baz), GetIsolatedOriginEntry(baz_http)));
}
{
base::test::MockLog mock_log;
EXPECT_CALL(mock_log, Log(::logging::LOG_ERROR, testing::_, testing::_,
testing::_, testing::HasSubstr("about:blank")))
.Times(1);
mock_log.StartCapturingLogs();
p->AddFutureIsolatedOrigins("about:blank", IsolatedOriginSource::TEST);
}
p->RemoveIsolatedOriginForTesting(foo);
p->RemoveIsolatedOriginForTesting(quxfoo);
p->RemoveIsolatedOriginForTesting(bar);
p->RemoveIsolatedOriginForTesting(baz);
p->RemoveIsolatedOriginForTesting(baz_http);
LOCKED_EXPECT_THAT(p->isolated_origins_lock_, p->isolated_origins_,
testing::IsEmpty());
}
TEST_P(ChildProcessSecurityPolicyTest, IsolateAllSuborigins) {
url::Origin qux = url::Origin::Create(GURL("https://qux.com/"));
IsolatedOriginPattern etld1_wild("https://[*.]foo.com");
IsolatedOriginPattern etld2_wild("https://[*.]bar.foo.com");
url::Origin etld1 = url::Origin::Create(GURL("https://foo.com"));
url::Origin etld2 = url::Origin::Create(GURL("https://bar.foo.com"));
ChildProcessSecurityPolicyImpl* p =
ChildProcessSecurityPolicyImpl::GetInstance();
p->AddFutureIsolatedOrigins({etld1_wild}, IsolatedOriginSource::TEST);
LOCKED_EXPECT_THAT(
p->isolated_origins_lock_, p->isolated_origins_,
testing::UnorderedElementsAre(GetIsolatedOriginEntry(etld1, true)));
p->AddFutureIsolatedOrigins({qux}, IsolatedOriginSource::TEST);
LOCKED_EXPECT_THAT(
p->isolated_origins_lock_, p->isolated_origins_,
testing::UnorderedElementsAre(GetIsolatedOriginEntry(etld1, true),
GetIsolatedOriginEntry(qux, false)));
p->AddFutureIsolatedOrigins({etld2_wild}, IsolatedOriginSource::TEST);
LOCKED_EXPECT_THAT(p->isolated_origins_lock_, p->isolated_origins_,
testing::UnorderedElementsAre(
GetIsolatedOriginEntry(etld1, etld2, true, true),
GetIsolatedOriginEntry(qux, false)));
p->RemoveIsolatedOriginForTesting(etld1);
LOCKED_EXPECT_THAT(
p->isolated_origins_lock_, p->isolated_origins_,
testing::UnorderedElementsAre(GetIsolatedOriginEntry(etld2, true),
GetIsolatedOriginEntry(qux, false)));
p->RemoveIsolatedOriginForTesting(qux);
p->RemoveIsolatedOriginForTesting(etld2);
LOCKED_EXPECT_THAT(p->isolated_origins_lock_, p->isolated_origins_,
testing::IsEmpty());
}
TEST_P(ChildProcessSecurityPolicyTest, WildcardAndNonWildcardOrigins) {
ChildProcessSecurityPolicyImpl* p =
ChildProcessSecurityPolicyImpl::GetInstance();
LOCKED_EXPECT_THAT(p->isolated_origins_lock_, p->isolated_origins_,
testing::IsEmpty());
IsolatedOriginPattern inner_isolated("https://inner.isolated.com");
IsolatedOriginPattern wildcard("https://[*.]wildcard.com");
IsolatedOriginPattern inner_wildcard("https://[*.]inner.wildcard.com");
GURL isolated_url("https://isolated.com");
GURL inner_isolated_url("https://inner.isolated.com");
GURL host_inner_isolated_url("https://host.inner.isolated.com");
GURL wildcard_url("https://wildcard.com");
GURL inner_wildcard_url("https://inner.wildcard.com");
GURL host_inner_wildcard_url("https://host.inner.wildcard.com");
GURL unrelated_url("https://unrelated.com");
std::map<GURL, GURL> origins_site_test_map{
{isolated_url, isolated_url},
{inner_isolated_url, isolated_url},
{host_inner_isolated_url, isolated_url},
{wildcard_url, wildcard_url},
{inner_wildcard_url, wildcard_url},
{host_inner_wildcard_url, wildcard_url},
{unrelated_url, unrelated_url},
};
CheckGetSiteForURL(browser_context(), origins_site_test_map);
p->AddFutureIsolatedOrigins({wildcard}, IsolatedOriginSource::TEST);
origins_site_test_map[inner_wildcard_url] = inner_wildcard_url;
origins_site_test_map[host_inner_wildcard_url] = host_inner_wildcard_url;
CheckGetSiteForURL(browser_context(), origins_site_test_map);
p->AddFutureIsolatedOrigins({inner_isolated}, IsolatedOriginSource::TEST);
origins_site_test_map[inner_isolated_url] = inner_isolated_url;
origins_site_test_map[host_inner_isolated_url] = inner_isolated_url;
CheckGetSiteForURL(browser_context(), origins_site_test_map);
p->AddFutureIsolatedOrigins({inner_wildcard}, IsolatedOriginSource::TEST);
CheckGetSiteForURL(browser_context(), origins_site_test_map);
p->RemoveIsolatedOriginForTesting(wildcard.origin());
p->RemoveIsolatedOriginForTesting(inner_isolated.origin());
p->RemoveIsolatedOriginForTesting(inner_wildcard.origin());
LOCKED_EXPECT_THAT(p->isolated_origins_lock_, p->isolated_origins_,
testing::IsEmpty());
}
TEST_P(ChildProcessSecurityPolicyTest, WildcardAndNonWildcardEmbedded) {
ChildProcessSecurityPolicyImpl* p =
ChildProcessSecurityPolicyImpl::GetInstance();
LOCKED_EXPECT_THAT(p->isolated_origins_lock_, p->isolated_origins_,
testing::IsEmpty());
{
IsolatedOriginPattern isolated("https://isolated.com");
IsolatedOriginPattern wildcard_isolated(
"https://[*.]wildcard.isolated.com");
GURL isolated_url("https://isolated.com");
GURL a_isolated_url("https://a.isolated.com");
GURL wildcard_isolated_url("https://wildcard.isolated.com");
GURL a_wildcard_isolated_url("https://a.wildcard.isolated.com");
p->AddFutureIsolatedOrigins({isolated, wildcard_isolated},
IsolatedOriginSource::TEST);
std::map<GURL, GURL> origin_site_map{
{isolated_url, isolated_url},
{a_isolated_url, isolated_url},
{wildcard_isolated_url, wildcard_isolated_url},
{a_wildcard_isolated_url, a_wildcard_isolated_url},
};
CheckGetSiteForURL(browser_context(), origin_site_map);
p->RemoveIsolatedOriginForTesting(isolated.origin());
p->RemoveIsolatedOriginForTesting(wildcard_isolated.origin());
}
LOCKED_EXPECT_THAT(p->isolated_origins_lock_, p->isolated_origins_,
testing::IsEmpty());
{
IsolatedOriginPattern wildcard("https://[*.]wildcard.com");
IsolatedOriginPattern isolated_wildcard("https://isolated.wildcard.com");
GURL wildcard_url("https://wildcard.com");
GURL a_wildcard_url("https://a.wildcard.com");
GURL isolated_wildcard_url("https://isolated.wildcard.com");
GURL a_isolated_wildcard_url("https://a.isolated.wildcard.com");
p->AddFutureIsolatedOrigins({wildcard, isolated_wildcard},
IsolatedOriginSource::TEST);
std::map<GURL, GURL> origin_site_map{
{wildcard_url, wildcard_url},
{a_wildcard_url, a_wildcard_url},
{isolated_wildcard_url, isolated_wildcard_url},
{a_isolated_wildcard_url, a_isolated_wildcard_url},
};
CheckGetSiteForURL(browser_context(), origin_site_map);
p->RemoveIsolatedOriginForTesting(wildcard.origin());
p->RemoveIsolatedOriginForTesting(isolated_wildcard.origin());
}
LOCKED_EXPECT_THAT(p->isolated_origins_lock_, p->isolated_origins_,
testing::IsEmpty());
{
IsolatedOriginPattern outer("https://[*.]outer.com");
IsolatedOriginPattern inner("https://[*.]inner.outer.com");
GURL outer_url("https://outer.com");
GURL a_outer_url("https://a.outer.com");
GURL inner_url("https://inner.outer.com");
GURL a_inner_url("https://a.inner.outer.com");
p->AddFutureIsolatedOrigins({inner, outer}, IsolatedOriginSource::TEST);
std::map<GURL, GURL> origin_site_map{
{outer_url, outer_url},
{a_outer_url, a_outer_url},
{inner_url, inner_url},
{a_inner_url, a_inner_url},
};
CheckGetSiteForURL(browser_context(), origin_site_map);
p->RemoveIsolatedOriginForTesting(outer.origin());
p->RemoveIsolatedOriginForTesting(inner.origin());
}
LOCKED_EXPECT_THAT(p->isolated_origins_lock_, p->isolated_origins_,
testing::IsEmpty());
{
IsolatedOriginPattern wild("https://[*.]bar.foo.com");
IsolatedOriginPattern single("https://bar.foo.com");
GURL host_url("https://host.bar.foo.com");
p->AddFutureIsolatedOrigins({wild}, IsolatedOriginSource::TEST);
std::map<GURL, GURL> origin_site_map{
{host_url, host_url},
};
CheckGetSiteForURL(browser_context(), origin_site_map);
p->AddFutureIsolatedOrigins({single}, IsolatedOriginSource::TEST);
CheckGetSiteForURL(browser_context(), origin_site_map);
p->RemoveIsolatedOriginForTesting(wild.origin());
p->RemoveIsolatedOriginForTesting(single.origin());
}
LOCKED_EXPECT_THAT(p->isolated_origins_lock_, p->isolated_origins_,
testing::IsEmpty());
{
IsolatedOriginPattern wild("https://[*.]bar.foo.com");
IsolatedOriginPattern single("https://bar.foo.com");
GURL host_url("https://host.bar.foo.com");
GURL domain_url("https://bar.foo.com");
p->AddFutureIsolatedOrigins({single}, IsolatedOriginSource::TEST);
std::map<GURL, GURL> origin_site_map{
{host_url, domain_url},
};
CheckGetSiteForURL(browser_context(), origin_site_map);
p->AddFutureIsolatedOrigins({wild}, IsolatedOriginSource::TEST);
CheckGetSiteForURL(browser_context(), origin_site_map);
p->RemoveIsolatedOriginForTesting(wild.origin());
p->RemoveIsolatedOriginForTesting(single.origin());
}
LOCKED_EXPECT_THAT(p->isolated_origins_lock_, p->isolated_origins_,
testing::IsEmpty());
}
TEST_P(ChildProcessSecurityPolicyTest, DynamicIsolatedOrigins) {
url::Origin foo = url::Origin::Create(GURL("https://foo.com/"));
url::Origin bar = url::Origin::Create(GURL("https://bar.com/"));
url::Origin baz = url::Origin::Create(GURL("https://baz.com/"));
url::Origin qux = url::Origin::Create(GURL("https://qux.com/"));
ChildProcessSecurityPolicyImpl* p =
ChildProcessSecurityPolicyImpl::GetInstance();
LOCKED_EXPECT_THAT(p->isolated_origins_lock_, p->isolated_origins_,
testing::IsEmpty());
BrowsingInstanceId initial_id(SiteInstanceImpl::NextBrowsingInstanceId());
p->AddFutureIsolatedOrigins({foo, bar}, IsolatedOriginSource::TEST);
LOCKED_EXPECT_THAT(
p->isolated_origins_lock_, p->isolated_origins_,
testing::UnorderedElementsAre(GetIsolatedOriginEntry(initial_id, foo),
GetIsolatedOriginEntry(initial_id, bar)));
p->AddFutureIsolatedOrigins({bar}, IsolatedOriginSource::TEST);
LOCKED_EXPECT_THAT(
p->isolated_origins_lock_, p->isolated_origins_,
testing::UnorderedElementsAre(GetIsolatedOriginEntry(initial_id, foo),
GetIsolatedOriginEntry(initial_id, bar)));
TestBrowserContext context;
scoped_refptr<SiteInstanceImpl> foo_instance =
SiteInstanceImpl::CreateForTesting(&context, GURL("https://foo.com/"));
EXPECT_EQ(initial_id,
foo_instance->GetIsolationContext().browsing_instance_id());
EXPECT_EQ(BrowsingInstanceId::FromUnsafeValue(initial_id.value() + 1),
SiteInstanceImpl::NextBrowsingInstanceId());
p->AddFutureIsolatedOrigins({baz}, IsolatedOriginSource::TEST);
LOCKED_EXPECT_THAT(p->isolated_origins_lock_, p->isolated_origins_,
testing::UnorderedElementsAre(
GetIsolatedOriginEntry(initial_id, foo),
GetIsolatedOriginEntry(initial_id, bar),
GetIsolatedOriginEntry(initial_id.value() + 1, baz)));
p->AddFutureIsolatedOrigins({bar}, IsolatedOriginSource::TEST);
LOCKED_EXPECT_THAT(p->isolated_origins_lock_, p->isolated_origins_,
testing::UnorderedElementsAre(
GetIsolatedOriginEntry(initial_id, foo),
GetIsolatedOriginEntry(initial_id, bar),
GetIsolatedOriginEntry(initial_id.value() + 1, baz)));
scoped_refptr<SiteInstanceImpl> bar_instance =
SiteInstanceImpl::CreateForTesting(&context, GURL("https://bar.com/"));
EXPECT_EQ(BrowsingInstanceId::FromUnsafeValue(initial_id.value() + 1),
bar_instance->GetIsolationContext().browsing_instance_id());
EXPECT_EQ(BrowsingInstanceId::FromUnsafeValue(initial_id.value() + 2),
SiteInstanceImpl::NextBrowsingInstanceId());
p->AddFutureIsolatedOrigins({qux}, IsolatedOriginSource::TEST);
LOCKED_EXPECT_THAT(p->isolated_origins_lock_, p->isolated_origins_,
testing::UnorderedElementsAre(
GetIsolatedOriginEntry(initial_id, foo),
GetIsolatedOriginEntry(initial_id, bar),
GetIsolatedOriginEntry(initial_id.value() + 1, baz),
GetIsolatedOriginEntry(initial_id.value() + 2, qux)));
EXPECT_TRUE(IsIsolatedOrigin(&context, initial_id, foo));
EXPECT_TRUE(IsIsolatedOrigin(&context, initial_id, bar));
EXPECT_FALSE(IsIsolatedOrigin(&context, initial_id, baz));
EXPECT_FALSE(IsIsolatedOrigin(&context, initial_id, qux));
EXPECT_TRUE(IsIsolatedOrigin(&context, initial_id.value() + 1, foo));
EXPECT_TRUE(IsIsolatedOrigin(&context, initial_id.value() + 1, bar));
EXPECT_TRUE(IsIsolatedOrigin(&context, initial_id.value() + 1, baz));
EXPECT_FALSE(IsIsolatedOrigin(&context, initial_id.value() + 1, qux));
EXPECT_TRUE(IsIsolatedOrigin(&context, initial_id.value() + 2, foo));
EXPECT_TRUE(IsIsolatedOrigin(&context, initial_id.value() + 2, bar));
EXPECT_TRUE(IsIsolatedOrigin(&context, initial_id.value() + 2, baz));
EXPECT_TRUE(IsIsolatedOrigin(&context, initial_id.value() + 2, qux));
EXPECT_TRUE(IsIsolatedOrigin(&context, initial_id.value() + 42, foo));
EXPECT_TRUE(IsIsolatedOrigin(&context, initial_id.value() + 42, bar));
EXPECT_TRUE(IsIsolatedOrigin(&context, initial_id.value() + 42, baz));
EXPECT_TRUE(IsIsolatedOrigin(&context, initial_id.value() + 42, qux));
EXPECT_TRUE(p->IsIsolatedOrigin(IsolationContext(&context), foo,
false ));
EXPECT_TRUE(p->IsIsolatedOrigin(IsolationContext(&context), bar,
false ));
EXPECT_TRUE(p->IsIsolatedOrigin(IsolationContext(&context), baz,
false ));
EXPECT_TRUE(p->IsIsolatedOrigin(IsolationContext(&context), qux,
false ));
p->RemoveIsolatedOriginForTesting(foo);
p->RemoveIsolatedOriginForTesting(bar);
p->RemoveIsolatedOriginForTesting(baz);
p->RemoveIsolatedOriginForTesting(qux);
}
TEST_P(ChildProcessSecurityPolicyTest, IsIsolatedOriginWithEmptyHost) {
ChildProcessSecurityPolicyImpl* p =
ChildProcessSecurityPolicyImpl::GetInstance();
TestBrowserContext context;
EXPECT_FALSE(p->IsIsolatedOrigin(IsolationContext(&context),
url::Origin::Create(GURL()),
false ));
EXPECT_FALSE(p->IsIsolatedOrigin(IsolationContext(&context),
url::Origin::Create(GURL("file:///foo")),
false ));
}
TEST_P(ChildProcessSecurityPolicyTest,
IsolatedOriginsForSpecificBrowserContexts) {
url::Origin foo = url::Origin::Create(GURL("https://foo.com/"));
url::Origin bar = url::Origin::Create(GURL("https://bar.com/"));
ChildProcessSecurityPolicyImpl* p =
ChildProcessSecurityPolicyImpl::GetInstance();
LOCKED_EXPECT_THAT(p->isolated_origins_lock_, p->isolated_origins_,
testing::IsEmpty());
BrowsingInstanceId initial_id(SiteInstanceImpl::NextBrowsingInstanceId());
p->AddFutureIsolatedOrigins({foo}, IsolatedOriginSource::TEST);
TestBrowserContext context1, context2;
p->AddFutureIsolatedOrigins({bar}, IsolatedOriginSource::TEST, &context1);
EXPECT_TRUE(IsIsolatedOrigin(&context1, initial_id, foo));
EXPECT_TRUE(IsIsolatedOrigin(&context2, initial_id, foo));
EXPECT_TRUE(IsIsolatedOrigin(&context1, initial_id, bar));
EXPECT_FALSE(IsIsolatedOrigin(&context2, initial_id, bar));
scoped_refptr<SiteInstanceImpl> foo_instance =
SiteInstanceImpl::CreateForTesting(&context1, GURL("https://foo.com/"));
EXPECT_EQ(initial_id,
foo_instance->GetIsolationContext().browsing_instance_id());
EXPECT_EQ(BrowsingInstanceId::FromUnsafeValue(initial_id.value() + 1),
SiteInstanceImpl::NextBrowsingInstanceId());
EXPECT_EQ(&context1, foo_instance->GetIsolationContext()
.browser_or_resource_context()
.ToBrowserContext());
EXPECT_EQ(1, GetIsolatedOriginEntryCount(foo));
p->AddFutureIsolatedOrigins({foo}, IsolatedOriginSource::TEST, &context1);
EXPECT_EQ(2, GetIsolatedOriginEntryCount(foo));
EXPECT_TRUE(IsIsolatedOrigin(&context1, initial_id, foo));
EXPECT_TRUE(IsIsolatedOrigin(&context2, initial_id, foo));
EXPECT_EQ(1, GetIsolatedOriginEntryCount(bar));
p->AddFutureIsolatedOrigins({bar}, IsolatedOriginSource::TEST, &context1);
EXPECT_EQ(1, GetIsolatedOriginEntryCount(bar));
EXPECT_TRUE(IsIsolatedOrigin(&context1, initial_id, bar));
EXPECT_FALSE(IsIsolatedOrigin(&context2, initial_id, bar));
p->AddFutureIsolatedOrigins({bar}, IsolatedOriginSource::TEST, &context2);
EXPECT_EQ(2, GetIsolatedOriginEntryCount(bar));
EXPECT_FALSE(IsIsolatedOrigin(&context2, initial_id, bar));
EXPECT_TRUE(IsIsolatedOrigin(&context2, initial_id.value() + 1, bar));
EXPECT_TRUE(IsIsolatedOrigin(&context1, initial_id, bar));
EXPECT_TRUE(IsIsolatedOrigin(&context1, initial_id.value() + 1, bar));
TestBrowserContext context3;
EXPECT_TRUE(IsIsolatedOrigin(&context3, initial_id, foo));
EXPECT_TRUE(IsIsolatedOrigin(&context3, initial_id.value() + 1, foo));
EXPECT_FALSE(IsIsolatedOrigin(&context3, initial_id, bar));
EXPECT_FALSE(IsIsolatedOrigin(&context3, initial_id.value() + 1, bar));
p->AddFutureIsolatedOrigins({bar}, IsolatedOriginSource::TEST);
EXPECT_EQ(3, GetIsolatedOriginEntryCount(bar));
EXPECT_FALSE(IsIsolatedOrigin(&context3, initial_id, bar));
EXPECT_TRUE(IsIsolatedOrigin(&context3, initial_id.value() + 1, bar));
TestBrowserContext context4;
p->AddFutureIsolatedOrigins({bar}, IsolatedOriginSource::TEST, &context4);
EXPECT_EQ(4, GetIsolatedOriginEntryCount(bar));
p->RemoveIsolatedOriginForTesting(foo);
p->RemoveIsolatedOriginForTesting(bar);
}
TEST_P(ChildProcessSecurityPolicyTest,
IsolatedOriginsRemovedWhenBrowserContextDestroyed) {
url::Origin foo = url::Origin::Create(GURL("https://foo.com/"));
url::Origin sub_foo = url::Origin::Create(GURL("https://sub.foo.com/"));
url::Origin bar = url::Origin::Create(GURL("https://bar.com/"));
url::Origin baz = url::Origin::Create(GURL("https://baz.com/"));
ChildProcessSecurityPolicyImpl* p =
ChildProcessSecurityPolicyImpl::GetInstance();
LOCKED_EXPECT_THAT(p->isolated_origins_lock_, p->isolated_origins_,
testing::IsEmpty());
BrowsingInstanceId initial_id(SiteInstanceImpl::NextBrowsingInstanceId());
std::unique_ptr<TestBrowserContext> context1(new TestBrowserContext());
std::unique_ptr<TestBrowserContext> context2(new TestBrowserContext());
p->AddFutureIsolatedOrigins({foo}, IsolatedOriginSource::TEST,
context1.get());
EXPECT_EQ(1, GetIsolatedOriginEntryCount(foo));
EXPECT_TRUE(IsIsolatedOrigin(context1.get(), initial_id, foo));
EXPECT_TRUE(IsIsolatedOrigin(context1.get(), initial_id, sub_foo));
EXPECT_FALSE(IsIsolatedOrigin(context2.get(), initial_id, foo));
EXPECT_FALSE(IsIsolatedOrigin(context2.get(), initial_id, sub_foo));
p->AddFutureIsolatedOrigins({sub_foo, bar}, IsolatedOriginSource::TEST,
context2.get());
EXPECT_EQ(1, GetIsolatedOriginEntryCount(sub_foo));
EXPECT_EQ(1, GetIsolatedOriginEntryCount(bar));
EXPECT_TRUE(IsIsolatedOrigin(context2.get(), initial_id, sub_foo));
EXPECT_TRUE(IsIsolatedOrigin(context2.get(), initial_id, bar));
EXPECT_FALSE(IsIsolatedOrigin(context2.get(), initial_id, foo));
p->AddFutureIsolatedOrigins({baz}, IsolatedOriginSource::TEST,
context1.get());
p->AddFutureIsolatedOrigins({baz}, IsolatedOriginSource::TEST,
context2.get());
EXPECT_EQ(2, GetIsolatedOriginEntryCount(baz));
EXPECT_TRUE(IsIsolatedOrigin(context1.get(), initial_id, baz));
EXPECT_TRUE(IsIsolatedOrigin(context2.get(), initial_id, baz));
context1.reset();
EXPECT_EQ(0, GetIsolatedOriginEntryCount(foo));
EXPECT_EQ(1, GetIsolatedOriginEntryCount(sub_foo));
EXPECT_EQ(1, GetIsolatedOriginEntryCount(bar));
EXPECT_EQ(1, GetIsolatedOriginEntryCount(baz));
EXPECT_TRUE(IsIsolatedOrigin(context2.get(), initial_id, sub_foo));
EXPECT_TRUE(IsIsolatedOrigin(context2.get(), initial_id, bar));
EXPECT_TRUE(IsIsolatedOrigin(context2.get(), initial_id, baz));
context2.reset();
LOCKED_EXPECT_THAT(p->isolated_origins_lock_, p->isolated_origins_,
testing::IsEmpty());
}
TEST_P(ChildProcessSecurityPolicyTest, IsolatedOriginPattern) {
const base::StringPiece etld1_wild("https://[*.]foo.com");
url::Origin etld1_wild_origin = url::Origin::Create(GURL("https://foo.com"));
IsolatedOriginPattern p(etld1_wild);
EXPECT_TRUE(p.isolate_all_subdomains());
EXPECT_TRUE(p.is_valid());
EXPECT_EQ(p.origin(), etld1_wild_origin);
const base::StringPiece etld2_wild("https://[*.]bar.foo.com");
url::Origin etld2_wild_origin =
url::Origin::Create(GURL("https://bar.foo.com"));
bool result = p.Parse(etld2_wild);
EXPECT_TRUE(result);
EXPECT_TRUE(p.isolate_all_subdomains());
EXPECT_TRUE(p.is_valid());
EXPECT_EQ(p.origin(), etld2_wild_origin);
EXPECT_FALSE(p.origin().opaque());
const base::StringPiece etld1("https://baz.com");
url::Origin etld1_origin = url::Origin::Create(GURL("https://baz.com"));
result = p.Parse(etld1);
EXPECT_TRUE(result);
EXPECT_FALSE(p.isolate_all_subdomains());
EXPECT_TRUE(p.is_valid());
EXPECT_EQ(p.origin(), etld1_origin);
EXPECT_FALSE(p.origin().opaque());
const base::StringPiece bad_scheme("ftp://foo.com");
result = p.Parse(bad_scheme);
EXPECT_FALSE(result);
EXPECT_FALSE(p.isolate_all_subdomains());
EXPECT_FALSE(p.is_valid());
EXPECT_TRUE(p.origin().opaque());
const base::StringPiece no_scheme_sep("httpsfoo.com");
result = p.Parse(no_scheme_sep);
EXPECT_FALSE(result);
EXPECT_FALSE(p.isolate_all_subdomains());
EXPECT_FALSE(p.is_valid());
EXPECT_TRUE(p.origin().opaque());
const base::StringPiece bad_registry("https://co.uk");
result = p.Parse(bad_registry);
EXPECT_FALSE(result);
EXPECT_FALSE(p.isolate_all_subdomains());
EXPECT_FALSE(p.is_valid());
EXPECT_TRUE(p.origin().opaque());
const base::StringPiece trailing_dot("https://bar.com.");
result = p.Parse(trailing_dot);
EXPECT_FALSE(result);
EXPECT_FALSE(p.isolate_all_subdomains());
EXPECT_FALSE(p.is_valid());
EXPECT_TRUE(p.origin().opaque());
const base::StringPiece ip_addr("https://10.20.30.40");
url::Origin ip_origin = url::Origin::Create(GURL("https://10.20.30.40"));
result = p.Parse(ip_addr);
EXPECT_TRUE(result);
EXPECT_FALSE(p.isolate_all_subdomains());
EXPECT_FALSE(p.origin().opaque());
EXPECT_TRUE(p.is_valid());
EXPECT_EQ(p.origin(), ip_origin);
const base::StringPiece wild_ip_addr("https://[*.]10.20.30.40");
result = p.Parse(wild_ip_addr);
EXPECT_FALSE(result);
EXPECT_FALSE(p.isolate_all_subdomains());
EXPECT_FALSE(p.is_valid());
const url::Origin bad_origin;
IsolatedOriginPattern bad_pattern(bad_origin);
EXPECT_FALSE(bad_pattern.isolate_all_subdomains());
EXPECT_TRUE(bad_pattern.origin().opaque());
EXPECT_FALSE(p.is_valid());
}
TEST_P(ChildProcessSecurityPolicyTest, GetIsolatedOrigins) {
url::Origin foo = url::Origin::Create(GURL("https://foo.com/"));
url::Origin bar = url::Origin::Create(GURL("https://bar.com/"));
url::Origin baz = url::Origin::Create(GURL("https://baz.com/"));
url::Origin qux = url::Origin::Create(GURL("https://qux.com/"));
ChildProcessSecurityPolicyImpl* p =
ChildProcessSecurityPolicyImpl::GetInstance();
EXPECT_THAT(p->GetIsolatedOrigins(), testing::IsEmpty());
p->AddFutureIsolatedOrigins({foo}, IsolatedOriginSource::TEST);
p->AddFutureIsolatedOrigins({bar}, IsolatedOriginSource::FIELD_TRIAL);
EXPECT_THAT(p->GetIsolatedOrigins(), testing::UnorderedElementsAre(foo, bar));
EXPECT_THAT(p->GetIsolatedOrigins(IsolatedOriginSource::TEST),
testing::UnorderedElementsAre(foo));
EXPECT_THAT(p->GetIsolatedOrigins(IsolatedOriginSource::FIELD_TRIAL),
testing::UnorderedElementsAre(bar));
p->AddFutureIsolatedOrigins({baz}, IsolatedOriginSource::POLICY);
p->AddFutureIsolatedOrigins({qux}, IsolatedOriginSource::COMMAND_LINE);
EXPECT_THAT(p->GetIsolatedOrigins(),
testing::UnorderedElementsAre(foo, bar, baz, qux));
EXPECT_THAT(p->GetIsolatedOrigins(IsolatedOriginSource::TEST),
testing::UnorderedElementsAre(foo));
EXPECT_THAT(p->GetIsolatedOrigins(IsolatedOriginSource::FIELD_TRIAL),
testing::UnorderedElementsAre(bar));
EXPECT_THAT(p->GetIsolatedOrigins(IsolatedOriginSource::POLICY),
testing::UnorderedElementsAre(baz));
EXPECT_THAT(p->GetIsolatedOrigins(IsolatedOriginSource::COMMAND_LINE),
testing::UnorderedElementsAre(qux));
p->RemoveIsolatedOriginForTesting(foo);
p->RemoveIsolatedOriginForTesting(bar);
p->RemoveIsolatedOriginForTesting(baz);
p->RemoveIsolatedOriginForTesting(qux);
EXPECT_THAT(p->GetIsolatedOrigins(), testing::IsEmpty());
}
TEST_P(ChildProcessSecurityPolicyTest, GetIsolatedOriginsWithProfile) {
url::Origin foo = url::Origin::Create(GURL("https://foo.com/"));
url::Origin bar = url::Origin::Create(GURL("https://bar.com/"));
url::Origin baz = url::Origin::Create(GURL("https://baz.com/"));
url::Origin qux = url::Origin::Create(GURL("https://qux.com/"));
ChildProcessSecurityPolicyImpl* p =
ChildProcessSecurityPolicyImpl::GetInstance();
TestBrowserContext context1, context2;
EXPECT_THAT(p->GetIsolatedOrigins(), testing::IsEmpty());
p->AddFutureIsolatedOrigins({foo}, IsolatedOriginSource::TEST);
p->AddFutureIsolatedOrigins({bar}, IsolatedOriginSource::USER_TRIGGERED,
&context1);
p->AddFutureIsolatedOrigins({baz}, IsolatedOriginSource::POLICY, &context2);
p->AddFutureIsolatedOrigins({qux}, IsolatedOriginSource::USER_TRIGGERED,
&context1);
p->AddFutureIsolatedOrigins({qux}, IsolatedOriginSource::USER_TRIGGERED,
&context2);
EXPECT_THAT(p->GetIsolatedOrigins(), testing::UnorderedElementsAre(foo));
EXPECT_THAT(p->GetIsolatedOrigins(IsolatedOriginSource::TEST),
testing::UnorderedElementsAre(foo));
EXPECT_THAT(p->GetIsolatedOrigins(IsolatedOriginSource::TEST, &context1),
testing::UnorderedElementsAre(foo));
EXPECT_THAT(p->GetIsolatedOrigins(IsolatedOriginSource::TEST, &context2),
testing::UnorderedElementsAre(foo));
EXPECT_THAT(p->GetIsolatedOrigins(IsolatedOriginSource::USER_TRIGGERED),
testing::IsEmpty());
EXPECT_THAT(
p->GetIsolatedOrigins(IsolatedOriginSource::USER_TRIGGERED, &context1),
testing::UnorderedElementsAre(bar, qux));
EXPECT_THAT(
p->GetIsolatedOrigins(IsolatedOriginSource::USER_TRIGGERED, &context2),
testing::UnorderedElementsAre(qux));
EXPECT_THAT(p->GetIsolatedOrigins(IsolatedOriginSource::POLICY),
testing::IsEmpty());
EXPECT_THAT(p->GetIsolatedOrigins(IsolatedOriginSource::POLICY, &context1),
testing::IsEmpty());
EXPECT_THAT(p->GetIsolatedOrigins(IsolatedOriginSource::POLICY, &context2),
testing::UnorderedElementsAre(baz));
p->RemoveIsolatedOriginForTesting(foo);
p->RemoveIsolatedOriginForTesting(bar);
p->RemoveIsolatedOriginForTesting(baz);
p->RemoveIsolatedOriginForTesting(qux);
EXPECT_THAT(p->GetIsolatedOrigins(), testing::IsEmpty());
}
TEST_P(ChildProcessSecurityPolicyTest, IsolatedOriginPatternEquality) {
std::string foo("https://foo.com");
std::string foo_port("https://foo.com:8000");
std::string foo_path("https://foo.com/some/path");
EXPECT_EQ(IsolatedOriginPattern(foo), IsolatedOriginPattern(foo_port));
EXPECT_EQ(IsolatedOriginPattern(foo), IsolatedOriginPattern(foo_path));
std::string wild_foo("https://[*.]foo.com");
std::string wild_foo_port("https://[*.]foo.com:8000");
std::string wild_foo_path("https://[*.]foo.com/some/path");
EXPECT_EQ(IsolatedOriginPattern(wild_foo),
IsolatedOriginPattern(wild_foo_port));
EXPECT_EQ(IsolatedOriginPattern(wild_foo),
IsolatedOriginPattern(wild_foo_path));
EXPECT_FALSE(IsolatedOriginPattern(foo) == IsolatedOriginPattern(wild_foo));
}
TEST_P(ChildProcessSecurityPolicyTest, ParseIsolatedOrigins) {
EXPECT_THAT(ChildProcessSecurityPolicyImpl::ParseIsolatedOrigins(""),
testing::IsEmpty());
EXPECT_THAT(
ChildProcessSecurityPolicyImpl::ParseIsolatedOrigins(
"http://isolated.foo.com"),
testing::ElementsAre(IsolatedOriginPattern("http://isolated.foo.com")));
EXPECT_THAT(
ChildProcessSecurityPolicyImpl::ParseIsolatedOrigins(
"http://a.com,https://b.com,,https://c.com:8000"),
testing::ElementsAre(IsolatedOriginPattern("http://a.com"),
IsolatedOriginPattern("https://b.com"),
IsolatedOriginPattern("https://c.com:8000")));
EXPECT_THAT(
ChildProcessSecurityPolicyImpl::ParseIsolatedOrigins(
"https://b.com,https://b.com,https://b.com:1234"),
testing::ElementsAre(IsolatedOriginPattern("https://b.com"),
IsolatedOriginPattern("https://b.com"),
IsolatedOriginPattern("https://b.com:1234")));
EXPECT_THAT(
ChildProcessSecurityPolicyImpl::ParseIsolatedOrigins(
"https://[*.]wild.foo.com"),
testing::ElementsAre(IsolatedOriginPattern("https://[*.]wild.foo.com")));
EXPECT_THAT(
ChildProcessSecurityPolicyImpl::ParseIsolatedOrigins(
"https://[*.]wild.foo.com,https://isolated.foo.com"),
testing::ElementsAre(IsolatedOriginPattern("https://[*.]wild.foo.com"),
IsolatedOriginPattern("https://isolated.foo.com")));
}
TEST_P(ChildProcessSecurityPolicyTest, WildcardDefaultPort) {
ChildProcessSecurityPolicyImpl* p =
ChildProcessSecurityPolicyImpl::GetInstance();
EXPECT_THAT(p->GetIsolatedOrigins(), testing::IsEmpty());
url::Origin isolated_origin_with_port =
url::Origin::Create(GURL("https://isolated.com:1234"));
url::Origin isolated_origin =
url::Origin::Create(GURL("https://isolated.com"));
url::Origin wild_with_port =
url::Origin::Create(GURL("https://a.wild.com:5678"));
url::Origin wild_origin = url::Origin::Create(GURL("https://a.wild.com"));
IsolatedOriginPattern wild_pattern("https://[*.]wild.com:5678");
p->AddFutureIsolatedOrigins({isolated_origin_with_port},
IsolatedOriginSource::TEST);
p->AddFutureIsolatedOrigins({wild_pattern}, IsolatedOriginSource::TEST);
IsolationContext isolation_context(browser_context());
url::Origin lookup_origin;
const bool kOriginRequestsIsolation = false;
EXPECT_TRUE(p->GetMatchingProcessIsolatedOrigin(
isolation_context, isolated_origin_with_port, kOriginRequestsIsolation,
&lookup_origin));
EXPECT_EQ(url::DefaultPortForScheme(lookup_origin.scheme().data(),
lookup_origin.scheme().length()),
lookup_origin.port());
EXPECT_EQ(isolated_origin, lookup_origin);
p->RemoveIsolatedOriginForTesting(isolated_origin);
EXPECT_TRUE(p->GetMatchingProcessIsolatedOrigin(
isolation_context, wild_with_port, kOriginRequestsIsolation,
&lookup_origin));
EXPECT_EQ(url::DefaultPortForScheme(lookup_origin.scheme().data(),
lookup_origin.scheme().length()),
lookup_origin.port());
EXPECT_EQ(wild_origin, lookup_origin);
p->RemoveIsolatedOriginForTesting(wild_pattern.origin());
EXPECT_THAT(p->GetIsolatedOrigins(), testing::IsEmpty());
}
TEST_P(ChildProcessSecurityPolicyTest, ProcessLockMatching) {
GURL nonapp_url("https://bar.com/");
GURL app_url("https://some.app.foo.com/");
GURL app_effective_url("https://app.com/");
EffectiveURLContentBrowserClient modified_client(
app_url, app_effective_url, true);
ContentBrowserClient* original_client =
SetBrowserClientForTesting(&modified_client);
IsolationContext isolation_context(browser_context());
auto nonapp_urlinfo = UrlInfo::CreateForTesting(
nonapp_url, CreateStoragePartitionConfigForTesting());
auto ui_nonapp_url_siteinfo =
SiteInfo::Create(isolation_context, nonapp_urlinfo);
auto ui_nonapp_url_lock =
ProcessLock::Create(isolation_context, nonapp_urlinfo);
auto app_urlinfo = UrlInfo::CreateForTesting(
app_url, CreateStoragePartitionConfigForTesting());
auto ui_app_url_lock = ProcessLock::Create(isolation_context, app_urlinfo);
auto ui_app_url_siteinfo = SiteInfo::Create(isolation_context, app_urlinfo);
SiteInfo io_nonapp_url_siteinfo(browser_context());
ProcessLock io_nonapp_url_lock;
SiteInfo io_app_url_siteinfo(browser_context());
ProcessLock io_app_url_lock;
base::WaitableEvent io_locks_set_event;
GetIOThreadTaskRunner({})->PostTask(
FROM_HERE, base::BindLambdaForTesting([&]() {
io_nonapp_url_siteinfo =
SiteInfo::CreateOnIOThread(isolation_context, nonapp_urlinfo);
io_nonapp_url_lock =
ProcessLock::Create(isolation_context, nonapp_urlinfo);
io_app_url_siteinfo =
SiteInfo::CreateOnIOThread(isolation_context, app_urlinfo);
io_app_url_lock = ProcessLock::Create(isolation_context, app_urlinfo);
io_locks_set_event.Signal();
}));
io_locks_set_event.Wait();
EXPECT_EQ(ui_nonapp_url_siteinfo, io_nonapp_url_siteinfo);
EXPECT_EQ(ui_nonapp_url_lock, io_nonapp_url_lock);
EXPECT_NE(ui_app_url_siteinfo, io_app_url_siteinfo);
EXPECT_NE(ui_app_url_siteinfo.site_url(), io_app_url_siteinfo.site_url());
EXPECT_EQ(ui_app_url_siteinfo.process_lock_url(),
io_app_url_siteinfo.process_lock_url());
EXPECT_EQ(ui_app_url_lock, io_app_url_lock);
SetBrowserClientForTesting(original_client);
}
TEST_P(ChildProcessSecurityPolicyTest,
IsolatedOriginsForSpecificBrowsingInstances) {
url::Origin foo = url::Origin::Create(GURL("https://foo.com/"));
url::Origin bar = url::Origin::Create(GURL("https://bar.com/"));
url::Origin baz = url::Origin::Create(GURL("https://baz.com/"));
ChildProcessSecurityPolicyImpl* p =
ChildProcessSecurityPolicyImpl::GetInstance();
LOCKED_EXPECT_THAT(p->isolated_origins_lock_, p->isolated_origins_,
testing::IsEmpty());
TestBrowserContext context;
scoped_refptr<SiteInstanceImpl> foo_instance =
SiteInstanceImpl::CreateForTesting(&context, GURL("https://foo.com/"));
auto foo_browsing_instance_id =
foo_instance->GetIsolationContext().browsing_instance_id();
scoped_refptr<SiteInstanceImpl> bar_instance =
SiteInstanceImpl::CreateForTesting(&context, GURL("https://bar.com/"));
auto bar_browsing_instance_id =
bar_instance->GetIsolationContext().browsing_instance_id();
scoped_refptr<SiteInstanceImpl> baz_instance =
SiteInstanceImpl::CreateForTesting(&context, GURL("https://baz.com/"));
auto baz_browsing_instance_id =
baz_instance->GetIsolationContext().browsing_instance_id();
p->AddCoopIsolatedOriginForBrowsingInstance(
foo_instance->GetIsolationContext(), foo, IsolatedOriginSource::TEST);
LOCKED_EXPECT_THAT(
p->isolated_origins_lock_, p->isolated_origins_,
testing::UnorderedElementsAre(GetIsolatedOriginEntry(
&context, false ,
foo_browsing_instance_id, foo)));
EXPECT_TRUE(IsIsolatedOrigin(&context, foo_browsing_instance_id, foo));
EXPECT_FALSE(IsIsolatedOrigin(&context, foo_browsing_instance_id, bar));
EXPECT_FALSE(IsIsolatedOrigin(&context, foo_browsing_instance_id, baz));
EXPECT_FALSE(IsIsolatedOrigin(&context, bar_browsing_instance_id, foo));
EXPECT_FALSE(IsIsolatedOrigin(&context, bar_browsing_instance_id, bar));
EXPECT_FALSE(IsIsolatedOrigin(&context, bar_browsing_instance_id, baz));
EXPECT_FALSE(IsIsolatedOrigin(&context, baz_browsing_instance_id, foo));
EXPECT_FALSE(IsIsolatedOrigin(&context, baz_browsing_instance_id, bar));
EXPECT_FALSE(IsIsolatedOrigin(&context, baz_browsing_instance_id, baz));
EXPECT_TRUE(
IsIsolatedOrigin(&context, foo_browsing_instance_id,
url::Origin::Create(GURL("https://sub.foo.com"))));
EXPECT_TRUE(
IsIsolatedOrigin(&context, foo_browsing_instance_id,
url::Origin::Create(GURL("https://sub2.sub.foo.com"))));
p->AddCoopIsolatedOriginForBrowsingInstance(
foo_instance->GetIsolationContext(), foo, IsolatedOriginSource::TEST);
EXPECT_EQ(1, GetIsolatedOriginEntryCount(foo));
LOCKED_EXPECT_THAT(
p->isolated_origins_lock_, p->isolated_origins_,
testing::UnorderedElementsAre(GetIsolatedOriginEntry(
&context, false ,
foo_browsing_instance_id, foo)));
p->AddCoopIsolatedOriginForBrowsingInstance(
baz_instance->GetIsolationContext(), baz, IsolatedOriginSource::TEST);
LOCKED_EXPECT_THAT(
p->isolated_origins_lock_, p->isolated_origins_,
testing::UnorderedElementsAre(
GetIsolatedOriginEntry(
&context, false ,
foo_browsing_instance_id, foo),
GetIsolatedOriginEntry(
&context, false ,
baz_browsing_instance_id, baz)));
EXPECT_TRUE(IsIsolatedOrigin(&context, foo_browsing_instance_id, foo));
EXPECT_FALSE(IsIsolatedOrigin(&context, foo_browsing_instance_id, bar));
EXPECT_FALSE(IsIsolatedOrigin(&context, foo_browsing_instance_id, baz));
EXPECT_FALSE(IsIsolatedOrigin(&context, bar_browsing_instance_id, foo));
EXPECT_FALSE(IsIsolatedOrigin(&context, bar_browsing_instance_id, bar));
EXPECT_FALSE(IsIsolatedOrigin(&context, bar_browsing_instance_id, baz));
EXPECT_FALSE(IsIsolatedOrigin(&context, baz_browsing_instance_id, foo));
EXPECT_FALSE(IsIsolatedOrigin(&context, baz_browsing_instance_id, bar));
EXPECT_TRUE(IsIsolatedOrigin(&context, baz_browsing_instance_id, baz));
p->AddCoopIsolatedOriginForBrowsingInstance(
foo_instance->GetIsolationContext(), bar, IsolatedOriginSource::TEST);
EXPECT_TRUE(IsIsolatedOrigin(&context, foo_browsing_instance_id, foo));
EXPECT_TRUE(IsIsolatedOrigin(&context, foo_browsing_instance_id, bar));
EXPECT_FALSE(IsIsolatedOrigin(&context, foo_browsing_instance_id, baz));
EXPECT_FALSE(IsIsolatedOrigin(&context, bar_browsing_instance_id, foo));
EXPECT_FALSE(IsIsolatedOrigin(&context, bar_browsing_instance_id, bar));
EXPECT_FALSE(IsIsolatedOrigin(&context, bar_browsing_instance_id, baz));
EXPECT_FALSE(IsIsolatedOrigin(&context, baz_browsing_instance_id, foo));
EXPECT_FALSE(IsIsolatedOrigin(&context, baz_browsing_instance_id, bar));
EXPECT_TRUE(IsIsolatedOrigin(&context, baz_browsing_instance_id, baz));
p->AddCoopIsolatedOriginForBrowsingInstance(
bar_instance->GetIsolationContext(), foo, IsolatedOriginSource::TEST);
p->AddCoopIsolatedOriginForBrowsingInstance(
baz_instance->GetIsolationContext(), foo, IsolatedOriginSource::TEST);
EXPECT_TRUE(IsIsolatedOrigin(&context, foo_browsing_instance_id, foo));
EXPECT_TRUE(IsIsolatedOrigin(&context, foo_browsing_instance_id, bar));
EXPECT_FALSE(IsIsolatedOrigin(&context, foo_browsing_instance_id, baz));
EXPECT_TRUE(IsIsolatedOrigin(&context, bar_browsing_instance_id, foo));
EXPECT_FALSE(IsIsolatedOrigin(&context, bar_browsing_instance_id, bar));
EXPECT_FALSE(IsIsolatedOrigin(&context, bar_browsing_instance_id, baz));
EXPECT_TRUE(IsIsolatedOrigin(&context, baz_browsing_instance_id, foo));
EXPECT_FALSE(IsIsolatedOrigin(&context, baz_browsing_instance_id, bar));
EXPECT_TRUE(IsIsolatedOrigin(&context, baz_browsing_instance_id, baz));
EXPECT_EQ(3, GetIsolatedOriginEntryCount(foo));
p->SetBrowsingInstanceCleanupDelayForTesting(0);
foo_instance.reset();
EXPECT_FALSE(IsIsolatedOrigin(&context, foo_browsing_instance_id, foo));
EXPECT_FALSE(IsIsolatedOrigin(&context, foo_browsing_instance_id, bar));
EXPECT_FALSE(IsIsolatedOrigin(&context, foo_browsing_instance_id, baz));
EXPECT_TRUE(IsIsolatedOrigin(&context, bar_browsing_instance_id, foo));
EXPECT_FALSE(IsIsolatedOrigin(&context, bar_browsing_instance_id, bar));
EXPECT_FALSE(IsIsolatedOrigin(&context, bar_browsing_instance_id, baz));
EXPECT_TRUE(IsIsolatedOrigin(&context, baz_browsing_instance_id, foo));
EXPECT_FALSE(IsIsolatedOrigin(&context, baz_browsing_instance_id, bar));
EXPECT_TRUE(IsIsolatedOrigin(&context, baz_browsing_instance_id, baz));
p->ClearIsolatedOriginsForTesting();
}
TEST_P(ChildProcessSecurityPolicyTest,
IsolatedOriginsForCurrentAndFutureBrowsingInstances) {
url::Origin foo = url::Origin::Create(GURL("https://foo.com/"));
url::Origin bar = url::Origin::Create(GURL("https://bar.com/"));
ChildProcessSecurityPolicyImpl* p =
ChildProcessSecurityPolicyImpl::GetInstance();
LOCKED_EXPECT_THAT(p->isolated_origins_lock_, p->isolated_origins_,
testing::IsEmpty());
TestBrowserContext context;
scoped_refptr<SiteInstanceImpl> foo_instance =
SiteInstanceImpl::CreateForTesting(&context, GURL("https://foo.com/"));
auto foo_browsing_instance_id =
foo_instance->GetIsolationContext().browsing_instance_id();
p->AddCoopIsolatedOriginForBrowsingInstance(
foo_instance->GetIsolationContext(), foo, IsolatedOriginSource::TEST);
EXPECT_EQ(1, GetIsolatedOriginEntryCount(foo));
scoped_refptr<SiteInstanceImpl> bar_instance =
SiteInstanceImpl::CreateForTesting(&context, GURL("https://bar.com/"));
auto bar_browsing_instance_id =
bar_instance->GetIsolationContext().browsing_instance_id();
BrowsingInstanceId future_id(SiteInstanceImpl::NextBrowsingInstanceId());
p->AddFutureIsolatedOrigins({foo}, IsolatedOriginSource::TEST, &context);
EXPECT_EQ(2, GetIsolatedOriginEntryCount(foo));
EXPECT_TRUE(IsIsolatedOrigin(&context, foo_browsing_instance_id, foo));
EXPECT_FALSE(IsIsolatedOrigin(&context, bar_browsing_instance_id, foo));
EXPECT_TRUE(IsIsolatedOrigin(&context, future_id, foo));
EXPECT_TRUE(IsIsolatedOrigin(&context, future_id.value() + 42, foo));
EXPECT_FALSE(IsIsolatedOrigin(&context, foo_browsing_instance_id, bar));
EXPECT_FALSE(IsIsolatedOrigin(&context, bar_browsing_instance_id, bar));
EXPECT_FALSE(IsIsolatedOrigin(&context, future_id, bar));
scoped_refptr<SiteInstanceImpl> future_instance =
SiteInstanceImpl::CreateForTesting(&context, GURL("https://foo.com/"));
EXPECT_EQ(future_id,
future_instance->GetIsolationContext().browsing_instance_id());
p->AddCoopIsolatedOriginForBrowsingInstance(
future_instance->GetIsolationContext(), foo, IsolatedOriginSource::TEST);
EXPECT_EQ(2, GetIsolatedOriginEntryCount(foo));
p->AddFutureIsolatedOrigins({foo}, IsolatedOriginSource::TEST, &context);
EXPECT_EQ(2, GetIsolatedOriginEntryCount(foo));
EXPECT_LT(bar_browsing_instance_id, future_id);
p->AddCoopIsolatedOriginForBrowsingInstance(
bar_instance->GetIsolationContext(), foo, IsolatedOriginSource::TEST);
EXPECT_EQ(3, GetIsolatedOriginEntryCount(foo));
EXPECT_TRUE(IsIsolatedOrigin(&context, foo_browsing_instance_id, foo));
EXPECT_TRUE(IsIsolatedOrigin(&context, bar_browsing_instance_id, foo));
EXPECT_TRUE(IsIsolatedOrigin(&context, future_id, foo));
EXPECT_TRUE(IsIsolatedOrigin(&context, future_id.value() + 42, foo));
p->SetBrowsingInstanceCleanupDelayForTesting(0);
foo_instance.reset();
EXPECT_EQ(2, GetIsolatedOriginEntryCount(foo));
EXPECT_FALSE(IsIsolatedOrigin(&context, foo_browsing_instance_id, foo));
EXPECT_TRUE(IsIsolatedOrigin(&context, bar_browsing_instance_id, foo));
EXPECT_TRUE(IsIsolatedOrigin(&context, future_id, foo));
EXPECT_TRUE(IsIsolatedOrigin(&context, future_id.value() + 42, foo));
future_instance.reset();
EXPECT_EQ(2, GetIsolatedOriginEntryCount(foo));
EXPECT_FALSE(IsIsolatedOrigin(&context, foo_browsing_instance_id, foo));
EXPECT_TRUE(IsIsolatedOrigin(&context, bar_browsing_instance_id, foo));
EXPECT_TRUE(IsIsolatedOrigin(&context, future_id, foo));
EXPECT_TRUE(IsIsolatedOrigin(&context, future_id.value() + 42, foo));
p->ClearIsolatedOriginsForTesting();
}
TEST_P(ChildProcessSecurityPolicyTest, NoBrowsingInstanceIDs_OriginKeyed) {
url::Origin foo = url::Origin::Create(GURL("https://sub.foo.com/"));
ChildProcessSecurityPolicyImpl* p =
ChildProcessSecurityPolicyImpl::GetInstance();
p->SetBrowsingInstanceCleanupDelayForTesting(0);
TestBrowserContext context;
{
auto origin_isolation_request =
static_cast<UrlInfo::OriginIsolationRequest>(
UrlInfo::OriginIsolationRequest::kOriginAgentCluster |
UrlInfo::OriginIsolationRequest::kRequiresOriginKeyedProcess);
UrlInfo url_info(UrlInfoInit(foo.GetURL())
.WithOriginIsolationRequest(origin_isolation_request));
scoped_refptr<SiteInstanceImpl> foo_instance =
SiteInstanceImpl::CreateForUrlInfo(&context, url_info,
false,
false);
p->Add(kRendererID, &context);
p->LockProcess(foo_instance->GetIsolationContext(), kRendererID,
false,
ProcessLock::FromSiteInfo(foo_instance->GetSiteInfo()));
EXPECT_TRUE(p->GetProcessLock(kRendererID).is_locked_to_site());
EXPECT_TRUE(p->GetProcessLock(kRendererID).is_origin_keyed_process());
EXPECT_EQ(foo.GetURL(), p->GetProcessLock(kRendererID).lock_url());
EXPECT_TRUE(ProcessLock::FromSiteInfo(foo_instance->GetSiteInfo())
.is_origin_keyed_process());
EXPECT_TRUE(p->DetermineOriginAgentClusterIsolation(
foo_instance->GetIsolationContext(), foo,
OriginAgentClusterIsolationState::CreateNonIsolated())
.requires_origin_keyed_process());
}
EXPECT_EQ(static_cast<size_t>(0),
p->BrowsingInstanceIdCountForTesting(kRendererID));
EXPECT_TRUE(p->CanAccessDataForOrigin(kRendererID, foo));
EXPECT_FALSE(p->CanAccessDataForOrigin(
kRendererID, url::Origin::Create(GURL("https://foo.com/"))));
EXPECT_FALSE(p->CanAccessDataForOrigin(
kRendererID, url::Origin::Create(GURL("https://bar.com/"))));
p->Remove(kRendererID);
}
TEST_P(ChildProcessSecurityPolicyTest, NoBrowsingInstanceIDs_SiteKeyed) {
url::Origin foo = url::Origin::Create(GURL("https://sub.foo.com/"));
ChildProcessSecurityPolicyImpl* p =
ChildProcessSecurityPolicyImpl::GetInstance();
p->SetBrowsingInstanceCleanupDelayForTesting(0);
TestBrowserContext context;
{
p->Add(kRendererID, &context);
p->AddFutureIsolatedOrigins({url::Origin::Create(GURL("https://foo.com"))},
IsolatedOriginSource::TEST, &context);
UrlInfo url_info(UrlInfoInit(foo.GetURL()));
scoped_refptr<SiteInstanceImpl> foo_instance =
SiteInstanceImpl::CreateForUrlInfo(&context, url_info,
false,
false);
p->LockProcess(foo_instance->GetIsolationContext(), kRendererID,
false,
ProcessLock::FromSiteInfo(foo_instance->GetSiteInfo()));
EXPECT_TRUE(p->GetProcessLock(kRendererID).is_locked_to_site());
EXPECT_FALSE(p->GetProcessLock(kRendererID).is_origin_keyed_process());
EXPECT_EQ(SiteInfo::GetSiteForOrigin(foo),
p->GetProcessLock(kRendererID).lock_url());
EXPECT_FALSE(ProcessLock::FromSiteInfo(foo_instance->GetSiteInfo())
.is_origin_keyed_process());
EXPECT_FALSE(p->DetermineOriginAgentClusterIsolation(
foo_instance->GetIsolationContext(), foo,
OriginAgentClusterIsolationState::CreateNonIsolated())
.requires_origin_keyed_process());
}
EXPECT_EQ(static_cast<size_t>(0),
p->BrowsingInstanceIdCountForTesting(kRendererID));
EXPECT_TRUE(p->CanAccessDataForOrigin(kRendererID, foo));
EXPECT_TRUE(p->CanAccessDataForOrigin(
kRendererID, url::Origin::Create(GURL("https://foo.com/"))));
EXPECT_FALSE(p->CanAccessDataForOrigin(
kRendererID, url::Origin::Create(GURL("https://bar.com/"))));
p->Remove(kRendererID);
}
TEST_P(ChildProcessSecurityPolicyTest, NoBrowsingInstanceIDs_UnlockedProcess) {
GURL foo_url = GURL("https://foo.com/");
url::Origin foo = url::Origin::Create(foo_url);
ChildProcessSecurityPolicyImpl* p =
ChildProcessSecurityPolicyImpl::GetInstance();
p->SetBrowsingInstanceCleanupDelayForTesting(0);
base::test::ScopedFeatureList feature_list;
feature_list.InitWithFeatures(
{features::kProcessSharingWithDefaultSiteInstances},
{features::kProcessSharingWithStrictSiteInstances});
EXPECT_TRUE(base::FeatureList::IsEnabled(
features::kProcessSharingWithDefaultSiteInstances));
EXPECT_FALSE(base::FeatureList::IsEnabled(
features::kProcessSharingWithStrictSiteInstances));
base::test::ScopedCommandLine scoped_command_line;
scoped_command_line.GetProcessCommandLine()->AppendSwitch(
switches::kDisableSiteIsolation);
scoped_command_line.GetProcessCommandLine()->RemoveSwitch(
switches::kSitePerProcess);
EXPECT_FALSE(SiteIsolationPolicy::UseDedicatedProcessesForAllSites());
EXPECT_EQ(static_cast<size_t>(0),
p->BrowsingInstanceIdCountForTesting(kRendererID));
TestBrowserContext context;
{
scoped_refptr<SiteInstanceImpl> foo_instance =
SiteInstanceImpl::CreateForTesting(&context, foo_url);
p->Add(kRendererID, &context);
p->LockProcess(foo_instance->GetIsolationContext(), kRendererID,
false,
ProcessLock::CreateAllowAnySite(
StoragePartitionConfig::CreateDefault(&context),
WebExposedIsolationInfo::CreateNonIsolated()));
EXPECT_TRUE(foo_instance->IsDefaultSiteInstance());
EXPECT_TRUE(foo_instance->HasSite());
EXPECT_EQ(foo_instance->GetSiteInfo(),
SiteInfo::CreateForDefaultSiteInstance(
foo_instance->GetIsolationContext(),
StoragePartitionConfig::CreateDefault(&context),
WebExposedIsolationInfo::CreateNonIsolated()));
EXPECT_FALSE(foo_instance->RequiresDedicatedProcess());
}
EXPECT_EQ(static_cast<size_t>(0),
p->BrowsingInstanceIdCountForTesting(kRendererID));
EXPECT_FALSE(p->GetProcessLock(kRendererID).is_locked_to_site());
EXPECT_FALSE(p->CanAccessDataForOrigin(kRendererID, foo));
p->Remove(kRendererID);
}
TEST_P(ChildProcessSecurityPolicyTest, CannotLockUsedProcessToSite) {
ChildProcessSecurityPolicyImpl* p =
ChildProcessSecurityPolicyImpl::GetInstance();
TestBrowserContext context;
scoped_refptr<SiteInstanceImpl> foo_instance =
SiteInstanceImpl::CreateForTesting(&context, GURL("https://foo.com"));
scoped_refptr<SiteInstanceImpl> bar_instance =
SiteInstanceImpl::CreateForTesting(&context, GURL("https://bar.com"));
p->Add(kRendererID, &context);
p->LockProcess(foo_instance->GetIsolationContext(), kRendererID,
false,
ProcessLock::CreateAllowAnySite(
StoragePartitionConfig::CreateDefault(&context),
WebExposedIsolationInfo::CreateNonIsolated()));
EXPECT_TRUE(p->GetProcessLock(kRendererID).allows_any_site());
EXPECT_FALSE(p->GetProcessLock(kRendererID).is_locked_to_site());
EXPECT_CHECK_DEATH_WITH(
{
p->LockProcess(bar_instance->GetIsolationContext(), kRendererID,
true,
ProcessLock::FromSiteInfo(bar_instance->GetSiteInfo()));
},
"Cannot lock an already used process to .*bar\\.com");
p->Remove(kRendererID);
}
INSTANTIATE_TEST_SUITE_P(
,
ChildProcessSecurityPolicyTest,
::testing::Values(ChildProcessSecurityPolicyTestCase::kCitadelDisabled,
ChildProcessSecurityPolicyTestCase::kCitadelEnabled),
&ChildProcessSecurityPolicyTest::DescribeParams);
}