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
11using content::BrowserThread;
12using content::RenderProcessHost;
13using content::SiteInstance;
14using content::WebContents;
15
16SiteData::SiteData() {}
17
18SiteData::~SiteData() {}
19
20SiteDetails::SiteDetails() {}
21
22SiteDetails::~SiteDetails() {}
23
24void 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
73void 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