// Copyright 2019 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "metrics/process_meter.h"

#include <pcrecpp.h>
#include <string>
#include <unordered_map>
#include <vector>

#include <base/command_line.h>
#include <base/files/file_enumerator.h>
#include <base/files/file_path.h>
#include <base/files/file_util.h>
#include <base/macros.h>
#include <base/strings/string_number_conversions.h>
#include <base/strings/string_split.h>
#include <base/strings/string_util.h>
#include <base/strings/stringprintf.h>
#include <gtest/gtest_prod.h>  // for FRIEND_TEST

#include "metrics/metrics_library.h"

namespace chromeos_metrics {

// UMA histogram names for process memory usage, split by process groups and
// types of memory.  They must match MemoryStatKind and ProcessGroupKind in
// process_meter.h.  C++ doesn't have C-style static array initializers, so the
// unit test checks this.
constexpr char const* kProcessMemoryUMANames[PG_KINDS_COUNT][MEM_KINDS_COUNT] =
    {{
         "Platform.Memory.Browser.Total",
         "Platform.Memory.Browser.Anon",
         "Platform.Memory.Browser.File",
         "Platform.Memory.Browser.Shmem",
         "Platform.Memory.Browser.Swap",
     },
     {
         "Platform.Memory.Gpu.Total",
         "Platform.Memory.Gpu.Anon",
         "Platform.Memory.Gpu.File",
         "Platform.Memory.Gpu.Shmem",
         "Platform.Memory.Gpu.Swap",
     },
     {
         "Platform.Memory.Renderers.Total",
         "Platform.Memory.Renderers.Anon",
         "Platform.Memory.Renderers.File",
         "Platform.Memory.Renderers.Shmem",
         "Platform.Memory.Renderers.Swap",
     },
     {
         "Platform.Memory.ARC.Total",
         "Platform.Memory.ARC.Anon",
         "Platform.Memory.ARC.File",
         "Platform.Memory.ARC.Shmem",
         "Platform.Memory.ARC.Swap",
     },
     {
         "Platform.Memory.VMs.Total",
         "Platform.Memory.VMs.Anon",
         "Platform.Memory.VMs.File",
         "Platform.Memory.VMs.Shmem",
         "Platform.Memory.VMs.Swap",
     },
     {
         "Platform.Memory.Daemons.Total",
         "Platform.Memory.Daemons.Anon",
         "Platform.Memory.Daemons.File",
         "Platform.Memory.Daemons.Shmem",
         "Platform.Memory.Daemons.Swap",
     }};

// Chrome process classification.  We rely on the "--type=xyz" command line flag
// to processes.  A partial list of types is in
// content/public/common/content_switches.cc.  We classify them as shown:
//
// const char kGpuProcess[]                    = "gpu-process";    // GPU
// const char kPpapiBrokerProcess[]            = "ppapi-broker";   // browser
// const char kPpapiPluginProcess[]            = "ppapi";          // renderer
// const char kRendererProcess[]               = "renderer";       // renderer
// const char kUtilityProcess[]                = "utility";        // renderer
//
// (PPAPI stands for "pepper plugin API", which includes Flash).  Additionally
// there is "zygote" and "broker", which we classify as browser.
//
// The browser process does not have a --type==xyz flag.

ChromeProcessKind GetChromeKind(const base::CommandLine& cmdline) {
  // Assume all Chrome binaries are in /opt/google/chrome.
  auto program = cmdline.GetProgram().MaybeAsASCII();

  // Chrome execs a bunch of other binaries (for instance, crossystem) so we
  // can't have a complete list.
  if (!base::StartsWith(program, "/opt/google/chrome",
                        base::CompareCase::SENSITIVE)) {
    return CHROME_OTHER;
  }

  if (program.find("/opt/google/chrome/nacl_helper") == 0)
    return CHROME_BROWSER_HELPER;

  if (!cmdline.HasSwitch("type"))
    return CHROME_BROWSER;

  auto type = cmdline.GetSwitchValueASCII("type");
  // TODO(chromium:963210): remove the following "if" and let the next one
  // handle the "broker" case.
  if (strcmp(type.c_str(), "broker") == 0)
    return CHROME_BROWSER_HELPER;

  if (type == "broker" || type == "ppapi-broker" || type == "zygote") {
    return CHROME_BROWSER_HELPER;
  }

  // clang-format off
  if (type == "renderer" ||
      type == "ppapi" ||
      type == "sandbox" ||
      type == "utility") {
    return CHROME_RENDERER;
  }
  // clang-format on

  if (type == "gpu-process")
    return CHROME_GPU;

  return CHROME_OTHER;
}

bool GetARCInitPID(const base::FilePath& run_root, int* pid_out) {
  // ARC init may have stopped and restarted, so look up its PID.
  std::string file_content;
  if (!base::ReadFileToString(run_root.Append(kMetricsARCInitPIDFile),
                              &file_content)) {
    // ARC is not running.
    return false;
  }

  base::TrimWhitespaceASCII(file_content, base::TRIM_TRAILING, &file_content);
  if (!base::StringToInt(file_content, pid_out)) {
    LOG(FATAL) << "invalid integer in ARC init pid file: " << file_content;
  }
  return true;
}

bool FindProcessWithPrefix(
    const std::string& prefix,
    const std::unordered_map<int, std::unique_ptr<ProcessNode>>& processes,
    ProcessNode** process) {
  for (const auto& pit : processes) {
    if (pit.second->HasPrefix(prefix)) {
      *process = pit.second.get();
      return true;
    }
  }
  return false;
}

const bool ProcessNode::HasPrefix(const std::string& prefix) const {
  return cmdline_.GetProgram().MaybeAsASCII().find(prefix) == 0;
}

const void ProcessNode::CollectSubtree(std::vector<ProcessNode*>* processes) {
  processes->push_back(this);
  for (const auto& child : children_) {
    child->CollectSubtree(processes);
  }
}

void ProcessInfo::Classify() {
  // Find all ARC processes starting from ARC init.
  int arc_init_pid;
  if (GetARCInitPID(run_root_, &arc_init_pid)) {
    if (process_map_.find(arc_init_pid) == process_map_.end()) {
      LOG(WARNING) << "ARC init disappeared";
    } else {
      process_map_[arc_init_pid]->CollectSubtree(&groups_[PG_ARC]);
    }
  }

  // Find VM processes starting from vm_concierge and seneschal processes.
  ProcessNode* concierge;
  if (FindProcessWithPrefix("/usr/bin/vm_concierge", process_map_, &concierge))
    concierge->CollectSubtree(&groups_[PG_VMS]);

  ProcessNode* seneschal;
  if (FindProcessWithPrefix("/usr/bin/seneschal", process_map_, &seneschal)) {
    seneschal->CollectSubtree(&groups_[PG_VMS]);
  }

  // Find the browser process.
  ProcessNode* browser_process = nullptr;
  for (const auto& pit : process_map_) {
    if (GetChromeKind(pit.second->GetCmdline()) == CHROME_BROWSER) {
      browser_process = pit.second.get();
    }
  }

  // Find all descendants of the chrome browser.
  std::vector<ProcessNode*> chrome_processes;
  if (browser_process != nullptr)
    browser_process->CollectSubtree(&chrome_processes);

  // Classify the chrome processes.
  for (const auto& process : chrome_processes) {
    switch (GetChromeKind(process->GetCmdline())) {
      case CHROME_RENDERER:
        groups_[PG_RENDERERS].push_back(process);
        break;
      case CHROME_GPU:
        groups_[PG_GPU].push_back(process);
        break;
      case CHROME_BROWSER:
      case CHROME_BROWSER_HELPER:
        groups_[PG_BROWSER].push_back(process);
        break;
      case CHROME_OTHER:
        // Treat other as a browser process.
        LOG(WARNING) << "Unknown chrome process type in "
                     << process->GetCmdlineString();
        groups_[PG_BROWSER].push_back(process);
        break;
      case CHROME_NOT_CHROME:
        LOG(FATAL) << "Unexpected chrome process: "
                   << process->GetCmdlineString();
        break;
    }
  }

  // Compute daemon processes.  Start by making a copy of the map of all
  // processes.  Then remove ARC, VMs, and Chrome processes.
  std::unordered_map<int, ProcessNode*> daemon_processes_map;
  for (const auto& pit : process_map_) {
    daemon_processes_map[pit.first] = pit.second.get();
  }

  for (const auto& process : groups_[PG_ARC]) {
    daemon_processes_map.erase(process->GetPID());
  }
  for (const auto& process : groups_[PG_VMS]) {
    daemon_processes_map.erase(process->GetPID());
  }
  for (const auto& process : chrome_processes) {
    daemon_processes_map.erase(process->GetPID());
  }

  for (const auto& pit : daemon_processes_map) {
    groups_[PG_DAEMONS].push_back(pit.second);
  }

  // Make sure there is at most one GPU process.
  CHECK_LE(groups_[PG_GPU].size(), 1);
}

bool ProcessNode::RetrieveProcessData(const base::FilePath& procfs_root) {
  std::string file_content;
  // Get PPID and name from /proc/#/stat.
  const std::string stat_name = base::StringPrintf("%d/stat", pid_);
  const base::FilePath stat_path = procfs_root.Append(stat_name);
  if (!base::ReadFileToString(stat_path, &file_content)) {
    // Assume process has exited.
    return false;
  }
  // stat: pid (comm) run_state ppid etc. The only parentheses in the file
  // are around <comm>.
  pcrecpp::RE re(R"(.*\((.*)\) \w+ (\d+)(.|\n)*)");
  if (!re.FullMatch(file_content, &name_, &ppid_))
    LOG(FATAL) << "cannot parse /proc/pid/stat: " << file_content;

  // Get command line from /proc/#/cmdline and parse it.
  const std::string cmdline_name = base::StringPrintf("%d/cmdline", pid_);
  const base::FilePath cmdline_path = procfs_root.Append(cmdline_name);
  if (!base::ReadFileToString(cmdline_path, &file_content)) {
    // Assume process has exited.
    return false;
  }
  cmdline_string_ = file_content;
  cmdline_ = base::CommandLine(base::SplitString(
      file_content, " ", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY));

  return true;
}

void ProcessNode::LinkToParent(
    const std::unordered_map<int, std::unique_ptr<ProcessNode>>& processes) {
  if (ppid_ == 0) {
    // Not every process has a parent.
    return;
  }
  auto pit = processes.find(ppid_);
  if (pit == processes.end()) {
    // Parent process does not exist.  This might happen on a race, before the
    // orphan is reparented to init.  At worst, this should be rare.  We do the
    // reparenting for consistency.
    LOG(WARNING) << "PID " << pid_ << ": parent " << ppid_ << " not found";
    ppid_ = 1;
    pit = processes.find(ppid_);
  }
  // |pit| is now guaranteed to be valid.
  parent_ = pit->second.get();
  parent_->children_.push_back(this);
}

void ProcessInfo::Collect() {
  // Collect all processes.
  base::FileEnumerator proc_enum(procfs_root_, false,
                                 base::FileEnumerator::DIRECTORIES);
  for (base::FilePath path = proc_enum.Next(); !path.empty();
       path = proc_enum.Next()) {
    std::string pid_string = path.BaseName().MaybeAsASCII();
    // Skip directories that do not represent processes.
    int pid;
    if (!base::StringToInt(pid_string, &pid))
      continue;
    if (process_map_.find(pid) == process_map_.end()) {
      process_map_.emplace(pid, std::make_unique<ProcessNode>(pid));
    } else {
      // This seems rather unlikely, but just in case.
      LOG(WARNING) << "duplicate PID: " << pid;
    }
  }

  // Sanity check.
  if (process_map_.find(1) == process_map_.end())
    LOG(FATAL) << "cannot find init process";

  // Construct process tree.
  for (const auto& pit : process_map_) {
    ProcessNode* process = pit.second.get();
    if (!process->RetrieveProcessData(procfs_root_)) {
      // Process went away, so ignore it.
      continue;
    }
    // Set up parent/children links.
    process->LinkToParent(process_map_);
  }
}

const std::vector<ProcessNode*>& ProcessInfo::GetGroup(
    ProcessGroupKind group_kind) {
  return groups_[group_kind];
}

void GetMemoryUsage(const base::FilePath& procfs_path,
                    int pid,
                    ProcessMemoryStats* stats) {
  static bool has_smaps_rollup =
      base::PathExists(procfs_path.Append("1/smaps_rollup"));
  std::string file_content;

  const std::string file_name = has_smaps_rollup
                                    ? base::StringPrintf("%d/smaps_rollup", pid)
                                    : base::StringPrintf("%d/totmaps", pid);
  const base::FilePath file_path = procfs_path.Append(file_name);
  if (!base::ReadFileToString(file_path, &file_content))
    return;
  const std::vector<std::string> lines = base::SplitString(
      file_content, "\n", base::KEEP_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
  struct NameValuePair {
    const std::string name;
    uint64_t value;
  };
  std::vector<NameValuePair> pairs = {{"Pss:", 0},
                                      {"Pss_Anon:", 0},
                                      {"Pss_File:", 0},
                                      {"Pss_Shmem:", 0},
                                      {"Swap:", 0}};
  int index = 0;
  for (const auto& line : lines) {
    if (base::StartsWith(line, pairs[index].name,
                         base::CompareCase::SENSITIVE)) {
      std::vector<std::string> fields = base::SplitString(
          line, " ", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
      if (fields.size() != 3)
        LOG(FATAL) << "bad rollup line: " << line;
      if (!base::StringToUint64(fields[1], &pairs[index].value))
        LOG(FATAL) << "bad integer in rollup line: " << line;
      index++;
      if (index == pairs.size())
        break;
    }
  }
  if (index < pairs.size() && index != 0) {
    // If some fields aren't present, return zeros instead of crashing.
    return;
  }

  stats->rss_sizes[MEM_TOTAL] = pairs[0].value * 1024;
  stats->rss_sizes[MEM_ANON] = pairs[1].value * 1024;
  stats->rss_sizes[MEM_FILE] = pairs[2].value * 1024;
  stats->rss_sizes[MEM_SHMEM] = pairs[3].value * 1024;
  stats->rss_sizes[MEM_SWAP] = pairs[4].value * 1024;
}

void AccumulateProcessGroupStats(const base::FilePath& procfs_path,
                                 const std::vector<ProcessNode*>& processes,
                                 ProcessMemoryStats* stats) {
  for (const auto& process : processes) {
    ProcessMemoryStats process_stats;
    GetMemoryUsage(procfs_path, process->GetPID(), &process_stats);
    // If GetMemoryUsage fails (which will happen if the process has
    // exited), process_stats are all 0 and the accumulation is a no-op.
    for (int i = 0; i < MEM_KINDS_COUNT; i++) {
      stats->rss_sizes[i] += process_stats.rss_sizes[i];
    }
  }
}

}  // namespace chromeos_metrics
