| Index: content/browser/renderer_host/render_process_host_impl.cc
|
| diff --git a/content/browser/renderer_host/render_process_host_impl.cc b/content/browser/renderer_host/render_process_host_impl.cc
|
| index 8e759337fd632a9af30667f8d2ec36c1a8890b58..e450a5ea03b98deded425ca8dd141b303321534b 100644
|
| --- a/content/browser/renderer_host/render_process_host_impl.cc
|
| +++ b/content/browser/renderer_host/render_process_host_impl.cc
|
| @@ -91,6 +91,7 @@
|
| #include "content/public/browser/browser_context.h"
|
| #include "content/public/browser/content_browser_client.h"
|
| #include "content/public/browser/notification_service.h"
|
| +#include "content/public/browser/render_process_host_factory.h"
|
| #include "content/public/browser/resource_context.h"
|
| #include "content/public/browser/user_metrics.h"
|
| #include "content/public/browser/web_ui_controller_factory.h"
|
| @@ -208,6 +209,11 @@ class RendererURLRequestContextSelector
|
| base::LazyInstance<IDMap<RenderProcessHost> >::Leaky
|
| g_all_hosts = LAZY_INSTANCE_INITIALIZER;
|
|
|
| +// The global map of BrowsingContexts to SiteProcessMaps, allowing us to
|
| +// implement process-per-site mode within each BrowsingContext.
|
| +base::LazyInstance<RenderProcessHostImpl::ContextSiteProcessMap>::Leaky
|
| + g_context_site_process_map_ = LAZY_INSTANCE_INITIALIZER;
|
| +
|
| } // namespace
|
|
|
| // Stores the maximum number of renderer processes the content module can
|
| @@ -338,7 +344,7 @@ RenderProcessHostImpl::~RenderProcessHostImpl() {
|
| }
|
|
|
| ClearTransportDIBCache();
|
| - UnregisterHost(GetID());
|
| + UnregisterHost(GetID(), this);
|
| }
|
|
|
| void RenderProcessHostImpl::EnableSendQueue() {
|
| @@ -1071,7 +1077,7 @@ void RenderProcessHostImpl::Cleanup() {
|
|
|
| // Remove ourself from the list of renderer processes so that we can't be
|
| // reused in between now and when the Delete task runs.
|
| - g_all_hosts.Get().Remove(GetID());
|
| + UnregisterHost(GetID(), this);
|
| }
|
| }
|
|
|
| @@ -1130,9 +1136,33 @@ void RenderProcessHostImpl::RegisterHost(int host_id, RenderProcessHost* host) {
|
| }
|
|
|
| // static
|
| -void RenderProcessHostImpl::UnregisterHost(int host_id) {
|
| +void RenderProcessHostImpl::UnregisterHost(int host_id,
|
| + RenderProcessHost* host) {
|
| if (g_all_hosts.Get().Lookup(host_id))
|
| g_all_hosts.Get().Remove(host_id);
|
| +
|
| + // Look up the map of site to process for the given browser_context,
|
| + // in case we need to remove this process from it. It will be registered
|
| + // under any sites it rendered that use process-per-site mode.
|
| + RenderProcessHostImpl::SiteProcessMap* map =
|
| + &g_context_site_process_map_.Get()[host->GetBrowserContext()];
|
| + // Find all instances of this process in the map, then separately remove them.
|
| + std::set<std::string> sites;
|
| + for (RenderProcessHostImpl::SiteProcessMap::const_iterator i = map->begin();
|
| + i != map->end();
|
| + i++) {
|
| + if (i->second == host)
|
| + sites.insert(i->first);
|
| + }
|
| + for (std::set<std::string>::iterator i = sites.begin();
|
| + i != sites.end();
|
| + i++) {
|
| + RenderProcessHostImpl::SiteProcessMap::iterator iter = map->find(*i);
|
| + if (iter != map->end()) {
|
| + DCHECK_EQ(iter->second, host);
|
| + map->erase(iter);
|
| + }
|
| + }
|
| }
|
|
|
| // static
|
| @@ -1235,10 +1265,78 @@ RenderProcessHost* RenderProcessHost::GetExistingProcessHost(
|
| return NULL;
|
| }
|
|
|
| +// static
|
| +bool RenderProcessHost::ShouldUseProcessPerSite(BrowserContext* browser_context,
|
| + const GURL& url) {
|
| + // Returns true if we should use the process-per-site model. This will be
|
| + // the case if the --process-per-site switch is specified, or in
|
| + // process-per-site-instance for particular sites (e.g., WebUI).
|
| +
|
| + const CommandLine& command_line = *CommandLine::ForCurrentProcess();
|
| + if (command_line.HasSwitch(switches::kProcessPerSite))
|
| + return true;
|
| +
|
| + // We want to consolidate particular sites like WebUI when we are using
|
| + // process-per-tab or process-per-site-instance models.
|
| + // Note that --single-process is handled in ShouldTryToUseExistingProcessHost.
|
| +
|
| + if (content::GetContentClient()->browser()->
|
| + ShouldUseProcessPerSite(browser_context, url)) {
|
| + return true;
|
| + }
|
| +
|
| + // DevTools pages have WebUI type but should not reuse the same host.
|
| + WebUIControllerFactory* factory =
|
| + content::GetContentClient()->browser()->GetWebUIControllerFactory();
|
| + if (factory &&
|
| + factory->UseWebUIForURL(browser_context, url) &&
|
| + !url.SchemeIs(chrome::kChromeDevToolsScheme)) {
|
| + return true;
|
| + }
|
| +
|
| + // In all other cases, don't use process-per-site logic.
|
| + return false;
|
| +}
|
| +
|
| +// static
|
| +RenderProcessHost* RenderProcessHost::GetProcessHostForSite(
|
| + BrowserContext* browser_context,
|
| + const GURL& url) {
|
| + // Look up the map of site to process for the given browser_context.
|
| + RenderProcessHostImpl::SiteProcessMap* map =
|
| + &g_context_site_process_map_.Get()[browser_context];
|
| +
|
| + // See if we have an existing process for this site.
|
| + std::string site = SiteInstanceImpl::GetSiteForURL(browser_context, url)
|
| + .possibly_invalid_spec();
|
| + RenderProcessHostImpl::SiteProcessMap::iterator i = map->find(site);
|
| + if (i != map->end())
|
| + return i->second;
|
| +
|
| + // Otherwise, the caller should create a new process and register it.
|
| + return NULL;
|
| +}
|
| +
|
| +void RenderProcessHost::RegisterProcessHostForSite(
|
| + BrowserContext* browser_context,
|
| + RenderProcessHost* process,
|
| + const GURL& url) {
|
| + // Look up the map of site to process for the given browser_context.
|
| + RenderProcessHostImpl::SiteProcessMap* map =
|
| + &g_context_site_process_map_.Get()[browser_context];
|
| +
|
| + // TODO(creis): Determine if it's better to allow registration of
|
| + // empty sites or not. For now, group anything from which we can't parse
|
| + // a site into the same process, when using --process-per-site.
|
| + std::string site = SiteInstanceImpl::GetSiteForURL(browser_context, url)
|
| + .possibly_invalid_spec();
|
| + (*map)[site] = process;
|
| +}
|
| +
|
| void RenderProcessHostImpl::ProcessDied(base::ProcessHandle handle,
|
| - base::TerminationStatus status,
|
| - int exit_code,
|
| - bool was_alive) {
|
| + base::TerminationStatus status,
|
| + int exit_code,
|
| + bool was_alive) {
|
| // Our child process has died. If we didn't expect it, it's a crash.
|
| // In any case, we need to let everyone know it's gone.
|
| // The OnChannelError notification can fire multiple times due to nested sync
|
|
|