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