diff options
author | jam@chromium.org <jam@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-02-11 23:55:10 +0000 |
---|---|---|
committer | jam@chromium.org <jam@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-02-11 23:55:10 +0000 |
commit | a27a938d8511abfaf89d6e2d0e4d4242c76dffed (patch) | |
tree | 98b133536459106b96a0ee09e0deb94b8d92c4b3 | |
parent | 342c2c40bd1729fe985d5a6ee06f6eb28bbcdc22 (diff) | |
download | chromium_src-a27a938d8511abfaf89d6e2d0e4d4242c76dffed.zip chromium_src-a27a938d8511abfaf89d6e2d0e4d4242c76dffed.tar.gz chromium_src-a27a938d8511abfaf89d6e2d0e4d4242c76dffed.tar.bz2 |
Refactor plugin process code in the browser process so that the browser/about:memory/task manager/metrics code doesn't depend on PluginProcessHost pointers. In a future changelist I'll add one central child process registry in the browser process.
Review URL: http://codereview.chromium.org/20196
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@9621 0039d316-1c4b-4281-b951-d872f2087c98
27 files changed, 554 insertions, 600 deletions
diff --git a/base/base_lib.scons b/base/base_lib.scons index ac27c3c..f32ddd8 100644 --- a/base/base_lib.scons +++ b/base/base_lib.scons @@ -188,6 +188,7 @@ input_files = ChromeFileList([ 'scoped_clipboard_writer.h', 'scoped_comptr_win.h', 'scoped_handle.h', + 'scoped_handle_win.h', 'scoped_nsautorelease_pool.h', 'scoped_ptr.h', 'scoped_temp_dir.cc', diff --git a/base/build/base.vcproj b/base/build/base.vcproj index feaeae3..b9dacfc 100644 --- a/base/build/base.vcproj +++ b/base/build/base.vcproj @@ -718,6 +718,10 @@ > </File> <File + RelativePath="..\scoped_handle_win.h" + > + </File> + <File RelativePath="..\scoped_nsautorelease_pool.h" > </File> diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources.grd index a084af4..6a8669d 100644 --- a/chrome/app/generated_resources.grd +++ b/chrome/app/generated_resources.grd @@ -1526,6 +1526,9 @@ each locale. --> <message name="IDS_TASK_MANAGER_UNKNOWN_PLUGIN_NAME" desc="The prefix for a Task Manager plugin row"> Unknown plug-in </message> + <message name="IDS_TASK_MANAGER_WORKER_PREFIX" desc="The prefix for a Task Manager HTML5 Web Worker process row"> + Web Worker: <ph name="WORKER_NAME">$1<ex>http://www.domain.com</ex></ph> + </message> <!-- Session Crashed Info Bar--> <message name="IDS_SESSION_CRASHED_VIEW_RESTORE_BUTTON" desc="Title of the restore button in the session crashed view."> diff --git a/chrome/browser/browser.cc b/chrome/browser/browser.cc index 95afc30..6491c56 100644 --- a/chrome/browser/browser.cc +++ b/chrome/browser/browser.cc @@ -96,10 +96,9 @@ class ReducePluginsWorkingSetTask : public Task { virtual void Run() { #if defined(OS_WIN) for (PluginProcessHostIterator iter; !iter.Done(); ++iter) { - PluginProcessHost* plugin = const_cast<PluginProcessHost*>(*iter); - DCHECK(plugin->process()); - base::Process process(plugin->process()); - process.ReduceWorkingSet(); + ChildProcessInfo* child = const_cast<PluginProcessHost*>(*iter); + DCHECK(child->process().handle()); + child->process().ReduceWorkingSet(); } #endif } diff --git a/chrome/browser/browser.scons b/chrome/browser/browser.scons index ea092ea..00ac75c 100644 --- a/chrome/browser/browser.scons +++ b/chrome/browser/browser.scons @@ -118,7 +118,6 @@ input_files = ChromeFileList([ 'meta_table_helper.h', 'plugin_process_host.cc', 'plugin_process_host.h', - 'plugin_process_info.h', 'plugin_service.cc', 'plugin_service.h', '../tools/build/win/precompiled_wtl.cc', diff --git a/chrome/browser/browser.vcproj b/chrome/browser/browser.vcproj index 91c6b41..8c02fd3 100644 --- a/chrome/browser/browser.vcproj +++ b/chrome/browser/browser.vcproj @@ -434,10 +434,6 @@ > </File> <File - RelativePath=".\plugin_process_info.h" - > - </File> - <File RelativePath=".\plugin_service.cc" > </File> diff --git a/chrome/browser/browser_about_handler.cc b/chrome/browser/browser_about_handler.cc index d8ff07f..bf89af0 100644 --- a/chrome/browser/browser_about_handler.cc +++ b/chrome/browser/browser_about_handler.cc @@ -22,7 +22,6 @@ #include "chrome/browser/net/dns_global.h" #include "chrome/browser/profile.h" #include "chrome/browser/profile_manager.h" -#include "chrome/browser/renderer_host/render_process_host.h" #include "chrome/browser/renderer_host/render_view_host.h" #include "chrome/browser/views/about_ipc_dialog.h" #include "chrome/common/jstemplate_builder.h" @@ -93,8 +92,7 @@ class AboutMemoryHandler : public MemoryDetails { private: void BindProcessMetrics(DictionaryValue* data, ProcessMemoryInformation* info); - void GetTabContentsTitles(RenderProcessHost* rph, ListValue* titles); - void AppendProcess(ListValue* renderers, ProcessMemoryInformation* info); + void AppendProcess(ListValue* child_data, ProcessMemoryInformation* info); void FinishAboutMemory(); AboutSource* source_; @@ -496,85 +494,25 @@ void AboutMemoryHandler::BindProcessMetrics(DictionaryValue* data, data->SetInteger(L"processes", info->num_processes); } -// Helper for AboutMemory to iterate over a RenderProcessHost's listeners -// and retrieve the tab titles. -void AboutMemoryHandler::GetTabContentsTitles(RenderProcessHost* rph, - ListValue* titles) { - RenderProcessHost::listeners_iterator iter; - // NOTE: This is a bit dangerous. We know that for now, listeners - // are always RenderWidgetHosts. But in theory, they don't - // have to be. - for (iter = rph->listeners_begin(); iter != rph->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 = static_cast<WebContents*>(host->delegate()); - DCHECK(contents); - if (!contents) - continue; - - std::wstring title = contents->GetTitle(); - StringValue* val = NULL; - if (!title.length()) - title = L"Untitled"; - val = new StringValue(title); - titles->Append(val); - } -} - // Helper for AboutMemory to append memory usage information for all -// sub-processes (renderers & plugins) used by chrome. -void AboutMemoryHandler::AppendProcess(ListValue* renderers, +// sub-processes (i.e. renderers, plugins) used by Chrome. +void AboutMemoryHandler::AppendProcess(ListValue* child_data, ProcessMemoryInformation* info) { - DCHECK(renderers && info); + DCHECK(child_data && info); // Append a new DictionaryValue for this renderer to our list. - DictionaryValue* renderer = new DictionaryValue(); - renderers->Append(renderer); - BindProcessMetrics(renderer, info); - - // Now get more information about the process. - - // First, figure out if it is a renderer. - RenderProcessHost::iterator renderer_iter; - for (renderer_iter = RenderProcessHost::begin(); renderer_iter != - RenderProcessHost::end(); ++renderer_iter) { - if (renderer_iter->second->process().pid() == info->pid) - break; - } - if (renderer_iter != RenderProcessHost::end()) { - std::wstring renderer_label(L"Tab "); - renderer_label.append(FormatNumber(renderer_iter->second->host_id())); - if (info->is_diagnostics) - renderer_label.append(L" (diagnostics)"); - renderer->SetString(L"renderer_id", renderer_label); - ListValue* titles = new ListValue(); - renderer->Set(L"titles", titles); - GetTabContentsTitles(renderer_iter->second, titles); - return; - } - - // Figure out if this is a plugin process. - for (size_t index = 0; index < plugins()->size(); ++index) { - if (info->pid == (*plugins())[index].pid) { - // It is a plugin! - std::wstring label(L"Plug-in"); - std::wstring name; - renderer->SetString(L"renderer_id", label); - FileVersionInfo* version_info = - FileVersionInfo::CreateFileVersionInfo( - (*plugins())[index].plugin_path); - if (version_info) - name = version_info->product_name(); - ListValue* titles = new ListValue(); - renderer->Set(L"titles", titles); - titles->Append(new StringValue(name)); - return; - } - } + DictionaryValue* child = new DictionaryValue(); + child_data->Append(child); + BindProcessMetrics(child, info); + + std::wstring child_label(ChildProcessInfo::GetTypeNameInEnglish(info->type)); + if (info->is_diagnostics) + child_label.append(L" (diagnostics)"); + child->SetString(L"child_name", child_label); + ListValue* titles = new ListValue(); + child->Set(L"titles", titles); + for (size_t i = 0; i < info->titles.size(); ++i) + titles->Append(new StringValue(info->titles[i])); } @@ -631,20 +569,18 @@ void AboutMemoryHandler::OnDetailsAvailable() { if (log_string.length() > 0) LOG(INFO) << "memory: " << log_string; - // Set the browser & renderer detailed process data. DictionaryValue* browser_data = new DictionaryValue(); root.Set(L"browzr_data", browser_data); - ListValue* renderer_data = new ListValue(); - root.Set(L"renderer_data", renderer_data); + ListValue* child_data = new ListValue(); + root.Set(L"child_data", child_data); - DWORD browser_pid = GetCurrentProcessId(); ProcessData process = browser_processes[0]; // Chrome is the first browser. for (size_t index = 0; index < process.processes.size(); index++) { - if (process.processes[index].pid == browser_pid) + if (process.processes[index].type == ChildProcessInfo::BROWSER_PROCESS) BindProcessMetrics(browser_data, &process.processes[index]); else - AppendProcess(renderer_data, &process.processes[index]); + AppendProcess(child_data, &process.processes[index]); } // Get about_memory.html @@ -665,4 +601,3 @@ void BrowserAboutHandler::AboutMemory(AboutSource* source, int request_id) { // The AboutMemoryHandler cleans itself up. new AboutMemoryHandler(source, request_id); } - diff --git a/chrome/browser/memory_details.cc b/chrome/browser/memory_details.cc index f2c3f79..e1279fe 100644 --- a/chrome/browser/memory_details.cc +++ b/chrome/browser/memory_details.cc @@ -10,9 +10,9 @@ #include "base/image_util.h" #include "base/message_loop.h" #include "base/process_util.h" +#include "base/scoped_ptr.h" #include "base/thread.h" #include "chrome/browser/browser_process.h" -#include "chrome/browser/browser_trial.h" #include "chrome/browser/chrome_thread.h" #include "chrome/browser/plugin_process_host.h" #include "chrome/browser/plugin_service.h" @@ -64,155 +64,190 @@ void MemoryDetails::StartFetch() { // 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::CollectPluginInformation)); + NewRunnableMethod(this, &MemoryDetails::CollectChildInfoOnIOThread)); } -void MemoryDetails::CollectPluginInformation() { +void MemoryDetails::CollectChildInfoOnIOThread() { DCHECK(MessageLoop::current() == ChromeThread::GetMessageLoop(ChromeThread::IO)); + std::vector<ProcessMemoryInformation> child_info; + // Collect the list of plugins. for (PluginProcessHostIterator plugin_iter; !plugin_iter.Done(); ++plugin_iter) { - PluginProcessHost* plugin = const_cast<PluginProcessHost*>(*plugin_iter); - DCHECK(plugin); - if (!plugin || !plugin->process()) + ChildProcessInfo* child = const_cast<PluginProcessHost*>(*plugin_iter); + DCHECK(child); + if (!child || !child->process().handle()) continue; - PluginProcessInformation info; - info.pid = base::GetProcId(plugin->process()); - if (info.pid != 0) { - info.plugin_path = plugin->plugin_path(); - plugins_.push_back(info); - } + ProcessMemoryInformation info; + info.pid = child->process().pid(); + if (!info.pid) + continue; + + info.type = child->type(); + info.titles.push_back(child->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)); + NewRunnableMethod(this, &MemoryDetails::CollectProcessData, child_info)); } -void MemoryDetails::CollectProcessData() { +void MemoryDetails::CollectProcessData( + std::vector<ProcessMemoryInformation> child_info) { DCHECK(MessageLoop::current() == ChromeThread::GetMessageLoop(ChromeThread::FILE)); int array_size = 32; - DWORD* process_list = NULL; + scoped_ptr_malloc<DWORD> process_list; DWORD bytes_used = 0; do { array_size *= 2; - process_list = static_cast<DWORD*>( - realloc(process_list, sizeof(*process_list) * array_size)); + process_list.reset(static_cast<DWORD*>( + realloc(process_list.release(), sizeof(DWORD) * array_size))); // EnumProcesses doesn't return an error if the array is too small. // We have to check if the return buffer is full, and if so, call it // again. See msdn docs for more info. - if (!EnumProcesses(process_list, array_size * sizeof(*process_list), + if (!EnumProcesses(process_list.get(), array_size * sizeof(DWORD), &bytes_used)) { LOG(ERROR) << "EnumProcesses failed: " << GetLastError(); return; } - } while (bytes_used == (array_size * sizeof(*process_list))); + } while (bytes_used == (array_size * sizeof(DWORD))); - int num_processes = bytes_used / sizeof(*process_list); + int num_processes = bytes_used / sizeof(DWORD); // Clear old data. for (int index = 0; index < arraysize(g_process_template); index++) process_data_[index].processes.clear(); for (int index = 0; index < num_processes; index++) { - HANDLE handle = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, - FALSE, process_list[index]); - if (handle) { - TCHAR name[MAX_PATH]; - if (GetModuleBaseName(handle, NULL, name, MAX_PATH-1)) { - for (int index2 = 0; index2 < arraysize(g_process_template); index2++) { - if (_wcsicmp(process_data_[index2].process_name, name) == 0) { - // Get Memory Information. - ProcessMemoryInformation info; - info.pid = process_list[index]; - scoped_ptr<base::ProcessMetrics> metrics; - metrics.reset(base::ProcessMetrics::CreateProcessMetrics(handle)); - metrics->GetCommittedKBytes(&info.committed); - metrics->GetWorkingSetKBytes(&info.working_set); - - // Get Version Information. - if (index2 == 0) { // Chrome - scoped_ptr<FileVersionInfo> version_info( - FileVersionInfo::CreateFileVersionInfoForCurrentModule()); - if (version_info != NULL) - info.version = version_info->file_version(); - } else if (GetModuleFileNameEx(handle, NULL, name, MAX_PATH-1)) { - std::wstring str_name(name); - scoped_ptr<FileVersionInfo> version_info( - FileVersionInfo::CreateFileVersionInfo(str_name)); - if (version_info != NULL) { - info.version = version_info->product_version(); - info.product_name = version_info->product_name(); - } - } - - // Add the process info to our list. - process_data_[index2].processes.push_back(info); - break; - } + int pid = process_list.get()[index]; + ScopedHandle handle(OpenProcess( + PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, pid)); + if (!handle.Get()) + continue; + TCHAR name[MAX_PATH]; + if (!GetModuleBaseName(handle, NULL, name, MAX_PATH - 1)) + continue; + for (int index2 = 0; index2 < arraysize(g_process_template); index2++) { + if (_wcsicmp(process_data_[index2].process_name, name) != 0) + continue; + // Get Memory Information. + ProcessMemoryInformation info; + info.pid = pid; + if (info.pid == GetCurrentProcessId()) + info.type = ChildProcessInfo::BROWSER_PROCESS; + else + info.type = ChildProcessInfo::UNKNOWN_PROCESS; + + scoped_ptr<base::ProcessMetrics> metrics; + metrics.reset(base::ProcessMetrics::CreateProcessMetrics(handle)); + metrics->GetCommittedKBytes(&info.committed); + metrics->GetWorkingSetKBytes(&info.working_set); + + // Get Version Information. + if (index2 == 0) { // Chrome + scoped_ptr<FileVersionInfo> version_info( + FileVersionInfo::CreateFileVersionInfoForCurrentModule()); + if (version_info != NULL) + info.version = version_info->file_version(); + // Check if this is one of the child processes whose data we collected + // on the IO thread, and if so copy over that data. + for (size_t child = 0; child < child_info.size(); child++) { + if (child_info[child].pid != info.pid) + continue; + info.titles = child_info[child].titles; + info.type = child_info[child].type; + break; + } + } else if (GetModuleFileNameEx(handle, NULL, name, MAX_PATH - 1)) { + std::wstring str_name(name); + scoped_ptr<FileVersionInfo> version_info( + FileVersionInfo::CreateFileVersionInfo(str_name)); + if (version_info != NULL) { + info.version = version_info->product_version(); + info.product_name = version_info->product_name(); } } - CloseHandle(handle); + + // Add the process info to our list. + process_data_[index2].processes.push_back(info); + break; } } - free(process_list); // Finally return to the browser thread. ui_loop_->PostTask(FROM_HERE, - NewRunnableMethod(this, &MemoryDetails::CollectRenderHostInformation)); + NewRunnableMethod(this, &MemoryDetails::CollectChildInfoOnUIThread)); } -void MemoryDetails::CollectRenderHostInformation() { +void MemoryDetails::CollectChildInfoOnUIThread() { DCHECK(MessageLoop::current() == ui_loop_); - // Determine if this is a diagnostics-related process. We skip all - // diagnostics pages (e.g. "about:xxx" URLs). Iterate the RenderProcessHosts - // to find the tab contents. If it is of type TAB_CONTENTS_ABOUT_UI, mark - // the process as diagnostics related. + // 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. If it is of type TAB_CONTENTS_ABOUT_UI, mark the + // process as diagnostics related. RenderProcessHost::iterator renderer_iter; for (renderer_iter = RenderProcessHost::begin(); renderer_iter != RenderProcessHost::end(); ++renderer_iter) { DCHECK(renderer_iter->second); - if (process_data_[CHROME_BROWSER].processes[index].pid == - renderer_iter->second->process().pid()) { - // 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 = - static_cast<WebContents*>(host->delegate()); - DCHECK(contents); - if (!contents) - continue; - - if (contents->type() == TAB_CONTENTS_ABOUT_UI) - process_data_[CHROME_BROWSER].processes[index].is_diagnostics = - true; - } + 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 = + static_cast<WebContents*>(host->delegate()); + DCHECK(contents); + if (!contents) + continue; + std::wstring title = contents->GetTitle(); + if (!title.length()) + title = L"Untitled"; + process.titles.push_back(title); + if (contents->type() == TAB_CONTENTS_ABOUT_UI) + 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(); @@ -222,61 +257,36 @@ void MemoryDetails::UpdateHistograms() { // Reports a set of memory metrics to UMA. // Memory is measured in units of 10KB. - // If field trial is active, report results in special histograms. - static scoped_refptr<FieldTrial> trial( - FieldTrialList::Find(BrowserTrial::kMemoryModelFieldTrial)); - - DWORD browser_pid = GetCurrentProcessId(); 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; - if (browser.processes[index].pid == browser_pid) { - if (trial.get()) { - if (trial->boolean_value()) - UMA_HISTOGRAM_MEMORY_KB(L"Memory.Browser_trial_high_memory", sample); - else - UMA_HISTOGRAM_MEMORY_KB(L"Memory.Browser_trial_med_memory", sample); - } else { - UMA_HISTOGRAM_MEMORY_KB(L"Memory.Browser", sample); - } - } else { - bool is_plugin_process = false; - for (size_t index2 = 0; index2 < plugins_.size(); index2++) { - if (browser.processes[index].pid == plugins_[index2].pid) { - UMA_HISTOGRAM_MEMORY_KB(L"Memory.Plugin", sample); - is_plugin_process = true; - break; - } - } - if (!is_plugin_process) { - if (trial.get()) { - if (trial->boolean_value()) - UMA_HISTOGRAM_MEMORY_KB(L"Memory.Renderer_trial_high_memory", - sample); - else - UMA_HISTOGRAM_MEMORY_KB(L"Memory.Renderer_trial_med_memory", - sample); - } else { - UMA_HISTOGRAM_MEMORY_KB(L"Memory.Renderer", sample); - } - } + switch (browser.processes[index].type) { + case ChildProcessInfo::BROWSER_PROCESS: + UMA_HISTOGRAM_MEMORY_KB(L"Memory.Browser", sample); + break; + case ChildProcessInfo::RENDER_PROCESS: + UMA_HISTOGRAM_MEMORY_KB(L"Memory.Renderer", sample); + break; + case ChildProcessInfo::PLUGIN_PROCESS: + UMA_HISTOGRAM_MEMORY_KB(L"Memory.Plugin", sample); + plugin_count++; + break; + case ChildProcessInfo::WORKER_PROCESS: + UMA_HISTOGRAM_MEMORY_KB(L"Memory.Worker", sample); + worker_count++; + break; } } + UMA_HISTOGRAM_COUNTS_100(L"Memory.ProcessCount", static_cast<int>(browser.processes.size())); - UMA_HISTOGRAM_COUNTS_100(L"Memory.PluginProcessCount", - static_cast<int>(plugins_.size())); + UMA_HISTOGRAM_COUNTS_100(L"Memory.PluginProcessCount", plugin_count); + UMA_HISTOGRAM_COUNTS_100(L"Memory.WorkerProcessCount", worker_count); int total_sample = static_cast<int>(aggregate_memory / 1000); - if (trial.get()) { - if (trial->boolean_value()) - UMA_HISTOGRAM_MEMORY_MB(L"Memory.Total_trial_high_memory", total_sample); - else - UMA_HISTOGRAM_MEMORY_MB(L"Memory.Total_trial_med_memory", total_sample); - } else { - UMA_HISTOGRAM_MEMORY_MB(L"Memory.Total", total_sample); - } + UMA_HISTOGRAM_MEMORY_MB(L"Memory.Total", total_sample); } - diff --git a/chrome/browser/memory_details.h b/chrome/browser/memory_details.h index 0a542cc..17a00a1 100644 --- a/chrome/browser/memory_details.h +++ b/chrome/browser/memory_details.h @@ -12,6 +12,7 @@ #include "base/file_path.h" #include "base/process_util.h" #include "base/ref_counted.h" +#include "chrome/common/child_process_info.h" class MessageLoop; @@ -38,17 +39,14 @@ struct ProcessMemoryInformation { // A process is a diagnostics process if it is rendering // about:xxx information. bool is_diagnostics; + // If this is a child process of Chrome, what type (i.e. plugin) it is. + ChildProcessInfo::ProcessType type; + // A collection of titles used, i.e. for a tab it'll show all the page titles. + std::vector<std::wstring> titles; }; typedef std::vector<ProcessMemoryInformation> ProcessMemoryInformationList; -// Information that we need about a plugin process. -struct PluginProcessInformation { - int pid; - FilePath plugin_path; -}; -typedef std::vector<PluginProcessInformation> PluginProcessInformationList; - // Browser Process Information. struct ProcessData { const wchar_t* name; @@ -95,9 +93,6 @@ class MemoryDetails : public base::RefCountedThreadSafe<MemoryDetails> { // after OnDetailsAvailable() has been called. ProcessData* processes() { return process_data_; } - // Access to the plugin details. - const PluginProcessInformationList* plugins() const { return &plugins_; } - // Initiate updating the current memory details. These are fetched // asynchronously because data must be collected from multiple threads. // OnDetailsAvailable will be called when this process is complete. @@ -106,30 +101,30 @@ class MemoryDetails : public base::RefCountedThreadSafe<MemoryDetails> { virtual void OnDetailsAvailable() {} private: - // Collect the a list of information about current plugin processes that - // will be used by about:memory. When finished, invokes back to the - // return_loop to run the rest of the about:memory functionality. - // Runs on the IO thread because the PluginProcessHost is only accessible - // from the IO thread. - void CollectPluginInformation(); + // Collect child process information on the IO thread. This is needed because + // information about some child process types (i.e. plugins) can only be taken + // on that thread. The data will be used by about:memory. When finished, + // invokes back to the file thread to run the rest of the about:memory + // functionality. + void CollectChildInfoOnIOThread(); // Collect current process information from the OS and store it // for processing. If data has already been collected, clears old // data and re-collects the data. // Note - this function enumerates memory details from many processes - // and is fairly expensive to run. - void CollectProcessData(); + // and is fairly expensive to run, hence it's run on the file thread. + // The parameter holds information about processes from the IO thread. + void CollectProcessData(std::vector<ProcessMemoryInformation>); - // Collect renderer specific information. This information is gathered - // on the Browser thread, where the RenderHostIterator is accessible. - void CollectRenderHostInformation(); + // Collect child process information on the UI thread. Information about + // renderer processes is only available there. + void CollectChildInfoOnUIThread(); // Each time we take a memory sample, we do a little work to update // the global histograms for tracking memory usage. void UpdateHistograms(); ProcessData process_data_[MAX_BROWSERS]; - PluginProcessInformationList plugins_; MessageLoop* ui_loop_; DISALLOW_EVIL_CONSTRUCTORS(MemoryDetails); diff --git a/chrome/browser/metrics/metrics_log.cc b/chrome/browser/metrics/metrics_log.cc index 3603e0c..27cb88e 100644 --- a/chrome/browser/metrics/metrics_log.cc +++ b/chrome/browser/metrics/metrics_log.cc @@ -382,16 +382,13 @@ void MetricsLog::WritePluginStabilityElements(PrefService* pref) { } DictionaryValue* plugin_dict = static_cast<DictionaryValue*>(*iter); - std::wstring plugin_path; - plugin_dict->GetString(prefs::kStabilityPluginPath, &plugin_path); - plugin_path = file_util::GetFilenameFromPath(plugin_path); - if (plugin_path.empty()) { - NOTREACHED(); - continue; - } + std::wstring plugin_name; + plugin_dict->GetString(prefs::kStabilityPluginName, &plugin_name); OPEN_ELEMENT_FOR_SCOPE("pluginstability"); - WriteAttribute("filename", CreateBase64Hash(WideToUTF8(plugin_path))); + // Use "filename" instead of "name", otherwise we need to update the + // UMA servers. + WriteAttribute("filename", CreateBase64Hash(WideToUTF8(plugin_name))); int launches = 0; plugin_dict->GetInteger(prefs::kStabilityPluginLaunches, &launches); diff --git a/chrome/browser/metrics/metrics_service.cc b/chrome/browser/metrics/metrics_service.cc index b25b5b1..55aca76 100644 --- a/chrome/browser/metrics/metrics_service.cc +++ b/chrome/browser/metrics/metrics_service.cc @@ -170,12 +170,12 @@ #include "chrome/browser/browser_process.h" #include "chrome/browser/load_notification_details.h" #include "chrome/browser/memory_details.h" -#include "chrome/browser/plugin_process_info.h" #include "chrome/browser/plugin_service.h" #include "chrome/browser/profile.h" #include "chrome/browser/renderer_host/render_process_host.h" #include "chrome/browser/search_engines/template_url.h" #include "chrome/browser/search_engines/template_url_model.h" +#include "chrome/common/child_process_info.h" #include "chrome/common/chrome_paths.h" #include "chrome/common/libxml_utils.h" #include "chrome/common/notification_service.h" @@ -464,10 +464,10 @@ void MetricsService::Observe(NotificationType type, LogRendererInSandbox(*Details<bool>(details).ptr()); break; - case NotificationType::PLUGIN_PROCESS_HOST_CONNECTED: - case NotificationType::PLUGIN_PROCESS_CRASHED: - case NotificationType::PLUGIN_INSTANCE_CREATED: - LogPluginChange(type, source, details); + case NotificationType::CHILD_PROCESS_HOST_CONNECTED: + case NotificationType::CHILD_PROCESS_CRASHED: + case NotificationType::CHILD_INSTANCE_CREATED: + LogChildProcessChange(type, source, details); break; case NotificationType::TEMPLATE_URL_MODEL_LOADED: @@ -723,11 +723,11 @@ void MetricsService::ListenerRegistration(bool start_listening) { start_listening); AddOrRemoveObserver(this, NotificationType::RENDERER_PROCESS_HANG, start_listening); - AddOrRemoveObserver(this, NotificationType::PLUGIN_PROCESS_HOST_CONNECTED, + AddOrRemoveObserver(this, NotificationType::CHILD_PROCESS_HOST_CONNECTED, start_listening); - AddOrRemoveObserver(this, NotificationType::PLUGIN_INSTANCE_CREATED, + AddOrRemoveObserver(this, NotificationType::CHILD_INSTANCE_CREATED, start_listening); - AddOrRemoveObserver(this, NotificationType::PLUGIN_PROCESS_CRASHED, + AddOrRemoveObserver(this, NotificationType::CHILD_PROCESS_CRASHED, start_listening); AddOrRemoveObserver(this, NotificationType::TEMPLATE_URL_MODEL_LOADED, start_listening); @@ -1533,26 +1533,29 @@ void MetricsService::LogRendererHang() { IncrementPrefValue(prefs::kStabilityRendererHangCount); } -void MetricsService::LogPluginChange(NotificationType type, - const NotificationSource& source, - const NotificationDetails& details) { - FilePath plugin = Details<PluginProcessInfo>(details)->plugin_path(); +void MetricsService::LogChildProcessChange( + NotificationType type, + const NotificationSource& source, + const NotificationDetails& details) { + const std::wstring& child_name = + Details<ChildProcessInfo>(details)->name(); - if (plugin_stats_buffer_.find(plugin) == plugin_stats_buffer_.end()) { - plugin_stats_buffer_[plugin] = PluginStats(); + if (child_process_stats_buffer_.find(child_name) == + child_process_stats_buffer_.end()) { + child_process_stats_buffer_[child_name] = ChildProcessStats(); } - PluginStats& stats = plugin_stats_buffer_[plugin]; + ChildProcessStats& stats = child_process_stats_buffer_[child_name]; switch (type.value) { - case NotificationType::PLUGIN_PROCESS_HOST_CONNECTED: + case NotificationType::CHILD_PROCESS_HOST_CONNECTED: stats.process_launches++; break; - case NotificationType::PLUGIN_INSTANCE_CREATED: + case NotificationType::CHILD_INSTANCE_CREATED: stats.instances++; break; - case NotificationType::PLUGIN_PROCESS_CRASHED: + case NotificationType::CHILD_PROCESS_CRASHED: stats.process_crashes++; break; @@ -1620,18 +1623,18 @@ void MetricsService::RecordPluginChanges(PrefService* pref) { } DictionaryValue* plugin_dict = static_cast<DictionaryValue*>(*value_iter); - FilePath::StringType plugin_path_str; - plugin_dict->GetString(prefs::kStabilityPluginPath, &plugin_path_str); - if (plugin_path_str.empty()) { + std::wstring plugin_name; + plugin_dict->GetString(prefs::kStabilityPluginName, &plugin_name); + if (plugin_name.empty()) { NOTREACHED(); continue; } - FilePath plugin_path(plugin_path_str); - if (plugin_stats_buffer_.find(plugin_path) == plugin_stats_buffer_.end()) + if (child_process_stats_buffer_.find(plugin_name) == + child_process_stats_buffer_.end()) continue; - PluginStats stats = plugin_stats_buffer_[plugin_path]; + ChildProcessStats stats = child_process_stats_buffer_[plugin_name]; if (stats.process_launches) { int launches = 0; plugin_dict->GetInteger(prefs::kStabilityPluginLaunches, &launches); @@ -1651,19 +1654,19 @@ void MetricsService::RecordPluginChanges(PrefService* pref) { plugin_dict->SetInteger(prefs::kStabilityPluginInstances, instances); } - plugin_stats_buffer_.erase(plugin_path); + child_process_stats_buffer_.erase(plugin_name); } // Now go through and add dictionaries for plugins that didn't already have // reports in Local State. - for (std::map<FilePath, PluginStats>::iterator cache_iter = - plugin_stats_buffer_.begin(); - cache_iter != plugin_stats_buffer_.end(); ++cache_iter) { - FilePath plugin_path = cache_iter->first; - PluginStats stats = cache_iter->second; + for (std::map<std::wstring, ChildProcessStats>::iterator cache_iter = + child_process_stats_buffer_.begin(); + cache_iter != child_process_stats_buffer_.end(); ++cache_iter) { + std::wstring plugin_name = cache_iter->first; + ChildProcessStats stats = cache_iter->second; DictionaryValue* plugin_dict = new DictionaryValue; - plugin_dict->SetString(prefs::kStabilityPluginPath, plugin_path.value()); + plugin_dict->SetString(prefs::kStabilityPluginName, plugin_name); plugin_dict->SetInteger(prefs::kStabilityPluginLaunches, stats.process_launches); plugin_dict->SetInteger(prefs::kStabilityPluginCrashes, @@ -1672,7 +1675,7 @@ void MetricsService::RecordPluginChanges(PrefService* pref) { stats.instances); plugins->Append(plugin_dict); } - plugin_stats_buffer_.clear(); + child_process_stats_buffer_.clear(); } bool MetricsService::CanLogNotification(NotificationType type, diff --git a/chrome/browser/metrics/metrics_service.h b/chrome/browser/metrics/metrics_service.h index 64780d7..d42d953 100644 --- a/chrome/browser/metrics/metrics_service.h +++ b/chrome/browser/metrics/metrics_service.h @@ -15,7 +15,6 @@ #include <vector> #include "base/basictypes.h" -#include "base/file_path.h" #include "base/histogram.h" #include "base/scoped_ptr.h" #include "base/values.h" @@ -30,22 +29,23 @@ class PrefService; class Profile; class TemplateURLModel; -// This is used to quickly log stats from plugin-related notifications in -// MetricsService::plugin_stats_buffer_. The buffer's contents are transferred +// This is used to quickly log stats from child process related notifications in +// MetricsService::child_stats_buffer_. The buffer's contents are transferred // out when Local State is periodically saved. The information is then // reported to the UMA server on next launch. -struct PluginStats { +struct ChildProcessStats { public: - PluginStats() : process_launches(0), process_crashes(0), instances(0) {} + ChildProcessStats() : process_launches(0), process_crashes(0), instances(0) {} - // The number of times that the given plugin process has been launched + // The number of times that the given child process has been launched int process_launches; - // The number of times that the given plugin process has crashed + // The number of times that the given child process has crashed int process_crashes; - // The number of instances of this plugin that have been created. - // An instance is a DOM object rendered by this plugin during a page load. + // The number of instances of this child process that have been created. + // An instance is a DOM object rendered by this child process during a page + // load. int instances; }; @@ -315,12 +315,12 @@ class MetricsService : public NotificationObserver, // Sets preferences for the for the number of bookmarks in model. void LogBookmarks(BookmarkModel* model); - // Records a plugin-related notification. These are recorded to an in-object - // buffer because these notifications are sent on page load, and we don't - // want to slow that down. - void LogPluginChange(NotificationType type, - const NotificationSource& source, - const NotificationDetails& details); + // Records a child process related notification. These are recorded to an + // in-object buffer because these notifications are sent on page load, and we + // don't want to slow that down. + void LogChildProcessChange(NotificationType type, + const NotificationSource& source, + const NotificationDetails& details); // Logs keywords specific metrics. Keyword metrics are recorded in the // profile specific metrics. @@ -421,9 +421,9 @@ class MetricsService : public NotificationObserver, WindowMap window_map_; int next_window_id_; - // Buffer of plugin notifications for quick access. See PluginStats - // documentation above for more details. - std::map<FilePath, PluginStats> plugin_stats_buffer_; + // Buffer of child process notifications for quick access. See + // ChildProcessStats documentation above for more details. + std::map<std::wstring, ChildProcessStats> child_process_stats_buffer_; ScopedRunnableMethodFactory<MetricsService> log_sender_factory_; ScopedRunnableMethodFactory<MetricsService> state_saver_factory_; diff --git a/chrome/browser/plugin_process_host.cc b/chrome/browser/plugin_process_host.cc index feab679..6ba74de 100644 --- a/chrome/browser/plugin_process_host.cc +++ b/chrome/browser/plugin_process_host.cc @@ -10,15 +10,16 @@ #include "base/command_line.h" #include "base/debug_util.h" #include "base/file_util.h" +#include "base/file_version_info.h" #include "base/logging.h" #include "base/path_service.h" #include "base/process_util.h" +#include "base/scoped_ptr.h" #include "base/thread.h" #include "base/win_util.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/chrome_plugin_browsing_context.h" #include "chrome/browser/chrome_thread.h" -#include "chrome/browser/plugin_process_info.h" #include "chrome/browser/plugin_service.h" #include "chrome/browser/profile.h" #include "chrome/browser/renderer_host/browser_render_process_host.h" @@ -32,6 +33,7 @@ #include "chrome/common/ipc_logging.h" #include "chrome/common/logging_chrome.h" #include "chrome/common/notification_service.h" +#include "chrome/common/notification_type.h" #include "chrome/common/plugin_messages.h" #include "chrome/common/process_watcher.h" #include "chrome/common/render_messages.h" @@ -51,47 +53,20 @@ static const char kDefaultPluginFinderURL[] = class PluginNotificationTask : public Task { public: PluginNotificationTask(NotificationType notification_type, - FilePath plugin_path, - HANDLE process); + ChildProcessInfo* info) + : notification_type_(notification_type), info_(*info) { } - virtual void Run(); + virtual void Run() { + NotificationService::current()-> + Notify(notification_type_, NotificationService::AllSources(), + Details<ChildProcessInfo>(&info_)); + } private: NotificationType notification_type_; - FilePath plugin_path_; - HANDLE process_; + ChildProcessInfo info_; }; -PluginNotificationTask::PluginNotificationTask( - NotificationType notification_type, - FilePath plugin_path, - HANDLE process) - : notification_type_(notification_type), - process_(process), - plugin_path_(plugin_path) { -} - -void PluginNotificationTask::Run() { - // Verify that the notification type is one that makes sense. - switch (notification_type_.value) { - case NotificationType::PLUGIN_PROCESS_HOST_CONNECTED: - case NotificationType::PLUGIN_PROCESS_HOST_DISCONNECTED: - case NotificationType::PLUGIN_PROCESS_CRASHED: - case NotificationType::PLUGIN_INSTANCE_CREATED: - break; - - default: - NOTREACHED(); - return; - } - - PluginProcessInfo ppi(plugin_path_, process_); - // As mentioned in the notification_types.h, the PluginProcessInfo details - // are only valid for the time of the notification. - NotificationService::current()-> - Notify(notification_type_, NotificationService::AllSources(), - Details<PluginProcessInfo>(&ppi)); -} // The PluginDownloadUrlHelper is used to handle one download URL request // from the plugin. Each download request is handled by a new instance @@ -383,27 +358,29 @@ class DestroyWindowTask : public Task { PluginProcessHost::PluginProcessHost(PluginService* plugin_service) - : process_(NULL), - opening_channel_(false), + : opening_channel_(false), resource_dispatcher_host_(plugin_service->resource_dispatcher_host()), ALLOW_THIS_IN_INITIALIZER_LIST(resolve_proxy_msg_helper_(this, NULL)), plugin_service_(plugin_service) { DCHECK(resource_dispatcher_host_); + set_type(PLUGIN_PROCESS); } PluginProcessHost::~PluginProcessHost() { - if (process_.handle()) { + if (process().handle()) { watcher_.StopWatching(); - ProcessWatcher::EnsureProcessTerminated(process_.handle()); + ProcessWatcher::EnsureProcessTerminated(process().handle()); } } -bool PluginProcessHost::Init(const FilePath& plugin_path, +bool PluginProcessHost::Init(const WebPluginInfo& info, const std::string& activex_clsid, const std::wstring& locale) { DCHECK(channel_.get() == NULL); - plugin_path_ = plugin_path; + info_ = info; + set_name(info_.name); + channel_id_ = GenerateRandomChannelID(this); channel_.reset(new IPC::Channel(channel_id_, IPC::Channel::MODE_SERVER, @@ -480,7 +457,7 @@ bool PluginProcessHost::Init(const FilePath& plugin_path, channel_id_); cmd_line.AppendSwitchWithValue(switches::kPluginPath, - plugin_path.ToWStringHack()); + info.path.ToWStringHack()); bool in_sandbox = !browser_command_line.HasSwitch(switches::kNoSandbox) && browser_command_line.HasSwitch(switches::kSafePlugins); @@ -499,7 +476,7 @@ bool PluginProcessHost::Init(const FilePath& plugin_path, std::wstring trusted_plugins = browser_command_line.GetSwitchValue(switches::kTrustedPlugins); - if (!AddPolicyForPlugin(plugin_path, activex_clsid, trusted_plugins, + if (!AddPolicyForPlugin(info.path, activex_clsid, trusted_plugins, policy)) { NOTREACHED(); return false; @@ -520,7 +497,7 @@ bool PluginProcessHost::Init(const FilePath& plugin_path, ResumeThread(target.hThread); CloseHandle(target.hThread); - process_.set_handle(target.hProcess); + process().set_handle(target.hProcess); // Help the process a little. It can't start the debugger by itself if // the process is in a sandbox. @@ -528,23 +505,23 @@ bool PluginProcessHost::Init(const FilePath& plugin_path, DebugUtil::SpawnDebuggerOnProcess(target.dwProcessId); } else { // spawn child process - HANDLE process; - if (!base::LaunchApp(cmd_line, false, false, &process)) + HANDLE handle; + if (!base::LaunchApp(cmd_line, false, false, &handle)) return false; - process_.set_handle(process); + process().set_handle(handle); } - watcher_.StartWatching(process_.handle(), this); + watcher_.StartWatching(process().handle(), this); FilePath gears_path; if (PathService::Get(chrome::FILE_GEARS_PLUGIN, &gears_path)) { FilePath::StringType gears_path_lc = StringToLowerASCII(gears_path.value()); FilePath::StringType plugin_path_lc = - StringToLowerASCII(plugin_path.value()); + StringToLowerASCII(info.path.value()); if (plugin_path_lc == gears_path_lc) { // Give Gears plugins "background" priority. See // http://b/issue?id=1280317. - process_.SetProcessBackgrounded(true); + process().SetProcessBackgrounded(true); } } @@ -563,22 +540,21 @@ bool PluginProcessHost::Send(IPC::Message* msg) { // indicates the plugin process has exited void PluginProcessHost::OnObjectSignaled(HANDLE object) { - DCHECK(process_.handle()); - DCHECK_EQ(object, process_.handle()); + DCHECK(process().handle()); + DCHECK_EQ(object, process().handle()); bool did_crash = base::DidProcessCrash(object); if (did_crash) { // Report that this plugin crashed. plugin_service_->main_message_loop()->PostTask(FROM_HERE, - new PluginNotificationTask(NotificationType::PLUGIN_PROCESS_CRASHED, - plugin_path(), object)); + new PluginNotificationTask( + NotificationType::CHILD_PROCESS_CRASHED, this)); } // Notify in the main loop of the disconnection. plugin_service_->main_message_loop()->PostTask(FROM_HERE, new PluginNotificationTask( - NotificationType::PLUGIN_PROCESS_HOST_DISCONNECTED, - plugin_path(), object)); + NotificationType::CHILD_PROCESS_HOST_DISCONNECTED, this)); // Cancel all requests for plugin processes. // TODO(mpcomplete): use a real process ID when http://b/issue?id=1210062 is @@ -647,8 +623,7 @@ void PluginProcessHost::OnChannelConnected(int32 peer_pid) { // Notify in the main loop of the connection. plugin_service_->main_message_loop()->PostTask(FROM_HERE, new PluginNotificationTask( - NotificationType::PLUGIN_PROCESS_HOST_CONNECTED, - plugin_path(), process())); + NotificationType::CHILD_PROCESS_HOST_CONNECTED, this)); } void PluginProcessHost::OnChannelError() { @@ -669,8 +644,8 @@ void PluginProcessHost::OpenChannelToPlugin( IPC::Message* reply_msg) { // Notify in the main loop of the instantiation. plugin_service_->main_message_loop()->PostTask(FROM_HERE, - new PluginNotificationTask(NotificationType::PLUGIN_INSTANCE_CREATED, - plugin_path(), process())); + new PluginNotificationTask( + NotificationType::CHILD_INSTANCE_CREATED, this)); if (opening_channel_) { pending_requests_.push_back( @@ -704,7 +679,7 @@ void PluginProcessHost::OnRequestResource( context = Profile::GetDefaultRequestContext(); resource_dispatcher_host_->BeginRequest(this, - process_.handle(), + process().handle(), render_process_host_id, MSG_ROUTING_CONTROL, request_id, @@ -743,7 +718,7 @@ void PluginProcessHost::OnSyncLoad( context = Profile::GetDefaultRequestContext(); resource_dispatcher_host_->BeginRequest(this, - process_.handle(), + process().handle(), render_process_host_id, MSG_ROUTING_CONTROL, request_id, @@ -802,7 +777,7 @@ void PluginProcessHost::RequestPluginChannel( HANDLE renderer_handle = NULL; BOOL result = DuplicateHandle(GetCurrentProcess(), renderer_message_filter->renderer_handle(), - process(), &renderer_handle, 0, FALSE, + process().handle(), &renderer_handle, 0, FALSE, DUPLICATE_SAME_ACCESS); DCHECK(result); @@ -826,7 +801,7 @@ void PluginProcessHost::OnChannelCreated(int process_id, == process_id) { ReplyToRenderer(sent_requests_[i].renderer_message_filter_.get(), channel_name, - plugin_path(), + info_.path, sent_requests_[i].reply_msg); sent_requests_.erase(sent_requests_.begin() + i); @@ -874,7 +849,7 @@ void PluginProcessHost::OnPluginMessage( DCHECK(MessageLoop::current() == ChromeThread::GetMessageLoop(ChromeThread::IO)); - ChromePluginLib *chrome_plugin = ChromePluginLib::Find(plugin_path_); + ChromePluginLib *chrome_plugin = ChromePluginLib::Find(info_.path); if (chrome_plugin) { void *data_ptr = const_cast<void*>(reinterpret_cast<const void*>(&data[0])); uint32 data_len = static_cast<uint32>(data.size()); @@ -885,7 +860,7 @@ void PluginProcessHost::OnPluginMessage( void PluginProcessHost::OnCreateWindow(HWND parent, IPC::Message* reply_msg) { // Need to create this window on the UI thread. plugin_service_->main_message_loop()->PostTask(FROM_HERE, - new CreateWindowTask(plugin_path_, parent, reply_msg)); + new CreateWindowTask(info_.path, parent, reply_msg)); } void PluginProcessHost::OnDestroyWindow(HWND window) { @@ -897,4 +872,3 @@ void PluginProcessHost::Shutdown() { Send(new PluginProcessMsg_BrowserShutdown); } - diff --git a/chrome/browser/plugin_process_host.h b/chrome/browser/plugin_process_host.h index 45eeaab..74e86fc 100644 --- a/chrome/browser/plugin_process_host.h +++ b/chrome/browser/plugin_process_host.h @@ -10,12 +10,13 @@ #include "base/basictypes.h" #include "base/id_map.h" #include "base/object_watcher.h" -#include "base/process.h" #include "base/scoped_ptr.h" #include "base/task.h" #include "chrome/browser/net/resolve_proxy_msg_helper.h" #include "chrome/browser/renderer_host/resource_message_filter.h" +#include "chrome/common/child_process_info.h" #include "chrome/common/ipc_channel_proxy.h" +#include "webkit/glue/webplugin.h" class PluginService; class PluginProcessHost; @@ -32,7 +33,8 @@ class GURL; // starting the plugin process when a plugin is created that doesn't already // have a process. After that, most of the communication is directly between // the renderer and plugin processes. -class PluginProcessHost : public IPC::Channel::Listener, +class PluginProcessHost : public ChildProcessInfo, + public IPC::Channel::Listener, public IPC::Message::Sender, public base::ObjectWatcher::Delegate, public ResolveProxyMsgHelper::Delegate { @@ -44,7 +46,7 @@ class PluginProcessHost : public IPC::Channel::Listener, // be called before the object can be used. If plugin_path is the // ActiveX-shim, then activex_clsid is the class id of ActiveX control, // otherwise activex_clsid is ignored. - bool Init(const FilePath& plugin_path, + bool Init(const WebPluginInfo& info, const std::string& activex_clsid, const std::wstring& locale); @@ -64,9 +66,6 @@ class PluginProcessHost : public IPC::Channel::Listener, int result, const std::string& proxy_list); - // Getter to the process, may return NULL if there is no connection. - HANDLE process() { return process_.handle(); } - // Tells the plugin process to create a new channel for communication with a // renderer. When the plugin process responds with the channel name, // reply_msg is used to send the name to the renderer. @@ -74,8 +73,6 @@ class PluginProcessHost : public IPC::Channel::Listener, const std::string& mime_type, IPC::Message* reply_msg); - const FilePath& plugin_path() const { return plugin_path_; } - // Sends the reply to an open channel request to the renderer with the given // channel name. static void ReplyToRenderer(ResourceMessageFilter* renderer_message_filter, @@ -140,9 +137,6 @@ class PluginProcessHost : public IPC::Channel::Listener, // the plugin process, but haven't heard back about yet. std::vector<ChannelRequest> sent_requests_; - // The handle to our plugin process. - base::Process process_; - // Used to watch the plugin process handle. base::ObjectWatcher watcher_; @@ -156,8 +150,8 @@ class PluginProcessHost : public IPC::Channel::Listener, // IPC Channel's id. std::wstring channel_id_; - // Path to the file of that plugin. - FilePath plugin_path_; + // Information about the plugin. + WebPluginInfo info_; PluginService* plugin_service_; diff --git a/chrome/browser/plugin_process_info.h b/chrome/browser/plugin_process_info.h deleted file mode 100644 index 90fc4f0..0000000 --- a/chrome/browser/plugin_process_info.h +++ /dev/null @@ -1,63 +0,0 @@ -// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// This class contains some information about a plugin process. -// It is used as the source to notifications about plugin process connections/ -// disconnections. -// It has a copy constructor and assignment operator so that it can be copied. -// It also defines the < operator so that it can be used as a key in a std::map. - -#ifndef CHROME_BROWSER_PLUGIN_PROCESS_INFO_H__ -#define CHROME_BROWSER_PLUGIN_PROCESS_INFO_H__ - -#include <string> -#include "windows.h" - -#include "base/file_path.h" - -class PluginProcessInfo { - public: - PluginProcessInfo(FilePath plugin_path, HANDLE process) - : plugin_path_(plugin_path), - process_(process) { - } - - PluginProcessInfo(const PluginProcessInfo& ppi) { - plugin_path_ = ppi.plugin_path_; - process_ = ppi.process_; - } - - ~PluginProcessInfo() { }; - - PluginProcessInfo& - PluginProcessInfo::operator=(const PluginProcessInfo& ppi) { - if (this != &ppi) { - plugin_path_ = ppi.plugin_path_; - process_ = ppi.process_; - } - return *this; - } - - // We define the < operator so that the PluginProcessInfo can be used as a key - // in a std::map. - bool operator <(const PluginProcessInfo& rhs) const { - if (process_ != rhs.process_) - return process_ < rhs.process_; - return plugin_path_ < rhs.plugin_path_; - } - - bool operator ==(const PluginProcessInfo& rhs) const { - return (process_ == rhs.process_) && (plugin_path_ == rhs.plugin_path_); - } - - FilePath plugin_path() const { return plugin_path_; } - - HANDLE process() const { return process_; } - - private: - FilePath plugin_path_; - HANDLE process_; -}; - -#endif // #ifndef CHROME_BROWSER_PLUGIN_PROCESS_INFO_H__ diff --git a/chrome/browser/plugin_service.cc b/chrome/browser/plugin_service.cc index aeec45b..cf72d07 100644 --- a/chrome/browser/plugin_service.cc +++ b/chrome/browser/plugin_service.cc @@ -85,9 +85,15 @@ PluginProcessHost* PluginService::FindOrStartPluginProcess( if (plugin_host) return plugin_host; + WebPluginInfo info; + if (!GetPluginInfoByPath(plugin_path, &info)) { + DCHECK(false); + return NULL; + } + // This plugin isn't loaded by any plugin process, so create a new process. plugin_host = new PluginProcessHost(this); - if (!plugin_host->Init(plugin_path, clsid, ui_locale_)) { + if (!plugin_host->Init(info, clsid, ui_locale_)) { DCHECK(false); // Init is not expected to fail delete plugin_host; return NULL; diff --git a/chrome/browser/resources/about_memory.html b/chrome/browser/resources/about_memory.html index a12231e4..ddae623 100644 --- a/chrome/browser/resources/about_memory.html +++ b/chrome/browser/resources/about_memory.html @@ -613,12 +613,12 @@ function enableHelpTooltips() { <span class='th' jseval="addToSum('tot_comm_map', $this.comm_map)" jscontent="comm_map"></span><span class='k'>k</span> </td> </tr> - <tr jsselect="renderer_data"> + <tr jsselect="child_data"> <td class='pid'> <span class='th' jscontent="pid"></span> </td> <td class='name'> - <div jscontent="renderer_id"></div> + <div jscontent="child_name"></div> <div jsselect="titles"> <span jscontent="$this"></span><br> </div> diff --git a/chrome/browser/task_manager.cc b/chrome/browser/task_manager.cc index 54704a9..a64352c 100644 --- a/chrome/browser/task_manager.cc +++ b/chrome/browser/task_manager.cc @@ -74,10 +74,10 @@ TaskManagerTableModel::TaskManagerTableModel(TaskManager* task_manager) new TaskManagerWebContentsResourceProvider(task_manager); wc_provider->AddRef(); providers_.push_back(wc_provider); - TaskManagerPluginProcessResourceProvider* plugin_provider = - new TaskManagerPluginProcessResourceProvider(task_manager); - plugin_provider->AddRef(); - providers_.push_back(plugin_provider); + TaskManagerChildProcessResourceProvider* child_process_provider = + new TaskManagerChildProcessResourceProvider(task_manager); + child_process_provider->AddRef(); + providers_.push_back(child_process_provider); } TaskManagerTableModel::~TaskManagerTableModel() { diff --git a/chrome/browser/task_manager_resource_providers.cc b/chrome/browser/task_manager_resource_providers.cc index d16085e..aa23d6e 100644 --- a/chrome/browser/task_manager_resource_providers.cc +++ b/chrome/browser/task_manager_resource_providers.cc @@ -255,74 +255,64 @@ void TaskManagerWebContentsResourceProvider::Observe(NotificationType type, } //////////////////////////////////////////////////////////////////////////////// -// TaskManagerPluginProcessResource class +// TaskManagerChildProcessResource class //////////////////////////////////////////////////////////////////////////////// -SkBitmap* TaskManagerPluginProcessResource::default_icon_ = NULL; +SkBitmap* TaskManagerChildProcessResource::default_icon_ = NULL; -TaskManagerPluginProcessResource::TaskManagerPluginProcessResource( - PluginProcessInfo plugin_proc) - : plugin_process_(plugin_proc), +TaskManagerChildProcessResource::TaskManagerChildProcessResource( + ChildProcessInfo child_proc) + : child_process_(child_proc), title_(), network_usage_support_(false) { - pid_ = base::GetProcId(plugin_proc.process()); + // We cache the process id because it's not cheap to calculate, and it won't + // be available when we get the plugin disconnected notification. + pid_ = child_proc.process().pid(); if (!default_icon_) { ResourceBundle& rb = ResourceBundle::GetSharedInstance(); default_icon_ = rb.GetBitmapNamed(IDR_PLUGIN); + // TODO(jabdelmalek): use different icon for web workers. } } -TaskManagerPluginProcessResource::~TaskManagerPluginProcessResource() { +TaskManagerChildProcessResource::~TaskManagerChildProcessResource() { } // TaskManagerResource methods: -std::wstring TaskManagerPluginProcessResource::GetTitle() const { - if (title_.empty()) { - std::wstring plugin_name; - WebPluginInfo info; - if (PluginService::GetInstance()-> - GetPluginInfoByPath(plugin_process_.plugin_path(), &info)) - plugin_name = info.name; - else - plugin_name = l10n_util::GetString(IDS_TASK_MANAGER_UNKNOWN_PLUGIN_NAME); - // Explicitly mark plugin_name as LTR if there is no strong RTL character, - // to avoid the wrong concatenation result similar to "!Yahoo! Mail: the - // best web-based Email: NIGULP", in which "NIGULP" stands for the Hebrew - // or Arabic word for "plugin". - l10n_util::AdjustStringForLocaleDirection(plugin_name, &plugin_name); - title_ = l10n_util::GetStringF(IDS_TASK_MANAGER_PLUGIN_PREFIX, - plugin_name); - } +std::wstring TaskManagerChildProcessResource::GetTitle() const { + if (title_.empty()) + title_ = child_process_.GetLocalizedTitle(); + return title_; } -SkBitmap TaskManagerPluginProcessResource::GetIcon() const { +SkBitmap TaskManagerChildProcessResource::GetIcon() const { return *default_icon_; } -HANDLE TaskManagerPluginProcessResource::GetProcess() const { - return plugin_process_.process(); +HANDLE TaskManagerChildProcessResource::GetProcess() const { + return (const_cast<ChildProcessInfo&>(child_process_)).process().handle(); } //////////////////////////////////////////////////////////////////////////////// -// TaskManagerPluginProcessResourceProvider class +// TaskManagerChildProcessResourceProvider class //////////////////////////////////////////////////////////////////////////////// -TaskManagerPluginProcessResourceProvider:: - TaskManagerPluginProcessResourceProvider(TaskManager* task_manager) +TaskManagerChildProcessResourceProvider:: + TaskManagerChildProcessResourceProvider(TaskManager* task_manager) : task_manager_(task_manager), updating_(false), ui_loop_(MessageLoop::current()) { } -TaskManagerPluginProcessResourceProvider:: - ~TaskManagerPluginProcessResourceProvider() { +TaskManagerChildProcessResourceProvider:: + ~TaskManagerChildProcessResourceProvider() { } -TaskManager::Resource* TaskManagerPluginProcessResourceProvider::GetResource( +TaskManager::Resource* TaskManagerChildProcessResourceProvider::GetResource( int origin_pid, int render_process_host_id, int routing_id) { - std::map<int, TaskManagerPluginProcessResource*>::iterator iter = + std::map<int, TaskManagerChildProcessResource*>::iterator iter = pid_to_resources_.find(origin_pid); if (iter != pid_to_resources_.end()) return iter->second; @@ -330,33 +320,33 @@ TaskManager::Resource* TaskManagerPluginProcessResourceProvider::GetResource( return NULL; } -void TaskManagerPluginProcessResourceProvider::StartUpdating() { +void TaskManagerChildProcessResourceProvider::StartUpdating() { DCHECK(!updating_); updating_ = true; // Register for notifications to get new plugin processes. NotificationService* service = NotificationService::current(); - service->AddObserver(this, NotificationType::PLUGIN_PROCESS_HOST_CONNECTED, + service->AddObserver(this, NotificationType::CHILD_PROCESS_HOST_CONNECTED, NotificationService::AllSources()); - service->AddObserver(this, NotificationType::PLUGIN_PROCESS_HOST_DISCONNECTED, + service->AddObserver(this, NotificationType::CHILD_PROCESS_HOST_DISCONNECTED, NotificationService::AllSources()); // Get the existing plugins MessageLoop* io_loop_ = g_browser_process->io_thread()->message_loop(); io_loop_->PostTask(FROM_HERE, NewRunnableMethod(this, - &TaskManagerPluginProcessResourceProvider::RetrievePluginProcessInfo)); + &TaskManagerChildProcessResourceProvider::RetrieveChildProcessInfo)); } -void TaskManagerPluginProcessResourceProvider::StopUpdating() { +void TaskManagerChildProcessResourceProvider::StopUpdating() { DCHECK(updating_); updating_ = false; // Unregister for notifications to get new plugin processes. NotificationService* service = NotificationService::current(); - service->RemoveObserver(this, NotificationType::PLUGIN_PROCESS_HOST_CONNECTED, + service->RemoveObserver(this, NotificationType::CHILD_PROCESS_HOST_CONNECTED, NotificationService::AllSources()); service->RemoveObserver(this, - NotificationType::PLUGIN_PROCESS_HOST_DISCONNECTED, + NotificationType::CHILD_PROCESS_HOST_DISCONNECTED, NotificationService::AllSources()); // Delete all the resources. @@ -364,19 +354,19 @@ void TaskManagerPluginProcessResourceProvider::StopUpdating() { resources_.clear(); pid_to_resources_.clear(); - existing_plugin_process_info.clear(); + existing_child_process_info_.clear(); } -void TaskManagerPluginProcessResourceProvider::Observe( +void TaskManagerChildProcessResourceProvider::Observe( NotificationType type, const NotificationSource& source, const NotificationDetails& details) { switch (type.value) { - case NotificationType::PLUGIN_PROCESS_HOST_CONNECTED: - Add(*Details<PluginProcessInfo>(details).ptr()); + case NotificationType::CHILD_PROCESS_HOST_CONNECTED: + Add(*Details<ChildProcessInfo>(details).ptr()); break; - case NotificationType::PLUGIN_PROCESS_HOST_DISCONNECTED: - Remove(*Details<PluginProcessInfo>(details).ptr()); + case NotificationType::CHILD_PROCESS_HOST_DISCONNECTED: + Remove(*Details<ChildProcessInfo>(details).ptr()); break; default: NOTREACHED() << "Unexpected notification."; @@ -384,41 +374,41 @@ void TaskManagerPluginProcessResourceProvider::Observe( } } -void TaskManagerPluginProcessResourceProvider::Add( - PluginProcessInfo plugin_process_info) { +void TaskManagerChildProcessResourceProvider::Add( + ChildProcessInfo child_process_info) { if (!updating_) return; - std::map<PluginProcessInfo, TaskManagerPluginProcessResource*>:: - const_iterator iter = resources_.find(plugin_process_info); + std::map<ChildProcessInfo, TaskManagerChildProcessResource*>:: + const_iterator iter = resources_.find(child_process_info); if (iter != resources_.end()) { - // The case may happen that we have added a plugin_process_host as part of + // The case may happen that we have added a child_process_info as part of // the iteration performed during StartUpdating() call but the notification // that it has connected was not fired yet. So when the notification // happens, we already know about this plugin and just ignore it. return; } - AddToTaskManager(plugin_process_info); + AddToTaskManager(child_process_info); } -void TaskManagerPluginProcessResourceProvider::Remove( - PluginProcessInfo plugin_process_info) { +void TaskManagerChildProcessResourceProvider::Remove( + ChildProcessInfo child_process_info) { if (!updating_) return; - std::map<PluginProcessInfo, TaskManagerPluginProcessResource*> - ::iterator iter = resources_.find(plugin_process_info); + std::map<ChildProcessInfo, TaskManagerChildProcessResource*> + ::iterator iter = resources_.find(child_process_info); if (iter == resources_.end()) { - // PluginProcessHost disconnection notifications are asynchronous, so we + // ChildProcessInfo disconnection notifications are asynchronous, so we // might be notified for a plugin we don't know anything about (if it was // closed before the task manager was shown and destroyed after that). return; } // Remove the resource from the Task Manager. - TaskManagerPluginProcessResource* resource = iter->second; + TaskManagerChildProcessResource* resource = iter->second; task_manager_->RemoveResource(resource); // Remove it from the provider. resources_.erase(iter); // Remove it from our pid map. - std::map<int, TaskManagerPluginProcessResource*>::iterator pid_iter = + std::map<int, TaskManagerChildProcessResource*>::iterator pid_iter = pid_to_resources_.find(resource->process_id()); DCHECK(pid_iter != pid_to_resources_.end()); if (pid_iter != pid_to_resources_.end()) @@ -428,37 +418,34 @@ void TaskManagerPluginProcessResourceProvider::Remove( delete resource; } -void TaskManagerPluginProcessResourceProvider::AddToTaskManager( - PluginProcessInfo plugin_process_info) { - TaskManagerPluginProcessResource* resource = - new TaskManagerPluginProcessResource(plugin_process_info); - resources_[plugin_process_info] = resource; - pid_to_resources_[base::GetProcId(plugin_process_info.process())] = - resource; +void TaskManagerChildProcessResourceProvider::AddToTaskManager( + ChildProcessInfo child_process_info) { + TaskManagerChildProcessResource* resource = + new TaskManagerChildProcessResource(child_process_info); + resources_[child_process_info] = resource; + pid_to_resources_[resource->process_id()] = resource; task_manager_->AddResource(resource); } // The PluginProcessIterator has to be used from the IO thread. -void TaskManagerPluginProcessResourceProvider::RetrievePluginProcessInfo() { +void TaskManagerChildProcessResourceProvider::RetrieveChildProcessInfo() { for (PluginProcessHostIterator iter; !iter.Done(); ++iter) { - PluginProcessHost* plugin = const_cast<PluginProcessHost*>(*iter); - DCHECK(plugin->process()); - PluginProcessInfo plugin_info(plugin->plugin_path(), plugin->process()); - existing_plugin_process_info.push_back(plugin_info); + const ChildProcessInfo* child = *iter; + existing_child_process_info_.push_back(*child); } // Now notify the UI thread that we have retrieved the PluginProcessHosts. ui_loop_->PostTask(FROM_HERE, NewRunnableMethod(this, - &TaskManagerPluginProcessResourceProvider::PluginProcessInfoRetreived)); + &TaskManagerChildProcessResourceProvider::ChildProcessInfoRetreived)); } // This is called on the UI thread. -void TaskManagerPluginProcessResourceProvider::PluginProcessInfoRetreived() { - std::vector<PluginProcessInfo>::const_iterator iter; - for (iter = existing_plugin_process_info.begin(); - iter != existing_plugin_process_info.end(); ++iter) { +void TaskManagerChildProcessResourceProvider::ChildProcessInfoRetreived() { + std::vector<ChildProcessInfo>::const_iterator iter; + for (iter = existing_child_process_info_.begin(); + iter != existing_child_process_info_.end(); ++iter) { Add(*iter); } - existing_plugin_process_info.clear(); + existing_child_process_info_.clear(); } //////////////////////////////////////////////////////////////////////////////// diff --git a/chrome/browser/task_manager_resource_providers.h b/chrome/browser/task_manager_resource_providers.h index 2fb0820..a56aed5 100644 --- a/chrome/browser/task_manager_resource_providers.h +++ b/chrome/browser/task_manager_resource_providers.h @@ -6,11 +6,10 @@ #define CHROME_BROWSER_TASK_MANAGER_RESOURCE_PROVIDERS_H_ #include "base/basictypes.h" -#include "chrome/browser/plugin_process_info.h" #include "chrome/browser/task_manager.h" +#include "chrome/common/child_process_info.h" #include "chrome/common/notification_observer.h" -class PluginProcessHost; class WebContents; // These file contains the resource providers used in the task manager. @@ -75,10 +74,10 @@ class TaskManagerWebContentsResourceProvider DISALLOW_COPY_AND_ASSIGN(TaskManagerWebContentsResourceProvider); }; -class TaskManagerPluginProcessResource : public TaskManager::Resource { +class TaskManagerChildProcessResource : public TaskManager::Resource { public: - explicit TaskManagerPluginProcessResource(PluginProcessInfo plugin_proc); - ~TaskManagerPluginProcessResource(); + explicit TaskManagerChildProcessResource(ChildProcessInfo child_proc); + ~TaskManagerChildProcessResource(); // TaskManagerResource methods: std::wstring GetTitle() const; @@ -93,29 +92,29 @@ class TaskManagerPluginProcessResource : public TaskManager::Resource { network_usage_support_ = true; } - // Returns the pid of the plugin process. + // Returns the pid of the child process. int process_id() const { return pid_; } private: - PluginProcessInfo plugin_process_; + ChildProcessInfo child_process_; int pid_; mutable std::wstring title_; bool network_usage_support_; - // The icon painted for plugins. + // The icon painted for the child processs. // TODO (jcampan): we should have plugin specific icons for well-known // plugins. static SkBitmap* default_icon_; - DISALLOW_COPY_AND_ASSIGN(TaskManagerPluginProcessResource); + DISALLOW_COPY_AND_ASSIGN(TaskManagerChildProcessResource); }; -class TaskManagerPluginProcessResourceProvider +class TaskManagerChildProcessResourceProvider : public TaskManager::ResourceProvider, public NotificationObserver { public: - explicit TaskManagerPluginProcessResourceProvider(TaskManager* task_manager); - virtual ~TaskManagerPluginProcessResourceProvider(); + explicit TaskManagerChildProcessResourceProvider(TaskManager* task_manager); + virtual ~TaskManagerChildProcessResourceProvider(); virtual TaskManager::Resource* GetResource(int origin_pid, int render_process_host_id, @@ -128,38 +127,38 @@ class TaskManagerPluginProcessResourceProvider const NotificationSource& source, const NotificationDetails& details); - // Retrieves the current PluginProcessInfo (performed in the IO thread). - virtual void RetrievePluginProcessInfo(); + // Retrieves the current ChildProcessInfo (performed in the IO thread). + virtual void RetrieveChildProcessInfo(); - // Notifies the UI thread that the PluginProcessInfo have been retrieved. - virtual void PluginProcessInfoRetreived(); + // Notifies the UI thread that the ChildProcessInfo have been retrieved. + virtual void ChildProcessInfoRetreived(); // Whether we are currently reporting to the task manager. Used to ignore // notifications sent after StopUpdating(). bool updating_; - // The list of PluginProcessInfo retrieved when starting the update. - std::vector<PluginProcessInfo> existing_plugin_process_info; + // The list of ChildProcessInfo retrieved when starting the update. + std::vector<ChildProcessInfo> existing_child_process_info_; private: - void Add(PluginProcessInfo plugin_process_info); - void Remove(PluginProcessInfo plugin_process_info); + void Add(ChildProcessInfo child_process_info); + void Remove(ChildProcessInfo child_process_info); - void AddToTaskManager(PluginProcessInfo plugin_process_info); + void AddToTaskManager(ChildProcessInfo child_process_info); TaskManager* task_manager_; MessageLoop* ui_loop_; - // Maps the actual resources (the PluginProcessInfo) to the Task Manager + // Maps the actual resources (the ChildProcessInfo) to the Task Manager // resources. - std::map<PluginProcessInfo, TaskManagerPluginProcessResource*> resources_; + std::map<ChildProcessInfo, TaskManagerChildProcessResource*> resources_; // Maps the pids to the resources (used for quick access to the resource on // byte read notifications). - std::map<int, TaskManagerPluginProcessResource*> pid_to_resources_; + std::map<int, TaskManagerChildProcessResource*> pid_to_resources_; - DISALLOW_COPY_AND_ASSIGN(TaskManagerPluginProcessResourceProvider); + DISALLOW_COPY_AND_ASSIGN(TaskManagerChildProcessResourceProvider); }; class TaskManagerBrowserProcessResource : public TaskManager::Resource { @@ -212,7 +211,7 @@ class TaskManagerBrowserProcessResourceProvider bool updating_; private: - void AddToTaskManager(PluginProcessInfo plugin_process_info); + void AddToTaskManager(ChildProcessInfo child_process_info); TaskManager* task_manager_; TaskManagerBrowserProcessResource resource_; diff --git a/chrome/common/child_process_info.cc b/chrome/common/child_process_info.cc new file mode 100644 index 0000000..ca777bd --- /dev/null +++ b/chrome/common/child_process_info.cc @@ -0,0 +1,51 @@ +// Copyright (c) 2009 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/common/child_process_info.h" + +#include "base/logging.h" +#include "chrome/common/l10n_util.h" + +#include "generated_resources.h" + +std::wstring ChildProcessInfo::GetTypeNameInEnglish( + ChildProcessInfo::ProcessType type) { + switch (type) { + case BROWSER_PROCESS: + return L"Browser"; + case RENDER_PROCESS: + return L"Tab"; + case PLUGIN_PROCESS: + return L"Plug-in"; + case WORKER_PROCESS: + return L"Web Worker"; + case UNKNOWN_PROCESS: + default: + DCHECK(false) << "Unknown child process type!"; + return L"Unknown"; + } +} + +std::wstring ChildProcessInfo::GetLocalizedTitle() const { + std::wstring title = name_; + if (type_ == ChildProcessInfo::PLUGIN_PROCESS && title.empty()) + title = l10n_util::GetString(IDS_TASK_MANAGER_UNKNOWN_PLUGIN_NAME); + + int message_id; + if (type_ == ChildProcessInfo::PLUGIN_PROCESS) { + message_id = IDS_TASK_MANAGER_PLUGIN_PREFIX; + } else if (type_ == ChildProcessInfo::WORKER_PROCESS) { + message_id = IDS_TASK_MANAGER_WORKER_PREFIX; + } else { + DCHECK(false) << "Need localized name for child process type."; + return title; + } + + // Explicitly mark name as LTR if there is no strong RTL character, + // to avoid the wrong concatenation result similar to "!Yahoo! Mail: the + // best web-based Email: NIGULP", in which "NIGULP" stands for the Hebrew + // or Arabic word for "plugin". + l10n_util::AdjustStringForLocaleDirection(title, &title); + return l10n_util::GetStringF(message_id, title); +} diff --git a/chrome/common/child_process_info.h b/chrome/common/child_process_info.h new file mode 100644 index 0000000..2007bcb --- /dev/null +++ b/chrome/common/child_process_info.h @@ -0,0 +1,66 @@ +// Copyright (c) 2009 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_COMMON_CHILD_PROCESS_INFO_H_ +#define CHROME_COMMON_CHILD_PROCESS_INFO_H_ + +#include <string> +#include "base/basictypes.h" +#include "base/process.h" + +// Holds information about a child process. +class ChildProcessInfo { + public: + enum ProcessType { + BROWSER_PROCESS, + RENDER_PROCESS, + PLUGIN_PROCESS, + WORKER_PROCESS, + UNKNOWN_PROCESS, + }; + + // Returns the type of the process. + ProcessType type() const { return 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_; } + + // Getter to the process. + base::Process& process() { return process_; } + + // 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::wstring GetTypeNameInEnglish(ProcessType type); + + // Returns a localized title for the child process. For example, a plugin + // process would be "Plug-in: Flash" when name is "Flash". + std::wstring GetLocalizedTitle() const; + + // We define the < operator so that the ChildProcessInfo can be used as a key + // in a std::map. + bool operator <(const ChildProcessInfo& rhs) const { + if (process_.handle() != rhs.process_.handle()) + return process_ .handle() < rhs.process_.handle(); + return name_ < rhs.name_; + } + + bool operator ==(const ChildProcessInfo& rhs) const { + return (process_.handle() == rhs.process_.handle()) && (name_ == rhs.name_); + } + + protected: + void set_type(ProcessType type) { type_ = type; } + void set_name(const std::wstring& name) { name_ = name; } + + private: + ProcessType type_; + std::wstring name_; + + // The handle to the process. + base::Process process_; +}; + +#endif // CHROME_COMMON_CHILD_PROCESS_INFO_H_ + diff --git a/chrome/common/common.scons b/chrome/common/common.scons index 829da06..832485f 100644 --- a/chrome/common/common.scons +++ b/chrome/common/common.scons @@ -106,6 +106,8 @@ input_files = ChromeFileList([ 'animation.h', 'child_process.cc', 'child_process.h', + 'child_process_info.cc', + 'child_process_info.h', 'chrome_constants.cc', 'chrome_constants.h', 'chrome_counters.cc', diff --git a/chrome/common/common.vcproj b/chrome/common/common.vcproj index 44c9962..00282224 100644 --- a/chrome/common/common.vcproj +++ b/chrome/common/common.vcproj @@ -342,6 +342,14 @@ > </File> <File + RelativePath=".\child_process_info.cc" + > + </File> + <File + RelativePath=".\child_process_info.h" + > + </File> + <File RelativePath=".\chrome_constants.cc" > </File> @@ -525,7 +533,7 @@ RelativePath=".\notification_details.h" > </File> - <File + <File RelativePath=".\notification_observer.h" > </File> diff --git a/chrome/common/notification_type.h b/chrome/common/notification_type.h index 7924866..5e59742 100644 --- a/chrome/common/notification_type.h +++ b/chrome/common/notification_type.h @@ -319,47 +319,35 @@ class NotificationType { // guaranteed to be valid after the notification. WEB_CACHE_STATS_OBSERVED, - // Plugins ----------------------------------------------------------------- + // Child Processes --------------------------------------------------------- - // This notification is sent when a plugin process host has connected to a - // plugin process. There is no usable source, since it is sent from an + // This notification is sent when a child process host has connected to a + // child process. There is no usable source, since it is sent from an // ephemeral task; register for AllSources() to receive this notification. - // The details are in a Details<PluginProcessInfo> with a pointer to a - // plug-in process info for the plugin, that is only valid for the time of - // the notification (don't keep this pointer around, make a copy of the - // object if you need to keep it). - PLUGIN_PROCESS_HOST_CONNECTED, - - // This message is sent after a PluginProcessHost is disconnected from the - // plugin process. There is no usable source, since it is sent from an + // The details are in a Details<ChildProcessInfo>. + CHILD_PROCESS_HOST_CONNECTED, + + // This message is sent after a ChildProcessHost is disconnected from the + // child process. There is no usable source, since it is sent from an // ephemeral task; register for AllSources() to receive this notification. - // The details are in a Details<PluginProcessInfo> with a pointer to a - // plug-in process info for the plugin, that is only valid for the time of - // the notification (don't keep this pointer around, make a copy of the - // object if you need to keep it). - PLUGIN_PROCESS_HOST_DISCONNECTED, + // The details are in a Details<ChildProcessInfo>. + CHILD_PROCESS_HOST_DISCONNECTED, - // This message is sent when a plugin process disappears unexpectedly. + // This message is sent when a child process disappears unexpectedly. // There is no usable source, since it is sent from an ephemeral task; // register for AllSources() to receive this notification. The details are - // in a Details<PluginProcessInfo> with a pointer to a plug-in process info - // for the plugin, that is only valid for the time of the notification - // (don't keep this pointer around, make a copy of the object if you need - // to keep it). - PLUGIN_PROCESS_CRASHED, + // in a Details<ChildProcessInfo>. + CHILD_PROCESS_CRASHED, - // This message indicates that an instance of a particular plugin was + // This message indicates that an instance of a particular child was // created in a page. (If one page contains several regions rendered by - // the same plugin, this notification will occur once for each region + // the same child, this notification will occur once for each region // during the page load.) // // There is no usable source, since it is sent from an ephemeral task; // register for AllSources() to receive this notification. The details are - // in a Details<PluginProcessInfo> with a pointer to a plug-in process info - // for the plugin, that is only valid for the time of the notification - // (don't keep this pointer around, make a copy of the object if you need - // to keep it). - PLUGIN_INSTANCE_CREATED, + // in a Details<ChildProcessInfo>. + CHILD_INSTANCE_CREATED, // This is sent when network interception is disabled for a plugin, or the // plugin is unloaded. This should only be sent/received on the browser IO diff --git a/chrome/common/pref_names.cc b/chrome/common/pref_names.cc index f00406d..8c8dc76 100644 --- a/chrome/common/pref_names.cc +++ b/chrome/common/pref_names.cc @@ -328,7 +328,7 @@ const wchar_t kStabilityUptimeSec[] = // This is the location of a list of dictionaries of plugin stability stats. const wchar_t kStabilityPluginStats[] = - L"user_experience_metrics.stability.plugin_stats"; + L"user_experience_metrics.stability.plugin_stats2"; // Number of times the renderer has become non-responsive since the last // report. @@ -353,7 +353,7 @@ const wchar_t kStabilityDebuggerNotPresent[] = // The keys below are used for the dictionaries in the // kStabilityPluginStats list. -const wchar_t kStabilityPluginPath[] = L"path"; +const wchar_t kStabilityPluginName[] = L"name"; const wchar_t kStabilityPluginLaunches[] = L"launches"; const wchar_t kStabilityPluginInstances[] = L"instances"; const wchar_t kStabilityPluginCrashes[] = L"crashes"; diff --git a/chrome/common/pref_names.h b/chrome/common/pref_names.h index 6e09d74..501b3e0 100644 --- a/chrome/common/pref_names.h +++ b/chrome/common/pref_names.h @@ -116,7 +116,7 @@ extern const wchar_t kSecurityRendererOnSboxDesktop[]; extern const wchar_t kSecurityRendererOnDefaultDesktop[]; extern const wchar_t kStabilityPluginStats[]; -extern const wchar_t kStabilityPluginPath[]; +extern const wchar_t kStabilityPluginName[]; extern const wchar_t kStabilityPluginLaunches[]; extern const wchar_t kStabilityPluginInstances[]; extern const wchar_t kStabilityPluginCrashes[]; |