// 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_resource_providers.h" #include "base/basictypes.h" #include "base/file_version_info.h" #include "base/i18n/rtl.h" #include "base/process_util.h" #include "base/stl_util-inl.h" #include "base/string_util.h" #include "base/threading/thread.h" #include "base/utf_string_conversions.h" #include "build/build_config.h" #include "chrome/app/chrome_command_ids.h" #include "chrome/browser/background_contents_service.h" #include "chrome/browser/background_contents_service_factory.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/extensions/extension_host.h" #include "chrome/browser/extensions/extension_process_manager.h" #include "chrome/browser/extensions/extension_service.h" #include "chrome/browser/notifications/balloon_collection.h" #include "chrome/browser/notifications/balloon_host.h" #include "chrome/browser/notifications/notification_ui_manager.h" #include "chrome/browser/prerender/prerender_contents.h" #include "chrome/browser/prerender/prerender_manager.h" #include "chrome/browser/profiles/profile_manager.h" #include "chrome/browser/tab_contents/background_contents.h" #include "chrome/browser/tab_contents/tab_util.h" #include "chrome/browser/ui/browser_list.h" #include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h" #include "chrome/common/extensions/extension.h" #include "chrome/common/render_messages.h" #include "content/browser/browser_child_process_host.h" #include "content/browser/browser_thread.h" #include "content/browser/renderer_host/render_message_filter.h" #include "content/browser/renderer_host/render_process_host.h" #include "content/browser/renderer_host/render_view_host.h" #include "content/browser/tab_contents/tab_contents.h" #include "content/common/notification_service.h" #include "grit/generated_resources.h" #include "grit/theme_resources.h" #include "third_party/sqlite/sqlite3.h" #include "ui/base/l10n/l10n_util.h" #include "ui/base/resource/resource_bundle.h" #if defined(OS_MACOSX) #include "skia/ext/skia_utils_mac.h" #endif #if defined(OS_WIN) #include "chrome/browser/app_icon_win.h" #include "ui/gfx/icon_util.h" #endif // defined(OS_WIN) namespace { // Returns the appropriate message prefix ID for tabs and extensions, // reflecting whether they are apps or in incognito mode. int GetMessagePrefixID(bool is_app, bool is_extension, bool is_incognito) { return is_app ? (is_incognito ? IDS_TASK_MANAGER_APP_INCOGNITO_PREFIX : IDS_TASK_MANAGER_APP_PREFIX) : (is_extension ? (is_incognito ? IDS_TASK_MANAGER_EXTENSION_INCOGNITO_PREFIX : IDS_TASK_MANAGER_EXTENSION_PREFIX) : IDS_TASK_MANAGER_TAB_PREFIX); } } // namespace //////////////////////////////////////////////////////////////////////////////// // TaskManagerRendererResource class //////////////////////////////////////////////////////////////////////////////// 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 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; stats_.scripts.size = 0; stats_.xslStyleSheets.size = 0; stats_.fonts.size = 0; } TaskManagerRendererResource::~TaskManagerRendererResource() { } void TaskManagerRendererResource::Refresh() { if (!pending_stats_update_) { render_view_host_->Send(new ViewMsg_GetCacheResourceStats); pending_stats_update_ = true; } if (!pending_v8_memory_allocated_update_) { render_view_host_->Send(new ViewMsg_GetV8HeapStats); pending_v8_memory_allocated_update_ = true; } } WebKit::WebCache::ResourceTypeStats TaskManagerRendererResource::GetWebCoreCacheStats() const { return stats_; } size_t TaskManagerRendererResource::GetV8MemoryAllocated() const { return v8_memory_allocated_; } size_t TaskManagerRendererResource::GetV8MemoryUsed() const { return v8_memory_used_; } void TaskManagerRendererResource::NotifyResourceTypeStats( const WebKit::WebCache::ResourceTypeStats& stats) { stats_ = stats; pending_stats_update_ = false; } 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; } base::ProcessHandle TaskManagerRendererResource::GetProcess() const { return process_; } TaskManager::Resource::Type TaskManagerRendererResource::GetType() const { return RENDERER; } bool TaskManagerRendererResource::ReportsCacheStats() const { return true; } bool TaskManagerRendererResource::ReportsV8MemoryStats() const { return true; } bool TaskManagerRendererResource::SupportNetworkUsage() const { return true; } //////////////////////////////////////////////////////////////////////////////// // TaskManagerTabContentsResource class //////////////////////////////////////////////////////////////////////////////// TaskManagerTabContentsResource::TaskManagerTabContentsResource( TabContentsWrapper* tab_contents) : TaskManagerRendererResource( tab_contents->tab_contents()->GetRenderProcessHost()->GetHandle(), tab_contents->render_view_host()), tab_contents_(tab_contents) { } TaskManagerTabContentsResource::~TaskManagerTabContentsResource() { } TaskManager::Resource::Type TaskManagerTabContentsResource::GetType() const { return tab_contents_->tab_contents()->HostsExtension() ? EXTENSION : RENDERER; } string16 TaskManagerTabContentsResource::GetTitle() const { // Fall back on the URL if there's no title. string16 tab_title = tab_contents_->tab_contents()->GetTitle(); if (tab_title.empty()) { tab_title = UTF8ToUTF16(tab_contents_->tab_contents()->GetURL().spec()); // Force URL to be LTR. tab_title = base::i18n::GetDisplayStringInLTRDirectionality(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); } ExtensionService* extensions_service = tab_contents_->profile()->GetExtensionService(); int message_id = GetMessagePrefixID( extensions_service->IsInstalledApp( tab_contents_->tab_contents()->GetURL()), tab_contents_->tab_contents()->HostsExtension(), tab_contents_->profile()->IsOffTheRecord()); return l10n_util::GetStringFUTF16(message_id, tab_title); } SkBitmap TaskManagerTabContentsResource::GetIcon() const { return tab_contents_->tab_contents()->GetFavicon(); } TabContentsWrapper* TaskManagerTabContentsResource::GetTabContents() const { return tab_contents_; } const Extension* TaskManagerTabContentsResource::GetExtension() const { if (tab_contents_->tab_contents()->HostsExtension()) { ExtensionService* extensions_service = tab_contents_->profile()->GetExtensionService(); return extensions_service->GetExtensionByURL( tab_contents_->tab_contents()->GetURL()); } return NULL; } //////////////////////////////////////////////////////////////////////////////// // TaskManagerTabContentsResourceProvider class //////////////////////////////////////////////////////////////////////////////// TaskManagerTabContentsResourceProvider:: TaskManagerTabContentsResourceProvider(TaskManager* task_manager) : updating_(false), task_manager_(task_manager) { } TaskManagerTabContentsResourceProvider:: ~TaskManagerTabContentsResourceProvider() { } TaskManager::Resource* TaskManagerTabContentsResourceProvider::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; // If an origin PID was specified then the request originated in a plugin // working on the TabContent's behalf, so ignore it. if (origin_pid) return NULL; TabContentsWrapper* wrapper = TabContentsWrapper::GetCurrentWrapperForContents(tab_contents); std::map<TabContentsWrapper*, TaskManagerTabContentsResource*>::iterator res_iter = resources_.find(wrapper); 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 TaskManagerTabContentsResourceProvider::StartUpdating() { DCHECK(!updating_); updating_ = true; // Add all the existing TabContents. for (TabContentsIterator iterator; !iterator.done(); ++iterator) Add(*iterator); // Then we register for notifications to get new tabs. registrar_.Add(this, NotificationType::TAB_CONTENTS_CONNECTED, NotificationService::AllSources()); registrar_.Add(this, NotificationType::TAB_CONTENTS_SWAPPED, NotificationService::AllSources()); registrar_.Add(this, NotificationType::TAB_CONTENTS_DISCONNECTED, NotificationService::AllSources()); // TAB_CONTENTS_DISCONNECTED should be enough to know when to remove a // resource. This is an attempt at mitigating a crasher that seem to // indicate a resource is still referencing a deleted TabContents // (http://crbug.com/7321). registrar_.Add(this, NotificationType::TAB_CONTENTS_DESTROYED, NotificationService::AllSources()); } void TaskManagerTabContentsResourceProvider::StopUpdating() { DCHECK(updating_); updating_ = false; // Then we unregister for notifications to get new tabs. registrar_.Remove(this, NotificationType::TAB_CONTENTS_CONNECTED, NotificationService::AllSources()); registrar_.Remove(this, NotificationType::TAB_CONTENTS_SWAPPED, NotificationService::AllSources()); registrar_.Remove(this, NotificationType::TAB_CONTENTS_DISCONNECTED, NotificationService::AllSources()); registrar_.Remove(this, NotificationType::TAB_CONTENTS_DESTROYED, NotificationService::AllSources()); // Delete all the resources. STLDeleteContainerPairSecondPointers(resources_.begin(), resources_.end()); resources_.clear(); } void TaskManagerTabContentsResourceProvider::AddToTaskManager( TabContentsWrapper* tab_contents) { TaskManagerTabContentsResource* resource = new TaskManagerTabContentsResource(tab_contents); resources_[tab_contents] = resource; task_manager_->AddResource(resource); } void TaskManagerTabContentsResourceProvider::Add( TabContentsWrapper* tab_contents) { if (!updating_) return; // Don't add dead tabs or tabs that haven't yet connected. if (!tab_contents->tab_contents()->GetRenderProcessHost()->GetHandle() || !tab_contents->tab_contents()->notify_disconnection()) { return; } std::map<TabContentsWrapper*, TaskManagerTabContentsResource*>::const_iterator iter = resources_.find(tab_contents); if (iter != resources_.end()) { // The case may happen that we have added a TabContents 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(tab_contents); } void TaskManagerTabContentsResourceProvider::Remove( TabContentsWrapper* tab_contents) { if (!updating_) return; std::map<TabContentsWrapper*, TaskManagerTabContentsResource*>::iterator iter = resources_.find(tab_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. TaskManagerTabContentsResource* resource = iter->second; task_manager_->RemoveResource(resource); // And from the provider. resources_.erase(iter); // Finally, delete the resource. delete resource; } void TaskManagerTabContentsResourceProvider::Observe(NotificationType type, const NotificationSource& source, const NotificationDetails& details) { TabContentsWrapper* tab_contents = TabContentsWrapper::GetCurrentWrapperForContents( Source<TabContents>(source).ptr()); // A background page does not have a TabContentsWrapper. if (!tab_contents) return; switch (type.value) { case NotificationType::TAB_CONTENTS_CONNECTED: Add(tab_contents); break; case NotificationType::TAB_CONTENTS_SWAPPED: Remove(tab_contents); Add(tab_contents); break; case NotificationType::TAB_CONTENTS_DESTROYED: // If this DCHECK is triggered, it could explain http://crbug.com/7321 . DCHECK(resources_.find(tab_contents) == resources_.end()) << "TAB_CONTENTS_DESTROYED with no associated " "TAB_CONTENTS_DISCONNECTED"; // Fall through. case NotificationType::TAB_CONTENTS_DISCONNECTED: Remove(tab_contents); break; default: NOTREACHED() << "Unexpected notification."; return; } } //////////////////////////////////////////////////////////////////////////////// // TaskManagerPrerenderResource class //////////////////////////////////////////////////////////////////////////////// // static SkBitmap* TaskManagerPrerenderResource::default_icon_ = NULL; TaskManagerPrerenderResource::TaskManagerPrerenderResource( RenderViewHost* render_view_host) : TaskManagerRendererResource( render_view_host->process()->GetHandle(), render_view_host), process_route_id_pair_(std::make_pair(render_view_host->process()->id(), render_view_host->routing_id())) { if (!default_icon_) { ResourceBundle& rb = ResourceBundle::GetSharedInstance(); default_icon_ = rb.GetBitmapNamed(IDR_PRERENDER); } } TaskManagerPrerenderResource::~TaskManagerPrerenderResource() { } TaskManager::Resource::Type TaskManagerPrerenderResource::GetType() const { return RENDERER; } string16 TaskManagerPrerenderResource::GetTitle() const { // The URL is used as the title. // TODO(dominich): Expose document title through RenderHostDelegate. // http://crbug.com/77776 RenderViewHost* render_view_host = RenderViewHost::FromID(process_route_id_pair_.first, process_route_id_pair_.second); // In some instances, for instance when the RenderProcessHost has been // destroyed, we try to get the title for a RenderViewHost that has // been removed. Return an empty string in this case. if (!render_view_host) return EmptyString16(); RenderViewHostDelegate* delegate = render_view_host->delegate(); string16 title = UTF8ToUTF16(delegate->GetURL().spec()); // Force URL to be LTR. title = base::i18n::GetDisplayStringInLTRDirectionality(title); int message_id = IDS_TASK_MANAGER_PRERENDER_PREFIX; return l10n_util::GetStringFUTF16(message_id, title); } SkBitmap TaskManagerPrerenderResource::GetIcon() const { // TODO(dominich): use the favicon if available. // http://crbug.com/77782 return *default_icon_; } //////////////////////////////////////////////////////////////////////////////// // TaskManagerPrerenderResourceProvider class //////////////////////////////////////////////////////////////////////////////// TaskManagerPrerenderResourceProvider::TaskManagerPrerenderResourceProvider( TaskManager* task_manager) : updating_(false), task_manager_(task_manager) { } TaskManagerPrerenderResourceProvider::~TaskManagerPrerenderResourceProvider() { STLDeleteContainerPairSecondPointers(resources_.begin(), resources_.end()); } TaskManager::Resource* TaskManagerPrerenderResourceProvider::GetResource( int origin_pid, int render_process_host_id, int routing_id) { // If an origin PID was specified then the request originated in a plugin so // ignore it. if (origin_pid) return NULL; ResourceMap::iterator res_iter = resources_.find( std::make_pair(render_process_host_id, routing_id)); if (res_iter == resources_.end()) return NULL; return res_iter->second; } void TaskManagerPrerenderResourceProvider::StartUpdating() { DCHECK(!updating_); updating_ = true; // Add all the existing PrerenderContents. const ResourceDispatcherHost* resource_dispatcher_host = g_browser_process->resource_dispatcher_host(); const ResourceDispatcherHost::PrerenderChildRouteIdPairs& prerender_child_route_id_pairs = resource_dispatcher_host->prerender_child_route_id_pairs(); for (ResourceDispatcherHost::PrerenderChildRouteIdPairs::const_iterator it = prerender_child_route_id_pairs.begin(); it != prerender_child_route_id_pairs.end(); ++it) { Add(*it); } // Then we register for notifications to get new prerender items. registrar_.Add(this, NotificationType::PRERENDER_CONTENTS_STARTED, NotificationService::AllSources()); registrar_.Add(this, NotificationType::PRERENDER_CONTENTS_USED, NotificationService::AllSources()); registrar_.Add(this, NotificationType::PRERENDER_CONTENTS_DESTROYED, NotificationService::AllSources()); } void TaskManagerPrerenderResourceProvider::StopUpdating() { DCHECK(updating_); updating_ = false; // Then we unregister for notifications to get new prerender items. registrar_.Remove(this, NotificationType::PRERENDER_CONTENTS_STARTED, NotificationService::AllSources()); registrar_.Remove(this, NotificationType::PRERENDER_CONTENTS_USED, NotificationService::AllSources()); registrar_.Remove(this, NotificationType::PRERENDER_CONTENTS_DESTROYED, NotificationService::AllSources()); // Delete all the resources. STLDeleteContainerPairSecondPointers(resources_.begin(), resources_.end()); resources_.clear(); } void TaskManagerPrerenderResourceProvider::AddToTaskManager( const std::pair<int, int>& process_route_id_pair) { RenderViewHost* render_view_host = RenderViewHost::FromID(process_route_id_pair.first, process_route_id_pair.second); CHECK(render_view_host); TaskManagerPrerenderResource* resource = new TaskManagerPrerenderResource(render_view_host); resources_[process_route_id_pair] = resource; task_manager_->AddResource(resource); } void TaskManagerPrerenderResourceProvider::Add( const std::pair<int, int>& process_route_id_pair) { if (!updating_) return; // Don't add dead prerender contents or prerender contents that haven't yet // started. RenderViewHost* render_view_host = RenderViewHost::FromID(process_route_id_pair.first, process_route_id_pair.second); if (!render_view_host) return; AddToTaskManager(process_route_id_pair); } void TaskManagerPrerenderResourceProvider::Remove( const std::pair<int, int>& process_route_id_pair) { if (!updating_) return; RenderViewHost* render_view_host = RenderViewHost::FromID(process_route_id_pair.first, process_route_id_pair.second); if (!render_view_host) { // This will happen if the PrerenderContents was used. We should have had a // PRERENDER_CONTENTS_USED message about it and already removed it, but // either way we can't remove a NULL resource. return; } ResourceMap::iterator iter = resources_.find(process_route_id_pair); DCHECK(iter != resources_.end()); // Remove the resource from the Task Manager. TaskManagerPrerenderResource* resource = iter->second; task_manager_->RemoveResource(resource); // And from the provider. resources_.erase(iter); // Finally, delete the resource. delete resource; } void TaskManagerPrerenderResourceProvider::Observe( NotificationType type, const NotificationSource& source, const NotificationDetails& details) { DCHECK(NotificationService::NoDetails() == details); switch (type.value) { case NotificationType::PRERENDER_CONTENTS_STARTED: Add(*Source<std::pair<int, int> >(source).ptr()); break; case NotificationType::PRERENDER_CONTENTS_USED: case NotificationType::PRERENDER_CONTENTS_DESTROYED: Remove(*Source<std::pair<int, int> >(source).ptr()); break; default: NOTREACHED() << "Unexpected notification."; return; } } //////////////////////////////////////////////////////////////////////////////// // TaskManagerBackgroundContentsResource class //////////////////////////////////////////////////////////////////////////////// SkBitmap* TaskManagerBackgroundContentsResource::default_icon_ = NULL; TaskManagerBackgroundContentsResource::TaskManagerBackgroundContentsResource( BackgroundContents* background_contents, const string16& 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_); } TaskManagerBackgroundContentsResource::~TaskManagerBackgroundContentsResource( ) { } string16 TaskManagerBackgroundContentsResource::GetTitle() const { string16 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 = base::i18n::GetDisplayStringInLTRDirectionality( UTF8ToUTF16(background_contents_->GetURL().spec())); } return l10n_util::GetStringFUTF16(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; // If an origin PID was specified, the request is from a plugin, not the // render view host process if (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(); std::vector<Profile*> profiles(profile_manager->GetLoadedProfiles()); for (size_t i = 0; i < profiles.size(); ++i) { BackgroundContentsService* background_contents_service = BackgroundContentsServiceFactory::GetForProfile(profiles[i]); ExtensionService* extensions_service = profiles[i]->GetExtensionService(); std::vector<BackgroundContents*> contents = background_contents_service->GetBackgroundContents(); for (std::vector<BackgroundContents*>::iterator iterator = contents.begin(); iterator != contents.end(); ++iterator) { string16 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 = UTF8ToUTF16(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 string16& application_name) { TaskManagerBackgroundContentsResource* resource = new TaskManagerBackgroundContentsResource(background_contents, application_name); resources_[background_contents] = resource; task_manager_->AddResource(resource); } void TaskManagerBackgroundContentsResourceProvider::Add( BackgroundContents* contents, const string16& 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. string16 application_name; ExtensionService* service = Source<Profile>(source)->GetExtensionService(); 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 = UTF8ToUTF16(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. string16 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; TaskManagerChildProcessResource::TaskManagerChildProcessResource( const ChildProcessInfo& child_proc) : child_process_(child_proc), title_(), network_usage_support_(false) { // 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.pid(); if (!default_icon_) { ResourceBundle& rb = ResourceBundle::GetSharedInstance(); default_icon_ = rb.GetBitmapNamed(IDR_PLUGIN); // TODO(jabdelmalek): use different icon for web workers. } } TaskManagerChildProcessResource::~TaskManagerChildProcessResource() { } // TaskManagerResource methods: string16 TaskManagerChildProcessResource::GetTitle() const { if (title_.empty()) title_ = GetLocalizedTitle(); return title_; } SkBitmap TaskManagerChildProcessResource::GetIcon() const { return *default_icon_; } base::ProcessHandle TaskManagerChildProcessResource::GetProcess() const { return child_process_.handle(); } 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: 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; case ChildProcessInfo::UTILITY_PROCESS: return TaskManager::Resource::UTILITY; case ChildProcessInfo::PROFILE_IMPORT_PROCESS: return TaskManager::Resource::PROFILE_IMPORT; case ChildProcessInfo::ZYGOTE_PROCESS: return TaskManager::Resource::ZYGOTE; case ChildProcessInfo::SANDBOX_HELPER_PROCESS: return TaskManager::Resource::SANDBOX_HELPER; case ChildProcessInfo::GPU_PROCESS: return TaskManager::Resource::GPU; default: return TaskManager::Resource::UNKNOWN; } } bool TaskManagerChildProcessResource::SupportNetworkUsage() const { return network_usage_support_; } void TaskManagerChildProcessResource::SetSupportNetworkUsage() { network_usage_support_ = true; } string16 TaskManagerChildProcessResource::GetLocalizedTitle() const { string16 title = WideToUTF16Hack(child_process_.name()); if (child_process_.type() == ChildProcessInfo::PLUGIN_PROCESS && title.empty()) { title = l10n_util::GetStringUTF16(IDS_TASK_MANAGER_UNKNOWN_PLUGIN_NAME); } // 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". base::i18n::AdjustStringForLocaleDirection(&title); switch (child_process_.type()) { case ChildProcessInfo::UTILITY_PROCESS: return l10n_util::GetStringUTF16(IDS_TASK_MANAGER_UTILITY_PREFIX); case ChildProcessInfo::PROFILE_IMPORT_PROCESS: return l10n_util::GetStringUTF16(IDS_TASK_MANAGER_UTILITY_PREFIX); case ChildProcessInfo::GPU_PROCESS: return l10n_util::GetStringUTF16(IDS_TASK_MANAGER_GPU_PREFIX); case ChildProcessInfo::NACL_BROKER_PROCESS: return l10n_util::GetStringUTF16(IDS_TASK_MANAGER_NACL_BROKER_PREFIX); case ChildProcessInfo::PLUGIN_PROCESS: case ChildProcessInfo::PPAPI_PLUGIN_PROCESS: case ChildProcessInfo::PPAPI_BROKER_PROCESS: { return l10n_util::GetStringFUTF16( IDS_TASK_MANAGER_PLUGIN_PREFIX, title, WideToUTF16Hack(child_process_.version())); } 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: case ChildProcessInfo::ZYGOTE_PROCESS: case ChildProcessInfo::SANDBOX_HELPER_PROCESS: NOTREACHED(); break; case ChildProcessInfo::UNKNOWN_PROCESS: NOTREACHED() << "Need localized name for child process type."; } return title; } //////////////////////////////////////////////////////////////////////////////// // TaskManagerChildProcessResourceProvider class //////////////////////////////////////////////////////////////////////////////// TaskManagerChildProcessResourceProvider:: TaskManagerChildProcessResourceProvider(TaskManager* task_manager) : updating_(false), task_manager_(task_manager) { } TaskManagerChildProcessResourceProvider:: ~TaskManagerChildProcessResourceProvider() { } TaskManager::Resource* TaskManagerChildProcessResourceProvider::GetResource( int origin_pid, int render_process_host_id, int routing_id) { std::map<int, TaskManagerChildProcessResource*>::iterator iter = pid_to_resources_.find(origin_pid); if (iter != pid_to_resources_.end()) return iter->second; else return NULL; } void TaskManagerChildProcessResourceProvider::StartUpdating() { DCHECK(!updating_); updating_ = true; // Register for notifications to get new child processes. registrar_.Add(this, NotificationType::CHILD_PROCESS_HOST_CONNECTED, NotificationService::AllSources()); registrar_.Add(this, NotificationType::CHILD_PROCESS_HOST_DISCONNECTED, NotificationService::AllSources()); // Get the existing child processes. BrowserThread::PostTask( BrowserThread::IO, FROM_HERE, NewRunnableMethod( this, &TaskManagerChildProcessResourceProvider::RetrieveChildProcessInfo)); } void TaskManagerChildProcessResourceProvider::StopUpdating() { DCHECK(updating_); updating_ = false; // Unregister for notifications to get new plugin processes. registrar_.Remove(this, NotificationType::CHILD_PROCESS_HOST_CONNECTED, NotificationService::AllSources()); registrar_.Remove(this, NotificationType::CHILD_PROCESS_HOST_DISCONNECTED, NotificationService::AllSources()); // Delete all the resources. STLDeleteContainerPairSecondPointers(resources_.begin(), resources_.end()); resources_.clear(); pid_to_resources_.clear(); existing_child_process_info_.clear(); } void TaskManagerChildProcessResourceProvider::Observe( NotificationType type, const NotificationSource& source, const NotificationDetails& details) { switch (type.value) { case NotificationType::CHILD_PROCESS_HOST_CONNECTED: Add(*Details<ChildProcessInfo>(details).ptr()); break; case NotificationType::CHILD_PROCESS_HOST_DISCONNECTED: Remove(*Details<ChildProcessInfo>(details).ptr()); break; default: NOTREACHED() << "Unexpected notification."; return; } } void TaskManagerChildProcessResourceProvider::Add( const ChildProcessInfo& child_process_info) { if (!updating_) return; 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 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(child_process_info); } void TaskManagerChildProcessResourceProvider::Remove( const ChildProcessInfo& child_process_info) { if (!updating_) return; std::map<ChildProcessInfo, TaskManagerChildProcessResource*> ::iterator iter = resources_.find(child_process_info); if (iter == resources_.end()) { // 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. 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, 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()) pid_to_resources_.erase(pid_iter); // Finally, delete the resource. delete resource; } void TaskManagerChildProcessResourceProvider::AddToTaskManager( const 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 ChildProcessInfo::Iterator has to be used from the IO thread. void TaskManagerChildProcessResourceProvider::RetrieveChildProcessInfo() { for (BrowserChildProcessHost::Iterator iter; !iter.Done(); ++iter) { // Only add processes which are already started, since we need their handle. if ((*iter)->handle() != base::kNullProcessHandle) existing_child_process_info_.push_back(**iter); } // Now notify the UI thread that we have retrieved information about child // processes. BrowserThread::PostTask( BrowserThread::UI, FROM_HERE, NewRunnableMethod(this, &TaskManagerChildProcessResourceProvider::ChildProcessInfoRetreived)); } // This is called on the UI thread. 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_child_process_info_.clear(); } //////////////////////////////////////////////////////////////////////////////// // TaskManagerExtensionProcessResource class //////////////////////////////////////////////////////////////////////////////// SkBitmap* TaskManagerExtensionProcessResource::default_icon_ = NULL; TaskManagerExtensionProcessResource::TaskManagerExtensionProcessResource( ExtensionHost* extension_host) : extension_host_(extension_host) { if (!default_icon_) { ResourceBundle& rb = ResourceBundle::GetSharedInstance(); default_icon_ = rb.GetBitmapNamed(IDR_PLUGIN); } process_handle_ = extension_host_->render_process_host()->GetHandle(); pid_ = base::GetProcId(process_handle_); string16 extension_name = UTF8ToUTF16(GetExtension()->name()); DCHECK(!extension_name.empty()); int message_id = GetMessagePrefixID(GetExtension()->is_app(), true, extension_host_->profile()->IsOffTheRecord()); title_ = l10n_util::GetStringFUTF16(message_id, extension_name); } TaskManagerExtensionProcessResource::~TaskManagerExtensionProcessResource() { } string16 TaskManagerExtensionProcessResource::GetTitle() const { return title_; } SkBitmap TaskManagerExtensionProcessResource::GetIcon() const { return *default_icon_; } base::ProcessHandle TaskManagerExtensionProcessResource::GetProcess() const { return process_handle_; } TaskManager::Resource::Type TaskManagerExtensionProcessResource::GetType() const { return EXTENSION; } bool TaskManagerExtensionProcessResource::SupportNetworkUsage() const { return true; } void TaskManagerExtensionProcessResource::SetSupportNetworkUsage() { NOTREACHED(); } const Extension* TaskManagerExtensionProcessResource::GetExtension() const { return extension_host_->extension(); } bool TaskManagerExtensionProcessResource::IsBackground() const { return extension_host_->GetRenderViewType() == ViewType::EXTENSION_BACKGROUND_PAGE; } //////////////////////////////////////////////////////////////////////////////// // TaskManagerExtensionProcessResourceProvider class //////////////////////////////////////////////////////////////////////////////// TaskManagerExtensionProcessResourceProvider:: TaskManagerExtensionProcessResourceProvider(TaskManager* task_manager) : task_manager_(task_manager), updating_(false) { } TaskManagerExtensionProcessResourceProvider:: ~TaskManagerExtensionProcessResourceProvider() { } TaskManager::Resource* TaskManagerExtensionProcessResourceProvider::GetResource( int origin_pid, int render_process_host_id, int routing_id) { std::map<int, TaskManagerExtensionProcessResource*>::iterator iter = pid_to_resources_.find(origin_pid); if (iter != pid_to_resources_.end()) return iter->second; else return NULL; } void TaskManagerExtensionProcessResourceProvider::StartUpdating() { DCHECK(!updating_); updating_ = true; // Add all the existing ExtensionHosts. ProfileManager* profile_manager = g_browser_process->profile_manager(); std::vector<Profile*> profiles(profile_manager->GetLoadedProfiles()); for (size_t i = 0; i < profiles.size(); ++i) { ExtensionProcessManager* process_manager = profiles[i]->GetExtensionProcessManager(); if (process_manager) { ExtensionProcessManager::const_iterator jt; for (jt = process_manager->begin(); jt != process_manager->end(); ++jt) AddToTaskManager(*jt); } // If we have an incognito profile active, include the split-mode incognito // extensions. if (BrowserList::IsOffTheRecordSessionActive()) { ExtensionProcessManager* process_manager = profiles[i]->GetOffTheRecordProfile()->GetExtensionProcessManager(); if (process_manager) { ExtensionProcessManager::const_iterator jt; for (jt = process_manager->begin(); jt != process_manager->end(); ++jt) AddToTaskManager(*jt); } } } // Register for notifications about extension process changes. registrar_.Add(this, NotificationType::EXTENSION_PROCESS_CREATED, NotificationService::AllSources()); registrar_.Add(this, NotificationType::EXTENSION_PROCESS_TERMINATED, NotificationService::AllSources()); registrar_.Add(this, NotificationType::EXTENSION_HOST_DESTROYED, NotificationService::AllSources()); } void TaskManagerExtensionProcessResourceProvider::StopUpdating() { DCHECK(updating_); updating_ = false; // Unregister for notifications about extension process changes. registrar_.Remove(this, NotificationType::EXTENSION_PROCESS_CREATED, NotificationService::AllSources()); registrar_.Remove(this, NotificationType::EXTENSION_PROCESS_TERMINATED, NotificationService::AllSources()); registrar_.Remove(this, NotificationType::EXTENSION_HOST_DESTROYED, NotificationService::AllSources()); // Delete all the resources. STLDeleteContainerPairSecondPointers(resources_.begin(), resources_.end()); resources_.clear(); pid_to_resources_.clear(); } void TaskManagerExtensionProcessResourceProvider::Observe( NotificationType type, const NotificationSource& source, const NotificationDetails& details) { switch (type.value) { case NotificationType::EXTENSION_PROCESS_CREATED: AddToTaskManager(Details<ExtensionHost>(details).ptr()); break; case NotificationType::EXTENSION_PROCESS_TERMINATED: case NotificationType::EXTENSION_HOST_DESTROYED: RemoveFromTaskManager(Details<ExtensionHost>(details).ptr()); break; default: NOTREACHED() << "Unexpected notification."; return; } } void TaskManagerExtensionProcessResourceProvider::AddToTaskManager( ExtensionHost* extension_host) { // Don't add dead extension processes. if (!extension_host->IsRenderViewLive()) return; TaskManagerExtensionProcessResource* resource = new TaskManagerExtensionProcessResource(extension_host); DCHECK(resources_.find(extension_host) == resources_.end()); resources_[extension_host] = resource; pid_to_resources_[resource->process_id()] = resource; task_manager_->AddResource(resource); } void TaskManagerExtensionProcessResourceProvider::RemoveFromTaskManager( ExtensionHost* extension_host) { if (!updating_) return; std::map<ExtensionHost*, TaskManagerExtensionProcessResource*> ::iterator iter = resources_.find(extension_host); if (iter == resources_.end()) return; // Remove the resource from the Task Manager. TaskManagerExtensionProcessResource* resource = iter->second; task_manager_->RemoveResource(resource); // Remove it from the provider. resources_.erase(iter); // Remove it from our pid map. std::map<int, TaskManagerExtensionProcessResource*>::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; } //////////////////////////////////////////////////////////////////////////////// // TaskManagerNotificationResource class //////////////////////////////////////////////////////////////////////////////// SkBitmap* TaskManagerNotificationResource::default_icon_ = NULL; TaskManagerNotificationResource::TaskManagerNotificationResource( BalloonHost* balloon_host) : balloon_host_(balloon_host) { if (!default_icon_) { ResourceBundle& rb = ResourceBundle::GetSharedInstance(); default_icon_ = rb.GetBitmapNamed(IDR_PLUGIN); } process_handle_ = balloon_host_->render_view_host()->process()->GetHandle(); pid_ = base::GetProcId(process_handle_); title_ = l10n_util::GetStringFUTF16(IDS_TASK_MANAGER_NOTIFICATION_PREFIX, balloon_host_->GetSource()); } TaskManagerNotificationResource::~TaskManagerNotificationResource() { } string16 TaskManagerNotificationResource::GetTitle() const { return title_; } SkBitmap TaskManagerNotificationResource::GetIcon() const { return *default_icon_; } base::ProcessHandle TaskManagerNotificationResource::GetProcess() const { return process_handle_; } TaskManager::Resource::Type TaskManagerNotificationResource::GetType() const { return NOTIFICATION; } bool TaskManagerNotificationResource::SupportNetworkUsage() const { return false; } //////////////////////////////////////////////////////////////////////////////// // TaskManagerNotificationResourceProvider class //////////////////////////////////////////////////////////////////////////////// TaskManagerNotificationResourceProvider:: TaskManagerNotificationResourceProvider(TaskManager* task_manager) : task_manager_(task_manager), updating_(false) { } TaskManagerNotificationResourceProvider:: ~TaskManagerNotificationResourceProvider() { } TaskManager::Resource* TaskManagerNotificationResourceProvider::GetResource( int origin_pid, int render_process_host_id, int routing_id) { // TODO(johnnyg): provide resources by pid if necessary. return NULL; } void TaskManagerNotificationResourceProvider::StartUpdating() { DCHECK(!updating_); updating_ = true; // Add all the existing BalloonHosts. BalloonCollection* collection = g_browser_process->notification_ui_manager()->balloon_collection(); const BalloonCollection::Balloons& balloons = collection->GetActiveBalloons(); for (BalloonCollection::Balloons::const_iterator it = balloons.begin(); it != balloons.end(); ++it) { AddToTaskManager((*it)->view()->GetHost()); } // Register for notifications about extension process changes. registrar_.Add(this, NotificationType::NOTIFY_BALLOON_CONNECTED, NotificationService::AllSources()); registrar_.Add(this, NotificationType::NOTIFY_BALLOON_DISCONNECTED, NotificationService::AllSources()); } void TaskManagerNotificationResourceProvider::StopUpdating() { DCHECK(updating_); updating_ = false; // Unregister for notifications about extension process changes. registrar_.Remove(this, NotificationType::NOTIFY_BALLOON_CONNECTED, NotificationService::AllSources()); registrar_.Remove(this, NotificationType::NOTIFY_BALLOON_DISCONNECTED, NotificationService::AllSources()); // Delete all the resources. STLDeleteContainerPairSecondPointers(resources_.begin(), resources_.end()); resources_.clear(); } void TaskManagerNotificationResourceProvider::Observe( NotificationType type, const NotificationSource& source, const NotificationDetails& details) { switch (type.value) { case NotificationType::NOTIFY_BALLOON_CONNECTED: AddToTaskManager(Source<BalloonHost>(source).ptr()); break; case NotificationType::NOTIFY_BALLOON_DISCONNECTED: RemoveFromTaskManager(Source<BalloonHost>(source).ptr()); break; default: NOTREACHED() << "Unexpected notification."; return; } } void TaskManagerNotificationResourceProvider::AddToTaskManager( BalloonHost* balloon_host) { TaskManagerNotificationResource* resource = new TaskManagerNotificationResource(balloon_host); DCHECK(resources_.find(balloon_host) == resources_.end()); resources_[balloon_host] = resource; task_manager_->AddResource(resource); } void TaskManagerNotificationResourceProvider::RemoveFromTaskManager( BalloonHost* balloon_host) { if (!updating_) return; std::map<BalloonHost*, TaskManagerNotificationResource*>::iterator iter = resources_.find(balloon_host); if (iter == resources_.end()) return; // Remove the resource from the Task Manager. TaskManagerNotificationResource* resource = iter->second; task_manager_->RemoveResource(resource); // Remove it from the map. resources_.erase(iter); // Finally, delete the resource. delete resource; } //////////////////////////////////////////////////////////////////////////////// // TaskManagerBrowserProcessResource class //////////////////////////////////////////////////////////////////////////////// SkBitmap* TaskManagerBrowserProcessResource::default_icon_ = NULL; TaskManagerBrowserProcessResource::TaskManagerBrowserProcessResource() : title_() { int pid = base::GetCurrentProcId(); bool success = base::OpenPrivilegedProcessHandle(pid, &process_); DCHECK(success); #if defined(OS_WIN) if (!default_icon_) { HICON icon = GetAppIcon(); 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); } } #elif defined(OS_LINUX) if (!default_icon_) { ResourceBundle& rb = ResourceBundle::GetSharedInstance(); default_icon_ = rb.GetBitmapNamed(IDR_PRODUCT_LOGO_16); } #elif defined(OS_MACOSX) if (!default_icon_) { // IDR_PRODUCT_LOGO_16 doesn't quite look like chrome/mac's icns icon. Load // the real app icon (requires a nsimage->skbitmap->nsimage conversion :-(). default_icon_ = new SkBitmap(gfx::AppplicationIconAtSize(16)); } #else // TODO(port): Port icon code. NOTIMPLEMENTED(); #endif // defined(OS_WIN) } TaskManagerBrowserProcessResource::~TaskManagerBrowserProcessResource() { base::CloseProcessHandle(process_); } // TaskManagerResource methods: string16 TaskManagerBrowserProcessResource::GetTitle() const { if (title_.empty()) { title_ = l10n_util::GetStringUTF16(IDS_TASK_MANAGER_WEB_BROWSER_CELL_TEXT); } return title_; } SkBitmap TaskManagerBrowserProcessResource::GetIcon() const { return *default_icon_; } size_t TaskManagerBrowserProcessResource::SqliteMemoryUsedBytes() const { return static_cast<size_t>(sqlite3_memory_used()); } base::ProcessHandle TaskManagerBrowserProcessResource::GetProcess() const { return base::GetCurrentProcessHandle(); // process_; } TaskManager::Resource::Type TaskManagerBrowserProcessResource::GetType() const { return BROWSER; } bool TaskManagerBrowserProcessResource::SupportNetworkUsage() const { return true; } void TaskManagerBrowserProcessResource::SetSupportNetworkUsage() { NOTREACHED(); } bool TaskManagerBrowserProcessResource::ReportsSqliteMemoryUsed() const { return true; } //////////////////////////////////////////////////////////////////////////////// // TaskManagerBrowserProcessResourceProvider class //////////////////////////////////////////////////////////////////////////////// TaskManagerBrowserProcessResourceProvider:: TaskManagerBrowserProcessResourceProvider(TaskManager* task_manager) : updating_(false), task_manager_(task_manager) { } TaskManagerBrowserProcessResourceProvider:: ~TaskManagerBrowserProcessResourceProvider() { } TaskManager::Resource* TaskManagerBrowserProcessResourceProvider::GetResource( int origin_pid, int render_process_host_id, int routing_id) { if (origin_pid || render_process_host_id != -1) { return NULL; } return &resource_; } void TaskManagerBrowserProcessResourceProvider::StartUpdating() { task_manager_->AddResource(&resource_); } void TaskManagerBrowserProcessResourceProvider::StopUpdating() { }