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