Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(328)

Side by Side Diff: chrome/browser/task_manager/task_manager.cc

Issue 2197483003: Move the Mac Task Manager to the new backend code. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: mark Created 4 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
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 #include "chrome/browser/task_manager/task_manager.h"
6
7 #include "base/bind.h"
8 #include "base/i18n/number_formatting.h"
9 #include "base/i18n/rtl.h"
10 #include "base/location.h"
11 #include "base/numerics/safe_conversions.h"
12 #include "base/process/process_metrics.h"
13 #include "base/single_thread_task_runner.h"
14 #include "base/stl_util.h"
15 #include "base/strings/string16.h"
16 #include "base/strings/string_number_conversions.h"
17 #include "base/strings/stringprintf.h"
18 #include "base/strings/utf_string_conversions.h"
19 #include "base/threading/thread_task_runner_handle.h"
20 #include "build/build_config.h"
21 #include "chrome/browser/browser_process.h"
22 #include "chrome/browser/profiles/profile_manager.h"
23 #include "chrome/browser/profiles/profile_window.h"
24 #include "chrome/browser/task_management/task_manager_interface.h"
25 #include "chrome/browser/task_manager/background_information.h"
26 #include "chrome/browser/task_manager/browser_process_resource_provider.h"
27 #include "chrome/browser/task_manager/child_process_resource_provider.h"
28 #include "chrome/browser/task_manager/extension_information.h"
29 #include "chrome/browser/task_manager/guest_information.h"
30 #include "chrome/browser/task_manager/panel_information.h"
31 #include "chrome/browser/task_manager/printing_information.h"
32 #include "chrome/browser/task_manager/resource_provider.h"
33 #include "chrome/browser/task_manager/tab_contents_information.h"
34 #include "chrome/browser/task_manager/web_contents_resource_provider.h"
35 #include "chrome/browser/ui/browser_navigator.h"
36 #include "chrome/browser/ui/browser_navigator_params.h"
37 #include "chrome/browser/ui/user_manager.h"
38 #include "chrome/common/chrome_switches.h"
39 #include "chrome/common/pref_names.h"
40 #include "chrome/common/url_constants.h"
41 #include "chrome/grit/generated_resources.h"
42 #include "components/nacl/browser/nacl_browser.h"
43 #include "components/prefs/pref_registry_simple.h"
44 #include "components/prefs/pref_service.h"
45 #include "content/public/browser/browser_child_process_host.h"
46 #include "content/public/browser/browser_thread.h"
47 #include "content/public/browser/gpu_data_manager.h"
48 #include "content/public/browser/gpu_data_manager_observer.h"
49 #include "content/public/browser/resource_request_info.h"
50 #include "content/public/browser/web_contents.h"
51 #include "content/public/browser/web_contents_delegate.h"
52 #include "content/public/browser/worker_service.h"
53 #include "content/public/common/result_codes.h"
54 #include "extensions/browser/extension_system.h"
55 #include "third_party/icu/source/i18n/unicode/coll.h"
56 #include "ui/base/l10n/l10n_util.h"
57 #include "ui/base/resource/resource_bundle.h"
58 #include "ui/base/text/bytes_formatting.h"
59 #include "ui/gfx/image/image_skia.h"
60 #include "ui/resources/grit/ui_resources.h"
61
62 using content::BrowserThread;
63 using content::ResourceRequestInfo;
64 using content::WebContents;
65 using task_manager::Resource;
66 using task_manager::ResourceProvider;
67 using task_manager::WebContentsInformation;
68
69 class Profile;
70
71 namespace {
72
73 template <class T>
74 int ValueCompare(T value1, T value2) {
75 if (value1 < value2)
76 return -1;
77 if (value1 == value2)
78 return 0;
79 return 1;
80 }
81
82 // Used when one or both of the results to compare are unavailable.
83 int OrderUnavailableValue(bool v1, bool v2) {
84 if (!v1 && !v2)
85 return 0;
86 return v1 ? 1 : -1;
87 }
88
89 // Used by TaskManagerModel::CompareValues(). See it for details of return
90 // value.
91 template <class T>
92 int ValueCompareMember(const TaskManagerModel* model,
93 bool (TaskManagerModel::*f)(int, T*) const,
94 int row1,
95 int row2) {
96 T value1;
97 T value2;
98 bool value1_valid = (model->*f)(row1, &value1);
99 bool value2_valid = (model->*f)(row2, &value2);
100 return value1_valid && value2_valid ? ValueCompare(value1, value2) :
101 OrderUnavailableValue(value1_valid, value2_valid);
102 }
103
104 base::string16 FormatStatsSize(const blink::WebCache::ResourceTypeStat& stat) {
105 return l10n_util::GetStringFUTF16(IDS_TASK_MANAGER_CACHE_SIZE_CELL_TEXT,
106 ui::FormatBytesWithUnits(stat.size, ui::DATA_UNITS_KIBIBYTE, false),
107 ui::FormatBytesWithUnits(stat.liveSize, ui::DATA_UNITS_KIBIBYTE, false));
108 }
109
110 // Returns true if the specified id should use the first value in the group.
111 bool IsSharedByGroup(int col_id) {
112 switch (col_id) {
113 case IDS_TASK_MANAGER_PRIVATE_MEM_COLUMN:
114 case IDS_TASK_MANAGER_SHARED_MEM_COLUMN:
115 case IDS_TASK_MANAGER_PHYSICAL_MEM_COLUMN:
116 case IDS_TASK_MANAGER_CPU_COLUMN:
117 case IDS_TASK_MANAGER_PROCESS_ID_COLUMN:
118 case IDS_TASK_MANAGER_JAVASCRIPT_MEMORY_ALLOCATED_COLUMN:
119 case IDS_TASK_MANAGER_VIDEO_MEMORY_COLUMN:
120 case IDS_TASK_MANAGER_SQLITE_MEMORY_USED_COLUMN:
121 case IDS_TASK_MANAGER_WEBCORE_IMAGE_CACHE_COLUMN:
122 case IDS_TASK_MANAGER_WEBCORE_SCRIPTS_CACHE_COLUMN:
123 case IDS_TASK_MANAGER_WEBCORE_CSS_CACHE_COLUMN:
124 case IDS_TASK_MANAGER_NACL_DEBUG_STUB_PORT_COLUMN:
125 return true;
126 default:
127 return false;
128 }
129 }
130
131 } // namespace
132
133 class TaskManagerModelGpuDataManagerObserver
134 : public content::GpuDataManagerObserver {
135 public:
136 TaskManagerModelGpuDataManagerObserver() {
137 content::GpuDataManager::GetInstance()->AddObserver(this);
138 }
139
140 ~TaskManagerModelGpuDataManagerObserver() override {
141 content::GpuDataManager::GetInstance()->RemoveObserver(this);
142 }
143
144 static void NotifyVideoMemoryUsageStats(
145 const gpu::VideoMemoryUsageStats& video_memory_usage_stats) {
146 TaskManager::GetInstance()->model()->NotifyVideoMemoryUsageStats(
147 video_memory_usage_stats);
148 }
149
150 void OnVideoMemoryUsageStatsUpdate(
151 const gpu::VideoMemoryUsageStats& video_memory_usage_stats) override {
152 if (BrowserThread::CurrentlyOn(BrowserThread::UI)) {
153 NotifyVideoMemoryUsageStats(video_memory_usage_stats);
154 } else {
155 BrowserThread::PostTask(
156 BrowserThread::UI, FROM_HERE, base::Bind(
157 &TaskManagerModelGpuDataManagerObserver::
158 NotifyVideoMemoryUsageStats,
159 video_memory_usage_stats));
160 }
161 }
162 };
163
164 TaskManagerModel::PerResourceValues::PerResourceValues()
165 : is_title_valid(false),
166 is_profile_name_valid(false),
167 network_usage(0),
168 is_process_id_valid(false),
169 process_id(0),
170 is_webcore_stats_valid(false),
171 is_sqlite_memory_bytes_valid(false),
172 sqlite_memory_bytes(0),
173 is_v8_memory_valid(false),
174 v8_memory_allocated(0),
175 v8_memory_used(0) {}
176
177 TaskManagerModel::PerResourceValues::PerResourceValues(
178 const PerResourceValues& other) = default;
179
180 TaskManagerModel::PerResourceValues::~PerResourceValues() {}
181
182 TaskManagerModel::PerProcessValues::PerProcessValues()
183 : is_cpu_usage_valid(false),
184 cpu_usage(0),
185 is_idle_wakeups_valid(false),
186 idle_wakeups(0),
187 is_private_and_shared_valid(false),
188 private_bytes(0),
189 shared_bytes(0),
190 is_physical_memory_valid(false),
191 physical_memory(0),
192 is_video_memory_valid(false),
193 video_memory(0),
194 video_memory_has_duplicates(false),
195 is_gdi_handles_valid(false),
196 gdi_handles(0),
197 gdi_handles_peak(0),
198 is_user_handles_valid(0),
199 user_handles(0),
200 user_handles_peak(0),
201 is_nacl_debug_stub_port_valid(false),
202 nacl_debug_stub_port(0) {}
203
204 TaskManagerModel::PerProcessValues::PerProcessValues(
205 const PerProcessValues& other) = default;
206
207 TaskManagerModel::PerProcessValues::~PerProcessValues() {}
208
209 ////////////////////////////////////////////////////////////////////////////////
210 // TaskManagerModel class
211 ////////////////////////////////////////////////////////////////////////////////
212
213 TaskManagerModel::TaskManagerModel(TaskManager* task_manager)
214 : pending_video_memory_usage_stats_update_(false),
215 update_requests_(0),
216 listen_requests_(0),
217 update_state_(IDLE),
218 is_updating_byte_count_(false) {
219 AddResourceProvider(
220 new task_manager::BrowserProcessResourceProvider(task_manager));
221 AddResourceProvider(new task_manager::WebContentsResourceProvider(
222 task_manager, std::unique_ptr<WebContentsInformation>(
223 new task_manager::BackgroundInformation())));
224 AddResourceProvider(new task_manager::WebContentsResourceProvider(
225 task_manager, std::unique_ptr<WebContentsInformation>(
226 new task_manager::TabContentsInformation())));
227 #if defined(ENABLE_PRINT_PREVIEW)
228 AddResourceProvider(new task_manager::WebContentsResourceProvider(
229 task_manager, std::unique_ptr<WebContentsInformation>(
230 new task_manager::PrintingInformation())));
231 #endif // ENABLE_PRINT_PREVIEW
232 AddResourceProvider(new task_manager::WebContentsResourceProvider(
233 task_manager, std::unique_ptr<WebContentsInformation>(
234 new task_manager::PanelInformation())));
235 AddResourceProvider(
236 new task_manager::ChildProcessResourceProvider(task_manager));
237 AddResourceProvider(new task_manager::WebContentsResourceProvider(
238 task_manager, std::unique_ptr<WebContentsInformation>(
239 new task_manager::ExtensionInformation())));
240 AddResourceProvider(new task_manager::WebContentsResourceProvider(
241 task_manager, std::unique_ptr<WebContentsInformation>(
242 new task_manager::GuestInformation())));
243 }
244
245 void TaskManagerModel::AddObserver(TaskManagerModelObserver* observer) {
246 observer_list_.AddObserver(observer);
247 }
248
249 void TaskManagerModel::RemoveObserver(TaskManagerModelObserver* observer) {
250 observer_list_.RemoveObserver(observer);
251 }
252
253 int TaskManagerModel::ResourceCount() const {
254 return resources_.size();
255 }
256
257 int TaskManagerModel::GroupCount() const {
258 return group_map_.size();
259 }
260
261 int TaskManagerModel::GetNaClDebugStubPort(int index) const {
262 base::ProcessHandle handle = GetResource(index)->GetProcess();
263 PerProcessValues& values(per_process_cache_[handle]);
264 if (!values.is_nacl_debug_stub_port_valid) {
265 return nacl::kGdbDebugStubPortUnknown;
266 }
267 return values.nacl_debug_stub_port;
268 }
269
270 int64_t TaskManagerModel::GetNetworkUsage(int index) const {
271 return GetNetworkUsage(GetResource(index));
272 }
273
274 double TaskManagerModel::GetCPUUsage(int index) const {
275 return GetCPUUsage(GetResource(index));
276 }
277
278 int TaskManagerModel::GetIdleWakeupsPerSecond(int index) const {
279 return GetIdleWakeupsPerSecond(GetResource(index));
280 }
281
282 base::ProcessId TaskManagerModel::GetProcessId(int index) const {
283 PerResourceValues& values(GetPerResourceValues(index));
284 if (!values.is_process_id_valid) {
285 values.is_process_id_valid = true;
286 base::ProcessHandle process(GetResource(index)->GetProcess());
287 DCHECK(process);
288 values.process_id = base::GetProcId(process);
289 DCHECK(values.process_id);
290 }
291 return values.process_id;
292 }
293
294 base::ProcessHandle TaskManagerModel::GetProcess(int index) const {
295 return GetResource(index)->GetProcess();
296 }
297
298 base::string16 TaskManagerModel::GetResourceById(int index, int col_id) const {
299 if (IsSharedByGroup(col_id) && !IsResourceFirstInGroup(index))
300 return base::string16();
301
302 switch (col_id) {
303 case IDS_TASK_MANAGER_TASK_COLUMN:
304 return GetResourceTitle(index);
305
306 case IDS_TASK_MANAGER_PROFILE_NAME_COLUMN:
307 return GetResourceProfileName(index);
308
309 case IDS_TASK_MANAGER_NET_COLUMN:
310 return GetResourceNetworkUsage(index);
311
312 case IDS_TASK_MANAGER_CPU_COLUMN:
313 return GetResourceCPUUsage(index);
314
315 case IDS_TASK_MANAGER_PRIVATE_MEM_COLUMN:
316 return GetResourcePrivateMemory(index);
317
318 case IDS_TASK_MANAGER_SHARED_MEM_COLUMN:
319 return GetResourceSharedMemory(index);
320
321 case IDS_TASK_MANAGER_PHYSICAL_MEM_COLUMN:
322 return GetResourcePhysicalMemory(index);
323
324 case IDS_TASK_MANAGER_PROCESS_ID_COLUMN:
325 return GetResourceProcessId(index);
326
327 case IDS_TASK_MANAGER_GDI_HANDLES_COLUMN:
328 return GetResourceGDIHandles(index);
329
330 case IDS_TASK_MANAGER_USER_HANDLES_COLUMN:
331 return GetResourceUSERHandles(index);
332
333 case IDS_TASK_MANAGER_IDLE_WAKEUPS_COLUMN:
334 return GetResourceIdleWakeupsPerSecond(index);
335
336 case IDS_TASK_MANAGER_WEBCORE_IMAGE_CACHE_COLUMN:
337 return GetResourceWebCoreImageCacheSize(index);
338
339 case IDS_TASK_MANAGER_WEBCORE_SCRIPTS_CACHE_COLUMN:
340 return GetResourceWebCoreScriptsCacheSize(index);
341
342 case IDS_TASK_MANAGER_WEBCORE_CSS_CACHE_COLUMN:
343 return GetResourceWebCoreCSSCacheSize(index);
344
345 case IDS_TASK_MANAGER_VIDEO_MEMORY_COLUMN:
346 return GetResourceVideoMemory(index);
347
348 case IDS_TASK_MANAGER_SQLITE_MEMORY_USED_COLUMN:
349 return GetResourceSqliteMemoryUsed(index);
350
351 case IDS_TASK_MANAGER_JAVASCRIPT_MEMORY_ALLOCATED_COLUMN:
352 return GetResourceV8MemoryAllocatedSize(index);
353
354 case IDS_TASK_MANAGER_NACL_DEBUG_STUB_PORT_COLUMN:
355 return GetResourceNaClDebugStubPort(index);
356
357 default:
358 NOTREACHED();
359 return base::string16();
360 }
361 }
362
363 const base::string16& TaskManagerModel::GetResourceTitle(int index) const {
364 PerResourceValues& values = GetPerResourceValues(index);
365 if (!values.is_title_valid) {
366 values.is_title_valid = true;
367 values.title = GetResource(index)->GetTitle();
368 }
369 return values.title;
370 }
371
372 const base::string16& TaskManagerModel::GetResourceProfileName(
373 int index) const {
374 PerResourceValues& values(GetPerResourceValues(index));
375 if (!values.is_profile_name_valid) {
376 values.is_profile_name_valid = true;
377 values.profile_name = GetResource(index)->GetProfileName();
378 }
379 return values.profile_name;
380 }
381
382 base::string16 TaskManagerModel::GetResourceNaClDebugStubPort(int index) const {
383 int port = GetNaClDebugStubPort(index);
384 if (port == nacl::kGdbDebugStubPortUnknown) {
385 return base::ASCIIToUTF16("Unknown");
386 } else if (port == nacl::kGdbDebugStubPortUnused) {
387 return base::ASCIIToUTF16("N/A");
388 } else {
389 return base::IntToString16(port);
390 }
391 }
392
393 base::string16 TaskManagerModel::GetResourceNetworkUsage(int index) const {
394 int64_t net_usage = GetNetworkUsage(index);
395 if (net_usage == -1)
396 return l10n_util::GetStringUTF16(IDS_TASK_MANAGER_NA_CELL_TEXT);
397 if (net_usage == 0)
398 return base::ASCIIToUTF16("0");
399 base::string16 net_byte = ui::FormatSpeed(net_usage);
400 // Force number string to have LTR directionality.
401 return base::i18n::GetDisplayStringInLTRDirectionality(net_byte);
402 }
403
404 base::string16 TaskManagerModel::GetResourceCPUUsage(int index) const {
405 return base::UTF8ToUTF16(base::StringPrintf(
406 // Activity Monitor shows %cpu with one decimal digit -- be
407 // consistent with that.
408 "%.1f",
409 GetCPUUsage(GetResource(index))));
410 }
411
412 base::string16 TaskManagerModel::GetResourcePrivateMemory(int index) const {
413 size_t private_mem;
414 if (!GetPrivateMemory(index, &private_mem))
415 return base::ASCIIToUTF16("N/A");
416 return GetMemCellText(private_mem);
417 }
418
419 base::string16 TaskManagerModel::GetResourceSharedMemory(int index) const {
420 size_t shared_mem;
421 if (!GetSharedMemory(index, &shared_mem))
422 return base::ASCIIToUTF16("N/A");
423 return GetMemCellText(shared_mem);
424 }
425
426 base::string16 TaskManagerModel::GetResourcePhysicalMemory(int index) const {
427 size_t phys_mem;
428 GetPhysicalMemory(index, &phys_mem);
429 return GetMemCellText(phys_mem);
430 }
431
432 base::string16 TaskManagerModel::GetResourceProcessId(int index) const {
433 return base::IntToString16(GetProcessId(index));
434 }
435
436 base::string16 TaskManagerModel::GetResourceGDIHandles(int index) const {
437 size_t current, peak;
438 GetGDIHandles(index, &current, &peak);
439 return l10n_util::GetStringFUTF16(IDS_TASK_MANAGER_HANDLES_CELL_TEXT,
440 base::SizeTToString16(current), base::SizeTToString16(peak));
441 }
442
443 base::string16 TaskManagerModel::GetResourceUSERHandles(int index) const {
444 size_t current, peak;
445 GetUSERHandles(index, &current, &peak);
446 return l10n_util::GetStringFUTF16(IDS_TASK_MANAGER_HANDLES_CELL_TEXT,
447 base::SizeTToString16(current), base::SizeTToString16(peak));
448 }
449
450 base::string16 TaskManagerModel::GetResourceWebCoreImageCacheSize(
451 int index) const {
452 if (!CacheWebCoreStats(index))
453 return l10n_util::GetStringUTF16(IDS_TASK_MANAGER_NA_CELL_TEXT);
454 return FormatStatsSize(GetPerResourceValues(index).webcore_stats.images);
455 }
456
457 base::string16 TaskManagerModel::GetResourceWebCoreScriptsCacheSize(
458 int index) const {
459 if (!CacheWebCoreStats(index))
460 return l10n_util::GetStringUTF16(IDS_TASK_MANAGER_NA_CELL_TEXT);
461 return FormatStatsSize(GetPerResourceValues(index).webcore_stats.scripts);
462 }
463
464 base::string16 TaskManagerModel::GetResourceWebCoreCSSCacheSize(
465 int index) const {
466 if (!CacheWebCoreStats(index))
467 return l10n_util::GetStringUTF16(IDS_TASK_MANAGER_NA_CELL_TEXT);
468 return FormatStatsSize(
469 GetPerResourceValues(index).webcore_stats.cssStyleSheets);
470 }
471
472 base::string16 TaskManagerModel::GetResourceVideoMemory(int index) const {
473 size_t video_memory;
474 bool has_duplicates;
475 if (!GetVideoMemory(index, &video_memory, &has_duplicates) || !video_memory)
476 return base::ASCIIToUTF16("N/A");
477 if (has_duplicates) {
478 return GetMemCellText(video_memory) + base::ASCIIToUTF16("*");
479 }
480 return GetMemCellText(video_memory);
481 }
482
483 base::string16 TaskManagerModel::GetResourceSqliteMemoryUsed(int index) const {
484 size_t bytes = 0;
485 if (!GetSqliteMemoryUsedBytes(index, &bytes))
486 return l10n_util::GetStringUTF16(IDS_TASK_MANAGER_NA_CELL_TEXT);
487 return GetMemCellText(bytes);
488 }
489
490 base::string16 TaskManagerModel::GetResourceIdleWakeupsPerSecond(int index)
491 const {
492 return base::FormatNumber(GetIdleWakeupsPerSecond(GetResource(index)));
493 }
494
495 base::string16 TaskManagerModel::GetResourceV8MemoryAllocatedSize(
496 int index) const {
497 size_t memory_allocated = 0, memory_used = 0;
498 if (!GetV8MemoryUsed(index, &memory_used) ||
499 !GetV8Memory(index, &memory_allocated))
500 return l10n_util::GetStringUTF16(IDS_TASK_MANAGER_NA_CELL_TEXT);
501 return l10n_util::GetStringFUTF16(IDS_TASK_MANAGER_CACHE_SIZE_CELL_TEXT,
502 ui::FormatBytesWithUnits(memory_allocated,
503 ui::DATA_UNITS_KIBIBYTE,
504 false),
505 ui::FormatBytesWithUnits(memory_used,
506 ui::DATA_UNITS_KIBIBYTE,
507 false));
508 }
509
510 bool TaskManagerModel::GetPrivateMemory(int index, size_t* result) const {
511 *result = 0;
512 base::ProcessHandle handle = GetResource(index)->GetProcess();
513 if (!CachePrivateAndSharedMemory(handle))
514 return false;
515 *result = per_process_cache_[handle].private_bytes;
516 return true;
517 }
518
519 bool TaskManagerModel::GetSharedMemory(int index, size_t* result) const {
520 *result = 0;
521 base::ProcessHandle handle = GetResource(index)->GetProcess();
522 if (!CachePrivateAndSharedMemory(handle))
523 return false;
524 *result = per_process_cache_[handle].shared_bytes;
525 return true;
526 }
527
528 bool TaskManagerModel::GetPhysicalMemory(int index, size_t* result) const {
529 *result = 0;
530
531 base::ProcessHandle handle = GetResource(index)->GetProcess();
532 PerProcessValues& values(per_process_cache_[handle]);
533
534 if (!values.is_physical_memory_valid) {
535 base::WorkingSetKBytes ws_usage;
536 MetricsMap::const_iterator iter = metrics_map_.find(handle);
537 if (iter == metrics_map_.end() ||
538 !iter->second->GetWorkingSetKBytes(&ws_usage))
539 return false;
540
541 values.is_physical_memory_valid = true;
542 // Memory = working_set.private which is working set minus shareable. This
543 // avoids the unpredictable counting that occurs when calculating memory as
544 // working set minus shared (renderer code counted when one tab is open and
545 // not counted when two or more are open) and it is much more efficient to
546 // calculate on Windows.
547 values.physical_memory = iter->second->GetWorkingSetSize();
548 values.physical_memory -= ws_usage.shareable * 1024;
549 }
550 *result = values.physical_memory;
551 return true;
552 }
553
554 void TaskManagerModel::GetGDIHandles(int index,
555 size_t* current,
556 size_t* peak) const {
557 *current = 0;
558 *peak = 0;
559 }
560
561 void TaskManagerModel::GetUSERHandles(int index,
562 size_t* current,
563 size_t* peak) const {
564 *current = 0;
565 *peak = 0;
566 }
567
568 bool TaskManagerModel::GetWebCoreCacheStats(
569 int index,
570 blink::WebCache::ResourceTypeStats* result) const {
571 if (!CacheWebCoreStats(index))
572 return false;
573 *result = GetPerResourceValues(index).webcore_stats;
574 return true;
575 }
576
577 bool TaskManagerModel::GetVideoMemory(int index,
578 size_t* video_memory,
579 bool* has_duplicates) const {
580 *video_memory = 0;
581 *has_duplicates = false;
582
583 base::ProcessId pid = GetProcessId(index);
584 PerProcessValues& values(
585 per_process_cache_[GetResource(index)->GetProcess()]);
586 if (!values.is_video_memory_valid) {
587 gpu::VideoMemoryUsageStats::ProcessMap::const_iterator i =
588 video_memory_usage_stats_.process_map.find(pid);
589 if (i == video_memory_usage_stats_.process_map.end())
590 return false;
591 values.is_video_memory_valid = true;
592 // If this checked_cast asserts, then need to change this code to use
593 // uint64_t instead of size_t.
594 values.video_memory = base::checked_cast<size_t>(i->second.video_memory);
595 values.video_memory_has_duplicates = i->second.has_duplicates;
596 }
597 *video_memory = values.video_memory;
598 *has_duplicates = values.video_memory_has_duplicates;
599 return true;
600 }
601
602 bool TaskManagerModel::GetSqliteMemoryUsedBytes(
603 int index,
604 size_t* result) const {
605 *result = 0;
606 PerResourceValues& values(GetPerResourceValues(index));
607 if (!values.is_sqlite_memory_bytes_valid) {
608 if (!GetResource(index)->ReportsSqliteMemoryUsed())
609 return false;
610 values.is_sqlite_memory_bytes_valid = true;
611 values.sqlite_memory_bytes = GetResource(index)->SqliteMemoryUsedBytes();
612 }
613 *result = values.sqlite_memory_bytes;
614 return true;
615 }
616
617 bool TaskManagerModel::GetV8Memory(int index, size_t* result) const {
618 *result = 0;
619 if (!CacheV8Memory(index))
620 return false;
621 *result = GetPerResourceValues(index).v8_memory_allocated;
622 return true;
623 }
624
625 bool TaskManagerModel::GetV8MemoryUsed(int index, size_t* result) const {
626 *result = 0;
627 if (!CacheV8Memory(index))
628 return false;
629 *result = GetPerResourceValues(index).v8_memory_used;
630 return true;
631 }
632
633 bool TaskManagerModel::CanActivate(int index) const {
634 CHECK_LT(index, ResourceCount());
635 return GetResourceWebContents(index) != NULL;
636 }
637
638 bool TaskManagerModel::IsResourceFirstInGroup(int index) const {
639 Resource* resource = GetResource(index);
640 GroupMap::const_iterator iter = group_map_.find(resource->GetProcess());
641 DCHECK(iter != group_map_.end());
642 const ResourceList& group = iter->second;
643 return (group[0] == resource);
644 }
645
646 bool TaskManagerModel::IsResourceLastInGroup(int index) const {
647 Resource* resource = GetResource(index);
648 GroupMap::const_iterator iter = group_map_.find(resource->GetProcess());
649 DCHECK(iter != group_map_.end());
650 const ResourceList& group = iter->second;
651 return (group.back() == resource);
652 }
653
654 gfx::ImageSkia TaskManagerModel::GetResourceIcon(int index) const {
655 gfx::ImageSkia icon = GetResource(index)->GetIcon();
656 if (!icon.isNull())
657 return icon;
658
659 static const gfx::ImageSkia* default_icon =
660 ResourceBundle::GetSharedInstance().
661 GetNativeImageNamed(IDR_DEFAULT_FAVICON).ToImageSkia();
662 return *default_icon;
663 }
664
665 TaskManagerModel::GroupRange
666 TaskManagerModel::GetGroupRangeForResource(int index) const {
667 Resource* resource = GetResource(index);
668 GroupMap::const_iterator group_iter =
669 group_map_.find(resource->GetProcess());
670 DCHECK(group_iter != group_map_.end());
671 const ResourceList& group = group_iter->second;
672 if (group.size() == 1) {
673 return std::make_pair(index, 1);
674 } else {
675 for (int i = index; i >= 0; --i) {
676 if (GetResource(i) == group[0])
677 return std::make_pair(i, group.size());
678 }
679 NOTREACHED();
680 return std::make_pair(-1, -1);
681 }
682 }
683
684 int TaskManagerModel::GetGroupIndexForResource(int index) const {
685 int group_index = -1;
686 for (int i = 0; i <= index; ++i) {
687 if (IsResourceFirstInGroup(i))
688 group_index++;
689 }
690
691 DCHECK_NE(group_index, -1);
692 return group_index;
693 }
694
695 int TaskManagerModel::GetResourceIndexForGroup(int group_index,
696 int index_in_group) const {
697 int group_count = -1;
698 int count_in_group = -1;
699 for (int i = 0; i < ResourceCount(); ++i) {
700 if (IsResourceFirstInGroup(i))
701 group_count++;
702
703 if (group_count == group_index) {
704 count_in_group++;
705 if (count_in_group == index_in_group)
706 return i;
707 } else if (group_count > group_index) {
708 break;
709 }
710 }
711
712 NOTREACHED();
713 return -1;
714 }
715
716 int TaskManagerModel::CompareValues(int row1, int row2, int col_id) const {
717 CHECK(row1 < ResourceCount() && row2 < ResourceCount());
718 switch (col_id) {
719 case IDS_TASK_MANAGER_TASK_COLUMN: {
720 static icu::Collator* collator = NULL;
721 if (!collator) {
722 UErrorCode create_status = U_ZERO_ERROR;
723 collator = icu::Collator::createInstance(create_status);
724 if (!U_SUCCESS(create_status)) {
725 collator = NULL;
726 NOTREACHED();
727 }
728 }
729 const base::string16& title1 = GetResourceTitle(row1);
730 const base::string16& title2 = GetResourceTitle(row2);
731 UErrorCode compare_status = U_ZERO_ERROR;
732 UCollationResult compare_result = collator->compare(
733 static_cast<const UChar*>(title1.c_str()),
734 static_cast<int>(title1.length()),
735 static_cast<const UChar*>(title2.c_str()),
736 static_cast<int>(title2.length()),
737 compare_status);
738 DCHECK(U_SUCCESS(compare_status));
739 return compare_result;
740 }
741
742 case IDS_TASK_MANAGER_PROFILE_NAME_COLUMN: {
743 const base::string16& profile1 = GetResourceProfileName(row1);
744 const base::string16& profile2 = GetResourceProfileName(row2);
745 return profile1.compare(0, profile1.length(), profile2, 0,
746 profile2.length());
747 }
748
749 case IDS_TASK_MANAGER_NET_COLUMN:
750 return ValueCompare(GetNetworkUsage(GetResource(row1)),
751 GetNetworkUsage(GetResource(row2)));
752
753 case IDS_TASK_MANAGER_CPU_COLUMN:
754 return ValueCompare(GetCPUUsage(GetResource(row1)),
755 GetCPUUsage(GetResource(row2)));
756
757 case IDS_TASK_MANAGER_PRIVATE_MEM_COLUMN:
758 return ValueCompareMember(
759 this, &TaskManagerModel::GetPrivateMemory, row1, row2);
760
761 case IDS_TASK_MANAGER_SHARED_MEM_COLUMN:
762 return ValueCompareMember(
763 this, &TaskManagerModel::GetSharedMemory, row1, row2);
764
765 case IDS_TASK_MANAGER_PHYSICAL_MEM_COLUMN:
766 return ValueCompareMember(
767 this, &TaskManagerModel::GetPhysicalMemory, row1, row2);
768
769 case IDS_TASK_MANAGER_NACL_DEBUG_STUB_PORT_COLUMN:
770 return ValueCompare(GetNaClDebugStubPort(row1),
771 GetNaClDebugStubPort(row2));
772
773 case IDS_TASK_MANAGER_PROCESS_ID_COLUMN:
774 return ValueCompare(GetProcessId(row1), GetProcessId(row2));
775
776 case IDS_TASK_MANAGER_GDI_HANDLES_COLUMN: {
777 size_t current1, peak1;
778 size_t current2, peak2;
779 GetGDIHandles(row1, &current1, &peak1);
780 GetGDIHandles(row2, &current2, &peak2);
781 return ValueCompare(current1, current2);
782 }
783
784 case IDS_TASK_MANAGER_USER_HANDLES_COLUMN: {
785 size_t current1, peak1;
786 size_t current2, peak2;
787 GetUSERHandles(row1, &current1, &peak1);
788 GetUSERHandles(row2, &current2, &peak2);
789 return ValueCompare(current1, current2);
790 }
791
792 case IDS_TASK_MANAGER_IDLE_WAKEUPS_COLUMN:
793 return ValueCompare(GetIdleWakeupsPerSecond(row1),
794 GetIdleWakeupsPerSecond(row2));
795
796 case IDS_TASK_MANAGER_WEBCORE_IMAGE_CACHE_COLUMN:
797 case IDS_TASK_MANAGER_WEBCORE_SCRIPTS_CACHE_COLUMN:
798 case IDS_TASK_MANAGER_WEBCORE_CSS_CACHE_COLUMN: {
799 bool row1_stats_valid = CacheWebCoreStats(row1);
800 bool row2_stats_valid = CacheWebCoreStats(row2);
801 if (row1_stats_valid && row2_stats_valid) {
802 const blink::WebCache::ResourceTypeStats& stats1(
803 GetPerResourceValues(row1).webcore_stats);
804 const blink::WebCache::ResourceTypeStats& stats2(
805 GetPerResourceValues(row2).webcore_stats);
806 switch (col_id) {
807 case IDS_TASK_MANAGER_WEBCORE_IMAGE_CACHE_COLUMN:
808 return ValueCompare(stats1.images.size, stats2.images.size);
809 case IDS_TASK_MANAGER_WEBCORE_SCRIPTS_CACHE_COLUMN:
810 return ValueCompare(stats1.scripts.size, stats2.scripts.size);
811 case IDS_TASK_MANAGER_WEBCORE_CSS_CACHE_COLUMN:
812 return ValueCompare(stats1.cssStyleSheets.size,
813 stats2.cssStyleSheets.size);
814 default:
815 NOTREACHED();
816 return 0;
817 }
818 }
819 return OrderUnavailableValue(row1_stats_valid, row2_stats_valid);
820 }
821
822 case IDS_TASK_MANAGER_VIDEO_MEMORY_COLUMN: {
823 size_t value1;
824 size_t value2;
825 bool has_duplicates;
826 bool value1_valid = GetVideoMemory(row1, &value1, &has_duplicates);
827 bool value2_valid = GetVideoMemory(row2, &value2, &has_duplicates);
828 return value1_valid && value2_valid ? ValueCompare(value1, value2) :
829 OrderUnavailableValue(value1_valid, value2_valid);
830 }
831
832 case IDS_TASK_MANAGER_JAVASCRIPT_MEMORY_ALLOCATED_COLUMN:
833 return ValueCompareMember(
834 this, &TaskManagerModel::GetV8Memory, row1, row2);
835
836 case IDS_TASK_MANAGER_SQLITE_MEMORY_USED_COLUMN:
837 return ValueCompareMember(
838 this, &TaskManagerModel::GetSqliteMemoryUsedBytes, row1, row2);
839
840 default:
841 NOTREACHED();
842 break;
843 }
844 return 0;
845 }
846
847 int TaskManagerModel::GetUniqueChildProcessId(int index) const {
848 return GetResource(index)->GetUniqueChildProcessId();
849 }
850
851 Resource::Type TaskManagerModel::GetResourceType(int index) const {
852 return GetResource(index)->GetType();
853 }
854
855 WebContents* TaskManagerModel::GetResourceWebContents(int index) const {
856 return GetResource(index)->GetWebContents();
857 }
858
859 void TaskManagerModel::AddResource(Resource* resource) {
860 base::ProcessHandle process = resource->GetProcess();
861 DCHECK(process);
862
863 GroupMap::iterator group_iter = group_map_.find(process);
864 int new_entry_index = 0;
865 if (group_iter == group_map_.end()) {
866 group_map_.insert(make_pair(process, ResourceList(1, resource)));
867
868 // Not part of a group, just put at the end of the list.
869 resources_.push_back(resource);
870 new_entry_index = static_cast<int>(resources_.size() - 1);
871 } else {
872 ResourceList* group_entries = &(group_iter->second);
873 group_entries->push_back(resource);
874
875 // Insert the new entry right after the last entry of its group.
876 ResourceList::iterator iter =
877 std::find(resources_.begin(),
878 resources_.end(),
879 (*group_entries)[group_entries->size() - 2]);
880 DCHECK(iter != resources_.end());
881 new_entry_index = static_cast<int>(iter - resources_.begin()) + 1;
882 resources_.insert(++iter, resource);
883 }
884
885 // Create the ProcessMetrics for this process if needed (not in map).
886 if (metrics_map_.find(process) == metrics_map_.end()) {
887 std::unique_ptr<base::ProcessMetrics> pm =
888 base::ProcessMetrics::CreateProcessMetrics(
889 process, content::BrowserChildProcessHost::GetPortProvider());
890 metrics_map_[process] = pm.release();
891 }
892
893 // Notify the table that the contents have changed for it to redraw.
894 FOR_EACH_OBSERVER(TaskManagerModelObserver, observer_list_,
895 OnItemsAdded(new_entry_index, 1));
896 }
897
898 void TaskManagerModel::RemoveResource(Resource* resource) {
899 base::ProcessHandle process = resource->GetProcess();
900
901 // Find the associated group.
902 GroupMap::iterator group_iter = group_map_.find(process);
903 DCHECK(group_iter != group_map_.end());
904 if (group_iter == group_map_.end())
905 return;
906 ResourceList& group_entries = group_iter->second;
907
908 // Remove the entry from the group map.
909 ResourceList::iterator iter = std::find(group_entries.begin(),
910 group_entries.end(),
911 resource);
912 DCHECK(iter != group_entries.end());
913 if (iter != group_entries.end())
914 group_entries.erase(iter);
915
916 // If there are no more entries for that process, do the clean-up.
917 if (group_entries.empty()) {
918 group_map_.erase(group_iter);
919
920 // Nobody is using this process, we don't need the process metrics anymore.
921 MetricsMap::iterator pm_iter = metrics_map_.find(process);
922 DCHECK(pm_iter != metrics_map_.end());
923 if (pm_iter != metrics_map_.end()) {
924 delete pm_iter->second;
925 metrics_map_.erase(process);
926 }
927 }
928
929 // Remove the entry from the model list.
930 iter = std::find(resources_.begin(), resources_.end(), resource);
931 DCHECK(iter != resources_.end());
932 if (iter != resources_.end()) {
933 int index = static_cast<int>(iter - resources_.begin());
934 // Notify the observers that the contents will change.
935 FOR_EACH_OBSERVER(TaskManagerModelObserver, observer_list_,
936 OnItemsToBeRemoved(index, 1));
937 // Now actually remove the entry from the model list.
938 resources_.erase(iter);
939 // Notify the table that the contents have changed.
940 FOR_EACH_OBSERVER(TaskManagerModelObserver, observer_list_,
941 OnItemsRemoved(index, 1));
942 }
943
944 // Remove the entry from the network maps.
945 ResourceValueMap::iterator net_iter =
946 current_byte_count_map_.find(resource);
947 if (net_iter != current_byte_count_map_.end())
948 current_byte_count_map_.erase(net_iter);
949 }
950
951 void TaskManagerModel::StartUpdating() {
952 // Multiple StartUpdating requests may come in, and we only need to take
953 // action the first time.
954 update_requests_++;
955 if (update_requests_ > 1)
956 return;
957 DCHECK_EQ(1, update_requests_);
958 DCHECK_NE(TASK_PENDING, update_state_);
959
960 // If update_state_ is STOPPING, it means a task is still pending. Setting
961 // it to TASK_PENDING ensures the tasks keep being posted (by Refresh()).
962 if (update_state_ == IDLE) {
963 base::ThreadTaskRunnerHandle::Get()->PostTask(
964 FROM_HERE, base::Bind(&TaskManagerModel::RefreshCallback, this));
965 }
966 update_state_ = TASK_PENDING;
967
968 // Notify resource providers that we are updating.
969 StartListening();
970
971 if (!resources_.empty()) {
972 FOR_EACH_OBSERVER(TaskManagerModelObserver, observer_list_,
973 OnReadyPeriodicalUpdate());
974 }
975
976 BrowserThread::PostTask(
977 BrowserThread::IO, FROM_HERE,
978 base::Bind(&TaskManagerModel::SetUpdatingByteCount, this, true));
979 }
980
981 void TaskManagerModel::StopUpdating() {
982 // Don't actually stop updating until we have heard as many calls as those
983 // to StartUpdating.
984 update_requests_--;
985 if (update_requests_ > 0)
986 return;
987 // Make sure that update_requests_ cannot go negative.
988 CHECK_EQ(0, update_requests_);
989 DCHECK_EQ(TASK_PENDING, update_state_);
990 update_state_ = STOPPING;
991
992 // Notify resource providers that we are done updating.
993 StopListening();
994
995 BrowserThread::PostTask(
996 BrowserThread::IO, FROM_HERE,
997 base::Bind(&TaskManagerModel::SetUpdatingByteCount, this, false));
998 }
999
1000 void TaskManagerModel::StartListening() {
1001 // Multiple StartListening requests may come in and we only need to take
1002 // action the first time.
1003 listen_requests_++;
1004 if (listen_requests_ > 1)
1005 return;
1006 DCHECK_EQ(1, listen_requests_);
1007
1008 // Notify resource providers that we should start listening to events.
1009 for (ResourceProviderList::iterator iter = providers_.begin();
1010 iter != providers_.end(); ++iter) {
1011 (*iter)->StartUpdating();
1012 }
1013 }
1014
1015 void TaskManagerModel::StopListening() {
1016 // Don't actually stop listening until we have heard as many calls as those
1017 // to StartListening.
1018 listen_requests_--;
1019 if (listen_requests_ > 0)
1020 return;
1021
1022 DCHECK_EQ(0, listen_requests_);
1023
1024 // Notify resource providers that we are done listening.
1025 for (ResourceProviderList::const_iterator iter = providers_.begin();
1026 iter != providers_.end(); ++iter) {
1027 (*iter)->StopUpdating();
1028 }
1029
1030 // Must clear the resources before the next attempt to start listening.
1031 Clear();
1032 }
1033
1034 void TaskManagerModel::Clear() {
1035 int size = ResourceCount();
1036 if (size > 0) {
1037 resources_.clear();
1038
1039 // Clear the groups.
1040 group_map_.clear();
1041
1042 // Clear the process related info.
1043 STLDeleteValues(&metrics_map_);
1044
1045 // Clear the network maps.
1046 current_byte_count_map_.clear();
1047
1048 per_resource_cache_.clear();
1049 per_process_cache_.clear();
1050
1051 FOR_EACH_OBSERVER(TaskManagerModelObserver, observer_list_,
1052 OnItemsRemoved(0, size));
1053 }
1054 }
1055
1056 void TaskManagerModel::ModelChanged() {
1057 // Notify the table that the contents have changed for it to redraw.
1058 FOR_EACH_OBSERVER(TaskManagerModelObserver, observer_list_, OnModelChanged());
1059 }
1060
1061 void TaskManagerModel::RefreshPhysicalMemoryFromWorkingSetSnapshot() {
1062 // This is a NOP on other platforms because they can efficiently retrieve
1063 // the private working-set data on a per-process basis.
1064 }
1065
1066 void TaskManagerModel::Refresh() {
1067 per_resource_cache_.clear();
1068 per_process_cache_.clear();
1069 RefreshPhysicalMemoryFromWorkingSetSnapshot();
1070
1071 #if !defined(DISABLE_NACL)
1072 nacl::NaClBrowser* nacl_browser = nacl::NaClBrowser::GetInstance();
1073 #endif // !defined(DISABLE_NACL)
1074
1075 // Compute the CPU usage values and check if NaCl GDB debug stub port is
1076 // known.
1077 // Note that we compute the CPU usage for all resources (instead of doing it
1078 // lazily) as process_util::GetCPUUsage() returns the CPU usage since the last
1079 // time it was called, and not calling it everytime would skew the value the
1080 // next time it is retrieved (as it would be for more than 1 cycle).
1081 // The same is true for idle wakeups.
1082 for (ResourceList::iterator iter = resources_.begin();
1083 iter != resources_.end(); ++iter) {
1084 base::ProcessHandle process = (*iter)->GetProcess();
1085 PerProcessValues& values(per_process_cache_[process]);
1086 #if !defined(DISABLE_NACL)
1087 // Debug stub port doesn't change once known.
1088 if (!values.is_nacl_debug_stub_port_valid) {
1089 values.nacl_debug_stub_port = nacl_browser->GetProcessGdbDebugStubPort(
1090 (*iter)->GetUniqueChildProcessId());
1091 if (values.nacl_debug_stub_port != nacl::kGdbDebugStubPortUnknown) {
1092 values.is_nacl_debug_stub_port_valid = true;
1093 }
1094 }
1095 #endif // !defined(DISABLE_NACL)
1096 if (values.is_cpu_usage_valid && values.is_idle_wakeups_valid)
1097 continue;
1098 MetricsMap::iterator metrics_iter = metrics_map_.find(process);
1099 DCHECK(metrics_iter != metrics_map_.end());
1100 if (!values.is_cpu_usage_valid) {
1101 values.is_cpu_usage_valid = true;
1102 values.cpu_usage = metrics_iter->second->GetCPUUsage();
1103 }
1104 // TODO(port): Implement GetIdleWakeupsPerSecond() on other platforms,
1105 // crbug.com/120488
1106 if (!values.is_idle_wakeups_valid) {
1107 values.is_idle_wakeups_valid = true;
1108 values.idle_wakeups = metrics_iter->second->GetIdleWakeupsPerSecond();
1109 }
1110 }
1111
1112 // Send a request to refresh GPU memory consumption values
1113 RefreshVideoMemoryUsageStats();
1114
1115 // Compute the new network usage values.
1116 base::TimeDelta update_time =
1117 base::TimeDelta::FromMilliseconds(kUpdateTimeMs);
1118 for (ResourceValueMap::iterator iter = current_byte_count_map_.begin();
1119 iter != current_byte_count_map_.end(); ++iter) {
1120 PerResourceValues* values = &(per_resource_cache_[iter->first]);
1121 if (update_time > base::TimeDelta::FromSeconds(1))
1122 values->network_usage = iter->second / update_time.InSeconds();
1123 else
1124 values->network_usage = iter->second * (1 / update_time.InSeconds());
1125
1126 // Then we reset the current byte count.
1127 iter->second = 0;
1128 }
1129
1130 // Let resources update themselves if they need to.
1131 for (ResourceList::iterator iter = resources_.begin();
1132 iter != resources_.end(); ++iter) {
1133 (*iter)->Refresh();
1134 }
1135
1136 if (!resources_.empty()) {
1137 FOR_EACH_OBSERVER(TaskManagerModelObserver, observer_list_,
1138 OnItemsChanged(0, ResourceCount()));
1139 }
1140 }
1141
1142 void TaskManagerModel::NotifyVideoMemoryUsageStats(
1143 const gpu::VideoMemoryUsageStats& video_memory_usage_stats) {
1144 DCHECK(pending_video_memory_usage_stats_update_);
1145 video_memory_usage_stats_ = video_memory_usage_stats;
1146 pending_video_memory_usage_stats_update_ = false;
1147 }
1148
1149 void TaskManagerModel::NotifyBytesRead(const net::URLRequest& request,
1150 int64_t byte_count) {
1151 DCHECK_CURRENTLY_ON(BrowserThread::IO);
1152 if (!is_updating_byte_count_)
1153 return;
1154
1155 // Only net::URLRequestJob instances created by the ResourceDispatcherHost
1156 // have an associated ResourceRequestInfo and a render frame associated.
1157 // All other jobs will have -1 returned for the render process child and
1158 // routing ids - the jobs may still match a resource based on their origin id,
1159 // otherwise BytesRead() will attribute the activity to the Browser resource.
1160 const ResourceRequestInfo* info = ResourceRequestInfo::ForRequest(&request);
1161 int child_id = -1, route_id = -1;
1162 if (info)
1163 info->GetAssociatedRenderFrame(&child_id, &route_id);
1164
1165 // Get the origin PID of the request's originator. This will only be set for
1166 // plugins - for renderer or browser initiated requests it will be zero.
1167 int origin_pid = 0;
1168 if (info)
1169 origin_pid = info->GetOriginPID();
1170
1171 if (bytes_read_buffer_.empty()) {
1172 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
1173 FROM_HERE, base::Bind(&TaskManagerModel::NotifyMultipleBytesRead, this),
1174 base::TimeDelta::FromSeconds(1));
1175 }
1176
1177 bytes_read_buffer_.push_back(
1178 BytesReadParam(origin_pid, child_id, route_id, byte_count));
1179 }
1180
1181 // This is called on the UI thread.
1182 void TaskManagerModel::NotifyDataReady() {
1183 DCHECK_CURRENTLY_ON(BrowserThread::UI);
1184 for (size_t i = 0; i < on_data_ready_callbacks_.size(); ++i) {
1185 if (!on_data_ready_callbacks_[i].is_null())
1186 on_data_ready_callbacks_[i].Run();
1187 }
1188
1189 on_data_ready_callbacks_.clear();
1190 }
1191
1192 void TaskManagerModel::RegisterOnDataReadyCallback(
1193 const base::Closure& callback) {
1194 on_data_ready_callbacks_.push_back(callback);
1195 }
1196
1197 TaskManagerModel::~TaskManagerModel() {
1198 on_data_ready_callbacks_.clear();
1199 }
1200
1201 void TaskManagerModel::RefreshCallback() {
1202 DCHECK_NE(IDLE, update_state_);
1203
1204 if (update_state_ == STOPPING) {
1205 // We have been asked to stop.
1206 update_state_ = IDLE;
1207 return;
1208 }
1209
1210 Refresh();
1211
1212 // Schedule the next update.
1213 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
1214 FROM_HERE, base::Bind(&TaskManagerModel::RefreshCallback, this),
1215 base::TimeDelta::FromMilliseconds(kUpdateTimeMs));
1216 }
1217
1218 void TaskManagerModel::RefreshVideoMemoryUsageStats() {
1219 if (pending_video_memory_usage_stats_update_)
1220 return;
1221
1222 if (!video_memory_usage_stats_observer_.get()) {
1223 video_memory_usage_stats_observer_.reset(
1224 new TaskManagerModelGpuDataManagerObserver());
1225 }
1226 pending_video_memory_usage_stats_update_ = true;
1227 content::GpuDataManager::GetInstance()->RequestVideoMemoryUsageStatsUpdate();
1228 }
1229
1230 int64_t TaskManagerModel::GetNetworkUsageForResource(Resource* resource) const {
1231 // Returns default of 0 if no network usage.
1232 return per_resource_cache_[resource].network_usage;
1233 }
1234
1235 void TaskManagerModel::BytesRead(BytesReadParam param) {
1236 if (update_state_ != TASK_PENDING || listen_requests_ == 0) {
1237 // A notification sneaked in while we were stopping the updating, just
1238 // ignore it.
1239 return;
1240 }
1241
1242 // TODO(jcampan): this should be improved once we have a better way of
1243 // linking a network notification back to the object that initiated it.
1244 Resource* resource = NULL;
1245 for (ResourceProviderList::iterator iter = providers_.begin();
1246 iter != providers_.end(); ++iter) {
1247 resource = (*iter)->GetResource(param.origin_pid,
1248 param.child_id,
1249 param.route_id);
1250 if (resource)
1251 break;
1252 }
1253
1254 if (resource == NULL) {
1255 // We can't match a resource to the notification. That might mean the
1256 // tab that started a download was closed, or the request may have had
1257 // no originating resource associated with it in the first place.
1258 // We attribute orphaned/unaccounted activity to the Browser process.
1259 CHECK(param.origin_pid || (param.child_id != -1));
1260 param.origin_pid = 0;
1261 param.child_id = param.route_id = -1;
1262 BytesRead(param);
1263 return;
1264 }
1265
1266 // We do support network usage, mark the resource as such so it can report 0
1267 // instead of N/A.
1268 if (!resource->SupportNetworkUsage())
1269 resource->SetSupportNetworkUsage();
1270
1271 ResourceValueMap::const_iterator iter_res =
1272 current_byte_count_map_.find(resource);
1273 if (iter_res == current_byte_count_map_.end())
1274 current_byte_count_map_[resource] = param.byte_count;
1275 else
1276 current_byte_count_map_[resource] = iter_res->second + param.byte_count;
1277 }
1278
1279 void TaskManagerModel::MultipleBytesRead(
1280 const std::vector<BytesReadParam>* params) {
1281 DCHECK_CURRENTLY_ON(BrowserThread::UI);
1282 for (std::vector<BytesReadParam>::const_iterator it = params->begin();
1283 it != params->end(); ++it) {
1284 BytesRead(*it);
1285 }
1286 }
1287
1288 void TaskManagerModel::NotifyMultipleBytesRead() {
1289 DCHECK_CURRENTLY_ON(BrowserThread::IO);
1290 DCHECK(!bytes_read_buffer_.empty());
1291
1292 std::vector<BytesReadParam>* bytes_read_buffer =
1293 new std::vector<BytesReadParam>;
1294 bytes_read_buffer_.swap(*bytes_read_buffer);
1295 BrowserThread::PostTask(
1296 BrowserThread::UI, FROM_HERE,
1297 base::Bind(&TaskManagerModel::MultipleBytesRead, this,
1298 base::Owned(bytes_read_buffer)));
1299 }
1300
1301 void TaskManagerModel::SetUpdatingByteCount(bool is_updating) {
1302 DCHECK_CURRENTLY_ON(BrowserThread::IO);
1303 is_updating_byte_count_ = is_updating;
1304 }
1305
1306 int64_t TaskManagerModel::GetNetworkUsage(Resource* resource) const {
1307 int64_t net_usage = GetNetworkUsageForResource(resource);
1308 if (net_usage == 0 && !resource->SupportNetworkUsage())
1309 return -1;
1310 return net_usage;
1311 }
1312
1313 double TaskManagerModel::GetCPUUsage(Resource* resource) const {
1314 const PerProcessValues& values(per_process_cache_[resource->GetProcess()]);
1315 // Returns 0 if not valid, which is fine.
1316 return values.cpu_usage;
1317 }
1318
1319 int TaskManagerModel::GetIdleWakeupsPerSecond(Resource* resource) const {
1320 const PerProcessValues& values(per_process_cache_[resource->GetProcess()]);
1321 // Returns 0 if not valid, which is fine.
1322 return values.idle_wakeups;
1323 }
1324
1325 base::string16 TaskManagerModel::GetMemCellText(int64_t number) const {
1326 // System expectation is to show "100 kB", "200 MB", etc.
1327 // TODO(thakis): Switch to metric units (as opposed to powers of two).
1328 return ui::FormatBytes(number);
1329 }
1330
1331 bool TaskManagerModel::CachePrivateAndSharedMemory(
1332 base::ProcessHandle handle) const {
1333 PerProcessValues& values(per_process_cache_[handle]);
1334 if (values.is_private_and_shared_valid)
1335 return true;
1336
1337 MetricsMap::const_iterator iter = metrics_map_.find(handle);
1338 if (iter == metrics_map_.end() ||
1339 !iter->second->GetMemoryBytes(&values.private_bytes,
1340 &values.shared_bytes)) {
1341 return false;
1342 }
1343
1344 values.is_private_and_shared_valid = true;
1345 return true;
1346 }
1347
1348 bool TaskManagerModel::CacheWebCoreStats(int index) const {
1349 PerResourceValues& values(GetPerResourceValues(index));
1350 if (!values.is_webcore_stats_valid) {
1351 if (!GetResource(index)->ReportsCacheStats())
1352 return false;
1353 values.is_webcore_stats_valid = true;
1354 values.webcore_stats = GetResource(index)->GetWebCoreCacheStats();
1355 }
1356 return true;
1357 }
1358
1359 bool TaskManagerModel::CacheV8Memory(int index) const {
1360 PerResourceValues& values(GetPerResourceValues(index));
1361 if (!values.is_v8_memory_valid) {
1362 if (!GetResource(index)->ReportsV8MemoryStats())
1363 return false;
1364 values.is_v8_memory_valid = true;
1365 values.v8_memory_allocated = GetResource(index)->GetV8MemoryAllocated();
1366 values.v8_memory_used = GetResource(index)->GetV8MemoryUsed();
1367 }
1368 return true;
1369 }
1370
1371 void TaskManagerModel::AddResourceProvider(ResourceProvider* provider) {
1372 DCHECK(provider);
1373 providers_.push_back(provider);
1374 }
1375
1376 TaskManagerModel::PerResourceValues& TaskManagerModel::GetPerResourceValues(
1377 int index) const {
1378 return per_resource_cache_[GetResource(index)];
1379 }
1380
1381 Resource* TaskManagerModel::GetResource(int index) const {
1382 CHECK_GE(index, 0);
1383 CHECK_LT(index, static_cast<int>(resources_.size()));
1384 return resources_[index];
1385 }
1386
1387 ////////////////////////////////////////////////////////////////////////////////
1388 // TaskManager class
1389 ////////////////////////////////////////////////////////////////////////////////
1390
1391 bool TaskManager::IsBrowserProcess(int index) const {
1392 // If some of the selection is out of bounds, ignore. This may happen when
1393 // killing a process that manages several pages.
1394 return index < model_->ResourceCount() &&
1395 model_->GetProcess(index) == base::GetCurrentProcessHandle();
1396 }
1397
1398 void TaskManager::KillProcess(int index) {
1399 base::ProcessHandle process_handle = model_->GetProcess(index);
1400 DCHECK(process_handle);
1401 if (process_handle != base::GetCurrentProcessHandle()) {
1402 base::Process process =
1403 base::Process::DeprecatedGetProcessFromHandle(process_handle);
1404 process.Terminate(content::RESULT_CODE_KILLED, false);
1405 }
1406 }
1407
1408 void TaskManager::ActivateProcess(int index) {
1409 // GetResourceWebContents returns a pointer to the relevant web contents for
1410 // the resource. If the index doesn't correspond to any web contents
1411 // (i.e. refers to the Browser process or a plugin), GetWebContents will
1412 // return NULL.
1413 WebContents* chosen_web_contents = model_->GetResourceWebContents(index);
1414 if (chosen_web_contents && chosen_web_contents->GetDelegate())
1415 chosen_web_contents->GetDelegate()->ActivateContents(chosen_web_contents);
1416 }
1417
1418 void TaskManager::AddResource(Resource* resource) {
1419 model_->AddResource(resource);
1420 }
1421
1422 void TaskManager::RemoveResource(Resource* resource) {
1423 model_->RemoveResource(resource);
1424 }
1425
1426 void TaskManager::OnWindowClosed() {
1427 model_->StopUpdating();
1428 }
1429
1430 void TaskManager::ModelChanged() {
1431 model_->ModelChanged();
1432 }
1433
1434 // static
1435 TaskManager* TaskManager::GetInstance() {
1436 CHECK(!task_management::TaskManagerInterface::IsNewTaskManagerEnabled());
1437 return base::Singleton<TaskManager>::get();
1438 }
1439
1440 TaskManager::TaskManager()
1441 : model_(new TaskManagerModel(this)) {
1442 }
1443
1444 TaskManager::~TaskManager() {
1445 }
OLDNEW
« no previous file with comments | « chrome/browser/task_manager/task_manager.h ('k') | chrome/browser/task_manager/task_manager_tester_nonmac.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698