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 02f2bf99b06e234512fd311e96e72b0f3838a808..3870025b02cf754dd469e6407fcf415a24a8a660 100644 |
--- a/content/browser/renderer_host/render_process_host_impl.cc |
+++ b/content/browser/renderer_host/render_process_host_impl.cc |
@@ -564,6 +564,66 @@ class WorkerURLLoaderFactoryProviderImpl |
scoped_refptr<ServiceWorkerContextWrapper> service_worker_context_; |
}; |
+// The following object is used to keep track of which sites |
+// RenderProcessHosts are hosting frames and expecting navigations to. |
+// There are two of them per BrowserContext, one for frames and one for |
+// navigations. |
+const void* const kFrameSiteCountPerProcessTrackerKey = |
Charlie Reis
2017/05/15 03:41:52
I think pending and committed are probably better
clamy
2017/05/16 14:50:46
Done.
|
+ "FrameSiteCountPerProcessTrackerKey"; |
+const void* const kNavigationSiteCountPerProcessTrackerKey = |
+ "NavigationSiteCountPerProcessTrackerKey"; |
+class SiteCountPerProcessTracker : public base::SupportsUserData::Data, |
clamy
2017/05/04 16:01:01
This class + data structure looks a bit weird. Thi
nasko
2017/05/05 05:22:00
Yuck! Yet another reason to hate MockRenderProcess
Charlie Reis
2017/05/15 03:41:52
If we really want per-RPH state, we should find a
clamy
2017/05/15 15:21:15
This is how I had written it initially. However, w
Charlie Reis
2017/05/15 23:46:18
Interesting! Yes, I hadn't thought about the proc
clamy
2017/05/16 14:50:46
I've reversed the map as asked, and remove the obs
|
+ public RenderProcessHostObserver { |
+ public: |
+ SiteCountPerProcessTracker() {} |
+ ~SiteCountPerProcessTracker() override {} |
+ |
+ void AddCountForSiteForProcess(RenderProcessHost* render_process_host, |
+ std::string site) { |
nasko
2017/05/05 05:22:00
Why accept the site as a string and not a GURL?
clamy
2017/05/16 14:50:46
Done.
|
+ std::map<std::string, int>& counts_per_site = map_[render_process_host]; |
nasko
2017/05/05 05:22:00
I assume you are using operator[] intentionally he
clamy
2017/05/05 15:10:11
Yes. We want to create one if we don't have one, a
|
+ if (counts_per_site.empty()) |
+ render_process_host->AddObserver(this); |
+ ++counts_per_site[site]; |
+ } |
+ |
+ void RemoveCountForSiteForProcess(RenderProcessHost* render_process_host, |
+ std::string site) { |
+ std::map<std::string, int>& counts_per_site = map_[render_process_host]; |
nasko
2017/05/05 05:22:00
Shouldn't this be map_.find()?
clamy
2017/05/16 14:50:46
Done.
|
+ --counts_per_site[site]; |
+ DCHECK(counts_per_site[site] >= 0); |
+ if (counts_per_site[site] == 0) |
+ counts_per_site.erase(site); |
+ if (counts_per_site.empty()) { |
+ map_.erase(render_process_host); |
+ render_process_host->RemoveObserver(this); |
+ } |
+ } |
+ |
+ void RenderProcessHostDestroyed(RenderProcessHost* host) override { |
+ map_.erase(host); |
+ } |
+ |
+ void FindRenderProcessesForSite( |
+ std::string site, |
+ std::set<RenderProcessHost*>* foreground_processes, |
+ std::set<RenderProcessHost*>* background_processes) { |
+ for (auto site_counts_per_process : map_) { |
+ if (site_counts_per_process.second.count(site) > 0) { |
+ RenderProcessHost* host = site_counts_per_process.first; |
+ if (host->VisibleWidgetCount()) |
+ foreground_processes->insert(host); |
+ else |
+ background_processes->insert(host); |
+ } |
+ } |
+ } |
+ |
+ private: |
+ using SiteCountPerProcessMap = |
+ std::map<RenderProcessHost*, std::map<std::string, int>>; |
+ SiteCountPerProcessMap map_; |
+}; |
+ |
} // namespace |
RendererMainThreadFactoryFunction g_renderer_main_thread_factory = NULL; |
@@ -1684,6 +1744,90 @@ void RenderProcessHostImpl::set_render_process_host_factory( |
g_render_process_host_factory_ = rph_factory; |
} |
+// static |
+void RenderProcessHostImpl::AddFrameWithSite( |
+ BrowserContext* browser_context, |
+ RenderProcessHost* render_process_host, |
+ const GURL& site_url) { |
+ std::string site = SiteInstance::GetSiteForURL(browser_context, site_url) |
+ .possibly_invalid_spec(); |
nasko
2017/05/05 05:22:00
Why possibly_invalid_spec()? Shouldn't an non-empt
clamy
2017/05/16 14:50:46
It's now taking a GURL.
|
+ if (site.empty()) |
+ return; |
+ |
+ SiteCountPerProcessTracker* tracker = |
+ static_cast<SiteCountPerProcessTracker*>( |
+ browser_context->GetUserData(kFrameSiteCountPerProcessTrackerKey)); |
+ if (!tracker) { |
+ tracker = new SiteCountPerProcessTracker(); |
+ browser_context->SetUserData(kFrameSiteCountPerProcessTrackerKey, |
+ base::WrapUnique(tracker)); |
+ } |
+ tracker->AddCountForSiteForProcess(render_process_host, site); |
+} |
+ |
+// static |
+void RenderProcessHostImpl::RemoveFrameWithSite( |
+ BrowserContext* browser_context, |
+ RenderProcessHost* render_process_host, |
+ const GURL& site_url) { |
+ std::string site = SiteInstance::GetSiteForURL(browser_context, site_url) |
+ .possibly_invalid_spec(); |
+ if (site.empty()) |
+ return; |
+ |
+ SiteCountPerProcessTracker* tracker = |
+ static_cast<SiteCountPerProcessTracker*>( |
+ browser_context->GetUserData(kFrameSiteCountPerProcessTrackerKey)); |
+ if (!tracker) { |
+ tracker = new SiteCountPerProcessTracker(); |
+ browser_context->SetUserData(kFrameSiteCountPerProcessTrackerKey, |
+ base::WrapUnique(tracker)); |
+ } |
+ tracker->RemoveCountForSiteForProcess(render_process_host, site); |
+} |
+ |
+// static |
+void RenderProcessHostImpl::AddExpectedNavigationToSite( |
+ BrowserContext* browser_context, |
+ RenderProcessHost* render_process_host, |
+ const GURL& site_url) { |
+ std::string site = SiteInstance::GetSiteForURL(browser_context, site_url) |
+ .possibly_invalid_spec(); |
+ if (site.empty()) |
+ return; |
+ |
+ SiteCountPerProcessTracker* tracker = |
+ static_cast<SiteCountPerProcessTracker*>(browser_context->GetUserData( |
+ kNavigationSiteCountPerProcessTrackerKey)); |
+ if (!tracker) { |
+ tracker = new SiteCountPerProcessTracker(); |
+ browser_context->SetUserData(kNavigationSiteCountPerProcessTrackerKey, |
+ base::WrapUnique(tracker)); |
+ } |
+ tracker->AddCountForSiteForProcess(render_process_host, site); |
+} |
+ |
+// static |
+void RenderProcessHostImpl::RemoveExpectedNavigationToSite( |
+ BrowserContext* browser_context, |
+ RenderProcessHost* render_process_host, |
+ const GURL& site_url) { |
+ std::string site = SiteInstance::GetSiteForURL(browser_context, site_url) |
+ .possibly_invalid_spec(); |
+ if (site.empty()) |
+ return; |
+ |
+ SiteCountPerProcessTracker* tracker = |
+ static_cast<SiteCountPerProcessTracker*>(browser_context->GetUserData( |
+ kNavigationSiteCountPerProcessTrackerKey)); |
+ if (!tracker) { |
+ tracker = new SiteCountPerProcessTracker(); |
+ browser_context->SetUserData(kNavigationSiteCountPerProcessTrackerKey, |
+ base::WrapUnique(tracker)); |
+ } |
+ tracker->RemoveCountForSiteForProcess(render_process_host, site); |
+} |
+ |
bool RenderProcessHostImpl::IsForGuestsOnly() const { |
return is_for_guests_only_; |
} |
@@ -2796,6 +2940,10 @@ RenderProcessHost* RenderProcessHostImpl::GetProcessHostForSiteInstance( |
DCHECK(SiteIsolationPolicy::IsTopDocumentIsolationEnabled()); |
render_process_host = |
GetDefaultSubframeProcessHost(browser_context, site_instance); |
+ case SiteInstanceImpl::ProcessReusePolicy:: |
+ REUSE_CHECKING_FRAMES_AND_NAVIGATIONS: |
+ render_process_host = |
+ FindReusableProcessHostForSite(browser_context, site_url); |
break; |
default: |
break; |
@@ -3168,6 +3316,57 @@ RenderProcessHost* RenderProcessHostImpl::GetDefaultSubframeProcessHost( |
return holder->GetProcessHost(site_instance); |
} |
+// static |
+RenderProcessHost* RenderProcessHostImpl::FindReusableProcessHostForSite( |
+ BrowserContext* browser_context, |
+ const GURL& site_url) { |
+ std::string site = SiteInstance::GetSiteForURL(browser_context, site_url) |
+ .possibly_invalid_spec(); |
+ if (site.empty()) |
+ return nullptr; |
+ |
+ std::set<RenderProcessHost*> eligible_foreground_hosts; |
+ std::set<RenderProcessHost*> eligible_background_hosts; |
+ |
+ // Add the RenderProcessHosts hosting a frame rendering site to the list of |
nasko
2017/05/05 05:22:00
nit: "... hosting a frame for |site| to ..."
clamy
2017/05/16 14:50:46
Done.
|
+ // eligible RenderProcessHosts. |
+ SiteCountPerProcessTracker* frame_tracker = |
+ static_cast<SiteCountPerProcessTracker*>( |
+ browser_context->GetUserData(kFrameSiteCountPerProcessTrackerKey)); |
+ if (frame_tracker) { |
+ frame_tracker->FindRenderProcessesForSite(site, &eligible_foreground_hosts, |
+ &eligible_background_hosts); |
+ } |
+ |
+ // Add the RenderProcessHosts expecting a navigation to site to the list of |
+ // eligible RenderProcessHosts. |
+ SiteCountPerProcessTracker* navigation_tracker = |
clamy
2017/05/04 16:01:01
if we want to implement process-per-site using thi
|
+ static_cast<SiteCountPerProcessTracker*>(browser_context->GetUserData( |
+ kNavigationSiteCountPerProcessTrackerKey)); |
+ if (frame_tracker) { |
+ navigation_tracker->FindRenderProcessesForSite( |
+ site, &eligible_foreground_hosts, &eligible_background_hosts); |
+ } |
+ |
+ if (!eligible_foreground_hosts.empty()) { |
+ int index = rand() % eligible_foreground_hosts.size(); |
nasko
2017/05/05 05:22:00
base::RandInt
clamy
2017/05/16 14:50:46
Done.
|
+ auto iterator = eligible_foreground_hosts.begin(); |
+ for (int i = 0; i < index; ++i) |
+ ++iterator; |
+ return (*iterator); |
+ } |
+ |
+ if (!eligible_background_hosts.empty()) { |
+ int index = rand() % eligible_background_hosts.size(); |
nasko
2017/05/05 05:22:00
base::RandInt
clamy
2017/05/16 14:50:46
Done.
|
+ auto iterator = eligible_background_hosts.begin(); |
+ for (int i = 0; i < index; ++i) |
+ ++iterator; |
+ return (*iterator); |
+ } |
+ |
+ return nullptr; |
+} |
+ |
#if BUILDFLAG(ENABLE_WEBRTC) |
void RenderProcessHostImpl::OnRegisterAecDumpConsumer(int id) { |
BrowserThread::PostTask( |