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