15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2011 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/test/base/chrome_process_util.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <set>
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <string>
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <vector>
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/command_line.h"
12bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch#include "base/process/kill.h"
13bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch#include "base/process/process_iterator.h"
14eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/time/time.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/chrome_constants.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/test/base/test_switches.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/common/result_codes.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using base::TimeDelta;
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using base::TimeTicks;
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
22eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochnamespace {
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
24eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch// Returns the executable name of the current Chrome helper process.
252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)std::vector<base::FilePath::StringType> GetRunningHelperExecutableNames() {
26f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  base::FilePath::StringType name = chrome::kHelperProcessExecutableName;
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::vector<base::FilePath::StringType> names;
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  names.push_back(name);
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_MACOSX)
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The helper might show up as these different flavors depending on the
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // executable flags required.
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (const char* const* suffix = chrome::kHelperFlavorSuffixes;
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       *suffix;
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       ++suffix) {
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string flavor_name(name);
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    flavor_name.append(1, ' ');
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    flavor_name.append(*suffix);
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    names.push_back(flavor_name);
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return names;
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
47eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}  // namespace
48eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
49eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochvoid TerminateAllChromeProcesses(const ChromeProcessList& process_pids) {
50eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  ChromeProcessList::const_iterator it;
51eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  for (it = process_pids.begin(); it != process_pids.end(); ++it) {
52eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    base::ProcessHandle handle;
53eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    if (!base::OpenProcessHandle(*it, &handle)) {
54eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      // Ignore processes for which we can't open the handle. We don't
55eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      // guarantee that all processes will terminate, only try to do so.
56eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      continue;
57eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    }
58eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
59eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    base::KillProcess(handle, content::RESULT_CODE_KILLED, true);
60eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    base::CloseProcessHandle(handle);
61eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
62eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
63eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
64eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochclass ChildProcessFilter : public base::ProcessFilter {
65eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch public:
66eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  explicit ChildProcessFilter(base::ProcessId parent_pid)
67eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      : parent_pids_(&parent_pid, (&parent_pid) + 1) {}
68eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
69eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  explicit ChildProcessFilter(const std::vector<base::ProcessId>& parent_pids)
70eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      : parent_pids_(parent_pids.begin(), parent_pids.end()) {}
71eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
72eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  virtual bool Includes(const base::ProcessEntry& entry) const OVERRIDE {
73eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    return parent_pids_.find(entry.parent_pid()) != parent_pids_.end();
74eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
75eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
76eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch private:
77eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  const std::set<base::ProcessId> parent_pids_;
78eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
79eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  DISALLOW_COPY_AND_ASSIGN(ChildProcessFilter);
80eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch};
81eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ChromeProcessList GetRunningChromeProcesses(base::ProcessId browser_pid) {
832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const base::FilePath::CharType* executable_name =
84f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      chrome::kBrowserProcessExecutableName;
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ChromeProcessList result;
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (browser_pid == static_cast<base::ProcessId>(-1))
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return result;
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ChildProcessFilter filter(browser_pid);
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::NamedProcessIterator it(executable_name, &filter);
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  while (const base::ProcessEntry* process_entry = it.NextProcessEntry()) {
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    result.push_back(process_entry->pid());
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_POSIX) && !defined(OS_MACOSX)
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // On Unix we might be running with a zygote process for the renderers.
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Because of that we sweep the list of processes again and pick those which
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // are children of one of the processes that we've already seen.
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ChildProcessFilter filter(result);
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::NamedProcessIterator it(executable_name, &filter);
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    while (const base::ProcessEntry* process_entry = it.NextProcessEntry())
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      result.push_back(process_entry->pid());
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif  // defined(OS_POSIX) && !defined(OS_MACOSX)
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_POSIX)
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // On Mac OS X we run the subprocesses with a different bundle, and
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // on Linux via /proc/self/exe, so they end up with a different
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // name.  We must collect them in a second pass.
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
1122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    std::vector<base::FilePath::StringType> names =
1132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        GetRunningHelperExecutableNames();
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (size_t i = 0; i < names.size(); ++i) {
1152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::FilePath::StringType name = names[i];
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ChildProcessFilter filter(browser_pid);
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::NamedProcessIterator it(name, &filter);
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      while (const base::ProcessEntry* process_entry = it.NextProcessEntry())
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        result.push_back(process_entry->pid());
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif  // defined(OS_POSIX)
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  result.push_back(browser_pid);
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return result;
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if !defined(OS_MACOSX)
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)size_t ChromeTestProcessMetrics::GetPagefileUsage() {
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return process_metrics_->GetPagefileUsage();
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)size_t ChromeTestProcessMetrics::GetWorkingSetSize() {
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return process_metrics_->GetWorkingSetSize();
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif  // !defined(OS_MACOSX)
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ChromeTestProcessMetrics::~ChromeTestProcessMetrics() {}
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ChromeTestProcessMetrics::ChromeTestProcessMetrics(
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::ProcessHandle process) {
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if !defined(OS_MACOSX)
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  process_metrics_.reset(
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::ProcessMetrics::CreateProcessMetrics(process));
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  process_metrics_.reset(
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::ProcessMetrics::CreateProcessMetrics(process, NULL));
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  process_handle_ = process;
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
154