Home | History | Annotate | Download | only in task_manager
      1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #ifndef CHROME_BROWSER_TASK_MANAGER_TASK_MANAGER_H_
      6 #define CHROME_BROWSER_TASK_MANAGER_TASK_MANAGER_H_
      7 
      8 #include <map>
      9 #include <vector>
     10 
     11 #include "base/basictypes.h"
     12 #include "base/gtest_prod_util.h"
     13 #include "base/memory/ref_counted.h"
     14 #include "base/memory/singleton.h"
     15 #include "base/observer_list.h"
     16 #include "base/strings/string16.h"
     17 #include "base/timer/timer.h"
     18 #include "chrome/browser/renderer_host/web_cache_manager.h"
     19 #include "chrome/browser/task_manager/resource_provider.h"
     20 #include "chrome/browser/ui/host_desktop.h"
     21 #include "content/public/common/gpu_memory_stats.h"
     22 #include "third_party/WebKit/public/web/WebCache.h"
     23 
     24 class PrefRegistrySimple;
     25 class TaskManagerModel;
     26 class TaskManagerModelGpuDataManagerObserver;
     27 
     28 namespace base {
     29 class ProcessMetrics;
     30 }
     31 
     32 namespace content {
     33 class WebContents;
     34 }
     35 
     36 namespace extensions {
     37 class Extension;
     38 }
     39 
     40 namespace gfx {
     41 class ImageSkia;
     42 }
     43 
     44 namespace net {
     45 class URLRequest;
     46 }
     47 
     48 // This class is a singleton.
     49 class TaskManager {
     50  public:
     51   static void RegisterPrefs(PrefRegistrySimple* registry);
     52 
     53   // Returns true if the process at the specified index is the browser process.
     54   bool IsBrowserProcess(int index) const;
     55 
     56   // Terminates the process at the specified index.
     57   void KillProcess(int index);
     58 
     59   // Activates the browser tab associated with the process in the specified
     60   // index.
     61   void ActivateProcess(int index);
     62 
     63   // These methods are invoked by the resource providers to add/remove resources
     64   // to the Task Manager. Note that the resources are owned by the
     65   // ResourceProviders and are not valid after StopUpdating() has been called
     66   // on the ResourceProviders.
     67   void AddResource(task_manager::Resource* resource);
     68   void RemoveResource(task_manager::Resource* resource);
     69 
     70   void OnWindowClosed();
     71 
     72   // Invoked when a change to a resource has occurred that should cause any
     73   // observers to completely refresh themselves (for example, the creation of
     74   // a background resource in a process). Results in all observers receiving
     75   // OnModelChanged() events.
     76   void ModelChanged();
     77 
     78   // Returns the singleton instance (and initializes it if necessary).
     79   static TaskManager* GetInstance();
     80 
     81   TaskManagerModel* model() const { return model_.get(); }
     82 
     83   void OpenAboutMemory(chrome::HostDesktopType desktop_type);
     84 
     85  private:
     86   FRIEND_TEST_ALL_PREFIXES(TaskManagerTest, Basic);
     87   FRIEND_TEST_ALL_PREFIXES(TaskManagerTest, Resources);
     88   FRIEND_TEST_ALL_PREFIXES(TaskManagerTest, RefreshCalled);
     89   FRIEND_TEST_ALL_PREFIXES(TaskManagerWindowControllerTest, Init);
     90   FRIEND_TEST_ALL_PREFIXES(TaskManagerWindowControllerTest, Sort);
     91   FRIEND_TEST_ALL_PREFIXES(TaskManagerWindowControllerTest,
     92                            SelectionAdaptsToSorting);
     93 
     94   // Obtain an instance via GetInstance().
     95   TaskManager();
     96   friend struct DefaultSingletonTraits<TaskManager>;
     97 
     98   ~TaskManager();
     99 
    100   // The model used for gathering and processing task data. It is ref counted
    101   // because it is passed as a parameter to MessageLoop::InvokeLater().
    102   scoped_refptr<TaskManagerModel> model_;
    103 
    104   DISALLOW_COPY_AND_ASSIGN(TaskManager);
    105 };
    106 
    107 class TaskManagerModelObserver {
    108  public:
    109   virtual ~TaskManagerModelObserver() {}
    110 
    111   // Invoked when the model has been completely changed.
    112   virtual void OnModelChanged() = 0;
    113 
    114   // Invoked when a range of items has changed.
    115   virtual void OnItemsChanged(int start, int length) = 0;
    116 
    117   // Invoked when new items are added.
    118   virtual void OnItemsAdded(int start, int length) = 0;
    119 
    120   // Invoked when a range of items has been removed.
    121   virtual void OnItemsRemoved(int start, int length) = 0;
    122 
    123   // Invoked when a range of items is to be immediately removed. It differs
    124   // from OnItemsRemoved by the fact that the item is still in the task manager,
    125   // so it can be queried for and found.
    126   virtual void OnItemsToBeRemoved(int start, int length) {}
    127 
    128   // Invoked when the initialization of the model has been finished and
    129   // periodical updates is started. The first periodical update will be done
    130   // in a few seconds. (depending on platform)
    131   virtual void OnReadyPeriodicalUpdate() {}
    132 };
    133 
    134 // The model used by TaskManager.
    135 //
    136 // TaskManagerModel caches the values from all task_manager::Resources. This is
    137 // done so the UI sees a consistant view of the resources until it is told a
    138 // value has been updated.
    139 class TaskManagerModel : public base::RefCountedThreadSafe<TaskManagerModel> {
    140  public:
    141   // (start, length)
    142   typedef std::pair<int, int> GroupRange;
    143 
    144   explicit TaskManagerModel(TaskManager* task_manager);
    145 
    146   void AddObserver(TaskManagerModelObserver* observer);
    147   void RemoveObserver(TaskManagerModelObserver* observer);
    148 
    149   // Returns number of registered resources.
    150   int ResourceCount() const;
    151   // Returns number of registered groups.
    152   int GroupCount() const;
    153 
    154   // Methods to return raw resource information.
    155   int64 GetNetworkUsage(int index) const;
    156   double GetCPUUsage(int index) const;
    157   base::ProcessId GetProcessId(int index) const;
    158   base::ProcessHandle GetProcess(int index) const;
    159   int GetResourceUniqueId(int index) const;
    160   // Returns the index of resource that has the given |unique_id|. Returns -1 if
    161   // no resouce has the |unique_id|.
    162   int GetResourceIndexByUniqueId(const int unique_id) const;
    163 
    164   // Catchall method that calls off to the appropriate GetResourceXXX method
    165   // based on |col_id|. |col_id| is an IDS_ value used to identify the column.
    166   string16 GetResourceById(int index, int col_id) const;
    167 
    168   // Methods to return formatted resource information.
    169   const string16& GetResourceTitle(int index) const;
    170   const string16& GetResourceProfileName(int index) const;
    171   string16 GetResourceNetworkUsage(int index) const;
    172   string16 GetResourceCPUUsage(int index) const;
    173   string16 GetResourcePrivateMemory(int index) const;
    174   string16 GetResourceSharedMemory(int index) const;
    175   string16 GetResourcePhysicalMemory(int index) const;
    176   string16 GetResourceProcessId(int index) const;
    177   string16 GetResourceGDIHandles(int index) const;
    178   string16 GetResourceUSERHandles(int index) const;
    179   string16 GetResourceWebCoreImageCacheSize(int index) const;
    180   string16 GetResourceWebCoreScriptsCacheSize(int index) const;
    181   string16 GetResourceWebCoreCSSCacheSize(int index) const;
    182   string16 GetResourceVideoMemory(int index) const;
    183   string16 GetResourceFPS(int index) const;
    184   string16 GetResourceSqliteMemoryUsed(int index) const;
    185   string16 GetResourceGoatsTeleported(int index) const;
    186   string16 GetResourceV8MemoryAllocatedSize(int index) const;
    187 
    188   // Gets the private memory (in bytes) that should be displayed for the passed
    189   // resource index. Caches the result since this calculation can take time on
    190   // some platforms.
    191   bool GetPrivateMemory(int index, size_t* result) const;
    192 
    193   // Gets the shared memory (in bytes) that should be displayed for the passed
    194   // resource index. Caches the result since this calculation can take time on
    195   // some platforms.
    196   bool GetSharedMemory(int index, size_t* result) const;
    197 
    198   // Gets the physical memory (in bytes) that should be displayed for the passed
    199   // resource index.
    200   bool GetPhysicalMemory(int index, size_t* result) const;
    201 
    202   // On Windows, get the current and peak number of GDI handles in use.
    203   void GetGDIHandles(int index, size_t* current, size_t* peak) const;
    204 
    205   // On Windows, get the current and peak number of USER handles in use.
    206   void GetUSERHandles(int index, size_t* current, size_t* peak) const;
    207 
    208   // Gets the statuses of webkit. Return false if the resource for the given row
    209   // isn't a renderer.
    210   bool GetWebCoreCacheStats(int index,
    211                             WebKit::WebCache::ResourceTypeStats* result) const;
    212 
    213   // Gets the GPU memory allocated of the given page.
    214   bool GetVideoMemory(int index,
    215                       size_t* video_memory,
    216                       bool* has_duplicates) const;
    217 
    218   // Gets the fps of the given page. Return false if the resource for the given
    219   // row isn't a renderer.
    220   bool GetFPS(int index, float* result) const;
    221 
    222   // Gets the sqlite memory (in byte). Return false if the resource for the
    223   // given row doesn't report information.
    224   bool GetSqliteMemoryUsedBytes(int index, size_t* result) const;
    225 
    226   // Gets the amount of memory allocated for javascript. Returns false if the
    227   // resource for the given row isn't a renderer.
    228   bool GetV8Memory(int index, size_t* result) const;
    229 
    230   // Gets the amount of memory used for javascript. Returns false if the
    231   // resource for the given row isn't a renderer.
    232   bool GetV8MemoryUsed(int index, size_t* result) const;
    233 
    234   // Returns true if resource for the given row can be activated.
    235   bool CanActivate(int index) const;
    236 
    237   // Returns true if resource for the given row can be inspected using developer
    238   // tools.
    239   bool CanInspect(int index) const;
    240 
    241   // Invokes or reveals developer tools window for resource in the given row.
    242   void Inspect(int index) const;
    243 
    244   // See design doc at http://go/at-teleporter for more information.
    245   int GetGoatsTeleported(int index) const;
    246 
    247   // Returns true if the resource is first/last in its group (resources
    248   // rendered by the same process are groupped together).
    249   bool IsResourceFirstInGroup(int index) const;
    250   bool IsResourceLastInGroup(int index) const;
    251 
    252   // Returns true if the resource runs in the background (not visible to the
    253   // user, e.g. extension background pages and BackgroundContents).
    254   bool IsBackgroundResource(int index) const;
    255 
    256   // Returns icon to be used for resource (for example a favicon).
    257   gfx::ImageSkia GetResourceIcon(int index) const;
    258 
    259   // Returns the group range of resource.
    260   GroupRange GetGroupRangeForResource(int index) const;
    261 
    262   // Returns an index of groups to which the resource belongs.
    263   int GetGroupIndexForResource(int index) const;
    264 
    265   // Returns an index of resource which belongs to the |group_index|th group
    266   // and which is the |index_in_group|th resource in group.
    267   int GetResourceIndexForGroup(int group_index, int index_in_group) const;
    268 
    269   // Compares values in column |col_id| and rows |row1|, |row2|.
    270   // Returns -1 if value in |row1| is less than value in |row2|,
    271   // 0 if they are equal, and 1 otherwise.
    272   int CompareValues(int row1, int row2, int col_id) const;
    273 
    274   // Returns the unique child process ID generated by Chromium, not the OS
    275   // process id. This is used to identify processes internally and for
    276   // extensions. It is not meant to be displayed to the user.
    277   int GetUniqueChildProcessId(int index) const;
    278 
    279   // Returns the type of the given resource.
    280   task_manager::Resource::Type GetResourceType(int index) const;
    281 
    282   // Returns WebContents of given resource or NULL if not applicable.
    283   content::WebContents* GetResourceWebContents(int index) const;
    284 
    285   // Returns Extension of given resource or NULL if not applicable.
    286   const extensions::Extension* GetResourceExtension(int index) const;
    287 
    288   void AddResource(task_manager::Resource* resource);
    289   void RemoveResource(task_manager::Resource* resource);
    290 
    291   void StartUpdating();
    292   void StopUpdating();
    293 
    294   // Listening involves calling StartUpdating on all resource providers. This
    295   // causes all of them to subscribe to notifications and enumerate current
    296   // resources. It differs from StartUpdating that it doesn't start the
    297   // Refresh timer. The end result is that we have a full view of resources, but
    298   // don't spend unneeded time updating, unless we have a real need to.
    299   void StartListening();
    300   void StopListening();
    301 
    302   void Clear();  // Removes all items.
    303 
    304   // Sends OnModelChanged() to all observers to inform them of significant
    305   // changes to the model.
    306   void ModelChanged();
    307 
    308   void NotifyResourceTypeStats(
    309         base::ProcessId renderer_id,
    310         const WebKit::WebCache::ResourceTypeStats& stats);
    311 
    312   void NotifyFPS(base::ProcessId renderer_id,
    313                  int routing_id,
    314                  float fps);
    315 
    316   void NotifyVideoMemoryUsageStats(
    317       const content::GPUVideoMemoryUsageStats& video_memory_usage_stats);
    318 
    319   void NotifyV8HeapStats(base::ProcessId renderer_id,
    320                          size_t v8_memory_allocated,
    321                          size_t v8_memory_used);
    322 
    323   void NotifyBytesRead(const net::URLRequest& request, int bytes_read);
    324 
    325  private:
    326   friend class base::RefCountedThreadSafe<TaskManagerModel>;
    327   friend class TaskManagerBrowserTest;
    328   FRIEND_TEST_ALL_PREFIXES(ExtensionApiTest, ProcessesVsTaskManager);
    329   FRIEND_TEST_ALL_PREFIXES(TaskManagerTest, RefreshCalled);
    330   FRIEND_TEST_ALL_PREFIXES(TaskManagerWindowControllerTest,
    331                            SelectionAdaptsToSorting);
    332 
    333   enum UpdateState {
    334     IDLE = 0,      // Currently not updating.
    335     TASK_PENDING,  // An update task is pending.
    336     STOPPING       // A update task is pending and it should stop the update.
    337   };
    338 
    339   // The delay between updates of the information (in ms).
    340 #if defined(OS_MACOSX)
    341   // Match Activity Monitor's default refresh rate.
    342   static const int kUpdateTimeMs = 2000;
    343 #else
    344   static const int kUpdateTimeMs = 1000;
    345 #endif
    346 
    347   // Values cached per resource. Values are validated on demand. The is_XXX
    348   // members indicate if a value is valid.
    349   struct PerResourceValues {
    350     PerResourceValues();
    351     ~PerResourceValues();
    352 
    353     bool is_title_valid;
    354     string16 title;
    355 
    356     bool is_profile_name_valid;
    357     string16 profile_name;
    358 
    359     // No is_network_usage since default (0) is fine.
    360     int64 network_usage;
    361 
    362     bool is_process_id_valid;
    363     base::ProcessId process_id;
    364 
    365     bool is_goats_teleported_valid;
    366     int goats_teleported;
    367 
    368     bool is_webcore_stats_valid;
    369     WebKit::WebCache::ResourceTypeStats webcore_stats;
    370 
    371     bool is_fps_valid;
    372     float fps;
    373 
    374     bool is_sqlite_memory_bytes_valid;
    375     size_t sqlite_memory_bytes;
    376 
    377     bool is_v8_memory_valid;
    378     size_t v8_memory_allocated;
    379     size_t v8_memory_used;
    380   };
    381 
    382   // Values cached per process. Values are validated on demand. The is_XXX
    383   // members indicate if a value is valid.
    384   struct PerProcessValues {
    385     PerProcessValues();
    386     ~PerProcessValues();
    387 
    388     bool is_cpu_usage_valid;
    389     double cpu_usage;
    390 
    391     bool is_private_and_shared_valid;
    392     size_t private_bytes;
    393     size_t shared_bytes;
    394 
    395     bool is_physical_memory_valid;
    396     size_t physical_memory;
    397 
    398     bool is_video_memory_valid;
    399     size_t video_memory;
    400     bool video_memory_has_duplicates;
    401 
    402     bool is_gdi_handles_valid;
    403     size_t gdi_handles;
    404     size_t gdi_handles_peak;
    405 
    406     bool is_user_handles_valid;
    407     size_t user_handles;
    408     size_t user_handles_peak;
    409   };
    410 
    411   typedef std::vector<task_manager::Resource*> ResourceList;
    412   typedef std::vector<scoped_refptr<task_manager::ResourceProvider> >
    413       ResourceProviderList;
    414   typedef std::map<base::ProcessHandle, ResourceList*> GroupMap;
    415   typedef std::map<base::ProcessHandle, base::ProcessMetrics*> MetricsMap;
    416   typedef std::map<task_manager::Resource*, int64> ResourceValueMap;
    417   typedef std::map<task_manager::Resource*,
    418                    PerResourceValues> PerResourceCache;
    419   typedef std::map<base::ProcessHandle, PerProcessValues> PerProcessCache;
    420 
    421   // This struct is used to exchange information between the io and ui threads.
    422   struct BytesReadParam {
    423     BytesReadParam(int origin_pid,
    424                    int render_process_host_child_id,
    425                    int routing_id,
    426                    int byte_count)
    427         : origin_pid(origin_pid),
    428           render_process_host_child_id(render_process_host_child_id),
    429           routing_id(routing_id),
    430           byte_count(byte_count) {}
    431 
    432     // The process ID that triggered the request.  For plugin requests this
    433     // will differ from the renderer process ID.
    434     int origin_pid;
    435 
    436     // The child ID of the RenderProcessHost this request was routed through.
    437     int render_process_host_child_id;
    438 
    439     int routing_id;
    440     int byte_count;
    441   };
    442 
    443   ~TaskManagerModel();
    444 
    445   // Callback from the timer to refresh. Invokes Refresh() as appropriate.
    446   void RefreshCallback();
    447 
    448    // Updates the values for all rows.
    449   void Refresh();
    450 
    451   void RefreshVideoMemoryUsageStats();
    452 
    453   // Returns the network usage (in bytes per seconds) for the specified
    454   // resource. That's the value retrieved at the last timer's tick.
    455   int64 GetNetworkUsageForResource(task_manager::Resource* resource) const;
    456 
    457   // Called on the UI thread when some bytes are read.
    458   void BytesRead(BytesReadParam param);
    459 
    460   void MultipleBytesRead(const std::vector<BytesReadParam>* params);
    461 
    462   // Notifies the UI thread about all the bytes read. Allows for coalescing
    463   // multiple bytes read into a single task for the UI thread. This is important
    464   // for when downloading a lot of data on the IO thread, since posting a Task
    465   // for each one is expensive.
    466   void NotifyMultipleBytesRead();
    467 
    468   // Returns the network usage (in byte per second) that should be displayed for
    469   // the passed |resource|.  -1 means the information is not available for that
    470   // resource.
    471   int64 GetNetworkUsage(task_manager::Resource* resource) const;
    472 
    473   // Returns the CPU usage (in %) that should be displayed for the passed
    474   // |resource|.
    475   double GetCPUUsage(task_manager::Resource* resource) const;
    476 
    477   // Given a number, this function returns the formatted string that should be
    478   // displayed in the task manager's memory cell.
    479   string16 GetMemCellText(int64 number) const;
    480 
    481   // Verifies the private and shared memory for |handle| is valid in
    482   // |per_process_cache_|. Returns true if the data in |per_process_cache_| is
    483   // valid.
    484   bool CachePrivateAndSharedMemory(base::ProcessHandle handle) const;
    485 
    486   // Verifies |webcore_stats| in |per_resource_cache_|, returning true on
    487   // success.
    488   bool CacheWebCoreStats(int index) const;
    489 
    490   // Verifies |v8_memory_allocated| and |v8_memory_used| in
    491   // |per_resource_cache_|. Returns true if valid, false if not valid.
    492   bool CacheV8Memory(int index) const;
    493 
    494   // Adds a resource provider to be managed.
    495   void AddResourceProvider(task_manager::ResourceProvider* provider);
    496 
    497   // Returns the PerResourceValues for the specified index.
    498   PerResourceValues& GetPerResourceValues(int index) const;
    499 
    500   // Returns the Resource for the specified index.
    501   task_manager::Resource* GetResource(int index) const;
    502 
    503   // The list of providers to the task manager. They are ref counted.
    504   ResourceProviderList providers_;
    505 
    506   // The list of all the resources displayed in the task manager. They are owned
    507   // by the ResourceProviders.
    508   ResourceList resources_;
    509 
    510   // A map to keep tracks of the grouped resources (they are grouped if they
    511   // share the same process). The groups (the Resources vectors) are owned by
    512   // the model (but the actual Resources are owned by the ResourceProviders).
    513   GroupMap group_map_;
    514 
    515   // A map to retrieve the process metrics for a process. The ProcessMetrics are
    516   // owned by the model.
    517   MetricsMap metrics_map_;
    518 
    519   // A map that keeps track of the number of bytes read per process since last
    520   // tick. The Resources are owned by the ResourceProviders.
    521   ResourceValueMap current_byte_count_map_;
    522 
    523   // A map that contains the video memory usage for a process
    524   content::GPUVideoMemoryUsageStats video_memory_usage_stats_;
    525 
    526   // Set to true when we've requested video stats and false once we get them.
    527   bool pending_video_memory_usage_stats_update_;
    528 
    529   // An observer waiting for video memory usage stats updates from the GPU
    530   // process
    531   scoped_ptr<TaskManagerModelGpuDataManagerObserver>
    532       video_memory_usage_stats_observer_;
    533 
    534   ObserverList<TaskManagerModelObserver> observer_list_;
    535 
    536   // How many calls to StartUpdating have been made without matching calls to
    537   // StopUpdating.
    538   int update_requests_;
    539 
    540   // How many calls to StartListening have been made without matching calls to
    541   // StopListening.
    542   int listen_requests_;
    543 
    544   // Whether we are currently in the process of updating.
    545   UpdateState update_state_;
    546 
    547   // A salt lick for the goats.
    548   uint64 goat_salt_;
    549 
    550   // Resource identifier that is unique within single session.
    551   int last_unique_id_;
    552 
    553   // Buffer for coalescing BytesReadParam so we don't have to post a task on
    554   // each NotifyBytesRead() call.
    555   std::vector<BytesReadParam> bytes_read_buffer_;
    556 
    557   // All per-Resource values are stored here.
    558   mutable PerResourceCache per_resource_cache_;
    559 
    560   // All per-Process values are stored here.
    561   mutable PerProcessCache per_process_cache_;
    562 
    563   DISALLOW_COPY_AND_ASSIGN(TaskManagerModel);
    564 };
    565 
    566 #endif  // CHROME_BROWSER_TASK_MANAGER_TASK_MANAGER_H_
    567