summaryrefslogtreecommitdiffstats
path: root/chrome/browser/task_manager
diff options
context:
space:
mode:
authoryurys@chromium.org <yurys@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-11-02 10:21:59 +0000
committeryurys@chromium.org <yurys@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-11-02 10:21:59 +0000
commit7257c89a32ff192fd40541e0e86d8945346c808e (patch)
tree23ddfdec0340f2b54005de12660597f88c388511 /chrome/browser/task_manager
parent56196a8880f839403d40153f8ae919ea9e6362be (diff)
downloadchromium_src-7257c89a32ff192fd40541e0e86d8945346c808e.zip
chromium_src-7257c89a32ff192fd40541e0e86d8945346c808e.tar.gz
chromium_src-7257c89a32ff192fd40541e0e86d8945346c808e.tar.bz2
Provide detailed shared workers info in Task Manager. This patch introduces TaskManagerWorkerResourceProvider which supplies TaskManager with information about shared workers.
BUG=None TEST=None Review URL: http://codereview.chromium.org/8428014 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@108266 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser/task_manager')
-rw-r--r--chrome/browser/task_manager/task_manager.cc3
-rw-r--r--chrome/browser/task_manager/task_manager_resource_providers.cc18
-rw-r--r--chrome/browser/task_manager/task_manager_worker_resource_provider.cc330
-rw-r--r--chrome/browser/task_manager/task_manager_worker_resource_provider.h79
4 files changed, 421 insertions, 9 deletions
diff --git a/chrome/browser/task_manager/task_manager.cc b/chrome/browser/task_manager/task_manager.cc
index fe26022..a586892 100644
--- a/chrome/browser/task_manager/task_manager.cc
+++ b/chrome/browser/task_manager/task_manager.cc
@@ -20,6 +20,7 @@
#include "chrome/browser/prefs/pref_service.h"
#include "chrome/browser/profiles/profile_manager.h"
#include "chrome/browser/task_manager/task_manager_resource_providers.h"
+#include "chrome/browser/task_manager/task_manager_worker_resource_provider.h"
#include "chrome/browser/ui/browser_list.h"
#include "chrome/browser/ui/browser_window.h"
#include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h"
@@ -94,6 +95,8 @@ TaskManagerModel::TaskManagerModel(TaskManager* task_manager)
TaskManagerNotificationResourceProvider::Create(task_manager);
if (provider)
AddResourceProvider(provider);
+
+ AddResourceProvider(new TaskManagerWorkerResourceProvider(task_manager));
}
TaskManagerModel::~TaskManagerModel() {
diff --git a/chrome/browser/task_manager/task_manager_resource_providers.cc b/chrome/browser/task_manager/task_manager_resource_providers.cc
index 136115b..c21195b 100644
--- a/chrome/browser/task_manager/task_manager_resource_providers.cc
+++ b/chrome/browser/task_manager/task_manager_resource_providers.cc
@@ -789,16 +789,10 @@ TaskManager::Resource::Type TaskManagerChildProcessResource::GetType() const {
// Translate types to TaskManager::ResourceType, since ChildProcessInfo's type
// is not available for all TaskManager resources.
switch (child_process_.type()) {
- case ChildProcessInfo::BROWSER_PROCESS:
- return TaskManager::Resource::BROWSER;
- case ChildProcessInfo::RENDER_PROCESS:
- return TaskManager::Resource::RENDERER;
case ChildProcessInfo::PLUGIN_PROCESS:
case ChildProcessInfo::PPAPI_PLUGIN_PROCESS:
case ChildProcessInfo::PPAPI_BROKER_PROCESS:
return TaskManager::Resource::PLUGIN;
- case ChildProcessInfo::WORKER_PROCESS:
- return TaskManager::Resource::WORKER;
case ChildProcessInfo::NACL_LOADER_PROCESS:
case ChildProcessInfo::NACL_BROKER_PROCESS:
return TaskManager::Resource::NACL;
@@ -871,9 +865,6 @@ string16 TaskManagerChildProcessResource::GetLocalizedTitle() const {
case ChildProcessInfo::NACL_LOADER_PROCESS:
return l10n_util::GetStringFUTF16(IDS_TASK_MANAGER_NACL_PREFIX, title);
- case ChildProcessInfo::WORKER_PROCESS:
- return l10n_util::GetStringFUTF16(IDS_TASK_MANAGER_WORKER_PREFIX, title);
-
// These types don't need display names or get them from elsewhere.
case ChildProcessInfo::BROWSER_PROCESS:
case ChildProcessInfo::RENDER_PROCESS:
@@ -883,6 +874,10 @@ string16 TaskManagerChildProcessResource::GetLocalizedTitle() const {
NOTREACHED();
break;
+ case ChildProcessInfo::WORKER_PROCESS:
+ NOTREACHED() << "Workers are not handled by this provider.";
+ break;
+
case ChildProcessInfo::UNKNOWN_PROCESS:
NOTREACHED() << "Need localized name for child process type.";
}
@@ -976,6 +971,9 @@ void TaskManagerChildProcessResourceProvider::Add(
const ChildProcessInfo& child_process_info) {
if (!updating_)
return;
+ // Workers are handled by TaskManagerWorkerResourceProvider.
+ if (child_process_info.type() == ChildProcessInfo::WORKER_PROCESS)
+ return;
std::map<ChildProcessInfo, TaskManagerChildProcessResource*>::
const_iterator iter = resources_.find(child_process_info);
if (iter != resources_.end()) {
@@ -992,6 +990,8 @@ void TaskManagerChildProcessResourceProvider::Remove(
const ChildProcessInfo& child_process_info) {
if (!updating_)
return;
+ if (child_process_info.type() == ChildProcessInfo::WORKER_PROCESS)
+ return;
std::map<ChildProcessInfo, TaskManagerChildProcessResource*>
::iterator iter = resources_.find(child_process_info);
if (iter == resources_.end()) {
diff --git a/chrome/browser/task_manager/task_manager_worker_resource_provider.cc b/chrome/browser/task_manager/task_manager_worker_resource_provider.cc
new file mode 100644
index 0000000..bf29177
--- /dev/null
+++ b/chrome/browser/task_manager/task_manager_worker_resource_provider.cc
@@ -0,0 +1,330 @@
+// Copyright (c) 2011 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/browser/task_manager/task_manager_worker_resource_provider.h"
+
+#include "base/bind.h"
+#include "base/bind_helpers.h"
+#include "base/stl_util.h"
+#include "base/utf_string_conversions.h"
+#include "chrome/browser/browser_process.h"
+#include "chrome/browser/debugger/devtools_window.h"
+#include "content/browser/browser_child_process_host.h"
+#include "content/browser/worker_host/worker_process_host.h"
+#include "content/browser/worker_host/worker_service.h"
+#include "content/browser/worker_host/worker_service_observer.h"
+#include "content/public/browser/browser_thread.h"
+#include "content/public/browser/notification_service.h"
+#include "content/public/browser/notification_types.h"
+#include "grit/generated_resources.h"
+#include "grit/theme_resources_standard.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/resource/resource_bundle.h"
+
+// Objects of this class are created on the IO thread and then passed to the UI
+// thread where they are passed to the task manager. All methods must be called
+// only on the UI thread. Destructor may be called on any thread.
+class TaskManagerSharedWorkerResource : public TaskManager::Resource {
+ public:
+ TaskManagerSharedWorkerResource(const ChildProcessInfo& process_info,
+ int routing_id, const GURL& url,
+ const string16& name);
+ virtual ~TaskManagerSharedWorkerResource();
+
+ bool Matches(int process_id, int routing_id) const;
+
+ void UpdateProcessInfo(const ChildProcessInfo& process_info);
+ const ChildProcessInfo& process_info() { return process_info_; }
+
+ private:
+ // TaskManager::Resource methods:
+ virtual string16 GetTitle() const OVERRIDE;
+ virtual string16 GetProfileName() const OVERRIDE;
+ virtual SkBitmap GetIcon() const OVERRIDE;
+ virtual base::ProcessHandle GetProcess() const OVERRIDE;
+ virtual Type GetType() const OVERRIDE;
+
+ virtual bool SupportNetworkUsage() const OVERRIDE;
+ virtual void SetSupportNetworkUsage() OVERRIDE;
+
+ ChildProcessInfo process_info_;
+ int routing_id_;
+ string16 title_;
+
+ static SkBitmap* default_icon_;
+
+ DISALLOW_COPY_AND_ASSIGN(TaskManagerSharedWorkerResource);
+};
+
+SkBitmap* TaskManagerSharedWorkerResource::default_icon_ = NULL;
+
+TaskManagerSharedWorkerResource::TaskManagerSharedWorkerResource(
+ const ChildProcessInfo& process_info,
+ int routing_id,
+ const GURL& url,
+ const string16& name)
+ : process_info_(process_info),
+ routing_id_(routing_id) {
+ title_ = UTF8ToUTF16(url.spec());
+ if (!name.empty())
+ title_ += ASCIIToUTF16(" (") + name + ASCIIToUTF16(")");
+}
+
+TaskManagerSharedWorkerResource::~TaskManagerSharedWorkerResource() {
+}
+
+bool TaskManagerSharedWorkerResource::Matches(int process_id,
+ int routing_id) const {
+ return process_info_.id() == process_id && routing_id_ == routing_id;
+}
+
+void TaskManagerSharedWorkerResource::UpdateProcessInfo(
+ const ChildProcessInfo& process_info) {
+ process_info_ = process_info;
+}
+
+string16 TaskManagerSharedWorkerResource::GetTitle() const {
+ return l10n_util::GetStringFUTF16(IDS_TASK_MANAGER_WORKER_PREFIX, title_);
+}
+
+string16 TaskManagerSharedWorkerResource::GetProfileName() const {
+ return string16();
+}
+
+SkBitmap TaskManagerSharedWorkerResource::GetIcon() const {
+ if (!default_icon_) {
+ ResourceBundle& rb = ResourceBundle::GetSharedInstance();
+ default_icon_ = rb.GetBitmapNamed(IDR_PLUGIN);
+ // TODO(jabdelmalek): use different icon for web workers.
+ }
+ return *default_icon_;
+}
+
+base::ProcessHandle TaskManagerSharedWorkerResource::GetProcess() const {
+ return process_info_.handle();
+}
+
+TaskManager::Resource::Type TaskManagerSharedWorkerResource::GetType() const {
+ return WORKER;
+}
+
+bool TaskManagerSharedWorkerResource::SupportNetworkUsage() const {
+ return false;
+}
+
+void TaskManagerSharedWorkerResource::SetSupportNetworkUsage() {
+}
+
+
+// This class is needed to ensure that all resources in WorkerResourceList are
+// deleted if corresponding task is posted to but not executed on the UI
+// thread.
+class TaskManagerWorkerResourceProvider::WorkerResourceListHolder {
+ public:
+ WorkerResourceListHolder() {
+ }
+
+ ~WorkerResourceListHolder() {
+ STLDeleteElements(&resources_);
+ }
+
+ WorkerResourceList* resources() {
+ return &resources_;
+ }
+
+ private:
+ WorkerResourceList resources_;
+};
+
+
+TaskManagerWorkerResourceProvider::
+ TaskManagerWorkerResourceProvider(TaskManager* task_manager)
+ : updating_(false),
+ task_manager_(task_manager) {
+}
+
+TaskManagerWorkerResourceProvider::~TaskManagerWorkerResourceProvider() {
+ DeleteAllResources();
+}
+
+TaskManager::Resource* TaskManagerWorkerResourceProvider::GetResource(
+ int origin_pid,
+ int render_process_host_id,
+ int routing_id) {
+ return NULL;
+}
+
+void TaskManagerWorkerResourceProvider::StartUpdating() {
+ DCHECK(!updating_);
+ updating_ = true;
+ // Register for notifications to get new child processes.
+ registrar_.Add(this, content::NOTIFICATION_CHILD_PROCESS_HOST_CONNECTED,
+ content::NotificationService::AllBrowserContextsAndSources());
+ registrar_.Add(this, content::NOTIFICATION_CHILD_PROCESS_HOST_DISCONNECTED,
+ content::NotificationService::AllBrowserContextsAndSources());
+ // Get existing workers.
+ BrowserThread::PostTask(
+ BrowserThread::IO, FROM_HERE, base::Bind(
+ &TaskManagerWorkerResourceProvider::StartObservingWorkers,
+ this));
+}
+
+void TaskManagerWorkerResourceProvider::StopUpdating() {
+ DCHECK(updating_);
+ updating_ = false;
+ launching_workers_.clear();
+ DeleteAllResources();
+ registrar_.Remove(
+ this, content::NOTIFICATION_CHILD_PROCESS_HOST_CONNECTED,
+ content::NotificationService::AllBrowserContextsAndSources());
+ registrar_.Remove(
+ this, content::NOTIFICATION_CHILD_PROCESS_HOST_DISCONNECTED,
+ content::NotificationService::AllBrowserContextsAndSources());
+ BrowserThread::PostTask(
+ BrowserThread::IO, FROM_HERE, base::Bind(
+ &TaskManagerWorkerResourceProvider::StopObservingWorkers,
+ this));
+}
+
+void TaskManagerWorkerResourceProvider::WorkerCreated(
+ WorkerProcessHost* process,
+ const WorkerProcessHost::WorkerInstance& instance) {
+ TaskManagerSharedWorkerResource* resource =
+ new TaskManagerSharedWorkerResource(*process, instance.worker_route_id(),
+ instance.url(), instance.name());
+ BrowserThread::PostTask(
+ BrowserThread::UI, FROM_HERE,
+ base::Bind(&TaskManagerWorkerResourceProvider::NotifyWorkerCreated,
+ this, base::Owned(new WorkerResourceHolder(resource))));
+}
+
+void TaskManagerWorkerResourceProvider::WorkerDestroyed(
+ WorkerProcessHost* process,
+ int worker_route_id) {
+ BrowserThread::PostTask(
+ BrowserThread::UI, FROM_HERE, base::Bind(
+ &TaskManagerWorkerResourceProvider::NotifyWorkerDestroyed,
+ this, process->id(), worker_route_id));
+}
+
+void TaskManagerWorkerResourceProvider::Observe(
+ int type,
+ const content::NotificationSource& source,
+ const content::NotificationDetails& details) {
+ ChildProcessInfo* process_info =
+ content::Details<ChildProcessInfo>(details).ptr();
+ if (process_info->type() != ChildProcessInfo::WORKER_PROCESS)
+ return;
+ if (type == content::NOTIFICATION_CHILD_PROCESS_HOST_CONNECTED) {
+ ProcessIdToWorkerResources::iterator it =
+ launching_workers_.find(process_info->id());
+ if (it == launching_workers_.end())
+ return;
+ WorkerResourceList& resources = it->second;
+ for (WorkerResourceList::iterator r = resources.begin();
+ r !=resources.end(); ++r) {
+ (*r)->UpdateProcessInfo(*process_info);
+ task_manager_->AddResource(*r);
+ }
+ launching_workers_.erase(it);
+ } else if (type == content::NOTIFICATION_CHILD_PROCESS_HOST_DISCONNECTED) {
+ // Worker process may be destroyed before WorkerMsg_TerminateWorkerContex
+ // message is handled and WorkerDestroyed is fired. In this case we won't
+ // get WorkerDestroyed notification and have to clear resources for such
+ // workers here when the worker process has been destroyed.
+ for (WorkerResourceList::iterator it = resources_.begin();
+ it !=resources_.end();) {
+ if ((*it)->process_info().id() == process_info->id()) {
+ task_manager_->RemoveResource(*it);
+ delete *it;
+ it = resources_.erase(it);
+ } else {
+ ++it;
+ }
+ }
+ DCHECK(launching_workers_.find(process_info->id()) ==
+ launching_workers_.end());
+ }
+}
+
+void TaskManagerWorkerResourceProvider::NotifyWorkerCreated(
+ WorkerResourceHolder* resource_holder) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ if (!updating_)
+ return;
+ AddResource(resource_holder->release());
+}
+
+void TaskManagerWorkerResourceProvider::NotifyWorkerDestroyed(
+ int process_id, int routing_id) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ if (!updating_)
+ return;
+ for (WorkerResourceList::iterator it = resources_.begin();
+ it !=resources_.end(); ++it) {
+ if ((*it)->Matches(process_id, routing_id)) {
+ task_manager_->RemoveResource(*it);
+ delete *it;
+ resources_.erase(it);
+ return;
+ }
+ }
+}
+
+void TaskManagerWorkerResourceProvider::StartObservingWorkers() {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+
+ scoped_ptr<WorkerResourceListHolder> holder(new WorkerResourceListHolder);
+ BrowserChildProcessHost::Iterator iter(ChildProcessInfo::WORKER_PROCESS);
+ for (; !iter.Done(); ++iter) {
+ WorkerProcessHost* worker = static_cast<WorkerProcessHost*>(*iter);
+ const WorkerProcessHost::Instances& instances = worker->instances();
+ for (WorkerProcessHost::Instances::const_iterator i = instances.begin();
+ i != instances.end(); ++i) {
+ holder->resources()->push_back(new TaskManagerSharedWorkerResource(
+ **iter, i->worker_route_id(), i->url(), i->name()));
+ }
+ }
+
+ BrowserThread::PostTask(
+ BrowserThread::UI, FROM_HERE,
+ base::Bind(
+ &TaskManagerWorkerResourceProvider::AddWorkerResourceList,
+ this, base::Owned(holder.release())));
+
+ WorkerService::GetInstance()->AddObserver(this);
+}
+
+void TaskManagerWorkerResourceProvider::StopObservingWorkers() {
+ WorkerService::GetInstance()->RemoveObserver(this);
+}
+
+void TaskManagerWorkerResourceProvider::AddWorkerResourceList(
+ WorkerResourceListHolder* resource_list_holder) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ if (!updating_)
+ return;
+ WorkerResourceList* resources = resource_list_holder->resources();
+ for (WorkerResourceList::iterator it = resources->begin();
+ it !=resources->end(); ++it) {
+ AddResource(*it);
+ }
+ resources->clear();
+}
+
+void TaskManagerWorkerResourceProvider::AddResource(
+ TaskManagerSharedWorkerResource* resource) {
+ DCHECK(updating_);
+ resources_.push_back(resource);
+ if (resource->process_info().handle() == base::kNullProcessHandle) {
+ int process_id = resource->process_info().id();
+ launching_workers_[process_id].push_back(resource);
+ } else {
+ task_manager_->AddResource(resource);
+ }
+}
+
+void TaskManagerWorkerResourceProvider::DeleteAllResources() {
+ STLDeleteElements(&resources_);
+}
diff --git a/chrome/browser/task_manager/task_manager_worker_resource_provider.h b/chrome/browser/task_manager/task_manager_worker_resource_provider.h
new file mode 100644
index 0000000..990e3668
--- /dev/null
+++ b/chrome/browser/task_manager/task_manager_worker_resource_provider.h
@@ -0,0 +1,79 @@
+// Copyright (c) 2011 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_BROWSER_TASK_MANAGER_TASK_MANAGER_WORKER_RESOURCE_PROVIDER_H_
+#define CHROME_BROWSER_TASK_MANAGER_TASK_MANAGER_WORKER_RESOURCE_PROVIDER_H_
+#pragma once
+
+#include <map>
+#include <vector>
+
+#include "base/basictypes.h"
+#include "chrome/browser/task_manager/task_manager.h"
+#include "content/browser/worker_host/worker_service_observer.h"
+#include "content/public/browser/notification_observer.h"
+#include "content/public/browser/notification_registrar.h"
+
+class TaskManagerSharedWorkerResource;
+
+class TaskManagerWorkerResourceProvider
+ : public TaskManager::ResourceProvider,
+ private WorkerServiceObserver,
+ private content::NotificationObserver {
+ public:
+ explicit TaskManagerWorkerResourceProvider(TaskManager* task_manager);
+
+ private:
+ class WorkerResourceListHolder;
+ typedef std::vector<TaskManagerSharedWorkerResource*> WorkerResourceList;
+ typedef scoped_ptr<TaskManagerSharedWorkerResource> WorkerResourceHolder;
+ typedef std::map<int, WorkerResourceList> ProcessIdToWorkerResources;
+
+ virtual ~TaskManagerWorkerResourceProvider();
+
+ // TaskManager::ResourceProvider implementation.
+ virtual TaskManager::Resource* GetResource(int origin_pid,
+ int render_process_host_id,
+ int routing_id);
+ virtual void StartUpdating();
+ virtual void StopUpdating();
+
+ // WorkerServiceObserver implementation.
+ virtual void WorkerCreated(
+ WorkerProcessHost* process,
+ const WorkerProcessHost::WorkerInstance& instance) OVERRIDE;
+ virtual void WorkerDestroyed(
+ WorkerProcessHost* process,
+ int worker_route_id) OVERRIDE;
+ virtual void WorkerContextStarted(WorkerProcessHost*, int) OVERRIDE {}
+
+ // content::NotificationObserver implementation.
+ virtual void Observe(int type,
+ const content::NotificationSource& source,
+ const content::NotificationDetails& details);
+
+ void NotifyWorkerCreated(WorkerResourceHolder* resource_holder);
+ void NotifyWorkerDestroyed(int process_id, int routing_id);
+
+ void StartObservingWorkers();
+ void StopObservingWorkers();
+
+ void AddWorkerResourceList(WorkerResourceListHolder* resource_list_holder);
+ void AddResource(TaskManagerSharedWorkerResource* resource);
+ void DeleteAllResources();
+
+ bool updating_;
+ TaskManager* task_manager_;
+ WorkerResourceList resources_;
+ // Map from worker process id to the list of its workers. This list contains
+ // entries for worker processes which has not launched yet but for which we
+ // have already received WorkerCreated event. We don't add such workers to
+ // the task manager until the process is launched.
+ ProcessIdToWorkerResources launching_workers_;
+ content::NotificationRegistrar registrar_;
+
+ DISALLOW_COPY_AND_ASSIGN(TaskManagerWorkerResourceProvider);
+};
+
+#endif // CHROME_BROWSER_TASK_MANAGER_TASK_MANAGER_WORKER_RESOURCE_PROVIDER_H_