// 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 <stdlib.h>
#include <time.h>
#include <unistd.h>

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

#include <base/basictypes.h>
#include <base/files/file_path.h>
#include <base/logging.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 uint BrowserJob::kRestartTries = 4;
// static
const time_t BrowserJob::kRestartWindowSeconds = 60;

BrowserJob::BrowserJob(const std::vector<std::string>& arguments,
                       const std::map<std::string, std::string>&
                           environment_variables,
                       bool support_multi_profile,
                       uid_t desired_uid,
                       FileChecker* checker,
                       LoginMetrics* metrics,
                       SystemUtils* utils)
      : environment_variables_(environment_variables),
        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),
        support_multi_profile_(support_multi_profile),
        subprocess_(desired_uid, system_) {
  // 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();

  system_->RemoveFile(term_file_);
  if (system_->CreateReadOnlyFileInTempDir(&term_file_)) {
    extra_one_time_arguments_.push_back(
        base::StringPrintf("--%s=%s",
                           chromeos::switches::kTerminationMessageFile,
                           term_file_.value().c_str()));
  }
  if (first_boot)
    extra_one_time_arguments_.push_back(kFirstExecAfterBootFlag);

  LOG(INFO) << "Running child " << GetName() << "...";
  RecordTime();
  return subprocess_.ForkAndExec(ExportArgv(), environment_variables_);
}

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

  LOG(INFO) << "Sending termination message: " << message;
  system_->AtomicFileWrite(term_file_, message);
  subprocess_.KillEverything(signal);
}

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

  LOG(INFO) << "Sending termination message: " << message;
  system_->AtomicFileWrite(term_file_, message);
  subprocess_.Kill(signal);
}

void BrowserJob::WaitAndAbort(base::TimeDelta timeout) {
  if (subprocess_.pid() < 0)
    return;
  if (!system_->ChildIsGone(subprocess_.pid(), timeout)) {
    LOG(WARNING) << "Aborting child process " << subprocess_.pid()
                 << "'s process group " << timeout.InSeconds()
                 << " seconds after sending TERM signal";
    std::string message = base::StringPrintf(
        "Browser took more than %" PRId64 " seconds to exit after TERM.",
        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 and --login-profile flags.
// When supporting multiple simultaneous accounts, |userhash| is passed
// as the value for the latter.  When not, then the magic string "user"
// is passed.
// Chrome requires that we always pass the email (and maybe hash) of the
// first user who started a session, so this method handles that as well.
void BrowserJob::StartSession(const std::string& email,
                              const std::string& userhash) {
  if (!session_already_started_) {
    login_arguments_.clear();
    login_arguments_.push_back(kLoginUserFlag);
    login_arguments_.back().append(email);
    login_arguments_.push_back(kLoginProfileFlag);
    if (support_multi_profile_)
      login_arguments_.back().append(userhash);
    else
      login_arguments_.back().append("user");
  }
  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());
  }
  return to_return;
}

}  // namespace login_manager
