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 "base/strings/utf_string_conversions.h"
15 #include "chrome/common/chrome_constants.h"
16 #include "chrome/grit/chromium_strings.h"
17 #include "content/public/browser/browser_thread.h"
18 #include "content/public/common/process_type.h"
19 #include "ui/base/l10n/l10n_util.h"
21 using base::ProcessEntry
;
22 using base::ProcessId
;
23 using content::BrowserThread
;
27 // A helper for |CollectProcessData()| to include the chrome sandboxed
28 // processes in android which are not running as a child of the browser
30 void AddNonChildChromeProcesses(
31 std::vector
<ProcessMemoryInformation
>* processes
) {
32 base::ProcessIterator
process_iter(NULL
);
33 while (const ProcessEntry
* process_entry
= process_iter
.NextProcessEntry()) {
34 const std::vector
<std::string
>& cmd_args
= process_entry
->cmd_line_args();
35 if (cmd_args
.empty() ||
36 cmd_args
[0].find(chrome::kHelperProcessExecutableName
) ==
40 ProcessMemoryInformation info
;
41 info
.pid
= process_entry
->pid();
42 processes
->push_back(info
);
46 // For each of the pids, collect memory information about that process
47 // and append a record to |out|.
48 void GetProcessDataMemoryInformation(
49 const std::set
<ProcessId
>& pids
, ProcessData
* out
) {
50 for (std::set
<ProcessId
>::const_iterator i
= pids
.begin(); i
!= pids
.end();
52 ProcessMemoryInformation pmi
;
55 pmi
.num_processes
= 1;
57 if (pmi
.pid
== base::GetCurrentProcId())
58 pmi
.process_type
= content::PROCESS_TYPE_BROWSER
;
60 pmi
.process_type
= content::PROCESS_TYPE_UNKNOWN
;
62 scoped_ptr
<base::ProcessMetrics
> metrics(
63 base::ProcessMetrics::CreateProcessMetrics(*i
));
64 metrics
->GetWorkingSetKBytes(&pmi
.working_set
);
66 out
->processes
.push_back(pmi
);
70 // Find all children of the given process.
71 void GetAllChildren(const std::vector
<ProcessEntry
>& processes
,
72 const std::set
<ProcessId
>& roots
,
73 std::set
<ProcessId
>* out
) {
76 std::set
<ProcessId
> wavefront
;
77 for (std::set
<ProcessId
>::const_iterator i
= roots
.begin(); i
!= roots
.end();
82 while (wavefront
.size()) {
83 std::set
<ProcessId
> next_wavefront
;
84 for (std::vector
<ProcessEntry
>::const_iterator i
= processes
.begin();
85 i
!= processes
.end(); ++i
) {
86 if (wavefront
.count(i
->parent_pid())) {
87 out
->insert(i
->pid());
88 next_wavefront
.insert(i
->pid());
93 wavefront
.swap(next_wavefront
);
99 MemoryDetails::MemoryDetails() {
102 ProcessData
* MemoryDetails::ChromeBrowser() {
103 return &process_data_
[0];
106 void MemoryDetails::CollectProcessData(
108 const std::vector
<ProcessMemoryInformation
>& chrome_processes
) {
109 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
111 std::vector
<ProcessMemoryInformation
> all_processes(chrome_processes
);
112 AddNonChildChromeProcesses(&all_processes
);
114 std::vector
<ProcessEntry
> processes
;
115 base::ProcessIterator
process_iter(NULL
);
116 while (const ProcessEntry
* process_entry
= process_iter
.NextProcessEntry()) {
117 processes
.push_back(*process_entry
);
120 std::set
<ProcessId
> roots
;
121 roots
.insert(base::GetCurrentProcId());
122 for (std::vector
<ProcessMemoryInformation
>::const_iterator
123 i
= all_processes
.begin(); i
!= all_processes
.end(); ++i
) {
124 roots
.insert(i
->pid
);
127 std::set
<ProcessId
> current_browser_processes
;
128 GetAllChildren(processes
, roots
, ¤t_browser_processes
);
130 ProcessData current_browser
;
131 GetProcessDataMemoryInformation(current_browser_processes
, ¤t_browser
);
132 current_browser
.name
= l10n_util::GetStringUTF16(IDS_PRODUCT_NAME
);
133 current_browser
.process_name
=
134 base::ASCIIToUTF16(chrome::kBrowserProcessExecutableName
);
135 process_data_
.push_back(current_browser
);
137 // Finally return to the browser thread.
138 BrowserThread::PostTask(
139 BrowserThread::UI
, FROM_HERE
,
140 base::Bind(&MemoryDetails::CollectChildInfoOnUIThread
, this));