blob: b5efd8f56964bd07290bb0c9970d77bdd0e02978 [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"
Nate Chapin71da03c2019-02-05 01:21:4127#include "content/public/common/content_features.h"
creis0b49fa12017-07-10 16:31:1128#include "content/public/common/content_switches.h"
[email protected]a1d29162011-10-14 17:14:0329#include "content/public/common/url_constants.h"
clamy7fced7b2017-11-16 19:52:4330#include "content/public/common/url_utils.h"
[email protected]be28b5f42012-07-20 11:31:2531#include "net/base/registry_controlled_domains/registry_controlled_domain.h"
initial.commit09911bf2008-07-26 23:55:2932
[email protected]46488322012-10-30 03:22:2033namespace content {
[email protected]b6583592012-01-25 19:52:3334
Aaron Colwellf45e3a852019-06-06 00:48:2735namespace {
36
37// Returns true if CreateForURL() and related functions should be allowed to
38// return a default SiteInstance.
39bool ShouldAllowDefaultSiteInstance() {
Aaron Colwellc2ab84e2019-07-24 01:31:0040 return base::FeatureList::IsEnabled(
41 features::kProcessSharingWithDefaultSiteInstances);
Aaron Colwellf45e3a852019-06-06 00:48:2742}
43
44} // namespace
45
avib7348942015-12-25 20:57:1046int32_t SiteInstanceImpl::next_site_instance_id_ = 1;
[email protected]992db4c2011-05-12 15:37:1547
Aaron Colwell6fee3f52019-05-08 21:35:0248// static
49const GURL& SiteInstanceImpl::GetDefaultSiteURL() {
50 struct DefaultSiteURL {
51 const GURL url = GURL("http://unisolated.invalid");
52 };
53 static base::LazyInstance<DefaultSiteURL>::Leaky default_site_url =
54 LAZY_INSTANCE_INITIALIZER;
55
56 return default_site_url.Get().url;
57}
58
[email protected]b6583592012-01-25 19:52:3359SiteInstanceImpl::SiteInstanceImpl(BrowsingInstance* browsing_instance)
[email protected]992db4c2011-05-12 15:37:1560 : id_(next_site_instance_id_++),
creiscce56cd2014-09-29 22:45:2261 active_frame_count_(0),
[email protected]992db4c2011-05-12 15:37:1562 browsing_instance_(browsing_instance),
nickd5bbd0b2016-03-31 19:52:4463 process_(nullptr),
Lukasz Anforowicz3caa8372018-06-05 17:22:0764 can_associate_with_spare_process_(true),
nickd5bbd0b2016-03-31 19:52:4465 has_site_(false),
Tsuyoshi Horoeb576e62017-06-28 06:00:4166 process_reuse_policy_(ProcessReusePolicy::DEFAULT),
67 is_for_service_worker_(false) {
[email protected]4566f132009-03-12 01:55:1368 DCHECK(browsing_instance);
[email protected]4566f132009-03-12 01:55:1369}
70
[email protected]b6583592012-01-25 19:52:3371SiteInstanceImpl::~SiteInstanceImpl() {
[email protected]46488322012-10-30 03:22:2072 GetContentClient()->browser()->SiteInstanceDeleting(this);
[email protected]056ad2a2011-07-12 02:13:5573
Charlie Reiscf6aa512019-04-16 17:27:2974 if (process_) {
[email protected]40bfaf32013-11-19 01:35:4375 process_->RemoveObserver(this);
76
Charlie Reiscf6aa512019-04-16 17:27:2977 // Ensure the RenderProcessHost gets deleted if this SiteInstance created a
78 // process which was never used by any listeners.
79 process_->Cleanup();
80 }
81
initial.commit09911bf2008-07-26 23:55:2982 // Now that no one is referencing us, we can safely remove ourselves from
83 // the BrowsingInstance. Any future visits to a page from this site
84 // (within the same BrowsingInstance) can safely create a new SiteInstance.
85 if (has_site_)
dchengbccd6b82016-03-30 16:24:1986 browsing_instance_->UnregisterSiteInstance(this);
87}
88
Nasko Oskovdeb6c7ea2017-11-30 18:18:1189// static
dchengbccd6b82016-03-30 16:24:1990scoped_refptr<SiteInstanceImpl> SiteInstanceImpl::Create(
91 BrowserContext* browser_context) {
Lukasz Anforowicz4726a172018-10-15 21:25:1092 DCHECK(browser_context);
kylecharda69d882017-10-04 05:49:5293 return base::WrapRefCounted(
dchengbccd6b82016-03-30 16:24:1994 new SiteInstanceImpl(new BrowsingInstance(browser_context)));
95}
96
Nasko Oskovdeb6c7ea2017-11-30 18:18:1197// static
dchengbccd6b82016-03-30 16:24:1998scoped_refptr<SiteInstanceImpl> SiteInstanceImpl::CreateForURL(
99 BrowserContext* browser_context,
100 const GURL& url) {
Lukasz Anforowicz4726a172018-10-15 21:25:10101 DCHECK(browser_context);
dchengbccd6b82016-03-30 16:24:19102 // This will create a new SiteInstance and BrowsingInstance.
103 scoped_refptr<BrowsingInstance> instance(
104 new BrowsingInstance(browser_context));
Aaron Colwellf45e3a852019-06-06 00:48:27105 return instance->GetSiteInstanceForURL(url, ShouldAllowDefaultSiteInstance());
initial.commit09911bf2008-07-26 23:55:29106}
107
Nasko Oskovdeb6c7ea2017-11-30 18:18:11108// static
Aaron Colwellecc72fb2019-04-30 17:41:11109scoped_refptr<SiteInstanceImpl> SiteInstanceImpl::CreateForServiceWorker(
110 BrowserContext* browser_context,
Aaron Colwell369968ee2019-05-14 00:32:38111 const GURL& url,
112 bool can_reuse_process) {
Aaron Colwellecc72fb2019-04-30 17:41:11113 // This will create a new SiteInstance and BrowsingInstance.
114 scoped_refptr<BrowsingInstance> instance(
115 new BrowsingInstance(browser_context));
116
117 // We do NOT want to allow the default site instance here because workers
118 // need to be kept separate from other sites.
119 scoped_refptr<SiteInstanceImpl> site_instance =
120 instance->GetSiteInstanceForURL(url, /* allow_default_instance */ false);
121 site_instance->is_for_service_worker_ = true;
Aaron Colwell369968ee2019-05-14 00:32:38122
123 // Attempt to reuse a renderer process if possible. Note that in the
124 // <webview> case, process reuse isn't currently supported and a new
125 // process will always be created (https://crbug.com/752667).
126 DCHECK(site_instance->process_reuse_policy() ==
127 SiteInstanceImpl::ProcessReusePolicy::DEFAULT ||
128 site_instance->process_reuse_policy() ==
129 SiteInstanceImpl::ProcessReusePolicy::PROCESS_PER_SITE);
130 if (can_reuse_process) {
131 site_instance->set_process_reuse_policy(
132 SiteInstanceImpl::ProcessReusePolicy::REUSE_PENDING_OR_COMMITTED_SITE);
133 }
134 return site_instance;
135}
136
137// static
138scoped_refptr<SiteInstanceImpl>
139SiteInstanceImpl::CreateReusableInstanceForTesting(
140 BrowserContext* browser_context,
141 const GURL& url) {
142 DCHECK(browser_context);
143 // This will create a new SiteInstance and BrowsingInstance.
144 scoped_refptr<BrowsingInstance> instance(
145 new BrowsingInstance(browser_context));
146 auto site_instance =
147 instance->GetSiteInstanceForURL(url,
148 /* allow_default_instance */ false);
149 site_instance->set_process_reuse_policy(
150 SiteInstanceImpl::ProcessReusePolicy::REUSE_PENDING_OR_COMMITTED_SITE);
Aaron Colwellecc72fb2019-04-30 17:41:11151 return site_instance;
152}
153
154// static
Nasko Oskovdeb6c7ea2017-11-30 18:18:11155bool SiteInstanceImpl::ShouldAssignSiteForURL(const GURL& url) {
156 // about:blank should not "use up" a new SiteInstance. The SiteInstance can
157 // still be used for a normal web site.
Mohamed Abdelhalim9e868ca42019-04-25 16:53:29158 if (url.IsAboutBlank())
Nasko Oskovdeb6c7ea2017-11-30 18:18:11159 return false;
160
161 // The embedder will then have the opportunity to determine if the URL
162 // should "use up" the SiteInstance.
163 return GetContentClient()->browser()->ShouldAssignSiteForURL(url);
164}
165
Nicolas Pena7c7847f2018-05-30 01:36:05166// static
167bool SiteInstanceImpl::IsOriginLockASite(const GURL& lock_url) {
168 return lock_url.has_scheme() && lock_url.has_host();
169}
170
avib7348942015-12-25 20:57:10171int32_t SiteInstanceImpl::GetId() {
[email protected]b6583592012-01-25 19:52:33172 return id_;
173}
174
Chris Hamilton2ed5d5572019-05-23 22:47:58175int32_t SiteInstanceImpl::GetBrowsingInstanceId() {
176 // This is being vended out as an opaque ID, and it is always defined for
177 // a BrowsingInstance affiliated IsolationContext, so it's safe to call
178 // "GetUnsafeValue" and expose the inner value directly.
179 return browsing_instance_->isolation_context()
180 .browsing_instance_id()
181 .GetUnsafeValue();
182}
183
Alex Moshchuk8e5c1952019-01-15 03:39:50184const IsolationContext& SiteInstanceImpl::GetIsolationContext() {
185 return browsing_instance_->isolation_context();
186}
187
Nate Chapin71da03c2019-02-05 01:21:41188RenderProcessHost* SiteInstanceImpl::GetDefaultProcessIfUsable() {
189 if (!base::FeatureList::IsEnabled(
190 features::kProcessSharingWithStrictSiteInstances)) {
191 return nullptr;
192 }
193 if (RequiresDedicatedProcess())
194 return nullptr;
195 return browsing_instance_->default_process();
196}
197
Aaron Colwell0447cd02019-06-26 22:04:20198bool SiteInstanceImpl::IsDefaultSiteInstance() const {
Aaron Colwellddeccbdb2019-03-08 01:11:03199 return browsing_instance_->IsDefaultSiteInstance(this);
200}
201
Aaron Colwell0447cd02019-06-26 22:04:20202bool SiteInstanceImpl::IsSiteInDefaultSiteInstance(const GURL& site_url) const {
203 return browsing_instance_->IsSiteInDefaultSiteInstance(site_url);
204}
205
Nate Chapin71da03c2019-02-05 01:21:41206void SiteInstanceImpl::MaybeSetBrowsingInstanceDefaultProcess() {
207 if (!base::FeatureList::IsEnabled(
208 features::kProcessSharingWithStrictSiteInstances)) {
209 return;
210 }
211 // Wait until this SiteInstance both has a site and a process
212 // assigned, so that we can be sure that RequiresDedicatedProcess()
213 // is accurate and we actually have a process to set.
214 if (!process_ || !has_site_ || RequiresDedicatedProcess())
215 return;
216 if (browsing_instance_->default_process()) {
217 DCHECK_EQ(process_, browsing_instance_->default_process());
218 return;
219 }
220 browsing_instance_->SetDefaultProcess(process_);
221}
222
Alex Moshchuk8e5c1952019-01-15 03:39:50223// static
224BrowsingInstanceId SiteInstanceImpl::NextBrowsingInstanceId() {
225 return BrowsingInstance::NextBrowsingInstanceId();
226}
227
228bool SiteInstanceImpl::HasProcess() {
Ivan Kotenkov2c0d2bb32017-11-01 15:41:28229 if (process_ != nullptr)
[email protected]41fb79a52012-06-29 16:34:33230 return true;
231
232 // If we would use process-per-site for this site, also check if there is an
233 // existing process that we would use if GetProcess() were called.
Alex Moshchukf7488792019-03-11 22:37:57234 BrowserContext* browser_context = browsing_instance_->GetBrowserContext();
[email protected]41fb79a52012-06-29 16:34:33235 if (has_site_ &&
[email protected]1ae93fb12013-06-14 03:38:56236 RenderProcessHost::ShouldUseProcessPerSite(browser_context, site_) &&
Alex Moshchuk8e5c1952019-01-15 03:39:50237 RenderProcessHostImpl::GetSoleProcessHostForSite(
238 browser_context, GetIsolationContext(), site_, lock_url_)) {
[email protected]41fb79a52012-06-29 16:34:33239 return true;
240 }
241
242 return false;
[email protected]5ab79b02010-04-26 16:47:11243}
244
[email protected]41fb79a52012-06-29 16:34:33245RenderProcessHost* SiteInstanceImpl::GetProcess() {
[email protected]08c8ec7e2010-07-11 17:14:48246 // TODO(erikkay) It would be nice to ensure that the renderer type had been
247 // properly set before we get here. The default tab creation case winds up
248 // with no site set at this point, so it will default to TYPE_NORMAL. This
249 // may not be correct, so we'll wind up potentially creating a process that
250 // we then throw away, or worse sharing a process with the wrong process type.
251 // See crbug.com/43448.
252
initial.commit09911bf2008-07-26 23:55:29253 // Create a new process if ours went away or was reused.
[email protected]4566f132009-03-12 01:55:13254 if (!process_) {
Alex Moshchukf7488792019-03-11 22:37:57255 BrowserContext* browser_context = browsing_instance_->GetBrowserContext();
[email protected]41fb79a52012-06-29 16:34:33256
clamy63960c32017-05-10 22:57:07257 // Check if the ProcessReusePolicy should be updated.
258 bool should_use_process_per_site =
creisa9f04ba2017-05-19 22:27:42259 has_site_ &&
260 RenderProcessHost::ShouldUseProcessPerSite(browser_context, site_);
clamy63960c32017-05-10 22:57:07261 if (should_use_process_per_site) {
262 process_reuse_policy_ = ProcessReusePolicy::PROCESS_PER_SITE;
263 } else if (process_reuse_policy_ == ProcessReusePolicy::PROCESS_PER_SITE) {
264 process_reuse_policy_ = ProcessReusePolicy::DEFAULT;
[email protected]41fb79a52012-06-29 16:34:33265 }
266
Alex Moshchuk5f926a52018-08-29 20:57:30267 process_ = RenderProcessHostImpl::GetProcessHostForSiteInstance(this);
avi6d686db2017-01-06 02:28:57268
[email protected]41fb79a52012-06-29 16:34:33269 CHECK(process_);
[email protected]40bfaf32013-11-19 01:35:43270 process_->AddObserver(this);
[email protected]41fb79a52012-06-29 16:34:33271
Nate Chapin71da03c2019-02-05 01:21:41272 MaybeSetBrowsingInstanceDefaultProcess();
273
[email protected]41fb79a52012-06-29 16:34:33274 // If we are using process-per-site, we need to register this process
275 // for the current site so that we can find it again. (If no site is set
276 // at this time, we will register it in SetSite().)
clamy63960c32017-05-10 22:57:07277 if (process_reuse_policy_ == ProcessReusePolicy::PROCESS_PER_SITE &&
278 has_site_) {
Alex Moshchuk5f926a52018-08-29 20:57:30279 RenderProcessHostImpl::RegisterSoleProcessHostForSite(browser_context,
280 process_, this);
[email protected]41fb79a52012-06-29 16:34:33281 }
initial.commit09911bf2008-07-26 23:55:29282
naskob8744d22014-08-28 17:07:43283 TRACE_EVENT2("navigation", "SiteInstanceImpl::GetProcess",
284 "site id", id_, "process id", process_->GetID());
[email protected]46488322012-10-30 03:22:20285 GetContentClient()->browser()->SiteInstanceGotProcess(this);
[email protected]6f371442011-11-09 06:45:46286
[email protected]313b80bd2011-11-23 03:49:10287 if (has_site_)
alexmos13fe1962017-06-28 04:25:12288 LockToOriginIfNeeded();
initial.commit09911bf2008-07-26 23:55:29289 }
[email protected]4566f132009-03-12 01:55:13290 DCHECK(process_);
initial.commit09911bf2008-07-26 23:55:29291
[email protected]4566f132009-03-12 01:55:13292 return process_;
initial.commit09911bf2008-07-26 23:55:29293}
294
Lukasz Anforowicz3caa8372018-06-05 17:22:07295bool SiteInstanceImpl::CanAssociateWithSpareProcess() {
296 return can_associate_with_spare_process_;
297}
298
299void SiteInstanceImpl::PreventAssociationWithSpareProcess() {
300 can_associate_with_spare_process_ = false;
301}
302
[email protected]b6583592012-01-25 19:52:33303void SiteInstanceImpl::SetSite(const GURL& url) {
Charlie Reisc2099752019-04-06 01:21:12304 // TODO(creis): Consider calling ShouldAssignSiteForURL internally, rather
305 // than before multiple call sites. See https://crbug.com/949220.
naskob8744d22014-08-28 17:07:43306 TRACE_EVENT2("navigation", "SiteInstanceImpl::SetSite",
307 "site id", id_, "url", url.possibly_invalid_spec());
initial.commit09911bf2008-07-26 23:55:29308 // A SiteInstance's site should not change.
309 // TODO(creis): When following links or script navigations, we can currently
310 // render pages from other sites in this SiteInstance. This will eventually
311 // be fixed, but until then, we should still not set the site of a
312 // SiteInstance more than once.
313 DCHECK(!has_site_);
314
315 // Remember that this SiteInstance has been used to load a URL, even if the
316 // URL is invalid.
317 has_site_ = true;
Alex Moshchukf7488792019-03-11 22:37:57318 BrowserContext* browser_context = browsing_instance_->GetBrowserContext();
Alex Moshchuk25c64bb2017-12-02 02:50:11319 original_url_ = url;
Aaron Colwellddeccbdb2019-03-08 01:11:03320 browsing_instance_->GetSiteAndLockForURL(
321 url, /* allow_default_instance */ false, &site_, &lock_url_);
initial.commit09911bf2008-07-26 23:55:29322
323 // Now that we have a site, register it with the BrowsingInstance. This
324 // ensures that we won't create another SiteInstance for this site within
325 // the same BrowsingInstance, because all same-site pages within a
326 // BrowsingInstance can script each other.
327 browsing_instance_->RegisterSiteInstance(this);
[email protected]313b80bd2011-11-23 03:49:10328
clamy63960c32017-05-10 22:57:07329 // Update the process reuse policy based on the site.
330 bool should_use_process_per_site =
331 RenderProcessHost::ShouldUseProcessPerSite(browser_context, site_);
332 if (should_use_process_per_site) {
333 process_reuse_policy_ = ProcessReusePolicy::PROCESS_PER_SITE;
334 }
335
[email protected]41fb79a52012-06-29 16:34:33336 if (process_) {
alexmos13fe1962017-06-28 04:25:12337 LockToOriginIfNeeded();
[email protected]41fb79a52012-06-29 16:34:33338
339 // Ensure the process is registered for this site if necessary.
clamy63960c32017-05-10 22:57:07340 if (should_use_process_per_site) {
Alex Moshchuk5f926a52018-08-29 20:57:30341 RenderProcessHostImpl::RegisterSoleProcessHostForSite(browser_context,
342 process_, this);
[email protected]41fb79a52012-06-29 16:34:33343 }
Nate Chapin71da03c2019-02-05 01:21:41344 MaybeSetBrowsingInstanceDefaultProcess();
[email protected]41fb79a52012-06-29 16:34:33345 }
initial.commit09911bf2008-07-26 23:55:29346}
347
Aaron Colwelle953e562019-07-24 16:47:36348void SiteInstanceImpl::ConvertToDefaultOrSetSite(const GURL& url) {
349 DCHECK(!has_site_);
350
351 if (ShouldAllowDefaultSiteInstance() &&
352 browsing_instance_->TrySettingDefaultSiteInstance(this, url)) {
353 return;
354 }
355
356 SetSite(url);
357}
358
Lucas Furukawa Gadanid726e1e2019-05-08 16:20:03359const GURL& SiteInstanceImpl::GetSiteURL() {
[email protected]b6583592012-01-25 19:52:33360 return site_;
361}
362
363bool SiteInstanceImpl::HasSite() const {
364 return has_site_;
365}
366
367bool SiteInstanceImpl::HasRelatedSiteInstance(const GURL& url) {
initial.commit09911bf2008-07-26 23:55:29368 return browsing_instance_->HasSiteInstance(url);
369}
370
dchengbccd6b82016-03-30 16:24:19371scoped_refptr<SiteInstance> SiteInstanceImpl::GetRelatedSiteInstance(
372 const GURL& url) {
Aaron Colwellddeccbdb2019-03-08 01:11:03373 return browsing_instance_->GetSiteInstanceForURL(
374 url, /* allow_default_instance */ true);
initial.commit09911bf2008-07-26 23:55:29375}
376
[email protected]14392a52012-05-02 20:28:44377bool SiteInstanceImpl::IsRelatedSiteInstance(const SiteInstance* instance) {
[email protected]fc72bb12013-06-02 21:13:46378 return browsing_instance_.get() == static_cast<const SiteInstanceImpl*>(
379 instance)->browsing_instance_.get();
[email protected]14392a52012-05-02 20:28:44380}
381
[email protected]d5072a82014-05-15 05:50:18382size_t SiteInstanceImpl::GetRelatedActiveContentsCount() {
383 return browsing_instance_->active_contents_count();
384}
385
[email protected]f88628d02012-11-11 17:58:59386bool SiteInstanceImpl::HasWrongProcessForURL(const GURL& url) {
Clark DuVall4e1f0a72019-08-07 22:41:42387 DCHECK_CURRENTLY_ON(BrowserThread::UI);
[email protected]144a8102012-01-14 01:05:31388 // If the URL to navigate to can be associated with any site instance,
389 // we want to keep it in the same process.
[email protected]c02f1ba2014-02-03 06:53:53390 if (IsRendererDebugURL(url))
[email protected]144a8102012-01-14 01:05:31391 return false;
392
Nasko Oskov978c16b2018-08-03 22:17:06393 // Any process can host an about:blank URL, except the one used for error
394 // pages, which should not commit successful navigations. This check avoids a
395 // process transfer for browser-initiated navigations to about:blank in a
396 // dedicated process; without it, IsSuitableHost would consider this process
397 // unsuitable for about:blank when it compares origin locks.
398 // Renderer-initiated navigations will handle about:blank navigations
399 // elsewhere and leave them in the source SiteInstance, along with
400 // about:srcdoc and data:.
401 if (url.IsAboutBlank() && site_ != GURL(kUnreachableWebDataURL))
alexmos13fe1962017-06-28 04:25:12402 return false;
403
[email protected]88aae972011-12-16 01:14:18404 // If the site URL is an extension (e.g., for hosted apps or WebUI) but the
[email protected]d292d8a2011-05-25 03:47:11405 // process is not (or vice versa), make sure we notice and fix it.
Aaron Colwellddeccbdb2019-03-08 01:11:03406 GURL site_url;
407 GURL origin_lock;
408
409 // Note: This call must return information that is identical to what
410 // would be reported in the SiteInstance returned by
411 // GetRelatedSiteInstance(url).
412 browsing_instance_->GetSiteAndLockForURL(
413 url, /* allow_default_instance */ true, &site_url, &origin_lock);
Charlie Reisc2099752019-04-06 01:21:12414
Aaron Colwell7292aec2019-07-25 17:23:43415 // If this is a default SiteInstance and the BrowsingInstance gives us a
416 // non-default site URL even when we explicitly allow the default SiteInstance
417 // to be considered, then |url| does not belong in the same process as this
418 // SiteInstance. This can happen when the
419 // kProcessSharingWithDefaultSiteInstances feature is not enabled and the
420 // site URL is explicitly set on a SiteInstance for a URL that would normally
421 // be directed to the default SiteInstance (e.g. a site not requiring a
422 // dedicated process). This situation typically happens when the top-level
423 // frame is a site that should be in the default SiteInstance and the
424 // SiteInstance associated with that frame is initially a SiteInstance with
425 // no site URL set.
426 if (IsDefaultSiteInstance() && site_url != GetSiteURL())
427 return true;
428
Charlie Reisc2099752019-04-06 01:21:12429 // Note that HasProcess() may return true if process_ is null, in
430 // process-per-site cases where there's an existing process available.
431 // We want to use such a process in the IsSuitableHost check, so we
432 // may end up assigning process_ in the GetProcess() call below.
433 if (!HasProcess()) {
434 // If there is no process or site, then this is a new SiteInstance that can
435 // be used for anything.
436 if (!HasSite())
437 return false;
438
439 // If there is no process but there is a site, then the process must have
440 // been discarded after we navigated away. If the site URLs match, then it
441 // is safe to use this SiteInstance.
442 if (GetSiteURL() == site_url)
443 return false;
444
445 // If the site URLs do not match, but neither this SiteInstance nor the
446 // destination site_url require dedicated processes, then it is safe to use
447 // this SiteInstance.
448 if (!RequiresDedicatedProcess() &&
Aaron Colwell5080de62019-05-06 23:02:03449 !DoesSiteURLRequireDedicatedProcess(GetIsolationContext(), site_url)) {
Charlie Reisc2099752019-04-06 01:21:12450 return false;
451 }
452
453 // Otherwise, there's no process, the site URLs don't match, and at least
454 // one of them requires a dedicated process, so it is not safe to use this
455 // SiteInstance.
456 return true;
457 }
458
[email protected]88aae972011-12-16 01:14:18459 return !RenderProcessHostImpl::IsSuitableHost(
Alex Moshchukf7488792019-03-11 22:37:57460 GetProcess(), browsing_instance_->GetBrowserContext(),
Alex Moshchuk8e5c1952019-01-15 03:39:50461 GetIsolationContext(), site_url, origin_lock);
[email protected]d292d8a2011-05-25 03:47:11462}
463
nickd30fd962015-07-27 21:51:08464bool SiteInstanceImpl::RequiresDedicatedProcess() {
Clark DuVall4e1f0a72019-08-07 22:41:42465 DCHECK_CURRENTLY_ON(BrowserThread::UI);
nickd30fd962015-07-27 21:51:08466 if (!has_site_)
467 return false;
nickd5bbd0b2016-03-31 19:52:44468
Aaron Colwell5080de62019-05-06 23:02:03469 return DoesSiteURLRequireDedicatedProcess(GetIsolationContext(), site_);
nickd30fd962015-07-27 21:51:08470}
471
nick9f34e2892016-01-12 21:01:07472void SiteInstanceImpl::IncrementActiveFrameCount() {
473 active_frame_count_++;
474}
475
476void SiteInstanceImpl::DecrementActiveFrameCount() {
ericwilligers254597b2016-10-17 10:32:31477 if (--active_frame_count_ == 0) {
478 for (auto& observer : observers_)
479 observer.ActiveFrameCountIsZero(this);
480 }
nick9f34e2892016-01-12 21:01:07481}
482
[email protected]d5072a82014-05-15 05:50:18483void SiteInstanceImpl::IncrementRelatedActiveContentsCount() {
484 browsing_instance_->increment_active_contents_count();
485}
486
487void SiteInstanceImpl::DecrementRelatedActiveContentsCount() {
488 browsing_instance_->decrement_active_contents_count();
489}
490
nick9f34e2892016-01-12 21:01:07491void SiteInstanceImpl::AddObserver(Observer* observer) {
492 observers_.AddObserver(observer);
493}
494
495void SiteInstanceImpl::RemoveObserver(Observer* observer) {
496 observers_.RemoveObserver(observer);
497}
498
Lucas Furukawa Gadanid726e1e2019-05-08 16:20:03499BrowserContext* SiteInstanceImpl::GetBrowserContext() {
Alex Moshchukf7488792019-03-11 22:37:57500 return browsing_instance_->GetBrowserContext();
[email protected]72daaa92012-01-18 13:39:02501}
502
nickcc0d9142015-10-14 16:27:10503// static
dchengbccd6b82016-03-30 16:24:19504scoped_refptr<SiteInstance> SiteInstance::Create(
505 BrowserContext* browser_context) {
Lukasz Anforowicz4726a172018-10-15 21:25:10506 DCHECK(browser_context);
dchengbccd6b82016-03-30 16:24:19507 return SiteInstanceImpl::Create(browser_context);
initial.commit09911bf2008-07-26 23:55:29508}
509
nickcc0d9142015-10-14 16:27:10510// static
dchengbccd6b82016-03-30 16:24:19511scoped_refptr<SiteInstance> SiteInstance::CreateForURL(
512 BrowserContext* browser_context,
513 const GURL& url) {
Lukasz Anforowicz4726a172018-10-15 21:25:10514 DCHECK(browser_context);
dchengbccd6b82016-03-30 16:24:19515 return SiteInstanceImpl::CreateForURL(browser_context, url);
[email protected]d8a96622009-05-07 19:21:16516}
517
nickcc0d9142015-10-14 16:27:10518// static
Nasko Oskovdeb6c7ea2017-11-30 18:18:11519bool SiteInstance::ShouldAssignSiteForURL(const GURL& url) {
520 return SiteInstanceImpl::ShouldAssignSiteForURL(url);
521}
522
Alex Moshchuk78cf66bda2018-11-30 01:49:30523bool SiteInstanceImpl::IsSameSiteWithURL(const GURL& url) {
Aaron Colwell6fee3f52019-05-08 21:35:02524 if (IsDefaultSiteInstance()) {
Aaron Colwelle953e562019-07-24 16:47:36525 // about:blank URLs should always be considered same site just like they are
526 // in IsSameWebSite().
527 if (url.IsAboutBlank())
528 return true;
529
Aaron Colwell6fee3f52019-05-08 21:35:02530 // Consider |url| the same site if it could be handled by the
531 // default SiteInstance and we don't already have a SiteInstance for
532 // this URL.
533 // TODO(acolwell): Remove HasSiteInstance() call once we have a way to
534 // prevent SiteInstances with no site URL from being used for URLs
535 // that should be routed to the default SiteInstance.
536 DCHECK_EQ(site_, GetDefaultSiteURL());
537 return site_ == GetSiteForURLInternal(GetIsolationContext(), url,
538 true /* should_use_effective_urls */,
539 true /* allow_default_site_url */) &&
540 !browsing_instance_->HasSiteInstance(url);
541 }
542
Alex Moshchuk78cf66bda2018-11-30 01:49:30543 return SiteInstanceImpl::IsSameWebSite(
Lukasz Anforowicz1a0a89a2019-03-29 22:31:02544 GetIsolationContext(), site_, url,
545 true /* should_compare_effective_urls */);
Alex Moshchuk25c64bb2017-12-02 02:50:11546}
547
Aaron Colwell6fee3f52019-05-08 21:35:02548bool SiteInstanceImpl::IsOriginalUrlSameSite(
549 const GURL& dest_url,
550 bool should_compare_effective_urls) {
551 if (IsDefaultSiteInstance())
552 return IsSameSiteWithURL(dest_url);
553
554 return IsSameWebSite(GetIsolationContext(), original_url_, dest_url,
555 should_compare_effective_urls);
556}
557
Alex Moshchuk78cf66bda2018-11-30 01:49:30558// static
Lukasz Anforowicz1a0a89a2019-03-29 22:31:02559bool SiteInstanceImpl::IsSameWebSite(const IsolationContext& isolation_context,
Alex Moshchuk25c64bb2017-12-02 02:50:11560 const GURL& real_src_url,
561 const GURL& real_dest_url,
562 bool should_compare_effective_urls) {
Lukasz Anforowicz1a0a89a2019-03-29 22:31:02563 DCHECK_CURRENTLY_ON(BrowserThread::UI);
564 BrowserContext* browser_context =
565 isolation_context.browser_or_resource_context().ToBrowserContext();
Lukasz Anforowicz4726a172018-10-15 21:25:10566 DCHECK(browser_context);
Aaron Colwell6fee3f52019-05-08 21:35:02567 DCHECK_NE(real_src_url, GetDefaultSiteURL());
Lukasz Anforowicz4726a172018-10-15 21:25:10568
Alex Moshchuk25c64bb2017-12-02 02:50:11569 GURL src_url =
570 should_compare_effective_urls
571 ? SiteInstanceImpl::GetEffectiveURL(browser_context, real_src_url)
572 : real_src_url;
573 GURL dest_url =
574 should_compare_effective_urls
575 ? SiteInstanceImpl::GetEffectiveURL(browser_context, real_dest_url)
576 : real_dest_url;
[email protected]399583b2012-12-11 09:33:42577
578 // We infer web site boundaries based on the registered domain name of the
579 // top-level page and the scheme. We do not pay attention to the port if
580 // one is present, because pages served from different ports can still
581 // access each other if they change their document.domain variable.
582
583 // Some special URLs will match the site instance of any other URL. This is
584 // done before checking both of them for validity, since we want these URLs
585 // to have the same site instance as even an invalid one.
[email protected]855d7d572014-08-02 11:18:17586 if (IsRendererDebugURL(src_url) || IsRendererDebugURL(dest_url))
[email protected]399583b2012-12-11 09:33:42587 return true;
588
589 // If either URL is invalid, they aren't part of the same site.
[email protected]855d7d572014-08-02 11:18:17590 if (!src_url.is_valid() || !dest_url.is_valid())
[email protected]399583b2012-12-11 09:33:42591 return false;
592
[email protected]855d7d572014-08-02 11:18:17593 // If the destination url is just a blank page, we treat them as part of the
594 // same site.
Mohamed Abdelhalim9e868ca42019-04-25 16:53:29595 if (dest_url.IsAboutBlank())
[email protected]855d7d572014-08-02 11:18:17596 return true;
597
Alex Moshchuka308c9b2018-02-08 20:58:14598 // If the source and destination URLs are equal excluding the hash, they have
599 // the same site. This matters for file URLs, where SameDomainOrHost() would
600 // otherwise return false below.
601 if (src_url.EqualsIgnoringRef(dest_url))
602 return true;
603
Daniel Cheng88186bd52017-10-20 08:14:46604 url::Origin src_origin = url::Origin::Create(src_url);
605 url::Origin dest_origin = url::Origin::Create(dest_url);
alexmos3b9ad102017-05-26 23:41:08606
[email protected]399583b2012-12-11 09:33:42607 // If the schemes differ, they aren't part of the same site.
alexmoscbf995782017-06-01 03:13:13608 if (src_origin.scheme() != dest_origin.scheme())
[email protected]399583b2012-12-11 09:33:42609 return false;
610
W. James MacLeanf79c97e2019-05-02 20:35:46611 if (SiteIsolationPolicy::IsStrictOriginIsolationEnabled())
612 return src_origin == dest_origin;
613
alexmos4bc26322017-07-01 00:57:14614 if (!net::registry_controlled_domains::SameDomainOrHost(
615 src_origin, dest_origin,
616 net::registry_controlled_domains::INCLUDE_PRIVATE_REGISTRIES)) {
617 return false;
618 }
619
620 // If the sites are the same, check isolated origins. If either URL matches
Alex Moshchuk4e19b362018-09-10 21:14:36621 // an isolated origin, compare origins rather than sites. As an optimization
622 // to avoid unneeded isolated origin lookups, shortcut this check if the two
623 // origins are the same.
624 if (src_origin == dest_origin)
625 return true;
alexmos4bc26322017-07-01 00:57:14626 auto* policy = ChildProcessSecurityPolicyImpl::GetInstance();
627 url::Origin src_isolated_origin;
628 url::Origin dest_isolated_origin;
Alex Moshchuk8e5c1952019-01-15 03:39:50629 bool src_origin_is_isolated = policy->GetMatchingIsolatedOrigin(
630 isolation_context, src_origin, &src_isolated_origin);
631 bool dest_origin_is_isolated = policy->GetMatchingIsolatedOrigin(
632 isolation_context, dest_origin, &dest_isolated_origin);
alexmos4bc26322017-07-01 00:57:14633 if (src_origin_is_isolated || dest_origin_is_isolated) {
634 // Compare most specific matching origins to ensure that a subdomain of an
635 // isolated origin (e.g., https://subdomain.isolated.foo.com) also matches
636 // the isolated origin's site URL (e.g., https://isolated.foo.com).
637 return src_isolated_origin == dest_isolated_origin;
638 }
639
640 return true;
[email protected]399583b2012-12-11 09:33:42641}
642
Aaron Colwellf45e3a852019-06-06 00:48:27643bool SiteInstanceImpl::DoesSiteForURLMatch(const GURL& url) {
644 // Note: The |allow_default_site_url| value used here MUST match the value
645 // used in CreateForURL().
646 return site_ == GetSiteForURLInternal(GetIsolationContext(), url,
647 true /* should_use_effective_urls */,
648 ShouldAllowDefaultSiteInstance());
649}
650
nickcc0d9142015-10-14 16:27:10651// static
[email protected]399583b2012-12-11 09:33:42652GURL SiteInstance::GetSiteForURL(BrowserContext* browser_context,
Alex Moshchuk5f926a52018-08-29 20:57:30653 const GURL& url) {
Aaron Colwellea6921f2019-01-29 16:50:39654 DCHECK_CURRENTLY_ON(BrowserThread::UI);
655 DCHECK(browser_context);
656
Aaron Colwell3acea722019-04-24 21:54:43657 // By default, GetSiteForURL will resolve |url| to an effective URL
658 // before computing its site.
Alex Moshchuk8e5c1952019-01-15 03:39:50659 //
660 // TODO(alexmos): Callers inside content/ should already be using the
661 // internal SiteInstanceImpl version and providing a proper IsolationContext.
662 // For callers outside content/, plumb the applicable IsolationContext here,
663 // where needed. Eventually, GetSiteForURL should always require an
664 // IsolationContext to be passed in, and this implementation should just
665 // become SiteInstanceImpl::GetSiteForURL.
Aaron Colwell3acea722019-04-24 21:54:43666 return SiteInstanceImpl::GetSiteForURL(IsolationContext(browser_context),
667 url);
Alex Moshchuk5f926a52018-08-29 20:57:30668}
669
670// static
Alex Moshchuk8e5c1952019-01-15 03:39:50671GURL SiteInstanceImpl::DetermineProcessLockURL(
Alex Moshchuk8e5c1952019-01-15 03:39:50672 const IsolationContext& isolation_context,
673 const GURL& url) {
Alex Moshchuk5f926a52018-08-29 20:57:30674 // For the process lock URL, convert |url| to a site without resolving |url|
675 // to an effective URL.
Aaron Colwell3acea722019-04-24 21:54:43676 return SiteInstanceImpl::GetSiteForURLInternal(
Aaron Colwell6fee3f52019-05-08 21:35:02677 isolation_context, url, false /* should_use_effective_urls */,
678 false /* allow_default_site_url */);
Alex Moshchuk5f926a52018-08-29 20:57:30679}
680
Aaron Colwellea6921f2019-01-29 16:50:39681// static
Alex Moshchukf7488792019-03-11 22:37:57682GURL SiteInstanceImpl::GetSiteForURL(const IsolationContext& isolation_context,
Aaron Colwell3acea722019-04-24 21:54:43683 const GURL& real_url) {
684 return GetSiteForURLInternal(isolation_context, real_url,
Aaron Colwell6fee3f52019-05-08 21:35:02685 true /* should_use_effective_urls */,
686 false /* allow_default_site_url */);
Aaron Colwell3acea722019-04-24 21:54:43687}
688
689// static
690GURL SiteInstanceImpl::GetSiteForURLInternal(
691 const IsolationContext& isolation_context,
692 const GURL& real_url,
Aaron Colwell6fee3f52019-05-08 21:35:02693 bool should_use_effective_urls,
694 bool allow_default_site_url) {
[email protected]25a9e8e532012-06-22 06:16:28695 // TODO(fsamuel, creis): For some reason appID is not recognized as a host.
[email protected]6eb1a11e2013-10-09 00:54:37696 if (real_url.SchemeIs(kGuestScheme))
[email protected]25a9e8e532012-06-22 06:16:28697 return real_url;
698
Aaron Colwellea6921f2019-01-29 16:50:39699 if (should_use_effective_urls)
700 DCHECK_CURRENTLY_ON(BrowserThread::UI);
701
Alex Moshchuk5f926a52018-08-29 20:57:30702 GURL url = should_use_effective_urls
Alex Moshchukf7488792019-03-11 22:37:57703 ? SiteInstanceImpl::GetEffectiveURL(
704 isolation_context.browser_or_resource_context()
705 .ToBrowserContext(),
706 real_url)
Alex Moshchuk5f926a52018-08-29 20:57:30707 : real_url;
Daniel Cheng88186bd52017-10-20 08:14:46708 url::Origin origin = url::Origin::Create(url);
[email protected]3a8eecb2010-04-22 23:56:30709
Lukasz Anforowicz48097c42017-12-15 00:23:38710 // If the url has a host, then determine the site. Skip file URLs to avoid a
711 // situation where site URL of file://localhost/ would mismatch Blink's origin
712 // (which ignores the hostname in this case - see https://crbug.com/776160).
Aaron Colwell6fee3f52019-05-08 21:35:02713 GURL site_url;
Lukasz Anforowicz48097c42017-12-15 00:23:38714 if (!origin.host().empty() && origin.scheme() != url::kFileScheme) {
Alex Moshchuk12ce6c792019-05-10 00:32:09715 // For Strict Origin Isolation, use the full origin instead of site for all
716 // HTTP/HTTPS URLs. Note that the HTTP/HTTPS restriction guarantees that
717 // we won't hit this for hosted app effective URLs, which would otherwise
718 // need to append a non-translated site URL to the hash below (see
719 // https://crbug.com/961386).
720 if (SiteIsolationPolicy::IsStrictOriginIsolationEnabled() &&
721 origin.GetURL().SchemeIsHTTPOrHTTPS())
W. James MacLeanf79c97e2019-05-02 20:35:46722 return origin.GetURL();
723
Aaron Colwell6fee3f52019-05-08 21:35:02724 site_url = GetSiteForOrigin(origin);
Alex Moshchuk4e19b362018-09-10 21:14:36725
726 // Isolated origins should use the full origin as their site URL. A
727 // subdomain of an isolated origin should also use that isolated origin's
728 // site URL. It is important to check |origin| (based on |url|) rather than
729 // |real_url| here, since some effective URLs (such as for NTP) need to be
730 // resolved prior to the isolated origin lookup.
731 auto* policy = ChildProcessSecurityPolicyImpl::GetInstance();
732 url::Origin isolated_origin;
Alex Moshchuk8e5c1952019-01-15 03:39:50733 if (policy->GetMatchingIsolatedOrigin(isolation_context, origin, site_url,
734 &isolated_origin))
Alex Moshchuk4e19b362018-09-10 21:14:36735 return isolated_origin.GetURL();
Alex Moshchuk5f926a52018-08-29 20:57:30736
737 // If an effective URL was used, augment the effective site URL with the
738 // underlying web site in the hash. This is needed to keep
739 // navigations across sites covered by one hosted app in separate
740 // SiteInstances. See https://crbug.com/791796.
741 //
742 // TODO(https://crbug.com/734722): Consider replacing this hack with
743 // a proper security principal.
744 if (should_use_effective_urls && url != real_url) {
Alex Moshchuk4e19b362018-09-10 21:14:36745 std::string non_translated_site_url(
Aaron Colwell3acea722019-04-24 21:54:43746 GetSiteForURLInternal(isolation_context, real_url,
Aaron Colwell6fee3f52019-05-08 21:35:02747 false /* should_use_effective_urls */,
748 allow_default_site_url)
Alex Moshchuk4e19b362018-09-10 21:14:36749 .spec());
750 GURL::Replacements replacements;
751 replacements.SetRefStr(non_translated_site_url.c_str());
752 site_url = site_url.ReplaceComponents(replacements);
Alex Moshchuk5f926a52018-08-29 20:57:30753 }
Aaron Colwell6fee3f52019-05-08 21:35:02754 } else {
755 // If there is no host but there is a scheme, return the scheme.
756 // This is useful for cases like file URLs.
757 if (!origin.opaque()) {
758 // Prefer to use the scheme of |origin| rather than |url|, to correctly
759 // cover blob:file: and filesystem:file: URIs (see also
760 // https://crbug.com/697111).
761 DCHECK(!origin.scheme().empty());
762 site_url = GURL(origin.scheme() + ":");
763 } else if (url.has_scheme()) {
764 // In some cases, it is not safe to use just the scheme as a site URL, as
765 // that might allow two URLs created by different sites to share a
766 // process. See https://crbug.com/863623 and https://crbug.com/863069.
767 //
768 // TODO(alexmos,creis): This should eventually be expanded to certain
769 // other schemes, such as file:.
770 // TODO(creis): This currently causes problems with tests on Android and
771 // Android WebView. For now, skip it when Site Isolation is not enabled,
772 // since there's no need to isolate data and blob URLs from each other in
773 // that case.
774 bool is_site_isolation_enabled =
775 SiteIsolationPolicy::UseDedicatedProcessesForAllSites() ||
776 SiteIsolationPolicy::AreIsolatedOriginsEnabled();
777 if (is_site_isolation_enabled &&
778 (url.SchemeIsBlob() || url.scheme() == url::kDataScheme)) {
779 // We get here for blob URLs of form blob:null/guid. Use the full URL
780 // with the guid in that case, which isolates all blob URLs with unique
781 // origins from each other. We also get here for browser-initiated
782 // navigations to data URLs, which have a unique origin and should only
783 // share a process when they are identical. Remove hash from the URL in
784 // either case, since same-document navigations shouldn't use a
785 // different site URL.
786 if (url.has_ref()) {
787 GURL::Replacements replacements;
788 replacements.ClearRef();
789 url = url.ReplaceComponents(replacements);
790 }
791 site_url = url;
792 } else {
793 DCHECK(!url.scheme().empty());
794 site_url = GURL(url.scheme() + ":");
Alex Moshchukb1f87482018-07-19 01:51:51795 }
Aaron Colwell6fee3f52019-05-08 21:35:02796 } else {
797 // Otherwise the URL should be invalid; return an empty site.
798 DCHECK(!url.is_valid()) << url;
799 return GURL();
Alex Moshchukb1f87482018-07-19 01:51:51800 }
Lukasz Anforowiczd926a842018-03-09 01:50:45801 }
creisf60c2cd2014-12-18 00:41:02802
Aaron Colwell6fee3f52019-05-08 21:35:02803 if (allow_default_site_url &&
Aaron Colwell8bb0ada2019-07-18 22:41:23804 CanBePlacedInDefaultSiteInstance(isolation_context, url, site_url)) {
Aaron Colwell6fee3f52019-05-08 21:35:02805 return GetDefaultSiteURL();
806 }
807 return site_url;
initial.commit09911bf2008-07-26 23:55:29808}
809
nickcc0d9142015-10-14 16:27:10810// static
Aaron Colwell8bb0ada2019-07-18 22:41:23811bool SiteInstanceImpl::CanBePlacedInDefaultSiteInstance(
812 const IsolationContext& isolation_context,
813 const GURL& url,
814 const GURL& site_url) {
Clark DuVall4e1f0a72019-08-07 22:41:42815 DCHECK_CURRENTLY_ON(BrowserThread::UI);
Aaron Colwell8bb0ada2019-07-18 22:41:23816 // Exclude "chrome-guest:" URLs from the default SiteInstance to ensure that
817 // guest specific process selection, process swapping, and storage partition
818 // behavior is preserved.
819 if (url.SchemeIs(kGuestScheme))
820 return false;
821
822 // Exclude "file://" URLs from the default SiteInstance to prevent the
823 // default SiteInstance process from accumulating file access grants that
824 // could be exploited by other non-isolated sites.
825 if (url.SchemeIs(url::kFileScheme))
826 return false;
827
828 // Don't use the default SiteInstance when
829 // kProcessSharingWithStrictSiteInstances is enabled because we want each
830 // site to have its own SiteInstance object and logic elsewhere ensures
831 // that those SiteInstances share a process.
832 if (base::FeatureList::IsEnabled(
833 features::kProcessSharingWithStrictSiteInstances)) {
834 return false;
835 }
836
837 // Don't use the default SiteInstance when SiteInstance doesn't assign a
838 // site URL for |url|, since in that case the SiteInstance should remain
839 // unused, and a subsequent navigation should always be able to reuse it,
840 // whether or not it's to a site requiring a dedicated process or to a site
841 // that will use the default SiteInstance.
842 if (!ShouldAssignSiteForURL(url))
843 return false;
844
845 // Allow the default SiteInstance to be used for sites that don't need to be
846 // isolated in their own process.
847 return !DoesSiteURLRequireDedicatedProcess(isolation_context, site_url);
848}
849
850// static
Alex Moshchuk4e19b362018-09-10 21:14:36851GURL SiteInstanceImpl::GetSiteForOrigin(const url::Origin& origin) {
852 // Only keep the scheme and registered domain of |origin|.
853 std::string domain = net::registry_controlled_domains::GetDomainAndRegistry(
854 origin.host(),
855 net::registry_controlled_domains::INCLUDE_PRIVATE_REGISTRIES);
856 std::string site = origin.scheme();
857 site += url::kStandardSchemeSeparator;
858 site += domain.empty() ? origin.host() : domain;
859 return GURL(site);
860}
861
862// static
[email protected]4c3a23582012-08-18 08:54:34863GURL SiteInstanceImpl::GetEffectiveURL(BrowserContext* browser_context,
864 const GURL& url) {
Aaron Colwellea6921f2019-01-29 16:50:39865 DCHECK(browser_context);
Alex Moshchuka31c7882018-01-17 00:57:30866 return GetContentClient()->browser()->GetEffectiveURL(browser_context, url);
[email protected]3a8eecb2010-04-22 23:56:30867}
868
nickcc0d9142015-10-14 16:27:10869// static
Alex Moshchuk25c64bb2017-12-02 02:50:11870bool SiteInstanceImpl::HasEffectiveURL(BrowserContext* browser_context,
871 const GURL& url) {
872 return GetEffectiveURL(browser_context, url) != url;
873}
874
875// static
nickcc0d9142015-10-14 16:27:10876bool SiteInstanceImpl::DoesSiteRequireDedicatedProcess(
Alex Moshchuk8e5c1952019-01-15 03:39:50877 const IsolationContext& isolation_context,
nickdb193a12016-09-09 23:09:23878 const GURL& url) {
Clark DuVall4e1f0a72019-08-07 22:41:42879 DCHECK_CURRENTLY_ON(BrowserThread::UI);
Aaron Colwell5080de62019-05-06 23:02:03880 return SiteIsolationPolicy::UseDedicatedProcessesForAllSites() ||
881 DoesSiteURLRequireDedicatedProcess(
882 isolation_context,
883 SiteInstanceImpl::GetSiteForURL(isolation_context, url));
884}
885
886// static
887bool SiteInstanceImpl::DoesSiteURLRequireDedicatedProcess(
888 const IsolationContext& isolation_context,
889 const GURL& site_url) {
Clark DuVall4e1f0a72019-08-07 22:41:42890 DCHECK_CURRENTLY_ON(BrowserThread::UI);
Lukasz Anforowicz4aff3b82019-04-04 16:00:33891 DCHECK(isolation_context.browser_or_resource_context());
Lukasz Anforowicz4726a172018-10-15 21:25:10892
nickcc0d9142015-10-14 16:27:10893 // If --site-per-process is enabled, site isolation is enabled everywhere.
894 if (SiteIsolationPolicy::UseDedicatedProcessesForAllSites())
895 return true;
896
alexmos3b9ad102017-05-26 23:41:08897 // Always require a dedicated process for isolated origins.
alexmos3b9ad102017-05-26 23:41:08898 auto* policy = ChildProcessSecurityPolicyImpl::GetInstance();
Alex Moshchuk8e5c1952019-01-15 03:39:50899 if (policy->IsIsolatedOrigin(isolation_context,
900 url::Origin::Create(site_url)))
alexmos3b9ad102017-05-26 23:41:08901 return true;
902
Lukasz Anforowicz1f5ad402018-09-28 23:57:54903 // Error pages in main frames do require isolation, however since this is
904 // missing the context whether this is for a main frame or not, that part
905 // is enforced in RenderFrameHostManager.
906 if (site_url.SchemeIs(kChromeErrorScheme))
907 return true;
908
Aaron Colwell7be742612019-08-22 18:25:12909 // Isolate WebUI pages from one another and from other kinds of schemes.
910 for (const auto& webui_scheme : URLDataManagerBackend::GetWebUISchemes()) {
911 if (site_url.SchemeIs(webui_scheme))
912 return true;
913 }
Lukasz Anforowicz1f5ad402018-09-28 23:57:54914
nickdb193a12016-09-09 23:09:23915 // Let the content embedder enable site isolation for specific URLs. Use the
916 // canonical site url for this check, so that schemes with nested origins
917 // (blob and filesystem) work properly.
Avi Drissman8c36df72017-12-11 21:19:20918 if (GetContentClient()->browser()->DoesSiteRequireDedicatedProcess(
Clark DuVall4e1f0a72019-08-07 22:41:42919 isolation_context.browser_or_resource_context().ToBrowserContext(),
920 site_url)) {
nickcc0d9142015-10-14 16:27:10921 return true;
922 }
923
924 return false;
925}
926
alexmos13fe1962017-06-28 04:25:12927// static
Alex Moshchuk8e5c1952019-01-15 03:39:50928bool SiteInstanceImpl::ShouldLockToOrigin(
Alex Moshchuk8e5c1952019-01-15 03:39:50929 const IsolationContext& isolation_context,
930 GURL site_url) {
Lukasz Anforowicz1a0a89a2019-03-29 22:31:02931 DCHECK_CURRENTLY_ON(BrowserThread::UI);
932 BrowserContext* browser_context =
933 isolation_context.browser_or_resource_context().ToBrowserContext();
Lukasz Anforowicz4726a172018-10-15 21:25:10934 DCHECK(browser_context);
935
creis0b49fa12017-07-10 16:31:11936 // Don't lock to origin in --single-process mode, since this mode puts
937 // cross-site pages into the same process.
Alex Moshchukd4c4ca32018-08-15 20:36:51938 if (RenderProcessHost::run_renderer_in_process())
creis0b49fa12017-07-10 16:31:11939 return false;
940
Aaron Colwell5080de62019-05-06 23:02:03941 if (!DoesSiteURLRequireDedicatedProcess(isolation_context, site_url))
alexmos13fe1962017-06-28 04:25:12942 return false;
943
944 // Guest processes cannot be locked to their site because guests always have
945 // a fixed SiteInstance. The site of GURLs a guest loads doesn't match that
946 // SiteInstance. So we skip locking the guest process to the site.
947 // TODO(ncarter): Remove this exclusion once we can make origin lock per
948 // RenderFrame routing id.
949 if (site_url.SchemeIs(content::kGuestScheme))
950 return false;
951
alexmos13fe1962017-06-28 04:25:12952 // TODO(creis, nick): Until we can handle sites with effective URLs at the
953 // call sites of ChildProcessSecurityPolicy::CanAccessDataForOrigin, we
954 // must give the embedder a chance to exempt some sites to avoid process
955 // kills.
956 if (!GetContentClient()->browser()->ShouldLockToOrigin(browser_context,
957 site_url)) {
958 return false;
959 }
960
961 return true;
962}
963
Lukasz Anforowicz27851e62018-12-18 23:04:08964// static
965base::Optional<url::Origin> SiteInstanceImpl::GetRequestInitiatorSiteLock(
Lukasz Anforowicz27851e62018-12-18 23:04:08966 GURL site_url) {
Lukasz Anforowicz27851e62018-12-18 23:04:08967 // The following schemes are safe for sites that require a process lock:
968 // - data: - locking |request_initiator| to an opaque origin
969 // - http/https - requiring |request_initiator| to match |site_url| with
970 // DomainIs (i.e. suffix-based) comparison.
971 if (site_url.SchemeIsHTTPOrHTTPS() || site_url.SchemeIs(url::kDataScheme))
972 return url::Origin::Create(site_url);
973
974 // Other schemes might not be safe to use as |request_initiator_site_lock|.
975 // One example is chrome-guest://...
976 return base::nullopt;
977}
978
[email protected]40bfaf32013-11-19 01:35:43979void SiteInstanceImpl::RenderProcessHostDestroyed(RenderProcessHost* host) {
980 DCHECK_EQ(process_, host);
981 process_->RemoveObserver(this);
nickd5bbd0b2016-03-31 19:52:44982 process_ = nullptr;
[email protected]4566f132009-03-12 01:55:13983}
[email protected]313b80bd2011-11-23 03:49:10984
Bo Liu2a489402018-04-24 23:41:27985void SiteInstanceImpl::RenderProcessExited(
986 RenderProcessHost* host,
987 const ChildProcessTerminationInfo& info) {
ericwilligers254597b2016-10-17 10:32:31988 for (auto& observer : observers_)
Hajime Hoshi3b2e4222019-10-10 10:17:07989 observer.RenderProcessGone(this, info);
nick9f34e2892016-01-12 21:01:07990}
991
alexmos13fe1962017-06-28 04:25:12992void SiteInstanceImpl::LockToOriginIfNeeded() {
993 DCHECK(HasSite());
994
995 // From now on, this process should be considered "tainted" for future
996 // process reuse decisions:
997 // (1) If |site_| required a dedicated process, this SiteInstance's process
998 // can only host URLs for the same site.
999 // (2) Even if |site_| does not require a dedicated process, this
1000 // SiteInstance's process still cannot be reused to host other sites
1001 // requiring dedicated sites in the future.
1002 // We can get here either when we commit a URL into a SiteInstance that does
1003 // not yet have a site, or when we create a process for a SiteInstance with a
1004 // preassigned site.
1005 process_->SetIsUsed();
1006
Alex Moshchuk47dd00f2017-10-10 17:15:231007 ChildProcessSecurityPolicyImpl* policy =
1008 ChildProcessSecurityPolicyImpl::GetInstance();
Alex Moshchuk58225c82019-04-18 00:45:011009 GURL process_lock = policy->GetOriginLock(process_->GetID());
Lukasz Anforowicz1a0a89a2019-03-29 22:31:021010 if (ShouldLockToOrigin(GetIsolationContext(), site_)) {
Alex Moshchuk9cf5a45d2017-08-14 18:50:571011 // Sanity check that this won't try to assign an origin lock to a <webview>
1012 // process, which can't be locked.
1013 CHECK(!process_->IsForGuestsOnly());
1014
Alex Moshchuk58225c82019-04-18 00:45:011015 if (process_lock.is_empty()) {
1016 // TODO(nick): When all sites are isolated, this operation provides
1017 // strong protection. If only some sites are isolated, we need
1018 // additional logic to prevent the non-isolated sites from requesting
1019 // resources for isolated sites. https://crbug.com/509125
1020 TRACE_EVENT2("navigation", "SiteInstanceImpl::LockToOrigin", "site id",
1021 id_, "lock", lock_url().possibly_invalid_spec());
1022 process_->LockToOrigin(GetIsolationContext(), lock_url());
1023 } else if (process_lock != lock_url()) {
1024 // We should never attempt to reassign a different origin lock to a
1025 // process.
1026 base::debug::SetCrashKeyString(bad_message::GetRequestedSiteURLKey(),
1027 site_.spec());
1028 base::debug::SetCrashKeyString(
1029 bad_message::GetKilledProcessOriginLockKey(), process_lock.spec());
1030 CHECK(false) << "Trying to lock a process to " << lock_url()
1031 << " but the process is already locked to " << process_lock;
1032 } else {
1033 // Process already has the right origin lock assigned. This case will
1034 // happen for commits to |site_| after the first one.
Alex Moshchuk9cf5a45d2017-08-14 18:50:571035 }
Alex Moshchuk47dd00f2017-10-10 17:15:231036 } else {
1037 // If the site that we've just committed doesn't require a dedicated
1038 // process, make sure we aren't putting it in a process for a site that
1039 // does.
Alex Moshchuk58225c82019-04-18 00:45:011040 if (!process_lock.is_empty()) {
Alex Moshchuk1656c672018-04-28 01:48:341041 base::debug::SetCrashKeyString(bad_message::GetRequestedSiteURLKey(),
1042 site_.spec());
1043 base::debug::SetCrashKeyString(
Alex Moshchuk58225c82019-04-18 00:45:011044 bad_message::GetKilledProcessOriginLockKey(), process_lock.spec());
Alex Moshchuk1656c672018-04-28 01:48:341045 CHECK(false) << "Trying to commit non-isolated site " << site_
Alex Moshchuk58225c82019-04-18 00:45:011046 << " in process locked to " << process_lock;
Alex Moshchuk1656c672018-04-28 01:48:341047 }
[email protected]313b80bd2011-11-23 03:49:101048 }
Lukasz Anforowicz38003582019-09-24 19:08:051049
1050 // Track which isolation contexts use the given process. This lets
1051 // ChildProcessSecurityPolicyImpl (e.g. CanAccessDataForOrigin) determine
1052 // whether a given URL should require a lock or not (a dynamically isolated
1053 // origin may require a lock in some isolation contexts but not in others).
1054 policy->IncludeIsolationContext(process_->GetID(), GetIsolationContext());
[email protected]313b80bd2011-11-23 03:49:101055}
[email protected]46488322012-10-30 03:22:201056
Alex Moshchuk07e1bb42019-03-08 04:44:081057// static
1058void SiteInstance::StartIsolatingSite(BrowserContext* context,
1059 const GURL& url) {
1060 if (!SiteIsolationPolicy::AreDynamicIsolatedOriginsEnabled())
1061 return;
1062
1063 // Ignore attempts to isolate origins that are not supported. Do this here
1064 // instead of relying on AddIsolatedOrigins()'s internal validation, to avoid
1065 // the runtime warning generated by the latter.
1066 url::Origin origin(url::Origin::Create(url));
1067 if (!IsolatedOriginUtil::IsValidIsolatedOrigin(origin))
1068 return;
1069
1070 // Convert |url| to a site, to avoid breaking document.domain. Note that
1071 // this doesn't use effective URL resolution or other special cases from
1072 // GetSiteForURL() and simply converts |origin| to a scheme and eTLD+1.
1073 GURL site(SiteInstanceImpl::GetSiteForOrigin(origin));
1074
1075 ChildProcessSecurityPolicyImpl* policy =
1076 ChildProcessSecurityPolicyImpl::GetInstance();
Alex Moshchuke256d562019-04-26 21:43:571077 url::Origin site_origin(url::Origin::Create(site));
Alex Moshchukc4679422019-06-11 17:04:481078 policy->AddIsolatedOrigins(
1079 {site_origin},
1080 ChildProcessSecurityPolicy::IsolatedOriginSource::USER_TRIGGERED,
1081 context);
Alex Moshchuke256d562019-04-26 21:43:571082
1083 // This function currently assumes the new isolated site should persist
1084 // across restarts, so ask the embedder to save it, excluding off-the-record
1085 // profiles.
1086 if (!context->IsOffTheRecord())
1087 GetContentClient()->browser()->PersistIsolatedOrigin(context, site_origin);
Alex Moshchuk07e1bb42019-03-08 04:44:081088}
1089
[email protected]46488322012-10-30 03:22:201090} // namespace content