Chromium Code Reviews| Index: chrome/browser/chromeos/arc/arc_process_service.cc |
| diff --git a/chrome/browser/chromeos/arc/arc_process_service.cc b/chrome/browser/chromeos/arc/arc_process_service.cc |
| index 550ea0ae0c2f5a62cf0815969f2168c52a3a353c..8e8c810cb10a8f132ddb7e0952cb087f6496fe98 100644 |
| --- a/chrome/browser/chromeos/arc/arc_process_service.cc |
| +++ b/chrome/browser/chromeos/arc/arc_process_service.cc |
| @@ -13,6 +13,7 @@ |
| #include <set> |
| #include <string> |
| +#include "base/callback_forward.h" |
| #include "base/process/process.h" |
| #include "base/process/process_iterator.h" |
| #include "base/task_runner_util.h" |
| @@ -23,7 +24,7 @@ namespace arc { |
| namespace { |
| -const char kSequenceToken[] = "arc_process_service"; |
| +constexpr char kSequenceToken[] = "arc_process_service"; |
| // Weak pointer. This class is owned by ArcServiceManager. |
| ArcProcessService* g_arc_process_service = nullptr; |
| @@ -77,7 +78,51 @@ void ArcProcessService::Reset() { |
| nspid_to_pid_.clear(); |
| } |
| -bool ArcProcessService::RequestProcessList( |
| +void ArcProcessService::RequestSystemProcessList( |
| + RequestProcessListCallback callback) { |
| + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); |
| + |
| + auto runner = worker_pool_->GetSequencedTaskRunner( |
| + worker_pool_->GetNamedSequenceToken(kSequenceToken)); |
| + base::PostTaskAndReplyWithResult( |
| + runner.get(), FROM_HERE, |
| + base::Bind(&ArcProcessService::GetArcSystemProcessList), callback); |
| +} |
| + |
| +// static |
| +vector<ArcProcess> ArcProcessService::GetArcSystemProcessList() { |
| + vector<ArcProcess> ret_processes; |
| + const base::ProcessIterator::ProcessEntries& entry_list = |
| + base::ProcessIterator(nullptr).Snapshot(); |
| + ProcessId arc_init_pid = GetArcInitProcessId(entry_list); |
| + |
| + if (arc_init_pid == kNullProcessId) { |
| + return ret_processes; |
| + } |
| + |
| + // Enumerate the child processes of ARC init for gathering ARC System |
| + // Processes. |
| + for (const base::ProcessEntry& entry : entry_list) { |
| + // TODO(hctsai): For now, we only gather direct child process of init, need |
| + // to get the processes below. For example, intalled might |
|
Luis Héctor Chávez
2016/07/06 20:28:12
nit: installd
|
| + // fork dex2oat and it can be executed for minutes. |
| + if (entry.parent_pid() == arc_init_pid) { |
| + const ProcessId child_pid = entry.pid(); |
| + const ProcessId child_nspid = |
| + base::Process(child_pid).GetPidInNamespace(); |
| + const std::string process_name = |
| + !entry.cmd_line_args().empty() ? entry.cmd_line_args()[0] : ""; |
| + if (child_nspid != kNullProcessId) { |
| + ret_processes.emplace_back(child_nspid, child_pid, process_name, |
| + mojom::ProcessState::PERSISTENT); |
| + } |
| + } |
| + } |
| + |
| + return ret_processes; |
| +} |
| + |
| +bool ArcProcessService::RequestAppProcessList( |
| RequestProcessListCallback callback) { |
| DCHECK_CURRENTLY_ON(content::BrowserThread::UI); |
| @@ -93,60 +138,52 @@ bool ArcProcessService::RequestProcessList( |
| return true; |
| } |
| +vector<ArcProcess> ArcProcessService::ConvertMojoProcess( |
| + mojo::Array<arc::mojom::RunningAppProcessInfoPtr>& mojo_processes) { |
| + vector<ArcProcess> ret_processes; |
| + |
| + for (const auto& entry : mojo_processes) { |
| + ArcProcess arc_process(entry->pid, nspid_to_pid_[entry->pid], |
| + entry->process_name, entry->process_state); |
| + // |entry->packages| is provided only when process.mojom's verion is >=4. |
| + if (entry->packages) { |
| + for (const auto& package : entry->packages) { |
| + arc_process.packages().push_back(package.get()); |
| + } |
| + } |
| + ret_processes.push_back(std::move(arc_process)); |
| + } |
| + |
| + return ret_processes; |
| +} |
| + |
| void ArcProcessService::OnReceiveProcessList( |
| const RequestProcessListCallback& callback, |
| mojo::Array<arc::mojom::RunningAppProcessInfoPtr> mojo_processes) { |
|
Luis Héctor Chávez
2016/07/06 20:28:12
nit: if possible, rename all the |mojo_processes|
|
| DCHECK_CURRENTLY_ON(content::BrowserThread::UI); |
| - auto raw_processes = new vector<mojom::RunningAppProcessInfoPtr>(); |
| - mojo_processes.Swap(raw_processes); |
| - |
| - auto ret_processes = new vector<ArcProcess>(); |
| - // Post to its dedicated worker thread to avoid race condition. |
| - // Since no two tasks with the same token should be run at the same. |
| - // Note: GetSequencedTaskRunner's shutdown behavior defaults to |
| - // SKIP_ON_SHUTDOWN (ongoing task blocks shutdown). |
| - // So in theory using Unretained(this) should be fine since the life cycle |
| - // of |this| is the same as the main browser. |
| - // To be safe I still use weak pointers, but weak_ptrs can only bind to |
| - // methods without return values. That's why I can't use |
| - // PostTaskAndReplyWithResult but handle the return object by myself. |
| + vector<ArcProcess> processes = ConvertMojoProcess(mojo_processes); |
| auto runner = worker_pool_->GetSequencedTaskRunner( |
| worker_pool_->GetNamedSequenceToken(kSequenceToken)); |
| - runner->PostTaskAndReply( |
| - FROM_HERE, |
| - base::Bind(&ArcProcessService::UpdateAndReturnProcessList, |
| - weak_ptr_factory_.GetWeakPtr(), |
| - base::Owned(raw_processes), |
| - base::Unretained(ret_processes)), |
| - base::Bind(&ArcProcessService::CallbackRelay, |
| - weak_ptr_factory_.GetWeakPtr(), |
| - callback, |
| - base::Owned(ret_processes))); |
| + base::PostTaskAndReplyWithResult( |
| + runner.get(), FROM_HERE, |
| + base::Bind(&ArcProcessService::UpdateAndReturnProcessList, this, |
| + base::Passed(&processes)), |
| + callback); |
| } |
| -void ArcProcessService::CallbackRelay( |
| - const RequestProcessListCallback& callback, |
| - const vector<ArcProcess>* ret_processes) { |
| - DCHECK_CURRENTLY_ON(content::BrowserThread::UI); |
| - callback.Run(*ret_processes); |
| -} |
| - |
| -void ArcProcessService::UpdateAndReturnProcessList( |
| - const vector<arc::mojom::RunningAppProcessInfoPtr>* raw_processes, |
| - vector<ArcProcess>* ret_processes) { |
| - DCHECK(thread_checker_.CalledOnValidThread()); |
| - |
| +vector<ArcProcess> ArcProcessService::UpdateAndReturnProcessList( |
| + const vector<ArcProcess>& processes) { |
| // Cleanup dead pids in the cache |nspid_to_pid_|. |
| set<ProcessId> nspid_to_remove; |
| for (const auto& entry : nspid_to_pid_) { |
| nspid_to_remove.insert(entry.first); |
| } |
| bool unmapped_nspid = false; |
| - for (const auto& entry : *raw_processes) { |
| + for (const auto& entry : processes) { |
| // erase() returns 0 if coudln't find the key. It means a new process. |
| - if (nspid_to_remove.erase(entry->pid) == 0) { |
| - nspid_to_pid_[entry->pid] = kNullProcessId; |
| + if (nspid_to_remove.erase(entry.pid()) == 0) { |
| + nspid_to_pid_[entry.pid()] = kNullProcessId; |
| unmapped_nspid = true; |
| } |
| } |
| @@ -159,29 +196,24 @@ void ArcProcessService::UpdateAndReturnProcessList( |
| UpdateNspidToPidMap(); |
| } |
| - PopulateProcessList(raw_processes, ret_processes); |
| + return PopulateProcessList(processes); |
| } |
| -void ArcProcessService::PopulateProcessList( |
| - const vector<arc::mojom::RunningAppProcessInfoPtr>* raw_processes, |
| - vector<ArcProcess>* ret_processes) { |
| +vector<ArcProcess> ArcProcessService::PopulateProcessList( |
| + const vector<ArcProcess>& processes) { |
| DCHECK(thread_checker_.CalledOnValidThread()); |
| + vector<ArcProcess> ret_processes; |
| - for (const auto& entry : *raw_processes) { |
| - const auto it = nspid_to_pid_.find(entry->pid); |
| + for (const auto& entry : processes) { |
| + const auto it = nspid_to_pid_.find(entry.pid()); |
| // In case the process already dies so couldn't find corresponding pid. |
| if (it != nspid_to_pid_.end() && it->second != kNullProcessId) { |
| - ArcProcess arc_process(entry->pid, it->second, entry->process_name, |
| - entry->process_state); |
| - // |entry->packages| is provided only when process.mojom's verion is >=4. |
| - if (entry->packages) { |
| - for (const auto& package : entry->packages) { |
| - arc_process.packages().push_back(package.get()); |
| - } |
| - } |
| - ret_processes->push_back(std::move(arc_process)); |
| + ArcProcess arc_process(entry.nspid(), entry.pid(), entry.process_name(), |
| + entry.process_state()); |
| + ret_processes.push_back(std::move(arc_process)); |
| } |
| } |
| + return ret_processes; |
| } |
| // Computes a map from PID in ARC namespace to PID in system namespace. |
| @@ -208,16 +240,7 @@ void ArcProcessService::UpdateNspidToPidMap() { |
| process_tree[entry.parent_pid()].push_back(entry.pid()); |
| // Find the ARC init process. |
| - ProcessId arc_init_pid = kNullProcessId; |
| - for (const base::ProcessEntry& entry : entry_list) { |
| - // TODO(nya): Add more constraints to avoid mismatches. |
| - std::string process_name = |
| - !entry.cmd_line_args().empty() ? entry.cmd_line_args()[0] : ""; |
| - if (process_name == "/init") { |
| - arc_init_pid = entry.pid(); |
| - break; |
| - } |
| - } |
| + ProcessId arc_init_pid = GetArcInitProcessId(entry_list); |
| // Enumerate all processes under ARC init and create nspid -> pid map. |
| if (arc_init_pid != kNullProcessId) { |
| @@ -248,4 +271,19 @@ void ArcProcessService::UpdateNspidToPidMap() { |
| } |
| } |
| +// static |
| +ProcessId ArcProcessService::GetArcInitProcessId( |
| + const base::ProcessIterator::ProcessEntries& entry_list) { |
| + // Find the ARC init process. |
| + for (const base::ProcessEntry& entry : entry_list) { |
| + // TODO(nya): Add more constraints to avoid mismatches. |
| + std::string process_name = |
| + !entry.cmd_line_args().empty() ? entry.cmd_line_args()[0] : ""; |
| + if (process_name == "/init") { |
| + return entry.pid(); |
| + } |
| + } |
| + return kNullProcessId; |
| +} |
| + |
| } // namespace arc |