diff options
author | initial.commit <initial.commit@0039d316-1c4b-4281-b951-d872f2087c98> | 2008-07-26 23:55:29 +0000 |
---|---|---|
committer | initial.commit <initial.commit@0039d316-1c4b-4281-b951-d872f2087c98> | 2008-07-26 23:55:29 +0000 |
commit | 09911bf300f1a419907a9412154760efd0b7abc3 (patch) | |
tree | f131325fb4e2ad12c6d3504ab75b16dd92facfed /chrome/browser/task_manager_resource_providers.cc | |
parent | 586acc5fe142f498261f52c66862fa417c3d52d2 (diff) | |
download | chromium_src-09911bf300f1a419907a9412154760efd0b7abc3.zip chromium_src-09911bf300f1a419907a9412154760efd0b7abc3.tar.gz chromium_src-09911bf300f1a419907a9412154760efd0b7abc3.tar.bz2 |
Add chrome to the repository.
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@15 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser/task_manager_resource_providers.cc')
-rw-r--r-- | chrome/browser/task_manager_resource_providers.cc | 531 |
1 files changed, 531 insertions, 0 deletions
diff --git a/chrome/browser/task_manager_resource_providers.cc b/chrome/browser/task_manager_resource_providers.cc new file mode 100644 index 0000000..fa750c8 --- /dev/null +++ b/chrome/browser/task_manager_resource_providers.cc @@ -0,0 +1,531 @@ +// Copyright 2008, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#include "chrome/browser/task_manager_resource_providers.h" + +#include "base/file_version_info.h" +#include "base/message_loop.h" +#include "base/process_util.h" +#include "base/string_util.h" +#include "chrome/app/chrome_dll_resource.h" +#include "chrome/app/theme/theme_resources.h" +#include "chrome/browser/browser_process.h" +#include "chrome/browser/browser_list.h" +#include "chrome/browser/plugin_process_host.h" +#include "chrome/browser/plugin_service.h" +#include "chrome/browser/render_process_host.h" +#include "chrome/browser/resource_message_filter.h" +#include "chrome/browser/tab_util.h" +#include "chrome/browser/web_contents.h" +#include "chrome/common/resource_bundle.h" +#include "chrome/common/stl_util-inl.h" +#include "chrome/common/gfx/icon_util.h" + +#include "generated_resources.h" + +//////////////////////////////////////////////////////////////////////////////// +// TaskManagerWebContentsResource class +//////////////////////////////////////////////////////////////////////////////// + +TaskManagerWebContentsResource::TaskManagerWebContentsResource( + WebContents* web_contents) + : web_contents_(web_contents) { + // We cache the process as when the WebContents is closed the process + // becomes NULL and the TaskManager still needs it. + process_ = web_contents_->process()->process(); + pid_ = process_util::GetProcId(process_); +} + +TaskManagerWebContentsResource::~TaskManagerWebContentsResource() { +} + +std::wstring TaskManagerWebContentsResource::GetTitle() const { + // GetTitle() and GetURL() can only be invoked when the WebContents has a + // controller. + if (!web_contents_->controller()) + return std::wstring(); + + // Fall back on the URL if there's no title. + std::wstring tab_title(web_contents_->GetTitle()); + if (tab_title.empty()) + tab_title = UTF8ToWide(web_contents_->GetURL().spec()); + + return l10n_util::GetStringF(IDS_TASK_MANAGER_TAB_PREFIX, tab_title); +} + +SkBitmap TaskManagerWebContentsResource::GetIcon() const { + return web_contents_->GetFavIcon(); +} + +HANDLE TaskManagerWebContentsResource::GetProcess() const { + return process_; +} + +//////////////////////////////////////////////////////////////////////////////// +// TaskManagerWebContentsResourceProvider class +//////////////////////////////////////////////////////////////////////////////// + +TaskManagerWebContentsResourceProvider:: + TaskManagerWebContentsResourceProvider(TaskManager* task_manager) + : task_manager_(task_manager), + updating_(false) { +} + +TaskManagerWebContentsResourceProvider:: + ~TaskManagerWebContentsResourceProvider() { +} + +TaskManager::Resource* TaskManagerWebContentsResourceProvider::GetResource( + int origin_pid, + int render_process_host_id, + int routing_id) { + + TabContents* tab_contents = + tab_util::GetTabContentsByID(render_process_host_id, routing_id); + if (!tab_contents) // Not one of our resource. + return NULL; + WebContents* web_contents = tab_contents->AsWebContents(); + if (!web_contents) + return NULL; + + if (!web_contents->process()->process()) { + // We should not be holding on to a dead tab (it should have been removed + // through the NOTIFY_WEB_CONTENTS_DISCONNECTED notification. + NOTREACHED(); + return NULL; + } + + int pid = process_util::GetProcId(web_contents->process()->process()); + if (pid != origin_pid) + return NULL; + + std::map<WebContents*, TaskManagerWebContentsResource*>::iterator + res_iter = resources_.find(web_contents); + if (res_iter == resources_.end()) + // Can happen if the tab was closed while a network request was being + // performed. + return NULL; + + return res_iter->second; +} + +void TaskManagerWebContentsResourceProvider::StartUpdating() { + DCHECK(!updating_); + updating_ = true; + // Add all the existing WebContents. + for (WebContentsIterator iterator; !iterator.done(); iterator++) { + WebContents* web_contents = *iterator; + // Don't add dead tabs or tabs that haven't yet connected. + if (web_contents->process()->process() && + web_contents->notify_disconnection()) + AddToTaskManager(web_contents); + } + // Then we register for notifications to get new tabs. + NotificationService* service = NotificationService::current(); + service->AddObserver(this, NOTIFY_WEB_CONTENTS_CONNECTED, + NotificationService::AllSources()); + service->AddObserver(this, NOTIFY_WEB_CONTENTS_SWAPPED, + NotificationService::AllSources()); + service->AddObserver(this, NOTIFY_WEB_CONTENTS_DISCONNECTED, + NotificationService::AllSources()); +} + +void TaskManagerWebContentsResourceProvider::StopUpdating() { + DCHECK(updating_); + updating_ = false; + + // Then we unregister for notifications to get new tabs. + NotificationService* service = NotificationService::current(); + service->RemoveObserver(this, NOTIFY_WEB_CONTENTS_CONNECTED, + NotificationService::AllSources()); + service->RemoveObserver(this, NOTIFY_WEB_CONTENTS_SWAPPED, + NotificationService::AllSources()); + service->RemoveObserver(this, NOTIFY_WEB_CONTENTS_DISCONNECTED, + NotificationService::AllSources()); + + // Delete all the resources. + STLDeleteContainerPairSecondPointers(resources_.begin(), resources_.end()); + + resources_.clear(); +} + +void TaskManagerWebContentsResourceProvider::AddToTaskManager( + WebContents* web_contents) { + TaskManagerWebContentsResource* resource = + new TaskManagerWebContentsResource(web_contents); + resources_[web_contents] = resource; + task_manager_->AddResource(resource); +} + +void TaskManagerWebContentsResourceProvider::Add(WebContents* web_contents) { + if (!updating_) + return; + + if (!web_contents->process()->process()) { + // Don't add sad tabs, we would have no information to show for them since + // they have no associated process. + return; + } + + std::map<WebContents*, TaskManagerWebContentsResource*>::const_iterator + iter = resources_.find(web_contents); + if (iter != resources_.end()) { + // The case may happen that we have added a WebContents 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 tab and just ignore it. + return; + } + AddToTaskManager(web_contents); +} + +void TaskManagerWebContentsResourceProvider::Remove(WebContents* web_contents) { + if (!updating_) + return; + std::map<WebContents*, TaskManagerWebContentsResource*>::iterator + iter = resources_.find(web_contents); + if (iter == resources_.end()) { + // Since TabContents are destroyed asynchronously (see TabContentsCollector + // in navigation_controller.cc), we can be notified of a tab being removed + // that we don't know. This can happen if the user closes a tab and quickly + // opens the task manager, before the tab is actually destroyed. + return; + } + + // Remove the resource from the Task Manager. + TaskManagerWebContentsResource* resource = iter->second; + task_manager_->RemoveResource(resource); + // And from the provider. + resources_.erase(iter); + // Finally, delete the resource. + delete resource; +} + +void TaskManagerWebContentsResourceProvider::Observe(NotificationType type, + const NotificationSource& source, + const NotificationDetails& details) { + switch (type) { + case NOTIFY_WEB_CONTENTS_CONNECTED: + Add(Source<WebContents>(source).ptr()); + break; + case NOTIFY_WEB_CONTENTS_SWAPPED: + Remove(Source<WebContents>(source).ptr()); + Add(Source<WebContents>(source).ptr()); + break; + case NOTIFY_WEB_CONTENTS_DISCONNECTED: + Remove(Source<WebContents>(source).ptr()); + break; + default: + NOTREACHED() << "Unexpected notification."; + return; + } +} + +//////////////////////////////////////////////////////////////////////////////// +// TaskManagerPluginProcessResource class +//////////////////////////////////////////////////////////////////////////////// +SkBitmap* TaskManagerPluginProcessResource::default_icon_ = NULL; + +TaskManagerPluginProcessResource::TaskManagerPluginProcessResource( + PluginProcessInfo plugin_proc) + : plugin_process_(plugin_proc), + title_(), + network_usage_support_(false) { + pid_ = process_util::GetProcId(plugin_proc.process()); + if (!default_icon_) { + ResourceBundle& rb = ResourceBundle::GetSharedInstance(); + default_icon_ = rb.GetBitmapNamed(IDR_PLUGIN); + } +} + +TaskManagerPluginProcessResource::~TaskManagerPluginProcessResource() { +} + +// TaskManagerResource methods: +std::wstring TaskManagerPluginProcessResource::GetTitle() const { + if (title_.empty()) { + std::wstring plugin_name; + WebPluginInfo info; + if (PluginService::GetInstance()-> + GetPluginInfoByDllPath(plugin_process_.dll_path(), &info)) + plugin_name = info.name; + else + plugin_name = l10n_util::GetString(IDS_TASK_MANAGER_UNKNOWN_PLUGIN_NAME); + title_ = l10n_util::GetStringF(IDS_TASK_MANAGER_PLUGIN_PREFIX, + plugin_name); + } + return title_; +} + +SkBitmap TaskManagerPluginProcessResource::GetIcon() const { + return *default_icon_; +} + +HANDLE TaskManagerPluginProcessResource::GetProcess() const { + return plugin_process_.process(); +} + +//////////////////////////////////////////////////////////////////////////////// +// TaskManagerPluginProcessResourceProvider class +//////////////////////////////////////////////////////////////////////////////// + +TaskManagerPluginProcessResourceProvider:: + TaskManagerPluginProcessResourceProvider(TaskManager* task_manager) + : task_manager_(task_manager), + updating_(false), + ui_loop_(MessageLoop::current()) { +} + +TaskManagerPluginProcessResourceProvider:: + ~TaskManagerPluginProcessResourceProvider() { +} + +TaskManager::Resource* TaskManagerPluginProcessResourceProvider::GetResource( + int origin_pid, + int render_process_host_id, + int routing_id) { + std::map<int, TaskManagerPluginProcessResource*>::iterator iter = + pid_to_resources_.find(origin_pid); + if (iter != pid_to_resources_.end()) + return iter->second; + else + return NULL; +} + +void TaskManagerPluginProcessResourceProvider::StartUpdating() { + DCHECK(!updating_); + updating_ = true; + + // Register for notifications to get new plugin processes. + NotificationService* service = NotificationService::current(); + service->AddObserver(this, NOTIFY_PLUGIN_PROCESS_HOST_CONNECTED, + NotificationService::AllSources()); + service->AddObserver(this, NOTIFY_PLUGIN_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)); +} + +void TaskManagerPluginProcessResourceProvider::StopUpdating() { + DCHECK(updating_); + updating_ = false; + + // Unregister for notifications to get new plugin processes. + NotificationService* service = NotificationService::current(); + service->RemoveObserver(this, NOTIFY_PLUGIN_PROCESS_HOST_CONNECTED, + NotificationService::AllSources()); + service->RemoveObserver(this, NOTIFY_PLUGIN_PROCESS_HOST_DISCONNECTED, + NotificationService::AllSources()); + + // Delete all the resources. + STLDeleteContainerPairSecondPointers(resources_.begin(), resources_.end()); + + resources_.clear(); + pid_to_resources_.clear(); + existing_plugin_process_info.clear(); +} + +void TaskManagerPluginProcessResourceProvider::Observe( + NotificationType type, + const NotificationSource& source, + const NotificationDetails& details) { + switch (type) { + case NOTIFY_PLUGIN_PROCESS_HOST_CONNECTED: + Add(*Details<PluginProcessInfo>(details).ptr()); + break; + case NOTIFY_PLUGIN_PROCESS_HOST_DISCONNECTED: + Remove(*Details<PluginProcessInfo>(details).ptr()); + break; + default: + NOTREACHED() << "Unexpected notification."; + return; + } +} + +void TaskManagerPluginProcessResourceProvider::Add( + PluginProcessInfo plugin_process_info) { + if (!updating_) + return; + std::map<PluginProcessInfo, TaskManagerPluginProcessResource*>:: + const_iterator iter = resources_.find(plugin_process_info); + if (iter != resources_.end()) { + // The case may happen that we have added a plugin_process_host 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); +} + +void TaskManagerPluginProcessResourceProvider::Remove( + PluginProcessInfo plugin_process_info) { + if (!updating_) + return; + std::map<PluginProcessInfo, TaskManagerPluginProcessResource*> + ::iterator iter = resources_.find(plugin_process_info); + if (iter == resources_.end()) { + // PluginProcessHost 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; + 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 = + pid_to_resources_.find(resource->process_id()); + DCHECK(pid_iter != pid_to_resources_.end()); + if (pid_iter != pid_to_resources_.end()) + pid_to_resources_.erase(pid_iter); + + // Finally, delete the resource. + delete resource; +} + +void TaskManagerPluginProcessResourceProvider::AddToTaskManager( + PluginProcessInfo plugin_process_info) { + TaskManagerPluginProcessResource* resource = + new TaskManagerPluginProcessResource(plugin_process_info); + resources_[plugin_process_info] = resource; + pid_to_resources_[process_util::GetProcId(plugin_process_info.process())] = + resource; + task_manager_->AddResource(resource); +} + +// The PluginProcessIterator has to be used from the IO thread. +void TaskManagerPluginProcessResourceProvider::RetrievePluginProcessInfo() { + for (PluginProcessHostIterator iter; !iter.Done(); ++iter) { + PluginProcessHost* plugin = const_cast<PluginProcessHost*>(*iter); + DCHECK(plugin->process()); + PluginProcessInfo plugin_info(plugin->dll_path(), plugin->process()); + existing_plugin_process_info.push_back(plugin_info); + } + // Now notify the UI thread that we have retrieved the PluginProcessHosts. + ui_loop_->PostTask(FROM_HERE, NewRunnableMethod(this, + &TaskManagerPluginProcessResourceProvider::PluginProcessInfoRetreived)); +} + +// 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) { + Add(*iter); + } + existing_plugin_process_info.clear(); +} + +//////////////////////////////////////////////////////////////////////////////// +// TaskManagerBrowserProcessResource class +//////////////////////////////////////////////////////////////////////////////// + +SkBitmap* TaskManagerBrowserProcessResource::default_icon_ = NULL; + +TaskManagerBrowserProcessResource::TaskManagerBrowserProcessResource() +: title_(), + network_usage_support_(false) { + pid_ = GetCurrentProcessId(); + process_ = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, + FALSE, + pid_); + DCHECK(process_); + if (!default_icon_) { + HICON icon = LoadIcon(_AtlBaseModule.GetResourceInstance(), + MAKEINTRESOURCE(IDR_MAINFRAME)); + if (icon) { + ICONINFO icon_info = {0}; + BITMAP bitmap_info = {0}; + + GetIconInfo(icon, &icon_info); + GetObject(icon_info.hbmMask, sizeof(bitmap_info), &bitmap_info); + + gfx::Size icon_size(bitmap_info.bmWidth, bitmap_info.bmHeight); + default_icon_ = IconUtil::CreateSkBitmapFromHICON(icon, icon_size); + } + } +} + +TaskManagerBrowserProcessResource::~TaskManagerBrowserProcessResource() { + CloseHandle(process_); +} + +// TaskManagerResource methods: +std::wstring TaskManagerBrowserProcessResource::GetTitle() const { + if (title_.empty()) { + title_ = l10n_util::GetString(IDS_TASK_MANAGER_WEB_BROWSER_CELL_TEXT); + } + return title_; +} + +SkBitmap TaskManagerBrowserProcessResource::GetIcon() const { + return *default_icon_; +} + +HANDLE TaskManagerBrowserProcessResource::GetProcess() const { + return GetCurrentProcess(); // process_; +} + +//////////////////////////////////////////////////////////////////////////////// +// TaskManagerBrowserProcessResourceProvider class +//////////////////////////////////////////////////////////////////////////////// + +TaskManagerBrowserProcessResourceProvider:: + TaskManagerBrowserProcessResourceProvider(TaskManager* task_manager) + : task_manager_(task_manager) { +} + +TaskManagerBrowserProcessResourceProvider:: + ~TaskManagerBrowserProcessResourceProvider() { +} + +TaskManager::Resource* TaskManagerBrowserProcessResourceProvider::GetResource( + int origin_pid, + int render_process_host_id, + int routing_id) { + if (origin_pid != resource_.process_id()) { + return NULL; + } + + return &resource_; +} + +void TaskManagerBrowserProcessResourceProvider::StartUpdating() { + task_manager_->AddResource(&resource_); +} + +void TaskManagerBrowserProcessResourceProvider::StopUpdating() { +} + |