diff options
-rw-r--r-- | chrome/browser/browser_about_handler.cc | 4 | ||||
-rw-r--r-- | chrome/browser/memory_details.cc | 111 | ||||
-rw-r--r-- | chrome/browser/memory_details.h | 7 | ||||
-rw-r--r-- | chrome/browser/renderer_host/render_view_host.h | 6 | ||||
-rw-r--r-- | chrome/common/child_process_info.cc | 54 | ||||
-rw-r--r-- | chrome/common/child_process_info.h | 22 |
6 files changed, 178 insertions, 26 deletions
diff --git a/chrome/browser/browser_about_handler.cc b/chrome/browser/browser_about_handler.cc index 715f460..7ede87f 100644 --- a/chrome/browser/browser_about_handler.cc +++ b/chrome/browser/browser_about_handler.cc @@ -851,7 +851,9 @@ void AboutMemoryHandler::AppendProcess(ListValue* child_data, child_data->Append(child); BindProcessMetrics(child, info); - std::string child_label(ChildProcessInfo::GetTypeNameInEnglish(info->type)); + std::string child_label( + ChildProcessInfo::GetFullTypeNameInEnglish(info->type, + info->renderer_type)); if (info->is_diagnostics) child_label.append(" (diagnostics)"); child->SetString("child_name", child_label); diff --git a/chrome/browser/memory_details.cc b/chrome/browser/memory_details.cc index 6f83083..fc3d5f8 100644 --- a/chrome/browser/memory_details.cc +++ b/chrome/browser/memory_details.cc @@ -12,11 +12,14 @@ #include "base/utf_string_conversions.h" #include "chrome/browser/browser_child_process_host.h" #include "chrome/browser/browser_thread.h" +#include "chrome/browser/extensions/extension_host.h" #include "chrome/browser/renderer_host/backing_store_manager.h" #include "chrome/browser/renderer_host/render_process_host.h" #include "chrome/browser/renderer_host/render_view_host.h" #include "chrome/browser/tab_contents/navigation_entry.h" #include "chrome/browser/tab_contents/tab_contents.h" +#include "chrome/common/bindings_policy.h" +#include "chrome/common/extensions/extension.h" #include "chrome/common/url_constants.h" #include "grit/chromium_strings.h" #include "grit/generated_resources.h" @@ -30,7 +33,8 @@ ProcessMemoryInformation::ProcessMemoryInformation() : pid(0), num_processes(0), is_diagnostics(false), - type(ChildProcessInfo::UNKNOWN_PROCESS) { + type(ChildProcessInfo::UNKNOWN_PROCESS), + renderer_type(ChildProcessInfo::RENDERER_UNKNOWN) { } ProcessMemoryInformation::~ProcessMemoryInformation() {} @@ -90,6 +94,7 @@ void MemoryDetails::CollectChildInfoOnIOThread() { continue; info.type = iter->type(); + info.renderer_type = iter->renderer_type(); info.titles.push_back(WideToUTF16Hack(iter->name())); child_info.push_back(info); } @@ -113,19 +118,19 @@ void MemoryDetails::CollectChildInfoOnUIThread() { for (size_t index = 0; index < 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. + // check if it's a diagnostics-related process. We skip about:memory pages. + // Iterate the RenderProcessHosts to find the tab contents. ProcessMemoryInformation& process = chrome_browser->processes[index]; for (RenderProcessHost::iterator renderer_iter( RenderProcessHost::AllHostsIterator()); !renderer_iter.IsAtEnd(); renderer_iter.Advance()) { - DCHECK(renderer_iter.GetCurrentValue()); + RenderProcessHost* render_process_host = renderer_iter.GetCurrentValue(); + DCHECK(render_process_host); // Ignore processes that don't have a connection, such as crashed tabs. - if (!renderer_iter.GetCurrentValue()->HasConnection() || process.pid != - base::GetProcId(renderer_iter.GetCurrentValue()->GetHandle())) { + if (!render_process_host->HasConnection() || + process.pid != base::GetProcId(render_process_host->GetHandle())) { continue; } process.type = ChildProcessInfo::RENDER_PROCESS; @@ -137,7 +142,7 @@ void MemoryDetails::CollectChildInfoOnUIThread() { // are always RenderWidgetHosts. But in theory, they don't // have to be. RenderProcessHost::listeners_iterator iter( - renderer_iter.GetCurrentValue()->ListenersIterator()); + render_process_host->ListenersIterator()); for (; !iter.IsAtEnd(); iter.Advance()) { const RenderWidgetHost* widget = static_cast<const RenderWidgetHost*>(iter.GetCurrentValue()); @@ -146,11 +151,56 @@ void MemoryDetails::CollectChildInfoOnUIThread() { continue; const RenderViewHost* host = static_cast<const RenderViewHost*>(widget); + RenderViewHostDelegate* host_delegate = host->delegate(); + GURL url = host_delegate->GetURL(); + ViewType::Type type = host_delegate->GetRenderViewType(); + if (host->enabled_bindings() & BindingsPolicy::DOM_UI) { + // TODO(erikkay) the type for devtools doesn't actually appear to + // be set. + if (type == ViewType::DEV_TOOLS_UI) + process.renderer_type = ChildProcessInfo::RENDERER_DEVTOOLS; + else + process.renderer_type = ChildProcessInfo::RENDERER_CHROME; + } else if (host->enabled_bindings() & BindingsPolicy::EXTENSION) { + process.renderer_type = ChildProcessInfo::RENDERER_EXTENSION; + } TabContents* contents = NULL; - if (host->delegate()) - contents = host->delegate()->GetAsTabContents(); - if (!contents) + if (host_delegate) + contents = host_delegate->GetAsTabContents(); + if (!contents) { + if (host->is_extension_process()) { + // TODO(erikkay) should we just add GetAsExtensionHost to + // TabContents? + ExtensionHost* eh = static_cast<ExtensionHost*>(host_delegate); + string16 title = UTF8ToUTF16(eh->extension()->name()); + process.titles.push_back(title); + } else if (process.renderer_type == + ChildProcessInfo::RENDERER_UNKNOWN) { + process.titles.push_back(UTF8ToUTF16(url.spec())); + switch (type) { + case ViewType::BACKGROUND_CONTENTS: + process.renderer_type = + ChildProcessInfo::RENDERER_BACKGROUND_APP; + break; + case ViewType::INTERSTITIAL_PAGE: + process.renderer_type = ChildProcessInfo::RENDERER_INTERSTITIAL; + break; + case ViewType::NOTIFICATION: + process.renderer_type = ChildProcessInfo::RENDERER_NOTIFICATION; + break; + default: + process.renderer_type = ChildProcessInfo::RENDERER_UNKNOWN; + break; + } + } continue; + } + + // Since We have a TabContents and and the renderer type hasn't been + // set yet, it must be a normal tabbed renderer. + if (process.renderer_type == ChildProcessInfo::RENDERER_UNKNOWN) + process.renderer_type = ChildProcessInfo::RENDERER_NORMAL; + string16 title = contents->GetTitle(); if (!title.length()) title = l10n_util::GetStringUTF16(IDS_DEFAULT_TAB_TITLE); @@ -212,7 +262,11 @@ void MemoryDetails::UpdateHistograms() { const ProcessData& browser = *ChromeBrowser(); size_t aggregate_memory = 0; + int chrome_count = 0; + int extension_count = 0; int plugin_count = 0; + int renderer_count = 0; + int other_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); @@ -221,9 +275,30 @@ void MemoryDetails::UpdateHistograms() { case ChildProcessInfo::BROWSER_PROCESS: UMA_HISTOGRAM_MEMORY_KB("Memory.Browser", sample); break; - case ChildProcessInfo::RENDER_PROCESS: - UMA_HISTOGRAM_MEMORY_KB("Memory.Renderer", sample); + case ChildProcessInfo::RENDER_PROCESS: { + ChildProcessInfo::RendererProcessType renderer_type = + browser.processes[index].renderer_type; + switch (renderer_type) { + case ChildProcessInfo::RENDERER_EXTENSION: + UMA_HISTOGRAM_MEMORY_KB("Memory.Extension", sample); + extension_count++; + break; + case ChildProcessInfo::RENDERER_CHROME: + UMA_HISTOGRAM_MEMORY_KB("Memory.Chrome", sample); + chrome_count++; + break; + case ChildProcessInfo::RENDERER_UNKNOWN: + NOTREACHED() << "Unknown renderer process type."; + break; + case ChildProcessInfo::RENDERER_NORMAL: + default: + // TODO(erikkay): Should we bother splitting out the other subtypes? + UMA_HISTOGRAM_MEMORY_KB("Memory.Renderer", sample); + renderer_count++; + break; + } break; + } case ChildProcessInfo::PLUGIN_PROCESS: UMA_HISTOGRAM_MEMORY_KB("Memory.Plugin", sample); plugin_count++; @@ -234,21 +309,27 @@ void MemoryDetails::UpdateHistograms() { break; case ChildProcessInfo::UTILITY_PROCESS: UMA_HISTOGRAM_MEMORY_KB("Memory.Utility", sample); + other_count++; break; case ChildProcessInfo::ZYGOTE_PROCESS: UMA_HISTOGRAM_MEMORY_KB("Memory.Zygote", sample); + other_count++; break; case ChildProcessInfo::SANDBOX_HELPER_PROCESS: UMA_HISTOGRAM_MEMORY_KB("Memory.SandboxHelper", sample); + other_count++; break; case ChildProcessInfo::NACL_LOADER_PROCESS: UMA_HISTOGRAM_MEMORY_KB("Memory.NativeClient", sample); + other_count++; break; case ChildProcessInfo::NACL_BROKER_PROCESS: UMA_HISTOGRAM_MEMORY_KB("Memory.NativeClientBroker", sample); + other_count++; break; case ChildProcessInfo::GPU_PROCESS: UMA_HISTOGRAM_MEMORY_KB("Memory.Gpu", sample); + other_count++; break; default: NOTREACHED(); @@ -259,7 +340,11 @@ void MemoryDetails::UpdateHistograms() { UMA_HISTOGRAM_COUNTS_100("Memory.ProcessCount", static_cast<int>(browser.processes.size())); + UMA_HISTOGRAM_COUNTS_100("Memory.ChromeProcessCount", chrome_count); + UMA_HISTOGRAM_COUNTS_100("Memory.ExtensionProcessCount", extension_count); + UMA_HISTOGRAM_COUNTS_100("Memory.OtherProcessCount", other_count); UMA_HISTOGRAM_COUNTS_100("Memory.PluginProcessCount", plugin_count); + UMA_HISTOGRAM_COUNTS_100("Memory.RendererProcessCount", renderer_count); UMA_HISTOGRAM_COUNTS_100("Memory.WorkerProcessCount", worker_count); // TODO(viettrungluu): Do we want separate counts for the other // (platform-specific) process types? diff --git a/chrome/browser/memory_details.h b/chrome/browser/memory_details.h index b39a1a6..9333b56 100644 --- a/chrome/browser/memory_details.h +++ b/chrome/browser/memory_details.h @@ -32,11 +32,14 @@ struct ProcessMemoryInformation { string16 product_name; // The number of processes which this memory represents. int num_processes; - // A process is a diagnostics process if it is rendering - // about:xxx information. + // A process is a diagnostics process if it is rendering about:memory. + // Mark this specially so that it can avoid counting it in its own + // results. bool is_diagnostics; // If this is a child process of Chrome, what type (i.e. plugin) it is. ChildProcessInfo::ProcessType type; + // If this is a renderer process, what type it is. + ChildProcessInfo::RendererProcessType renderer_type; // A collection of titles used, i.e. for a tab it'll show all the page titles. std::vector<string16> titles; }; diff --git a/chrome/browser/renderer_host/render_view_host.h b/chrome/browser/renderer_host/render_view_host.h index 02c08d1..697b67d 100644 --- a/chrome/browser/renderer_host/render_view_host.h +++ b/chrome/browser/renderer_host/render_view_host.h @@ -152,7 +152,7 @@ class RenderViewHost : public RenderWidgetHost { // Returns whether navigation messages are currently suspended for this // RenderViewHost. Only true during a cross-site navigation, while waiting // for the onbeforeunload handler. - bool are_navigations_suspended() { return navigations_suspended_; } + bool are_navigations_suspended() const { return navigations_suspended_; } // Suspends (or unsuspends) any navigation messages from being sent from this // RenderViewHost. This is called when a pending RenderViewHost is created @@ -349,10 +349,10 @@ class RenderViewHost : public RenderWidgetHost { // Returns a bitwise OR of bindings types that have been enabled for this // RenderView. See BindingsPolicy for details. - int enabled_bindings() { return enabled_bindings_; } + int enabled_bindings() const { return enabled_bindings_; } // See variable comment. - bool is_extension_process() { return is_extension_process_; } + bool is_extension_process() const { return is_extension_process_; } void set_is_extension_process(bool is_extension_process) { is_extension_process_ = is_extension_process; } diff --git a/chrome/common/child_process_info.cc b/chrome/common/child_process_info.cc index 8774578..69122cc 100644 --- a/chrome/common/child_process_info.cc +++ b/chrome/common/child_process_info.cc @@ -16,8 +16,18 @@ #include "base/utf_string_conversions.h" #include "grit/generated_resources.h" +ChildProcessInfo::ChildProcessInfo(ProcessType type, int id) : + type_(type), + renderer_type_(RENDERER_UNKNOWN) { + if (id == -1) + id_ = GenerateChildProcessUniqueId(); + else + id_ = id; +} + ChildProcessInfo::ChildProcessInfo(const ChildProcessInfo& original) : type_(original.type_), + renderer_type_(original.renderer_type_), name_(original.name_), version_(original.version_), id_(original.id_), @@ -31,6 +41,7 @@ ChildProcessInfo& ChildProcessInfo::operator=( const ChildProcessInfo& original) { if (&original != this) { type_ = original.type_; + renderer_type_ = original.renderer_type_; name_ = original.name_; version_ = original.version_; id_ = original.id_; @@ -39,6 +50,7 @@ ChildProcessInfo& ChildProcessInfo::operator=( return *this; } +// static std::string ChildProcessInfo::GetTypeNameInEnglish( ChildProcessInfo::ProcessType type) { switch (type) { @@ -73,6 +85,41 @@ std::string ChildProcessInfo::GetTypeNameInEnglish( } } +// static +std::string ChildProcessInfo::GetRendererTypeNameInEnglish( + ChildProcessInfo::RendererProcessType type) { + switch (type) { + case RENDERER_NORMAL: + return "Tab"; + case RENDERER_CHROME: + return "Tab (Chrome)"; + case RENDERER_EXTENSION: + return "Extension"; + case RENDERER_DEVTOOLS: + return "Devtools"; + case RENDERER_INTERSTITIAL: + return "Interstitial"; + case RENDERER_NOTIFICATION: + return "Notification"; + case RENDERER_BACKGROUND_APP: + return "Background App"; + case RENDERER_UNKNOWN: + default: + NOTREACHED() << "Unknown renderer process type!"; + return "Unknown"; + } +} + +// static +std::string ChildProcessInfo::GetFullTypeNameInEnglish( + ChildProcessInfo::ProcessType type, + ChildProcessInfo::RendererProcessType rtype) { + if (type == RENDER_PROCESS) + return GetRendererTypeNameInEnglish(rtype); + return GetTypeNameInEnglish(type); +} + + string16 ChildProcessInfo::GetLocalizedTitle() const { string16 title = WideToUTF16Hack(name_); if (type_ == ChildProcessInfo::PLUGIN_PROCESS && title.empty()) @@ -124,13 +171,6 @@ string16 ChildProcessInfo::GetLocalizedTitle() const { return title; } -ChildProcessInfo::ChildProcessInfo(ProcessType type, int id) : type_(type) { - if (id == -1) - id_ = GenerateChildProcessUniqueId(); - else - id_ = id; -} - std::string ChildProcessInfo::GenerateRandomChannelID(void* instance) { // Note: the string must start with the current process id, this is how // child processes determine the pid of the parent. diff --git a/chrome/common/child_process_info.h b/chrome/common/child_process_info.h index 651978f..4d5b721 100644 --- a/chrome/common/child_process_info.h +++ b/chrome/common/child_process_info.h @@ -32,6 +32,19 @@ class ChildProcessInfo { PPAPI_PLUGIN_PROCESS }; + // NOTE: Do not remove or reorder the elements in this enum, and only add new + // items at the end. We depend on these specific values in a histogram. + enum RendererProcessType { + RENDERER_UNKNOWN = 0, + RENDERER_NORMAL, + RENDERER_CHROME, // DOMUI (chrome:// URL) + RENDERER_EXTENSION, // chrome-extension:// + RENDERER_DEVTOOLS, // Web inspector + RENDERER_INTERSTITIAL, // malware/phishing interstitial + RENDERER_NOTIFICATION, // HTML notification bubble + RENDERER_BACKGROUND_APP // hosted app background page + }; + ChildProcessInfo(const ChildProcessInfo& original); virtual ~ChildProcessInfo(); @@ -40,6 +53,10 @@ class ChildProcessInfo { // Returns the type of the process. ProcessType type() const { return type_; } + // Returns the renderer subtype of this process. + // Only valid if the type() is RENDER_PROCESS. + RendererProcessType renderer_type() const { return renderer_type_; } + // Returns the name of the process. i.e. for plugins it might be Flash, while // for workers it might be the domain that it's from. std::wstring name() const { return name_; } @@ -60,7 +77,10 @@ class ChildProcessInfo { // Returns an English name of the process type, should only be used for non // user-visible strings, or debugging pages like about:memory. + static std::string GetFullTypeNameInEnglish(ProcessType type, + RendererProcessType rtype); static std::string GetTypeNameInEnglish(ProcessType type); + static std::string GetRendererTypeNameInEnglish(RendererProcessType type); // Returns a localized title for the child process. For example, a plugin // process would be "Plug-in: Flash" when name is "Flash". @@ -99,12 +119,14 @@ class ChildProcessInfo { ChildProcessInfo(ProcessType type, int id); void set_type(ProcessType type) { type_ = type; } + void set_renderer_type(RendererProcessType type) { renderer_type_ = type; } void set_name(const std::wstring& name) { name_ = name; } void set_version(const std::wstring& ver) { version_ = ver; } void set_handle(base::ProcessHandle handle) { process_.set_handle(handle); } private: ProcessType type_; + RendererProcessType renderer_type_; std::wstring name_; std::wstring version_; int id_; |