Commit a117d6ec authored by Clark DuVall's avatar Clark DuVall Committed by Commit Bot

[WebLayer] Implement basic site isolation in WebLayer

This implements site isolation for the preloaded origin list on Android,
along with handling the memory threshold policy. The next step is to
implement the dynamic detection of password sites.

Bug: 1058364
Change-Id: I12b93c07bbb237a914f1f80704dbb049e5412db7
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2236064
Commit-Queue: Clark DuVall <cduvall@chromium.org>
Reviewed-by: default avatarJohn Abd-El-Malek <jam@chromium.org>
Reviewed-by: default avatarAlex Moshchuk <alexmos@chromium.org>
Cr-Commit-Position: refs/heads/master@{#776611}
parent 23716e41
......@@ -337,6 +337,7 @@ source_set("weblayer_lib_base") {
"//components/security_state/content",
"//components/services/storage/public/mojom",
"//components/sessions",
"//components/site_isolation",
"//components/spellcheck:buildflags",
"//components/ssl_errors",
"//components/startup_metric_utils/browser",
......
......@@ -39,6 +39,7 @@ include_rules = [
"+components/security_state/content/content_utils.h",
"+components/security_state/core/security_state.h",
"+components/sessions",
"+components/site_isolation",
"+components/spellcheck/browser",
"+components/ssl_errors",
"+components/startup_metric_utils",
......
......@@ -30,6 +30,8 @@
#include "components/security_interstitials/content/ssl_cert_reporter.h"
#include "components/security_interstitials/content/ssl_error_handler.h"
#include "components/security_interstitials/content/ssl_error_navigation_throttle.h"
#include "components/site_isolation/preloaded_isolated_origins.h"
#include "components/site_isolation/site_isolation_policy.h"
#include "components/strings/grit/components_locale_settings.h"
#include "components/variations/service/variations_service.h"
#include "content/public/browser/browser_context.h"
......@@ -411,6 +413,23 @@ bool ContentBrowserClientImpl::IsHandledURL(const GURL& url) {
return false;
}
std::vector<url::Origin>
ContentBrowserClientImpl::GetOriginsRequiringDedicatedProcess() {
return site_isolation::GetBrowserSpecificBuiltInIsolatedOrigins();
}
bool ContentBrowserClientImpl::ShouldDisableSiteIsolation() {
return site_isolation::SiteIsolationPolicy::
ShouldDisableSiteIsolationDueToMemoryThreshold();
}
std::vector<std::string>
ContentBrowserClientImpl::GetAdditionalSiteIsolationModes() {
if (site_isolation::SiteIsolationPolicy::IsIsolationForPasswordSitesEnabled())
return {"Isolate Password Sites"};
return {};
}
bool ContentBrowserClientImpl::CanCreateWindow(
content::RenderFrameHost* opener,
const GURL& opener_url,
......
......@@ -65,6 +65,9 @@ class ContentBrowserClientImpl : public content::ContentBrowserClient {
content::NavigationUIData* navigation_ui_data,
int frame_tree_node_id) override;
bool IsHandledURL(const GURL& url) override;
std::vector<url::Origin> GetOriginsRequiringDedicatedProcess() override;
bool ShouldDisableSiteIsolation() override;
std::vector<std::string> GetAdditionalSiteIsolationModes() override;
bool CanCreateWindow(content::RenderFrameHost* opener,
const GURL& opener_url,
const GURL& opener_top_level_frame_url,
......
// Copyright 2020 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 "components/site_isolation/site_isolation_policy.h"
#include "base/base_switches.h"
#include "base/system/sys_info.h"
#include "base/test/scoped_feature_list.h"
#include "build/build_config.h"
#include "components/site_isolation/features.h"
#include "components/site_isolation/preloaded_isolated_origins.h"
#include "content/public/browser/child_process_security_policy.h"
#include "content/public/browser/site_isolation_policy.h"
#include "content/public/common/content_features.h"
#include "content/public/common/content_switches.h"
#include "content/public/test/browser_task_environment.h"
#include "content/public/test/test_utils.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace weblayer {
namespace {
using testing::UnorderedElementsAreArray;
// Some command-line switches override field trials - the tests need to be
// skipped in this case.
bool ShouldSkipBecauseOfConflictingCommandLineSwitches() {
if (base::CommandLine::ForCurrentProcess()->HasSwitch(
switches::kSitePerProcess))
return true;
if (base::CommandLine::ForCurrentProcess()->HasSwitch(
switches::kDisableSiteIsolation))
return true;
return false;
}
} // namespace
class SiteIsolationPolicyTest : public testing::Test {
public:
SiteIsolationPolicyTest() = default;
void SetUp() override {
// This way the test always sees the same amount of physical memory
// (kLowMemoryDeviceThresholdMB = 512MB), regardless of how much memory is
// available in the testing environment.
base::CommandLine::ForCurrentProcess()->AppendSwitch(
switches::kEnableLowEndDeviceMode);
EXPECT_EQ(512, base::SysInfo::AmountOfPhysicalMemoryMB());
}
void SetMemoryThreshold(const std::string& threshold) {
threshold_feature_.InitAndEnableFeatureWithParameters(
site_isolation::features::kSitePerProcessOnlyForHighMemoryClients,
{{site_isolation::features::
kSitePerProcessOnlyForHighMemoryClientsParamName,
threshold}});
}
private:
content::BrowserTaskEnvironment task_environment_;
base::test::ScopedFeatureList threshold_feature_;
DISALLOW_COPY_AND_ASSIGN(SiteIsolationPolicyTest);
};
TEST_F(SiteIsolationPolicyTest, NoIsolationBelowMemoryThreshold) {
if (ShouldSkipBecauseOfConflictingCommandLineSwitches())
return;
SetMemoryThreshold("768");
EXPECT_FALSE(
content::SiteIsolationPolicy::UseDedicatedProcessesForAllSites());
EXPECT_FALSE(
content::SiteIsolationPolicy::ArePreloadedIsolatedOriginsEnabled());
}
TEST_F(SiteIsolationPolicyTest, IsolationAboveMemoryThreshold) {
if (ShouldSkipBecauseOfConflictingCommandLineSwitches())
return;
SetMemoryThreshold("128");
// Android should only use the preloaded origin list, while desktop should
// isolate all sites.
#if defined(OS_ANDROID)
EXPECT_FALSE(
content::SiteIsolationPolicy::UseDedicatedProcessesForAllSites());
EXPECT_TRUE(
content::SiteIsolationPolicy::ArePreloadedIsolatedOriginsEnabled());
#else
EXPECT_TRUE(content::SiteIsolationPolicy::UseDedicatedProcessesForAllSites());
EXPECT_FALSE(
content::SiteIsolationPolicy::ArePreloadedIsolatedOriginsEnabled());
#endif
}
TEST_F(SiteIsolationPolicyTest, IsolatedOriginsContainPreloadedOrigins) {
if (ShouldSkipBecauseOfConflictingCommandLineSwitches())
return;
content::SiteIsolationPolicy::ApplyGlobalIsolatedOrigins();
std::vector<url::Origin> expected_embedder_origins =
site_isolation::GetBrowserSpecificBuiltInIsolatedOrigins();
auto* cpsp = content::ChildProcessSecurityPolicy::GetInstance();
std::vector<url::Origin> isolated_origins = cpsp->GetIsolatedOrigins();
EXPECT_THAT(expected_embedder_origins,
UnorderedElementsAreArray(isolated_origins));
}
} // namespace weblayer
......@@ -202,16 +202,20 @@ source_set("run_all_unittests") {
public_deps = [
"//base/test:test_support",
"//content/test:test_support",
"//weblayer:weblayer_lib_base",
]
}
test("weblayer_unittests") {
deps = [
":run_all_unittests",
"//weblayer:weblayer_lib_base",
"//components/site_isolation",
]
if (is_android) {
deps += [ ":weblayer_test_assets" ]
}
sources = [ "../browser/profile_disk_operations_unittests.cc" ]
sources = [
"../browser/profile_disk_operations_unittests.cc",
"../browser/site_isolation_policy_unittest.cc",
]
}
......@@ -4,10 +4,51 @@
#include "base/bind.h"
#include "base/test/launcher/unit_test_launcher.h"
#include "base/threading/thread_restrictions.h"
#include "content/public/test/content_test_suite_base.h"
#include "content/public/test/unittest_test_suite.h"
#include "weblayer/browser/content_browser_client_impl.h"
#include "weblayer/common/content_client_impl.h"
#include "weblayer/utility/content_utility_client_impl.h"
namespace weblayer {
namespace {
class WebLayerUnitTestSuiteInitializer
: public testing::EmptyTestEventListener {
public:
WebLayerUnitTestSuiteInitializer() = default;
~WebLayerUnitTestSuiteInitializer() override = default;
WebLayerUnitTestSuiteInitializer(const WebLayerUnitTestSuiteInitializer&) =
delete;
WebLayerUnitTestSuiteInitializer& operator=(
const WebLayerUnitTestSuiteInitializer&) = delete;
void OnTestStart(const testing::TestInfo& test_info) override {
content_client_ = std::make_unique<ContentClientImpl>();
content::SetContentClient(content_client_.get());
browser_content_client_ =
std::make_unique<ContentBrowserClientImpl>(nullptr);
content::SetBrowserClientForTesting(browser_content_client_.get());
utility_content_client_ = std::make_unique<ContentUtilityClientImpl>();
content::SetUtilityClientForTesting(utility_content_client_.get());
}
void OnTestEnd(const testing::TestInfo& test_info) override {
browser_content_client_ = nullptr;
utility_content_client_ = nullptr;
content_client_ = nullptr;
content::SetContentClient(nullptr);
}
private:
std::unique_ptr<ContentClientImpl> content_client_;
std::unique_ptr<ContentBrowserClientImpl> browser_content_client_;
std::unique_ptr<ContentUtilityClientImpl> utility_content_client_;
};
} // namespace
class WebLayerTestSuite : public content::ContentTestSuiteBase {
public:
......@@ -16,6 +57,14 @@ class WebLayerTestSuite : public content::ContentTestSuiteBase {
WebLayerTestSuite(const WebLayerTestSuite&) = delete;
WebLayerTestSuite& operator=(const WebLayerTestSuite&) = delete;
void Initialize() override {
testing::TestEventListeners& listeners =
testing::UnitTest::GetInstance()->listeners();
listeners.Append(new WebLayerUnitTestSuiteInitializer);
ContentTestSuiteBase::Initialize();
}
};
} // namespace weblayer
......
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