Chromium Code Reviews| 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..f309f9adfe228d2f5ebef616257128e097996ab9 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,34 @@ 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()]; |
|
awong
2012/06/27 00:26:54
Having a global map of BrowserContext objects -> d
Charlie Reis
2012/06/27 20:53:43
That would be possible, but it also requires addin
awong
2012/06/27 21:24:40
sgtm
|
| + // Find all instances of this process in the map, to remove. |
| + 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); |
| + } |
| + // Remove them from the map. |
|
awong
2012/06/27 00:26:54
I'd just merge this with the previous comment. Thi
Charlie Reis
2012/06/27 20:53:43
Done.
|
| + 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 +1266,76 @@ 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. |
| + GURL site_url = SiteInstanceImpl::GetSiteForURL(browser_context, url); |
|
awong
2012/06/27 00:26:54
std::string site = SiteInstanceImpl::GetSiteForURL
Charlie Reis
2012/06/27 20:53:43
Done.
|
| + std::string site = site_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]; |
| + |
| + GURL site_url = SiteInstanceImpl::GetSiteForURL(browser_context, url); |
| + std::string site = site_url.possibly_invalid_spec(); |
| + if (!site.empty()) |
| + (*map)[site] = process; |
|
awong
2012/06/27 00:26:54
What happens if the site is empty? The process is
Charlie Reis
2012/06/27 20:53:43
Right. I didn't think we would want to group all
awong
2012/06/27 21:24:40
Cool. Also maybe a comment explaining why the beh
Charlie Reis
2012/06/27 21:42:30
Not sure there's a clear answer, so I added a TODO
|
| +} |
| + |
| 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 |