// Copyright (c) 2014 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.

// This class is most definitely NOT re-entrant.

#include "login_manager/browser_job.h"

#include <errno.h>
#include <inttypes.h>
#include <signal.h>
#include <stdint.h>
#include <stdlib.h>
#include <time.h>
#include <unistd.h>

#include <algorithm>
#include <deque>
#include <queue>
#include <string>
#include <vector>

#include <base/files/file_path.h>
#include <base/logging.h>
#include <base/macros.h>
#include <base/strings/string_util.h>
#include <chromeos/switches/chrome_switches.h>

#include "login_manager/file_checker.h"
#include "login_manager/login_metrics.h"
#include "login_manager/system_utils.h"

namespace login_manager {
// static
const char BrowserJobInterface::kLoginManagerFlag[] = "--login-manager";
// static
const char BrowserJobInterface::kLoginUserFlag[] = "--login-user=";
// static
const char BrowserJobInterface::kLoginProfileFlag[] = "--login-profile=";

// static
const char BrowserJob::kFirstExecAfterBootFlag[] = "--first-exec-after-boot";
// static
const uint32_t BrowserJob::kRestartTries = 4;
// static
const time_t BrowserJob::kRestartWindowSeconds = 60;

namespace {

constexpr const char kVmoduleFlag[] = "--vmodule=";

// Chrome only reads a single --vmodule flag. Combine them if we have multiple.
// Example:
//   --arg1 --vmodule=a=1,b=2 --arg2 --arg3 --vmodule=c=3
// becomes
//   --arg1 --arg2 --arg3 --vmodule=a=1,b=2,c=3
// If --vmodule is not present, args are kept intact.
void CombineVModuleArgs(std::vector<std::string>* args) {
  std::string combined_vmodule;
  auto head = args->begin();
  for (const auto arg : *args) {
    if (arg.find(kVmoduleFlag) == 0) {
      // The value of --vmodule is commma separated, so using a comma to join
      // each of them.
      if (!combined_vmodule.empty())
        combined_vmodule += ",";
      combined_vmodule += arg.substr(arraysize(kVmoduleFlag) - 1);
    } else {
      *head++ = arg;
    }
  }
  if (head != args->end()) {
    args->erase(head, args->end());
    args->push_back(kVmoduleFlag + combined_vmodule);
  }
}

}  // namespace

BrowserJob::BrowserJob(
    const std::vector<std::string>& arguments,
    const std::map<std::string, std::string>& environment_variables,
    uid_t desired_uid,
    FileChecker* checker,
    LoginMetrics* metrics,
    SystemUtils* utils)
    : arguments_(arguments),
      file_checker_(checker),
      login_metrics_(metrics),
      system_(utils),
      start_times_(std::deque<time_t>(kRestartTries, 0)),
      removed_login_manager_flag_(false),
      session_already_started_(false),
      subprocess_(desired_uid, system_) {
  // Convert map of env vars into a vector of strings.
  for (const auto& it : environment_variables)
    environment_variables_.push_back(it.first + "=" + it.second);

  // Take over managing the kLoginManagerFlag.
  std::vector<std::string>::iterator to_erase =
      std::remove(arguments_.begin(), arguments_.end(), kLoginManagerFlag);
  if (to_erase != arguments_.end()) {
    arguments_.erase(to_erase, arguments_.end());
    removed_login_manager_flag_ = true;
    login_arguments_.push_back(kLoginManagerFlag);
  }
}

BrowserJob::~BrowserJob() {
}

bool BrowserJob::ShouldRunBrowser() {
  return !file_checker_ || !file_checker_->exists();
}

bool BrowserJob::ShouldStop() const {
  return (system_->time(NULL) - start_times_.front() < kRestartWindowSeconds);
}

void BrowserJob::RecordTime() {
  start_times_.push(system_->time(NULL));
  start_times_.pop();
  DCHECK(start_times_.size() == kRestartTries);
}

bool BrowserJob::RunInBackground() {
  CHECK(login_metrics_);
  bool first_boot = !login_metrics_->HasRecordedChromeExec();
  login_metrics_->RecordStats("chrome-exec");

  extra_one_time_arguments_.clear();
  if (first_boot)
    extra_one_time_arguments_.push_back(kFirstExecAfterBootFlag);

  // Debugging for crbug.com/631640.
  const std::vector<std::string> argv(ExportArgv());
  std::string argstr;
  for (const std::string& s : argv)
    argstr += s + ' ';
  LOG(INFO) << "Running child " << argstr;
  RecordTime();
  return subprocess_.ForkAndExec(argv, environment_variables_);
}

void BrowserJob::KillEverything(int signal, const std::string& message) {
  if (subprocess_.pid() < 0)
    return;

  LOG(INFO) << "Terminating process group: " << message;
  subprocess_.KillEverything(signal);
}

void BrowserJob::Kill(int signal, const std::string& message) {
  if (subprocess_.pid() < 0)
    return;

  LOG(INFO) << "Terminating process: " << message;
  subprocess_.Kill(signal);
}

void BrowserJob::WaitAndAbort(base::TimeDelta timeout) {
  if (subprocess_.pid() < 0)
    return;
  if (!system_->ProcessGroupIsGone(subprocess_.pid(), timeout)) {
    LOG(WARNING) << "Aborting child process " << subprocess_.pid()
                 << "'s process group " << timeout.InSeconds()
                 << " seconds after sending signal";
    std::string message = base::StringPrintf("Browser took more than %" PRId64
                                             " seconds to exit after signal.",
                                             timeout.InSeconds());
    KillEverything(SIGABRT, message);
  } else {
    DLOG(INFO) << "Cleaned up child " << subprocess_.pid();
  }
}

// When user logs in we want to restart chrome in browsing mode with
// user signed in. Hence we remove --login-manager flag and add
// --login-user=|account_id| and --login-profile=|userhash| flags.
void BrowserJob::StartSession(const std::string& account_id,
                              const std::string& userhash) {
  if (!session_already_started_) {
    login_arguments_.clear();
    login_arguments_.push_back(kLoginUserFlag + account_id);
    login_arguments_.push_back(kLoginProfileFlag + userhash);
  }
  session_already_started_ = true;
}

void BrowserJob::StopSession() {
  login_arguments_.clear();
  if (removed_login_manager_flag_) {
    login_arguments_.push_back(kLoginManagerFlag);
    removed_login_manager_flag_ = false;
  }
}

const std::string BrowserJob::GetName() const {
  base::FilePath exec_file(arguments_[0]);
  return exec_file.BaseName().value();
}

void BrowserJob::SetArguments(const std::vector<std::string>& arguments) {
  // Ensure we preserve the program name to be executed, if we have one.
  std::string argv0;
  if (!arguments_.empty())
    argv0 = arguments_[0];

  arguments_ = arguments;

  if (!argv0.empty()) {
    if (arguments_.size())
      arguments_[0] = argv0;
    else
      arguments_.push_back(argv0);
  }
}

void BrowserJob::SetExtraArguments(const std::vector<std::string>& arguments) {
  extra_arguments_ = arguments;
}

void BrowserJob::ClearPid() {
  subprocess_.clear_pid();
}

std::vector<std::string> BrowserJob::ExportArgv() const {
  std::vector<std::string> to_return(arguments_.begin(), arguments_.end());
  to_return.insert(
      to_return.end(), login_arguments_.begin(), login_arguments_.end());
  to_return.insert(
      to_return.end(), extra_arguments_.begin(), extra_arguments_.end());

  if (!extra_one_time_arguments_.empty()) {
    to_return.insert(to_return.end(),
                     extra_one_time_arguments_.begin(),
                     extra_one_time_arguments_.end());
  }
  CombineVModuleArgs(&to_return);
  return to_return;
}

}  // namespace login_manager
