Commit 0672f8a0 authored by Lukasz Anforowicz's avatar Lukasz Anforowicz Committed by Commit Bot

Support for field trials of origin isolation.

CL overview
===========

This CL adds a base::Feature for origin isolation to support turning on
this feature in a field trial.  List of origins to isolate can be
specified via a field trial param (see also internal documentation at
cs/finch/experiment-params.md).


Testing
=======

I've tested this CL with the following repro steps:

1. Build Chrome with the CL patched-in (and with r518725 included).

2. Test the default behavior.
   2.1. Launch Chrome without any special command-line flags
        (except --user-data-dir).
   2.2. Go to https://csreis.github.io/tests/cross-site-iframe.html
   2.3. Click "Go cross-site (complex-page)" button
   2.4. In Chrome Task Manager verify that the subframe
        stays in the main frame's process

3. Test the field trial behavior.
   3.1. Launch Chrome with the following command-line flags:
      --enable-features="IsolateOrigins<MyTrialName" \
      --force-fieldtrials=MyTrialName/MyTrialGroup \
      --force-fieldtrial-params=MyTrialName.MyTrialGroup:OriginsList/https%3A%2F%2Fchromium-build.appspot.com
   3.2. Go to https://csreis.github.io/tests/cross-site-iframe.html
   3.3. Click "Go cross-site (complex-page)" button
   3.4. In Chrome Task Manager verify that there are 3 separate
        processes:
      - One for main frame (https://csreis.github.io/)
      - One for the isolated origin (https://chromium-build.appspot.com)
      - One for a subframe inside the isolated origin
        (https://chromium-status.appspot.com)

Note that in step 3.1 some characters in the field trial param had to be
escaped using percent encoding.


Other notes
===========

This CL refactors SiteIsolationPolicy and
ChildProcessSecurityPolicyImpl, so that

1) One can add a set of isolated origins to ChildProcessSecurityPolicyImpl
   regardless of the source (ContentBrowserClient vs cmdline/field-trial).
   After this CL, ChildProcessSecurityPolicyImpl exposes only a single
       void AddIsolatedOrigins(std::vector<url::Origin> origins);
   method (and doesn't anymore offer adding a single origin or
   parsing cmdline).

   One extra benefit of this change is that the
   ChildProcessSecurityPolicyImpl::lock_ is not taken and released
   once per every single origin (after this CL it is taken and released
   only once per batch of origins passed to AddIsolatedOrigins).

2) Parsing of a string with a list of origins can be reused for parsing
   cmdline arg and for parsing a field trial param.  After this CL,
   parsing is done via SiteIsolationPolicy::ParseIsolatedOrigins.
   Unit tests have correspondingly been moved from
   child_process_security_policy_unittest.cc to
   site_isolation_policy_unittest.cc


Bug: 780133
Change-Id: I28578bfd7f141ea8bdf0330f2342a1fb77619148
Reviewed-on: https://chromium-review.googlesource.com/786276
Commit-Queue: Łukasz Anforowicz <lukasza@chromium.org>
Reviewed-by: default avatarAlex Moshchuk <alexmos@chromium.org>
Cr-Commit-Position: refs/heads/master@{#520360}
parent 3c11bd5d
......@@ -93,6 +93,7 @@
#include "content/browser/webui/url_data_manager.h"
#include "content/common/content_switches_internal.h"
#include "content/common/service_manager/service_manager_connection_impl.h"
#include "content/common/site_isolation_policy.h"
#include "content/common/task_scheduler.h"
#include "content/public/browser/browser_main_parts.h"
#include "content/public/browser/content_browser_client.h"
......@@ -909,19 +910,11 @@ int BrowserMainLoop::PreCreateThreads() {
// Initialize origins that are whitelisted for process isolation. Must be
// done after base::FeatureList is initialized, but before any navigations
// can happen.
std::vector<url::Origin> origins =
GetContentClient()->browser()->GetOriginsRequiringDedicatedProcess();
ChildProcessSecurityPolicyImpl* policy =
ChildProcessSecurityPolicyImpl::GetInstance();
for (auto origin : origins)
policy->AddIsolatedOrigin(origin);
// The command line values must be read after `parts_->PreCreateThreads()` so
// that embedders can append values via policy.
if (parsed_command_line_.HasSwitch(switches::kIsolateOrigins)) {
policy->AddIsolatedOriginsFromCommandLine(
parsed_command_line_.GetSwitchValueASCII(switches::kIsolateOrigins));
}
policy->AddIsolatedOrigins(SiteIsolationPolicy::GetIsolatedOrigins());
policy->AddIsolatedOrigins(
GetContentClient()->browser()->GetOriginsRequiringDedicatedProcess());
return result_code_;
}
......
......@@ -15,7 +15,6 @@
#include "base/macros.h"
#include "base/memory/ptr_util.h"
#include "base/metrics/histogram_macros.h"
#include "base/strings/string_split.h"
#include "base/strings/string_util.h"
#include "build/build_config.h"
#include "content/browser/isolated_origin_util.h"
......@@ -1146,28 +1145,24 @@ bool ChildProcessSecurityPolicyImpl::CanSendMidiSysExMessage(int child_id) {
return state->second->can_send_midi_sysex();
}
void ChildProcessSecurityPolicyImpl::AddIsolatedOrigin(
const url::Origin& origin) {
CHECK(IsolatedOriginUtil::IsValidIsolatedOrigin(origin));
base::AutoLock lock(lock_);
if (isolated_origins_.count(origin)) {
LOG(ERROR) << "Ignoring duplicate isolated origin: " << origin.Serialize();
return;
}
void ChildProcessSecurityPolicyImpl::AddIsolatedOrigins(
std::vector<url::Origin> origins_to_add) {
// Filter out origins that cannot be used as an isolated origin.
auto end_of_valid_origins =
std::remove_if(origins_to_add.begin(), origins_to_add.end(),
[](const url::Origin& origin) {
if (IsolatedOriginUtil::IsValidIsolatedOrigin(origin))
return false; // Don't remove.
isolated_origins_.insert(origin);
}
LOG(ERROR) << "Invalid isolated origin: " << origin;
return true; // Remove.
});
origins_to_add.erase(end_of_valid_origins, origins_to_add.end());
void ChildProcessSecurityPolicyImpl::AddIsolatedOriginsFromCommandLine(
const std::string& origin_list) {
for (const base::StringPiece& origin_piece :
base::SplitStringPiece(origin_list, ",", base::TRIM_WHITESPACE,
base::SPLIT_WANT_NONEMPTY)) {
url::Origin origin = url::Origin::Create((GURL(origin_piece)));
if (!origin.unique())
AddIsolatedOrigin(origin);
}
// Taking the lock once and doing a batch insertion via base::flat_set::insert
// is important because of performance characteristics of base::flat_set.
base::AutoLock lock(lock_);
isolated_origins_.insert(origins_to_add.begin(), origins_to_add.end());
}
bool ChildProcessSecurityPolicyImpl::IsIsolatedOrigin(
......
......@@ -12,6 +12,7 @@
#include <vector>
#include "base/compiler_specific.h"
#include "base/containers/flat_set.h"
#include "base/gtest_prod_util.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
......@@ -208,7 +209,7 @@ class CONTENT_EXPORT ChildProcessSecurityPolicyImpl
// Returns true if sending system exclusive messages is allowed.
bool CanSendMidiSysExMessage(int child_id);
// Add an origin to the list of origins that require process isolation.
// Add |origins| to the list of origins that require process isolation.
// When making process model decisions for such origins, the full
// scheme+host+port tuple rather than scheme and eTLD+1 will be used.
// SiteInstances for these origins will also use the full origin as site URL.
......@@ -218,7 +219,7 @@ class CONTENT_EXPORT ChildProcessSecurityPolicyImpl
// isolated origin, then https://bar.isolated.foo.com will be considered part
// of the site for https://isolated.foo.com.
//
// Note that |origin| must not be unique. URLs that render with
// Note that origins from |origins| must not be unique - URLs that render with
// unique origins, such as data: URLs, are not supported. Suborigins (see
// https://w3c.github.io/webappsec-suborigins/ -- not to be confused with
// subdomains) and non-standard schemes are also not supported. Sandboxed
......@@ -228,13 +229,10 @@ class CONTENT_EXPORT ChildProcessSecurityPolicyImpl
// origin opens an about:blank popup, it will stay in the isolated origin's
// process. Nested URLs (filesystem: and blob:) retain process isolation
// behavior of their inner origin.
void AddIsolatedOrigin(const url::Origin& origin);
// Register a set of isolated origins as specified on the command line with
// the --isolate-origins flag. |origin_list| is the flag's value, which
// contains the list of comma-separated scheme-host-port origins. See
// AddIsolatedOrigin for definition of an isolated origin.
void AddIsolatedOriginsFromCommandLine(const std::string& origin_list);
//
// Note that it is okay if |origins| contains duplicates - the set of origins
// will be deduplicated inside the method.
void AddIsolatedOrigins(std::vector<url::Origin> origins);
// Check whether |origin| requires origin-wide process isolation.
//
......@@ -287,8 +285,7 @@ class CONTENT_EXPORT ChildProcessSecurityPolicyImpl
FRIEND_TEST_ALL_PREFIXES(ChildProcessSecurityPolicyInProcessBrowserTest,
NoLeak);
FRIEND_TEST_ALL_PREFIXES(ChildProcessSecurityPolicyTest, FilePermissions);
FRIEND_TEST_ALL_PREFIXES(ChildProcessSecurityPolicyTest,
IsolateOriginsFromCommandLine);
FRIEND_TEST_ALL_PREFIXES(ChildProcessSecurityPolicyTest, AddIsolatedOrigins);
class SecurityState;
......@@ -377,7 +374,7 @@ class CONTENT_EXPORT ChildProcessSecurityPolicyImpl
// when making process model decisions, rather than the origin's scheme and
// eTLD+1. Each of these origins requires a dedicated process. This set is
// protected by |lock_|.
std::set<url::Origin> isolated_origins_;
base::flat_set<url::Origin> isolated_origins_;
DISALLOW_COPY_AND_ASSIGN(ChildProcessSecurityPolicyImpl);
};
......
......@@ -6,6 +6,8 @@
#include <string>
#include "base/files/file_path.h"
#include "base/logging.h"
#include "base/test/mock_log.h"
#include "content/browser/child_process_security_policy_impl.h"
#include "content/public/common/url_constants.h"
#include "content/test/test_content_browser_client.h"
......@@ -13,6 +15,7 @@
#include "storage/browser/fileapi/file_system_url.h"
#include "storage/browser/fileapi/isolated_context.h"
#include "storage/common/fileapi/file_system_types.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "url/gurl.h"
#include "url/origin.h"
......@@ -972,32 +975,59 @@ TEST_F(ChildProcessSecurityPolicyTest, OriginGranting) {
p->Remove(kRendererID);
}
// Verifies ChildProcessSecurityPolicyImpl::AddIsolatedOrigins method.
TEST_F(ChildProcessSecurityPolicyTest, AddIsolatedOrigins) {
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 foobar = url::Origin::Create(GURL("https://foobar.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();
// Verifies parsing logic that extracts origins from --isolate-origins.
TEST_F(ChildProcessSecurityPolicyTest, IsolateOriginsFromCommandLine) {
// Invalid and unique origins are not permitted.
auto* policy = ChildProcessSecurityPolicyImpl::GetInstance();
policy->AddIsolatedOriginsFromCommandLine("foo");
policy->AddIsolatedOriginsFromCommandLine("");
policy->AddIsolatedOriginsFromCommandLine("about:blank");
EXPECT_EQ(0U, policy->isolated_origins_.size());
policy->AddIsolatedOriginsFromCommandLine("http://isolated.foo.com");
EXPECT_EQ(1U, policy->isolated_origins_.size());
EXPECT_TRUE(policy->IsIsolatedOrigin(
url::Origin::Create(GURL("http://isolated.foo.com"))));
policy->AddIsolatedOriginsFromCommandLine(
"http://a.com,https://b.com,,https://c.com:8000");
EXPECT_EQ(4U, policy->isolated_origins_.size());
EXPECT_TRUE(policy->IsIsolatedOrigin(
url::Origin::Create(GURL("http://isolated.foo.com"))));
EXPECT_TRUE(
policy->IsIsolatedOrigin(url::Origin::Create(GURL("http://a.com"))));
EXPECT_TRUE(
policy->IsIsolatedOrigin(url::Origin::Create(GURL("https://b.com"))));
EXPECT_TRUE(policy->IsIsolatedOrigin(
url::Origin::Create(GURL("https://c.com:8000"))));
// Initially there should be no isolated origins.
EXPECT_THAT(p->isolated_origins_, testing::IsEmpty());
// Verify deduplication of the argument.
p->AddIsolatedOrigins({foo, bar, bar});
EXPECT_THAT(p->isolated_origins_, testing::UnorderedElementsAre(foo, bar));
// Verify that the old set is extended (not replaced).
p->AddIsolatedOrigins({baz});
EXPECT_THAT(p->isolated_origins_,
testing::UnorderedElementsAre(foo, bar, baz));
// Verify deduplication against the old set.
p->AddIsolatedOrigins({foo});
EXPECT_THAT(p->isolated_origins_,
testing::UnorderedElementsAre(foo, bar, baz));
// Verify deduplication considers scheme and port differences.
p->AddIsolatedOrigins({baz, baz_http_8000, baz_https_8000});
EXPECT_THAT(p->isolated_origins_,
testing::UnorderedElementsAre(foo, bar, baz, baz_http_8000,
baz_https_8000));
// Verify that adding an origin that is invalid for isolation will 1) log a
// warning and 2) won't CHECK or crash the browser process, 3) will not add
// the invalid origin, but will add the remaining origins passed to
// AddIsolatedOrigins.
{
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->AddIsolatedOrigins({foobar, invalid_etld});
EXPECT_THAT(p->isolated_origins_,
testing::UnorderedElementsAre(foo, bar, baz, baz_http_8000,
baz_https_8000, foobar));
}
}
} // namespace content
......@@ -3,12 +3,15 @@
// found in the LICENSE file.
#include "base/command_line.h"
#include "base/macros.h"
#include "base/test/scoped_feature_list.h"
#include "content/browser/bad_message.h"
#include "content/browser/child_process_security_policy_impl.h"
#include "content/browser/storage_partition_impl.h"
#include "content/browser/web_contents/web_contents_impl.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/common/browser_side_navigation_policy.h"
#include "content/public/common/content_features.h"
#include "content/public/common/content_switches.h"
#include "content/public/test/browser_test_utils.h"
#include "content/public/test/content_browser_test.h"
......@@ -55,6 +58,9 @@ class IsolatedOriginTest : public ContentBrowserTest {
"document.body.appendChild(link);"
"link.click();"));
}
private:
DISALLOW_COPY_AND_ASSIGN(IsolatedOriginTest);
};
// Check that navigating a main frame from an non-isolated origin to an
......@@ -897,6 +903,8 @@ class StoragePartitonInterceptor
// Keep a pointer to the original implementation of the service, so all
// calls can be forwarded to it.
mojom::StoragePartitionService* storage_partition_service_;
DISALLOW_COPY_AND_ASSIGN(StoragePartitonInterceptor);
};
void CreateTestStoragePartitionService(
......@@ -930,4 +938,28 @@ IN_PROC_BROWSER_TEST_F(IsolatedOriginTest, LocalStorageOriginEnforcement) {
crash_observer.Wait();
}
class IsolatedOriginFieldTrialTest : public ContentBrowserTest {
public:
IsolatedOriginFieldTrialTest() {
scoped_feature_list_.InitAndEnableFeatureWithParameters(
features::kIsolateOrigins,
{{features::kIsolateOriginsFieldTrialParamName,
"https://field.trial.com/,https://bar.com/"}});
}
~IsolatedOriginFieldTrialTest() override {}
private:
base::test::ScopedFeatureList scoped_feature_list_;
DISALLOW_COPY_AND_ASSIGN(IsolatedOriginFieldTrialTest);
};
IN_PROC_BROWSER_TEST_F(IsolatedOriginFieldTrialTest, Test) {
auto* policy = ChildProcessSecurityPolicyImpl::GetInstance();
EXPECT_TRUE(policy->IsIsolatedOrigin(
url::Origin::Create(GURL("https://field.trial.com/"))));
EXPECT_TRUE(
policy->IsIsolatedOrigin(url::Origin::Create(GURL("https://bar.com/"))));
}
} // namespace content
......@@ -7,6 +7,7 @@
#include <stddef.h>
#include <memory>
#include <string>
#include <vector>
#include "base/command_line.h"
......@@ -47,7 +48,7 @@ const char kPrivilegedScheme[] = "privileged";
class SiteInstanceTestBrowserClient : public TestContentBrowserClient {
public:
explicit SiteInstanceTestBrowserClient()
SiteInstanceTestBrowserClient()
: privileged_process_id_(-1),
site_instance_delete_count_(0),
browsing_instance_delete_count_(0) {
......@@ -896,7 +897,7 @@ TEST_F(SiteInstanceTest, IsolatedOrigins) {
EXPECT_FALSE(policy->IsIsolatedOrigin(url::Origin::Create(isolated_foo_url)));
EXPECT_TRUE(SiteInstance::IsSameWebSite(nullptr, foo_url, isolated_foo_url));
policy->AddIsolatedOrigin(url::Origin::Create(isolated_foo_url));
policy->AddIsolatedOrigins({url::Origin::Create(isolated_foo_url)});
EXPECT_TRUE(policy->IsIsolatedOrigin(url::Origin::Create(isolated_foo_url)));
EXPECT_FALSE(policy->IsIsolatedOrigin(url::Origin::Create(foo_url)));
EXPECT_FALSE(
......@@ -908,7 +909,7 @@ TEST_F(SiteInstanceTest, IsolatedOrigins) {
EXPECT_FALSE(policy->IsIsolatedOrigin(
url::Origin::Create(GURL("http://isolated.foo.com:12345"))));
policy->AddIsolatedOrigin(url::Origin::Create(isolated_bar_url));
policy->AddIsolatedOrigins({url::Origin::Create(isolated_bar_url)});
EXPECT_TRUE(policy->IsIsolatedOrigin(url::Origin::Create(isolated_bar_url)));
// IsSameWebSite should compare origins rather than sites if either URL is an
......@@ -998,7 +999,7 @@ TEST_F(SiteInstanceTest, SubdomainOnIsolatedSite) {
GURL foo_isolated_url("http://foo.isolated.com");
auto* policy = ChildProcessSecurityPolicyImpl::GetInstance();
policy->AddIsolatedOrigin(url::Origin::Create(isolated_url));
policy->AddIsolatedOrigins({url::Origin::Create(isolated_url)});
EXPECT_TRUE(policy->IsIsolatedOrigin(url::Origin::Create(isolated_url)));
EXPECT_TRUE(policy->IsIsolatedOrigin(url::Origin::Create(foo_isolated_url)));
......@@ -1032,7 +1033,7 @@ TEST_F(SiteInstanceTest, SubdomainOnIsolatedSite) {
// Don't try to match subdomains on IP addresses.
GURL isolated_ip("http://127.0.0.1");
policy->AddIsolatedOrigin(url::Origin::Create(isolated_ip));
policy->AddIsolatedOrigins({url::Origin::Create(isolated_ip)});
EXPECT_TRUE(policy->IsIsolatedOrigin(url::Origin::Create(isolated_ip)));
EXPECT_FALSE(policy->IsIsolatedOrigin(
url::Origin::Create(GURL("http://42.127.0.0.1"))));
......@@ -1048,7 +1049,7 @@ TEST_F(SiteInstanceTest, SubdomainOnIsolatedOrigin) {
GURL baz_isolated_foo_url("http://baz.isolated.foo.com");
auto* policy = ChildProcessSecurityPolicyImpl::GetInstance();
policy->AddIsolatedOrigin(url::Origin::Create(isolated_foo_url));
policy->AddIsolatedOrigins({url::Origin::Create(isolated_foo_url)});
EXPECT_FALSE(policy->IsIsolatedOrigin(url::Origin::Create(foo_url)));
EXPECT_TRUE(policy->IsIsolatedOrigin(url::Origin::Create(isolated_foo_url)));
......@@ -1102,8 +1103,8 @@ TEST_F(SiteInstanceTest, MultipleIsolatedOriginsWithCommonSite) {
GURL qux_baz_bar_foo_url("http://qux.baz.bar.foo.com");
auto* policy = ChildProcessSecurityPolicyImpl::GetInstance();
policy->AddIsolatedOrigin(url::Origin::Create(foo_url));
policy->AddIsolatedOrigin(url::Origin::Create(baz_bar_foo_url));
policy->AddIsolatedOrigins(
{url::Origin::Create(foo_url), url::Origin::Create(baz_bar_foo_url)});
EXPECT_TRUE(policy->IsIsolatedOrigin(url::Origin::Create(foo_url)));
EXPECT_TRUE(policy->IsIsolatedOrigin(url::Origin::Create(bar_foo_url)));
......
......@@ -4,10 +4,15 @@
#include "content/common/site_isolation_policy.h"
#include <string>
#include "base/command_line.h"
#include "base/feature_list.h"
#include "base/metrics/field_trial_params.h"
#include "base/strings/string_split.h"
#include "content/public/common/content_features.h"
#include "content/public/common/content_switches.h"
#include "url/gurl.h"
namespace content {
......@@ -29,12 +34,43 @@ bool SiteIsolationPolicy::IsTopDocumentIsolationEnabled() {
// static
bool SiteIsolationPolicy::AreIsolatedOriginsEnabled() {
// TODO(alexmos): This currently assumes that isolated origins are only added
// via the command-line switch, which may not be true in the future. Remove
// this function when AreCrossProcessFramesPossible becomes true on Android
// above.
return base::CommandLine::ForCurrentProcess()->HasSwitch(
switches::kIsolateOrigins) ||
base::FeatureList::IsEnabled(features::kIsolateOrigins);
}
// static
std::vector<url::Origin> SiteIsolationPolicy::GetIsolatedOrigins() {
std::string cmdline_arg =
base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
switches::kIsolateOrigins);
if (!cmdline_arg.empty())
return ParseIsolatedOrigins(cmdline_arg);
if (base::FeatureList::IsEnabled(features::kIsolateOrigins)) {
std::string field_trial_arg = base::GetFieldTrialParamValueByFeature(
features::kIsolateOrigins,
features::kIsolateOriginsFieldTrialParamName);
return ParseIsolatedOrigins(field_trial_arg);
}
return std::vector<url::Origin>();
}
// static
std::vector<url::Origin> SiteIsolationPolicy::ParseIsolatedOrigins(
base::StringPiece arg) {
std::vector<base::StringPiece> origin_strings = base::SplitStringPiece(
arg, ",", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
std::vector<url::Origin> origins;
origins.reserve(origin_strings.size());
for (const base::StringPiece& origin_string : origin_strings) {
url::Origin origin = url::Origin::Create(GURL(origin_string));
if (!origin.unique())
origins.push_back(origin);
}
return origins;
}
} // namespace content
......@@ -5,9 +5,13 @@
#ifndef CONTENT_COMMON_SITE_ISOLATION_POLICY_H_
#define CONTENT_COMMON_SITE_ISOLATION_POLICY_H_
#include <vector>
#include "base/gtest_prod_util.h"
#include "base/macros.h"
#include "base/strings/string_piece_forward.h"
#include "content/common/content_export.h"
#include "url/gurl.h"
#include "url/origin.h"
namespace content {
......@@ -15,7 +19,7 @@ namespace content {
// site isolation, --site-per-process, and related features.
//
// This is currently static because all these modes are controlled by command-
// line flags.
// line flags or field trials.
//
// These methods can be called from any thread.
class CONTENT_EXPORT SiteIsolationPolicy {
......@@ -27,14 +31,21 @@ class CONTENT_EXPORT SiteIsolationPolicy {
// different process from the main frame.
static bool IsTopDocumentIsolationEnabled();
// Returns true if there exist origins that require process isolation. Such
// origins require a dedicated process, and hence they make cross-process
// iframes possible.
// Returns true if isolated origins feature is enabled.
static bool AreIsolatedOriginsEnabled();
// Returns the origins to isolate. See also AreIsolatedOriginsEnabled.
// This list applies globally to the whole browser in all profiles.
// TODO(lukasza): Make sure this list also includes the origins returned by
// ContentBrowserClient::GetOriginsRequiringDedicatedProcess.
static std::vector<url::Origin> GetIsolatedOrigins();
private:
SiteIsolationPolicy(); // Not instantiable.
FRIEND_TEST_ALL_PREFIXES(SiteIsolationPolicyTest, ParseIsolatedOrigins);
static std::vector<url::Origin> ParseIsolatedOrigins(base::StringPiece arg);
DISALLOW_COPY_AND_ASSIGN(SiteIsolationPolicy);
};
......
// Copyright 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "content/common/site_isolation_policy.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "url/gurl.h"
#include "url/origin.h"
namespace content {
// Verifies parsing logic in SiteIsolationPolicy::ParseIsolatedOrigins.
TEST(SiteIsolationPolicyTest, ParseIsolatedOrigins) {
// Invalid and unique origins are not permitted.
EXPECT_THAT(SiteIsolationPolicy::ParseIsolatedOrigins("foo"),
testing::IsEmpty());
EXPECT_THAT(SiteIsolationPolicy::ParseIsolatedOrigins(""),
testing::IsEmpty());
EXPECT_THAT(SiteIsolationPolicy::ParseIsolatedOrigins("about:blank"),
testing::IsEmpty());
// Single simple, valid origin.
EXPECT_THAT(
SiteIsolationPolicy::ParseIsolatedOrigins("http://isolated.foo.com"),
testing::ElementsAre(
url::Origin::Create(GURL("http://isolated.foo.com"))));
// Multiple comma-separated origins.
EXPECT_THAT(
SiteIsolationPolicy::ParseIsolatedOrigins(
"http://a.com,https://b.com,,https://c.com:8000"),
testing::ElementsAre(url::Origin::Create(GURL("http://a.com")),
url::Origin::Create(GURL("https://b.com")),
url::Origin::Create(GURL("https://c.com:8000"))));
// ParseIsolatedOrigins should not do any deduplication (that is the job of
// ChildProcessSecurityPolicyImpl::AddIsolatedOrigins).
EXPECT_THAT(
SiteIsolationPolicy::ParseIsolatedOrigins(
"https://b.com,https://b.com,https://b.com:1234"),
testing::ElementsAre(url::Origin::Create(GURL("https://b.com")),
url::Origin::Create(GURL("https://b.com")),
url::Origin::Create(GURL("https://b.com:1234"))));
}
} // namespace content
......@@ -420,6 +420,13 @@ const base::Feature kWebUsb{"WebUSB", base::FEATURE_ENABLED_BY_DEFAULT};
const base::Feature kImageCaptureAPI{"ImageCaptureAPI",
base::FEATURE_ENABLED_BY_DEFAULT};
// Alternative to switches::kIsolateOrigins, for turning on origin isolation.
// List of origins to isolate has to be specified via
// kIsolateOriginsFieldTrialParamName.
const base::Feature kIsolateOrigins{"IsolateOrigins",
base::FEATURE_DISABLED_BY_DEFAULT};
const char kIsolateOriginsFieldTrialParamName[] = "OriginsList";
const base::Feature kKeepAliveRendererForKeepaliveRequests{
"KeepAliveRendererForKeepaliveRequests", base::FEATURE_ENABLED_BY_DEFAULT};
......
......@@ -42,6 +42,8 @@ CONTENT_EXPORT extern const base::Feature kGamepadExtensions;
CONTENT_EXPORT extern const base::Feature kGuestViewCrossProcessFrames;
CONTENT_EXPORT extern const base::Feature kHeapCompaction;
CONTENT_EXPORT extern const base::Feature kImageCaptureAPI;
CONTENT_EXPORT extern const base::Feature kIsolateOrigins;
CONTENT_EXPORT extern const char kIsolateOriginsFieldTrialParamName[];
CONTENT_EXPORT extern const base::Feature
kKeepAliveRendererForKeepaliveRequests;
CONTENT_EXPORT extern const base::Feature kLazyInitializeMediaControls;
......
......@@ -1491,6 +1491,7 @@ test("content_unittests") {
"../common/service_manager/service_manager_connection_impl_unittest.cc",
"../common/service_worker/service_worker_types_unittest.cc",
"../common/service_worker/service_worker_utils_unittest.cc",
"../common/site_isolation_policy_unittest.cc",
"../common/throttling_url_loader_unittest.cc",
"../common/unique_name_helper_unittest.cc",
"../common/webplugininfo_unittest.cc",
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment