Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/browser/site_details.h" | 5 #include "chrome/browser/site_details.h" |
| 6 | 6 |
| 7 #include "base/metrics/histogram.h" | 7 #include "base/metrics/histogram.h" |
| 8 #include "content/public/browser/browser_thread.h" | 8 #include "content/public/browser/browser_thread.h" |
| 9 #include "content/public/browser/render_frame_host.h" | 9 #include "content/public/browser/render_frame_host.h" |
| 10 #include "content/public/browser/render_process_host.h" | 10 #include "content/public/browser/render_process_host.h" |
| 11 #include "url/origin.h" | 11 #include "url/origin.h" |
| 12 | 12 |
| 13 #if defined(ENABLE_EXTENSIONS) | 13 #if defined(ENABLE_EXTENSIONS) |
| 14 #include "extensions/browser/extension_registry.h" | 14 #include "extensions/browser/extension_registry.h" |
| 15 #include "extensions/common/constants.h" | 15 #include "extensions/common/constants.h" |
| 16 #include "extensions/common/extension.h" | 16 #include "extensions/common/extension.h" |
| 17 #endif | 17 #endif |
| 18 | 18 |
| 19 using content::BrowserContext; | 19 using content::BrowserContext; |
| 20 using content::BrowserThread; | 20 using content::BrowserThread; |
| 21 using content::RenderFrameHost; | 21 using content::RenderFrameHost; |
| 22 using content::RenderProcessHost; | 22 using content::RenderProcessHost; |
| 23 using content::SiteInstance; | 23 using content::SiteInstance; |
| 24 using content::WebContents; | 24 using content::WebContents; |
| 25 | 25 |
| 26 namespace { | 26 namespace { |
| 27 | 27 |
| 28 bool ShouldIsolate(BrowserContext* browser_context, | 28 bool ShouldIsolate(BrowserContext* browser_context, |
| 29 const IsolationScenario* scenario, | 29 const IsolationScenario& scenario, |
| 30 const GURL& site) { | 30 const GURL& site) { |
| 31 switch (scenario->policy) { | 31 switch (scenario.policy) { |
| 32 case ISOLATE_NOTHING: | 32 case ISOLATE_NOTHING: |
| 33 return false; | 33 return false; |
| 34 case ISOLATE_ALL_SITES: | 34 case ISOLATE_ALL_SITES: |
| 35 return true; | 35 return true; |
| 36 case ISOLATE_HTTPS_SITES: | 36 case ISOLATE_HTTPS_SITES: |
| 37 // Note: For estimation purposes "isolate https sites" is really | 37 // Note: For estimation purposes "isolate https sites" is really |
| 38 // implemented as "isolate non-http sites". This means that, for example, | 38 // implemented as "isolate non-http sites". This means that, for example, |
| 39 // the New Tab Page gets counted as two processes under this policy, and | 39 // the New Tab Page gets counted as two processes under this policy, and |
| 40 // extensions are isolated as well. | 40 // extensions are isolated as well. |
| 41 return !site.SchemeIs(url::kHttpScheme); | 41 return !site.SchemeIs(url::kHttpScheme); |
| 42 case ISOLATE_EXTENSIONS: { | 42 case ISOLATE_EXTENSIONS: { |
| 43 #if !defined(ENABLE_EXTENSIONS) | 43 #if !defined(ENABLE_EXTENSIONS) |
| 44 return false; | 44 return false; |
| 45 #else | 45 #else |
| 46 if (!site.SchemeIs(extensions::kExtensionScheme)) | 46 if (!site.SchemeIs(extensions::kExtensionScheme)) |
| 47 return false; | 47 return false; |
| 48 extensions::ExtensionRegistry* registry = | 48 extensions::ExtensionRegistry* registry = |
| 49 extensions::ExtensionRegistry::Get(browser_context); | 49 extensions::ExtensionRegistry::Get(browser_context); |
| 50 const extensions::Extension* extension = | 50 const extensions::Extension* extension = |
| 51 registry->enabled_extensions().GetExtensionOrAppByURL(site); | 51 registry->enabled_extensions().GetExtensionOrAppByURL(site); |
| 52 return extension && !extension->is_hosted_app(); | 52 return extension && !extension->is_hosted_app(); |
| 53 #endif | 53 #endif |
| 54 } | 54 } |
| 55 } | 55 } |
| 56 NOTREACHED(); | 56 NOTREACHED(); |
| 57 return true; | 57 return true; |
| 58 } | 58 } |
| 59 | 59 |
| 60 // Walk the frame tree and update |scenario|'s data for the given frame. Memoize | |
| 61 // each frame's computed URL in |frame_urls| so it can be reused when visiting | |
| 62 // its children. | |
| 63 void CollectForScenario(std::map<RenderFrameHost*, GURL>* frame_urls, | |
| 64 SiteInstance* primary, | |
| 65 IsolationScenario* scenario, | |
| 66 RenderFrameHost* frame) { | |
| 67 BrowserContext* context = primary->GetBrowserContext(); | |
| 68 | |
| 69 // Determine the site from the frame's origin, with a fallback to the | |
| 70 // frame's URL. In cases like <iframe sandbox>, we can wind up with an http | |
| 71 // URL but a unique origin. The origin of the resource will still determine | |
| 72 // process placement. | |
| 73 url::Origin origin = frame->GetLastCommittedOrigin(); | |
| 74 GURL site = SiteInstance::GetSiteForURL( | |
| 75 context, origin.unique() ? frame->GetLastCommittedURL() | |
| 76 : GURL(origin.Serialize())); | |
| 77 | |
| 78 bool should_isolate = ShouldIsolate(context, scenario, site); | |
| 79 | |
| 80 // Treat a subframe as part of its parent site if neither needs isolation. | |
| 81 if (!should_isolate && frame->GetParent()) { | |
| 82 GURL parent_site = (*frame_urls)[frame->GetParent()]; | |
| 83 if (!ShouldIsolate(context, scenario, parent_site)) | |
| 84 site = parent_site; | |
| 85 } | |
| 86 | |
| 87 bool process_per_site = | |
| 88 site.is_valid() && | |
| 89 RenderProcessHost::ShouldUseProcessPerSite(context, site); | |
| 90 | |
| 91 // If we don't need a dedicated process, and aren't living in a process- | |
| 92 // per-site process, we are nothing special: collapse our URL to a dummy | |
| 93 // site. | |
| 94 if (!process_per_site && !should_isolate) | |
| 95 site = GURL("http://"); | |
| 96 | |
| 97 // We model process-per-site by only inserting those sites into the first | |
| 98 // browsing instance in which they appear. | |
| 99 if (scenario->sites.insert(site).second || !process_per_site) | |
| 100 scenario->browsing_instance_site_map[primary->GetId()].insert(site); | |
| 101 | |
| 102 // Record our result in |frame_urls| for use by children. | |
| 103 (*frame_urls)[frame] = site; | |
| 104 } | |
| 105 | |
| 106 content::SiteInstance* DeterminePrimarySiteInstance( | 60 content::SiteInstance* DeterminePrimarySiteInstance( |
| 107 content::SiteInstance* instance, | 61 content::SiteInstance* instance, |
| 108 SiteData* site_data) { | 62 SiteData* site_data) { |
| 109 // Find the BrowsingInstance this WebContents belongs to by iterating over | 63 // Find the BrowsingInstance this WebContents belongs to by iterating over |
| 110 // the "primary" SiteInstances of each BrowsingInstance we've seen so far. | 64 // the "primary" SiteInstances of each BrowsingInstance we've seen so far. |
| 111 for (auto& existing_site_instance : site_data->instances) { | 65 for (auto& existing_site_instance : site_data->instances) { |
| 112 if (instance->IsRelatedSiteInstance(existing_site_instance.first)) { | 66 if (instance->IsRelatedSiteInstance(existing_site_instance.first)) { |
| 113 existing_site_instance.second.insert(instance); | 67 existing_site_instance.second.insert(instance); |
| 114 return existing_site_instance.first; | 68 return existing_site_instance.first; |
| 115 } | 69 } |
| 116 } | 70 } |
| 117 | 71 |
| 118 // Add |instance| as the "primary" SiteInstance of a new BrowsingInstance. | 72 // Add |instance| as the "primary" SiteInstance of a new BrowsingInstance. |
| 119 site_data->instances[instance].clear(); | 73 site_data->instances[instance].clear(); |
| 120 site_data->instances[instance].insert(instance); | 74 site_data->instances[instance].insert(instance); |
| 121 | 75 |
| 122 return instance; | 76 return instance; |
| 123 } | 77 } |
| 124 | 78 |
| 125 void CollectCurrentSnapshot(SiteData* site_data, RenderFrameHost* frame) { | |
| 126 if (frame->GetParent()) { | |
| 127 if (frame->GetSiteInstance() != frame->GetParent()->GetSiteInstance()) | |
| 128 site_data->out_of_process_frames++; | |
| 129 } | |
| 130 | |
| 131 DeterminePrimarySiteInstance(frame->GetSiteInstance(), site_data); | |
| 132 } | |
| 133 | |
| 134 } // namespace | 79 } // namespace |
| 135 | 80 |
| 136 IsolationScenario::IsolationScenario() : policy(ISOLATE_ALL_SITES) {} | 81 IsolationScenario::IsolationScenario() : policy(ISOLATE_ALL_SITES) {} |
| 137 | 82 |
| 138 IsolationScenario::~IsolationScenario() {} | 83 IsolationScenario::~IsolationScenario() {} |
| 139 | 84 |
| 140 SiteData::SiteData() : out_of_process_frames(0) { | 85 SiteData::SiteData() : out_of_process_frames(0) { |
| 141 for (int i = 0; i <= ISOLATION_SCENARIO_LAST; i++) | 86 for (int i = 0; i <= ISOLATION_SCENARIO_LAST; i++) |
| 142 scenarios[i].policy = static_cast<IsolationScenarioType>(i); | 87 scenarios[i].policy = static_cast<IsolationScenarioType>(i); |
| 143 } | 88 } |
| 144 | 89 |
| 145 SiteData::~SiteData() {} | 90 SiteData::~SiteData() {} |
| 146 | 91 |
| 147 SiteDetails::SiteDetails() {} | 92 SiteDetails::SiteDetails() {} |
| 148 | 93 |
| 149 SiteDetails::~SiteDetails() {} | 94 SiteDetails::~SiteDetails() {} |
| 150 | 95 |
| 151 void SiteDetails::CollectSiteInfo(WebContents* contents, | 96 void SiteDetails::CollectSiteInfo(WebContents* contents, |
| 152 SiteData* site_data) { | 97 SiteData* site_data) { |
| 153 DCHECK_CURRENTLY_ON(BrowserThread::UI); | 98 DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| 154 SiteInstance* primary = | 99 SiteInstance* primary = |
| 155 DeterminePrimarySiteInstance(contents->GetSiteInstance(), site_data); | 100 DeterminePrimarySiteInstance(contents->GetSiteInstance(), site_data); |
| 101 BrowserContext* context = primary->GetBrowserContext(); | |
| 156 | 102 |
| 157 // Now keep track of how many sites we have in this BrowsingInstance (and | 103 // Now keep track of how many sites we have in this BrowsingInstance (and |
| 158 // overall), including sites in iframes. | 104 // overall), including sites in iframes. |
| 159 for (IsolationScenario& scenario : site_data->scenarios) { | 105 for (IsolationScenario& scenario : site_data->scenarios) { |
| 160 std::map<RenderFrameHost*, GURL> memo; | 106 std::map<RenderFrameHost*, GURL> frame_urls; |
| 161 contents->ForEachFrame( | 107 for (RenderFrameHost* frame : contents->GetAllFrames()) { |
| 162 base::Bind(&CollectForScenario, base::Unretained(&memo), | 108 // Determine the site from the frame's origin, with a fallback to the |
| 163 base::Unretained(primary), base::Unretained(&scenario))); | 109 // frame's URL. In cases like <iframe sandbox>, we can wind up with an |
| 110 // http | |
| 111 // URL but a unique origin. The origin of the resource will still | |
|
Lei Zhang
2016/02/04 05:08:17
formatting
dcheng
2016/02/04 05:59:58
Done.
| |
| 112 // determine | |
| 113 // process placement. | |
| 114 url::Origin origin = frame->GetLastCommittedOrigin(); | |
| 115 GURL site = SiteInstance::GetSiteForURL( | |
| 116 context, origin.unique() ? frame->GetLastCommittedURL() | |
| 117 : GURL(origin.Serialize())); | |
| 118 | |
| 119 bool should_isolate = ShouldIsolate(context, scenario, site); | |
| 120 | |
| 121 // Treat a subframe as part of its parent site if neither needs isolation. | |
| 122 if (!should_isolate && frame->GetParent()) { | |
| 123 GURL parent_site = frame_urls[frame->GetParent()]; | |
| 124 if (!ShouldIsolate(context, scenario, parent_site)) | |
| 125 site = parent_site; | |
| 126 } | |
| 127 | |
| 128 bool process_per_site = | |
| 129 site.is_valid() && | |
| 130 RenderProcessHost::ShouldUseProcessPerSite(context, site); | |
| 131 | |
| 132 // If we don't need a dedicated process, and aren't living in a process- | |
| 133 // per-site process, we are nothing special: collapse our URL to a dummy | |
| 134 // site. | |
| 135 if (!process_per_site && !should_isolate) | |
| 136 site = GURL("http://"); | |
| 137 | |
| 138 // We model process-per-site by only inserting those sites into the first | |
| 139 // browsing instance in which they appear. | |
| 140 if (scenario.sites.insert(site).second || !process_per_site) | |
| 141 scenario.browsing_instance_site_map[primary->GetId()].insert(site); | |
| 142 | |
| 143 // Record our result in |frame_urls| for use by children. | |
| 144 frame_urls[frame] = site; | |
| 145 } | |
| 164 } | 146 } |
| 165 | 147 |
| 166 contents->ForEachFrame( | 148 for (RenderFrameHost* frame : contents->GetAllFrames()) { |
| 167 base::Bind(&CollectCurrentSnapshot, base::Unretained(site_data))); | 149 if (frame->GetParent()) { |
| 150 if (frame->GetSiteInstance() != frame->GetParent()->GetSiteInstance()) | |
| 151 site_data->out_of_process_frames++; | |
| 152 } | |
| 153 DeterminePrimarySiteInstance(frame->GetSiteInstance(), site_data); | |
| 154 } | |
| 168 } | 155 } |
| 169 | 156 |
| 170 void SiteDetails::UpdateHistograms( | 157 void SiteDetails::UpdateHistograms( |
| 171 const BrowserContextSiteDataMap& site_data_map, | 158 const BrowserContextSiteDataMap& site_data_map, |
| 172 int all_renderer_process_count, | 159 int all_renderer_process_count, |
| 173 int non_renderer_process_count) { | 160 int non_renderer_process_count) { |
| 174 // Reports a set of site-based process metrics to UMA. | 161 // Reports a set of site-based process metrics to UMA. |
| 175 int process_limit = RenderProcessHost::GetMaxRendererProcessCount(); | 162 int process_limit = RenderProcessHost::GetMaxRendererProcessCount(); |
| 176 | 163 |
| 177 // Sum the number of sites and SiteInstances in each BrowserContext and | 164 // Sum the number of sites and SiteInstances in each BrowserContext and |
| (...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 260 UMA_HISTOGRAM_COUNTS_100( | 247 UMA_HISTOGRAM_COUNTS_100( |
| 261 "SiteIsolation.IsolateExtensionsProcessCountLowerBound", | 248 "SiteIsolation.IsolateExtensionsProcessCountLowerBound", |
| 262 process_count_lower_bound[ISOLATE_EXTENSIONS]); | 249 process_count_lower_bound[ISOLATE_EXTENSIONS]); |
| 263 UMA_HISTOGRAM_COUNTS_100( | 250 UMA_HISTOGRAM_COUNTS_100( |
| 264 "SiteIsolation.IsolateExtensionsProcessCountEstimate", | 251 "SiteIsolation.IsolateExtensionsProcessCountEstimate", |
| 265 process_count_estimate[ISOLATE_EXTENSIONS]); | 252 process_count_estimate[ISOLATE_EXTENSIONS]); |
| 266 UMA_HISTOGRAM_COUNTS_100( | 253 UMA_HISTOGRAM_COUNTS_100( |
| 267 "SiteIsolation.IsolateExtensionsTotalProcessCountEstimate", | 254 "SiteIsolation.IsolateExtensionsTotalProcessCountEstimate", |
| 268 process_count_estimate[ISOLATE_EXTENSIONS] + non_renderer_process_count); | 255 process_count_estimate[ISOLATE_EXTENSIONS] + non_renderer_process_count); |
| 269 } | 256 } |
| OLD | NEW |