1 // Copyright (c) 2011 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/test/base/chrome_process_util.h"
11 #include "base/command_line.h"
12 #include "base/process/kill.h"
13 #include "base/process/process.h"
14 #include "base/process/process_iterator.h"
15 #include "base/time/time.h"
16 #include "chrome/common/chrome_constants.h"
17 #include "chrome/test/base/test_switches.h"
18 #include "content/public/common/result_codes.h"
20 using base::TimeDelta
;
21 using base::TimeTicks
;
25 // Returns the executable name of the current Chrome helper process.
26 std::vector
<base::FilePath::StringType
> GetRunningHelperExecutableNames() {
27 base::FilePath::StringType name
= chrome::kHelperProcessExecutableName
;
29 std::vector
<base::FilePath::StringType
> names
;
30 names
.push_back(name
);
32 #if defined(OS_MACOSX)
33 // The helper might show up as these different flavors depending on the
34 // executable flags required.
35 for (const char* const* suffix
= chrome::kHelperFlavorSuffixes
;
38 std::string
flavor_name(name
);
39 flavor_name
.append(1, ' ');
40 flavor_name
.append(*suffix
);
41 names
.push_back(flavor_name
);
50 void TerminateAllChromeProcesses(const ChromeProcessList
& process_pids
) {
51 ChromeProcessList::const_iterator it
;
52 for (it
= process_pids
.begin(); it
!= process_pids
.end(); ++it
) {
53 base::Process process
= base::Process::Open(*it
);
54 if (process
.IsValid()) {
55 // Ignore processes for which we can't open the handle. We don't
56 // guarantee that all processes will terminate, only try to do so.
57 base::KillProcess(process
.Handle(), content::RESULT_CODE_KILLED
, true);
62 class ChildProcessFilter
: public base::ProcessFilter
{
64 explicit ChildProcessFilter(base::ProcessId parent_pid
)
65 : parent_pids_(&parent_pid
, (&parent_pid
) + 1) {}
67 explicit ChildProcessFilter(const std::vector
<base::ProcessId
>& parent_pids
)
68 : parent_pids_(parent_pids
.begin(), parent_pids
.end()) {}
70 bool Includes(const base::ProcessEntry
& entry
) const override
{
71 return parent_pids_
.find(entry
.parent_pid()) != parent_pids_
.end();
75 const std::set
<base::ProcessId
> parent_pids_
;
77 DISALLOW_COPY_AND_ASSIGN(ChildProcessFilter
);
80 ChromeProcessList
GetRunningChromeProcesses(base::ProcessId browser_pid
) {
81 const base::FilePath::CharType
* executable_name
=
82 chrome::kBrowserProcessExecutableName
;
83 ChromeProcessList result
;
84 if (browser_pid
== static_cast<base::ProcessId
>(-1))
87 ChildProcessFilter
filter(browser_pid
);
88 base::NamedProcessIterator
it(executable_name
, &filter
);
89 while (const base::ProcessEntry
* process_entry
= it
.NextProcessEntry()) {
90 result
.push_back(process_entry
->pid());
93 #if defined(OS_POSIX) && !defined(OS_MACOSX)
94 // On Unix we might be running with a zygote process for the renderers.
95 // Because of that we sweep the list of processes again and pick those which
96 // are children of one of the processes that we've already seen.
98 ChildProcessFilter
filter(result
);
99 base::NamedProcessIterator
it(executable_name
, &filter
);
100 while (const base::ProcessEntry
* process_entry
= it
.NextProcessEntry())
101 result
.push_back(process_entry
->pid());
103 #endif // defined(OS_POSIX) && !defined(OS_MACOSX)
105 #if defined(OS_POSIX)
106 // On Mac OS X we run the subprocesses with a different bundle, and
107 // on Linux via /proc/self/exe, so they end up with a different
108 // name. We must collect them in a second pass.
110 std::vector
<base::FilePath::StringType
> names
=
111 GetRunningHelperExecutableNames();
112 for (size_t i
= 0; i
< names
.size(); ++i
) {
113 base::FilePath::StringType name
= names
[i
];
114 ChildProcessFilter
filter(browser_pid
);
115 base::NamedProcessIterator
it(name
, &filter
);
116 while (const base::ProcessEntry
* process_entry
= it
.NextProcessEntry())
117 result
.push_back(process_entry
->pid());
120 #endif // defined(OS_POSIX)
122 result
.push_back(browser_pid
);
127 #if !defined(OS_MACOSX)
129 size_t ChromeTestProcessMetrics::GetPagefileUsage() {
130 return process_metrics_
->GetPagefileUsage();
133 size_t ChromeTestProcessMetrics::GetWorkingSetSize() {
134 return process_metrics_
->GetWorkingSetSize();
137 #endif // !defined(OS_MACOSX)
139 ChromeTestProcessMetrics::~ChromeTestProcessMetrics() {}
141 ChromeTestProcessMetrics::ChromeTestProcessMetrics(
142 base::ProcessHandle process
) {
143 #if !defined(OS_MACOSX)
144 process_metrics_
.reset(
145 base::ProcessMetrics::CreateProcessMetrics(process
));
147 process_metrics_
.reset(
148 base::ProcessMetrics::CreateProcessMetrics(process
, NULL
));
150 process_handle_
= process
;