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