1 // Copyright 2015 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/sampling/task_manager_impl.h"
6 
7 #include <algorithm>
8 #include <memory>
9 #include <string>
10 #include <unordered_map>
11 #include <unordered_set>
12 #include <utility>
13 #include <vector>
14 
15 #include "base/bind.h"
16 #include "base/command_line.h"
17 #include "base/containers/adapters.h"
18 #include "base/task/post_task.h"
19 #include "base/task/thread_pool.h"
20 #include "build/build_config.h"
21 #include "chrome/browser/task_manager/providers/browser_process_task_provider.h"
22 #include "chrome/browser/task_manager/providers/child_process_task_provider.h"
23 #include "chrome/browser/task_manager/providers/fallback_task_provider.h"
24 #include "chrome/browser/task_manager/providers/render_process_host_task_provider.h"
25 #include "chrome/browser/task_manager/providers/spare_render_process_host_task_provider.h"
26 #include "chrome/browser/task_manager/providers/web_contents/web_contents_task_provider.h"
27 #include "chrome/browser/task_manager/providers/worker_task_provider.h"
28 #include "chrome/browser/task_manager/sampling/shared_sampler.h"
29 #include "components/nacl/common/buildflags.h"
30 #include "content/public/browser/browser_thread.h"
31 #include "content/public/browser/gpu_data_manager.h"
32 #include "content/public/browser/network_service_instance.h"
33 #include "content/public/browser/render_frame_host.h"
34 #include "content/public/browser/render_process_host.h"
35 #include "content/public/browser/web_contents.h"
36 #include "content/public/common/child_process_host.h"
37 #include "content/public/common/content_features.h"
38 #include "services/network/public/cpp/features.h"
39 #include "services/resource_coordinator/public/cpp/memory_instrumentation/memory_instrumentation.h"
40 
41 #if defined(OS_CHROMEOS)
42 #include "chrome/browser/chromeos/arc/process/arc_process_service.h"
43 #include "chrome/browser/task_manager/providers/arc/arc_process_task_provider.h"
44 #include "chrome/browser/task_manager/providers/vm/vm_process_task_provider.h"
45 #include "components/arc/arc_util.h"
46 #endif  // defined(OS_CHROMEOS)
47 
48 namespace task_manager {
49 
50 namespace {
51 
52 base::LazyInstance<TaskManagerImpl>::DestructorAtExit
53     lazy_task_manager_instance = LAZY_INSTANCE_INITIALIZER;
54 
CalculateNewBytesTransferred(int64_t this_refresh_bytes,int64_t last_refresh_bytes)55 int64_t CalculateNewBytesTransferred(int64_t this_refresh_bytes,
56                                      int64_t last_refresh_bytes) {
57   // Network Service could have restarted between the refresh, causing the
58   // accumulator to be cleared.
59   if (this_refresh_bytes < last_refresh_bytes)
60     return this_refresh_bytes;
61 
62   return this_refresh_bytes - last_refresh_bytes;
63 }
64 
65 }  // namespace
66 
operator ()(const BytesTransferredKey & key) const67 size_t BytesTransferredKey::Hasher::operator()(
68     const BytesTransferredKey& key) const {
69   return base::HashInts(key.child_id, key.route_id);
70 }
71 
operator ==(const BytesTransferredKey & other) const72 bool BytesTransferredKey::operator==(const BytesTransferredKey& other) const {
73   return child_id == other.child_id && route_id == other.route_id;
74 }
75 
TaskManagerImpl()76 TaskManagerImpl::TaskManagerImpl()
77     : on_background_data_ready_callback_(base::BindRepeating(
78           &TaskManagerImpl::OnTaskGroupBackgroundCalculationsDone,
79           base::Unretained(this))),
80       blocking_pool_runner_(base::ThreadPool::CreateSequencedTaskRunner(
81           {base::MayBlock(), base::TaskPriority::BEST_EFFORT,
82            base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN})),
83       shared_sampler_(new SharedSampler(blocking_pool_runner_)),
84       is_running_(false),
85       waiting_for_memory_dump_(false) {
86   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
87 
88   task_providers_.push_back(std::make_unique<BrowserProcessTaskProvider>());
89   task_providers_.push_back(std::make_unique<ChildProcessTaskProvider>());
90 
91   // Put all task providers for various types of RenderProcessHosts in this
92   // section. All of them should be added as primary subproviders for the
93   // FallbackTaskProvider, so that a fallback task can be shown for a renderer
94   // process if no other provider is shown for it.
95   std::vector<std::unique_ptr<TaskProvider>> primary_subproviders;
96   primary_subproviders.push_back(
97       std::make_unique<SpareRenderProcessHostTaskProvider>());
98   primary_subproviders.push_back(std::make_unique<WorkerTaskProvider>());
99   primary_subproviders.push_back(std::make_unique<WebContentsTaskProvider>());
100   task_providers_.push_back(std::make_unique<FallbackTaskProvider>(
101       std::move(primary_subproviders),
102       std::make_unique<RenderProcessHostTaskProvider>()));
103 
104 #if defined(OS_CHROMEOS)
105   if (arc::IsArcAvailable())
106     task_providers_.push_back(std::make_unique<ArcProcessTaskProvider>());
107   task_providers_.push_back(std::make_unique<VmProcessTaskProvider>());
108   arc_shared_sampler_ = std::make_unique<ArcSharedSampler>();
109 #endif  // defined(OS_CHROMEOS)
110 }
111 
~TaskManagerImpl()112 TaskManagerImpl::~TaskManagerImpl() {
113 }
114 
115 // static
GetInstance()116 TaskManagerImpl* TaskManagerImpl::GetInstance() {
117   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
118 
119   return lazy_task_manager_instance.Pointer();
120 }
121 
ActivateTask(TaskId task_id)122 void TaskManagerImpl::ActivateTask(TaskId task_id) {
123   GetTaskByTaskId(task_id)->Activate();
124 }
125 
IsTaskKillable(TaskId task_id)126 bool TaskManagerImpl::IsTaskKillable(TaskId task_id) {
127   return GetTaskByTaskId(task_id)->IsKillable();
128 }
129 
KillTask(TaskId task_id)130 void TaskManagerImpl::KillTask(TaskId task_id) {
131   GetTaskByTaskId(task_id)->Kill();
132 }
133 
GetPlatformIndependentCPUUsage(TaskId task_id) const134 double TaskManagerImpl::GetPlatformIndependentCPUUsage(TaskId task_id) const {
135   return GetTaskGroupByTaskId(task_id)->platform_independent_cpu_usage();
136 }
137 
GetStartTime(TaskId task_id) const138 base::Time TaskManagerImpl::GetStartTime(TaskId task_id) const {
139 #if defined(OS_WIN)
140   return GetTaskGroupByTaskId(task_id)->start_time();
141 #else
142   NOTIMPLEMENTED();
143   return base::Time();
144 #endif
145 }
146 
GetCpuTime(TaskId task_id) const147 base::TimeDelta TaskManagerImpl::GetCpuTime(TaskId task_id) const {
148 #if defined(OS_WIN)
149   return GetTaskGroupByTaskId(task_id)->cpu_time();
150 #else
151   NOTIMPLEMENTED();
152   return base::TimeDelta();
153 #endif
154 }
155 
GetMemoryFootprintUsage(TaskId task_id) const156 int64_t TaskManagerImpl::GetMemoryFootprintUsage(TaskId task_id) const {
157   return GetTaskGroupByTaskId(task_id)->footprint_bytes();
158 }
159 
GetSwappedMemoryUsage(TaskId task_id) const160 int64_t TaskManagerImpl::GetSwappedMemoryUsage(TaskId task_id) const {
161 #if defined(OS_CHROMEOS)
162   return GetTaskGroupByTaskId(task_id)->swapped_bytes();
163 #else
164   return -1;
165 #endif
166 }
167 
GetGpuMemoryUsage(TaskId task_id,bool * has_duplicates) const168 int64_t TaskManagerImpl::GetGpuMemoryUsage(TaskId task_id,
169                                            bool* has_duplicates) const {
170   const TaskGroup* task_group = GetTaskGroupByTaskId(task_id);
171   if (has_duplicates)
172     *has_duplicates = task_group->gpu_memory_has_duplicates();
173   return task_group->gpu_memory();
174 }
175 
GetIdleWakeupsPerSecond(TaskId task_id) const176 int TaskManagerImpl::GetIdleWakeupsPerSecond(TaskId task_id) const {
177   return GetTaskGroupByTaskId(task_id)->idle_wakeups_per_second();
178 }
179 
GetHardFaultsPerSecond(TaskId task_id) const180 int TaskManagerImpl::GetHardFaultsPerSecond(TaskId task_id) const {
181 #if defined(OS_WIN)
182   return GetTaskGroupByTaskId(task_id)->hard_faults_per_second();
183 #else
184   return -1;
185 #endif
186 }
187 
GetNaClDebugStubPort(TaskId task_id) const188 int TaskManagerImpl::GetNaClDebugStubPort(TaskId task_id) const {
189 #if BUILDFLAG(ENABLE_NACL)
190   return GetTaskGroupByTaskId(task_id)->nacl_debug_stub_port();
191 #else
192   return -2;
193 #endif  // BUILDFLAG(ENABLE_NACL)
194 }
195 
GetGDIHandles(TaskId task_id,int64_t * current,int64_t * peak) const196 void TaskManagerImpl::GetGDIHandles(TaskId task_id,
197                                     int64_t* current,
198                                     int64_t* peak) const {
199 #if defined(OS_WIN)
200   const TaskGroup* task_group = GetTaskGroupByTaskId(task_id);
201   *current = task_group->gdi_current_handles();
202   *peak = task_group->gdi_peak_handles();
203 #else
204   *current = -1;
205   *peak = -1;
206 #endif  // defined(OS_WIN)
207 }
208 
GetUSERHandles(TaskId task_id,int64_t * current,int64_t * peak) const209 void TaskManagerImpl::GetUSERHandles(TaskId task_id,
210                                      int64_t* current,
211                                      int64_t* peak) const {
212 #if defined(OS_WIN)
213   const TaskGroup* task_group = GetTaskGroupByTaskId(task_id);
214   *current = task_group->user_current_handles();
215   *peak = task_group->user_peak_handles();
216 #else
217   *current = -1;
218   *peak = -1;
219 #endif  // defined(OS_WIN)
220 }
221 
GetOpenFdCount(TaskId task_id) const222 int TaskManagerImpl::GetOpenFdCount(TaskId task_id) const {
223 #if defined(OS_LINUX) || defined(OS_CHROMEOS) || defined(OS_MAC) || defined(OS_BSD)
224   return GetTaskGroupByTaskId(task_id)->open_fd_count();
225 #else
226   return -1;
227 #endif  // defined(OS_LINUX) || defined(OS_CHROMEOS) || defined(OS_MAC) || defined(OS_BSD)
228 }
229 
IsTaskOnBackgroundedProcess(TaskId task_id) const230 bool TaskManagerImpl::IsTaskOnBackgroundedProcess(TaskId task_id) const {
231   return GetTaskGroupByTaskId(task_id)->is_backgrounded();
232 }
233 
GetTitle(TaskId task_id) const234 const base::string16& TaskManagerImpl::GetTitle(TaskId task_id) const {
235   return GetTaskByTaskId(task_id)->title();
236 }
237 
GetProfileName(TaskId task_id) const238 base::string16 TaskManagerImpl::GetProfileName(TaskId task_id) const {
239   return GetTaskByTaskId(task_id)->GetProfileName();
240 }
241 
GetIcon(TaskId task_id) const242 const gfx::ImageSkia& TaskManagerImpl::GetIcon(TaskId task_id) const {
243   return GetTaskByTaskId(task_id)->icon();
244 }
245 
GetProcessHandle(TaskId task_id) const246 const base::ProcessHandle& TaskManagerImpl::GetProcessHandle(
247     TaskId task_id) const {
248   return GetTaskGroupByTaskId(task_id)->process_handle();
249 }
250 
GetProcessId(TaskId task_id) const251 const base::ProcessId& TaskManagerImpl::GetProcessId(TaskId task_id) const {
252   return GetTaskGroupByTaskId(task_id)->process_id();
253 }
254 
GetType(TaskId task_id) const255 Task::Type TaskManagerImpl::GetType(TaskId task_id) const {
256   return GetTaskByTaskId(task_id)->GetType();
257 }
258 
GetTabId(TaskId task_id) const259 SessionID TaskManagerImpl::GetTabId(TaskId task_id) const {
260   return GetTaskByTaskId(task_id)->GetTabId();
261 }
262 
GetChildProcessUniqueId(TaskId task_id) const263 int TaskManagerImpl::GetChildProcessUniqueId(TaskId task_id) const {
264   return GetTaskByTaskId(task_id)->GetChildProcessUniqueID();
265 }
266 
GetTerminationStatus(TaskId task_id,base::TerminationStatus * out_status,int * out_error_code) const267 void TaskManagerImpl::GetTerminationStatus(TaskId task_id,
268                                            base::TerminationStatus* out_status,
269                                            int* out_error_code) const {
270   GetTaskByTaskId(task_id)->GetTerminationStatus(out_status, out_error_code);
271 }
272 
GetNetworkUsage(TaskId task_id) const273 int64_t TaskManagerImpl::GetNetworkUsage(TaskId task_id) const {
274   return GetTaskByTaskId(task_id)->network_usage_rate();
275 }
276 
GetCumulativeNetworkUsage(TaskId task_id) const277 int64_t TaskManagerImpl::GetCumulativeNetworkUsage(TaskId task_id) const {
278   return GetTaskByTaskId(task_id)->cumulative_network_usage();
279 }
280 
GetProcessTotalNetworkUsage(TaskId task_id) const281 int64_t TaskManagerImpl::GetProcessTotalNetworkUsage(TaskId task_id) const {
282   return GetTaskGroupByTaskId(task_id)->per_process_network_usage_rate();
283 }
284 
GetCumulativeProcessTotalNetworkUsage(TaskId task_id) const285 int64_t TaskManagerImpl::GetCumulativeProcessTotalNetworkUsage(
286     TaskId task_id) const {
287   return GetTaskGroupByTaskId(task_id)->cumulative_per_process_network_usage();
288 }
289 
GetSqliteMemoryUsed(TaskId task_id) const290 int64_t TaskManagerImpl::GetSqliteMemoryUsed(TaskId task_id) const {
291   return GetTaskByTaskId(task_id)->GetSqliteMemoryUsed();
292 }
293 
GetV8Memory(TaskId task_id,int64_t * allocated,int64_t * used) const294 bool TaskManagerImpl::GetV8Memory(TaskId task_id,
295                                   int64_t* allocated,
296                                   int64_t* used) const {
297   const Task* task = GetTaskByTaskId(task_id);
298   const int64_t allocated_memory = task->GetV8MemoryAllocated();
299   const int64_t used_memory = task->GetV8MemoryUsed();
300   if (allocated_memory == -1 || used_memory == -1)
301     return false;
302 
303   *allocated = allocated_memory;
304   *used = used_memory;
305 
306   return true;
307 }
308 
GetWebCacheStats(TaskId task_id,blink::WebCacheResourceTypeStats * stats) const309 bool TaskManagerImpl::GetWebCacheStats(
310     TaskId task_id,
311     blink::WebCacheResourceTypeStats* stats) const {
312   const Task* task = GetTaskByTaskId(task_id);
313   if (!task->ReportsWebCacheStats())
314     return false;
315 
316   *stats = task->GetWebCacheStats();
317 
318   return true;
319 }
320 
GetKeepaliveCount(TaskId task_id) const321 int TaskManagerImpl::GetKeepaliveCount(TaskId task_id) const {
322   const Task* task = GetTaskByTaskId(task_id);
323   if (!task)
324     return -1;
325 
326   return task->GetKeepaliveCount();
327 }
328 
GetTaskIdsList() const329 const TaskIdList& TaskManagerImpl::GetTaskIdsList() const {
330   DCHECK(is_running_) << "Task manager is not running. You must observe the "
331       "task manager for it to start running";
332 
333   if (sorted_task_ids_.empty()) {
334     // |comparator| groups and sorts by subtask-ness (to push all subtasks to be
335     // last), then by process type (e.g. the browser process should be first;
336     // renderer processes should be together), then tab id (processes used by
337     // the same tab should be kept together, and a tab should have a stable
338     // position in the list as it cycles through processes, and tab creation
339     // order is meaningful), and finally by task id (when all else is equal, put
340     // the oldest tasks first).
341     auto comparator = [](const Task* a, const Task* b) -> bool {
342       return std::make_tuple(a->HasParentTask(), a->GetType(), a->GetTabId(),
343                              a->task_id()) <
344              std::make_tuple(b->HasParentTask(), b->GetType(), b->GetTabId(),
345                              b->task_id());
346     };
347 
348     const size_t num_groups =
349         task_groups_by_proc_id_.size() + arc_vm_task_groups_by_proc_id_.size();
350 
351     // |task_groups_by_task_id_| contains all tasks, both VM and non-VM.
352     const size_t num_tasks = task_groups_by_task_id_.size();
353 
354     // Populate |tasks_to_visit| with one task from each group.
355     std::vector<const Task*> tasks_to_visit;
356     tasks_to_visit.reserve(num_groups);
357     std::unordered_map<const Task*, std::vector<const Task*>> children;
358     for (const auto& groups_pair : task_groups_by_proc_id_) {
359       // The first task in the group (per |comparator|) is the one used for
360       // sorting the group relative to other groups.
361       const std::vector<Task*>& tasks = groups_pair.second->tasks();
362       Task* group_task =
363           *std::min_element(tasks.begin(), tasks.end(), comparator);
364       tasks_to_visit.push_back(group_task);
365 
366       // Build the parent-to-child map, for use later.
367       for (const Task* task : tasks) {
368         if (task->HasParentTask())
369           children[task->GetParentTask()].push_back(task);
370         else
371           DCHECK(!group_task->HasParentTask());
372       }
373     }
374 
375     for (const auto& groups_pair : arc_vm_task_groups_by_proc_id_) {
376       const std::vector<Task*>& tasks = groups_pair.second->tasks();
377       Task* group_task =
378           *std::min_element(tasks.begin(), tasks.end(), comparator);
379       tasks_to_visit.push_back(group_task);
380     }
381 
382     // Now sort |tasks_to_visit| in reverse order (putting the browser process
383     // at back()). We will treat it as a stack from now on.
384     std::sort(tasks_to_visit.rbegin(), tasks_to_visit.rend(), comparator);
385     DCHECK_EQ(Task::BROWSER, tasks_to_visit.back()->GetType());
386 
387     // Using |tasks_to_visit| as a stack, and |visited_groups| to track which
388     // groups we've already added, add groups to |sorted_task_ids_| until all
389     // groups have been added.
390     sorted_task_ids_.reserve(num_tasks);
391     std::unordered_set<TaskGroup*> visited_groups;
392     visited_groups.reserve(num_groups);
393     std::vector<Task*> current_group_tasks;  // Outside loop for fewer mallocs.
394     while (visited_groups.size() < num_groups) {
395       DCHECK(!tasks_to_visit.empty());
396       TaskGroup* current_group =
397           GetTaskGroupByTaskId(tasks_to_visit.back()->task_id());
398       tasks_to_visit.pop_back();
399 
400       // Mark |current_group| as visited. If this fails, we've already added
401       // the group, and should skip over it.
402       if (!visited_groups.insert(current_group).second)
403         continue;
404 
405       // Make a copy of |current_group->tasks()|, sort it, and append the ids.
406       current_group_tasks = current_group->tasks();
407       std::sort(current_group_tasks.begin(), current_group_tasks.end(),
408                 comparator);
409       for (Task* task : current_group_tasks)
410         sorted_task_ids_.push_back(task->task_id());
411 
412       // Find the children of the tasks we just added, and push them into
413       // |tasks_to_visit|, so that we visit them soon. Work in reverse order,
414       // so that we visit them in forward order.
415       for (Task* parent : base::Reversed(current_group_tasks)) {
416         auto children_of_parent = children.find(parent);
417         if (children_of_parent != children.end()) {
418           // Sort children[parent], and then append in reversed order.
419           std::sort(children_of_parent->second.begin(),
420                     children_of_parent->second.end(), comparator);
421           tasks_to_visit.insert(tasks_to_visit.end(),
422                                 children_of_parent->second.rbegin(),
423                                 children_of_parent->second.rend());
424         }
425       }
426     }
427     DCHECK_EQ(num_tasks, sorted_task_ids_.size());
428   }
429 
430   return sorted_task_ids_;
431 }
432 
GetIdsOfTasksSharingSameProcess(TaskId task_id) const433 TaskIdList TaskManagerImpl::GetIdsOfTasksSharingSameProcess(
434     TaskId task_id) const {
435   DCHECK(is_running_) << "Task manager is not running. You must observe the "
436       "task manager for it to start running";
437 
438   TaskIdList result;
439   TaskGroup* group = GetTaskGroupByTaskId(task_id);
440   if (group) {
441     result.reserve(group->tasks().size());
442     for (Task* task : group->tasks())
443       result.push_back(task->task_id());
444   }
445   return result;
446 }
447 
GetNumberOfTasksOnSameProcess(TaskId task_id) const448 size_t TaskManagerImpl::GetNumberOfTasksOnSameProcess(TaskId task_id) const {
449   return GetTaskGroupByTaskId(task_id)->num_tasks();
450 }
451 
IsRunningInVM(TaskId task_id) const452 bool TaskManagerImpl::IsRunningInVM(TaskId task_id) const {
453   return GetTaskByTaskId(task_id)->IsRunningInVM();
454 }
455 
GetTaskIdForWebContents(content::WebContents * web_contents) const456 TaskId TaskManagerImpl::GetTaskIdForWebContents(
457     content::WebContents* web_contents) const {
458   if (!web_contents)
459     return -1;
460   content::RenderFrameHost* rfh = web_contents->GetMainFrame();
461   Task* task = GetTaskByRoute(rfh->GetProcess()->GetID(), rfh->GetRoutingID());
462   if (!task)
463     return -1;
464   return task->task_id();
465 }
466 
TaskAdded(Task * task)467 void TaskManagerImpl::TaskAdded(Task* task) {
468   DCHECK(task);
469 
470   const base::ProcessId proc_id = task->process_id();
471   const TaskId task_id = task->task_id();
472   const bool is_running_in_vm = task->IsRunningInVM();
473 
474   TaskManagerImpl::PidToTaskGroupMap& task_group_map =
475       is_running_in_vm ? arc_vm_task_groups_by_proc_id_
476                        : task_groups_by_proc_id_;
477 
478   std::unique_ptr<TaskGroup>& task_group = task_group_map[proc_id];
479   if (!task_group) {
480     task_group.reset(new TaskGroup(task->process_handle(), proc_id,
481                                    is_running_in_vm,
482                                    on_background_data_ready_callback_,
483                                    shared_sampler_, blocking_pool_runner_));
484 #if defined(OS_CHROMEOS)
485     if (task->GetType() == Task::ARC)
486       task_group->SetArcSampler(arc_shared_sampler_.get());
487 #endif
488   }
489 
490   task_group->AddTask(task);
491 
492   task_groups_by_task_id_[task_id] = task_group.get();
493 
494   // Invalidate the cached sorted IDs by clearing the list.
495   sorted_task_ids_.clear();
496 
497   NotifyObserversOnTaskAdded(task_id);
498 }
499 
TaskRemoved(Task * task)500 void TaskManagerImpl::TaskRemoved(Task* task) {
501   DCHECK(task);
502 
503   const base::ProcessId proc_id = task->process_id();
504   const TaskId task_id = task->task_id();
505   const bool is_running_in_vm = task->IsRunningInVM();
506 
507   TaskManagerImpl::PidToTaskGroupMap& task_group_map =
508       is_running_in_vm ? arc_vm_task_groups_by_proc_id_
509                        : task_groups_by_proc_id_;
510 
511   DCHECK(task_group_map.count(proc_id));
512 
513   NotifyObserversOnTaskToBeRemoved(task_id);
514 
515   TaskGroup* task_group = GetTaskGroupByTaskId(task_id);
516   task_group->RemoveTask(task);
517   task_groups_by_task_id_.erase(task_id);
518 
519   if (task_group->empty())
520     task_group_map.erase(proc_id);  // Deletes |task_group|.
521 
522   // Invalidate the cached sorted IDs by clearing the list.
523   sorted_task_ids_.clear();
524 }
525 
TaskUnresponsive(Task * task)526 void TaskManagerImpl::TaskUnresponsive(Task* task) {
527   DCHECK(task);
528   NotifyObserversOnTaskUnresponsive(task->task_id());
529 }
530 
OnTotalNetworkUsages(std::vector<network::mojom::NetworkUsagePtr> total_network_usages)531 void TaskManagerImpl::OnTotalNetworkUsages(
532     std::vector<network::mojom::NetworkUsagePtr> total_network_usages) {
533   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
534   BytesTransferredMap new_total_network_usages_map;
535   for (const auto& entry : total_network_usages) {
536     BytesTransferredKey process_info = {entry->process_id, entry->routing_id};
537     BytesTransferredParam total_bytes_transferred = {
538         entry->total_bytes_received, entry->total_bytes_sent};
539     new_total_network_usages_map[process_info] = total_bytes_transferred;
540 
541     auto last_refresh_usage =
542         last_refresh_total_network_usages_map_[process_info];
543     BytesTransferredParam new_bytes_transferred;
544     new_bytes_transferred.byte_read_count =
545         CalculateNewBytesTransferred(total_bytes_transferred.byte_read_count,
546                                      last_refresh_usage.byte_read_count);
547     new_bytes_transferred.byte_sent_count =
548         CalculateNewBytesTransferred(total_bytes_transferred.byte_sent_count,
549                                      last_refresh_usage.byte_sent_count);
550     DCHECK_GE(new_bytes_transferred.byte_read_count, 0);
551     DCHECK_GE(new_bytes_transferred.byte_sent_count, 0);
552 
553     if (!UpdateTasksWithBytesTransferred(process_info, new_bytes_transferred)) {
554       // We can't match a task to the notification.  That might mean the
555       // tab that started a download was closed, or the request may have had
556       // no originating task associated with it in the first place.
557       //
558       // Orphaned/unaccounted activity is credited to the Browser process.
559       BytesTransferredKey browser_process_key = {
560           content::ChildProcessHost::kInvalidUniqueID, MSG_ROUTING_NONE};
561       UpdateTasksWithBytesTransferred(browser_process_key,
562                                       new_bytes_transferred);
563     }
564   }
565   last_refresh_total_network_usages_map_.swap(new_total_network_usages_map);
566 }
567 
OnVideoMemoryUsageStatsUpdate(const gpu::VideoMemoryUsageStats & gpu_memory_stats)568 void TaskManagerImpl::OnVideoMemoryUsageStatsUpdate(
569     const gpu::VideoMemoryUsageStats& gpu_memory_stats) {
570   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
571 
572   gpu_memory_stats_ = gpu_memory_stats;
573 }
574 
OnReceivedMemoryDump(bool success,std::unique_ptr<memory_instrumentation::GlobalMemoryDump> dump)575 void TaskManagerImpl::OnReceivedMemoryDump(
576     bool success,
577     std::unique_ptr<memory_instrumentation::GlobalMemoryDump> dump) {
578   waiting_for_memory_dump_ = false;
579   // We can ignore the value of success as it is a coarse grained indicator
580   // of whether the global dump was successful; usually because of a missing
581   // process or OS dumps. There may still be useful information for other
582   // processes in the global dump when success is false.
583   if (!dump)
584     return;
585   for (const auto& pmd : dump->process_dumps()) {
586     auto it = task_groups_by_proc_id_.find(pmd.pid());
587     if (it == task_groups_by_proc_id_.end())
588       continue;
589     it->second->set_footprint_bytes(
590         static_cast<uint64_t>(pmd.os_dump().private_footprint_kb) * 1024);
591   }
592 }
593 
Refresh()594 void TaskManagerImpl::Refresh() {
595   if (IsResourceRefreshEnabled(REFRESH_TYPE_GPU_MEMORY)) {
596     content::GpuDataManager::GetInstance()->RequestVideoMemoryUsageStatsUpdate(
597         base::BindOnce(&TaskManagerImpl::OnVideoMemoryUsageStatsUpdate,
598                        weak_ptr_factory_.GetWeakPtr()));
599   }
600 
601   if (IsResourceRefreshEnabled(REFRESH_TYPE_MEMORY_FOOTPRINT) &&
602       !waiting_for_memory_dump_) {
603     // The callback keeps this object alive until the callback is invoked.
604     waiting_for_memory_dump_ = true;
605     auto callback = base::BindOnce(&TaskManagerImpl::OnReceivedMemoryDump,
606                                    weak_ptr_factory_.GetWeakPtr());
607     memory_instrumentation::MemoryInstrumentation::GetInstance()
608         ->RequestPrivateMemoryFootprint(base::kNullProcessId,
609                                         std::move(callback));
610   }
611 
612   if (TaskManagerObserver::IsResourceRefreshEnabled(
613           REFRESH_TYPE_NETWORK_USAGE, enabled_resources_flags())) {
614     content::GetNetworkService()->GetTotalNetworkUsages(
615         base::BindOnce(&TaskManagerImpl::OnTotalNetworkUsages,
616                        weak_ptr_factory_.GetWeakPtr()));
617   }
618 
619   for (auto& groups_itr : task_groups_by_proc_id_) {
620     groups_itr.second->Refresh(gpu_memory_stats_,
621                                GetCurrentRefreshTime(),
622                                enabled_resources_flags());
623   }
624 
625   for (auto& groups_itr : arc_vm_task_groups_by_proc_id_) {
626     groups_itr.second->Refresh(gpu_memory_stats_, GetCurrentRefreshTime(),
627                                enabled_resources_flags());
628   }
629 
630 #if defined(OS_CHROMEOS)
631   if (TaskManagerObserver::IsResourceRefreshEnabled(
632           REFRESH_TYPE_MEMORY_FOOTPRINT, enabled_resources_flags())) {
633     arc_shared_sampler_->Refresh();
634   }
635 #endif  // defined(OS_CHROMEOS)
636 
637   NotifyObserversOnRefresh(GetTaskIdsList());
638 }
639 
StartUpdating()640 void TaskManagerImpl::StartUpdating() {
641   if (is_running_)
642     return;
643 
644   is_running_ = true;
645 
646   for (const auto& provider : task_providers_)
647     provider->SetObserver(this);
648 
649   // Kick off fetch of asynchronous data, e.g., memory footprint, so that it
650   // will be displayed sooner after opening the task manager.
651   Refresh();
652 }
653 
StopUpdating()654 void TaskManagerImpl::StopUpdating() {
655   if (!is_running_)
656     return;
657 
658   is_running_ = false;
659 
660   for (const auto& provider : task_providers_)
661     provider->ClearObserver();
662 
663   task_groups_by_proc_id_.clear();
664   arc_vm_task_groups_by_proc_id_.clear();
665   task_groups_by_task_id_.clear();
666   sorted_task_ids_.clear();
667 }
668 
GetTaskByRoute(int child_id,int route_id) const669 Task* TaskManagerImpl::GetTaskByRoute(int child_id, int route_id) const {
670   for (const auto& task_provider : task_providers_) {
671     Task* task = task_provider->GetTaskOfUrlRequest(child_id, route_id);
672     if (task)
673       return task;
674   }
675   return nullptr;
676 }
677 
UpdateTasksWithBytesTransferred(const BytesTransferredKey & key,const BytesTransferredParam & param)678 bool TaskManagerImpl::UpdateTasksWithBytesTransferred(
679     const BytesTransferredKey& key,
680     const BytesTransferredParam& param) {
681   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
682 
683   Task* task = GetTaskByRoute(key.child_id, key.route_id);
684   if (task) {
685     task->OnNetworkBytesRead(param.byte_read_count);
686     task->OnNetworkBytesSent(param.byte_sent_count);
687     return true;
688   }
689 
690   // Couldn't match the bytes to any existing task.
691   return false;
692 }
693 
GetTaskGroupByTaskId(TaskId task_id) const694 TaskGroup* TaskManagerImpl::GetTaskGroupByTaskId(TaskId task_id) const {
695   auto it = task_groups_by_task_id_.find(task_id);
696   DCHECK(it != task_groups_by_task_id_.end());
697   return it->second;
698 }
699 
GetTaskByTaskId(TaskId task_id) const700 Task* TaskManagerImpl::GetTaskByTaskId(TaskId task_id) const {
701   return GetTaskGroupByTaskId(task_id)->GetTaskById(task_id);
702 }
703 
OnTaskGroupBackgroundCalculationsDone()704 void TaskManagerImpl::OnTaskGroupBackgroundCalculationsDone() {
705   for (const auto& groups_itr : task_groups_by_proc_id_) {
706     if (!groups_itr.second->AreBackgroundCalculationsDone())
707       return;
708   }
709   NotifyObserversOnRefreshWithBackgroundCalculations(GetTaskIdsList());
710   for (const auto& groups_itr : task_groups_by_proc_id_)
711     groups_itr.second->ClearCurrentBackgroundCalculationsFlags();
712 }
713 
714 }  // namespace task_manager
715