[email protected] | 72daaa9 | 2012-01-18 13:39:02 | [diff] [blame] | 1 | // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
license.bot | bf09a50 | 2008-08-24 00:55:55 | [diff] [blame] | 2 | // Use of this source code is governed by a BSD-style license that can be |
| 3 | // found in the LICENSE file. |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 4 | |
[email protected] | df8e899b | 2011-02-22 22:58:22 | [diff] [blame] | 5 | #include "content/browser/browsing_instance.h" |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 6 | |
| 7 | #include "base/command_line.h" |
[email protected] | dec76e80 | 2010-09-23 22:43:53 | [diff] [blame] | 8 | #include "base/logging.h" |
[email protected] | b658359 | 2012-01-25 19:52:33 | [diff] [blame] | 9 | #include "content/browser/site_instance_impl.h" |
[email protected] | ccb79730 | 2011-12-15 16:55:11 | [diff] [blame] | 10 | #include "content/public/browser/browser_context.h" |
Aaron Colwell | ddeccbdb | 2019-03-08 01:11:03 | [diff] [blame] | 11 | #include "content/public/browser/browser_or_resource_context.h" |
[email protected] | 87f3c08 | 2011-10-19 18:07:44 | [diff] [blame] | 12 | #include "content/public/browser/content_browser_client.h" |
Nick Carter | bf6264a5 | 2018-04-06 02:39:33 | [diff] [blame] | 13 | #include "content/public/browser/site_isolation_policy.h" |
Aaron Colwell | ddeccbdb | 2019-03-08 01:11:03 | [diff] [blame] | 14 | #include "content/public/common/content_features.h" |
[email protected] | c08950d2 | 2011-10-13 22:20:29 | [diff] [blame] | 15 | #include "content/public/common/content_switches.h" |
[email protected] | a1d2916 | 2011-10-14 17:14:03 | [diff] [blame] | 16 | #include "content/public/common/url_constants.h" |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 17 | |
[email protected] | 4648832 | 2012-10-30 03:22:20 | [diff] [blame] | 18 | namespace content { |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 19 | |
Alex Moshchuk | 8e5c195 | 2019-01-15 03:39:50 | [diff] [blame] | 20 | // Start the BrowsingInstance ID counter from 1 to avoid a conflict with the |
| 21 | // invalid BrowsingInstanceId value, which is 0 in its underlying IdType32. |
| 22 | int BrowsingInstance::next_browsing_instance_id_ = 1; |
| 23 | |
[email protected] | 4648832 | 2012-10-30 03:22:20 | [diff] [blame] | 24 | BrowsingInstance::BrowsingInstance(BrowserContext* browser_context) |
Alex Moshchuk | f748879 | 2019-03-11 22:37:57 | [diff] [blame] | 25 | : isolation_context_( |
Alex Moshchuk | 99b79542 | 2019-03-07 00:27:32 | [diff] [blame] | 26 | BrowsingInstanceId::FromUnsafeValue(next_browsing_instance_id_++), |
| 27 | BrowserOrResourceContext(browser_context)), |
Nate Chapin | 71da03c | 2019-02-05 01:21:41 | [diff] [blame] | 28 | active_contents_count_(0u), |
Aaron Colwell | c194831 | 2019-05-16 21:40:30 | [diff] [blame] | 29 | default_process_(nullptr), |
| 30 | default_site_instance_(nullptr) { |
Lukasz Anforowicz | 4726a17 | 2018-10-15 21:25:10 | [diff] [blame] | 31 | DCHECK(browser_context); |
[email protected] | dec76e80 | 2010-09-23 22:43:53 | [diff] [blame] | 32 | } |
| 33 | |
Nate Chapin | 71da03c | 2019-02-05 01:21:41 | [diff] [blame] | 34 | void BrowsingInstance::RenderProcessHostDestroyed(RenderProcessHost* host) { |
| 35 | DCHECK_EQ(default_process_, host); |
| 36 | // Only clear the default process if the RenderProcessHost object goes away, |
| 37 | // not if the renderer process goes away while the RenderProcessHost remains. |
| 38 | default_process_->RemoveObserver(this); |
| 39 | default_process_ = nullptr; |
| 40 | } |
| 41 | |
Alex Moshchuk | f748879 | 2019-03-11 22:37:57 | [diff] [blame] | 42 | BrowserContext* BrowsingInstance::GetBrowserContext() const { |
| 43 | return isolation_context_.browser_or_resource_context().ToBrowserContext(); |
| 44 | } |
| 45 | |
Nate Chapin | 71da03c | 2019-02-05 01:21:41 | [diff] [blame] | 46 | void BrowsingInstance::SetDefaultProcess(RenderProcessHost* default_process) { |
| 47 | DCHECK(!default_process_); |
Aaron Colwell | ddeccbdb | 2019-03-08 01:11:03 | [diff] [blame] | 48 | DCHECK(!default_site_instance_); |
Nate Chapin | 71da03c | 2019-02-05 01:21:41 | [diff] [blame] | 49 | default_process_ = default_process; |
| 50 | default_process_->AddObserver(this); |
| 51 | } |
| 52 | |
Aaron Colwell | ddeccbdb | 2019-03-08 01:11:03 | [diff] [blame] | 53 | bool BrowsingInstance::IsDefaultSiteInstance( |
| 54 | const SiteInstanceImpl* site_instance) const { |
Aaron Colwell | c194831 | 2019-05-16 21:40:30 | [diff] [blame] | 55 | return site_instance != nullptr && site_instance == default_site_instance_; |
Aaron Colwell | ddeccbdb | 2019-03-08 01:11:03 | [diff] [blame] | 56 | } |
| 57 | |
Aaron Colwell | 0447cd0 | 2019-06-26 22:04:20 | [diff] [blame] | 58 | bool BrowsingInstance::IsSiteInDefaultSiteInstance(const GURL& site_url) const { |
| 59 | return site_url_set_.find(site_url) != site_url_set_.end(); |
| 60 | } |
| 61 | |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 62 | bool BrowsingInstance::HasSiteInstance(const GURL& url) { |
Aaron Colwell | 24f2746a | 2019-04-25 16:57:43 | [diff] [blame] | 63 | std::string site = GetSiteForURL(url).possibly_invalid_spec(); |
[email protected] | 41fb79a5 | 2012-06-29 16:34:33 | [diff] [blame] | 64 | return site_instance_map_.find(site) != site_instance_map_.end(); |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 65 | } |
| 66 | |
dcheng | bccd6b8 | 2016-03-30 16:24:19 | [diff] [blame] | 67 | scoped_refptr<SiteInstanceImpl> BrowsingInstance::GetSiteInstanceForURL( |
Aaron Colwell | ddeccbdb | 2019-03-08 01:11:03 | [diff] [blame] | 68 | const GURL& url, |
| 69 | bool allow_default_instance) { |
| 70 | scoped_refptr<SiteInstanceImpl> site_instance = |
| 71 | GetSiteInstanceForURLHelper(url, allow_default_instance); |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 72 | |
Aaron Colwell | ddeccbdb | 2019-03-08 01:11:03 | [diff] [blame] | 73 | if (site_instance) |
| 74 | return site_instance; |
[email protected] | 41fb79a5 | 2012-06-29 16:34:33 | [diff] [blame] | 75 | |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 76 | // No current SiteInstance for this site, so let's create one. |
dcheng | bccd6b8 | 2016-03-30 16:24:19 | [diff] [blame] | 77 | scoped_refptr<SiteInstanceImpl> instance = new SiteInstanceImpl(this); |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 78 | |
Charlie Reis | c209975 | 2019-04-06 01:21:12 | [diff] [blame] | 79 | // Set the site of this new SiteInstance, which will register it with us, |
| 80 | // unless this URL should leave the SiteInstance's site unassigned. |
| 81 | if (SiteInstance::ShouldAssignSiteForURL(url)) |
| 82 | instance->SetSite(url); |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 83 | return instance; |
| 84 | } |
| 85 | |
Aaron Colwell | ddeccbdb | 2019-03-08 01:11:03 | [diff] [blame] | 86 | void BrowsingInstance::GetSiteAndLockForURL(const GURL& url, |
| 87 | bool allow_default_instance, |
| 88 | GURL* site_url, |
| 89 | GURL* lock_url) { |
| 90 | scoped_refptr<SiteInstanceImpl> site_instance = |
| 91 | GetSiteInstanceForURLHelper(url, allow_default_instance); |
| 92 | |
| 93 | if (site_instance) { |
| 94 | *site_url = site_instance->GetSiteURL(); |
| 95 | *lock_url = site_instance->lock_url(); |
| 96 | return; |
| 97 | } |
| 98 | |
Aaron Colwell | 24f2746a | 2019-04-25 16:57:43 | [diff] [blame] | 99 | *site_url = GetSiteForURL(url); |
Alex Moshchuk | f748879 | 2019-03-11 22:37:57 | [diff] [blame] | 100 | *lock_url = |
| 101 | SiteInstanceImpl::DetermineProcessLockURL(isolation_context_, url); |
Aaron Colwell | ddeccbdb | 2019-03-08 01:11:03 | [diff] [blame] | 102 | } |
| 103 | |
Aaron Colwell | e953e56 | 2019-07-24 16:47:36 | [diff] [blame] | 104 | bool BrowsingInstance::TrySettingDefaultSiteInstance( |
| 105 | SiteInstanceImpl* site_instance, |
| 106 | const GURL& url) { |
| 107 | DCHECK(!site_instance->HasSite()); |
| 108 | const GURL site_url = GetSiteForURL(url); |
| 109 | if (default_site_instance_ || |
| 110 | !SiteInstanceImpl::CanBePlacedInDefaultSiteInstance(isolation_context_, |
| 111 | url, site_url)) { |
| 112 | return false; |
| 113 | } |
| 114 | |
| 115 | // Note: |default_site_instance_| must be set before SetSite() call to |
| 116 | // properly trigger default SiteInstance behavior inside that method. |
| 117 | default_site_instance_ = site_instance; |
| 118 | site_instance->SetSite(SiteInstanceImpl::GetDefaultSiteURL()); |
| 119 | site_url_set_.insert(site_url); |
| 120 | return true; |
| 121 | } |
| 122 | |
Aaron Colwell | ddeccbdb | 2019-03-08 01:11:03 | [diff] [blame] | 123 | scoped_refptr<SiteInstanceImpl> BrowsingInstance::GetSiteInstanceForURLHelper( |
| 124 | const GURL& url, |
| 125 | bool allow_default_instance) { |
Aaron Colwell | 0447cd0 | 2019-06-26 22:04:20 | [diff] [blame] | 126 | const GURL site_url = GetSiteForURL(url); |
| 127 | auto i = site_instance_map_.find(site_url.possibly_invalid_spec()); |
Aaron Colwell | ddeccbdb | 2019-03-08 01:11:03 | [diff] [blame] | 128 | if (i != site_instance_map_.end()) |
| 129 | return i->second; |
| 130 | |
| 131 | // Check to see if we can use the default SiteInstance for sites that don't |
Aaron Colwell | 8bb0ada | 2019-07-18 22:41:23 | [diff] [blame] | 132 | // need to be isolated in their own process. |
| 133 | if (allow_default_instance && |
| 134 | SiteInstanceImpl::CanBePlacedInDefaultSiteInstance(isolation_context_, |
| 135 | url, site_url)) { |
Aaron Colwell | ddeccbdb | 2019-03-08 01:11:03 | [diff] [blame] | 136 | DCHECK(!default_process_); |
Aaron Colwell | c194831 | 2019-05-16 21:40:30 | [diff] [blame] | 137 | scoped_refptr<SiteInstanceImpl> site_instance = default_site_instance_; |
| 138 | if (!site_instance) { |
| 139 | site_instance = new SiteInstanceImpl(this); |
| 140 | |
| 141 | // Keep a copy of the pointer so it can be used for other URLs. This is |
| 142 | // safe because the SiteInstanceImpl destructor will call |
| 143 | // UnregisterSiteInstance() to clear this copy when the last |
| 144 | // reference to |site_instance| is destroyed. |
| 145 | // Note: This assignment MUST happen before the SetSite() call to ensure |
| 146 | // this instance is not added to |site_instance_map_| when SetSite() |
| 147 | // calls RegisterSiteInstance(). |
| 148 | default_site_instance_ = site_instance.get(); |
| 149 | |
| 150 | site_instance->SetSite(SiteInstanceImpl::GetDefaultSiteURL()); |
Aaron Colwell | ddeccbdb | 2019-03-08 01:11:03 | [diff] [blame] | 151 | } |
Aaron Colwell | 0447cd0 | 2019-06-26 22:04:20 | [diff] [blame] | 152 | |
| 153 | // Add |site_url| to the set so we can keep track of all the sites the |
| 154 | // the default SiteInstance has been returned for. |
| 155 | site_url_set_.insert(site_url); |
Aaron Colwell | c194831 | 2019-05-16 21:40:30 | [diff] [blame] | 156 | return site_instance; |
Aaron Colwell | ddeccbdb | 2019-03-08 01:11:03 | [diff] [blame] | 157 | } |
| 158 | |
| 159 | return nullptr; |
| 160 | } |
| 161 | |
dcheng | bccd6b8 | 2016-03-30 16:24:19 | [diff] [blame] | 162 | void BrowsingInstance::RegisterSiteInstance(SiteInstanceImpl* site_instance) { |
| 163 | DCHECK(site_instance->browsing_instance_.get() == this); |
| 164 | DCHECK(site_instance->HasSite()); |
nick | d5bbd0b | 2016-03-31 19:52:44 | [diff] [blame] | 165 | |
Aaron Colwell | ddeccbdb | 2019-03-08 01:11:03 | [diff] [blame] | 166 | // Explicitly prevent the |default_site_instance_| from being added since |
| 167 | // the map is only supposed to contain instances that map to a single site. |
Aaron Colwell | c194831 | 2019-05-16 21:40:30 | [diff] [blame] | 168 | if (site_instance == default_site_instance_) |
Aaron Colwell | ddeccbdb | 2019-03-08 01:11:03 | [diff] [blame] | 169 | return; |
| 170 | |
[email protected] | 77ab1731 | 2012-09-28 15:34:59 | [diff] [blame] | 171 | std::string site = site_instance->GetSiteURL().possibly_invalid_spec(); |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 172 | |
| 173 | // Only register if we don't have a SiteInstance for this site already. |
| 174 | // It's possible to have two SiteInstances point to the same site if two |
| 175 | // tabs are navigated there at the same time. (We don't call SetSite or |
| 176 | // register them until DidNavigate.) If there is a previously existing |
| 177 | // SiteInstance for this site, we just won't register the new one. |
jdoerrie | 55ec69d | 2018-10-08 13:34:46 | [diff] [blame] | 178 | auto i = site_instance_map_.find(site); |
[email protected] | 41fb79a5 | 2012-06-29 16:34:33 | [diff] [blame] | 179 | if (i == site_instance_map_.end()) { |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 180 | // Not previously registered, so register it. |
[email protected] | 41fb79a5 | 2012-06-29 16:34:33 | [diff] [blame] | 181 | site_instance_map_[site] = site_instance; |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 182 | } |
| 183 | } |
| 184 | |
dcheng | bccd6b8 | 2016-03-30 16:24:19 | [diff] [blame] | 185 | void BrowsingInstance::UnregisterSiteInstance(SiteInstanceImpl* site_instance) { |
| 186 | DCHECK(site_instance->browsing_instance_.get() == this); |
| 187 | DCHECK(site_instance->HasSite()); |
Aaron Colwell | c194831 | 2019-05-16 21:40:30 | [diff] [blame] | 188 | |
| 189 | if (site_instance == default_site_instance_) { |
| 190 | // The last reference to the default SiteInstance is being destroyed. |
| 191 | default_site_instance_ = nullptr; |
| 192 | } |
| 193 | |
[email protected] | 77ab1731 | 2012-09-28 15:34:59 | [diff] [blame] | 194 | std::string site = site_instance->GetSiteURL().possibly_invalid_spec(); |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 195 | |
| 196 | // Only unregister the SiteInstance if it is the same one that is registered |
| 197 | // for the site. (It might have been an unregistered SiteInstance. See the |
| 198 | // comments in RegisterSiteInstance.) |
jdoerrie | 55ec69d | 2018-10-08 13:34:46 | [diff] [blame] | 199 | auto i = site_instance_map_.find(site); |
[email protected] | 41fb79a5 | 2012-06-29 16:34:33 | [diff] [blame] | 200 | if (i != site_instance_map_.end() && i->second == site_instance) { |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 201 | // Matches, so erase it. |
[email protected] | 41fb79a5 | 2012-06-29 16:34:33 | [diff] [blame] | 202 | site_instance_map_.erase(i); |
initial.commit | 09911bf | 2008-07-26 23:55:29 | [diff] [blame] | 203 | } |
| 204 | } |
[email protected] | dec76e80 | 2010-09-23 22:43:53 | [diff] [blame] | 205 | |
Alex Moshchuk | 8e5c195 | 2019-01-15 03:39:50 | [diff] [blame] | 206 | // static |
| 207 | BrowsingInstanceId BrowsingInstance::NextBrowsingInstanceId() { |
| 208 | return BrowsingInstanceId::FromUnsafeValue(next_browsing_instance_id_); |
| 209 | } |
| 210 | |
[email protected] | dec76e80 | 2010-09-23 22:43:53 | [diff] [blame] | 211 | BrowsingInstance::~BrowsingInstance() { |
| 212 | // We should only be deleted when all of the SiteInstances that refer to |
| 213 | // us are gone. |
| 214 | DCHECK(site_instance_map_.empty()); |
[email protected] | d5072a8 | 2014-05-15 05:50:18 | [diff] [blame] | 215 | DCHECK_EQ(0u, active_contents_count_); |
Aaron Colwell | c194831 | 2019-05-16 21:40:30 | [diff] [blame] | 216 | DCHECK(!default_site_instance_); |
Nate Chapin | 71da03c | 2019-02-05 01:21:41 | [diff] [blame] | 217 | if (default_process_) |
| 218 | default_process_->RemoveObserver(this); |
[email protected] | dec76e80 | 2010-09-23 22:43:53 | [diff] [blame] | 219 | } |
[email protected] | 4648832 | 2012-10-30 03:22:20 | [diff] [blame] | 220 | |
Aaron Colwell | f35ff83 | 2019-04-25 18:05:43 | [diff] [blame] | 221 | GURL BrowsingInstance::GetSiteForURL(const GURL& url) const { |
Aaron Colwell | 24f2746a | 2019-04-25 16:57:43 | [diff] [blame] | 222 | return SiteInstanceImpl::GetSiteForURL(isolation_context_, url); |
| 223 | } |
| 224 | |
[email protected] | 4648832 | 2012-10-30 03:22:20 | [diff] [blame] | 225 | } // namespace content |