1 // 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.
5 #include "chrome/browser/memory_details.h"
11 #include "base/bind.h"
12 #include "base/memory/scoped_ptr.h"
13 #include "base/process/process_iterator.h"
14 #include "chrome/common/chrome_constants.h"
15 #include "content/public/browser/browser_thread.h"
16 #include "content/public/common/process_type.h"
17 #include "grit/chromium_strings.h"
18 #include "ui/base/l10n/l10n_util.h"
20 using base::ProcessEntry
;
21 using base::ProcessId
;
22 using content::BrowserThread
;
26 // A helper for |CollectProcessData()| to include the chrome sandboxed
27 // processes in android which are not running as a child of the browser
29 void AddNonChildChromeProcesses(
30 std::vector
<ProcessMemoryInformation
>* processes
) {
31 base::ProcessIterator
process_iter(NULL
);
32 while (const ProcessEntry
* process_entry
= process_iter
.NextProcessEntry()) {
33 const std::vector
<std::string
>& cmd_args
= process_entry
->cmd_line_args();
34 if (cmd_args
.empty() ||
35 cmd_args
[0].find(chrome::kHelperProcessExecutableName
) ==
39 ProcessMemoryInformation info
;
40 info
.pid
= process_entry
->pid();
41 processes
->push_back(info
);
45 // For each of the pids, collect memory information about that process
46 // and append a record to |out|.
47 void GetProcessDataMemoryInformation(
48 const std::set
<ProcessId
>& pids
, ProcessData
* out
) {
49 for (std::set
<ProcessId
>::const_iterator i
= pids
.begin(); i
!= pids
.end();
51 ProcessMemoryInformation pmi
;
54 pmi
.num_processes
= 1;
56 if (pmi
.pid
== base::GetCurrentProcId())
57 pmi
.process_type
= content::PROCESS_TYPE_BROWSER
;
59 pmi
.process_type
= content::PROCESS_TYPE_UNKNOWN
;
61 scoped_ptr
<base::ProcessMetrics
> metrics(
62 base::ProcessMetrics::CreateProcessMetrics(*i
));
63 metrics
->GetWorkingSetKBytes(&pmi
.working_set
);
65 out
->processes
.push_back(pmi
);
69 // Find all children of the given process.
70 void GetAllChildren(const std::vector
<ProcessEntry
>& processes
,
71 const std::set
<ProcessId
>& roots
,
72 std::set
<ProcessId
>* out
) {
75 std::set
<ProcessId
> wavefront
;
76 for (std::set
<ProcessId
>::const_iterator i
= roots
.begin(); i
!= roots
.end();
81 while (wavefront
.size()) {
82 std::set
<ProcessId
> next_wavefront
;
83 for (std::vector
<ProcessEntry
>::const_iterator i
= processes
.begin();
84 i
!= processes
.end(); ++i
) {
85 if (wavefront
.count(i
->parent_pid())) {
86 out
->insert(i
->pid());
87 next_wavefront
.insert(i
->pid());
92 wavefront
.swap(next_wavefront
);
98 MemoryDetails::MemoryDetails()
99 : user_metrics_mode_(UPDATE_USER_METRICS
) {
102 ProcessData
* MemoryDetails::ChromeBrowser() {
103 return &process_data_
[0];
106 void MemoryDetails::CollectProcessData(
107 const std::vector
<ProcessMemoryInformation
>& chrome_processes
) {
108 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
110 std::vector
<ProcessMemoryInformation
> all_processes(chrome_processes
);
111 AddNonChildChromeProcesses(&all_processes
);
113 std::vector
<ProcessEntry
> processes
;
114 base::ProcessIterator
process_iter(NULL
);
115 while (const ProcessEntry
* process_entry
= process_iter
.NextProcessEntry()) {
116 processes
.push_back(*process_entry
);
119 std::set
<ProcessId
> roots
;
120 roots
.insert(base::GetCurrentProcId());
121 for (std::vector
<ProcessMemoryInformation
>::const_iterator
122 i
= all_processes
.begin(); i
!= all_processes
.end(); ++i
) {
123 roots
.insert(i
->pid
);
126 std::set
<ProcessId
> current_browser_processes
;
127 GetAllChildren(processes
, roots
, ¤t_browser_processes
);
129 ProcessData current_browser
;
130 GetProcessDataMemoryInformation(current_browser_processes
, ¤t_browser
);
131 current_browser
.name
= l10n_util::GetStringUTF16(IDS_PRODUCT_NAME
);
132 current_browser
.process_name
=
133 reinterpret_cast<unsigned int>(chrome::kBrowserProcessExecutableName
);
134 process_data_
.push_back(current_browser
);
136 // Finally return to the browser thread.
137 BrowserThread::PostTask(
138 BrowserThread::UI
, FROM_HERE
,
139 base::Bind(&MemoryDetails::CollectChildInfoOnUIThread
, this));