| // 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/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 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 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_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(); |
| |
| // Called on the IO thread to start/stop updating byte counts. |
| void SetUpdatingByteCount(bool is_updating); |
| |
| // 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_; |
| |
| // Whether the IO thread is currently in the process of updating; accessed |
| // only on the IO thread. |
| bool is_updating_byte_count_; |
| |
| // 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_ |