blob: 185669adfe92f125d91f285c6da6467dfc1ec79c [file] [log] [blame]
[email protected]52b590e2012-02-20 23:02:421// 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/memory_details.h"
6
dcheng4af48582016-04-19 00:29:357#include <memory>
[email protected]52b590e2012-02-20 23:02:428#include <set>
[email protected]0b7b99a2013-01-16 17:42:569#include <string>
10#include <vector>
[email protected]52b590e2012-02-20 23:02:4211
12#include "base/bind.h"
[email protected]54724e22013-07-25 13:02:1513#include "base/process/process_iterator.h"
[email protected]995378a2014-03-28 04:11:0514#include "base/strings/utf_string_conversions.h"
Eric Seckler8652dcd52018-09-20 10:42:2815#include "base/task/post_task.h"
Etienne Pierre-doray7675ee52018-09-11 21:55:4616#include "base/threading/scoped_blocking_call.h"
[email protected]52b590e2012-02-20 23:02:4217#include "chrome/common/chrome_constants.h"
[email protected]af39f002014-08-22 10:18:1818#include "chrome/grit/chromium_strings.h"
Eric Seckler8652dcd52018-09-20 10:42:2819#include "content/public/browser/browser_task_traits.h"
[email protected]52b590e2012-02-20 23:02:4220#include "content/public/browser/browser_thread.h"
21#include "content/public/common/process_type.h"
[email protected]52b590e2012-02-20 23:02:4222#include "ui/base/l10n/l10n_util.h"
23
24using base::ProcessEntry;
25using base::ProcessId;
26using content::BrowserThread;
27
28namespace {
29
30// A helper for |CollectProcessData()| to include the chrome sandboxed
31// processes in android which are not running as a child of the browser
32// process.
33void AddNonChildChromeProcesses(
34 std::vector<ProcessMemoryInformation>* processes) {
35 base::ProcessIterator process_iter(NULL);
36 while (const ProcessEntry* process_entry = process_iter.NextProcessEntry()) {
[email protected]0b7b99a2013-01-16 17:42:5637 const std::vector<std::string>& cmd_args = process_entry->cmd_line_args();
38 if (cmd_args.empty() ||
39 cmd_args[0].find(chrome::kHelperProcessExecutableName) ==
40 std::string::npos) {
[email protected]52b590e2012-02-20 23:02:4241 continue;
42 }
43 ProcessMemoryInformation info;
44 info.pid = process_entry->pid();
45 processes->push_back(info);
46 }
47}
48
49// For each of the pids, collect memory information about that process
50// and append a record to |out|.
51void GetProcessDataMemoryInformation(
52 const std::set<ProcessId>& pids, ProcessData* out) {
53 for (std::set<ProcessId>::const_iterator i = pids.begin(); i != pids.end();
54 ++i) {
55 ProcessMemoryInformation pmi;
56
57 pmi.pid = *i;
58 pmi.num_processes = 1;
59
Siddhartha73d35d092017-12-21 20:09:2060 base::ProcessId current_pid = base::GetCurrentProcId();
61 if (pmi.pid == current_pid)
[email protected]f3b357692013-03-22 05:16:1362 pmi.process_type = content::PROCESS_TYPE_BROWSER;
[email protected]52b590e2012-02-20 23:02:4263 else
[email protected]f3b357692013-03-22 05:16:1364 pmi.process_type = content::PROCESS_TYPE_UNKNOWN;
[email protected]52b590e2012-02-20 23:02:4265
dcheng4af48582016-04-19 00:29:3566 std::unique_ptr<base::ProcessMetrics> metrics(
[email protected]52b590e2012-02-20 23:02:4267 base::ProcessMetrics::CreateProcessMetrics(*i));
Siddhartha73d35d092017-12-21 20:09:2068
69 // TODO(ssid): Reading "/proc/fd" only works for current process. For child
70 // processes, the values need to be computed by the process itself.
71 if (pmi.pid == current_pid) {
72 pmi.num_open_fds = metrics->GetOpenFdCount();
73 pmi.open_fds_soft_limit = metrics->GetOpenFdSoftLimit();
74 }
[email protected]52b590e2012-02-20 23:02:4275
76 out->processes.push_back(pmi);
77 }
78}
79
80// Find all children of the given process.
81void GetAllChildren(const std::vector<ProcessEntry>& processes,
82 const std::set<ProcessId>& roots,
83 std::set<ProcessId>* out) {
84 *out = roots;
85
86 std::set<ProcessId> wavefront;
87 for (std::set<ProcessId>::const_iterator i = roots.begin(); i != roots.end();
88 ++i) {
89 wavefront.insert(*i);
90 }
91
92 while (wavefront.size()) {
93 std::set<ProcessId> next_wavefront;
94 for (std::vector<ProcessEntry>::const_iterator i = processes.begin();
95 i != processes.end(); ++i) {
96 if (wavefront.count(i->parent_pid())) {
97 out->insert(i->pid());
98 next_wavefront.insert(i->pid());
99 }
100 }
101
102 wavefront.clear();
103 wavefront.swap(next_wavefront);
104 }
105}
106
107} // namespace
108
asvitkine89406d1f2015-01-17 06:57:10109MemoryDetails::MemoryDetails() {
[email protected]52b590e2012-02-20 23:02:42110}
111
112ProcessData* MemoryDetails::ChromeBrowser() {
113 return &process_data_[0];
114}
115
116void MemoryDetails::CollectProcessData(
117 const std::vector<ProcessMemoryInformation>& chrome_processes) {
Etienne Pierre-doray7675ee52018-09-11 21:55:46118 base::ScopedBlockingCall scoped_blocking_call(base::BlockingType::WILL_BLOCK);
[email protected]52b590e2012-02-20 23:02:42119
120 std::vector<ProcessMemoryInformation> all_processes(chrome_processes);
121 AddNonChildChromeProcesses(&all_processes);
122
123 std::vector<ProcessEntry> processes;
124 base::ProcessIterator process_iter(NULL);
125 while (const ProcessEntry* process_entry = process_iter.NextProcessEntry()) {
126 processes.push_back(*process_entry);
127 }
128
129 std::set<ProcessId> roots;
130 roots.insert(base::GetCurrentProcId());
131 for (std::vector<ProcessMemoryInformation>::const_iterator
132 i = all_processes.begin(); i != all_processes.end(); ++i) {
133 roots.insert(i->pid);
134 }
135
136 std::set<ProcessId> current_browser_processes;
137 GetAllChildren(processes, roots, &current_browser_processes);
138
139 ProcessData current_browser;
140 GetProcessDataMemoryInformation(current_browser_processes, &current_browser);
141 current_browser.name = l10n_util::GetStringUTF16(IDS_PRODUCT_NAME);
142 current_browser.process_name =
[email protected]995378a2014-03-28 04:11:05143 base::ASCIIToUTF16(chrome::kBrowserProcessExecutableName);
[email protected]52b590e2012-02-20 23:02:42144 process_data_.push_back(current_browser);
145
146 // Finally return to the browser thread.
Eric Seckler8652dcd52018-09-20 10:42:28147 base::PostTaskWithTraits(
148 FROM_HERE, {BrowserThread::UI},
[email protected]52b590e2012-02-20 23:02:42149 base::Bind(&MemoryDetails::CollectChildInfoOnUIThread, this));
150}