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/providers/arc/arc_process_task_provider.h"
6
7 #include <stddef.h>
8
9 #include <queue>
10 #include <set>
11 #include <utility>
12 #include <vector>
13
14 #include "base/bind.h"
15 #include "base/callback.h"
16 #include "base/logging.h"
17 #include "base/process/process.h"
18 #include "base/threading/thread_task_runner_handle.h"
19 #include "base/trace_event/trace_event.h"
20 #include "chrome/browser/chromeos/arc/process/arc_process_service.h"
21 #include "components/arc/mojom/process.mojom.h"
22
23 namespace task_manager {
24
25 using std::set;
26 using arc::ArcProcess;
27 using base::Process;
28 using base::ProcessId;
29
ArcProcessTaskProvider()30 ArcProcessTaskProvider::ArcProcessTaskProvider() : is_updating_(false) {}
31
32 ArcProcessTaskProvider::~ArcProcessTaskProvider() = default;
33
GetTaskOfUrlRequest(int child_id,int route_id)34 Task* ArcProcessTaskProvider::GetTaskOfUrlRequest(int child_id, int route_id) {
35 // ARC tasks are not associated with any URL request.
36 return nullptr;
37 }
38
UpdateProcessList(ArcTaskMap * pid_to_task,std::vector<ArcProcess> processes)39 void ArcProcessTaskProvider::UpdateProcessList(
40 ArcTaskMap* pid_to_task,
41 std::vector<ArcProcess> processes) {
42 if (!is_updating_)
43 return;
44
45 // NB: |processes| can be already stale here because it is sent via IPC, and
46 // we can never avoid that. See also the comment at the declaration of
47 // ArcProcessTaskProvider.
48
49 set<ProcessId> nspid_to_remove;
50 for (const auto& entry : *pid_to_task)
51 nspid_to_remove.insert(entry.first);
52
53 for (auto& entry : processes) {
54 if (nspid_to_remove.erase(entry.nspid()) == 0) {
55 // New arc process.
56 std::unique_ptr<ArcProcessTask>& task = (*pid_to_task)[entry.nspid()];
57 // After calling NotifyObserverTaskAdded(), the raw pointer of |task| is
58 // remebered somewhere else. One should not (implicitly) delete the
59 // referenced object before calling NotifyObserverTaskRemoved() first
60 // (crbug.com/587707).
61 DCHECK(!task.get()) <<
62 "Task with the same pid should not be added twice.";
63 task = std::make_unique<ArcProcessTask>(std::move(entry));
64 NotifyObserverTaskAdded(task.get());
65 } else {
66 // Update process state of existing process.
67 std::unique_ptr<ArcProcessTask>& task = (*pid_to_task)[entry.nspid()];
68 DCHECK(task.get());
69 task->SetProcessState(entry.process_state());
70 }
71 }
72
73 for (const auto& entry : nspid_to_remove) {
74 // Stale arc process.
75 NotifyObserverTaskRemoved((*pid_to_task)[entry].get());
76 pid_to_task->erase(entry);
77 }
78 }
79
OnUpdateAppProcessList(OptionalArcProcessList processes)80 void ArcProcessTaskProvider::OnUpdateAppProcessList(
81 OptionalArcProcessList processes) {
82 if (!processes) {
83 VLOG(2) << "ARC process instance is not ready.";
84 ScheduleNextAppRequest();
85 return;
86 }
87
88 TRACE_EVENT0("browser", "ArcProcessTaskProvider::OnUpdateAppProcessList");
89 UpdateProcessList(&nspid_to_task_, std::move(*processes));
90 ScheduleNextAppRequest();
91 }
92
OnUpdateSystemProcessList(OptionalArcProcessList processes)93 void ArcProcessTaskProvider::OnUpdateSystemProcessList(
94 OptionalArcProcessList processes) {
95 if (processes)
96 UpdateProcessList(&nspid_to_sys_task_, std::move(*processes));
97 ScheduleNextSystemRequest();
98 }
99
RequestAppProcessList()100 void ArcProcessTaskProvider::RequestAppProcessList() {
101 arc::ArcProcessService* arc_process_service =
102 arc::ArcProcessService::Get();
103 if (!arc_process_service) {
104 VLOG(2) << "ARC process instance is not ready.";
105 ScheduleNextAppRequest();
106 return;
107 }
108
109 auto callback =
110 base::BindOnce(&ArcProcessTaskProvider::OnUpdateAppProcessList,
111 weak_ptr_factory_.GetWeakPtr());
112 arc_process_service->RequestAppProcessList(std::move(callback));
113 }
114
RequestSystemProcessList()115 void ArcProcessTaskProvider::RequestSystemProcessList() {
116 arc::ArcProcessService* arc_process_service = arc::ArcProcessService::Get();
117 if (!arc_process_service) {
118 VLOG(2) << "ARC process instance is not ready.";
119 ScheduleNextSystemRequest();
120 return;
121 }
122
123 auto callback =
124 base::BindOnce(&ArcProcessTaskProvider::OnUpdateSystemProcessList,
125 weak_ptr_factory_.GetWeakPtr());
126 arc_process_service->RequestSystemProcessList(std::move(callback));
127 }
128
StartUpdating()129 void ArcProcessTaskProvider::StartUpdating() {
130 is_updating_ = true;
131 RequestAppProcessList();
132 RequestSystemProcessList();
133 }
134
StopUpdating()135 void ArcProcessTaskProvider::StopUpdating() {
136 is_updating_ = false;
137 weak_ptr_factory_.InvalidateWeakPtrs();
138 nspid_to_task_.clear();
139 nspid_to_sys_task_.clear();
140 }
141
ScheduleNextRequest(base::OnceClosure task)142 void ArcProcessTaskProvider::ScheduleNextRequest(base::OnceClosure task) {
143 if (!is_updating_)
144 return;
145 // TODO(nya): Remove this timer once ARC starts to send us UpdateProcessList
146 // message when the process list changed. As of today, ARC does not send
147 // the process list unless we request it by RequestAppProcessList message.
148 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
149 FROM_HERE, std::move(task),
150 arc::ArcProcessService::kProcessSnapshotRefreshTime);
151 }
152
ScheduleNextAppRequest()153 void ArcProcessTaskProvider::ScheduleNextAppRequest() {
154 ScheduleNextRequest(
155 base::BindOnce(&ArcProcessTaskProvider::RequestAppProcessList,
156 weak_ptr_factory_.GetWeakPtr()));
157 }
158
ScheduleNextSystemRequest()159 void ArcProcessTaskProvider::ScheduleNextSystemRequest() {
160 ScheduleNextRequest(
161 base::BindOnce(&ArcProcessTaskProvider::RequestSystemProcessList,
162 weak_ptr_factory_.GetWeakPtr()));
163 }
164
165 } // namespace task_manager
166