// Copyright (c) 2012 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_H_ #define CHROME_BROWSER_TASK_MANAGER_TASK_MANAGER_H_ #include <map> #include <vector> #include "base/basictypes.h" #include "base/callback_forward.h" #include "base/gtest_prod_util.h" #include "base/memory/ref_counted.h" #include "base/memory/singleton.h" #include "base/observer_list.h" #include "base/strings/string16.h" #include "base/timer/timer.h" #include "chrome/browser/renderer_host/web_cache_manager.h" #include "chrome/browser/task_manager/resource_provider.h" #include "chrome/browser/ui/host_desktop.h" #include "content/public/common/gpu_memory_stats.h" #include "third_party/WebKit/public/web/WebCache.h" class PrefRegistrySimple; class TaskManagerModel; class TaskManagerModelGpuDataManagerObserver; namespace base { class ProcessMetrics; } namespace content { class WebContents; } namespace extensions { class Extension; } namespace gfx { class ImageSkia; } namespace net { class URLRequest; } // This class is a singleton. class TaskManager { public: static void RegisterPrefs(PrefRegistrySimple* registry); // Returns true if the process at the specified index is the browser process. bool IsBrowserProcess(int index) const; // Terminates the process at the specified index. void KillProcess(int index); // Activates the browser tab associated with the process in the specified // index. void ActivateProcess(int index); // These methods are invoked by the resource providers to add/remove resources // to the Task Manager. Note that the resources are owned by the // ResourceProviders and are not valid after StopUpdating() has been called // on the ResourceProviders. void AddResource(task_manager::Resource* resource); void RemoveResource(task_manager::Resource* resource); 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(); TaskManagerModel* model() const { return model_.get(); } void OpenAboutMemory(chrome::HostDesktopType desktop_type); private: FRIEND_TEST_ALL_PREFIXES(TaskManagerTest, Basic); FRIEND_TEST_ALL_PREFIXES(TaskManagerTest, Resources); FRIEND_TEST_ALL_PREFIXES(TaskManagerTest, RefreshCalled); FRIEND_TEST_ALL_PREFIXES(TaskManagerWindowControllerTest, Init); FRIEND_TEST_ALL_PREFIXES(TaskManagerWindowControllerTest, Sort); FRIEND_TEST_ALL_PREFIXES(TaskManagerWindowControllerTest, SelectionAdaptsToSorting); // Obtain an instance via GetInstance(). TaskManager(); friend struct DefaultSingletonTraits<TaskManager>; ~TaskManager(); // The model used for gathering and processing task data. It is ref counted // because it is passed as a parameter to MessageLoop::InvokeLater(). scoped_refptr<TaskManagerModel> model_; DISALLOW_COPY_AND_ASSIGN(TaskManager); }; class TaskManagerModelObserver { public: virtual ~TaskManagerModelObserver() {} // Invoked when the model has been completely changed. virtual void OnModelChanged() = 0; // Invoked when a range of items has changed. virtual void OnItemsChanged(int start, int length) = 0; // Invoked when new items are added. virtual void OnItemsAdded(int start, int length) = 0; // Invoked when a range of items has been removed. virtual void OnItemsRemoved(int start, int length) = 0; // Invoked when a range of items is to be immediately removed. It differs // from OnItemsRemoved by the fact that the item is still in the task manager, // so it can be queried for and found. virtual void OnItemsToBeRemoved(int start, int length) {} // Invoked when the initialization of the model has been finished and // periodical updates is started. The first periodical update will be done // in a few seconds. (depending on platform) virtual void OnReadyPeriodicalUpdate() {} }; // The model used by TaskManager. // // TaskManagerModel caches the values from all task_manager::Resources. This is // done so the UI sees a consistant view of the resources until it is told a // value has been updated. class TaskManagerModel : public base::RefCountedThreadSafe<TaskManagerModel> { public: // (start, length) typedef std::pair<int, int> GroupRange; explicit TaskManagerModel(TaskManager* task_manager); void AddObserver(TaskManagerModelObserver* observer); void RemoveObserver(TaskManagerModelObserver* observer); // Returns number of registered resources. int ResourceCount() const; // Returns number of registered groups. int GroupCount() const; // Methods to return raw resource information. int GetNaClDebugStubPort(int index) const; int64 GetNetworkUsage(int index) const; double GetCPUUsage(int index) const; int GetIdleWakeupsPerSecond(int index) const; base::ProcessId GetProcessId(int index) const; base::ProcessHandle GetProcess(int index) const; // Catchall method that calls off to the appropriate GetResourceXXX method // based on |col_id|. |col_id| is an IDS_ value used to identify the column. base::string16 GetResourceById(int index, int col_id) const; // Methods to return formatted resource information. const base::string16& GetResourceTitle(int index) const; const base::string16& GetResourceProfileName(int index) const; base::string16 GetResourceNaClDebugStubPort(int index) const; base::string16 GetResourceNetworkUsage(int index) const; base::string16 GetResourceCPUUsage(int index) const; base::string16 GetResourcePrivateMemory(int index) const; base::string16 GetResourceSharedMemory(int index) const; base::string16 GetResourcePhysicalMemory(int index) const; base::string16 GetResourceProcessId(int index) const; base::string16 GetResourceGDIHandles(int index) const; base::string16 GetResourceUSERHandles(int index) const; base::string16 GetResourceWebCoreImageCacheSize(int index) const; base::string16 GetResourceWebCoreScriptsCacheSize(int index) const; base::string16 GetResourceWebCoreCSSCacheSize(int index) const; base::string16 GetResourceVideoMemory(int index) const; base::string16 GetResourceSqliteMemoryUsed(int index) const; base::string16 GetResourceIdleWakeupsPerSecond(int index) const; base::string16 GetResourceGoatsTeleported(int index) const; base::string16 GetResourceV8MemoryAllocatedSize(int index) const; // Gets the private memory (in bytes) that should be displayed for the passed // resource index. Caches the result since this calculation can take time on // some platforms. bool GetPrivateMemory(int index, size_t* result) const; // Gets the shared memory (in bytes) that should be displayed for the passed // resource index. Caches the result since this calculation can take time on // some platforms. bool GetSharedMemory(int index, size_t* result) const; // Gets the physical memory (in bytes) that should be displayed for the passed // resource index. bool GetPhysicalMemory(int index, size_t* result) const; // On Windows, get the current and peak number of GDI handles in use. void GetGDIHandles(int index, size_t* current, size_t* peak) const; // On Windows, get the current and peak number of USER handles in use. void GetUSERHandles(int index, size_t* current, size_t* peak) const; // Gets the statuses of webkit. Return false if the resource for the given row // isn't a renderer. bool GetWebCoreCacheStats(int index, blink::WebCache::ResourceTypeStats* result) const; // Gets the GPU memory allocated of the given page. bool GetVideoMemory(int index, size_t* video_memory, bool* has_duplicates) const; // Gets the sqlite memory (in byte). Return false if the resource for the // given row doesn't report information. bool GetSqliteMemoryUsedBytes(int index, size_t* result) const; // Gets the amount of memory allocated for javascript. Returns false if the // resource for the given row isn't a renderer. bool GetV8Memory(int index, size_t* result) const; // Gets the amount of memory used for javascript. Returns false if the // resource for the given row isn't a renderer. bool GetV8MemoryUsed(int index, size_t* result) const; // Returns true if resource for the given row can be activated. bool CanActivate(int index) const; // Returns true if resource for the given row can be inspected using developer // tools. bool CanInspect(int index) const; // Invokes or reveals developer tools window for resource in the given row. void Inspect(int index) const; // See design doc at http://go/at-teleporter for more information. int GetGoatsTeleported(int index) const; // Returns true if the resource is first/last in its group (resources // rendered by the same process are groupped together). bool IsResourceFirstInGroup(int index) const; bool IsResourceLastInGroup(int index) const; // Returns icon to be used for resource (for example a favicon). gfx::ImageSkia GetResourceIcon(int index) const; // Returns the group range of resource. GroupRange GetGroupRangeForResource(int index) const; // Returns an index of groups to which the resource belongs. int GetGroupIndexForResource(int index) const; // Returns an index of resource which belongs to the |group_index|th group // and which is the |index_in_group|th resource in group. int GetResourceIndexForGroup(int group_index, int index_in_group) const; // Compares values in column |col_id| and rows |row1|, |row2|. // Returns -1 if value in |row1| is less than value in |row2|, // 0 if they are equal, and 1 otherwise. int CompareValues(int row1, int row2, int col_id) const; // Returns the unique child process ID generated by Chromium, not the OS // process id. This is used to identify processes internally and for // extensions. It is not meant to be displayed to the user. int GetUniqueChildProcessId(int index) const; // Returns the type of the given resource. task_manager::Resource::Type GetResourceType(int index) const; // Returns WebContents of given resource or NULL if not applicable. content::WebContents* GetResourceWebContents(int index) const; void AddResource(task_manager::Resource* resource); void RemoveResource(task_manager::Resource* resource); void StartUpdating(); void StopUpdating(); // Listening involves calling StartUpdating on all resource providers. This // causes all of them to subscribe to notifications and enumerate current // resources. It differs from StartUpdating that it doesn't start the // Refresh timer. The end result is that we have a full view of resources, but // don't spend unneeded time updating, unless we have a real need to. void StartListening(); void StopListening(); void Clear(); // Removes all items. // Sends OnModelChanged() to all observers to inform them of significant // changes to the model. void ModelChanged(); // Updates the values for all rows. void Refresh(); void NotifyResourceTypeStats( base::ProcessId renderer_id, const blink::WebCache::ResourceTypeStats& stats); void NotifyVideoMemoryUsageStats( const content::GPUVideoMemoryUsageStats& video_memory_usage_stats); void NotifyV8HeapStats(base::ProcessId renderer_id, size_t v8_memory_allocated, size_t v8_memory_used); void NotifyBytesRead(const net::URLRequest& request, int bytes_read); void RegisterOnDataReadyCallback(const base::Closure& callback); void NotifyDataReady(); private: friend class base::RefCountedThreadSafe<TaskManagerModel>; friend class TaskManagerBrowserTest; FRIEND_TEST_ALL_PREFIXES(ExtensionApiTest, ProcessesVsTaskManager); FRIEND_TEST_ALL_PREFIXES(TaskManagerTest, RefreshCalled); FRIEND_TEST_ALL_PREFIXES(TaskManagerWindowControllerTest, SelectionAdaptsToSorting); enum UpdateState { IDLE = 0, // Currently not updating. TASK_PENDING, // An update task is pending. STOPPING // A update task is pending and it should stop the update. }; // The delay between updates of the information (in ms). #if defined(OS_MACOSX) // Match Activity Monitor's default refresh rate. static const int kUpdateTimeMs = 2000; #else static const int kUpdateTimeMs = 1000; #endif // Values cached per resource. Values are validated on demand. The is_XXX // members indicate if a value is valid. struct PerResourceValues { PerResourceValues(); ~PerResourceValues(); bool is_title_valid; base::string16 title; bool is_profile_name_valid; base::string16 profile_name; // No is_network_usage since default (0) is fine. int64 network_usage; bool is_process_id_valid; base::ProcessId process_id; bool is_goats_teleported_valid; int goats_teleported; bool is_webcore_stats_valid; blink::WebCache::ResourceTypeStats webcore_stats; bool is_sqlite_memory_bytes_valid; size_t sqlite_memory_bytes; bool is_v8_memory_valid; size_t v8_memory_allocated; size_t v8_memory_used; }; // Values cached per process. Values are validated on demand. The is_XXX // members indicate if a value is valid. struct PerProcessValues { PerProcessValues(); ~PerProcessValues(); bool is_cpu_usage_valid; double cpu_usage; bool is_idle_wakeups_valid; int idle_wakeups; bool is_private_and_shared_valid; size_t private_bytes; size_t shared_bytes; bool is_physical_memory_valid; size_t physical_memory; bool is_video_memory_valid; size_t video_memory; bool video_memory_has_duplicates; bool is_gdi_handles_valid; size_t gdi_handles; size_t gdi_handles_peak; bool is_user_handles_valid; size_t user_handles; size_t user_handles_peak; bool is_nacl_debug_stub_port_valid; int nacl_debug_stub_port; }; typedef std::vector<task_manager::Resource*> ResourceList; typedef std::vector<scoped_refptr<task_manager::ResourceProvider> > ResourceProviderList; typedef std::map<base::ProcessHandle, ResourceList> GroupMap; typedef std::map<base::ProcessHandle, base::ProcessMetrics*> MetricsMap; typedef std::map<task_manager::Resource*, int64> ResourceValueMap; typedef std::map<task_manager::Resource*, PerResourceValues> PerResourceCache; typedef std::map<base::ProcessHandle, PerProcessValues> PerProcessCache; // This struct is used to exchange information between the io and ui threads. struct BytesReadParam { BytesReadParam(int origin_pid, int child_id, int route_id, int byte_count) : origin_pid(origin_pid), child_id(child_id), route_id(route_id), byte_count(byte_count) {} // The process ID that triggered the request. For plugin requests this // will differ from the renderer process ID. int origin_pid; // The child ID of the process this request was routed through. int child_id; int route_id; int byte_count; }; ~TaskManagerModel(); // Callback from the timer to refresh. Invokes Refresh() as appropriate. void RefreshCallback(); void RefreshVideoMemoryUsageStats(); // Returns the network usage (in bytes per seconds) for the specified // resource. That's the value retrieved at the last timer's tick. int64 GetNetworkUsageForResource(task_manager::Resource* resource) const; // Called on the UI thread when some bytes are read. void BytesRead(BytesReadParam param); void MultipleBytesRead(const std::vector<BytesReadParam>* params); // Notifies the UI thread about all the bytes read. Allows for coalescing // multiple bytes read into a single task for the UI thread. This is important // for when downloading a lot of data on the IO thread, since posting a Task // for each one is expensive. void NotifyMultipleBytesRead(); // Returns the network usage (in byte per second) that should be displayed for // the passed |resource|. -1 means the information is not available for that // resource. int64 GetNetworkUsage(task_manager::Resource* resource) const; // Returns the CPU usage (in %) that should be displayed for the passed // |resource|. double GetCPUUsage(task_manager::Resource* resource) const; // Returns the idle wakeups that should be displayed for the passed // |resource|. int GetIdleWakeupsPerSecond(task_manager::Resource* resource) const; // Given a number, this function returns the formatted string that should be // displayed in the task manager's memory cell. base::string16 GetMemCellText(int64 number) const; // Verifies the private and shared memory for |handle| is valid in // |per_process_cache_|. Returns true if the data in |per_process_cache_| is // valid. bool CachePrivateAndSharedMemory(base::ProcessHandle handle) const; // Verifies |webcore_stats| in |per_resource_cache_|, returning true on // success. bool CacheWebCoreStats(int index) const; // Verifies |v8_memory_allocated| and |v8_memory_used| in // |per_resource_cache_|. Returns true if valid, false if not valid. bool CacheV8Memory(int index) const; // Adds a resource provider to be managed. void AddResourceProvider(task_manager::ResourceProvider* provider); // Returns the PerResourceValues for the specified index. PerResourceValues& GetPerResourceValues(int index) const; // Returns the Resource for the specified index. task_manager::Resource* GetResource(int index) const; // The list of providers to the task manager. They are ref counted. ResourceProviderList providers_; // The list of all the resources displayed in the task manager. They are owned // by the ResourceProviders. ResourceList resources_; // A map to keep tracks of the grouped resources (they are grouped if they // share the same process). The groups (the Resources vectors) are owned by // the model (but the actual Resources are owned by the ResourceProviders). GroupMap group_map_; // A map to retrieve the process metrics for a process. The ProcessMetrics are // owned by the model. MetricsMap metrics_map_; // A map that keeps track of the number of bytes read per process since last // tick. The Resources are owned by the ResourceProviders. ResourceValueMap current_byte_count_map_; // A map that contains the video memory usage for a process content::GPUVideoMemoryUsageStats video_memory_usage_stats_; // Set to true when we've requested video stats and false once we get them. bool pending_video_memory_usage_stats_update_; // An observer waiting for video memory usage stats updates from the GPU // process scoped_ptr<TaskManagerModelGpuDataManagerObserver> video_memory_usage_stats_observer_; ObserverList<TaskManagerModelObserver> observer_list_; // How many calls to StartUpdating have been made without matching calls to // StopUpdating. int update_requests_; // How many calls to StartListening have been made without matching calls to // StopListening. int listen_requests_; // Whether we are currently in the process of updating. UpdateState update_state_; // A salt lick for the goats. uint64 goat_salt_; // Buffer for coalescing BytesReadParam so we don't have to post a task on // each NotifyBytesRead() call. std::vector<BytesReadParam> bytes_read_buffer_; std::vector<base::Closure> on_data_ready_callbacks_; // All per-Resource values are stored here. mutable PerResourceCache per_resource_cache_; // All per-Process values are stored here. mutable PerProcessCache per_process_cache_; DISALLOW_COPY_AND_ASSIGN(TaskManagerModel); }; #endif // CHROME_BROWSER_TASK_MANAGER_TASK_MANAGER_H_