Index: chrome/browser/memory_details_win.cc |
=================================================================== |
--- chrome/browser/memory_details_win.cc (revision 18899) |
+++ chrome/browser/memory_details_win.cc (working copy) |
@@ -5,6 +5,7 @@ |
#include "chrome/browser/memory_details.h" |
#include <psapi.h> |
+#include "app/l10n_util.h" |
#include "base/file_version_info.h" |
#include "base/string_util.h" |
#include "chrome/browser/browser_process.h" |
@@ -14,14 +15,30 @@ |
#include "chrome/browser/tab_contents/tab_contents.h" |
#include "chrome/common/child_process_host.h" |
#include "chrome/common/url_constants.h" |
+#include "grit/chromium_strings.h" |
-class RenderViewHostDelegate; |
+// Known browsers which we collect details for. |
+enum { |
+ CHROME_BROWSER = 0, |
+ IE_BROWSER, |
+ FIREFOX_BROWSER, |
+ OPERA_BROWSER, |
+ SAFARI_BROWSER, |
+ IE_64BIT_BROWSER, |
+ KONQUEROR_BROWSER, |
+ MAX_BROWSERS |
+} BrowserProcess; |
// Template of static data we use for finding browser process information. |
// These entries must match the ordering for MemoryDetails::BrowserProcess. |
-static ProcessData |
- g_process_template[MemoryDetails::MAX_BROWSERS] = { |
- { L"Chromium", L"chrome.exe", }, |
+static ProcessData g_process_template[MAX_BROWSERS]; |
+ |
+MemoryDetails::MemoryDetails() |
+ : ui_loop_(NULL) { |
+ static const std::wstring google_browser_name = |
+ l10n_util::GetString(IDS_PRODUCT_NAME); |
+ ProcessData g_process_template[MAX_BROWSERS] = { |
+ { google_browser_name.c_str(), L"chrome.exe", }, |
{ L"IE", L"iexplore.exe", }, |
{ L"Firefox", L"firefox.exe", }, |
{ L"Opera", L"opera.exe", }, |
@@ -30,63 +47,18 @@ |
{ L"Konqueror", L"konqueror.exe", }, |
}; |
- |
-// About threading: |
-// |
-// This operation will hit no fewer than 3 threads. |
-// |
-// The ChildProcessInfo::Iterator can only be accessed from the IO thread. |
-// |
-// The RenderProcessHostIterator can only be accessed from the UI thread. |
-// |
-// This operation can take 30-100ms to complete. We never want to have |
-// one task run for that long on the UI or IO threads. So, we run the |
-// expensive parts of this operation over on the file thread. |
-// |
- |
-MemoryDetails::MemoryDetails() |
- : ui_loop_(NULL) { |
for (int index = 0; index < arraysize(g_process_template); ++index) { |
- process_data_[index].name = g_process_template[index].name; |
- process_data_[index].process_name = g_process_template[index].process_name; |
+ ProcessData process; |
+ process.name = g_process_template[index].name; |
+ process.process_name = g_process_template[index].process_name; |
+ process_data_.push_back(process); |
} |
} |
-void MemoryDetails::StartFetch() { |
- ui_loop_ = MessageLoop::current(); |
- |
- DCHECK(ui_loop_ != g_browser_process->io_thread()->message_loop()); |
- DCHECK(ui_loop_ != g_browser_process->file_thread()->message_loop()); |
- |
- // In order to process this request, we need to use the plugin information. |
- // However, plugin process information is only available from the IO thread. |
- g_browser_process->io_thread()->message_loop()->PostTask(FROM_HERE, |
- NewRunnableMethod(this, &MemoryDetails::CollectChildInfoOnIOThread)); |
+ProcessData* MemoryDetails::ChromeBrowser() { |
+ return &process_data_[CHROME_BROWSER]; |
} |
-void MemoryDetails::CollectChildInfoOnIOThread() { |
- DCHECK(MessageLoop::current() == |
- ChromeThread::GetMessageLoop(ChromeThread::IO)); |
- |
- std::vector<ProcessMemoryInformation> child_info; |
- |
- // Collect the list of child processes. |
- for (ChildProcessHost::Iterator iter; !iter.Done(); ++iter) { |
- ProcessMemoryInformation info; |
- info.pid = iter->GetProcessId(); |
- if (!info.pid) |
- continue; |
- |
- info.type = iter->type(); |
- info.titles.push_back(iter->name()); |
- child_info.push_back(info); |
- } |
- |
- // Now go do expensive memory lookups from the file thread. |
- ChromeThread::GetMessageLoop(ChromeThread::FILE)->PostTask(FROM_HERE, |
- NewRunnableMethod(this, &MemoryDetails::CollectProcessData, child_info)); |
-} |
- |
void MemoryDetails::CollectProcessData( |
std::vector<ProcessMemoryInformation> child_info) { |
DCHECK(MessageLoop::current() == |
@@ -181,129 +153,3 @@ |
ui_loop_->PostTask(FROM_HERE, |
NewRunnableMethod(this, &MemoryDetails::CollectChildInfoOnUIThread)); |
} |
- |
-void MemoryDetails::CollectChildInfoOnUIThread() { |
- DCHECK(MessageLoop::current() == ui_loop_); |
- |
- // Get more information about the process. |
- for (size_t index = 0; index < process_data_[CHROME_BROWSER].processes.size(); |
- index++) { |
- // Check if it's a renderer, if so get the list of page titles in it and |
- // check if it's a diagnostics-related process. We skip all diagnostics |
- // pages (e.g. "about:xxx" URLs). Iterate the RenderProcessHosts to find |
- // the tab contents. |
- RenderProcessHost::iterator renderer_iter; |
- for (renderer_iter = RenderProcessHost::begin(); renderer_iter != |
- RenderProcessHost::end(); ++renderer_iter) { |
- DCHECK(renderer_iter->second); |
- ProcessMemoryInformation& process = |
- process_data_[CHROME_BROWSER].processes[index]; |
- if (process.pid != renderer_iter->second->process().pid()) |
- continue; |
- process.type = ChildProcessInfo::RENDER_PROCESS; |
- // The RenderProcessHost may host multiple TabContents. Any |
- // of them which contain diagnostics information make the whole |
- // process be considered a diagnostics process. |
- // |
- // NOTE: This is a bit dangerous. We know that for now, listeners |
- // are always RenderWidgetHosts. But in theory, they don't |
- // have to be. |
- RenderProcessHost::listeners_iterator iter; |
- for (iter = renderer_iter->second->listeners_begin(); |
- iter != renderer_iter->second->listeners_end(); ++iter) { |
- RenderWidgetHost* widget = |
- static_cast<RenderWidgetHost*>(iter->second); |
- DCHECK(widget); |
- if (!widget || !widget->IsRenderView()) |
- continue; |
- |
- RenderViewHost* host = static_cast<RenderViewHost*>(widget); |
- TabContents* contents = NULL; |
- if (host->delegate()) |
- contents = host->delegate()->GetAsTabContents(); |
- if (!contents) |
- continue; |
- std::wstring title = UTF16ToWideHack(contents->GetTitle()); |
- if (!title.length()) |
- title = L"Untitled"; |
- process.titles.push_back(title); |
- |
- // We need to check the pending entry as well as the display_url to |
- // see if it's an about:memory URL (we don't want to count these in the |
- // total memory usage of the browser). |
- // |
- // When we reach here, about:memory will be the pending entry since we |
- // haven't responded with any data such that it would be committed. If |
- // you have another about:memory tab open (which would be committed), |
- // we don't want to count it either, so we also check the last committed |
- // entry. |
- // |
- // Either the pending or last committed entries can be NULL. |
- const NavigationEntry* pending_entry = |
- contents->controller().pending_entry(); |
- const NavigationEntry* last_committed_entry = |
- contents->controller().GetLastCommittedEntry(); |
- if ((last_committed_entry && |
- LowerCaseEqualsASCII(last_committed_entry->display_url().spec(), |
- chrome::kAboutMemoryURL)) || |
- (pending_entry && |
- LowerCaseEqualsASCII(pending_entry->display_url().spec(), |
- chrome::kAboutMemoryURL))) |
- process.is_diagnostics = true; |
- } |
- } |
- } |
- |
- // Get rid of other Chrome processes that are from a different profile. |
- for (size_t index = 0; index < process_data_[CHROME_BROWSER].processes.size(); |
- index++) { |
- if (process_data_[CHROME_BROWSER].processes[index].type == |
- ChildProcessInfo::UNKNOWN_PROCESS) { |
- process_data_[CHROME_BROWSER].processes.erase( |
- process_data_[CHROME_BROWSER].processes.begin() + index); |
- index--; |
- } |
- } |
- |
- UpdateHistograms(); |
- |
- OnDetailsAvailable(); |
-} |
- |
-void MemoryDetails::UpdateHistograms() { |
- // Reports a set of memory metrics to UMA. |
- // Memory is measured in units of 10KB. |
- |
- ProcessData browser = process_data_[CHROME_BROWSER]; |
- size_t aggregate_memory = 0; |
- int plugin_count = 0; |
- int worker_count = 0; |
- for (size_t index = 0; index < browser.processes.size(); index++) { |
- int sample = static_cast<int>(browser.processes[index].working_set.priv); |
- aggregate_memory += sample; |
- switch (browser.processes[index].type) { |
- case ChildProcessInfo::BROWSER_PROCESS: |
- UMA_HISTOGRAM_MEMORY_KB("Memory.Browser", sample); |
- break; |
- case ChildProcessInfo::RENDER_PROCESS: |
- UMA_HISTOGRAM_MEMORY_KB("Memory.Renderer", sample); |
- break; |
- case ChildProcessInfo::PLUGIN_PROCESS: |
- UMA_HISTOGRAM_MEMORY_KB("Memory.Plugin", sample); |
- plugin_count++; |
- break; |
- case ChildProcessInfo::WORKER_PROCESS: |
- UMA_HISTOGRAM_MEMORY_KB("Memory.Worker", sample); |
- worker_count++; |
- break; |
- } |
- } |
- |
- UMA_HISTOGRAM_COUNTS_100("Memory.ProcessCount", |
- static_cast<int>(browser.processes.size())); |
- UMA_HISTOGRAM_COUNTS_100("Memory.PluginProcessCount", plugin_count); |
- UMA_HISTOGRAM_COUNTS_100("Memory.WorkerProcessCount", worker_count); |
- |
- int total_sample = static_cast<int>(aggregate_memory / 1000); |
- UMA_HISTOGRAM_MEMORY_MB("Memory.Total", total_sample); |
-} |