diff options
Diffstat (limited to 'chrome/browser/task_manager')
-rw-r--r-- | chrome/browser/task_manager/task_manager.cc | 54 | ||||
-rw-r--r-- | chrome/browser/task_manager/task_manager.h | 18 | ||||
-rw-r--r-- | chrome/browser/task_manager/task_manager_browsertest.cc | 36 | ||||
-rw-r--r-- | chrome/browser/task_manager/task_manager_resource_providers.cc | 368 | ||||
-rw-r--r-- | chrome/browser/task_manager/task_manager_resource_providers.h | 113 |
5 files changed, 509 insertions, 80 deletions
diff --git a/chrome/browser/task_manager/task_manager.cc b/chrome/browser/task_manager/task_manager.cc index 2711925..c6500fa 100644 --- a/chrome/browser/task_manager/task_manager.cc +++ b/chrome/browser/task_manager/task_manager.cc @@ -78,6 +78,10 @@ TaskManagerModel::TaskManagerModel(TaskManager* task_manager) new TaskManagerBrowserProcessResourceProvider(task_manager); browser_provider->AddRef(); providers_.push_back(browser_provider); + TaskManagerBackgroundContentsResourceProvider* bc_provider = + new TaskManagerBackgroundContentsResourceProvider(task_manager); + bc_provider->AddRef(); + providers_.push_back(bc_provider); TaskManagerTabContentsResourceProvider* wc_provider = new TaskManagerTabContentsResourceProvider(task_manager); wc_provider->AddRef(); @@ -116,12 +120,12 @@ void TaskManagerModel::RemoveObserver(TaskManagerModelObserver* observer) { } string16 TaskManagerModel::GetResourceTitle(int index) const { - CHECK(index < ResourceCount()); + CHECK_LT(index, ResourceCount()); return WideToUTF16Hack(resources_[index]->GetTitle()); } int64 TaskManagerModel::GetNetworkUsage(int index) const { - CHECK(index < ResourceCount()); + CHECK_LT(index, ResourceCount()); return GetNetworkUsage(resources_[index]); } @@ -138,12 +142,12 @@ string16 TaskManagerModel::GetResourceNetworkUsage(int index) const { } double TaskManagerModel::GetCPUUsage(int index) const { - CHECK(index < ResourceCount()); + CHECK_LT(index, ResourceCount()); return GetCPUUsage(resources_[index]); } string16 TaskManagerModel::GetResourceCPUUsage(int index) const { - CHECK(index < ResourceCount()); + CHECK_LT(index, ResourceCount()); return WideToUTF16Hack(StringPrintf( #if defined(OS_MACOSX) // Activity Monitor shows %cpu with one decimal digit -- be @@ -176,7 +180,7 @@ string16 TaskManagerModel::GetResourcePhysicalMemory(int index) const { } int TaskManagerModel::GetProcessId(int index) const { - CHECK(index < ResourceCount()); + CHECK_LT(index, ResourceCount()); return base::GetProcId(resources_[index]->GetProcess()); } @@ -185,13 +189,13 @@ string16 TaskManagerModel::GetResourceProcessId(int index) const { } string16 TaskManagerModel::GetResourceGoatsTeleported(int index) const { - CHECK(index < ResourceCount()); + CHECK_LT(index, ResourceCount()); return base::FormatNumber(GetGoatsTeleported(index)); } string16 TaskManagerModel::GetResourceWebCoreImageCacheSize( int index) const { - CHECK(index < ResourceCount()); + CHECK_LT(index, ResourceCount()); if (!resources_[index]->ReportsCacheStats()) return l10n_util::GetStringUTF16(IDS_TASK_MANAGER_NA_CELL_TEXT); const WebKit::WebCache::ResourceTypeStats stats( @@ -201,7 +205,7 @@ string16 TaskManagerModel::GetResourceWebCoreImageCacheSize( string16 TaskManagerModel::GetResourceWebCoreScriptsCacheSize( int index) const { - CHECK(index < ResourceCount()); + CHECK_LT(index, ResourceCount()); if (!resources_[index]->ReportsCacheStats()) return l10n_util::GetStringUTF16(IDS_TASK_MANAGER_NA_CELL_TEXT); const WebKit::WebCache::ResourceTypeStats stats( @@ -211,7 +215,7 @@ string16 TaskManagerModel::GetResourceWebCoreScriptsCacheSize( string16 TaskManagerModel::GetResourceWebCoreCSSCacheSize( int index) const { - CHECK(index < ResourceCount()); + CHECK_LT(index, ResourceCount()); if (!resources_[index]->ReportsCacheStats()) return l10n_util::GetStringUTF16(IDS_TASK_MANAGER_NA_CELL_TEXT); const WebKit::WebCache::ResourceTypeStats stats( @@ -220,7 +224,7 @@ string16 TaskManagerModel::GetResourceWebCoreCSSCacheSize( } string16 TaskManagerModel::GetResourceSqliteMemoryUsed(int index) const { - CHECK(index < ResourceCount()); + CHECK_LT(index, ResourceCount()); if (!resources_[index]->ReportsSqliteMemoryUsed()) return l10n_util::GetStringUTF16(IDS_TASK_MANAGER_NA_CELL_TEXT); return GetMemCellText(resources_[index]->SqliteMemoryUsedBytes()); @@ -240,7 +244,7 @@ string16 TaskManagerModel::GetResourceV8MemoryAllocatedSize( } bool TaskManagerModel::IsResourceFirstInGroup(int index) const { - CHECK(index < ResourceCount()); + CHECK_LT(index, ResourceCount()); TaskManager::Resource* resource = resources_[index]; GroupMap::const_iterator iter = group_map_.find(resource->GetProcess()); DCHECK(iter != group_map_.end()); @@ -248,8 +252,13 @@ bool TaskManagerModel::IsResourceFirstInGroup(int index) const { return ((*group)[0] == resource); } +bool TaskManagerModel::IsBackgroundResource(int index) const { + CHECK_LT(index, ResourceCount()); + return resources_[index]->IsBackground(); +} + SkBitmap TaskManagerModel::GetResourceIcon(int index) const { - CHECK(index < ResourceCount()); + CHECK_LT(index, ResourceCount()); SkBitmap icon = resources_[index]->GetIcon(); if (!icon.isNull()) return icon; @@ -261,7 +270,7 @@ SkBitmap TaskManagerModel::GetResourceIcon(int index) const { std::pair<int, int> TaskManagerModel::GetGroupRangeForResource(int index) const { - CHECK(index < ResourceCount()); + CHECK_LT(index, ResourceCount()); TaskManager::Resource* resource = resources_[index]; GroupMap::const_iterator group_iter = group_map_.find(resource->GetProcess()); @@ -388,22 +397,22 @@ int TaskManagerModel::CompareValues(int row1, int row2, int col_id) const { base::ProcessHandle TaskManagerModel::GetResourceProcessHandle(int index) const { - CHECK(index < ResourceCount()); + CHECK_LT(index, ResourceCount()); return resources_[index]->GetProcess(); } TaskManager::Resource::Type TaskManagerModel::GetResourceType(int index) const { - CHECK(index < ResourceCount()); + CHECK_LT(index, ResourceCount()); return resources_[index]->GetType(); } TabContents* TaskManagerModel::GetResourceTabContents(int index) const { - CHECK(index < ResourceCount()); + CHECK_LT(index, ResourceCount()); return resources_[index]->GetTabContents(); } const Extension* TaskManagerModel::GetResourceExtension(int index) const { - CHECK(index < ResourceCount()); + CHECK_LT(index, ResourceCount()); return resources_[index]->GetExtension(); } @@ -607,7 +616,7 @@ void TaskManagerModel::AddResource(TaskManager::Resource* resource) { resources_.end(), (*group_entries)[group_entries->size() - 2]); DCHECK(iter != resources_.end()); - new_entry_index = static_cast<int>(iter - resources_.begin()); + new_entry_index = static_cast<int>(iter - resources_.begin()) + 1; resources_.insert(++iter, resource); } @@ -711,6 +720,11 @@ void TaskManagerModel::Clear() { } } +void TaskManagerModel::ModelChanged() { + // Notify the table that the contents have changed for it to redraw. + FOR_EACH_OBSERVER(TaskManagerModelObserver, observer_list_, OnModelChanged()); +} + void TaskManagerModel::NotifyResourceTypeStats( base::ProcessId renderer_id, const WebKit::WebCache::ResourceTypeStats& stats) { @@ -962,6 +976,10 @@ void TaskManager::OnWindowClosed() { model_->StopUpdating(); } +void TaskManager::ModelChanged() { + model_->ModelChanged(); +} + // static TaskManager* TaskManager::GetInstance() { return Singleton<TaskManager>::get(); diff --git a/chrome/browser/task_manager/task_manager.h b/chrome/browser/task_manager/task_manager.h index cef241c..9d933e5 100644 --- a/chrome/browser/task_manager/task_manager.h +++ b/chrome/browser/task_manager/task_manager.h @@ -102,6 +102,10 @@ class TaskManager { const WebKit::WebCache::ResourceTypeStats& stats) {} virtual void NotifyV8HeapStats(size_t v8_memory_allocated, size_t v8_memory_used) {} + + // Returns true if this resource is not visible to the user because it lives + // in the background (e.g. extension background page, background contents). + virtual bool IsBackground() const { return false; } }; // ResourceProviders are responsible for adding/removing resources to the task @@ -156,6 +160,12 @@ class TaskManager { void OnWindowClosed(); + // Invoked when a change to a resource has occurred that should cause any + // observers to completely refresh themselves (for example, the creation of + // a background resource in a process). Results in all observers receiving + // OnModelChanged() events. + void ModelChanged(); + // Returns the singleton instance (and initializes it if necessary). static TaskManager* GetInstance(); @@ -259,6 +269,10 @@ class TaskManagerModel : public URLRequestJobTracker::JobObserver, // rendered by the same process are groupped together). bool IsResourceFirstInGroup(int index) const; + // Returns true if the resource runs in the background (not visible to the + // user, e.g. extension background pages and BackgroundContents). + bool IsBackgroundResource(int index) const; + // Returns icon to be used for resource (for example a favicon). SkBitmap GetResourceIcon(int index) const; @@ -300,6 +314,10 @@ class TaskManagerModel : public URLRequestJobTracker::JobObserver, void Clear(); // Removes all items. + // Sends OnModelChanged() to all observers to inform them of significant + // changes to the model. + void ModelChanged(); + void NotifyResourceTypeStats( base::ProcessId renderer_id, const WebKit::WebCache::ResourceTypeStats& stats); diff --git a/chrome/browser/task_manager/task_manager_browsertest.cc b/chrome/browser/task_manager/task_manager_browsertest.cc index 9e3c181..91cc23d 100644 --- a/chrome/browser/task_manager/task_manager_browsertest.cc +++ b/chrome/browser/task_manager/task_manager_browsertest.cc @@ -7,18 +7,20 @@ #include "app/l10n_util.h" #include "base/file_path.h" #include "base/utf_string_conversions.h" -#include "chrome/browser/browser.h" -#include "chrome/browser/browser_navigator.h" +#include "chrome/browser/background_contents_service.h" #include "chrome/browser/browser_process.h" -#include "chrome/browser/browser_window.h" #include "chrome/browser/extensions/crashed_extension_infobar.h" #include "chrome/browser/extensions/extension_browsertest.h" #include "chrome/browser/notifications/desktop_notification_service.h" #include "chrome/browser/notifications/notification_test_util.h" #include "chrome/browser/notifications/notification_ui_manager.h" +#include "chrome/browser/profile.h" #include "chrome/browser/tab_contents/infobar_delegate.h" #include "chrome/browser/tab_contents/tab_contents.h" #include "chrome/browser/tabs/tab_strip_model.h" +#include "chrome/browser/ui/browser.h" +#include "chrome/browser/ui/browser_navigator.h" +#include "chrome/browser/ui/browser_window.h" #include "chrome/common/extensions/extension.h" #include "chrome/common/page_transition_types.h" #include "chrome/test/in_process_browser_test.h" @@ -118,6 +120,34 @@ IN_PROC_BROWSER_TEST_F(TaskManagerBrowserTest, NoticeTabContentsChanges) { WaitForResourceChange(2); } +IN_PROC_BROWSER_TEST_F(TaskManagerBrowserTest, NoticeBGContentsChanges) { + EXPECT_EQ(0, model()->ResourceCount()); + + // Show the task manager. This populates the model, and helps with debugging + // (you see the task manager). + browser()->window()->ShowTaskManager(); + + // Browser and the New Tab Page. + EXPECT_EQ(2, model()->ResourceCount()); + + // Open a new background contents and make sure we notice that. + GURL url(ui_test_utils::GetTestUrl(FilePath(FilePath::kCurrentDirectory), + FilePath(kTitle1File))); + + BackgroundContentsService* service = + browser()->profile()->GetBackgroundContentsService(); + string16 application_id(ASCIIToUTF16("test_app_id")); + service->LoadBackgroundContents(browser()->profile(), + url, + ASCIIToUTF16("background_page"), + application_id); + WaitForResourceChange(3); + + // Close the background contents and verify that we notice. + service->ShutdownAssociatedBackgroundContents(application_id); + WaitForResourceChange(2); +} + #if defined(OS_WIN) // http://crbug.com/31663 #define MAYBE_NoticeExtensionChanges DISABLED_NoticeExtensionChanges diff --git a/chrome/browser/task_manager/task_manager_resource_providers.cc b/chrome/browser/task_manager/task_manager_resource_providers.cc index 0c3d5d8..73476c9 100644 --- a/chrome/browser/task_manager/task_manager_resource_providers.cc +++ b/chrome/browser/task_manager/task_manager_resource_providers.cc @@ -15,13 +15,16 @@ #include "base/stl_util-inl.h" #include "base/string_util.h" #include "base/thread.h" +#include "base/utf_string_conversions.h" #include "chrome/app/chrome_command_ids.h" +#include "chrome/browser/background_contents_service.h" #include "chrome/browser/browser_child_process_host.h" #include "chrome/browser/browser_list.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/browser_thread.h" #include "chrome/browser/extensions/extension_host.h" #include "chrome/browser/extensions/extension_process_manager.h" +#include "chrome/browser/extensions/extensions_service.h" #include "chrome/browser/notifications/balloon_collection.h" #include "chrome/browser/notifications/balloon_host.h" #include "chrome/browser/notifications/notification_ui_manager.h" @@ -29,8 +32,9 @@ #include "chrome/browser/renderer_host/render_process_host.h" #include "chrome/browser/renderer_host/render_view_host.h" #include "chrome/browser/renderer_host/resource_message_filter.h" -#include "chrome/browser/tab_contents/tab_util.h" +#include "chrome/browser/tab_contents/background_contents.h" #include "chrome/browser/tab_contents/tab_contents.h" +#include "chrome/browser/tab_contents/tab_util.h" #include "chrome/common/extensions/extension.h" #include "chrome/common/notification_service.h" #include "chrome/common/render_messages.h" @@ -46,20 +50,20 @@ #include "gfx/icon_util.h" #endif // defined(OS_WIN) + //////////////////////////////////////////////////////////////////////////////// -// TaskManagerTabContentsResource class +// TaskManagerRendererResource class //////////////////////////////////////////////////////////////////////////////// - -TaskManagerTabContentsResource::TaskManagerTabContentsResource( - TabContents* tab_contents) - : tab_contents_(tab_contents), +TaskManagerRendererResource::TaskManagerRendererResource( + base::ProcessHandle process, RenderViewHost* render_view_host) + : process_(process), + render_view_host_(render_view_host), pending_stats_update_(false), v8_memory_allocated_(0), v8_memory_used_(0), pending_v8_memory_allocated_update_(false) { - // We cache the process as when the TabContents is closed the process - // becomes NULL and the TaskManager still needs it. - process_ = tab_contents_->GetRenderProcessHost()->GetHandle(); + // We cache the process and pid as when a Tab/BackgroundContents is closed the + // process reference becomes NULL and the TaskManager still needs it. pid_ = base::GetProcId(process_); stats_.images.size = 0; stats_.cssStyleSheets.size = 0; @@ -68,76 +72,92 @@ TaskManagerTabContentsResource::TaskManagerTabContentsResource( stats_.fonts.size = 0; } -TaskManagerTabContentsResource::~TaskManagerTabContentsResource() { +TaskManagerRendererResource::~TaskManagerRendererResource() { } -std::wstring TaskManagerTabContentsResource::GetTitle() const { - // Fall back on the URL if there's no title. - std::wstring tab_title(UTF16ToWideHack(tab_contents_->GetTitle())); - if (tab_title.empty()) { - tab_title = UTF8ToWide(tab_contents_->GetURL().spec()); - // Force URL to be LTR. - tab_title = UTF16ToWide(base::i18n::GetDisplayStringInLTRDirectionality( - WideToUTF16(tab_title))); - } else { - // Since the tab_title will be concatenated with - // IDS_TASK_MANAGER_TAB_PREFIX, we need to explicitly set the tab_title to - // be LTR format if there is no strong RTL charater in it. Otherwise, if - // IDS_TASK_MANAGER_TAB_PREFIX is an RTL word, the concatenated result - // might be wrong. For example, http://mail.yahoo.com, whose title is - // "Yahoo! Mail: The best web-based Email!", without setting it explicitly - // as LTR format, the concatenated result will be "!Yahoo! Mail: The best - // web-based Email :BAT", in which the capital letters "BAT" stands for - // the Hebrew word for "tab". - base::i18n::AdjustStringForLocaleDirection(tab_title, &tab_title); - } - - return l10n_util::GetStringF(IDS_TASK_MANAGER_TAB_PREFIX, tab_title); -} - -void TaskManagerTabContentsResource::Refresh() { +void TaskManagerRendererResource::Refresh() { if (!pending_stats_update_) { - tab_contents_->render_view_host()->Send(new ViewMsg_GetCacheResourceStats); + render_view_host_->Send(new ViewMsg_GetCacheResourceStats); pending_stats_update_ = true; } if (!pending_v8_memory_allocated_update_) { - tab_contents_->render_view_host()->Send(new ViewMsg_GetV8HeapStats); + render_view_host_->Send(new ViewMsg_GetV8HeapStats); pending_v8_memory_allocated_update_ = true; } } WebKit::WebCache::ResourceTypeStats - TaskManagerTabContentsResource::GetWebCoreCacheStats() const { +TaskManagerRendererResource::GetWebCoreCacheStats() const { return stats_; } -size_t TaskManagerTabContentsResource::GetV8MemoryAllocated() const { +size_t TaskManagerRendererResource::GetV8MemoryAllocated() const { return v8_memory_allocated_; } -size_t TaskManagerTabContentsResource::GetV8MemoryUsed() const { +size_t TaskManagerRendererResource::GetV8MemoryUsed() const { return v8_memory_used_; } -void TaskManagerTabContentsResource::NotifyResourceTypeStats( +void TaskManagerRendererResource::NotifyResourceTypeStats( const WebKit::WebCache::ResourceTypeStats& stats) { stats_ = stats; pending_stats_update_ = false; } -void TaskManagerTabContentsResource::NotifyV8HeapStats( +void TaskManagerRendererResource::NotifyV8HeapStats( size_t v8_memory_allocated, size_t v8_memory_used) { v8_memory_allocated_ = v8_memory_allocated; v8_memory_used_ = v8_memory_used; pending_v8_memory_allocated_update_ = false; } -SkBitmap TaskManagerTabContentsResource::GetIcon() const { - return tab_contents_->GetFavIcon(); +base::ProcessHandle TaskManagerRendererResource::GetProcess() const { + return process_; } -base::ProcessHandle TaskManagerTabContentsResource::GetProcess() const { - return process_; +//////////////////////////////////////////////////////////////////////////////// +// TaskManagerTabContentsResource class +//////////////////////////////////////////////////////////////////////////////// + +TaskManagerTabContentsResource::TaskManagerTabContentsResource( + TabContents* tab_contents) + : TaskManagerRendererResource( + tab_contents->GetRenderProcessHost()->GetHandle(), + tab_contents->render_view_host()), + tab_contents_(tab_contents) { +} + +TaskManagerTabContentsResource::~TaskManagerTabContentsResource() { +} + +std::wstring TaskManagerTabContentsResource::GetTitle() const { + // Fall back on the URL if there's no title. + std::wstring tab_title(UTF16ToWideHack(tab_contents_->GetTitle())); + if (tab_title.empty()) { + tab_title = UTF8ToWide(tab_contents_->GetURL().spec()); + // Force URL to be LTR. + tab_title = UTF16ToWide(base::i18n::GetDisplayStringInLTRDirectionality( + WideToUTF16(tab_title))); + } else { + // Since the tab_title will be concatenated with + // IDS_TASK_MANAGER_TAB_PREFIX, we need to explicitly set the tab_title to + // be LTR format if there is no strong RTL charater in it. Otherwise, if + // IDS_TASK_MANAGER_TAB_PREFIX is an RTL word, the concatenated result + // might be wrong. For example, http://mail.yahoo.com, whose title is + // "Yahoo! Mail: The best web-based Email!", without setting it explicitly + // as LTR format, the concatenated result will be "!Yahoo! Mail: The best + // web-based Email :BAT", in which the capital letters "BAT" stands for + // the Hebrew word for "tab". + base::i18n::AdjustStringForLocaleDirection(tab_title, &tab_title); + } + + return l10n_util::GetStringF(IDS_TASK_MANAGER_TAB_PREFIX, tab_title); +} + + +SkBitmap TaskManagerTabContentsResource::GetIcon() const { + return tab_contents_->GetFavIcon(); } TabContents* TaskManagerTabContentsResource::GetTabContents() const { @@ -183,11 +203,11 @@ TaskManager::Resource* TaskManagerTabContentsResourceProvider::GetResource( std::map<TabContents*, TaskManagerTabContentsResource*>::iterator res_iter = resources_.find(tab_contents); - if (res_iter == resources_.end()) + 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; } @@ -316,6 +336,253 @@ void TaskManagerTabContentsResourceProvider::Observe(NotificationType type, } //////////////////////////////////////////////////////////////////////////////// +// TaskManagerBackgroundContentsResource class +//////////////////////////////////////////////////////////////////////////////// + +SkBitmap* TaskManagerBackgroundContentsResource::default_icon_ = NULL; + +TaskManagerBackgroundContentsResource::TaskManagerBackgroundContentsResource( + BackgroundContents* background_contents, + const std::wstring& application_name) + : TaskManagerRendererResource( + background_contents->render_view_host()->process()->GetHandle(), + background_contents->render_view_host()), + background_contents_(background_contents), + application_name_(application_name) { + // Just use the same icon that other extension resources do. + // TODO(atwilson): Use the favicon when that's available. + if (!default_icon_) { + ResourceBundle& rb = ResourceBundle::GetSharedInstance(); + default_icon_ = rb.GetBitmapNamed(IDR_PLUGIN); + } + // Ensure that the string has the appropriate direction markers (see comment + // in TaskManagerTabContentsResource::GetTitle()). + base::i18n::AdjustStringForLocaleDirection(application_name_, + &application_name_); +} + +TaskManagerBackgroundContentsResource::~TaskManagerBackgroundContentsResource( + ) { +} + +std::wstring TaskManagerBackgroundContentsResource::GetTitle() const { + std::wstring title = application_name_; + + if (title.empty()) { + // No title (can't locate the parent app for some reason) so just display + // the URL (properly forced to be LTR). + title = UTF16ToWide(base::i18n::GetDisplayStringInLTRDirectionality( + UTF8ToUTF16(background_contents_->GetURL().spec()))); + } + return l10n_util::GetStringF(IDS_TASK_MANAGER_BACKGROUND_PREFIX, title); +} + + +SkBitmap TaskManagerBackgroundContentsResource::GetIcon() const { + return *default_icon_; +} + +bool TaskManagerBackgroundContentsResource::IsBackground() const { + return true; +} + +//////////////////////////////////////////////////////////////////////////////// +// TaskManagerBackgroundContentsResourceProvider class +//////////////////////////////////////////////////////////////////////////////// + +TaskManagerBackgroundContentsResourceProvider:: + TaskManagerBackgroundContentsResourceProvider(TaskManager* task_manager) + : updating_(false), + task_manager_(task_manager) { +} + +TaskManagerBackgroundContentsResourceProvider:: + ~TaskManagerBackgroundContentsResourceProvider() { +} + +TaskManager::Resource* +TaskManagerBackgroundContentsResourceProvider::GetResource( + int origin_pid, + int render_process_host_id, + int routing_id) { + + BackgroundContents* contents = BackgroundContents::GetBackgroundContentsByID( + render_process_host_id, routing_id); + if (!contents) // This resource no longer exists. + return NULL; + + base::ProcessHandle process_handle = + contents->render_view_host()->process()->GetHandle(); + if (!process_handle) // Process crashed. + return NULL; + + int pid = base::GetProcId(process_handle); + if (pid != origin_pid) + return NULL; + + std::map<BackgroundContents*, + TaskManagerBackgroundContentsResource*>::iterator res_iter = + resources_.find(contents); + if (res_iter == resources_.end()) + // Can happen if the page went away while a network request was being + // performed. + return NULL; + + return res_iter->second; +} + +void TaskManagerBackgroundContentsResourceProvider::StartUpdating() { + DCHECK(!updating_); + updating_ = true; + + // Add all the existing BackgroundContents from every profile. + ProfileManager* profile_manager = g_browser_process->profile_manager(); + for (ProfileManager::const_iterator it = profile_manager->begin(); + it != profile_manager->end(); ++it) { + BackgroundContentsService* background_contents_service = + (*it)->GetBackgroundContentsService(); + ExtensionsService* extensions_service = (*it)->GetExtensionsService(); + std::vector<BackgroundContents*> contents = + background_contents_service->GetBackgroundContents(); + for (std::vector<BackgroundContents*>::iterator iterator = contents.begin(); + iterator != contents.end(); ++iterator) { + std::wstring application_name; + // Lookup the name from the parent extension. + if (extensions_service) { + const string16& application_id = + background_contents_service->GetParentApplicationId(*iterator); + const Extension* extension = extensions_service->GetExtensionById( + UTF16ToUTF8(application_id), false); + if (extension) + application_name = UTF8ToWide(extension->name()); + } + Add(*iterator, application_name); + } + } + + // Then we register for notifications to get new BackgroundContents. + registrar_.Add(this, NotificationType::BACKGROUND_CONTENTS_OPENED, + NotificationService::AllSources()); + registrar_.Add(this, NotificationType::BACKGROUND_CONTENTS_NAVIGATED, + NotificationService::AllSources()); + registrar_.Add(this, NotificationType::BACKGROUND_CONTENTS_DELETED, + NotificationService::AllSources()); +} + +void TaskManagerBackgroundContentsResourceProvider::StopUpdating() { + DCHECK(updating_); + updating_ = false; + + // Unregister for notifications + registrar_.Remove(this, NotificationType::BACKGROUND_CONTENTS_OPENED, + NotificationService::AllSources()); + registrar_.Remove(this, NotificationType::BACKGROUND_CONTENTS_NAVIGATED, + NotificationService::AllSources()); + registrar_.Remove(this, NotificationType::BACKGROUND_CONTENTS_DELETED, + NotificationService::AllSources()); + + // Delete all the resources. + STLDeleteContainerPairSecondPointers(resources_.begin(), resources_.end()); + + resources_.clear(); +} + +void TaskManagerBackgroundContentsResourceProvider::AddToTaskManager( + BackgroundContents* background_contents, + const std::wstring& application_name) { + TaskManagerBackgroundContentsResource* resource = + new TaskManagerBackgroundContentsResource(background_contents, + application_name); + resources_[background_contents] = resource; + task_manager_->AddResource(resource); +} + +void TaskManagerBackgroundContentsResourceProvider::Add( + BackgroundContents* contents, const std::wstring& application_name) { + if (!updating_) + return; + + // Don't add contents whose process is dead. + if (!contents->render_view_host()->process()->GetHandle()) + return; + + // Should never add the same BackgroundContents twice. + DCHECK(resources_.find(contents) == resources_.end()); + AddToTaskManager(contents, application_name); +} + +void TaskManagerBackgroundContentsResourceProvider::Remove( + BackgroundContents* contents) { + if (!updating_) + return; + std::map<BackgroundContents*, + TaskManagerBackgroundContentsResource*>::iterator iter = + resources_.find(contents); + DCHECK(iter != resources_.end()); + + // Remove the resource from the Task Manager. + TaskManagerBackgroundContentsResource* resource = iter->second; + task_manager_->RemoveResource(resource); + // And from the provider. + resources_.erase(iter); + // Finally, delete the resource. + delete resource; +} + +void TaskManagerBackgroundContentsResourceProvider::Observe( + NotificationType type, + const NotificationSource& source, + const NotificationDetails& details) { + switch (type.value) { + case NotificationType::BACKGROUND_CONTENTS_OPENED: { + // Get the name from the parent application. If no parent application is + // found, just pass an empty string - BackgroundContentsResource::GetTitle + // will display the URL instead in this case. This should never happen + // except in rare cases when an extension is being unloaded or chrome is + // exiting while the task manager is displayed. + std::wstring application_name; + ExtensionsService* service = + Source<Profile>(source)->GetExtensionsService(); + if (service) { + std::string application_id = UTF16ToUTF8( + Details<BackgroundContentsOpenedDetails>(details)->application_id); + const Extension* extension = + service->GetExtensionById(application_id, false); + // Extension can be NULL when running unit tests. + if (extension) + application_name = UTF8ToWide(extension->name()); + } + Add(Details<BackgroundContentsOpenedDetails>(details)->contents, + application_name); + // Opening a new BackgroundContents needs to force the display to refresh + // (applications may now be considered "background" that weren't before). + task_manager_->ModelChanged(); + break; + } + case NotificationType::BACKGROUND_CONTENTS_NAVIGATED: { + BackgroundContents* contents = Details<BackgroundContents>(details).ptr(); + // Should never get a NAVIGATED before OPENED. + DCHECK(resources_.find(contents) != resources_.end()); + // Preserve the application name. + std::wstring application_name( + resources_.find(contents)->second->application_name()); + Remove(contents); + Add(contents, application_name); + break; + } + case NotificationType::BACKGROUND_CONTENTS_DELETED: + Remove(Details<BackgroundContents>(details).ptr()); + // Closing a BackgroundContents needs to force the display to refresh + // (applications may now be considered "foreground" that weren't before). + task_manager_->ModelChanged(); + break; + default: + NOTREACHED() << "Unexpected notification."; + return; + } +} + +//////////////////////////////////////////////////////////////////////////////// // TaskManagerChildProcessResource class //////////////////////////////////////////////////////////////////////////////// SkBitmap* TaskManagerChildProcessResource::default_icon_ = NULL; @@ -590,6 +857,11 @@ const Extension* TaskManagerExtensionProcessResource::GetExtension() const { return extension_host_->extension(); } +bool TaskManagerExtensionProcessResource::IsBackground() const { + return extension_host_->GetRenderViewType() == + ViewType::EXTENSION_BACKGROUND_PAGE; +} + //////////////////////////////////////////////////////////////////////////////// // TaskManagerExtensionProcessResourceProvider class //////////////////////////////////////////////////////////////////////////////// diff --git a/chrome/browser/task_manager/task_manager_resource_providers.h b/chrome/browser/task_manager/task_manager_resource_providers.h index 5145a7e..9c4e8c4 100644 --- a/chrome/browser/task_manager/task_manager_resource_providers.h +++ b/chrome/browser/task_manager/task_manager_resource_providers.h @@ -17,33 +17,33 @@ #include "chrome/common/notification_registrar.h" #include "third_party/WebKit/WebKit/chromium/public/WebCache.h" +class BackgroundContents; class BalloonHost; class Extension; class ExtensionHost; +class RenderViewHost; class TabContents; // These file contains the resource providers used in the task manager. -class TaskManagerTabContentsResource : public TaskManager::Resource { +// Base class for various types of render process resources that provides common +// functionality like stats tracking. +class TaskManagerRendererResource : public TaskManager::Resource { public: - explicit TaskManagerTabContentsResource(TabContents* tab_contents); - ~TaskManagerTabContentsResource(); + TaskManagerRendererResource(base::ProcessHandle process, + RenderViewHost* render_view_host); + virtual ~TaskManagerRendererResource(); - // TaskManagerResource methods: - std::wstring GetTitle() const; - SkBitmap GetIcon() const; + // TaskManager::Resource methods: base::ProcessHandle GetProcess() const; Type GetType() const { return RENDERER; } - TabContents* GetTabContents() const; - virtual bool ReportsCacheStats() const { return true; } virtual WebKit::WebCache::ResourceTypeStats GetWebCoreCacheStats() const; - virtual bool ReportsV8MemoryStats() const { return true; } virtual size_t GetV8MemoryAllocated() const; virtual size_t GetV8MemoryUsed() const; - // TabContents always provide the network usage. + // RenderResources always provide the network usage. bool SupportNetworkUsage() const { return true; } void SetSupportNetworkUsage() { } @@ -56,9 +56,11 @@ class TaskManagerTabContentsResource : public TaskManager::Resource { size_t v8_memory_used); private: - TabContents* tab_contents_; base::ProcessHandle process_; int pid_; + + // RenderViewHost we use to fetch stats. + RenderViewHost* render_view_host_; // The stats_ field holds information about resource usage in the renderer // process and so it is updated asynchronously by the Refresh() call. WebKit::WebCache::ResourceTypeStats stats_; @@ -70,6 +72,22 @@ class TaskManagerTabContentsResource : public TaskManager::Resource { size_t v8_memory_used_; bool pending_v8_memory_allocated_update_; + DISALLOW_COPY_AND_ASSIGN(TaskManagerRendererResource); +}; + +class TaskManagerTabContentsResource : public TaskManagerRendererResource { + public: + explicit TaskManagerTabContentsResource(TabContents* tab_contents); + ~TaskManagerTabContentsResource(); + + // TaskManager::Resource methods: + virtual std::wstring GetTitle() const; + virtual SkBitmap GetIcon() const; + virtual TabContents* GetTabContents() const; + + private: + TabContents* tab_contents_; + DISALLOW_COPY_AND_ASSIGN(TaskManagerTabContentsResource); }; @@ -114,6 +132,77 @@ class TaskManagerTabContentsResourceProvider DISALLOW_COPY_AND_ASSIGN(TaskManagerTabContentsResourceProvider); }; +class TaskManagerBackgroundContentsResource + : public TaskManagerRendererResource { + public: + TaskManagerBackgroundContentsResource( + BackgroundContents* background_contents, + const std::wstring& application_name); + ~TaskManagerBackgroundContentsResource(); + + // TaskManager::Resource methods: + virtual std::wstring GetTitle() const; + virtual SkBitmap GetIcon() const; + virtual bool IsBackground() const; + + const std::wstring& application_name() const { return application_name_; } + private: + BackgroundContents* background_contents_; + + std::wstring application_name_; + + // The icon painted for BackgroundContents. + // TODO(atwilson): Use the favicon when there's a way to get the favicon for + // BackgroundContents. + static SkBitmap* default_icon_; + + DISALLOW_COPY_AND_ASSIGN(TaskManagerBackgroundContentsResource); +}; + +class TaskManagerBackgroundContentsResourceProvider + : public TaskManager::ResourceProvider, + public NotificationObserver { + public: + explicit TaskManagerBackgroundContentsResourceProvider( + TaskManager* task_manager); + + virtual TaskManager::Resource* GetResource(int origin_pid, + int render_process_host_id, + int routing_id); + virtual void StartUpdating(); + virtual void StopUpdating(); + + // NotificationObserver method: + virtual void Observe(NotificationType type, + const NotificationSource& source, + const NotificationDetails& details); + + private: + virtual ~TaskManagerBackgroundContentsResourceProvider(); + + void Add(BackgroundContents* background_contents, const std::wstring& title); + void Remove(BackgroundContents* background_contents); + + void AddToTaskManager(BackgroundContents* background_contents, + const std::wstring& title); + + // Whether we are currently reporting to the task manager. Used to ignore + // notifications sent after StopUpdating(). + bool updating_; + + TaskManager* task_manager_; + + // Maps the actual resources (the BackgroundContents) to the Task Manager + // resources. + std::map<BackgroundContents*, TaskManagerBackgroundContentsResource*> + resources_; + + // A scoped container for notification registries. + NotificationRegistrar registrar_; + + DISALLOW_COPY_AND_ASSIGN(TaskManagerBackgroundContentsResourceProvider); +}; + class TaskManagerChildProcessResource : public TaskManager::Resource { public: explicit TaskManagerChildProcessResource(const ChildProcessInfo& child_proc); @@ -221,6 +310,8 @@ class TaskManagerExtensionProcessResource : public TaskManager::Resource { // Returns the pid of the extension process. int process_id() const { return pid_; } + // Returns true if the associated extension has a background page. + bool IsBackground() const; private: // The icon painted for the extension process. static SkBitmap* default_icon_; |