• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.
4 
5 #include "chrome/test/base/chrome_process_util.h"
6 
7 #include <set>
8 #include <string>
9 #include <vector>
10 
11 #include "base/command_line.h"
12 #include "base/process/kill.h"
13 #include "base/process/process_iterator.h"
14 #include "base/time/time.h"
15 #include "chrome/common/chrome_constants.h"
16 #include "chrome/test/base/test_switches.h"
17 #include "content/public/common/result_codes.h"
18 
19 using base::TimeDelta;
20 using base::TimeTicks;
21 
22 namespace {
23 
24 // Returns the executable name of the current Chrome browser process.
GetRunningBrowserExecutableName()25 const base::FilePath::CharType* GetRunningBrowserExecutableName() {
26   const CommandLine* cmd_line = CommandLine::ForCurrentProcess();
27   if (cmd_line->HasSwitch(switches::kEnableChromiumBranding))
28     return chrome::kBrowserProcessExecutableNameChromium;
29   return chrome::kBrowserProcessExecutableName;
30 }
31 
32 // Returns the executable name of the current Chrome helper process.
GetRunningHelperExecutableNames()33 std::vector<base::FilePath::StringType> GetRunningHelperExecutableNames() {
34   base::FilePath::StringType name;
35   const CommandLine* cmd_line = CommandLine::ForCurrentProcess();
36   if (cmd_line->HasSwitch(switches::kEnableChromiumBranding)) {
37     name = chrome::kHelperProcessExecutableNameChromium;
38   } else {
39     name = chrome::kHelperProcessExecutableName;
40   }
41 
42   std::vector<base::FilePath::StringType> names;
43   names.push_back(name);
44 
45 #if defined(OS_MACOSX)
46   // The helper might show up as these different flavors depending on the
47   // executable flags required.
48   for (const char* const* suffix = chrome::kHelperFlavorSuffixes;
49        *suffix;
50        ++suffix) {
51     std::string flavor_name(name);
52     flavor_name.append(1, ' ');
53     flavor_name.append(*suffix);
54     names.push_back(flavor_name);
55   }
56 #endif
57 
58   return names;
59 }
60 
61 }  // namespace
62 
TerminateAllChromeProcesses(const ChromeProcessList & process_pids)63 void TerminateAllChromeProcesses(const ChromeProcessList& process_pids) {
64   ChromeProcessList::const_iterator it;
65   for (it = process_pids.begin(); it != process_pids.end(); ++it) {
66     base::ProcessHandle handle;
67     if (!base::OpenProcessHandle(*it, &handle)) {
68       // Ignore processes for which we can't open the handle. We don't
69       // guarantee that all processes will terminate, only try to do so.
70       continue;
71     }
72 
73     base::KillProcess(handle, content::RESULT_CODE_KILLED, true);
74     base::CloseProcessHandle(handle);
75   }
76 }
77 
78 class ChildProcessFilter : public base::ProcessFilter {
79  public:
ChildProcessFilter(base::ProcessId parent_pid)80   explicit ChildProcessFilter(base::ProcessId parent_pid)
81       : parent_pids_(&parent_pid, (&parent_pid) + 1) {}
82 
ChildProcessFilter(const std::vector<base::ProcessId> & parent_pids)83   explicit ChildProcessFilter(const std::vector<base::ProcessId>& parent_pids)
84       : parent_pids_(parent_pids.begin(), parent_pids.end()) {}
85 
Includes(const base::ProcessEntry & entry) const86   virtual bool Includes(const base::ProcessEntry& entry) const OVERRIDE {
87     return parent_pids_.find(entry.parent_pid()) != parent_pids_.end();
88   }
89 
90  private:
91   const std::set<base::ProcessId> parent_pids_;
92 
93   DISALLOW_COPY_AND_ASSIGN(ChildProcessFilter);
94 };
95 
GetRunningChromeProcesses(base::ProcessId browser_pid)96 ChromeProcessList GetRunningChromeProcesses(base::ProcessId browser_pid) {
97   const base::FilePath::CharType* executable_name =
98       GetRunningBrowserExecutableName();
99   ChromeProcessList result;
100   if (browser_pid == static_cast<base::ProcessId>(-1))
101     return result;
102 
103   ChildProcessFilter filter(browser_pid);
104   base::NamedProcessIterator it(executable_name, &filter);
105   while (const base::ProcessEntry* process_entry = it.NextProcessEntry()) {
106     result.push_back(process_entry->pid());
107   }
108 
109 #if defined(OS_POSIX) && !defined(OS_MACOSX)
110   // On Unix we might be running with a zygote process for the renderers.
111   // Because of that we sweep the list of processes again and pick those which
112   // are children of one of the processes that we've already seen.
113   {
114     ChildProcessFilter filter(result);
115     base::NamedProcessIterator it(executable_name, &filter);
116     while (const base::ProcessEntry* process_entry = it.NextProcessEntry())
117       result.push_back(process_entry->pid());
118   }
119 #endif  // defined(OS_POSIX) && !defined(OS_MACOSX)
120 
121 #if defined(OS_POSIX)
122   // On Mac OS X we run the subprocesses with a different bundle, and
123   // on Linux via /proc/self/exe, so they end up with a different
124   // name.  We must collect them in a second pass.
125   {
126     std::vector<base::FilePath::StringType> names =
127         GetRunningHelperExecutableNames();
128     for (size_t i = 0; i < names.size(); ++i) {
129       base::FilePath::StringType name = names[i];
130       ChildProcessFilter filter(browser_pid);
131       base::NamedProcessIterator it(name, &filter);
132       while (const base::ProcessEntry* process_entry = it.NextProcessEntry())
133         result.push_back(process_entry->pid());
134     }
135   }
136 #endif  // defined(OS_POSIX)
137 
138   result.push_back(browser_pid);
139 
140   return result;
141 }
142 
143 #if !defined(OS_MACOSX)
144 
GetPagefileUsage()145 size_t ChromeTestProcessMetrics::GetPagefileUsage() {
146   return process_metrics_->GetPagefileUsage();
147 }
148 
GetWorkingSetSize()149 size_t ChromeTestProcessMetrics::GetWorkingSetSize() {
150   return process_metrics_->GetWorkingSetSize();
151 }
152 
153 #endif  // !defined(OS_MACOSX)
154 
~ChromeTestProcessMetrics()155 ChromeTestProcessMetrics::~ChromeTestProcessMetrics() {}
156 
ChromeTestProcessMetrics(base::ProcessHandle process)157 ChromeTestProcessMetrics::ChromeTestProcessMetrics(
158     base::ProcessHandle process) {
159 #if !defined(OS_MACOSX)
160   process_metrics_.reset(
161       base::ProcessMetrics::CreateProcessMetrics(process));
162 #else
163   process_metrics_.reset(
164       base::ProcessMetrics::CreateProcessMetrics(process, NULL));
165 #endif
166   process_handle_ = process;
167 }
168