1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "chrome/browser/site_details.h"
6
7 #include "base/metrics/histogram.h"
8 #include "content/public/browser/browser_thread.h"
9 #include "content/public/browser/render_process_host.h"
10
11 using content::BrowserThread;
12 using content::RenderProcessHost;
13 using content::SiteInstance;
14 using content::WebContents;
15
SiteData()16 SiteData::SiteData() {}
17
~SiteData()18 SiteData::~SiteData() {}
19
SiteDetails()20 SiteDetails::SiteDetails() {}
21
~SiteDetails()22 SiteDetails::~SiteDetails() {}
23
CollectSiteInfo(WebContents * contents,SiteData * site_data)24 void SiteDetails::CollectSiteInfo(WebContents* contents,
25 SiteData* site_data) {
26 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
27 content::BrowserContext* browser_context = contents->GetBrowserContext();
28
29 // Find the BrowsingInstance this WebContents belongs to by iterating over
30 // the "primary" SiteInstances of each BrowsingInstance we've seen so far.
31 SiteInstance* instance = contents->GetSiteInstance();
32 SiteInstance* primary = NULL;
33 for (size_t i = 0; i < site_data->instances.size(); ++i) {
34 if (instance->IsRelatedSiteInstance(site_data->instances[i])) {
35 primary = site_data->instances[i];
36 break;
37 }
38 }
39 if (!primary) {
40 // Remember this as the "primary" SiteInstance of a new BrowsingInstance.
41 primary = instance;
42 site_data->instances.push_back(instance);
43 }
44
45 // Now keep track of how many sites we have in this BrowsingInstance (and
46 // overall), including sites in iframes.
47 std::set<GURL> sites_in_tab = contents->GetSitesInTab();
48 for (std::set<GURL>::iterator iter = sites_in_tab.begin();
49 iter != sites_in_tab.end(); ++iter) {
50 // Skip about:blank, since we won't usually give it its own process.
51 // Because about:blank has no host, its site URL will be blank.
52 if (iter->is_empty())
53 continue;
54
55 // Make sure we don't overcount process-per-site sites, like the NTP.
56 if (RenderProcessHost::ShouldUseProcessPerSite(browser_context, *iter) &&
57 site_data->sites.find(*iter) != site_data->sites.end()) {
58 continue;
59 }
60
61 site_data->sites.insert(*iter);
62 site_data->instance_site_map[primary->GetId()].insert(*iter);
63
64 // Also keep track of how things would look if we only isolated HTTPS sites.
65 // In this model, all HTTP sites are grouped into one "http://" site. HTTPS
66 // and other schemes (e.g., chrome:) are still isolated.
67 GURL https_site = iter->SchemeIs("http") ? GURL("http://") : *iter;
68 site_data->https_sites.insert(https_site);
69 site_data->instance_https_site_map[primary->GetId()].insert(https_site);
70 }
71 }
72
UpdateHistograms(const BrowserContextSiteDataMap & site_data_map,int all_renderer_process_count,int non_renderer_process_count)73 void SiteDetails::UpdateHistograms(
74 const BrowserContextSiteDataMap& site_data_map,
75 int all_renderer_process_count,
76 int non_renderer_process_count) {
77 // Reports a set of site-based process metrics to UMA.
78 int process_limit = RenderProcessHost::GetMaxRendererProcessCount();
79
80 // Sum the number of sites and SiteInstances in each BrowserContext.
81 int num_sites = 0;
82 int num_https_sites = 0;
83 int num_browsing_instances = 0;
84 int num_isolated_site_instances = 0;
85 int num_isolated_https_site_instances = 0;
86 for (BrowserContextSiteDataMap::const_iterator i = site_data_map.begin();
87 i != site_data_map.end(); ++i) {
88 num_sites += i->second.sites.size();
89 num_https_sites += i->second.https_sites.size();
90 num_browsing_instances += i->second.instance_site_map.size();
91 for (BrowsingInstanceSiteMap::const_iterator iter =
92 i->second.instance_site_map.begin();
93 iter != i->second.instance_site_map.end(); ++iter) {
94 num_isolated_site_instances += iter->second.size();
95 }
96 for (BrowsingInstanceSiteMap::const_iterator iter =
97 i->second.instance_https_site_map.begin();
98 iter != i->second.instance_https_site_map.end(); ++iter) {
99 num_isolated_https_site_instances += iter->second.size();
100 }
101 }
102
103 // Predict the number of processes needed when isolating all sites and when
104 // isolating only HTTPS sites.
105 int process_count_lower_bound = num_sites;
106 int process_count_upper_bound = num_sites + process_limit - 1;
107 int process_count_estimate = std::min(
108 num_isolated_site_instances, process_count_upper_bound);
109
110 int process_count_https_lower_bound = num_https_sites;
111 int process_count_https_upper_bound = num_https_sites + process_limit - 1;
112 int process_count_https_estimate = std::min(
113 num_isolated_https_site_instances, process_count_https_upper_bound);
114
115 // Just renderer process count:
116 UMA_HISTOGRAM_COUNTS_100("SiteIsolation.CurrentRendererProcessCount",
117 all_renderer_process_count);
118 UMA_HISTOGRAM_COUNTS_100(
119 "SiteIsolation.BrowsingInstanceCount",
120 num_browsing_instances);
121 UMA_HISTOGRAM_COUNTS_100(
122 "SiteIsolation.IsolateAllSitesProcessCountNoLimit",
123 num_isolated_site_instances);
124 UMA_HISTOGRAM_COUNTS_100(
125 "SiteIsolation.IsolateAllSitesProcessCountLowerBound",
126 process_count_lower_bound);
127 UMA_HISTOGRAM_COUNTS_100(
128 "SiteIsolation.IsolateAllSitesProcessCountEstimate",
129 process_count_estimate);
130 UMA_HISTOGRAM_COUNTS_100(
131 "SiteIsolation.IsolateHttpsSitesProcessCountNoLimit",
132 num_isolated_https_site_instances);
133 UMA_HISTOGRAM_COUNTS_100(
134 "SiteIsolation.IsolateHttpsSitesProcessCountLowerBound",
135 process_count_https_lower_bound);
136 UMA_HISTOGRAM_COUNTS_100(
137 "SiteIsolation.IsolateHttpsSitesProcessCountEstimate",
138 process_count_https_estimate);
139
140 // Total process count:
141 UMA_HISTOGRAM_COUNTS_100(
142 "SiteIsolation.IsolateAllSitesTotalProcessCountEstimate",
143 process_count_estimate + non_renderer_process_count);
144 UMA_HISTOGRAM_COUNTS_100(
145 "SiteIsolation.IsolateHttpsSitesTotalProcessCountEstimate",
146 process_count_https_estimate + non_renderer_process_count);
147 }
148