Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(683)

Side by Side Diff: chrome/browser/memory_details.cc

Issue 1406133002: Several Site Details / Memory metrics fixes (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@no_isolate_apps4
Patch Set: Self-review fixes / simplifications Created 5 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | chrome/browser/site_details.h » ('j') | chrome/browser/site_details.cc » ('J')
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 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/memory_details.h" 5 #include "chrome/browser/memory_details.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 #include <set> 8 #include <set>
9 9
10 #include "base/bind.h" 10 #include "base/bind.h"
(...skipping 197 matching lines...) Expand 10 before | Expand all | Expand 10 after
208 } 208 }
209 209
210 void MemoryDetails::CollectChildInfoOnUIThread() { 210 void MemoryDetails::CollectChildInfoOnUIThread() {
211 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 211 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
212 212
213 #if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_ANDROID) 213 #if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_ANDROID)
214 const pid_t zygote_pid = content::ZygoteHost::GetInstance()->GetPid(); 214 const pid_t zygote_pid = content::ZygoteHost::GetInstance()->GetPid();
215 #endif 215 #endif
216 216
217 ProcessData* const chrome_browser = ChromeBrowser(); 217 ProcessData* const chrome_browser = ChromeBrowser();
218
219 // First pass, collate the widgets by process ID.
220 std::map<base::ProcessId, std::vector<RenderWidgetHost*>> widgets_by_pid;
221 scoped_ptr<content::RenderWidgetHostIterator> widget_it(
222 RenderWidgetHost::GetRenderWidgetHosts());
223 while (content::RenderWidgetHost* widget = widget_it->GetNextHost()) {
224 // Ignore processes that don't have a connection, such as crashed tabs.
225 if (!widget->GetProcess()->HasConnection())
226 continue;
227 base::ProcessId pid = base::GetProcId(widget->GetProcess()->GetHandle());
228 widgets_by_pid[pid].push_back(widget);
229 }
230
218 // Get more information about the process. 231 // Get more information about the process.
219 for (size_t index = 0; index < chrome_browser->processes.size(); 232 for (ProcessMemoryInformation& process : chrome_browser->processes) {
220 index++) { 233 // If there's at least one widget in the process, it is some kind of
221 // Check if it's a renderer, if so get the list of page titles in it and 234 // renderer process belonging to this browser. All these widgets will share
222 // check if it's a diagnostics-related process. We skip about:memory pages. 235 // a RenderProcessHost.
223 // Iterate the RenderProcessHosts to find the tab contents. 236 content::RenderProcessHost* render_process_host = nullptr;
224 ProcessMemoryInformation& process = 237 if (!widgets_by_pid[process.pid].empty()) {
225 chrome_browser->processes[index]; 238 // Mark it as a normal renderer process, if we don't refine it to some
239 // other |renderer_type| later.
240 process.process_type = content::PROCESS_TYPE_RENDERER;
241 process.renderer_type = ProcessMemoryInformation::RENDERER_NORMAL;
242 render_process_host = widgets_by_pid[process.pid].front()->GetProcess();
243 }
226 244
227 scoped_ptr<content::RenderWidgetHostIterator> widgets(
228 RenderWidgetHost::GetRenderWidgetHosts());
229 while (content::RenderWidgetHost* widget = widgets->GetNextHost()) {
230 content::RenderProcessHost* render_process_host =
231 widget->GetProcess();
232 DCHECK(render_process_host);
233 // Ignore processes that don't have a connection, such as crashed tabs.
234 if (!render_process_host->HasConnection() ||
235 process.pid != base::GetProcId(render_process_host->GetHandle())) {
236 continue;
237 }
238
239 // The RenderProcessHost may host multiple WebContentses. Any
240 // of them which contain diagnostics information make the whole
241 // process be considered a diagnostics process.
242 if (!widget->IsRenderView())
243 continue;
244
245 process.process_type = content::PROCESS_TYPE_RENDERER;
246 bool is_extension = false;
247 RenderViewHost* host = RenderViewHost::From(widget);
248 #if defined(ENABLE_EXTENSIONS) 245 #if defined(ENABLE_EXTENSIONS)
246 // Determine if this is an extension process.
247 bool process_is_for_extensions = false;
248 if (render_process_host) {
249 content::BrowserContext* context = 249 content::BrowserContext* context =
250 render_process_host->GetBrowserContext(); 250 render_process_host->GetBrowserContext();
251 extensions::ExtensionRegistry* extension_registry = 251 extensions::ExtensionRegistry* extension_registry =
252 extensions::ExtensionRegistry::Get(context); 252 extensions::ExtensionRegistry::Get(context);
253 extensions::ProcessMap* extension_process_map = 253 extensions::ProcessMap* extension_process_map =
254 extensions::ProcessMap::Get(context); 254 extensions::ProcessMap::Get(context);
255 is_extension = extension_process_map->Contains( 255 process_is_for_extensions =
256 host->GetProcess()->GetID()); 256 extension_process_map->Contains(render_process_host->GetID());
257
258 // For our purposes, don't count processes containing only hosted apps
259 // as extension processes. See also: crbug.com/102533.
260 std::set<std::string> extension_ids =
261 extension_process_map->GetExtensionsInProcess(
262 render_process_host->GetID());
263 for (std::set<std::string>::iterator iter = extension_ids.begin();
264 iter != extension_ids.end(); ++iter) {
265 const Extension* extension =
266 extension_registry->enabled_extensions().GetByID(*iter);
267 if (extension && !extension->is_hosted_app()) {
268 process.renderer_type = ProcessMemoryInformation::RENDERER_EXTENSION;
269 break;
270 }
271 }
272 }
257 #endif 273 #endif
258 274
259 WebContents* contents = WebContents::FromRenderViewHost(host); 275 // Use the list of widgets to iterate over the WebContents instances whose
260 GURL url; 276 // main RenderFrameHosts are in |process|. Refine our determination of the
261 if (contents) { 277 // |process.renderer_type|, and record the page titles.
262 url = contents->GetURL(); 278 for (content::RenderWidgetHost* widget : widgets_by_pid[process.pid]) {
263 SiteData* site_data = 279 DCHECK_EQ(render_process_host, widget->GetProcess());
264 &chrome_browser->site_data[contents->GetBrowserContext()]; 280
265 SiteDetails::CollectSiteInfo(contents, site_data); 281 if (!widget->IsRenderView())
282 continue;
283
284 RenderViewHost* rvh = RenderViewHost::From(widget);
285 WebContents* contents = WebContents::FromRenderViewHost(rvh);
286
287 // Assume that an RVH without a web contents is an interstitial.
288 if (!contents) {
289 process.renderer_type = ProcessMemoryInformation::RENDERER_INTERSTITIAL;
290 continue;
266 } 291 }
292
293 // If this is a RVH for a subframe; skip it to avoid double-counting the
294 // WebContents.
295 if (rvh != contents->GetRenderViewHost())
296 continue;
297
298 // The rest of this block will happen only once per WebContents.
299 GURL page_url = contents->GetURL();
Charlie Reis 2015/10/23 19:03:40 Using the deprecated GetURL method was a bug, sinc
ncarter (slow) 2015/10/29 19:55:06 Done.
300 SiteData* site_data =
301 &chrome_browser->site_data[contents->GetBrowserContext()];
302 SiteDetails::CollectSiteInfo(contents, site_data);
303
304 bool is_webui =
305 rvh->GetEnabledBindings() & content::BINDINGS_POLICY_WEB_UI;
306
307 if (is_webui) {
308 process.renderer_type = ProcessMemoryInformation::RENDERER_CHROME;
309 }
310
267 #if defined(ENABLE_EXTENSIONS) 311 #if defined(ENABLE_EXTENSIONS)
268 extensions::ViewType type = extensions::GetViewType(contents); 312 if (!is_webui && process_is_for_extensions) {
269 #endif
270 if (host->GetEnabledBindings() & content::BINDINGS_POLICY_WEB_UI) {
271 process.renderer_type = ProcessMemoryInformation::RENDERER_CHROME;
272 } else if (is_extension) {
273 #if defined(ENABLE_EXTENSIONS)
274 // For our purposes, don't count processes containing only hosted apps
275 // as extension processes. See also: crbug.com/102533.
276 std::set<std::string> extension_ids =
277 extension_process_map->GetExtensionsInProcess(
278 host->GetProcess()->GetID());
279 for (std::set<std::string>::iterator iter = extension_ids.begin();
280 iter != extension_ids.end(); ++iter) {
281 const Extension* extension =
282 extension_registry->enabled_extensions().GetByID(*iter);
283 if (extension && !extension->is_hosted_app()) {
284 process.renderer_type =
285 ProcessMemoryInformation::RENDERER_EXTENSION;
286 break;
287 }
288 }
289 #endif
290 }
291 #if defined(ENABLE_EXTENSIONS)
292 if (is_extension) {
293 const Extension* extension = 313 const Extension* extension =
294 extension_registry->enabled_extensions().GetByID(url.host()); 314 extensions::ExtensionRegistry::Get(
315 render_process_host->GetBrowserContext())
316 ->enabled_extensions()
317 .GetByID(page_url.host());
295 if (extension) { 318 if (extension) {
296 base::string16 title = base::UTF8ToUTF16(extension->name()); 319 base::string16 title = base::UTF8ToUTF16(extension->name());
297 process.titles.push_back(title); 320 process.titles.push_back(title);
298 process.renderer_type = 321 process.renderer_type =
299 ProcessMemoryInformation::RENDERER_EXTENSION; 322 ProcessMemoryInformation::RENDERER_EXTENSION;
300 continue; 323 continue;
301 } 324 }
302 } 325 }
303 #endif
304 326
305 if (!contents) { 327 extensions::ViewType type = extensions::GetViewType(contents);
306 process.renderer_type =
307 ProcessMemoryInformation::RENDERER_INTERSTITIAL;
308 continue;
309 }
310
311 #if defined(ENABLE_EXTENSIONS)
312 if (type == extensions::VIEW_TYPE_BACKGROUND_CONTENTS) { 328 if (type == extensions::VIEW_TYPE_BACKGROUND_CONTENTS) {
313 process.titles.push_back(base::UTF8ToUTF16(url.spec())); 329 process.titles.push_back(base::UTF8ToUTF16(page_url.spec()));
314 process.renderer_type = 330 process.renderer_type =
315 ProcessMemoryInformation::RENDERER_BACKGROUND_APP; 331 ProcessMemoryInformation::RENDERER_BACKGROUND_APP;
316 continue; 332 continue;
317 } 333 }
318 #endif 334 #endif
319 335
320 // Since we have a WebContents and and the renderer type hasn't been
321 // set yet, it must be a normal tabbed renderer.
322 if (process.renderer_type == ProcessMemoryInformation::RENDERER_UNKNOWN)
323 process.renderer_type = ProcessMemoryInformation::RENDERER_NORMAL;
324
325 base::string16 title = contents->GetTitle(); 336 base::string16 title = contents->GetTitle();
326 if (!title.length()) 337 if (!title.length())
327 title = l10n_util::GetStringUTF16(IDS_DEFAULT_TAB_TITLE); 338 title = l10n_util::GetStringUTF16(IDS_DEFAULT_TAB_TITLE);
328 process.titles.push_back(title); 339 process.titles.push_back(title);
329 340
341 // The presence of a single WebContents with a diagnostics page will make
342 // make the whole process be considered a diagnostics process.
Charlie Reis 2015/10/23 19:03:39 Thank you for moving this comment! It made no sen
ncarter (slow) 2015/10/29 19:55:06 Done.
343 //
330 // We need to check the pending entry as well as the virtual_url to 344 // We need to check the pending entry as well as the virtual_url to
331 // see if it's a chrome://memory URL (we don't want to count these in 345 // see if it's a chrome://memory URL (we don't want to count these in
332 // the total memory usage of the browser). 346 // the total memory usage of the browser).
333 // 347 //
334 // When we reach here, chrome://memory will be the pending entry since 348 // When we reach here, chrome://memory will be the pending entry since
335 // we haven't responded with any data such that it would be committed. 349 // we haven't responded with any data such that it would be committed.
336 // If you have another chrome://memory tab open (which would be 350 // If you have another chrome://memory tab open (which would be
337 // committed), we don't want to count it either, so we also check the 351 // committed), we don't want to count it either, so we also check the
338 // last committed entry. 352 // last committed entry.
339 // 353 //
(...skipping 15 matching lines...) Expand all
355 } 369 }
356 370
357 #if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_ANDROID) 371 #if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_ANDROID)
358 if (process.pid == zygote_pid) { 372 if (process.pid == zygote_pid) {
359 process.process_type = content::PROCESS_TYPE_ZYGOTE; 373 process.process_type = content::PROCESS_TYPE_ZYGOTE;
360 } 374 }
361 #endif 375 #endif
362 } 376 }
363 377
364 // Get rid of other Chrome processes that are from a different profile. 378 // Get rid of other Chrome processes that are from a different profile.
365 for (size_t index = 0; index < chrome_browser->processes.size(); 379 auto is_unknown = [](ProcessMemoryInformation& process) {
366 index++) { 380 return process.process_type == content::PROCESS_TYPE_UNKNOWN;
367 if (chrome_browser->processes[index].process_type == 381 };
368 content::PROCESS_TYPE_UNKNOWN) { 382 auto& vector = chrome_browser->processes;
369 chrome_browser->processes.erase( 383 vector.erase(std::remove_if(vector.begin(), vector.end(), is_unknown),
370 chrome_browser->processes.begin() + index); 384 vector.end());
371 index--;
372 }
373 }
374 385
375 OnDetailsAvailable(); 386 OnDetailsAvailable();
376 } 387 }
OLDNEW
« no previous file with comments | « no previous file | chrome/browser/site_details.h » ('j') | chrome/browser/site_details.cc » ('J')

Powered by Google App Engine
This is Rietveld 408576698