1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "content/public/browser/site_isolation_policy.h"
6
7 #include <algorithm>
8 #include <iterator>
9 #include <string>
10 #include <utility>
11
12 #include "base/bind.h"
13 #include "base/command_line.h"
14 #include "base/feature_list.h"
15 #include "base/metrics/field_trial_params.h"
16 #include "base/strings/string_split.h"
17 #include "build/build_config.h"
18 #include "content/public/browser/child_process_security_policy.h"
19 #include "content/public/browser/content_browser_client.h"
20 #include "content/public/common/content_client.h"
21 #include "content/public/common/content_features.h"
22 #include "content/public/common/content_switches.h"
23 #include "url/gurl.h"
24
25 namespace content {
26
27 namespace {
28
IsSiteIsolationDisabled()29 bool IsSiteIsolationDisabled() {
30 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
31 switches::kDisableSiteIsolation)) {
32 return true;
33 }
34
35 #if defined(OS_ANDROID)
36 // Desktop platforms no longer support disabling Site Isolation by policy.
37 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
38 switches::kDisableSiteIsolationForPolicy)) {
39 return true;
40 }
41 #endif
42
43 // Check with the embedder. In particular, chrome/ uses this to disable site
44 // isolation when below a memory threshold.
45 return GetContentClient() &&
46 GetContentClient()->browser()->ShouldDisableSiteIsolation();
47 }
48
49 } // namespace
50
51 // static
UseDedicatedProcessesForAllSites()52 bool SiteIsolationPolicy::UseDedicatedProcessesForAllSites() {
53 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
54 switches::kSitePerProcess)) {
55 return true;
56 }
57
58 if (IsSiteIsolationDisabled())
59 return false;
60
61 // The switches above needs to be checked first, because if the
62 // ContentBrowserClient consults a base::Feature, then it will activate the
63 // field trial and assigns the client either to a control or an experiment
64 // group - such assignment should be final.
65 return GetContentClient() &&
66 GetContentClient()->browser()->ShouldEnableStrictSiteIsolation();
67 }
68
69 // static
AreIsolatedOriginsEnabled()70 bool SiteIsolationPolicy::AreIsolatedOriginsEnabled() {
71 // NOTE: Because it is possible for --isolate-origins to be isolating origins
72 // at a finer-than-site granularity, we do not suppress --isolate-origins when
73 // --site-per-process is also enabled.
74 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
75 switches::kIsolateOrigins)) {
76 return true;
77 }
78
79 if (IsSiteIsolationDisabled())
80 return false;
81
82 // The feature needs to be checked last, because checking the feature
83 // activates the field trial and assigns the client either to a control or an
84 // experiment group - such assignment should be final.
85 return base::FeatureList::IsEnabled(features::kIsolateOrigins);
86 }
87
88 // static
IsStrictOriginIsolationEnabled()89 bool SiteIsolationPolicy::IsStrictOriginIsolationEnabled() {
90 // If the feature is explicitly enabled by the user (e.g., from
91 // chrome://flags), honor this regardless of checks to disable site isolation
92 // below. This means this takes precedence over memory thresholds or
93 // switches to disable site isolation.
94 if (base::FeatureList::GetInstance()->IsFeatureOverriddenFromCommandLine(
95 features::kStrictOriginIsolation.name,
96 base::FeatureList::OVERRIDE_ENABLE_FEATURE)) {
97 return true;
98 }
99
100 // TODO(wjmaclean): Figure out what should happen when this feature is
101 // combined with --isolate-origins.
102 if (IsSiteIsolationDisabled())
103 return false;
104
105 // The feature needs to be checked last, because checking the feature
106 // activates the field trial and assigns the client either to a control or an
107 // experiment group - such assignment should be final.
108 return base::FeatureList::IsEnabled(features::kStrictOriginIsolation);
109 }
110
111 // static
IsErrorPageIsolationEnabled(bool in_main_frame)112 bool SiteIsolationPolicy::IsErrorPageIsolationEnabled(bool in_main_frame) {
113 return GetContentClient()->browser()->ShouldIsolateErrorPage(in_main_frame);
114 }
115
116 // static
ShouldPdfCompositorBeEnabledForOopifs()117 bool SiteIsolationPolicy::ShouldPdfCompositorBeEnabledForOopifs() {
118 // TODO(weili): We only create pdf compositor client and use pdf compositor
119 // service when site-per-process or isolate-origins flag/feature is enabled,
120 // or top-document-isolation feature is enabled. This may not cover all cases
121 // where OOPIF is used such as isolate-extensions, but should be good for
122 // feature testing purpose. Eventually, we will remove this check and use pdf
123 // compositor service by default for printing.
124 return AreIsolatedOriginsEnabled() || UseDedicatedProcessesForAllSites();
125 }
126
127 // static
AreDynamicIsolatedOriginsEnabled()128 bool SiteIsolationPolicy::AreDynamicIsolatedOriginsEnabled() {
129 return !IsSiteIsolationDisabled();
130 }
131
132 // static
GetIsolatedOriginsFromCommandLine()133 std::string SiteIsolationPolicy::GetIsolatedOriginsFromCommandLine() {
134 std::string cmdline_arg =
135 base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
136 switches::kIsolateOrigins);
137
138 return cmdline_arg;
139 }
140
GetIsolatedOriginsFromFieldTrial()141 std::string SiteIsolationPolicy::GetIsolatedOriginsFromFieldTrial() {
142 std::string origins;
143
144 // Check if site isolation modes are turned off (e.g., due to an opt-out
145 // flag).
146 if (IsSiteIsolationDisabled())
147 return origins;
148
149 // The feature needs to be checked after the opt-out, because checking the
150 // feature activates the field trial and assigns the client either to a
151 // control or an experiment group - such assignment should be final.
152 if (base::FeatureList::IsEnabled(features::kIsolateOrigins)) {
153 origins = base::GetFieldTrialParamValueByFeature(
154 features::kIsolateOrigins,
155 features::kIsolateOriginsFieldTrialParamName);
156 }
157
158 return origins;
159 }
160
ApplyGlobalIsolatedOrigins()161 void SiteIsolationPolicy::ApplyGlobalIsolatedOrigins() {
162 ChildProcessSecurityPolicy* policy =
163 ChildProcessSecurityPolicy::GetInstance();
164
165 std::string from_cmdline = GetIsolatedOriginsFromCommandLine();
166 policy->AddIsolatedOrigins(
167 from_cmdline,
168 ChildProcessSecurityPolicy::IsolatedOriginSource::COMMAND_LINE);
169
170 std::string from_trial = GetIsolatedOriginsFromFieldTrial();
171 policy->AddIsolatedOrigins(
172 from_trial,
173 ChildProcessSecurityPolicy::IsolatedOriginSource::FIELD_TRIAL);
174
175 std::vector<url::Origin> from_embedder =
176 GetContentClient()->browser()->GetOriginsRequiringDedicatedProcess();
177 policy->AddIsolatedOrigins(
178 from_embedder,
179 ChildProcessSecurityPolicy::IsolatedOriginSource::BUILT_IN);
180 }
181
182 } // namespace content
183