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