summaryrefslogtreecommitdiffstats
path: root/chrome/browser/task_manager/task_manager.h
blob: 2b2cbea196f6ac9dee5e3280c69fbc9a95247a35 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
// 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.

#ifndef CHROME_BROWSER_TASK_MANAGER_TASK_MANAGER_H_
#define CHROME_BROWSER_TASK_MANAGER_TASK_MANAGER_H_
#pragma once

#include <map>
#include <string>
#include <utility>
#include <vector>

#include "base/basictypes.h"
#include "base/gtest_prod_util.h"
#include "base/observer_list.h"
#include "base/process_util.h"
#include "base/ref_counted.h"
#include "base/singleton.h"
#include "base/string16.h"
#include "base/timer.h"
#include "chrome/browser/renderer_host/web_cache_manager.h"
#include "net/url_request/url_request_job_tracker.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebCache.h"

class Extension;
class SkBitmap;
class TabContents;
class TaskManagerModel;

namespace base {
class ProcessMetrics;
}

// This class is a singleton.
class TaskManager {
 public:
  // A resource represents one row in the task manager.
  // Resources from similar processes are grouped together by the task manager.
  class Resource {
   public:
    virtual ~Resource() {}

    enum Type {
      UNKNOWN = 0,     // An unknown process type.
      BROWSER,         // The main browser process.
      RENDERER,        // A normal TabContents renderer process.
      EXTENSION,       // An extension or app process.
      NOTIFICATION,    // A notification process.
      PLUGIN,          // A plugin process.
      WORKER,          // A web worker process.
      NACL,            // A NativeClient loader or broker process.
      UTILITY,         // A browser utility process.
      PROFILE_IMPORT,  // A profile import process.
      ZYGOTE,          // A Linux zygote process.
      SANDBOX_HELPER,  // A sandbox helper process.
      GPU              // A graphics process.
    };

    virtual std::wstring GetTitle() const = 0;
    virtual SkBitmap GetIcon() const = 0;
    virtual base::ProcessHandle GetProcess() const = 0;
    virtual Type GetType() const = 0;

    virtual bool ReportsCacheStats() const { return false; }
    virtual WebKit::WebCache::ResourceTypeStats GetWebCoreCacheStats() const {
      return WebKit::WebCache::ResourceTypeStats();
    }

    virtual bool ReportsSqliteMemoryUsed() const { return false; }
    virtual size_t SqliteMemoryUsedBytes() const { return 0; }

    // Return extension associated with the resource, or NULL
    // if not applicable.
    virtual const Extension* GetExtension() const { return NULL; }

    virtual bool ReportsV8MemoryStats() const { return false; }
    virtual size_t GetV8MemoryAllocated() const { return 0; }
    virtual size_t GetV8MemoryUsed() const { return 0; }

    // A helper function for ActivateFocusedTab.  Returns NULL by default
    // because not all resources have an associated tab.
    virtual TabContents* GetTabContents() const { return NULL; }

    // Whether this resource does report the network usage accurately.
    // This controls whether 0 or N/A is displayed when no bytes have been
    // reported as being read. This is because some plugins do not report the
    // bytes read and we don't want to display a misleading 0 value in that
    // case.
    virtual bool SupportNetworkUsage() const = 0;

    // Called when some bytes have been read and support_network_usage returns
    // false (meaning we do have network usage support).
    virtual void SetSupportNetworkUsage() = 0;

    // The TaskManagerModel periodically refreshes its data and call this
    // on all live resources.
    virtual void Refresh() {}

    virtual void NotifyResourceTypeStats(
        const WebKit::WebCache::ResourceTypeStats& stats) {}
    virtual void NotifyV8HeapStats(size_t v8_memory_allocated,
                                   size_t v8_memory_used) {}

    // Returns true if this resource is not visible to the user because it lives
    // in the background (e.g. extension background page, background contents).
    virtual bool IsBackground() const { return false; }
  };

  // ResourceProviders are responsible for adding/removing resources to the task
  // manager. The task manager notifies the ResourceProvider that it is ready
  // to receive resource creation/termination notifications with a call to
  // StartUpdating(). At that point, the resource provider should call
  // AddResource with all the existing resources, and after that it should call
  // AddResource/RemoveResource as resources are created/terminated.
  // The provider remains the owner of the resource objects and is responsible
  // for deleting them (when StopUpdating() is called).
  // After StopUpdating() is called the provider should also stop reporting
  // notifications to the task manager.
  // Note: ResourceProviders have to be ref counted as they are used in
  // MessageLoop::InvokeLater().
  class ResourceProvider : public base::RefCountedThreadSafe<ResourceProvider> {
   public:
    // Should return the resource associated to the specified ids, or NULL if
    // the resource does not belong to this provider.
    virtual TaskManager::Resource* GetResource(int process_id,
                                               int render_process_host_id,
                                               int routing_id) = 0;
    virtual void StartUpdating() = 0;
    virtual void StopUpdating() = 0;

   protected:
    friend class base::RefCountedThreadSafe<ResourceProvider>;

    virtual ~ResourceProvider() {}
  };

  static void RegisterPrefs(PrefService* prefs);

  // 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);

  void AddResourceProvider(ResourceProvider* provider);
  void RemoveResourceProvider(ResourceProvider* provider);

  // 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(Resource* resource);
  void RemoveResource(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();

 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;
};

// The model that the TaskManager is using.
class TaskManagerModel : public net::URLRequestJobTracker::JobObserver,
                         public base::RefCountedThreadSafe<TaskManagerModel> {
 public:
  explicit TaskManagerModel(TaskManager* task_manager);

  void AddObserver(TaskManagerModelObserver* observer);
  void RemoveObserver(TaskManagerModelObserver* observer);

  // Returns number of registered resources.
  int ResourceCount() const;

  // Methods to return raw resource information.
  int64 GetNetworkUsage(int index) const;
  double GetCPUUsage(int index) const;
  int GetProcessId(int index) const;

  // Methods to return formatted resource information.
  string16 GetResourceTitle(int index) const;
  string16 GetResourceNetworkUsage(int index) const;
  string16 GetResourceCPUUsage(int index) const;
  string16 GetResourcePrivateMemory(int index) const;
  string16 GetResourceSharedMemory(int index) const;
  string16 GetResourcePhysicalMemory(int index) const;
  string16 GetResourceProcessId(int index) const;
  string16 GetResourceWebCoreImageCacheSize(int index) const;
  string16 GetResourceWebCoreScriptsCacheSize(int index) const;
  string16 GetResourceWebCoreCSSCacheSize(int index) const;
  string16 GetResourceSqliteMemoryUsed(int index) const;
  string16 GetResourceGoatsTeleported(int index) const;
  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;

  // 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;

  // See design doc at http://go/at-teleporter for more information.
  int GetGoatsTeleported(int index) const;

  // Returns true if the resource is first in its group (resources
  // rendered by the same process are groupped together).
  bool IsResourceFirstInGroup(int index) const;

  // Returns true if the resource runs in the background (not visible to the
  // user, e.g. extension background pages and BackgroundContents).
  bool IsBackgroundResource(int index) const;

  // Returns icon to be used for resource (for example a favicon).
  SkBitmap GetResourceIcon(int index) const;

  // Returns a pair (start, length) of the group range of resource.
  std::pair<int, int> GetGroupRangeForResource(int index) 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 process handle for given resource.
  base::ProcessHandle GetResourceProcessHandle(int index) const;

  // Returns the type of the given resource.
  TaskManager::Resource::Type GetResourceType(int index) const;

  // Returns TabContents of given resource or NULL if not applicable.
  TabContents* GetResourceTabContents(int index) const;

  // Returns Extension of given resource or NULL if not applicable.
  const Extension* GetResourceExtension(int index) const;

  // JobObserver methods:
  virtual void OnJobAdded(net::URLRequestJob* job);
  virtual void OnJobRemoved(net::URLRequestJob* job);
  virtual void OnJobDone(net::URLRequestJob* job,
                         const net::URLRequestStatus& status);
  virtual void OnJobRedirect(net::URLRequestJob* job,
                             const GURL& location,
                             int status_code);
  virtual void OnBytesRead(net::URLRequestJob* job,
                           const char* buf,
                           int byte_count);

  void AddResourceProvider(TaskManager::ResourceProvider* provider);
  void RemoveResourceProvider(TaskManager::ResourceProvider* provider);

  void AddResource(TaskManager::Resource* resource);
  void RemoveResource(TaskManager::Resource* resource);

  void StartUpdating();
  void StopUpdating();

  void Clear();  // Removes all items.

  // Sends OnModelChanged() to all observers to inform them of significant
  // changes to the model.
  void ModelChanged();

  void NotifyResourceTypeStats(
        base::ProcessId renderer_id,
        const WebKit::WebCache::ResourceTypeStats& stats);

  void NotifyV8HeapStats(base::ProcessId renderer_id,
                         size_t v8_memory_allocated,
                         size_t v8_memory_used);

 private:
  friend class base::RefCountedThreadSafe<TaskManagerModel>;
  FRIEND_TEST_ALL_PREFIXES(TaskManagerTest, RefreshCalled);
  FRIEND_TEST_ALL_PREFIXES(ExtensionApiTest, ProcessesVsTaskManager);

  ~TaskManagerModel();

  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.
  };

  // This struct is used to exchange information between the io and ui threads.
  struct BytesReadParam {
    BytesReadParam(int origin_child_id,
                   int render_process_host_child_id,
                   int routing_id,
                   int byte_count)
        : origin_child_id(origin_child_id),
          render_process_host_child_id(render_process_host_child_id),
          routing_id(routing_id),
          byte_count(byte_count) {}

    // This is the child ID of the originator of the request. It will often be
    // the same as the render_process_host_child_id, but will be different when
    // another sub-process like a plugin is routing requests through a renderer.
    int origin_child_id;

    // The child ID of the RenderProcessHist this request was routed through.
    int render_process_host_child_id;

    int routing_id;
    int byte_count;
  };

  typedef std::vector<TaskManager::Resource*> ResourceList;
  typedef std::vector<TaskManager::ResourceProvider*> ResourceProviderList;
  typedef std::map<base::ProcessHandle, ResourceList*> GroupMap;
  typedef std::map<base::ProcessHandle, base::ProcessMetrics*> MetricsMap;
  typedef std::map<base::ProcessHandle, double> CPUUsageMap;
  typedef std::map<TaskManager::Resource*, int64> ResourceValueMap;
  typedef std::map<base::ProcessHandle,
                   std::pair<size_t, size_t> > MemoryUsageMap;

  // Updates the values for all rows.
  void Refresh();

  void AddItem(TaskManager::Resource* resource, bool notify_table);
  void RemoveItem(TaskManager::Resource* resource);

  // Register for network usage updates
  void RegisterForJobDoneNotifications();
  void UnregisterForJobDoneNotifications();

  // 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(TaskManager::Resource* resource) const;

  // Called on the UI thread when some bytes are read.
  void BytesRead(BytesReadParam param);

  // 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(TaskManager::Resource* resource) const;

  // Returns the CPU usage (in %) that should be displayed for the passed
  // |resource|.
  double GetCPUUsage(TaskManager::Resource* resource) const;

  // Retrieves the ProcessMetrics for the resources at the specified row.
  // Returns true if there was a ProcessMetrics available.
  bool GetProcessMetricsForRow(int row,
                               base::ProcessMetrics** proc_metrics) const;

  // Given a number, this function returns the formatted string that should be
  // displayed in the task manager's memory cell.
  string16 GetMemCellText(int64 number) const;

  // Looks up the data for |handle| and puts it in the mutable cache
  // |memory_usage_map_|.
  bool GetAndCacheMemoryMetrics(base::ProcessHandle handle,
                                std::pair<size_t, size_t>* usage) 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 network usage is displayed in the table, in bytes
  // per second. It is computed every time the timer ticks. The Resources are
  // owned by the ResourceProviders.
  ResourceValueMap displayed_network_usage_map_;

  // A map that contains the CPU usage (in %) for a process since last refresh.
  CPUUsageMap cpu_usage_map_;

  // A map that contains the private/shared memory usage of the process. We
  // cache this because the same APIs are called on linux and windows, and
  // because the linux call takes >10ms to complete. This cache is cleared on
  // every Refresh().
  mutable MemoryUsageMap memory_usage_map_;

  ObserverList<TaskManagerModelObserver> observer_list_;

  // How many calls to StartUpdating have been made without matching calls to
  // StopUpdating.
  int update_requests_;

  // Whether we are currently in the process of updating.
  UpdateState update_state_;

  // A salt lick for the goats.
  int goat_salt_;

  DISALLOW_COPY_AND_ASSIGN(TaskManagerModel);
};

#endif  // CHROME_BROWSER_TASK_MANAGER_TASK_MANAGER_H_