// Copyright (c) 2014 The Chromium 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 "components/browser_watcher/exit_code_watcher_win.h"

#include <windows.h>

#include <utility>

#include "base/logging.h"
#include "base/metrics/sparse_histogram.h"
#include "base/process/kill.h"
#include "base/process/process.h"
#include "base/process/process_handle.h"
#include "base/sequenced_task_runner.h"
#include "base/threading/thread.h"
#include "base/threading/thread_task_runner_handle.h"

namespace browser_watcher {

const char kBrowserExitCodeHistogramName[] = "Stability.BrowserExitCodes";

ExitCodeWatcher::ExitCodeWatcher()
    : background_thread_("ExitCodeWatcherThread"),
      exit_code_(STILL_ACTIVE),
      stop_watching_handle_(CreateEvent(nullptr, TRUE, FALSE, nullptr)) {
  DCHECK(stop_watching_handle_.IsValid());
}

ExitCodeWatcher::~ExitCodeWatcher() {}

bool ExitCodeWatcher::Initialize(base::Process process) {
  if (!process.IsValid()) {
    LOG(ERROR) << "Invalid parent handle, can't get parent process ID.";
    return false;
  }

  DWORD process_pid = process.Pid();
  if (process_pid == 0) {
    LOG(ERROR) << "Invalid parent handle, can't get parent process ID.";
    return false;
  }

  FILETIME creation_time = {};
  FILETIME dummy = {};
  if (!::GetProcessTimes(process.Handle(), &creation_time, &dummy, &dummy,
                         &dummy)) {
    PLOG(ERROR) << "Invalid parent handle, can't get parent process times.";
    return false;
  }

  // Success, take ownership of the process.
  process_ = std::move(process);

  return true;
}

bool ExitCodeWatcher::StartWatching() {
  if (!background_thread_.StartWithOptions(
          base::Thread::Options(base::MessagePumpType::IO, 0))) {
    return false;
  }

  if (!background_thread_.task_runner()->PostTask(
          FROM_HERE, base::BindOnce(&ExitCodeWatcher::WaitForExit,
                                    base::Unretained(this)))) {
    background_thread_.Stop();
    return false;
  }

  return true;
}

void ExitCodeWatcher::StopWatching() {
  if (stop_watching_handle_.IsValid()) {
    SetEvent(stop_watching_handle_.Get());
  }
}

void ExitCodeWatcher::WaitForExit() {
  base::Process::WaitExitStatus wait_result =
      process_.WaitForExitOrEvent(stop_watching_handle_, &exit_code_);
  if (wait_result == base::Process::WaitExitStatus::PROCESS_EXITED) {
    WriteProcessExitCode(exit_code_);
  } else if (wait_result == base::Process::WaitExitStatus::FAILED) {
    LOG(ERROR) << "Failed to wait for process exit or stop event";
  }
}

bool ExitCodeWatcher::WriteProcessExitCode(int exit_code) {
  if (exit_code != STILL_ACTIVE) {
    // Record the exit codes in a sparse stability histogram, as the range of
    // values used to report failures is large.
    base::HistogramBase* exit_code_histogram =
        base::SparseHistogram::FactoryGet(
            kBrowserExitCodeHistogramName,
            base::HistogramBase::kUmaStabilityHistogramFlag);
    exit_code_histogram->Add(exit_code);
    return true;
  }
  return false;
}

}  // namespace browser_watcher
