| 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 4ac27dc3c34712a1d1a8ccf6caa4d6a90b1b7252..667fd0c6f0b6e0d7838c880e1bd4979d86e1a216 100644
|
| --- a/content/browser/renderer_host/render_process_host_impl.cc
|
| +++ b/content/browser/renderer_host/render_process_host_impl.cc
|
| @@ -629,6 +629,106 @@ class RenderProcessHostIsReadyObserver : public RenderProcessHostObserver {
|
| DISALLOW_COPY_AND_ASSIGN(RenderProcessHostIsReadyObserver);
|
| };
|
|
|
| +// The following class is used to track the sites each RenderProcessHost is
|
| +// hosting frames for and expecting navigations to. There are two of them per
|
| +// BrowserContext: one for frames and one for navigations.
|
| +//
|
| +// For each site, the SiteProcessCountTracker keeps a map of counts per
|
| +// RenderProcessHost, which represents the number of frames/navigations
|
| +// for this site that are associated with the RenderProcessHost. This allows to
|
| +// quickly lookup a list of RenderProcessHost that can be used by a particular
|
| +// SiteInstance. On the other hand, it does not allow to quickly lookup which
|
| +// sites are hosted by a RenderProcessHost. This class is meant to help reusing
|
| +// RenderProcessHosts among SiteInstances, not to perform security checks for a
|
| +// RenderProcessHost.
|
| +const void* const kCommittedSiteProcessCountTrackerKey =
|
| + "CommittedSiteProcessCountTrackerKey";
|
| +const void* const kPendingSiteProcessCountTrackerKey =
|
| + "PendingSiteProcessCountTrackerKey";
|
| +class SiteProcessCountTracker : public base::SupportsUserData::Data,
|
| + public RenderProcessHostObserver {
|
| + public:
|
| + SiteProcessCountTracker() {}
|
| + ~SiteProcessCountTracker() override { DCHECK(map_.empty()); }
|
| +
|
| + void IncrementSiteProcessCount(const GURL& site_url,
|
| + int render_process_host_id) {
|
| + std::map<ProcessID, Count>& counts_per_process = map_[site_url];
|
| + ++counts_per_process[render_process_host_id];
|
| +
|
| +#ifndef NDEBUG
|
| + // In debug builds, observe the RenderProcessHost destruction, to check
|
| + // that it is properly removed from the map.
|
| + RenderProcessHost* host = RenderProcessHost::FromID(render_process_host_id);
|
| + if (!HasProcess(host))
|
| + host->AddObserver(this);
|
| +#endif
|
| + }
|
| +
|
| + void DecrementSiteProcessCount(const GURL& site_url,
|
| + int render_process_host_id) {
|
| + auto result = map_.find(site_url);
|
| + DCHECK(result != map_.end());
|
| + std::map<ProcessID, Count>& counts_per_process = result->second;
|
| +
|
| + --counts_per_process[render_process_host_id];
|
| + DCHECK(counts_per_process[render_process_host_id] >= 0);
|
| +
|
| + if (counts_per_process[render_process_host_id] == 0)
|
| + counts_per_process.erase(render_process_host_id);
|
| +
|
| + if (counts_per_process.empty())
|
| + map_.erase(site_url);
|
| + }
|
| +
|
| + void FindRenderProcessesForSite(
|
| + const GURL& site_url,
|
| + std::set<RenderProcessHost*>* foreground_processes,
|
| + std::set<RenderProcessHost*>* background_processes) {
|
| + auto result = map_.find(site_url);
|
| + if (result == map_.end())
|
| + return;
|
| +
|
| + std::map<ProcessID, Count>& counts_per_process = result->second;
|
| + for (auto iter : counts_per_process) {
|
| + RenderProcessHost* host = RenderProcessHost::FromID(iter.first);
|
| + DCHECK(host);
|
| + if (host->VisibleWidgetCount())
|
| + foreground_processes->insert(host);
|
| + else
|
| + background_processes->insert(host);
|
| + }
|
| + }
|
| +
|
| + private:
|
| + void RenderProcessHostDestroyed(RenderProcessHost* host) override {
|
| +#ifndef NDEBUG
|
| + host->RemoveObserver(this);
|
| + DCHECK(!HasProcess(host));
|
| +#endif
|
| + }
|
| +
|
| +#ifndef NDEBUG
|
| + // Used in debug builds to ensure that RenderProcessHost don't persist in the
|
| + // map after they've been destroyed.
|
| + bool HasProcess(RenderProcessHost* process) {
|
| + for (auto iter : map_) {
|
| + std::map<ProcessID, Count>& counts_per_process = iter.second;
|
| + for (auto iter_process : counts_per_process) {
|
| + if (iter_process.first == process->GetID())
|
| + return true;
|
| + }
|
| + }
|
| + return false;
|
| + }
|
| +#endif
|
| +
|
| + using ProcessID = int;
|
| + using Count = int;
|
| + using CountPerProcessPerSiteMap = std::map<GURL, std::map<ProcessID, Count>>;
|
| + CountPerProcessPerSiteMap map_;
|
| +};
|
| +
|
| } // namespace
|
|
|
| RendererMainThreadFactoryFunction g_renderer_main_thread_factory = NULL;
|
| @@ -1748,6 +1848,78 @@ 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) {
|
| + if (site_url.is_empty())
|
| + return;
|
| +
|
| + SiteProcessCountTracker* tracker = static_cast<SiteProcessCountTracker*>(
|
| + browser_context->GetUserData(kCommittedSiteProcessCountTrackerKey));
|
| + if (!tracker) {
|
| + tracker = new SiteProcessCountTracker();
|
| + browser_context->SetUserData(kCommittedSiteProcessCountTrackerKey,
|
| + base::WrapUnique(tracker));
|
| + }
|
| + tracker->IncrementSiteProcessCount(site_url, render_process_host->GetID());
|
| +}
|
| +
|
| +// static
|
| +void RenderProcessHostImpl::RemoveFrameWithSite(
|
| + BrowserContext* browser_context,
|
| + RenderProcessHost* render_process_host,
|
| + const GURL& site_url) {
|
| + if (site_url.is_empty())
|
| + return;
|
| +
|
| + SiteProcessCountTracker* tracker = static_cast<SiteProcessCountTracker*>(
|
| + browser_context->GetUserData(kCommittedSiteProcessCountTrackerKey));
|
| + if (!tracker) {
|
| + tracker = new SiteProcessCountTracker();
|
| + browser_context->SetUserData(kCommittedSiteProcessCountTrackerKey,
|
| + base::WrapUnique(tracker));
|
| + }
|
| + tracker->DecrementSiteProcessCount(site_url, render_process_host->GetID());
|
| +}
|
| +
|
| +// static
|
| +void RenderProcessHostImpl::AddExpectedNavigationToSite(
|
| + BrowserContext* browser_context,
|
| + RenderProcessHost* render_process_host,
|
| + const GURL& site_url) {
|
| + if (site_url.is_empty())
|
| + return;
|
| +
|
| + SiteProcessCountTracker* tracker = static_cast<SiteProcessCountTracker*>(
|
| + browser_context->GetUserData(kPendingSiteProcessCountTrackerKey));
|
| + if (!tracker) {
|
| + tracker = new SiteProcessCountTracker();
|
| + browser_context->SetUserData(kPendingSiteProcessCountTrackerKey,
|
| + base::WrapUnique(tracker));
|
| + }
|
| + tracker->IncrementSiteProcessCount(site_url, render_process_host->GetID());
|
| +}
|
| +
|
| +// static
|
| +void RenderProcessHostImpl::RemoveExpectedNavigationToSite(
|
| + BrowserContext* browser_context,
|
| + RenderProcessHost* render_process_host,
|
| + const GURL& site_url) {
|
| + if (site_url.is_empty())
|
| + return;
|
| +
|
| + SiteProcessCountTracker* tracker = static_cast<SiteProcessCountTracker*>(
|
| + browser_context->GetUserData(kPendingSiteProcessCountTrackerKey));
|
| + if (!tracker) {
|
| + tracker = new SiteProcessCountTracker();
|
| + browser_context->SetUserData(kPendingSiteProcessCountTrackerKey,
|
| + base::WrapUnique(tracker));
|
| + }
|
| + tracker->DecrementSiteProcessCount(site_url, render_process_host->GetID());
|
| +}
|
| +
|
| bool RenderProcessHostImpl::IsForGuestsOnly() const {
|
| return is_for_guests_only_;
|
| }
|
| @@ -2874,6 +3046,10 @@ RenderProcessHost* RenderProcessHostImpl::GetProcessHostForSiteInstance(
|
| render_process_host = GetDefaultSubframeProcessHost(
|
| browser_context, site_instance, is_for_guests_only);
|
| break;
|
| + case SiteInstanceImpl::ProcessReusePolicy::REUSE_PENDING_OR_COMMITTED_SITE:
|
| + render_process_host =
|
| + FindReusableProcessHostForSite(browser_context, site_url);
|
| + break;
|
| default:
|
| break;
|
| }
|
| @@ -3266,6 +3442,57 @@ RenderProcessHost* RenderProcessHostImpl::GetDefaultSubframeProcessHost(
|
| return holder->GetProcessHost(site_instance, is_for_guests_only);
|
| }
|
|
|
| +// static
|
| +RenderProcessHost* RenderProcessHostImpl::FindReusableProcessHostForSite(
|
| + BrowserContext* browser_context,
|
| + const GURL& site_url) {
|
| + if (site_url.is_empty())
|
| + return nullptr;
|
| +
|
| + std::set<RenderProcessHost*> eligible_foreground_hosts;
|
| + std::set<RenderProcessHost*> eligible_background_hosts;
|
| +
|
| + // First, add the RenderProcessHosts expecting a navigation to |site_url| to
|
| + // the list of eligible RenderProcessHosts.
|
| + SiteProcessCountTracker* pending_tracker =
|
| + static_cast<SiteProcessCountTracker*>(
|
| + browser_context->GetUserData(kPendingSiteProcessCountTrackerKey));
|
| + if (pending_tracker) {
|
| + pending_tracker->FindRenderProcessesForSite(
|
| + site_url, &eligible_foreground_hosts, &eligible_background_hosts);
|
| + }
|
| +
|
| + if (eligible_foreground_hosts.empty()) {
|
| + // If needed, add the RenderProcessHosts hosting a frame for |site_url| to
|
| + // the list of eligible RenderProcessHosts.
|
| + SiteProcessCountTracker* committed_tracker =
|
| + static_cast<SiteProcessCountTracker*>(
|
| + browser_context->GetUserData(kCommittedSiteProcessCountTrackerKey));
|
| + if (committed_tracker) {
|
| + committed_tracker->FindRenderProcessesForSite(
|
| + site_url, &eligible_foreground_hosts, &eligible_background_hosts);
|
| + }
|
| + }
|
| +
|
| + if (!eligible_foreground_hosts.empty()) {
|
| + int index = base::RandInt(0, eligible_foreground_hosts.size() - 1);
|
| + auto iterator = eligible_foreground_hosts.begin();
|
| + for (int i = 0; i < index; ++i)
|
| + ++iterator;
|
| + return (*iterator);
|
| + }
|
| +
|
| + if (!eligible_background_hosts.empty()) {
|
| + int index = base::RandInt(0, eligible_background_hosts.size() - 1);
|
| + 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(
|
|
|