blob: 0b36c6c075cc3e7cac578b165cd3326ff3b05975 [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
[email protected]313b80bd2011-11-23 03:49:107#include "base/command_line.h"
[email protected]39365212011-02-24 01:01:008#include "content/browser/browsing_instance.h"
[email protected]b9535422012-02-09 01:47:599#include "content/browser/child_process_security_policy_impl.h"
[email protected]f3b1a082011-11-18 00:34:3010#include "content/browser/renderer_host/render_process_host_impl.h"
[email protected]87f3c082011-10-19 18:07:4411#include "content/public/browser/content_browser_client.h"
[email protected]ad50def52011-10-19 23:17:0712#include "content/public/browser/notification_service.h"
[email protected]0d6e9bd2011-10-18 04:29:1613#include "content/public/browser/notification_types.h"
[email protected]f3b1a082011-11-18 00:34:3014#include "content/public/browser/render_process_host_factory.h"
[email protected]41fb79a52012-06-29 16:34:3315#include "content/public/browser/web_ui_controller_factory.h"
[email protected]313b80bd2011-11-23 03:49:1016#include "content/public/common/content_switches.h"
[email protected]a1d29162011-10-14 17:14:0317#include "content/public/common/url_constants.h"
initial.commit09911bf2008-07-26 23:55:2918#include "net/base/registry_controlled_domain.h"
19
[email protected]41fb79a52012-06-29 16:34:3320using content::RenderProcessHost;
[email protected]42ac7852012-06-01 06:38:4821using content::RenderProcessHostImpl;
[email protected]b6583592012-01-25 19:52:3322using content::SiteInstance;
[email protected]41fb79a52012-06-29 16:34:3323using content::WebUIControllerFactory;
[email protected]b6583592012-01-25 19:52:3324
[email protected]2ee0418e2009-06-26 21:00:4325static bool IsURLSameAsAnySiteInstance(const GURL& url) {
26 if (!url.is_valid())
27 return false;
[email protected]0f012df82011-05-19 14:15:2928
[email protected]89f550b2011-06-08 18:34:0329 // We treat javascript: as the same site as any URL since it is actually
30 // a modifier on existing pages.
31 if (url.SchemeIs(chrome::kJavaScriptScheme))
[email protected]0f012df82011-05-19 14:15:2932 return true;
[email protected]0f012df82011-05-19 14:15:2933
[email protected]8bf1048012012-02-08 01:22:1834 return url == GURL(chrome::kChromeUICrashURL) ||
35 url == GURL(chrome::kChromeUIKillURL) ||
36 url == GURL(chrome::kChromeUIHangURL) ||
37 url == GURL(chrome::kChromeUIShorthangURL);
[email protected]2ee0418e2009-06-26 21:00:4338}
39
[email protected]b6583592012-01-25 19:52:3340int32 SiteInstanceImpl::next_site_instance_id_ = 1;
[email protected]992db4c2011-05-12 15:37:1541
[email protected]b6583592012-01-25 19:52:3342SiteInstanceImpl::SiteInstanceImpl(BrowsingInstance* browsing_instance)
[email protected]992db4c2011-05-12 15:37:1543 : id_(next_site_instance_id_++),
44 browsing_instance_(browsing_instance),
[email protected]4566f132009-03-12 01:55:1345 render_process_host_factory_(NULL),
46 process_(NULL),
[email protected]4566f132009-03-12 01:55:1347 has_site_(false) {
48 DCHECK(browsing_instance);
49
[email protected]432115822011-07-10 15:52:2750 registrar_.Add(this, content::NOTIFICATION_RENDERER_PROCESS_TERMINATED,
[email protected]ad50def52011-10-19 23:17:0751 content::NotificationService::AllBrowserContextsAndSources());
[email protected]4566f132009-03-12 01:55:1352}
53
[email protected]b6583592012-01-25 19:52:3354SiteInstanceImpl::~SiteInstanceImpl() {
[email protected]6f371442011-11-09 06:45:4655 content::GetContentClient()->browser()->SiteInstanceDeleting(this);
[email protected]056ad2a2011-07-12 02:13:5556
initial.commit09911bf2008-07-26 23:55:2957 // Now that no one is referencing us, we can safely remove ourselves from
58 // the BrowsingInstance. Any future visits to a page from this site
59 // (within the same BrowsingInstance) can safely create a new SiteInstance.
60 if (has_site_)
[email protected]b6583592012-01-25 19:52:3361 browsing_instance_->UnregisterSiteInstance(
62 static_cast<SiteInstance*>(this));
initial.commit09911bf2008-07-26 23:55:2963}
64
[email protected]b6583592012-01-25 19:52:3365int32 SiteInstanceImpl::GetId() {
66 return id_;
67}
68
69bool SiteInstanceImpl::HasProcess() const {
[email protected]41fb79a52012-06-29 16:34:3370 if (process_ != NULL)
71 return true;
72
73 // If we would use process-per-site for this site, also check if there is an
74 // existing process that we would use if GetProcess() were called.
75 content::BrowserContext* browser_context =
76 browsing_instance_->browser_context();
77 if (has_site_ &&
78 RenderProcessHostImpl::ShouldUseProcessPerSite(browser_context, site_) &&
79 RenderProcessHostImpl::GetProcessHostForSite(browser_context, site_)) {
80 return true;
81 }
82
83 return false;
[email protected]5ab79b02010-04-26 16:47:1184}
85
[email protected]41fb79a52012-06-29 16:34:3386RenderProcessHost* SiteInstanceImpl::GetProcess() {
[email protected]08c8ec7e2010-07-11 17:14:4887 // TODO(erikkay) It would be nice to ensure that the renderer type had been
88 // properly set before we get here. The default tab creation case winds up
89 // with no site set at this point, so it will default to TYPE_NORMAL. This
90 // may not be correct, so we'll wind up potentially creating a process that
91 // we then throw away, or worse sharing a process with the wrong process type.
92 // See crbug.com/43448.
93
initial.commit09911bf2008-07-26 23:55:2994 // Create a new process if ours went away or was reused.
[email protected]4566f132009-03-12 01:55:1395 if (!process_) {
[email protected]41fb79a52012-06-29 16:34:3396 content::BrowserContext* browser_context =
97 browsing_instance_->browser_context();
98
99 // If we should use process-per-site mode (either in general or for the
100 // given site), then look for an existing RenderProcessHost for the site.
101 bool use_process_per_site = has_site_ &&
102 RenderProcessHostImpl::ShouldUseProcessPerSite(browser_context, site_);
103 if (use_process_per_site) {
104 process_ = RenderProcessHostImpl::GetProcessHostForSite(browser_context,
105 site_);
106 }
107
108 // If not (or if none found), see if we should reuse an existing process.
109 if (!process_ && RenderProcessHostImpl::ShouldTryToUseExistingProcessHost(
110 browser_context, site_)) {
111 process_ = RenderProcessHostImpl::GetExistingProcessHost(browser_context,
112 site_);
113 }
initial.commit09911bf2008-07-26 23:55:29114
115 // Otherwise (or if that fails), create a new one.
[email protected]4566f132009-03-12 01:55:13116 if (!process_) {
[email protected]a6df5112009-01-21 23:50:15117 if (render_process_host_factory_) {
[email protected]4566f132009-03-12 01:55:13118 process_ = render_process_host_factory_->CreateRenderProcessHost(
[email protected]41fb79a52012-06-29 16:34:33119 browser_context);
[email protected]a6df5112009-01-21 23:50:15120 } else {
[email protected]3d7474ff2011-07-27 17:47:37121 process_ =
[email protected]41fb79a52012-06-29 16:34:33122 new RenderProcessHostImpl(browser_context,
[email protected]25a9e8e532012-06-22 06:16:28123 site_.SchemeIs(chrome::kGuestScheme));
[email protected]a6df5112009-01-21 23:50:15124 }
125 }
[email protected]41fb79a52012-06-29 16:34:33126 CHECK(process_);
127
128 // If we are using process-per-site, we need to register this process
129 // for the current site so that we can find it again. (If no site is set
130 // at this time, we will register it in SetSite().)
131 if (use_process_per_site) {
132 RenderProcessHostImpl::RegisterProcessHostForSite(browser_context,
133 process_, site_);
134 }
initial.commit09911bf2008-07-26 23:55:29135
[email protected]6f371442011-11-09 06:45:46136 content::GetContentClient()->browser()->SiteInstanceGotProcess(this);
137
[email protected]313b80bd2011-11-23 03:49:10138 if (has_site_)
139 LockToOrigin();
initial.commit09911bf2008-07-26 23:55:29140 }
[email protected]4566f132009-03-12 01:55:13141 DCHECK(process_);
initial.commit09911bf2008-07-26 23:55:29142
[email protected]4566f132009-03-12 01:55:13143 return process_;
initial.commit09911bf2008-07-26 23:55:29144}
145
[email protected]b6583592012-01-25 19:52:33146void SiteInstanceImpl::SetSite(const GURL& url) {
initial.commit09911bf2008-07-26 23:55:29147 // A SiteInstance's site should not change.
148 // TODO(creis): When following links or script navigations, we can currently
149 // render pages from other sites in this SiteInstance. This will eventually
150 // be fixed, but until then, we should still not set the site of a
151 // SiteInstance more than once.
152 DCHECK(!has_site_);
153
154 // Remember that this SiteInstance has been used to load a URL, even if the
155 // URL is invalid.
156 has_site_ = true;
[email protected]41fb79a52012-06-29 16:34:33157 content::BrowserContext* browser_context =
158 browsing_instance_->browser_context();
159 site_ = GetSiteForURL(browser_context, url);
initial.commit09911bf2008-07-26 23:55:29160
161 // Now that we have a site, register it with the BrowsingInstance. This
162 // ensures that we won't create another SiteInstance for this site within
163 // the same BrowsingInstance, because all same-site pages within a
164 // BrowsingInstance can script each other.
165 browsing_instance_->RegisterSiteInstance(this);
[email protected]313b80bd2011-11-23 03:49:10166
[email protected]41fb79a52012-06-29 16:34:33167 if (process_) {
[email protected]313b80bd2011-11-23 03:49:10168 LockToOrigin();
[email protected]41fb79a52012-06-29 16:34:33169
170 // Ensure the process is registered for this site if necessary.
171 if (RenderProcessHostImpl::ShouldUseProcessPerSite(browser_context,
172 site_)) {
173 RenderProcessHostImpl::RegisterProcessHostForSite(
174 browser_context, process_, site_);
175 }
176 }
initial.commit09911bf2008-07-26 23:55:29177}
178
[email protected]b6583592012-01-25 19:52:33179const GURL& SiteInstanceImpl::GetSite() const {
180 return site_;
181}
182
183bool SiteInstanceImpl::HasSite() const {
184 return has_site_;
185}
186
187bool SiteInstanceImpl::HasRelatedSiteInstance(const GURL& url) {
initial.commit09911bf2008-07-26 23:55:29188 return browsing_instance_->HasSiteInstance(url);
189}
190
[email protected]b6583592012-01-25 19:52:33191SiteInstance* SiteInstanceImpl::GetRelatedSiteInstance(const GURL& url) {
initial.commit09911bf2008-07-26 23:55:29192 return browsing_instance_->GetSiteInstanceForURL(url);
193}
194
[email protected]14392a52012-05-02 20:28:44195bool SiteInstanceImpl::IsRelatedSiteInstance(const SiteInstance* instance) {
196 return browsing_instance_ ==
197 static_cast<const SiteInstanceImpl*>(instance)->browsing_instance_;
198}
199
[email protected]b6583592012-01-25 19:52:33200bool SiteInstanceImpl::HasWrongProcessForURL(const GURL& url) const {
[email protected]d292d8a2011-05-25 03:47:11201 // Having no process isn't a problem, since we'll assign it correctly.
202 if (!HasProcess())
203 return false;
204
[email protected]144a8102012-01-14 01:05:31205 // If the URL to navigate to can be associated with any site instance,
206 // we want to keep it in the same process.
207 if (IsURLSameAsAnySiteInstance(url))
208 return false;
209
[email protected]88aae972011-12-16 01:14:18210 // If the site URL is an extension (e.g., for hosted apps or WebUI) but the
[email protected]d292d8a2011-05-25 03:47:11211 // process is not (or vice versa), make sure we notice and fix it.
[email protected]2a5221b2011-09-27 23:07:31212 GURL site_url = GetSiteForURL(browsing_instance_->browser_context(), url);
[email protected]88aae972011-12-16 01:14:18213 return !RenderProcessHostImpl::IsSuitableHost(
214 process_, browsing_instance_->browser_context(), site_url);
[email protected]d292d8a2011-05-25 03:47:11215}
216
[email protected]b6583592012-01-25 19:52:33217content::BrowserContext* SiteInstanceImpl::GetBrowserContext() const {
[email protected]72daaa92012-01-18 13:39:02218 return browsing_instance_->browser_context();
219}
220
initial.commit09911bf2008-07-26 23:55:29221/*static*/
[email protected]b6583592012-01-25 19:52:33222SiteInstance* SiteInstance::Create(content::BrowserContext* browser_context) {
223 return new SiteInstanceImpl(new BrowsingInstance(browser_context));
initial.commit09911bf2008-07-26 23:55:29224}
225
226/*static*/
[email protected]b6583592012-01-25 19:52:33227SiteInstance* SiteInstance::CreateForURL(
[email protected]3d7474ff2011-07-27 17:47:37228 content::BrowserContext* browser_context, const GURL& url) {
[email protected]633fbc42009-05-07 23:39:47229 // This BrowsingInstance may be deleted if it returns an existing
230 // SiteInstance.
[email protected]3d7474ff2011-07-27 17:47:37231 scoped_refptr<BrowsingInstance> instance(
232 new BrowsingInstance(browser_context));
[email protected]633fbc42009-05-07 23:39:47233 return instance->GetSiteInstanceForURL(url);
[email protected]d8a96622009-05-07 19:21:16234}
235
236/*static*/
[email protected]b6583592012-01-25 19:52:33237GURL SiteInstanceImpl::GetSiteForURL(content::BrowserContext* browser_context,
238 const GURL& real_url) {
[email protected]25a9e8e532012-06-22 06:16:28239 // TODO(fsamuel, creis): For some reason appID is not recognized as a host.
240 if (real_url.SchemeIs(chrome::kGuestScheme))
241 return real_url;
242
[email protected]b6583592012-01-25 19:52:33243 GURL url = SiteInstanceImpl::GetEffectiveURL(browser_context, real_url);
[email protected]3a8eecb2010-04-22 23:56:30244
initial.commit09911bf2008-07-26 23:55:29245 // URLs with no host should have an empty site.
246 GURL site;
247
248 // TODO(creis): For many protocols, we should just treat the scheme as the
[email protected]76a010b2008-12-07 23:48:03249 // site, since there is no host. e.g., file:, about:, chrome:
initial.commit09911bf2008-07-26 23:55:29250
251 // If the url has a host, then determine the site.
252 if (url.has_host()) {
[email protected]6705b232008-11-26 00:16:51253 // Only keep the scheme and registered domain as given by GetOrigin. This
254 // may also include a port, which we need to drop.
initial.commit09911bf2008-07-26 23:55:29255 site = url.GetOrigin();
256
[email protected]6705b232008-11-26 00:16:51257 // Remove port, if any.
258 if (site.has_port()) {
259 GURL::Replacements rep;
260 rep.ClearPort();
261 site = site.ReplaceComponents(rep);
262 }
263
initial.commit09911bf2008-07-26 23:55:29264 // If this URL has a registered domain, we only want to remember that part.
265 std::string domain =
[email protected]8ac1a752008-07-31 19:40:37266 net::RegistryControlledDomainService::GetDomainAndRegistry(url);
initial.commit09911bf2008-07-26 23:55:29267 if (!domain.empty()) {
268 GURL::Replacements rep;
269 rep.SetHostStr(domain);
270 site = site.ReplaceComponents(rep);
271 }
272 }
273 return site;
274}
275
276/*static*/
[email protected]3d7474ff2011-07-27 17:47:37277bool SiteInstance::IsSameWebSite(content::BrowserContext* browser_context,
[email protected]b6583592012-01-25 19:52:33278 const GURL& real_url1,
279 const GURL& real_url2) {
280 GURL url1 = SiteInstanceImpl::GetEffectiveURL(browser_context, real_url1);
281 GURL url2 = SiteInstanceImpl::GetEffectiveURL(browser_context, real_url2);
[email protected]3a8eecb2010-04-22 23:56:30282
initial.commit09911bf2008-07-26 23:55:29283 // We infer web site boundaries based on the registered domain name of the
[email protected]6705b232008-11-26 00:16:51284 // top-level page and the scheme. We do not pay attention to the port if
285 // one is present, because pages served from different ports can still
286 // access each other if they change their document.domain variable.
initial.commit09911bf2008-07-26 23:55:29287
[email protected]2ee0418e2009-06-26 21:00:43288 // Some special URLs will match the site instance of any other URL. This is
289 // done before checking both of them for validity, since we want these URLs
290 // to have the same site instance as even an invalid one.
291 if (IsURLSameAsAnySiteInstance(url1) || IsURLSameAsAnySiteInstance(url2))
initial.commit09911bf2008-07-26 23:55:29292 return true;
293
294 // If either URL is invalid, they aren't part of the same site.
[email protected]2ee0418e2009-06-26 21:00:43295 if (!url1.is_valid() || !url2.is_valid())
initial.commit09911bf2008-07-26 23:55:29296 return false;
initial.commit09911bf2008-07-26 23:55:29297
[email protected]6705b232008-11-26 00:16:51298 // If the schemes differ, they aren't part of the same site.
[email protected]2ee0418e2009-06-26 21:00:43299 if (url1.scheme() != url2.scheme())
initial.commit09911bf2008-07-26 23:55:29300 return false;
initial.commit09911bf2008-07-26 23:55:29301
[email protected]8ac1a752008-07-31 19:40:37302 return net::RegistryControlledDomainService::SameDomainOrHost(url1, url2);
initial.commit09911bf2008-07-26 23:55:29303}
[email protected]4566f132009-03-12 01:55:13304
[email protected]3a8eecb2010-04-22 23:56:30305/*static*/
[email protected]b6583592012-01-25 19:52:33306GURL SiteInstanceImpl::GetEffectiveURL(
307 content::BrowserContext* browser_context,
308 const GURL& url) {
[email protected]3d7474ff2011-07-27 17:47:37309 return content::GetContentClient()->browser()->
310 GetEffectiveURL(browser_context, url);
[email protected]3a8eecb2010-04-22 23:56:30311}
312
[email protected]b6583592012-01-25 19:52:33313void SiteInstanceImpl::Observe(int type,
314 const content::NotificationSource& source,
315 const content::NotificationDetails& details) {
[email protected]432115822011-07-10 15:52:27316 DCHECK(type == content::NOTIFICATION_RENDERER_PROCESS_TERMINATED);
[email protected]41fb79a52012-06-29 16:34:33317 RenderProcessHost* rph = content::Source<RenderProcessHost>(source).ptr();
[email protected]4566f132009-03-12 01:55:13318 if (rph == process_)
319 process_ = NULL;
320}
[email protected]313b80bd2011-11-23 03:49:10321
[email protected]b6583592012-01-25 19:52:33322void SiteInstanceImpl::LockToOrigin() {
[email protected]313b80bd2011-11-23 03:49:10323 const CommandLine& command_line = *CommandLine::ForCurrentProcess();
324 if (command_line.HasSwitch(switches::kEnableStrictSiteIsolation)) {
[email protected]b9535422012-02-09 01:47:59325 ChildProcessSecurityPolicyImpl* policy =
326 ChildProcessSecurityPolicyImpl::GetInstance();
[email protected]313b80bd2011-11-23 03:49:10327 policy->LockToOrigin(process_->GetID(), site_);
328 }
329}
330