|  | // Copyright 2013 The Chromium Authors. All rights reserved. | 
|  | // Use of this source code is governed by a BSD-style license that can be | 
|  | // found in the LICENSE file. | 
|  |  | 
|  | #include "chrome/browser/site_details.h" | 
|  |  | 
|  | #include "base/metrics/histogram.h" | 
|  | #include "content/public/browser/browser_thread.h" | 
|  | #include "content/public/browser/render_process_host.h" | 
|  |  | 
|  | using content::BrowserThread; | 
|  | using content::RenderProcessHost; | 
|  | using content::SiteInstance; | 
|  | using content::WebContents; | 
|  |  | 
|  | SiteData::SiteData() {} | 
|  |  | 
|  | SiteData::~SiteData() {} | 
|  |  | 
|  | SiteDetails::SiteDetails() {} | 
|  |  | 
|  | SiteDetails::~SiteDetails() {} | 
|  |  | 
|  | void SiteDetails::CollectSiteInfo(WebContents* contents, | 
|  | SiteData* site_data) { | 
|  | DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 
|  | content::BrowserContext* browser_context = contents->GetBrowserContext(); | 
|  |  | 
|  | // Find the BrowsingInstance this WebContents belongs to by iterating over | 
|  | // the "primary" SiteInstances of each BrowsingInstance we've seen so far. | 
|  | SiteInstance* instance = contents->GetSiteInstance(); | 
|  | SiteInstance* primary = NULL; | 
|  | for (size_t i = 0; i < site_data->instances.size(); ++i) { | 
|  | if (instance->IsRelatedSiteInstance(site_data->instances[i])) { | 
|  | primary = site_data->instances[i]; | 
|  | break; | 
|  | } | 
|  | } | 
|  | if (!primary) { | 
|  | // Remember this as the "primary" SiteInstance of a new BrowsingInstance. | 
|  | primary = instance; | 
|  | site_data->instances.push_back(instance); | 
|  | } | 
|  |  | 
|  | // Now keep track of how many sites we have in this BrowsingInstance (and | 
|  | // overall), including sites in iframes. | 
|  | std::set<GURL> sites_in_tab = contents->GetSitesInTab(); | 
|  | for (std::set<GURL>::iterator iter = sites_in_tab.begin(); | 
|  | iter != sites_in_tab.end(); ++iter) { | 
|  | // Skip about:blank, since we won't usually give it its own process. | 
|  | // Because about:blank has no host, its site URL will be blank. | 
|  | if (iter->is_empty()) | 
|  | continue; | 
|  |  | 
|  | // Make sure we don't overcount process-per-site sites, like the NTP. | 
|  | if (RenderProcessHost::ShouldUseProcessPerSite(browser_context, *iter) && | 
|  | site_data->sites.find(*iter) != site_data->sites.end()) { | 
|  | continue; | 
|  | } | 
|  |  | 
|  | site_data->sites.insert(*iter); | 
|  | site_data->instance_site_map[primary->GetId()].insert(*iter); | 
|  |  | 
|  | // Also keep track of how things would look if we only isolated HTTPS sites. | 
|  | // In this model, all HTTP sites are grouped into one "http://" site.  HTTPS | 
|  | // and other schemes (e.g., chrome:) are still isolated. | 
|  | GURL https_site = iter->SchemeIs("http") ? GURL("http://") : *iter; | 
|  | site_data->https_sites.insert(https_site); | 
|  | site_data->instance_https_site_map[primary->GetId()].insert(https_site); | 
|  | } | 
|  | } | 
|  |  | 
|  | void SiteDetails::UpdateHistograms( | 
|  | const BrowserContextSiteDataMap& site_data_map, | 
|  | int all_renderer_process_count, | 
|  | int non_renderer_process_count) { | 
|  | // Reports a set of site-based process metrics to UMA. | 
|  | int process_limit = RenderProcessHost::GetMaxRendererProcessCount(); | 
|  |  | 
|  | // Sum the number of sites and SiteInstances in each BrowserContext. | 
|  | int num_sites = 0; | 
|  | int num_https_sites = 0; | 
|  | int num_browsing_instances = 0; | 
|  | int num_isolated_site_instances = 0; | 
|  | int num_isolated_https_site_instances = 0; | 
|  | for (BrowserContextSiteDataMap::const_iterator i = site_data_map.begin(); | 
|  | i != site_data_map.end(); ++i) { | 
|  | num_sites += i->second.sites.size(); | 
|  | num_https_sites += i->second.https_sites.size(); | 
|  | num_browsing_instances += i->second.instance_site_map.size(); | 
|  | for (BrowsingInstanceSiteMap::const_iterator iter = | 
|  | i->second.instance_site_map.begin(); | 
|  | iter != i->second.instance_site_map.end(); ++iter) { | 
|  | num_isolated_site_instances += iter->second.size(); | 
|  | } | 
|  | for (BrowsingInstanceSiteMap::const_iterator iter = | 
|  | i->second.instance_https_site_map.begin(); | 
|  | iter != i->second.instance_https_site_map.end(); ++iter) { | 
|  | num_isolated_https_site_instances += iter->second.size(); | 
|  | } | 
|  | } | 
|  |  | 
|  | // Predict the number of processes needed when isolating all sites and when | 
|  | // isolating only HTTPS sites. | 
|  | int process_count_lower_bound = num_sites; | 
|  | int process_count_upper_bound = num_sites + process_limit - 1; | 
|  | int process_count_estimate = std::min( | 
|  | num_isolated_site_instances, process_count_upper_bound); | 
|  |  | 
|  | int process_count_https_lower_bound = num_https_sites; | 
|  | int process_count_https_upper_bound = num_https_sites + process_limit - 1; | 
|  | int process_count_https_estimate = std::min( | 
|  | num_isolated_https_site_instances, process_count_https_upper_bound); | 
|  |  | 
|  | // Just renderer process count: | 
|  | UMA_HISTOGRAM_COUNTS_100("SiteIsolation.CurrentRendererProcessCount", | 
|  | all_renderer_process_count); | 
|  | UMA_HISTOGRAM_COUNTS_100( | 
|  | "SiteIsolation.BrowsingInstanceCount", | 
|  | num_browsing_instances); | 
|  | UMA_HISTOGRAM_COUNTS_100( | 
|  | "SiteIsolation.IsolateAllSitesProcessCountNoLimit", | 
|  | num_isolated_site_instances); | 
|  | UMA_HISTOGRAM_COUNTS_100( | 
|  | "SiteIsolation.IsolateAllSitesProcessCountLowerBound", | 
|  | process_count_lower_bound); | 
|  | UMA_HISTOGRAM_COUNTS_100( | 
|  | "SiteIsolation.IsolateAllSitesProcessCountEstimate", | 
|  | process_count_estimate); | 
|  | UMA_HISTOGRAM_COUNTS_100( | 
|  | "SiteIsolation.IsolateHttpsSitesProcessCountNoLimit", | 
|  | num_isolated_https_site_instances); | 
|  | UMA_HISTOGRAM_COUNTS_100( | 
|  | "SiteIsolation.IsolateHttpsSitesProcessCountLowerBound", | 
|  | process_count_https_lower_bound); | 
|  | UMA_HISTOGRAM_COUNTS_100( | 
|  | "SiteIsolation.IsolateHttpsSitesProcessCountEstimate", | 
|  | process_count_https_estimate); | 
|  |  | 
|  | // Total process count: | 
|  | UMA_HISTOGRAM_COUNTS_100( | 
|  | "SiteIsolation.IsolateAllSitesTotalProcessCountEstimate", | 
|  | process_count_estimate + non_renderer_process_count); | 
|  | UMA_HISTOGRAM_COUNTS_100( | 
|  | "SiteIsolation.IsolateHttpsSitesTotalProcessCountEstimate", | 
|  | process_count_https_estimate + non_renderer_process_count); | 
|  | } |