blob: d8dea1784eca2fc5f4e7da3948bedc5899f876ce [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"
alexmos3b9ad102017-05-26 23:41:0811#include "base/macros.h"
avicb129c02017-05-03 06:49:2912#include "base/memory/ptr_util.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"
[email protected]f3b1a082011-11-18 00:34:3017#include "content/browser/renderer_host/render_process_host_impl.h"
Lukasz Anforowiczbb0cfd5e2017-12-14 22:39:4618#include "content/browser/site_isolation_policy.h"
[email protected]4c3a23582012-08-18 08:54:3419#include "content/browser/storage_partition_impl.h"
[email protected]87f3c082011-10-19 18:07:4420#include "content/public/browser/content_browser_client.h"
[email protected]f3b1a082011-11-18 00:34:3021#include "content/public/browser/render_process_host_factory.h"
[email protected]41fb79a52012-06-29 16:34:3322#include "content/public/browser/web_ui_controller_factory.h"
creis0b49fa12017-07-10 16:31:1123#include "content/public/common/content_switches.h"
[email protected]a1d29162011-10-14 17:14:0324#include "content/public/common/url_constants.h"
clamy7fced7b2017-11-16 19:52:4325#include "content/public/common/url_utils.h"
[email protected]be28b5f42012-07-20 11:31:2526#include "net/base/registry_controlled_domains/registry_controlled_domain.h"
initial.commit09911bf2008-07-26 23:55:2927
[email protected]46488322012-10-30 03:22:2028namespace content {
[email protected]b6583592012-01-25 19:52:3329
avib7348942015-12-25 20:57:1030int32_t SiteInstanceImpl::next_site_instance_id_ = 1;
[email protected]992db4c2011-05-12 15:37:1531
[email protected]b6583592012-01-25 19:52:3332SiteInstanceImpl::SiteInstanceImpl(BrowsingInstance* browsing_instance)
[email protected]992db4c2011-05-12 15:37:1533 : id_(next_site_instance_id_++),
creiscce56cd2014-09-29 22:45:2234 active_frame_count_(0),
[email protected]992db4c2011-05-12 15:37:1535 browsing_instance_(browsing_instance),
nickd5bbd0b2016-03-31 19:52:4436 process_(nullptr),
37 has_site_(false),
Tsuyoshi Horoeb576e62017-06-28 06:00:4138 process_reuse_policy_(ProcessReusePolicy::DEFAULT),
39 is_for_service_worker_(false) {
[email protected]4566f132009-03-12 01:55:1340 DCHECK(browsing_instance);
[email protected]4566f132009-03-12 01:55:1341}
42
[email protected]b6583592012-01-25 19:52:3343SiteInstanceImpl::~SiteInstanceImpl() {
[email protected]46488322012-10-30 03:22:2044 GetContentClient()->browser()->SiteInstanceDeleting(this);
[email protected]056ad2a2011-07-12 02:13:5545
[email protected]40bfaf32013-11-19 01:35:4346 if (process_)
47 process_->RemoveObserver(this);
48
initial.commit09911bf2008-07-26 23:55:2949 // Now that no one is referencing us, we can safely remove ourselves from
50 // the BrowsingInstance. Any future visits to a page from this site
51 // (within the same BrowsingInstance) can safely create a new SiteInstance.
52 if (has_site_)
dchengbccd6b82016-03-30 16:24:1953 browsing_instance_->UnregisterSiteInstance(this);
54}
55
Nasko Oskovdeb6c7ea2017-11-30 18:18:1156// static
dchengbccd6b82016-03-30 16:24:1957scoped_refptr<SiteInstanceImpl> SiteInstanceImpl::Create(
58 BrowserContext* browser_context) {
kylecharda69d882017-10-04 05:49:5259 return base::WrapRefCounted(
dchengbccd6b82016-03-30 16:24:1960 new SiteInstanceImpl(new BrowsingInstance(browser_context)));
61}
62
Nasko Oskovdeb6c7ea2017-11-30 18:18:1163// static
dchengbccd6b82016-03-30 16:24:1964scoped_refptr<SiteInstanceImpl> SiteInstanceImpl::CreateForURL(
65 BrowserContext* browser_context,
66 const GURL& url) {
67 // This will create a new SiteInstance and BrowsingInstance.
68 scoped_refptr<BrowsingInstance> instance(
69 new BrowsingInstance(browser_context));
70 return instance->GetSiteInstanceForURL(url);
initial.commit09911bf2008-07-26 23:55:2971}
72
Nasko Oskovdeb6c7ea2017-11-30 18:18:1173// static
74bool SiteInstanceImpl::ShouldAssignSiteForURL(const GURL& url) {
75 // about:blank should not "use up" a new SiteInstance. The SiteInstance can
76 // still be used for a normal web site.
77 if (url == url::kAboutBlankURL)
78 return false;
79
80 // The embedder will then have the opportunity to determine if the URL
81 // should "use up" the SiteInstance.
82 return GetContentClient()->browser()->ShouldAssignSiteForURL(url);
83}
84
avib7348942015-12-25 20:57:1085int32_t SiteInstanceImpl::GetId() {
[email protected]b6583592012-01-25 19:52:3386 return id_;
87}
88
89bool SiteInstanceImpl::HasProcess() const {
Ivan Kotenkov2c0d2bb32017-11-01 15:41:2890 if (process_ != nullptr)
[email protected]41fb79a52012-06-29 16:34:3391 return true;
92
93 // If we would use process-per-site for this site, also check if there is an
94 // existing process that we would use if GetProcess() were called.
[email protected]46488322012-10-30 03:22:2095 BrowserContext* browser_context =
[email protected]41fb79a52012-06-29 16:34:3396 browsing_instance_->browser_context();
97 if (has_site_ &&
[email protected]1ae93fb12013-06-14 03:38:5698 RenderProcessHost::ShouldUseProcessPerSite(browser_context, site_) &&
[email protected]41fb79a52012-06-29 16:34:3399 RenderProcessHostImpl::GetProcessHostForSite(browser_context, site_)) {
100 return true;
101 }
102
103 return false;
[email protected]5ab79b02010-04-26 16:47:11104}
105
[email protected]41fb79a52012-06-29 16:34:33106RenderProcessHost* SiteInstanceImpl::GetProcess() {
[email protected]08c8ec7e2010-07-11 17:14:48107 // TODO(erikkay) It would be nice to ensure that the renderer type had been
108 // properly set before we get here. The default tab creation case winds up
109 // with no site set at this point, so it will default to TYPE_NORMAL. This
110 // may not be correct, so we'll wind up potentially creating a process that
111 // we then throw away, or worse sharing a process with the wrong process type.
112 // See crbug.com/43448.
113
initial.commit09911bf2008-07-26 23:55:29114 // Create a new process if ours went away or was reused.
[email protected]4566f132009-03-12 01:55:13115 if (!process_) {
[email protected]4c3a23582012-08-18 08:54:34116 BrowserContext* browser_context = browsing_instance_->browser_context();
[email protected]41fb79a52012-06-29 16:34:33117
clamy63960c32017-05-10 22:57:07118 // Check if the ProcessReusePolicy should be updated.
119 bool should_use_process_per_site =
creisa9f04ba2017-05-19 22:27:42120 has_site_ &&
121 RenderProcessHost::ShouldUseProcessPerSite(browser_context, site_);
clamy63960c32017-05-10 22:57:07122 if (should_use_process_per_site) {
123 process_reuse_policy_ = ProcessReusePolicy::PROCESS_PER_SITE;
124 } else if (process_reuse_policy_ == ProcessReusePolicy::PROCESS_PER_SITE) {
125 process_reuse_policy_ = ProcessReusePolicy::DEFAULT;
[email protected]41fb79a52012-06-29 16:34:33126 }
127
clamy63960c32017-05-10 22:57:07128 process_ = RenderProcessHostImpl::GetProcessHostForSiteInstance(
129 browser_context, this);
avi6d686db2017-01-06 02:28:57130
[email protected]41fb79a52012-06-29 16:34:33131 CHECK(process_);
[email protected]40bfaf32013-11-19 01:35:43132 process_->AddObserver(this);
[email protected]41fb79a52012-06-29 16:34:33133
134 // If we are using process-per-site, we need to register this process
135 // for the current site so that we can find it again. (If no site is set
136 // at this time, we will register it in SetSite().)
clamy63960c32017-05-10 22:57:07137 if (process_reuse_policy_ == ProcessReusePolicy::PROCESS_PER_SITE &&
138 has_site_) {
[email protected]41fb79a52012-06-29 16:34:33139 RenderProcessHostImpl::RegisterProcessHostForSite(browser_context,
140 process_, site_);
141 }
initial.commit09911bf2008-07-26 23:55:29142
naskob8744d22014-08-28 17:07:43143 TRACE_EVENT2("navigation", "SiteInstanceImpl::GetProcess",
144 "site id", id_, "process id", process_->GetID());
[email protected]46488322012-10-30 03:22:20145 GetContentClient()->browser()->SiteInstanceGotProcess(this);
[email protected]6f371442011-11-09 06:45:46146
[email protected]313b80bd2011-11-23 03:49:10147 if (has_site_)
alexmos13fe1962017-06-28 04:25:12148 LockToOriginIfNeeded();
initial.commit09911bf2008-07-26 23:55:29149 }
[email protected]4566f132009-03-12 01:55:13150 DCHECK(process_);
initial.commit09911bf2008-07-26 23:55:29151
[email protected]4566f132009-03-12 01:55:13152 return process_;
initial.commit09911bf2008-07-26 23:55:29153}
154
[email protected]b6583592012-01-25 19:52:33155void SiteInstanceImpl::SetSite(const GURL& url) {
naskob8744d22014-08-28 17:07:43156 TRACE_EVENT2("navigation", "SiteInstanceImpl::SetSite",
157 "site id", id_, "url", url.possibly_invalid_spec());
initial.commit09911bf2008-07-26 23:55:29158 // A SiteInstance's site should not change.
159 // TODO(creis): When following links or script navigations, we can currently
160 // render pages from other sites in this SiteInstance. This will eventually
161 // be fixed, but until then, we should still not set the site of a
162 // SiteInstance more than once.
163 DCHECK(!has_site_);
164
165 // Remember that this SiteInstance has been used to load a URL, even if the
166 // URL is invalid.
167 has_site_ = true;
[email protected]4c3a23582012-08-18 08:54:34168 BrowserContext* browser_context = browsing_instance_->browser_context();
[email protected]41fb79a52012-06-29 16:34:33169 site_ = GetSiteForURL(browser_context, url);
Alex Moshchuk25c64bb2017-12-02 02:50:11170 original_url_ = url;
initial.commit09911bf2008-07-26 23:55:29171
172 // Now that we have a site, register it with the BrowsingInstance. This
173 // ensures that we won't create another SiteInstance for this site within
174 // the same BrowsingInstance, because all same-site pages within a
175 // BrowsingInstance can script each other.
176 browsing_instance_->RegisterSiteInstance(this);
[email protected]313b80bd2011-11-23 03:49:10177
clamy63960c32017-05-10 22:57:07178 // Update the process reuse policy based on the site.
179 bool should_use_process_per_site =
180 RenderProcessHost::ShouldUseProcessPerSite(browser_context, site_);
181 if (should_use_process_per_site) {
182 process_reuse_policy_ = ProcessReusePolicy::PROCESS_PER_SITE;
183 }
184
[email protected]41fb79a52012-06-29 16:34:33185 if (process_) {
alexmos13fe1962017-06-28 04:25:12186 LockToOriginIfNeeded();
[email protected]41fb79a52012-06-29 16:34:33187
188 // Ensure the process is registered for this site if necessary.
clamy63960c32017-05-10 22:57:07189 if (should_use_process_per_site) {
[email protected]41fb79a52012-06-29 16:34:33190 RenderProcessHostImpl::RegisterProcessHostForSite(
191 browser_context, process_, site_);
192 }
193 }
initial.commit09911bf2008-07-26 23:55:29194}
195
[email protected]77ab17312012-09-28 15:34:59196const GURL& SiteInstanceImpl::GetSiteURL() const {
[email protected]b6583592012-01-25 19:52:33197 return site_;
198}
199
200bool SiteInstanceImpl::HasSite() const {
201 return has_site_;
202}
203
204bool SiteInstanceImpl::HasRelatedSiteInstance(const GURL& url) {
initial.commit09911bf2008-07-26 23:55:29205 return browsing_instance_->HasSiteInstance(url);
206}
207
dchengbccd6b82016-03-30 16:24:19208scoped_refptr<SiteInstance> SiteInstanceImpl::GetRelatedSiteInstance(
209 const GURL& url) {
initial.commit09911bf2008-07-26 23:55:29210 return browsing_instance_->GetSiteInstanceForURL(url);
211}
212
[email protected]14392a52012-05-02 20:28:44213bool SiteInstanceImpl::IsRelatedSiteInstance(const SiteInstance* instance) {
[email protected]fc72bb12013-06-02 21:13:46214 return browsing_instance_.get() == static_cast<const SiteInstanceImpl*>(
215 instance)->browsing_instance_.get();
[email protected]14392a52012-05-02 20:28:44216}
217
[email protected]d5072a82014-05-15 05:50:18218size_t SiteInstanceImpl::GetRelatedActiveContentsCount() {
219 return browsing_instance_->active_contents_count();
220}
221
[email protected]f88628d02012-11-11 17:58:59222bool SiteInstanceImpl::HasWrongProcessForURL(const GURL& url) {
[email protected]d292d8a2011-05-25 03:47:11223 // Having no process isn't a problem, since we'll assign it correctly.
[email protected]f88628d02012-11-11 17:58:59224 // Note that HasProcess() may return true if process_ is null, in
225 // process-per-site cases where there's an existing process available.
226 // We want to use such a process in the IsSuitableHost check, so we
227 // may end up assigning process_ in the GetProcess() call below.
228 if (!HasProcess())
[email protected]d292d8a2011-05-25 03:47:11229 return false;
230
[email protected]144a8102012-01-14 01:05:31231 // If the URL to navigate to can be associated with any site instance,
232 // we want to keep it in the same process.
[email protected]c02f1ba2014-02-03 06:53:53233 if (IsRendererDebugURL(url))
[email protected]144a8102012-01-14 01:05:31234 return false;
235
alexmos13fe1962017-06-28 04:25:12236 // Any process can host an about:blank URL. This check avoids a process
237 // transfer for browser-initiated navigations to about:blank in a dedicated
238 // process; without it, IsSuitableHost would consider this process unsuitable
239 // for about:blank when it compares origin locks. Renderer-initiated
240 // navigations will handle about:blank navigations elsewhere and leave them
241 // in the source SiteInstance, along with about:srcdoc and data:.
242 if (url == url::kAboutBlankURL)
243 return false;
244
[email protected]88aae972011-12-16 01:14:18245 // If the site URL is an extension (e.g., for hosted apps or WebUI) but the
[email protected]d292d8a2011-05-25 03:47:11246 // process is not (or vice versa), make sure we notice and fix it.
[email protected]2a5221b2011-09-27 23:07:31247 GURL site_url = GetSiteForURL(browsing_instance_->browser_context(), url);
[email protected]88aae972011-12-16 01:14:18248 return !RenderProcessHostImpl::IsSuitableHost(
[email protected]f88628d02012-11-11 17:58:59249 GetProcess(), browsing_instance_->browser_context(), site_url);
[email protected]d292d8a2011-05-25 03:47:11250}
251
nickd5bbd0b2016-03-31 19:52:44252scoped_refptr<SiteInstanceImpl>
253SiteInstanceImpl::GetDefaultSubframeSiteInstance() {
254 return browsing_instance_->GetDefaultSubframeSiteInstance();
255}
256
nickd30fd962015-07-27 21:51:08257bool SiteInstanceImpl::RequiresDedicatedProcess() {
258 if (!has_site_)
259 return false;
nickd5bbd0b2016-03-31 19:52:44260
261 return DoesSiteRequireDedicatedProcess(GetBrowserContext(), site_);
nickd30fd962015-07-27 21:51:08262}
263
avi85cacb72016-10-26 22:39:33264bool SiteInstanceImpl::IsDefaultSubframeSiteInstance() const {
clamy63960c32017-05-10 22:57:07265 return process_reuse_policy_ ==
266 ProcessReusePolicy::USE_DEFAULT_SUBFRAME_PROCESS;
avi85cacb72016-10-26 22:39:33267}
268
nick9f34e2892016-01-12 21:01:07269void SiteInstanceImpl::IncrementActiveFrameCount() {
270 active_frame_count_++;
271}
272
273void SiteInstanceImpl::DecrementActiveFrameCount() {
ericwilligers254597b2016-10-17 10:32:31274 if (--active_frame_count_ == 0) {
275 for (auto& observer : observers_)
276 observer.ActiveFrameCountIsZero(this);
277 }
nick9f34e2892016-01-12 21:01:07278}
279
[email protected]d5072a82014-05-15 05:50:18280void SiteInstanceImpl::IncrementRelatedActiveContentsCount() {
281 browsing_instance_->increment_active_contents_count();
282}
283
284void SiteInstanceImpl::DecrementRelatedActiveContentsCount() {
285 browsing_instance_->decrement_active_contents_count();
286}
287
nick9f34e2892016-01-12 21:01:07288void SiteInstanceImpl::AddObserver(Observer* observer) {
289 observers_.AddObserver(observer);
290}
291
292void SiteInstanceImpl::RemoveObserver(Observer* observer) {
293 observers_.RemoveObserver(observer);
294}
295
[email protected]4c3a23582012-08-18 08:54:34296BrowserContext* SiteInstanceImpl::GetBrowserContext() const {
[email protected]72daaa92012-01-18 13:39:02297 return browsing_instance_->browser_context();
298}
299
nickcc0d9142015-10-14 16:27:10300// static
dchengbccd6b82016-03-30 16:24:19301scoped_refptr<SiteInstance> SiteInstance::Create(
302 BrowserContext* browser_context) {
303 return SiteInstanceImpl::Create(browser_context);
initial.commit09911bf2008-07-26 23:55:29304}
305
nickcc0d9142015-10-14 16:27:10306// static
dchengbccd6b82016-03-30 16:24:19307scoped_refptr<SiteInstance> SiteInstance::CreateForURL(
308 BrowserContext* browser_context,
309 const GURL& url) {
310 return SiteInstanceImpl::CreateForURL(browser_context, url);
[email protected]d8a96622009-05-07 19:21:16311}
312
nickcc0d9142015-10-14 16:27:10313// static
Nasko Oskovdeb6c7ea2017-11-30 18:18:11314bool SiteInstance::ShouldAssignSiteForURL(const GURL& url) {
315 return SiteInstanceImpl::ShouldAssignSiteForURL(url);
316}
317
318// static
[email protected]399583b2012-12-11 09:33:42319bool SiteInstance::IsSameWebSite(BrowserContext* browser_context,
[email protected]855d7d572014-08-02 11:18:17320 const GURL& real_src_url,
321 const GURL& real_dest_url) {
Alex Moshchuk25c64bb2017-12-02 02:50:11322 return SiteInstanceImpl::IsSameWebSite(browser_context, real_src_url,
323 real_dest_url, true);
324}
325
326bool SiteInstanceImpl::IsSameWebSite(BrowserContext* browser_context,
327 const GURL& real_src_url,
328 const GURL& real_dest_url,
329 bool should_compare_effective_urls) {
330 GURL src_url =
331 should_compare_effective_urls
332 ? SiteInstanceImpl::GetEffectiveURL(browser_context, real_src_url)
333 : real_src_url;
334 GURL dest_url =
335 should_compare_effective_urls
336 ? SiteInstanceImpl::GetEffectiveURL(browser_context, real_dest_url)
337 : real_dest_url;
[email protected]399583b2012-12-11 09:33:42338
339 // We infer web site boundaries based on the registered domain name of the
340 // top-level page and the scheme. We do not pay attention to the port if
341 // one is present, because pages served from different ports can still
342 // access each other if they change their document.domain variable.
343
344 // Some special URLs will match the site instance of any other URL. This is
345 // done before checking both of them for validity, since we want these URLs
346 // to have the same site instance as even an invalid one.
[email protected]855d7d572014-08-02 11:18:17347 if (IsRendererDebugURL(src_url) || IsRendererDebugURL(dest_url))
[email protected]399583b2012-12-11 09:33:42348 return true;
349
350 // If either URL is invalid, they aren't part of the same site.
[email protected]855d7d572014-08-02 11:18:17351 if (!src_url.is_valid() || !dest_url.is_valid())
[email protected]399583b2012-12-11 09:33:42352 return false;
353
[email protected]855d7d572014-08-02 11:18:17354 // If the destination url is just a blank page, we treat them as part of the
355 // same site.
356 GURL blank_page(url::kAboutBlankURL);
357 if (dest_url == blank_page)
358 return true;
359
Alex Moshchuka308c9b2018-02-08 20:58:14360 // If the source and destination URLs are equal excluding the hash, they have
361 // the same site. This matters for file URLs, where SameDomainOrHost() would
362 // otherwise return false below.
363 if (src_url.EqualsIgnoringRef(dest_url))
364 return true;
365
Daniel Cheng88186bd52017-10-20 08:14:46366 url::Origin src_origin = url::Origin::Create(src_url);
367 url::Origin dest_origin = url::Origin::Create(dest_url);
alexmos3b9ad102017-05-26 23:41:08368
[email protected]399583b2012-12-11 09:33:42369 // If the schemes differ, they aren't part of the same site.
alexmoscbf995782017-06-01 03:13:13370 if (src_origin.scheme() != dest_origin.scheme())
[email protected]399583b2012-12-11 09:33:42371 return false;
372
alexmos4bc26322017-07-01 00:57:14373 if (!net::registry_controlled_domains::SameDomainOrHost(
374 src_origin, dest_origin,
375 net::registry_controlled_domains::INCLUDE_PRIVATE_REGISTRIES)) {
376 return false;
377 }
378
379 // If the sites are the same, check isolated origins. If either URL matches
380 // an isolated origin, compare origins rather than sites.
381 auto* policy = ChildProcessSecurityPolicyImpl::GetInstance();
382 url::Origin src_isolated_origin;
383 url::Origin dest_isolated_origin;
384 bool src_origin_is_isolated =
385 policy->GetMatchingIsolatedOrigin(src_origin, &src_isolated_origin);
386 bool dest_origin_is_isolated =
387 policy->GetMatchingIsolatedOrigin(dest_origin, &dest_isolated_origin);
388 if (src_origin_is_isolated || dest_origin_is_isolated) {
389 // Compare most specific matching origins to ensure that a subdomain of an
390 // isolated origin (e.g., https://subdomain.isolated.foo.com) also matches
391 // the isolated origin's site URL (e.g., https://isolated.foo.com).
392 return src_isolated_origin == dest_isolated_origin;
393 }
394
395 return true;
[email protected]399583b2012-12-11 09:33:42396}
397
nickcc0d9142015-10-14 16:27:10398// static
[email protected]399583b2012-12-11 09:33:42399GURL SiteInstance::GetSiteForURL(BrowserContext* browser_context,
400 const GURL& real_url) {
[email protected]25a9e8e532012-06-22 06:16:28401 // TODO(fsamuel, creis): For some reason appID is not recognized as a host.
[email protected]6eb1a11e2013-10-09 00:54:37402 if (real_url.SchemeIs(kGuestScheme))
[email protected]25a9e8e532012-06-22 06:16:28403 return real_url;
404
[email protected]b6583592012-01-25 19:52:33405 GURL url = SiteInstanceImpl::GetEffectiveURL(browser_context, real_url);
Daniel Cheng88186bd52017-10-20 08:14:46406 url::Origin origin = url::Origin::Create(url);
[email protected]3a8eecb2010-04-22 23:56:30407
alexmos4bc26322017-07-01 00:57:14408 // Isolated origins should use the full origin as their site URL. A subdomain
Alex Moshchukbb99a332017-11-22 04:49:57409 // of an isolated origin should also use that isolated origin's site URL. It
410 // is important to check |url| rather than |real_url| here, since some
411 // effective URLs (such as for NTP) need to be resolved prior to the isolated
412 // origin lookup.
alexmos3b9ad102017-05-26 23:41:08413 auto* policy = ChildProcessSecurityPolicyImpl::GetInstance();
alexmos4bc26322017-07-01 00:57:14414 url::Origin isolated_origin;
Lukasz Anforowicz217fd272018-03-07 21:41:43415 if (policy->GetMatchingIsolatedOrigin(origin, &isolated_origin))
alexmos4bc26322017-07-01 00:57:14416 return isolated_origin.GetURL();
alexmos3b9ad102017-05-26 23:41:08417
Lukasz Anforowicz48097c42017-12-15 00:23:38418 // If the url has a host, then determine the site. Skip file URLs to avoid a
419 // situation where site URL of file://localhost/ would mismatch Blink's origin
420 // (which ignores the hostname in this case - see https://crbug.com/776160).
421 if (!origin.host().empty() && origin.scheme() != url::kFileScheme) {
nick1dd47922016-04-29 16:44:48422 // Only keep the scheme and registered domain of |origin|.
423 std::string domain = net::registry_controlled_domains::GetDomainAndRegistry(
424 origin.host(),
425 net::registry_controlled_domains::INCLUDE_PRIVATE_REGISTRIES);
426 std::string site = origin.scheme();
427 site += url::kStandardSchemeSeparator;
428 site += domain.empty() ? origin.host() : domain;
429 return GURL(site);
initial.commit09911bf2008-07-26 23:55:29430 }
creisf60c2cd2014-12-18 00:41:02431
432 // If there is no host but there is a scheme, return the scheme.
433 // This is useful for cases like file URLs.
Lukasz Anforowicz217fd272018-03-07 21:41:43434 if (!origin.unique()) {
435 // Prefer to use the scheme of |origin| rather than |url|, to correctly
436 // cover blob: and filesystem: URIs (see also https://crbug.com/697111).
Lukasz Anforowiczd926a842018-03-09 01:50:45437 DCHECK(!origin.scheme().empty());
438 return GURL(origin.scheme() + ":");
439 } else if (url.has_scheme()) {
440 DCHECK(!url.scheme().empty());
creisf60c2cd2014-12-18 00:41:02441 return GURL(url.scheme() + ":");
Lukasz Anforowiczd926a842018-03-09 01:50:45442 }
creisf60c2cd2014-12-18 00:41:02443
444 // Otherwise the URL should be invalid; return an empty site.
Lukasz Anforowicz217fd272018-03-07 21:41:43445 DCHECK(!url.is_valid()) << url;
creisf60c2cd2014-12-18 00:41:02446 return GURL();
initial.commit09911bf2008-07-26 23:55:29447}
448
nickcc0d9142015-10-14 16:27:10449// static
[email protected]4c3a23582012-08-18 08:54:34450GURL SiteInstanceImpl::GetEffectiveURL(BrowserContext* browser_context,
451 const GURL& url) {
Alex Moshchuka31c7882018-01-17 00:57:30452 return GetContentClient()->browser()->GetEffectiveURL(browser_context, url);
[email protected]3a8eecb2010-04-22 23:56:30453}
454
nickcc0d9142015-10-14 16:27:10455// static
Alex Moshchuk25c64bb2017-12-02 02:50:11456bool SiteInstanceImpl::HasEffectiveURL(BrowserContext* browser_context,
457 const GURL& url) {
458 return GetEffectiveURL(browser_context, url) != url;
459}
460
461// static
nickcc0d9142015-10-14 16:27:10462bool SiteInstanceImpl::DoesSiteRequireDedicatedProcess(
463 BrowserContext* browser_context,
nickdb193a12016-09-09 23:09:23464 const GURL& url) {
nickcc0d9142015-10-14 16:27:10465 // If --site-per-process is enabled, site isolation is enabled everywhere.
466 if (SiteIsolationPolicy::UseDedicatedProcessesForAllSites())
467 return true;
468
alexmos3b9ad102017-05-26 23:41:08469 // Always require a dedicated process for isolated origins.
470 GURL site_url = GetSiteForURL(browser_context, url);
471 auto* policy = ChildProcessSecurityPolicyImpl::GetInstance();
Daniel Cheng88186bd52017-10-20 08:14:46472 if (policy->IsIsolatedOrigin(url::Origin::Create(site_url)))
alexmos3b9ad102017-05-26 23:41:08473 return true;
474
nickdb193a12016-09-09 23:09:23475 // Let the content embedder enable site isolation for specific URLs. Use the
476 // canonical site url for this check, so that schemes with nested origins
477 // (blob and filesystem) work properly.
Avi Drissman8c36df72017-12-11 21:19:20478 if (GetContentClient()->browser()->DoesSiteRequireDedicatedProcess(
nickdb193a12016-09-09 23:09:23479 browser_context, site_url)) {
nickcc0d9142015-10-14 16:27:10480 return true;
481 }
482
483 return false;
484}
485
alexmos13fe1962017-06-28 04:25:12486// static
487bool SiteInstanceImpl::ShouldLockToOrigin(BrowserContext* browser_context,
Alex Moshchuk9cf5a45d2017-08-14 18:50:57488 RenderProcessHost* host,
alexmos13fe1962017-06-28 04:25:12489 GURL site_url) {
creis0b49fa12017-07-10 16:31:11490 // Don't lock to origin in --single-process mode, since this mode puts
491 // cross-site pages into the same process.
Alex Moshchuk9cf5a45d2017-08-14 18:50:57492 if (host->run_renderer_in_process())
creis0b49fa12017-07-10 16:31:11493 return false;
494
alexmos13fe1962017-06-28 04:25:12495 if (!DoesSiteRequireDedicatedProcess(browser_context, site_url))
496 return false;
497
498 // Guest processes cannot be locked to their site because guests always have
499 // a fixed SiteInstance. The site of GURLs a guest loads doesn't match that
500 // SiteInstance. So we skip locking the guest process to the site.
501 // TODO(ncarter): Remove this exclusion once we can make origin lock per
502 // RenderFrame routing id.
503 if (site_url.SchemeIs(content::kGuestScheme))
504 return false;
505
506 // TODO(creis, nick) https://crbug.com/510588 Chrome UI pages use the same
507 // site (chrome://chrome), so they can't be locked because the site being
508 // loaded doesn't match the SiteInstance.
509 if (site_url.SchemeIs(content::kChromeUIScheme))
510 return false;
511
512 // TODO(creis, nick): Until we can handle sites with effective URLs at the
513 // call sites of ChildProcessSecurityPolicy::CanAccessDataForOrigin, we
514 // must give the embedder a chance to exempt some sites to avoid process
515 // kills.
516 if (!GetContentClient()->browser()->ShouldLockToOrigin(browser_context,
517 site_url)) {
518 return false;
519 }
520
521 return true;
522}
523
[email protected]40bfaf32013-11-19 01:35:43524void SiteInstanceImpl::RenderProcessHostDestroyed(RenderProcessHost* host) {
525 DCHECK_EQ(process_, host);
526 process_->RemoveObserver(this);
nickd5bbd0b2016-03-31 19:52:44527 process_ = nullptr;
[email protected]4566f132009-03-12 01:55:13528}
[email protected]313b80bd2011-11-23 03:49:10529
nick9f34e2892016-01-12 21:01:07530void SiteInstanceImpl::RenderProcessWillExit(RenderProcessHost* host) {
531 // TODO(nick): http://crbug.com/575400 - RenderProcessWillExit might not serve
532 // any purpose here.
ericwilligers254597b2016-10-17 10:32:31533 for (auto& observer : observers_)
534 observer.RenderProcessGone(this);
nick9f34e2892016-01-12 21:01:07535}
536
537void SiteInstanceImpl::RenderProcessExited(RenderProcessHost* host,
538 base::TerminationStatus status,
539 int exit_code) {
ericwilligers254597b2016-10-17 10:32:31540 for (auto& observer : observers_)
541 observer.RenderProcessGone(this);
nick9f34e2892016-01-12 21:01:07542}
543
alexmos13fe1962017-06-28 04:25:12544void SiteInstanceImpl::LockToOriginIfNeeded() {
545 DCHECK(HasSite());
546
547 // From now on, this process should be considered "tainted" for future
548 // process reuse decisions:
549 // (1) If |site_| required a dedicated process, this SiteInstance's process
550 // can only host URLs for the same site.
551 // (2) Even if |site_| does not require a dedicated process, this
552 // SiteInstance's process still cannot be reused to host other sites
553 // requiring dedicated sites in the future.
554 // We can get here either when we commit a URL into a SiteInstance that does
555 // not yet have a site, or when we create a process for a SiteInstance with a
556 // preassigned site.
557 process_->SetIsUsed();
558
Alex Moshchuk47dd00f2017-10-10 17:15:23559 ChildProcessSecurityPolicyImpl* policy =
560 ChildProcessSecurityPolicyImpl::GetInstance();
561 auto lock_state = policy->CheckOriginLock(process_->GetID(), site_);
Alex Moshchuk9cf5a45d2017-08-14 18:50:57562 if (ShouldLockToOrigin(GetBrowserContext(), process_, site_)) {
Alex Moshchuk9cf5a45d2017-08-14 18:50:57563 // Sanity check that this won't try to assign an origin lock to a <webview>
564 // process, which can't be locked.
565 CHECK(!process_->IsForGuestsOnly());
566
Alex Moshchuk9cf5a45d2017-08-14 18:50:57567 switch (lock_state) {
568 case ChildProcessSecurityPolicyImpl::CheckOriginLockResult::NO_LOCK: {
Alex Moshchuk47dd00f2017-10-10 17:15:23569 // TODO(nick): When all sites are isolated, this operation provides
570 // strong protection. If only some sites are isolated, we need
571 // additional logic to prevent the non-isolated sites from requesting
572 // resources for isolated sites. https://crbug.com/509125
Alex Moshchuk9cf5a45d2017-08-14 18:50:57573 policy->LockToOrigin(process_->GetID(), site_);
574 break;
575 }
576 case ChildProcessSecurityPolicyImpl::CheckOriginLockResult::
577 HAS_WRONG_LOCK:
578 // We should never attempt to reassign a different origin lock to a
579 // process.
Robert Sesek1e07e372017-12-09 01:34:42580 base::debug::SetCrashKeyString(bad_message::GetRequestedSiteURLKey(),
581 site_.spec());
582 base::debug::SetCrashKeyString(
583 bad_message::GetKilledProcessOriginLockKey(),
Alex Moshchuk4479b97c2017-10-17 23:20:32584 policy->GetOriginLock(process_->GetID()).spec());
Alex Moshchuk54bf13042017-10-13 04:25:29585 CHECK(false) << "Trying to lock a process to " << site_
586 << " but the process is already locked to "
587 << policy->GetOriginLock(process_->GetID());
Alex Moshchuk9cf5a45d2017-08-14 18:50:57588 break;
589 case ChildProcessSecurityPolicyImpl::CheckOriginLockResult::
590 HAS_EQUAL_LOCK:
591 // Process already has the right origin lock assigned. This case will
592 // happen for commits to |site_| after the first one.
593 break;
594 default:
595 NOTREACHED();
596 }
Alex Moshchuk47dd00f2017-10-10 17:15:23597 } else {
598 // If the site that we've just committed doesn't require a dedicated
599 // process, make sure we aren't putting it in a process for a site that
600 // does.
Robert Sesek1e07e372017-12-09 01:34:42601 base::debug::SetCrashKeyString(bad_message::GetRequestedSiteURLKey(),
602 site_.spec());
603 base::debug::SetCrashKeyString(
604 bad_message::GetKilledProcessOriginLockKey(),
Alex Moshchuk4479b97c2017-10-17 23:20:32605 policy->GetOriginLock(process_->GetID()).spec());
Alex Moshchuk47dd00f2017-10-10 17:15:23606 CHECK_EQ(lock_state,
Alex Moshchuk54bf13042017-10-13 04:25:29607 ChildProcessSecurityPolicyImpl::CheckOriginLockResult::NO_LOCK)
608 << "Trying to commit non-isolated site " << site_
609 << " in process locked to " << policy->GetOriginLock(process_->GetID());
[email protected]313b80bd2011-11-23 03:49:10610 }
611}
[email protected]46488322012-10-30 03:22:20612
613} // namespace content