blob: 47a9466685e091e7ca13a36e4967780482945037 [file] [log] [blame]
[email protected]144a8102012-01-14 01:05:311// Copyright (c) 2012 The Chromium Authors. All rights reserved.
license.botbf09a502008-08-24 00:55:552// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
initial.commit09911bf2008-07-26 23:55:294
[email protected]b6583592012-01-25 19:52:335#include "content/browser/site_instance_impl.h"
initial.commit09911bf2008-07-26 23:55:296
Lukasz Anforowicz48097c42017-12-15 00:23:387#include <string>
8
creis0b49fa12017-07-10 16:31:119#include "base/command_line.h"
Alex Moshchuk4479b97c2017-10-17 23:20:3210#include "base/debug/crash_logging.h"
Aaron Colwell6fee3f52019-05-08 21:35:0211#include "base/lazy_instance.h"
alexmos3b9ad102017-05-26 23:41:0812#include "base/macros.h"
[email protected]39365212011-02-24 01:01:0013#include "content/browser/browsing_instance.h"
[email protected]b9535422012-02-09 01:47:5914#include "content/browser/child_process_security_policy_impl.h"
[email protected]c02f1ba2014-02-03 06:53:5315#include "content/browser/frame_host/debug_urls.h"
nick9f34e2892016-01-12 21:01:0716#include "content/browser/frame_host/frame_tree_node.h"
Alex Moshchuk07e1bb42019-03-08 04:44:0817#include "content/browser/isolated_origin_util.h"
Alex Moshchuk8e5c1952019-01-15 03:39:5018#include "content/browser/isolation_context.h"
[email protected]f3b1a082011-11-18 00:34:3019#include "content/browser/renderer_host/render_process_host_impl.h"
[email protected]4c3a23582012-08-18 08:54:3420#include "content/browser/storage_partition_impl.h"
Aaron Colwell7be742612019-08-22 18:25:1221#include "content/browser/webui/url_data_manager_backend.h"
Aaron Colwellea6921f2019-01-29 16:50:3922#include "content/public/browser/browser_or_resource_context.h"
[email protected]87f3c082011-10-19 18:07:4423#include "content/public/browser/content_browser_client.h"
[email protected]f3b1a082011-11-18 00:34:3024#include "content/public/browser/render_process_host_factory.h"
Nick Carterbf6264a52018-04-06 02:39:3325#include "content/public/browser/site_isolation_policy.h"
[email protected]41fb79a52012-06-29 16:34:3326#include "content/public/browser/web_ui_controller_factory.h"
Hans Wennborg5ffd1392019-10-16 11:00:0227#include "content/public/common/content_client.h"
Nate Chapin71da03c2019-02-05 01:21:4128#include "content/public/common/content_features.h"
creis0b49fa12017-07-10 16:31:1129#include "content/public/common/content_switches.h"
[email protected]a1d29162011-10-14 17:14:0330#include "content/public/common/url_constants.h"
clamy7fced7b2017-11-16 19:52:4331#include "content/public/common/url_utils.h"
[email protected]be28b5f42012-07-20 11:31:2532#include "net/base/registry_controlled_domains/registry_controlled_domain.h"
initial.commit09911bf2008-07-26 23:55:2933
[email protected]46488322012-10-30 03:22:2034namespace content {
[email protected]b6583592012-01-25 19:52:3335
Aaron Colwellf45e3a852019-06-06 00:48:2736namespace {
37
38// Returns true if CreateForURL() and related functions should be allowed to
39// return a default SiteInstance.
40bool ShouldAllowDefaultSiteInstance() {
Aaron Colwellc2ab84e2019-07-24 01:31:0041 return base::FeatureList::IsEnabled(
42 features::kProcessSharingWithDefaultSiteInstances);
Aaron Colwellf45e3a852019-06-06 00:48:2743}
44
45} // namespace
46
avib7348942015-12-25 20:57:1047int32_t SiteInstanceImpl::next_site_instance_id_ = 1;
[email protected]992db4c2011-05-12 15:37:1548
Aaron Colwell6fee3f52019-05-08 21:35:0249// static
50const GURL& SiteInstanceImpl::GetDefaultSiteURL() {
51 struct DefaultSiteURL {
52 const GURL url = GURL("http://unisolated.invalid");
53 };
54 static base::LazyInstance<DefaultSiteURL>::Leaky default_site_url =
55 LAZY_INSTANCE_INITIALIZER;
56
57 return default_site_url.Get().url;
58}
59
[email protected]b6583592012-01-25 19:52:3360SiteInstanceImpl::SiteInstanceImpl(BrowsingInstance* browsing_instance)
[email protected]992db4c2011-05-12 15:37:1561 : id_(next_site_instance_id_++),
creiscce56cd2014-09-29 22:45:2262 active_frame_count_(0),
[email protected]992db4c2011-05-12 15:37:1563 browsing_instance_(browsing_instance),
nickd5bbd0b2016-03-31 19:52:4464 process_(nullptr),
Lukasz Anforowicz3caa8372018-06-05 17:22:0765 can_associate_with_spare_process_(true),
nickd5bbd0b2016-03-31 19:52:4466 has_site_(false),
Tsuyoshi Horoeb576e62017-06-28 06:00:4167 process_reuse_policy_(ProcessReusePolicy::DEFAULT),
68 is_for_service_worker_(false) {
[email protected]4566f132009-03-12 01:55:1369 DCHECK(browsing_instance);
[email protected]4566f132009-03-12 01:55:1370}
71
[email protected]b6583592012-01-25 19:52:3372SiteInstanceImpl::~SiteInstanceImpl() {
[email protected]46488322012-10-30 03:22:2073 GetContentClient()->browser()->SiteInstanceDeleting(this);
[email protected]056ad2a2011-07-12 02:13:5574
Charlie Reiscf6aa512019-04-16 17:27:2975 if (process_) {
[email protected]40bfaf32013-11-19 01:35:4376 process_->RemoveObserver(this);
77
Charlie Reiscf6aa512019-04-16 17:27:2978 // Ensure the RenderProcessHost gets deleted if this SiteInstance created a
79 // process which was never used by any listeners.
80 process_->Cleanup();
81 }
82
initial.commit09911bf2008-07-26 23:55:2983 // Now that no one is referencing us, we can safely remove ourselves from
84 // the BrowsingInstance. Any future visits to a page from this site
85 // (within the same BrowsingInstance) can safely create a new SiteInstance.
86 if (has_site_)
dchengbccd6b82016-03-30 16:24:1987 browsing_instance_->UnregisterSiteInstance(this);
88}
89
Nasko Oskovdeb6c7ea2017-11-30 18:18:1190// static
dchengbccd6b82016-03-30 16:24:1991scoped_refptr<SiteInstanceImpl> SiteInstanceImpl::Create(
92 BrowserContext* browser_context) {
Lukasz Anforowicz4726a172018-10-15 21:25:1093 DCHECK(browser_context);
kylecharda69d882017-10-04 05:49:5294 return base::WrapRefCounted(
dchengbccd6b82016-03-30 16:24:1995 new SiteInstanceImpl(new BrowsingInstance(browser_context)));
96}
97
Nasko Oskovdeb6c7ea2017-11-30 18:18:1198// static
dchengbccd6b82016-03-30 16:24:1999scoped_refptr<SiteInstanceImpl> SiteInstanceImpl::CreateForURL(
100 BrowserContext* browser_context,
101 const GURL& url) {
Lukasz Anforowicz4726a172018-10-15 21:25:10102 DCHECK(browser_context);
dchengbccd6b82016-03-30 16:24:19103 // This will create a new SiteInstance and BrowsingInstance.
104 scoped_refptr<BrowsingInstance> instance(
105 new BrowsingInstance(browser_context));
Aaron Colwellf45e3a852019-06-06 00:48:27106 return instance->GetSiteInstanceForURL(url, ShouldAllowDefaultSiteInstance());
initial.commit09911bf2008-07-26 23:55:29107}
108
Nasko Oskovdeb6c7ea2017-11-30 18:18:11109// static
Aaron Colwellecc72fb2019-04-30 17:41:11110scoped_refptr<SiteInstanceImpl> SiteInstanceImpl::CreateForServiceWorker(
111 BrowserContext* browser_context,
Aaron Colwell369968ee2019-05-14 00:32:38112 const GURL& url,
113 bool can_reuse_process) {
Aaron Colwellecc72fb2019-04-30 17:41:11114 // This will create a new SiteInstance and BrowsingInstance.
115 scoped_refptr<BrowsingInstance> instance(
116 new BrowsingInstance(browser_context));
117
118 // We do NOT want to allow the default site instance here because workers
119 // need to be kept separate from other sites.
120 scoped_refptr<SiteInstanceImpl> site_instance =
121 instance->GetSiteInstanceForURL(url, /* allow_default_instance */ false);
122 site_instance->is_for_service_worker_ = true;
Aaron Colwell369968ee2019-05-14 00:32:38123
124 // Attempt to reuse a renderer process if possible. Note that in the
125 // <webview> case, process reuse isn't currently supported and a new
126 // process will always be created (https://crbug.com/752667).
127 DCHECK(site_instance->process_reuse_policy() ==
128 SiteInstanceImpl::ProcessReusePolicy::DEFAULT ||
129 site_instance->process_reuse_policy() ==
130 SiteInstanceImpl::ProcessReusePolicy::PROCESS_PER_SITE);
131 if (can_reuse_process) {
132 site_instance->set_process_reuse_policy(
133 SiteInstanceImpl::ProcessReusePolicy::REUSE_PENDING_OR_COMMITTED_SITE);
134 }
135 return site_instance;
136}
137
138// static
139scoped_refptr<SiteInstanceImpl>
140SiteInstanceImpl::CreateReusableInstanceForTesting(
141 BrowserContext* browser_context,
142 const GURL& url) {
143 DCHECK(browser_context);
144 // This will create a new SiteInstance and BrowsingInstance.
145 scoped_refptr<BrowsingInstance> instance(
146 new BrowsingInstance(browser_context));
147 auto site_instance =
148 instance->GetSiteInstanceForURL(url,
149 /* allow_default_instance */ false);
150 site_instance->set_process_reuse_policy(
151 SiteInstanceImpl::ProcessReusePolicy::REUSE_PENDING_OR_COMMITTED_SITE);
Aaron Colwellecc72fb2019-04-30 17:41:11152 return site_instance;
153}
154
155// static
Nasko Oskovdeb6c7ea2017-11-30 18:18:11156bool SiteInstanceImpl::ShouldAssignSiteForURL(const GURL& url) {
157 // about:blank should not "use up" a new SiteInstance. The SiteInstance can
158 // still be used for a normal web site.
Mohamed Abdelhalim9e868ca42019-04-25 16:53:29159 if (url.IsAboutBlank())
Nasko Oskovdeb6c7ea2017-11-30 18:18:11160 return false;
161
162 // The embedder will then have the opportunity to determine if the URL
163 // should "use up" the SiteInstance.
164 return GetContentClient()->browser()->ShouldAssignSiteForURL(url);
165}
166
Nicolas Pena7c7847f2018-05-30 01:36:05167// static
168bool SiteInstanceImpl::IsOriginLockASite(const GURL& lock_url) {
169 return lock_url.has_scheme() && lock_url.has_host();
170}
171
avib7348942015-12-25 20:57:10172int32_t SiteInstanceImpl::GetId() {
[email protected]b6583592012-01-25 19:52:33173 return id_;
174}
175
Chris Hamilton2ed5d5572019-05-23 22:47:58176int32_t SiteInstanceImpl::GetBrowsingInstanceId() {
177 // This is being vended out as an opaque ID, and it is always defined for
178 // a BrowsingInstance affiliated IsolationContext, so it's safe to call
179 // "GetUnsafeValue" and expose the inner value directly.
180 return browsing_instance_->isolation_context()
181 .browsing_instance_id()
182 .GetUnsafeValue();
183}
184
Alex Moshchuk8e5c1952019-01-15 03:39:50185const IsolationContext& SiteInstanceImpl::GetIsolationContext() {
186 return browsing_instance_->isolation_context();
187}
188
Nate Chapin71da03c2019-02-05 01:21:41189RenderProcessHost* SiteInstanceImpl::GetDefaultProcessIfUsable() {
190 if (!base::FeatureList::IsEnabled(
191 features::kProcessSharingWithStrictSiteInstances)) {
192 return nullptr;
193 }
194 if (RequiresDedicatedProcess())
195 return nullptr;
196 return browsing_instance_->default_process();
197}
198
Aaron Colwell0447cd02019-06-26 22:04:20199bool SiteInstanceImpl::IsDefaultSiteInstance() const {
Aaron Colwellddeccbdb2019-03-08 01:11:03200 return browsing_instance_->IsDefaultSiteInstance(this);
201}
202
Aaron Colwell0447cd02019-06-26 22:04:20203bool SiteInstanceImpl::IsSiteInDefaultSiteInstance(const GURL& site_url) const {
204 return browsing_instance_->IsSiteInDefaultSiteInstance(site_url);
205}
206
Nate Chapin71da03c2019-02-05 01:21:41207void SiteInstanceImpl::MaybeSetBrowsingInstanceDefaultProcess() {
208 if (!base::FeatureList::IsEnabled(
209 features::kProcessSharingWithStrictSiteInstances)) {
210 return;
211 }
212 // Wait until this SiteInstance both has a site and a process
213 // assigned, so that we can be sure that RequiresDedicatedProcess()
214 // is accurate and we actually have a process to set.
215 if (!process_ || !has_site_ || RequiresDedicatedProcess())
216 return;
217 if (browsing_instance_->default_process()) {
218 DCHECK_EQ(process_, browsing_instance_->default_process());
219 return;
220 }
221 browsing_instance_->SetDefaultProcess(process_);
222}
223
Alex Moshchuk8e5c1952019-01-15 03:39:50224// static
225BrowsingInstanceId SiteInstanceImpl::NextBrowsingInstanceId() {
226 return BrowsingInstance::NextBrowsingInstanceId();
227}
228
229bool SiteInstanceImpl::HasProcess() {
Ivan Kotenkov2c0d2bb32017-11-01 15:41:28230 if (process_ != nullptr)
[email protected]41fb79a52012-06-29 16:34:33231 return true;
232
233 // If we would use process-per-site for this site, also check if there is an
234 // existing process that we would use if GetProcess() were called.
Alex Moshchukf7488792019-03-11 22:37:57235 BrowserContext* browser_context = browsing_instance_->GetBrowserContext();
[email protected]41fb79a52012-06-29 16:34:33236 if (has_site_ &&
[email protected]1ae93fb12013-06-14 03:38:56237 RenderProcessHost::ShouldUseProcessPerSite(browser_context, site_) &&
Alex Moshchuk8e5c1952019-01-15 03:39:50238 RenderProcessHostImpl::GetSoleProcessHostForSite(
239 browser_context, GetIsolationContext(), site_, lock_url_)) {
[email protected]41fb79a52012-06-29 16:34:33240 return true;
241 }
242
243 return false;
[email protected]5ab79b02010-04-26 16:47:11244}
245
[email protected]41fb79a52012-06-29 16:34:33246RenderProcessHost* SiteInstanceImpl::GetProcess() {
[email protected]08c8ec7e2010-07-11 17:14:48247 // TODO(erikkay) It would be nice to ensure that the renderer type had been
248 // properly set before we get here. The default tab creation case winds up
249 // with no site set at this point, so it will default to TYPE_NORMAL. This
250 // may not be correct, so we'll wind up potentially creating a process that
251 // we then throw away, or worse sharing a process with the wrong process type.
252 // See crbug.com/43448.
253
initial.commit09911bf2008-07-26 23:55:29254 // Create a new process if ours went away or was reused.
[email protected]4566f132009-03-12 01:55:13255 if (!process_) {
Alex Moshchukf7488792019-03-11 22:37:57256 BrowserContext* browser_context = browsing_instance_->GetBrowserContext();
[email protected]41fb79a52012-06-29 16:34:33257
clamy63960c32017-05-10 22:57:07258 // Check if the ProcessReusePolicy should be updated.
259 bool should_use_process_per_site =
creisa9f04ba2017-05-19 22:27:42260 has_site_ &&
261 RenderProcessHost::ShouldUseProcessPerSite(browser_context, site_);
clamy63960c32017-05-10 22:57:07262 if (should_use_process_per_site) {
263 process_reuse_policy_ = ProcessReusePolicy::PROCESS_PER_SITE;
264 } else if (process_reuse_policy_ == ProcessReusePolicy::PROCESS_PER_SITE) {
265 process_reuse_policy_ = ProcessReusePolicy::DEFAULT;
[email protected]41fb79a52012-06-29 16:34:33266 }
267
Alex Moshchuk5f926a52018-08-29 20:57:30268 process_ = RenderProcessHostImpl::GetProcessHostForSiteInstance(this);
avi6d686db2017-01-06 02:28:57269
[email protected]41fb79a52012-06-29 16:34:33270 CHECK(process_);
[email protected]40bfaf32013-11-19 01:35:43271 process_->AddObserver(this);
[email protected]41fb79a52012-06-29 16:34:33272
Nate Chapin71da03c2019-02-05 01:21:41273 MaybeSetBrowsingInstanceDefaultProcess();
274
[email protected]41fb79a52012-06-29 16:34:33275 // If we are using process-per-site, we need to register this process
276 // for the current site so that we can find it again. (If no site is set
277 // at this time, we will register it in SetSite().)
clamy63960c32017-05-10 22:57:07278 if (process_reuse_policy_ == ProcessReusePolicy::PROCESS_PER_SITE &&
279 has_site_) {
Alex Moshchuk5f926a52018-08-29 20:57:30280 RenderProcessHostImpl::RegisterSoleProcessHostForSite(browser_context,
281 process_, this);
[email protected]41fb79a52012-06-29 16:34:33282 }
initial.commit09911bf2008-07-26 23:55:29283
naskob8744d22014-08-28 17:07:43284 TRACE_EVENT2("navigation", "SiteInstanceImpl::GetProcess",
285 "site id", id_, "process id", process_->GetID());
[email protected]46488322012-10-30 03:22:20286 GetContentClient()->browser()->SiteInstanceGotProcess(this);
[email protected]6f371442011-11-09 06:45:46287
[email protected]313b80bd2011-11-23 03:49:10288 if (has_site_)
alexmos13fe1962017-06-28 04:25:12289 LockToOriginIfNeeded();
initial.commit09911bf2008-07-26 23:55:29290 }
[email protected]4566f132009-03-12 01:55:13291 DCHECK(process_);
initial.commit09911bf2008-07-26 23:55:29292
[email protected]4566f132009-03-12 01:55:13293 return process_;
initial.commit09911bf2008-07-26 23:55:29294}
295
Lukasz Anforowicz3caa8372018-06-05 17:22:07296bool SiteInstanceImpl::CanAssociateWithSpareProcess() {
297 return can_associate_with_spare_process_;
298}
299
300void SiteInstanceImpl::PreventAssociationWithSpareProcess() {
301 can_associate_with_spare_process_ = false;
302}
303
[email protected]b6583592012-01-25 19:52:33304void SiteInstanceImpl::SetSite(const GURL& url) {
Charlie Reisc2099752019-04-06 01:21:12305 // TODO(creis): Consider calling ShouldAssignSiteForURL internally, rather
306 // than before multiple call sites. See https://crbug.com/949220.
naskob8744d22014-08-28 17:07:43307 TRACE_EVENT2("navigation", "SiteInstanceImpl::SetSite",
308 "site id", id_, "url", url.possibly_invalid_spec());
initial.commit09911bf2008-07-26 23:55:29309 // A SiteInstance's site should not change.
310 // TODO(creis): When following links or script navigations, we can currently
311 // render pages from other sites in this SiteInstance. This will eventually
312 // be fixed, but until then, we should still not set the site of a
313 // SiteInstance more than once.
314 DCHECK(!has_site_);
315
316 // Remember that this SiteInstance has been used to load a URL, even if the
317 // URL is invalid.
318 has_site_ = true;
Alex Moshchukf7488792019-03-11 22:37:57319 BrowserContext* browser_context = browsing_instance_->GetBrowserContext();
Alex Moshchuk25c64bb2017-12-02 02:50:11320 original_url_ = url;
Aaron Colwellddeccbdb2019-03-08 01:11:03321 browsing_instance_->GetSiteAndLockForURL(
322 url, /* allow_default_instance */ false, &site_, &lock_url_);
initial.commit09911bf2008-07-26 23:55:29323
324 // Now that we have a site, register it with the BrowsingInstance. This
325 // ensures that we won't create another SiteInstance for this site within
326 // the same BrowsingInstance, because all same-site pages within a
327 // BrowsingInstance can script each other.
328 browsing_instance_->RegisterSiteInstance(this);
[email protected]313b80bd2011-11-23 03:49:10329
clamy63960c32017-05-10 22:57:07330 // Update the process reuse policy based on the site.
331 bool should_use_process_per_site =
332 RenderProcessHost::ShouldUseProcessPerSite(browser_context, site_);
333 if (should_use_process_per_site) {
334 process_reuse_policy_ = ProcessReusePolicy::PROCESS_PER_SITE;
335 }
336
[email protected]41fb79a52012-06-29 16:34:33337 if (process_) {
alexmos13fe1962017-06-28 04:25:12338 LockToOriginIfNeeded();
[email protected]41fb79a52012-06-29 16:34:33339
340 // Ensure the process is registered for this site if necessary.
clamy63960c32017-05-10 22:57:07341 if (should_use_process_per_site) {
Alex Moshchuk5f926a52018-08-29 20:57:30342 RenderProcessHostImpl::RegisterSoleProcessHostForSite(browser_context,
343 process_, this);
[email protected]41fb79a52012-06-29 16:34:33344 }
Nate Chapin71da03c2019-02-05 01:21:41345 MaybeSetBrowsingInstanceDefaultProcess();
[email protected]41fb79a52012-06-29 16:34:33346 }
initial.commit09911bf2008-07-26 23:55:29347}
348
Aaron Colwelle953e562019-07-24 16:47:36349void SiteInstanceImpl::ConvertToDefaultOrSetSite(const GURL& url) {
350 DCHECK(!has_site_);
351
352 if (ShouldAllowDefaultSiteInstance() &&
353 browsing_instance_->TrySettingDefaultSiteInstance(this, url)) {
354 return;
355 }
356
357 SetSite(url);
358}
359
Lucas Furukawa Gadanid726e1e2019-05-08 16:20:03360const GURL& SiteInstanceImpl::GetSiteURL() {
[email protected]b6583592012-01-25 19:52:33361 return site_;
362}
363
364bool SiteInstanceImpl::HasSite() const {
365 return has_site_;
366}
367
368bool SiteInstanceImpl::HasRelatedSiteInstance(const GURL& url) {
initial.commit09911bf2008-07-26 23:55:29369 return browsing_instance_->HasSiteInstance(url);
370}
371
dchengbccd6b82016-03-30 16:24:19372scoped_refptr<SiteInstance> SiteInstanceImpl::GetRelatedSiteInstance(
373 const GURL& url) {
Aaron Colwellddeccbdb2019-03-08 01:11:03374 return browsing_instance_->GetSiteInstanceForURL(
375 url, /* allow_default_instance */ true);
initial.commit09911bf2008-07-26 23:55:29376}
377
[email protected]14392a52012-05-02 20:28:44378bool SiteInstanceImpl::IsRelatedSiteInstance(const SiteInstance* instance) {
[email protected]fc72bb12013-06-02 21:13:46379 return browsing_instance_.get() == static_cast<const SiteInstanceImpl*>(
380 instance)->browsing_instance_.get();
[email protected]14392a52012-05-02 20:28:44381}
382
[email protected]d5072a82014-05-15 05:50:18383size_t SiteInstanceImpl::GetRelatedActiveContentsCount() {
384 return browsing_instance_->active_contents_count();
385}
386
[email protected]f88628d02012-11-11 17:58:59387bool SiteInstanceImpl::HasWrongProcessForURL(const GURL& url) {
Clark DuVall4e1f0a72019-08-07 22:41:42388 DCHECK_CURRENTLY_ON(BrowserThread::UI);
[email protected]144a8102012-01-14 01:05:31389 // If the URL to navigate to can be associated with any site instance,
390 // we want to keep it in the same process.
[email protected]c02f1ba2014-02-03 06:53:53391 if (IsRendererDebugURL(url))
[email protected]144a8102012-01-14 01:05:31392 return false;
393
Nasko Oskov978c16b2018-08-03 22:17:06394 // Any process can host an about:blank URL, except the one used for error
395 // pages, which should not commit successful navigations. This check avoids a
396 // process transfer for browser-initiated navigations to about:blank in a
397 // dedicated process; without it, IsSuitableHost would consider this process
398 // unsuitable for about:blank when it compares origin locks.
399 // Renderer-initiated navigations will handle about:blank navigations
400 // elsewhere and leave them in the source SiteInstance, along with
401 // about:srcdoc and data:.
402 if (url.IsAboutBlank() && site_ != GURL(kUnreachableWebDataURL))
alexmos13fe1962017-06-28 04:25:12403 return false;
404
[email protected]88aae972011-12-16 01:14:18405 // If the site URL is an extension (e.g., for hosted apps or WebUI) but the
[email protected]d292d8a2011-05-25 03:47:11406 // process is not (or vice versa), make sure we notice and fix it.
Aaron Colwellddeccbdb2019-03-08 01:11:03407 GURL site_url;
408 GURL origin_lock;
409
410 // Note: This call must return information that is identical to what
411 // would be reported in the SiteInstance returned by
412 // GetRelatedSiteInstance(url).
413 browsing_instance_->GetSiteAndLockForURL(
414 url, /* allow_default_instance */ true, &site_url, &origin_lock);
Charlie Reisc2099752019-04-06 01:21:12415
Aaron Colwell7292aec2019-07-25 17:23:43416 // If this is a default SiteInstance and the BrowsingInstance gives us a
417 // non-default site URL even when we explicitly allow the default SiteInstance
418 // to be considered, then |url| does not belong in the same process as this
419 // SiteInstance. This can happen when the
420 // kProcessSharingWithDefaultSiteInstances feature is not enabled and the
421 // site URL is explicitly set on a SiteInstance for a URL that would normally
422 // be directed to the default SiteInstance (e.g. a site not requiring a
423 // dedicated process). This situation typically happens when the top-level
424 // frame is a site that should be in the default SiteInstance and the
425 // SiteInstance associated with that frame is initially a SiteInstance with
426 // no site URL set.
427 if (IsDefaultSiteInstance() && site_url != GetSiteURL())
428 return true;
429
Charlie Reisc2099752019-04-06 01:21:12430 // Note that HasProcess() may return true if process_ is null, in
431 // process-per-site cases where there's an existing process available.
432 // We want to use such a process in the IsSuitableHost check, so we
433 // may end up assigning process_ in the GetProcess() call below.
434 if (!HasProcess()) {
435 // If there is no process or site, then this is a new SiteInstance that can
436 // be used for anything.
437 if (!HasSite())
438 return false;
439
440 // If there is no process but there is a site, then the process must have
441 // been discarded after we navigated away. If the site URLs match, then it
442 // is safe to use this SiteInstance.
443 if (GetSiteURL() == site_url)
444 return false;
445
446 // If the site URLs do not match, but neither this SiteInstance nor the
447 // destination site_url require dedicated processes, then it is safe to use
448 // this SiteInstance.
449 if (!RequiresDedicatedProcess() &&
Aaron Colwell5080de62019-05-06 23:02:03450 !DoesSiteURLRequireDedicatedProcess(GetIsolationContext(), site_url)) {
Charlie Reisc2099752019-04-06 01:21:12451 return false;
452 }
453
454 // Otherwise, there's no process, the site URLs don't match, and at least
455 // one of them requires a dedicated process, so it is not safe to use this
456 // SiteInstance.
457 return true;
458 }
459
[email protected]88aae972011-12-16 01:14:18460 return !RenderProcessHostImpl::IsSuitableHost(
Alex Moshchukf7488792019-03-11 22:37:57461 GetProcess(), browsing_instance_->GetBrowserContext(),
Alex Moshchuk8e5c1952019-01-15 03:39:50462 GetIsolationContext(), site_url, origin_lock);
[email protected]d292d8a2011-05-25 03:47:11463}
464
nickd30fd962015-07-27 21:51:08465bool SiteInstanceImpl::RequiresDedicatedProcess() {
Clark DuVall4e1f0a72019-08-07 22:41:42466 DCHECK_CURRENTLY_ON(BrowserThread::UI);
nickd30fd962015-07-27 21:51:08467 if (!has_site_)
468 return false;
nickd5bbd0b2016-03-31 19:52:44469
Aaron Colwell5080de62019-05-06 23:02:03470 return DoesSiteURLRequireDedicatedProcess(GetIsolationContext(), site_);
nickd30fd962015-07-27 21:51:08471}
472
nick9f34e2892016-01-12 21:01:07473void SiteInstanceImpl::IncrementActiveFrameCount() {
474 active_frame_count_++;
475}
476
477void SiteInstanceImpl::DecrementActiveFrameCount() {
ericwilligers254597b2016-10-17 10:32:31478 if (--active_frame_count_ == 0) {
479 for (auto& observer : observers_)
480 observer.ActiveFrameCountIsZero(this);
481 }
nick9f34e2892016-01-12 21:01:07482}
483
[email protected]d5072a82014-05-15 05:50:18484void SiteInstanceImpl::IncrementRelatedActiveContentsCount() {
485 browsing_instance_->increment_active_contents_count();
486}
487
488void SiteInstanceImpl::DecrementRelatedActiveContentsCount() {
489 browsing_instance_->decrement_active_contents_count();
490}
491
nick9f34e2892016-01-12 21:01:07492void SiteInstanceImpl::AddObserver(Observer* observer) {
493 observers_.AddObserver(observer);
494}
495
496void SiteInstanceImpl::RemoveObserver(Observer* observer) {
497 observers_.RemoveObserver(observer);
498}
499
Lucas Furukawa Gadanid726e1e2019-05-08 16:20:03500BrowserContext* SiteInstanceImpl::GetBrowserContext() {
Alex Moshchukf7488792019-03-11 22:37:57501 return browsing_instance_->GetBrowserContext();
[email protected]72daaa92012-01-18 13:39:02502}
503
nickcc0d9142015-10-14 16:27:10504// static
dchengbccd6b82016-03-30 16:24:19505scoped_refptr<SiteInstance> SiteInstance::Create(
506 BrowserContext* browser_context) {
Lukasz Anforowicz4726a172018-10-15 21:25:10507 DCHECK(browser_context);
dchengbccd6b82016-03-30 16:24:19508 return SiteInstanceImpl::Create(browser_context);
initial.commit09911bf2008-07-26 23:55:29509}
510
nickcc0d9142015-10-14 16:27:10511// static
dchengbccd6b82016-03-30 16:24:19512scoped_refptr<SiteInstance> SiteInstance::CreateForURL(
513 BrowserContext* browser_context,
514 const GURL& url) {
Lukasz Anforowicz4726a172018-10-15 21:25:10515 DCHECK(browser_context);
dchengbccd6b82016-03-30 16:24:19516 return SiteInstanceImpl::CreateForURL(browser_context, url);
[email protected]d8a96622009-05-07 19:21:16517}
518
nickcc0d9142015-10-14 16:27:10519// static
Nasko Oskovdeb6c7ea2017-11-30 18:18:11520bool SiteInstance::ShouldAssignSiteForURL(const GURL& url) {
521 return SiteInstanceImpl::ShouldAssignSiteForURL(url);
522}
523
Alex Moshchuk78cf66bda2018-11-30 01:49:30524bool SiteInstanceImpl::IsSameSiteWithURL(const GURL& url) {
Aaron Colwell6fee3f52019-05-08 21:35:02525 if (IsDefaultSiteInstance()) {
Aaron Colwelle953e562019-07-24 16:47:36526 // about:blank URLs should always be considered same site just like they are
527 // in IsSameWebSite().
528 if (url.IsAboutBlank())
529 return true;
530
Aaron Colwell6fee3f52019-05-08 21:35:02531 // Consider |url| the same site if it could be handled by the
532 // default SiteInstance and we don't already have a SiteInstance for
533 // this URL.
534 // TODO(acolwell): Remove HasSiteInstance() call once we have a way to
535 // prevent SiteInstances with no site URL from being used for URLs
536 // that should be routed to the default SiteInstance.
537 DCHECK_EQ(site_, GetDefaultSiteURL());
538 return site_ == GetSiteForURLInternal(GetIsolationContext(), url,
539 true /* should_use_effective_urls */,
540 true /* allow_default_site_url */) &&
541 !browsing_instance_->HasSiteInstance(url);
542 }
543
Alex Moshchuk78cf66bda2018-11-30 01:49:30544 return SiteInstanceImpl::IsSameWebSite(
Lukasz Anforowicz1a0a89a2019-03-29 22:31:02545 GetIsolationContext(), site_, url,
546 true /* should_compare_effective_urls */);
Alex Moshchuk25c64bb2017-12-02 02:50:11547}
548
Aaron Colwell6fee3f52019-05-08 21:35:02549bool SiteInstanceImpl::IsOriginalUrlSameSite(
550 const GURL& dest_url,
551 bool should_compare_effective_urls) {
552 if (IsDefaultSiteInstance())
553 return IsSameSiteWithURL(dest_url);
554
555 return IsSameWebSite(GetIsolationContext(), original_url_, dest_url,
556 should_compare_effective_urls);
557}
558
Alex Moshchuk78cf66bda2018-11-30 01:49:30559// static
Lukasz Anforowicz1a0a89a2019-03-29 22:31:02560bool SiteInstanceImpl::IsSameWebSite(const IsolationContext& isolation_context,
Alex Moshchuk25c64bb2017-12-02 02:50:11561 const GURL& real_src_url,
562 const GURL& real_dest_url,
563 bool should_compare_effective_urls) {
Lukasz Anforowicz1a0a89a2019-03-29 22:31:02564 DCHECK_CURRENTLY_ON(BrowserThread::UI);
565 BrowserContext* browser_context =
566 isolation_context.browser_or_resource_context().ToBrowserContext();
Lukasz Anforowicz4726a172018-10-15 21:25:10567 DCHECK(browser_context);
Aaron Colwell6fee3f52019-05-08 21:35:02568 DCHECK_NE(real_src_url, GetDefaultSiteURL());
Lukasz Anforowicz4726a172018-10-15 21:25:10569
Alex Moshchuk25c64bb2017-12-02 02:50:11570 GURL src_url =
571 should_compare_effective_urls
572 ? SiteInstanceImpl::GetEffectiveURL(browser_context, real_src_url)
573 : real_src_url;
574 GURL dest_url =
575 should_compare_effective_urls
576 ? SiteInstanceImpl::GetEffectiveURL(browser_context, real_dest_url)
577 : real_dest_url;
[email protected]399583b2012-12-11 09:33:42578
579 // We infer web site boundaries based on the registered domain name of the
580 // top-level page and the scheme. We do not pay attention to the port if
581 // one is present, because pages served from different ports can still
582 // access each other if they change their document.domain variable.
583
584 // Some special URLs will match the site instance of any other URL. This is
585 // done before checking both of them for validity, since we want these URLs
586 // to have the same site instance as even an invalid one.
[email protected]855d7d572014-08-02 11:18:17587 if (IsRendererDebugURL(src_url) || IsRendererDebugURL(dest_url))
[email protected]399583b2012-12-11 09:33:42588 return true;
589
590 // If either URL is invalid, they aren't part of the same site.
[email protected]855d7d572014-08-02 11:18:17591 if (!src_url.is_valid() || !dest_url.is_valid())
[email protected]399583b2012-12-11 09:33:42592 return false;
593
[email protected]855d7d572014-08-02 11:18:17594 // If the destination url is just a blank page, we treat them as part of the
595 // same site.
Mohamed Abdelhalim9e868ca42019-04-25 16:53:29596 if (dest_url.IsAboutBlank())
[email protected]855d7d572014-08-02 11:18:17597 return true;
598
Alex Moshchuka308c9b2018-02-08 20:58:14599 // If the source and destination URLs are equal excluding the hash, they have
600 // the same site. This matters for file URLs, where SameDomainOrHost() would
601 // otherwise return false below.
602 if (src_url.EqualsIgnoringRef(dest_url))
603 return true;
604
Daniel Cheng88186bd52017-10-20 08:14:46605 url::Origin src_origin = url::Origin::Create(src_url);
606 url::Origin dest_origin = url::Origin::Create(dest_url);
alexmos3b9ad102017-05-26 23:41:08607
[email protected]399583b2012-12-11 09:33:42608 // If the schemes differ, they aren't part of the same site.
alexmoscbf995782017-06-01 03:13:13609 if (src_origin.scheme() != dest_origin.scheme())
[email protected]399583b2012-12-11 09:33:42610 return false;
611
W. James MacLeanf79c97e2019-05-02 20:35:46612 if (SiteIsolationPolicy::IsStrictOriginIsolationEnabled())
613 return src_origin == dest_origin;
614
alexmos4bc26322017-07-01 00:57:14615 if (!net::registry_controlled_domains::SameDomainOrHost(
616 src_origin, dest_origin,
617 net::registry_controlled_domains::INCLUDE_PRIVATE_REGISTRIES)) {
618 return false;
619 }
620
621 // If the sites are the same, check isolated origins. If either URL matches
Alex Moshchuk4e19b362018-09-10 21:14:36622 // an isolated origin, compare origins rather than sites. As an optimization
623 // to avoid unneeded isolated origin lookups, shortcut this check if the two
624 // origins are the same.
625 if (src_origin == dest_origin)
626 return true;
alexmos4bc26322017-07-01 00:57:14627 auto* policy = ChildProcessSecurityPolicyImpl::GetInstance();
628 url::Origin src_isolated_origin;
629 url::Origin dest_isolated_origin;
Alex Moshchuk8e5c1952019-01-15 03:39:50630 bool src_origin_is_isolated = policy->GetMatchingIsolatedOrigin(
631 isolation_context, src_origin, &src_isolated_origin);
632 bool dest_origin_is_isolated = policy->GetMatchingIsolatedOrigin(
633 isolation_context, dest_origin, &dest_isolated_origin);
alexmos4bc26322017-07-01 00:57:14634 if (src_origin_is_isolated || dest_origin_is_isolated) {
635 // Compare most specific matching origins to ensure that a subdomain of an
636 // isolated origin (e.g., https://subdomain.isolated.foo.com) also matches
637 // the isolated origin's site URL (e.g., https://isolated.foo.com).
638 return src_isolated_origin == dest_isolated_origin;
639 }
640
641 return true;
[email protected]399583b2012-12-11 09:33:42642}
643
Aaron Colwellf45e3a852019-06-06 00:48:27644bool SiteInstanceImpl::DoesSiteForURLMatch(const GURL& url) {
645 // Note: The |allow_default_site_url| value used here MUST match the value
646 // used in CreateForURL().
647 return site_ == GetSiteForURLInternal(GetIsolationContext(), url,
648 true /* should_use_effective_urls */,
649 ShouldAllowDefaultSiteInstance());
650}
651
nickcc0d9142015-10-14 16:27:10652// static
[email protected]399583b2012-12-11 09:33:42653GURL SiteInstance::GetSiteForURL(BrowserContext* browser_context,
Alex Moshchuk5f926a52018-08-29 20:57:30654 const GURL& url) {
Aaron Colwellea6921f2019-01-29 16:50:39655 DCHECK_CURRENTLY_ON(BrowserThread::UI);
656 DCHECK(browser_context);
657
Aaron Colwell3acea722019-04-24 21:54:43658 // By default, GetSiteForURL will resolve |url| to an effective URL
659 // before computing its site.
Alex Moshchuk8e5c1952019-01-15 03:39:50660 //
661 // TODO(alexmos): Callers inside content/ should already be using the
662 // internal SiteInstanceImpl version and providing a proper IsolationContext.
663 // For callers outside content/, plumb the applicable IsolationContext here,
664 // where needed. Eventually, GetSiteForURL should always require an
665 // IsolationContext to be passed in, and this implementation should just
666 // become SiteInstanceImpl::GetSiteForURL.
Aaron Colwell3acea722019-04-24 21:54:43667 return SiteInstanceImpl::GetSiteForURL(IsolationContext(browser_context),
668 url);
Alex Moshchuk5f926a52018-08-29 20:57:30669}
670
671// static
Alex Moshchuk8e5c1952019-01-15 03:39:50672GURL SiteInstanceImpl::DetermineProcessLockURL(
Alex Moshchuk8e5c1952019-01-15 03:39:50673 const IsolationContext& isolation_context,
674 const GURL& url) {
Alex Moshchuk5f926a52018-08-29 20:57:30675 // For the process lock URL, convert |url| to a site without resolving |url|
676 // to an effective URL.
Aaron Colwell3acea722019-04-24 21:54:43677 return SiteInstanceImpl::GetSiteForURLInternal(
Aaron Colwell6fee3f52019-05-08 21:35:02678 isolation_context, url, false /* should_use_effective_urls */,
679 false /* allow_default_site_url */);
Alex Moshchuk5f926a52018-08-29 20:57:30680}
681
Aaron Colwellea6921f2019-01-29 16:50:39682// static
Alex Moshchukf7488792019-03-11 22:37:57683GURL SiteInstanceImpl::GetSiteForURL(const IsolationContext& isolation_context,
Aaron Colwell3acea722019-04-24 21:54:43684 const GURL& real_url) {
685 return GetSiteForURLInternal(isolation_context, real_url,
Aaron Colwell6fee3f52019-05-08 21:35:02686 true /* should_use_effective_urls */,
687 false /* allow_default_site_url */);
Aaron Colwell3acea722019-04-24 21:54:43688}
689
690// static
691GURL SiteInstanceImpl::GetSiteForURLInternal(
692 const IsolationContext& isolation_context,
693 const GURL& real_url,
Aaron Colwell6fee3f52019-05-08 21:35:02694 bool should_use_effective_urls,
695 bool allow_default_site_url) {
[email protected]25a9e8e532012-06-22 06:16:28696 // TODO(fsamuel, creis): For some reason appID is not recognized as a host.
[email protected]6eb1a11e2013-10-09 00:54:37697 if (real_url.SchemeIs(kGuestScheme))
[email protected]25a9e8e532012-06-22 06:16:28698 return real_url;
699
Aaron Colwellea6921f2019-01-29 16:50:39700 if (should_use_effective_urls)
701 DCHECK_CURRENTLY_ON(BrowserThread::UI);
702
Alex Moshchuk5f926a52018-08-29 20:57:30703 GURL url = should_use_effective_urls
Alex Moshchukf7488792019-03-11 22:37:57704 ? SiteInstanceImpl::GetEffectiveURL(
705 isolation_context.browser_or_resource_context()
706 .ToBrowserContext(),
707 real_url)
Alex Moshchuk5f926a52018-08-29 20:57:30708 : real_url;
Daniel Cheng88186bd52017-10-20 08:14:46709 url::Origin origin = url::Origin::Create(url);
[email protected]3a8eecb2010-04-22 23:56:30710
Lukasz Anforowicz48097c42017-12-15 00:23:38711 // If the url has a host, then determine the site. Skip file URLs to avoid a
712 // situation where site URL of file://localhost/ would mismatch Blink's origin
713 // (which ignores the hostname in this case - see https://crbug.com/776160).
Aaron Colwell6fee3f52019-05-08 21:35:02714 GURL site_url;
Lukasz Anforowicz48097c42017-12-15 00:23:38715 if (!origin.host().empty() && origin.scheme() != url::kFileScheme) {
Alex Moshchuk12ce6c792019-05-10 00:32:09716 // For Strict Origin Isolation, use the full origin instead of site for all
717 // HTTP/HTTPS URLs. Note that the HTTP/HTTPS restriction guarantees that
718 // we won't hit this for hosted app effective URLs, which would otherwise
719 // need to append a non-translated site URL to the hash below (see
720 // https://crbug.com/961386).
721 if (SiteIsolationPolicy::IsStrictOriginIsolationEnabled() &&
722 origin.GetURL().SchemeIsHTTPOrHTTPS())
W. James MacLeanf79c97e2019-05-02 20:35:46723 return origin.GetURL();
724
Aaron Colwell6fee3f52019-05-08 21:35:02725 site_url = GetSiteForOrigin(origin);
Alex Moshchuk4e19b362018-09-10 21:14:36726
727 // Isolated origins should use the full origin as their site URL. A
728 // subdomain of an isolated origin should also use that isolated origin's
729 // site URL. It is important to check |origin| (based on |url|) rather than
730 // |real_url| here, since some effective URLs (such as for NTP) need to be
731 // resolved prior to the isolated origin lookup.
732 auto* policy = ChildProcessSecurityPolicyImpl::GetInstance();
733 url::Origin isolated_origin;
Alex Moshchuk8e5c1952019-01-15 03:39:50734 if (policy->GetMatchingIsolatedOrigin(isolation_context, origin, site_url,
735 &isolated_origin))
Alex Moshchuk4e19b362018-09-10 21:14:36736 return isolated_origin.GetURL();
Alex Moshchuk5f926a52018-08-29 20:57:30737
738 // If an effective URL was used, augment the effective site URL with the
739 // underlying web site in the hash. This is needed to keep
740 // navigations across sites covered by one hosted app in separate
741 // SiteInstances. See https://crbug.com/791796.
742 //
743 // TODO(https://crbug.com/734722): Consider replacing this hack with
744 // a proper security principal.
745 if (should_use_effective_urls && url != real_url) {
Alex Moshchuk4e19b362018-09-10 21:14:36746 std::string non_translated_site_url(
Aaron Colwell3acea722019-04-24 21:54:43747 GetSiteForURLInternal(isolation_context, real_url,
Aaron Colwell6fee3f52019-05-08 21:35:02748 false /* should_use_effective_urls */,
749 allow_default_site_url)
Alex Moshchuk4e19b362018-09-10 21:14:36750 .spec());
751 GURL::Replacements replacements;
752 replacements.SetRefStr(non_translated_site_url.c_str());
753 site_url = site_url.ReplaceComponents(replacements);
Alex Moshchuk5f926a52018-08-29 20:57:30754 }
Aaron Colwell6fee3f52019-05-08 21:35:02755 } else {
756 // If there is no host but there is a scheme, return the scheme.
757 // This is useful for cases like file URLs.
758 if (!origin.opaque()) {
759 // Prefer to use the scheme of |origin| rather than |url|, to correctly
760 // cover blob:file: and filesystem:file: URIs (see also
761 // https://crbug.com/697111).
762 DCHECK(!origin.scheme().empty());
763 site_url = GURL(origin.scheme() + ":");
764 } else if (url.has_scheme()) {
765 // In some cases, it is not safe to use just the scheme as a site URL, as
766 // that might allow two URLs created by different sites to share a
767 // process. See https://crbug.com/863623 and https://crbug.com/863069.
768 //
769 // TODO(alexmos,creis): This should eventually be expanded to certain
770 // other schemes, such as file:.
771 // TODO(creis): This currently causes problems with tests on Android and
772 // Android WebView. For now, skip it when Site Isolation is not enabled,
773 // since there's no need to isolate data and blob URLs from each other in
774 // that case.
775 bool is_site_isolation_enabled =
776 SiteIsolationPolicy::UseDedicatedProcessesForAllSites() ||
777 SiteIsolationPolicy::AreIsolatedOriginsEnabled();
778 if (is_site_isolation_enabled &&
779 (url.SchemeIsBlob() || url.scheme() == url::kDataScheme)) {
780 // We get here for blob URLs of form blob:null/guid. Use the full URL
781 // with the guid in that case, which isolates all blob URLs with unique
782 // origins from each other. We also get here for browser-initiated
783 // navigations to data URLs, which have a unique origin and should only
784 // share a process when they are identical. Remove hash from the URL in
785 // either case, since same-document navigations shouldn't use a
786 // different site URL.
787 if (url.has_ref()) {
788 GURL::Replacements replacements;
789 replacements.ClearRef();
790 url = url.ReplaceComponents(replacements);
791 }
792 site_url = url;
793 } else {
794 DCHECK(!url.scheme().empty());
795 site_url = GURL(url.scheme() + ":");
Alex Moshchukb1f87482018-07-19 01:51:51796 }
Aaron Colwell6fee3f52019-05-08 21:35:02797 } else {
798 // Otherwise the URL should be invalid; return an empty site.
799 DCHECK(!url.is_valid()) << url;
800 return GURL();
Alex Moshchukb1f87482018-07-19 01:51:51801 }
Lukasz Anforowiczd926a842018-03-09 01:50:45802 }
creisf60c2cd2014-12-18 00:41:02803
Aaron Colwell6fee3f52019-05-08 21:35:02804 if (allow_default_site_url &&
Aaron Colwell8bb0ada2019-07-18 22:41:23805 CanBePlacedInDefaultSiteInstance(isolation_context, url, site_url)) {
Aaron Colwell6fee3f52019-05-08 21:35:02806 return GetDefaultSiteURL();
807 }
808 return site_url;
initial.commit09911bf2008-07-26 23:55:29809}
810
nickcc0d9142015-10-14 16:27:10811// static
Aaron Colwell8bb0ada2019-07-18 22:41:23812bool SiteInstanceImpl::CanBePlacedInDefaultSiteInstance(
813 const IsolationContext& isolation_context,
814 const GURL& url,
815 const GURL& site_url) {
Clark DuVall4e1f0a72019-08-07 22:41:42816 DCHECK_CURRENTLY_ON(BrowserThread::UI);
Aaron Colwell8bb0ada2019-07-18 22:41:23817 // Exclude "chrome-guest:" URLs from the default SiteInstance to ensure that
818 // guest specific process selection, process swapping, and storage partition
819 // behavior is preserved.
820 if (url.SchemeIs(kGuestScheme))
821 return false;
822
823 // Exclude "file://" URLs from the default SiteInstance to prevent the
824 // default SiteInstance process from accumulating file access grants that
825 // could be exploited by other non-isolated sites.
826 if (url.SchemeIs(url::kFileScheme))
827 return false;
828
829 // Don't use the default SiteInstance when
830 // kProcessSharingWithStrictSiteInstances is enabled because we want each
831 // site to have its own SiteInstance object and logic elsewhere ensures
832 // that those SiteInstances share a process.
833 if (base::FeatureList::IsEnabled(
834 features::kProcessSharingWithStrictSiteInstances)) {
835 return false;
836 }
837
838 // Don't use the default SiteInstance when SiteInstance doesn't assign a
839 // site URL for |url|, since in that case the SiteInstance should remain
840 // unused, and a subsequent navigation should always be able to reuse it,
841 // whether or not it's to a site requiring a dedicated process or to a site
842 // that will use the default SiteInstance.
843 if (!ShouldAssignSiteForURL(url))
844 return false;
845
846 // Allow the default SiteInstance to be used for sites that don't need to be
847 // isolated in their own process.
848 return !DoesSiteURLRequireDedicatedProcess(isolation_context, site_url);
849}
850
851// static
Alex Moshchuk4e19b362018-09-10 21:14:36852GURL SiteInstanceImpl::GetSiteForOrigin(const url::Origin& origin) {
853 // Only keep the scheme and registered domain of |origin|.
854 std::string domain = net::registry_controlled_domains::GetDomainAndRegistry(
855 origin.host(),
856 net::registry_controlled_domains::INCLUDE_PRIVATE_REGISTRIES);
857 std::string site = origin.scheme();
858 site += url::kStandardSchemeSeparator;
859 site += domain.empty() ? origin.host() : domain;
860 return GURL(site);
861}
862
863// static
[email protected]4c3a23582012-08-18 08:54:34864GURL SiteInstanceImpl::GetEffectiveURL(BrowserContext* browser_context,
865 const GURL& url) {
Aaron Colwellea6921f2019-01-29 16:50:39866 DCHECK(browser_context);
Alex Moshchuka31c7882018-01-17 00:57:30867 return GetContentClient()->browser()->GetEffectiveURL(browser_context, url);
[email protected]3a8eecb2010-04-22 23:56:30868}
869
nickcc0d9142015-10-14 16:27:10870// static
Alex Moshchuk25c64bb2017-12-02 02:50:11871bool SiteInstanceImpl::HasEffectiveURL(BrowserContext* browser_context,
872 const GURL& url) {
873 return GetEffectiveURL(browser_context, url) != url;
874}
875
876// static
nickcc0d9142015-10-14 16:27:10877bool SiteInstanceImpl::DoesSiteRequireDedicatedProcess(
Alex Moshchuk8e5c1952019-01-15 03:39:50878 const IsolationContext& isolation_context,
nickdb193a12016-09-09 23:09:23879 const GURL& url) {
Clark DuVall4e1f0a72019-08-07 22:41:42880 DCHECK_CURRENTLY_ON(BrowserThread::UI);
Aaron Colwell5080de62019-05-06 23:02:03881 return SiteIsolationPolicy::UseDedicatedProcessesForAllSites() ||
882 DoesSiteURLRequireDedicatedProcess(
883 isolation_context,
884 SiteInstanceImpl::GetSiteForURL(isolation_context, url));
885}
886
887// static
888bool SiteInstanceImpl::DoesSiteURLRequireDedicatedProcess(
889 const IsolationContext& isolation_context,
890 const GURL& site_url) {
Clark DuVall4e1f0a72019-08-07 22:41:42891 DCHECK_CURRENTLY_ON(BrowserThread::UI);
Lukasz Anforowicz4aff3b82019-04-04 16:00:33892 DCHECK(isolation_context.browser_or_resource_context());
Lukasz Anforowicz4726a172018-10-15 21:25:10893
nickcc0d9142015-10-14 16:27:10894 // If --site-per-process is enabled, site isolation is enabled everywhere.
895 if (SiteIsolationPolicy::UseDedicatedProcessesForAllSites())
896 return true;
897
alexmos3b9ad102017-05-26 23:41:08898 // Always require a dedicated process for isolated origins.
alexmos3b9ad102017-05-26 23:41:08899 auto* policy = ChildProcessSecurityPolicyImpl::GetInstance();
Alex Moshchuk8e5c1952019-01-15 03:39:50900 if (policy->IsIsolatedOrigin(isolation_context,
901 url::Origin::Create(site_url)))
alexmos3b9ad102017-05-26 23:41:08902 return true;
903
Lukasz Anforowicz1f5ad402018-09-28 23:57:54904 // Error pages in main frames do require isolation, however since this is
905 // missing the context whether this is for a main frame or not, that part
906 // is enforced in RenderFrameHostManager.
907 if (site_url.SchemeIs(kChromeErrorScheme))
908 return true;
909
Aaron Colwell7be742612019-08-22 18:25:12910 // Isolate WebUI pages from one another and from other kinds of schemes.
911 for (const auto& webui_scheme : URLDataManagerBackend::GetWebUISchemes()) {
912 if (site_url.SchemeIs(webui_scheme))
913 return true;
914 }
Lukasz Anforowicz1f5ad402018-09-28 23:57:54915
nickdb193a12016-09-09 23:09:23916 // Let the content embedder enable site isolation for specific URLs. Use the
917 // canonical site url for this check, so that schemes with nested origins
918 // (blob and filesystem) work properly.
Avi Drissman8c36df72017-12-11 21:19:20919 if (GetContentClient()->browser()->DoesSiteRequireDedicatedProcess(
Clark DuVall4e1f0a72019-08-07 22:41:42920 isolation_context.browser_or_resource_context().ToBrowserContext(),
921 site_url)) {
nickcc0d9142015-10-14 16:27:10922 return true;
923 }
924
925 return false;
926}
927
alexmos13fe1962017-06-28 04:25:12928// static
Alex Moshchuk8e5c1952019-01-15 03:39:50929bool SiteInstanceImpl::ShouldLockToOrigin(
Alex Moshchuk8e5c1952019-01-15 03:39:50930 const IsolationContext& isolation_context,
931 GURL site_url) {
Lukasz Anforowicz1a0a89a2019-03-29 22:31:02932 DCHECK_CURRENTLY_ON(BrowserThread::UI);
933 BrowserContext* browser_context =
934 isolation_context.browser_or_resource_context().ToBrowserContext();
Lukasz Anforowicz4726a172018-10-15 21:25:10935 DCHECK(browser_context);
936
creis0b49fa12017-07-10 16:31:11937 // Don't lock to origin in --single-process mode, since this mode puts
938 // cross-site pages into the same process.
Alex Moshchukd4c4ca32018-08-15 20:36:51939 if (RenderProcessHost::run_renderer_in_process())
creis0b49fa12017-07-10 16:31:11940 return false;
941
Aaron Colwell5080de62019-05-06 23:02:03942 if (!DoesSiteURLRequireDedicatedProcess(isolation_context, site_url))
alexmos13fe1962017-06-28 04:25:12943 return false;
944
945 // Guest processes cannot be locked to their site because guests always have
946 // a fixed SiteInstance. The site of GURLs a guest loads doesn't match that
947 // SiteInstance. So we skip locking the guest process to the site.
948 // TODO(ncarter): Remove this exclusion once we can make origin lock per
949 // RenderFrame routing id.
950 if (site_url.SchemeIs(content::kGuestScheme))
951 return false;
952
alexmos13fe1962017-06-28 04:25:12953 // TODO(creis, nick): Until we can handle sites with effective URLs at the
954 // call sites of ChildProcessSecurityPolicy::CanAccessDataForOrigin, we
955 // must give the embedder a chance to exempt some sites to avoid process
956 // kills.
957 if (!GetContentClient()->browser()->ShouldLockToOrigin(browser_context,
958 site_url)) {
959 return false;
960 }
961
962 return true;
963}
964
Lukasz Anforowicz27851e62018-12-18 23:04:08965// static
966base::Optional<url::Origin> SiteInstanceImpl::GetRequestInitiatorSiteLock(
Lukasz Anforowicz27851e62018-12-18 23:04:08967 GURL site_url) {
Lukasz Anforowicz27851e62018-12-18 23:04:08968 // The following schemes are safe for sites that require a process lock:
969 // - data: - locking |request_initiator| to an opaque origin
970 // - http/https - requiring |request_initiator| to match |site_url| with
971 // DomainIs (i.e. suffix-based) comparison.
972 if (site_url.SchemeIsHTTPOrHTTPS() || site_url.SchemeIs(url::kDataScheme))
973 return url::Origin::Create(site_url);
974
975 // Other schemes might not be safe to use as |request_initiator_site_lock|.
976 // One example is chrome-guest://...
977 return base::nullopt;
978}
979
[email protected]40bfaf32013-11-19 01:35:43980void SiteInstanceImpl::RenderProcessHostDestroyed(RenderProcessHost* host) {
981 DCHECK_EQ(process_, host);
982 process_->RemoveObserver(this);
nickd5bbd0b2016-03-31 19:52:44983 process_ = nullptr;
[email protected]4566f132009-03-12 01:55:13984}
[email protected]313b80bd2011-11-23 03:49:10985
Bo Liu2a489402018-04-24 23:41:27986void SiteInstanceImpl::RenderProcessExited(
987 RenderProcessHost* host,
988 const ChildProcessTerminationInfo& info) {
ericwilligers254597b2016-10-17 10:32:31989 for (auto& observer : observers_)
Hajime Hoshi3b2e4222019-10-10 10:17:07990 observer.RenderProcessGone(this, info);
nick9f34e2892016-01-12 21:01:07991}
992
alexmos13fe1962017-06-28 04:25:12993void SiteInstanceImpl::LockToOriginIfNeeded() {
994 DCHECK(HasSite());
995
996 // From now on, this process should be considered "tainted" for future
997 // process reuse decisions:
998 // (1) If |site_| required a dedicated process, this SiteInstance's process
999 // can only host URLs for the same site.
1000 // (2) Even if |site_| does not require a dedicated process, this
1001 // SiteInstance's process still cannot be reused to host other sites
1002 // requiring dedicated sites in the future.
1003 // We can get here either when we commit a URL into a SiteInstance that does
1004 // not yet have a site, or when we create a process for a SiteInstance with a
1005 // preassigned site.
1006 process_->SetIsUsed();
1007
Alex Moshchuk47dd00f2017-10-10 17:15:231008 ChildProcessSecurityPolicyImpl* policy =
1009 ChildProcessSecurityPolicyImpl::GetInstance();
Alex Moshchuk58225c82019-04-18 00:45:011010 GURL process_lock = policy->GetOriginLock(process_->GetID());
Lukasz Anforowicz1a0a89a2019-03-29 22:31:021011 if (ShouldLockToOrigin(GetIsolationContext(), site_)) {
Alex Moshchuk9cf5a45d2017-08-14 18:50:571012 // Sanity check that this won't try to assign an origin lock to a <webview>
1013 // process, which can't be locked.
1014 CHECK(!process_->IsForGuestsOnly());
1015
Alex Moshchuk58225c82019-04-18 00:45:011016 if (process_lock.is_empty()) {
1017 // TODO(nick): When all sites are isolated, this operation provides
1018 // strong protection. If only some sites are isolated, we need
1019 // additional logic to prevent the non-isolated sites from requesting
1020 // resources for isolated sites. https://crbug.com/509125
1021 TRACE_EVENT2("navigation", "SiteInstanceImpl::LockToOrigin", "site id",
1022 id_, "lock", lock_url().possibly_invalid_spec());
1023 process_->LockToOrigin(GetIsolationContext(), lock_url());
1024 } else if (process_lock != lock_url()) {
1025 // We should never attempt to reassign a different origin lock to a
1026 // process.
1027 base::debug::SetCrashKeyString(bad_message::GetRequestedSiteURLKey(),
1028 site_.spec());
1029 base::debug::SetCrashKeyString(
1030 bad_message::GetKilledProcessOriginLockKey(), process_lock.spec());
1031 CHECK(false) << "Trying to lock a process to " << lock_url()
1032 << " but the process is already locked to " << process_lock;
1033 } else {
1034 // Process already has the right origin lock assigned. This case will
1035 // happen for commits to |site_| after the first one.
Alex Moshchuk9cf5a45d2017-08-14 18:50:571036 }
Alex Moshchuk47dd00f2017-10-10 17:15:231037 } else {
1038 // If the site that we've just committed doesn't require a dedicated
1039 // process, make sure we aren't putting it in a process for a site that
1040 // does.
Alex Moshchuk58225c82019-04-18 00:45:011041 if (!process_lock.is_empty()) {
Alex Moshchuk1656c672018-04-28 01:48:341042 base::debug::SetCrashKeyString(bad_message::GetRequestedSiteURLKey(),
1043 site_.spec());
1044 base::debug::SetCrashKeyString(
Alex Moshchuk58225c82019-04-18 00:45:011045 bad_message::GetKilledProcessOriginLockKey(), process_lock.spec());
Alex Moshchuk1656c672018-04-28 01:48:341046 CHECK(false) << "Trying to commit non-isolated site " << site_
Alex Moshchuk58225c82019-04-18 00:45:011047 << " in process locked to " << process_lock;
Alex Moshchuk1656c672018-04-28 01:48:341048 }
[email protected]313b80bd2011-11-23 03:49:101049 }
Lukasz Anforowicz38003582019-09-24 19:08:051050
1051 // Track which isolation contexts use the given process. This lets
1052 // ChildProcessSecurityPolicyImpl (e.g. CanAccessDataForOrigin) determine
1053 // whether a given URL should require a lock or not (a dynamically isolated
1054 // origin may require a lock in some isolation contexts but not in others).
1055 policy->IncludeIsolationContext(process_->GetID(), GetIsolationContext());
[email protected]313b80bd2011-11-23 03:49:101056}
[email protected]46488322012-10-30 03:22:201057
Alex Moshchuk07e1bb42019-03-08 04:44:081058// static
1059void SiteInstance::StartIsolatingSite(BrowserContext* context,
1060 const GURL& url) {
1061 if (!SiteIsolationPolicy::AreDynamicIsolatedOriginsEnabled())
1062 return;
1063
1064 // Ignore attempts to isolate origins that are not supported. Do this here
1065 // instead of relying on AddIsolatedOrigins()'s internal validation, to avoid
1066 // the runtime warning generated by the latter.
1067 url::Origin origin(url::Origin::Create(url));
1068 if (!IsolatedOriginUtil::IsValidIsolatedOrigin(origin))
1069 return;
1070
1071 // Convert |url| to a site, to avoid breaking document.domain. Note that
1072 // this doesn't use effective URL resolution or other special cases from
1073 // GetSiteForURL() and simply converts |origin| to a scheme and eTLD+1.
1074 GURL site(SiteInstanceImpl::GetSiteForOrigin(origin));
1075
1076 ChildProcessSecurityPolicyImpl* policy =
1077 ChildProcessSecurityPolicyImpl::GetInstance();
Alex Moshchuke256d562019-04-26 21:43:571078 url::Origin site_origin(url::Origin::Create(site));
Alex Moshchukc4679422019-06-11 17:04:481079 policy->AddIsolatedOrigins(
1080 {site_origin},
1081 ChildProcessSecurityPolicy::IsolatedOriginSource::USER_TRIGGERED,
1082 context);
Alex Moshchuke256d562019-04-26 21:43:571083
1084 // This function currently assumes the new isolated site should persist
1085 // across restarts, so ask the embedder to save it, excluding off-the-record
1086 // profiles.
1087 if (!context->IsOffTheRecord())
1088 GetContentClient()->browser()->PersistIsolatedOrigin(context, site_origin);
Alex Moshchuk07e1bb42019-03-08 04:44:081089}
1090
[email protected]46488322012-10-30 03:22:201091} // namespace content