Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 "base/bind.h" | 7 #include "base/bind.h" |
| 8 #include "base/file_version_info.h" | 8 #include "base/file_version_info.h" |
| 9 #include "base/metrics/histogram.h" | 9 #include "base/metrics/histogram.h" |
| 10 #include "base/process_util.h" | 10 #include "base/process_util.h" |
| (...skipping 196 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 207 ProcessData* const chrome_browser = ChromeBrowser(); | 207 ProcessData* const chrome_browser = ChromeBrowser(); |
| 208 // Get more information about the process. | 208 // Get more information about the process. |
| 209 for (size_t index = 0; index < chrome_browser->processes.size(); | 209 for (size_t index = 0; index < chrome_browser->processes.size(); |
| 210 index++) { | 210 index++) { |
| 211 // Check if it's a renderer, if so get the list of page titles in it and | 211 // Check if it's a renderer, if so get the list of page titles in it and |
| 212 // check if it's a diagnostics-related process. We skip about:memory pages. | 212 // check if it's a diagnostics-related process. We skip about:memory pages. |
| 213 // Iterate the RenderProcessHosts to find the tab contents. | 213 // Iterate the RenderProcessHosts to find the tab contents. |
| 214 ProcessMemoryInformation& process = | 214 ProcessMemoryInformation& process = |
| 215 chrome_browser->processes[index]; | 215 chrome_browser->processes[index]; |
| 216 | 216 |
| 217 for (content::RenderProcessHost::iterator renderer_iter( | 217 RenderWidgetHost::List widgets = RenderWidgetHost::GetRenderWidgetHosts(); |
| 218 content::RenderProcessHost::AllHostsIterator()); | 218 for (RenderWidgetHost::List::const_iterator it = widgets.begin(); |
| 219 !renderer_iter.IsAtEnd(); renderer_iter.Advance()) { | 219 it != widgets.end(); ++it) { |
|
jam
2013/06/12 19:59:59
ditto
nasko
2013/06/12 21:18:59
Done.
| |
| 220 content::RenderProcessHost* render_process_host = | 220 const RenderWidgetHost* widget = *it; |
| 221 renderer_iter.GetCurrentValue(); | 221 content::RenderProcessHost* render_process_host = widget->GetProcess(); |
| 222 DCHECK(render_process_host); | 222 DCHECK(render_process_host); |
| 223 // Ignore processes that don't have a connection, such as crashed tabs. | 223 // Ignore processes that don't have a connection, such as crashed tabs. |
| 224 if (!render_process_host->HasConnection() || | 224 if (!render_process_host->HasConnection() || |
| 225 process.pid != base::GetProcId(render_process_host->GetHandle())) { | 225 process.pid != base::GetProcId(render_process_host->GetHandle())) { |
| 226 continue; | 226 continue; |
| 227 } | 227 } |
| 228 process.process_type = content::PROCESS_TYPE_RENDERER; | 228 process.process_type = content::PROCESS_TYPE_RENDERER; |
| 229 Profile* profile = | 229 Profile* profile = |
| 230 Profile::FromBrowserContext( | 230 Profile::FromBrowserContext( |
| 231 render_process_host->GetBrowserContext()); | 231 render_process_host->GetBrowserContext()); |
| 232 ExtensionService* extension_service = profile->GetExtensionService(); | 232 ExtensionService* extension_service = profile->GetExtensionService(); |
| 233 extensions::ProcessMap* extension_process_map = NULL; | 233 extensions::ProcessMap* extension_process_map = NULL; |
| 234 // No extensions on Android. So extension_service can be NULL. | 234 // No extensions on Android. So extension_service can be NULL. |
| 235 if (extension_service) | 235 if (extension_service) |
| 236 extension_process_map = extension_service->process_map(); | 236 extension_process_map = extension_service->process_map(); |
| 237 | 237 |
| 238 // The RenderProcessHost may host multiple WebContentses. Any | 238 // The RenderProcessHost may host multiple WebContentses. Any |
| 239 // of them which contain diagnostics information make the whole | 239 // of them which contain diagnostics information make the whole |
| 240 // process be considered a diagnostics process. | 240 // process be considered a diagnostics process. |
| 241 content::RenderProcessHost::RenderWidgetHostsIterator iter( | 241 if (!widget->IsRenderView()) |
| 242 render_process_host->GetRenderWidgetHostsIterator()); | 242 continue; |
| 243 for (; !iter.IsAtEnd(); iter.Advance()) { | |
| 244 const RenderWidgetHost* widget = iter.GetCurrentValue(); | |
| 245 DCHECK(widget); | |
| 246 if (!widget || !widget->IsRenderView()) | |
| 247 continue; | |
| 248 | 243 |
| 249 RenderViewHost* host = | 244 RenderViewHost* host = |
| 250 RenderViewHost::From(const_cast<RenderWidgetHost*>(widget)); | 245 RenderViewHost::From(const_cast<RenderWidgetHost*>(widget)); |
| 251 WebContents* contents = WebContents::FromRenderViewHost(host); | 246 WebContents* contents = WebContents::FromRenderViewHost(host); |
| 252 GURL url; | 247 GURL url; |
| 253 if (contents) | 248 if (contents) |
| 254 url = contents->GetURL(); | 249 url = contents->GetURL(); |
| 255 extensions::ViewType type = extensions::GetViewType(contents); | 250 extensions::ViewType type = extensions::GetViewType(contents); |
| 256 if (host->GetEnabledBindings() & content::BINDINGS_POLICY_WEB_UI) { | 251 if (host->GetEnabledBindings() & content::BINDINGS_POLICY_WEB_UI) { |
| 257 process.renderer_type = ProcessMemoryInformation::RENDERER_CHROME; | 252 process.renderer_type = ProcessMemoryInformation::RENDERER_CHROME; |
| 258 } else if (extension_process_map && | 253 } else if (extension_process_map && |
| 259 extension_process_map->Contains(host->GetProcess()->GetID())) { | 254 extension_process_map->Contains(host->GetProcess()->GetID())) { |
| 260 // For our purposes, don't count processes containing only hosted apps | 255 // For our purposes, don't count processes containing only hosted apps |
| 261 // as extension processes. See also: crbug.com/102533. | 256 // as extension processes. See also: crbug.com/102533. |
| 262 std::set<std::string> extension_ids = | 257 std::set<std::string> extension_ids = |
| 263 extension_process_map->GetExtensionsInProcess( | 258 extension_process_map->GetExtensionsInProcess( |
| 264 host->GetProcess()->GetID()); | 259 host->GetProcess()->GetID()); |
| 265 for (std::set<std::string>::iterator iter = extension_ids.begin(); | 260 for (std::set<std::string>::iterator iter = extension_ids.begin(); |
| 266 iter != extension_ids.end(); ++iter) { | 261 iter != extension_ids.end(); ++iter) { |
| 267 const Extension* extension = | 262 const Extension* extension = |
| 268 extension_service->GetExtensionById(*iter, false); | 263 extension_service->GetExtensionById(*iter, false); |
| 269 if (extension && !extension->is_hosted_app()) { | 264 if (extension && !extension->is_hosted_app()) { |
| 270 process.renderer_type = | 265 process.renderer_type = |
| 271 ProcessMemoryInformation::RENDERER_EXTENSION; | 266 ProcessMemoryInformation::RENDERER_EXTENSION; |
| 272 break; | 267 break; |
| 273 } | |
| 274 } | 268 } |
| 275 } | 269 } |
| 276 if (extension_process_map && | 270 } |
| 277 extension_process_map->Contains(host->GetProcess()->GetID())) { | 271 if (extension_process_map && |
| 278 const Extension* extension = | 272 extension_process_map->Contains(host->GetProcess()->GetID())) { |
| 279 extension_service->extensions()->GetByID(url.host()); | 273 const Extension* extension = |
| 280 if (extension) { | 274 extension_service->extensions()->GetByID(url.host()); |
| 281 string16 title = UTF8ToUTF16(extension->name()); | 275 if (extension) { |
| 282 process.titles.push_back(title); | 276 string16 title = UTF8ToUTF16(extension->name()); |
| 283 process.renderer_type = | 277 process.titles.push_back(title); |
| 284 ProcessMemoryInformation::RENDERER_EXTENSION; | |
| 285 continue; | |
| 286 } | |
| 287 } | |
| 288 | |
| 289 if (!contents) { | |
| 290 process.renderer_type = | 278 process.renderer_type = |
| 291 ProcessMemoryInformation::RENDERER_INTERSTITIAL; | 279 ProcessMemoryInformation::RENDERER_EXTENSION; |
| 292 continue; | 280 continue; |
| 293 } | 281 } |
| 282 } | |
| 294 | 283 |
| 295 if (type == extensions::VIEW_TYPE_BACKGROUND_CONTENTS) { | 284 if (!contents) { |
| 296 process.titles.push_back(UTF8ToUTF16(url.spec())); | 285 process.renderer_type = |
| 297 process.renderer_type = | 286 ProcessMemoryInformation::RENDERER_INTERSTITIAL; |
| 298 ProcessMemoryInformation::RENDERER_BACKGROUND_APP; | 287 continue; |
| 299 continue; | 288 } |
| 300 } | |
| 301 | 289 |
| 302 if (type == extensions::VIEW_TYPE_NOTIFICATION) { | 290 if (type == extensions::VIEW_TYPE_BACKGROUND_CONTENTS) { |
| 303 process.titles.push_back(UTF8ToUTF16(url.spec())); | 291 process.titles.push_back(UTF8ToUTF16(url.spec())); |
| 304 process.renderer_type = | 292 process.renderer_type = |
| 305 ProcessMemoryInformation::RENDERER_NOTIFICATION; | 293 ProcessMemoryInformation::RENDERER_BACKGROUND_APP; |
| 306 continue; | 294 continue; |
| 307 } | 295 } |
| 308 | 296 |
| 309 // Since we have a WebContents and and the renderer type hasn't been | 297 if (type == extensions::VIEW_TYPE_NOTIFICATION) { |
| 310 // set yet, it must be a normal tabbed renderer. | 298 process.titles.push_back(UTF8ToUTF16(url.spec())); |
| 311 if (process.renderer_type == ProcessMemoryInformation::RENDERER_UNKNOWN) | 299 process.renderer_type = |
| 312 process.renderer_type = ProcessMemoryInformation::RENDERER_NORMAL; | 300 ProcessMemoryInformation::RENDERER_NOTIFICATION; |
| 301 continue; | |
| 302 } | |
| 313 | 303 |
| 314 string16 title = contents->GetTitle(); | 304 // Since we have a WebContents and and the renderer type hasn't been |
| 315 if (!title.length()) | 305 // set yet, it must be a normal tabbed renderer. |
| 316 title = l10n_util::GetStringUTF16(IDS_DEFAULT_TAB_TITLE); | 306 if (process.renderer_type == ProcessMemoryInformation::RENDERER_UNKNOWN) |
| 317 process.titles.push_back(title); | 307 process.renderer_type = ProcessMemoryInformation::RENDERER_NORMAL; |
| 318 | 308 |
| 319 // We need to check the pending entry as well as the virtual_url to | 309 string16 title = contents->GetTitle(); |
| 320 // see if it's a chrome://memory URL (we don't want to count these in | 310 if (!title.length()) |
| 321 // the total memory usage of the browser). | 311 title = l10n_util::GetStringUTF16(IDS_DEFAULT_TAB_TITLE); |
| 322 // | 312 process.titles.push_back(title); |
| 323 // When we reach here, chrome://memory will be the pending entry since | 313 |
| 324 // we haven't responded with any data such that it would be committed. | 314 // We need to check the pending entry as well as the virtual_url to |
| 325 // If you have another chrome://memory tab open (which would be | 315 // see if it's a chrome://memory URL (we don't want to count these in |
| 326 // committed), we don't want to count it either, so we also check the | 316 // the total memory usage of the browser). |
| 327 // last committed entry. | 317 // |
| 328 // | 318 // When we reach here, chrome://memory will be the pending entry since |
| 329 // Either the pending or last committed entries can be NULL. | 319 // we haven't responded with any data such that it would be committed. |
| 330 const NavigationEntry* pending_entry = | 320 // If you have another chrome://memory tab open (which would be |
| 331 contents->GetController().GetPendingEntry(); | 321 // committed), we don't want to count it either, so we also check the |
| 332 const NavigationEntry* last_committed_entry = | 322 // last committed entry. |
| 333 contents->GetController().GetLastCommittedEntry(); | 323 // |
| 334 if ((last_committed_entry && | 324 // Either the pending or last committed entries can be NULL. |
| 335 LowerCaseEqualsASCII(last_committed_entry->GetVirtualURL().spec(), | 325 const NavigationEntry* pending_entry = |
| 336 chrome::kChromeUIMemoryURL)) || | 326 contents->GetController().GetPendingEntry(); |
| 337 (pending_entry && | 327 const NavigationEntry* last_committed_entry = |
| 338 LowerCaseEqualsASCII(pending_entry->GetVirtualURL().spec(), | 328 contents->GetController().GetLastCommittedEntry(); |
| 339 chrome::kChromeUIMemoryURL))) | 329 if ((last_committed_entry && |
| 340 process.is_diagnostics = true; | 330 LowerCaseEqualsASCII(last_committed_entry->GetVirtualURL().spec(), |
| 331 chrome::kChromeUIMemoryURL)) || | |
| 332 (pending_entry && | |
| 333 LowerCaseEqualsASCII(pending_entry->GetVirtualURL().spec(), | |
| 334 chrome::kChromeUIMemoryURL))) { | |
| 335 process.is_diagnostics = true; | |
| 341 } | 336 } |
| 342 } | 337 } |
| 343 | 338 |
| 344 #if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_ANDROID) | 339 #if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_ANDROID) |
| 345 if (process.pid == zygote_pid) { | 340 if (process.pid == zygote_pid) { |
| 346 process.process_type = content::PROCESS_TYPE_ZYGOTE; | 341 process.process_type = content::PROCESS_TYPE_ZYGOTE; |
| 347 } else if (process.pid == sandbox_helper_pid) { | 342 } else if (process.pid == sandbox_helper_pid) { |
| 348 process.process_type = content::PROCESS_TYPE_SANDBOX_HELPER; | 343 process.process_type = content::PROCESS_TYPE_SANDBOX_HELPER; |
| 349 } | 344 } |
| 350 #endif | 345 #endif |
| (...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 478 UMA_HISTOGRAM_COUNTS_100("Memory.PepperPluginBrokerProcessCount", | 473 UMA_HISTOGRAM_COUNTS_100("Memory.PepperPluginBrokerProcessCount", |
| 479 pepper_plugin_broker_count); | 474 pepper_plugin_broker_count); |
| 480 UMA_HISTOGRAM_COUNTS_100("Memory.RendererProcessCount", renderer_count); | 475 UMA_HISTOGRAM_COUNTS_100("Memory.RendererProcessCount", renderer_count); |
| 481 UMA_HISTOGRAM_COUNTS_100("Memory.WorkerProcessCount", worker_count); | 476 UMA_HISTOGRAM_COUNTS_100("Memory.WorkerProcessCount", worker_count); |
| 482 // TODO(viettrungluu): Do we want separate counts for the other | 477 // TODO(viettrungluu): Do we want separate counts for the other |
| 483 // (platform-specific) process types? | 478 // (platform-specific) process types? |
| 484 | 479 |
| 485 int total_sample = static_cast<int>(aggregate_memory / 1000); | 480 int total_sample = static_cast<int>(aggregate_memory / 1000); |
| 486 UMA_HISTOGRAM_MEMORY_MB("Memory.Total", total_sample); | 481 UMA_HISTOGRAM_MEMORY_MB("Memory.Total", total_sample); |
| 487 } | 482 } |
| OLD | NEW |