// 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 "chrome/app/chrome_watcher_command_line_win.h"

#include <stdint.h>

#include <string>

#include "base/command_line.h"
#include "base/files/file_path.h"
#include "base/logging.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/stringprintf.h"
#include "base/win/win_util.h"
#include "chrome/common/chrome_switches.h"
#include "components/startup_metric_utils/common/pre_read_field_trial_utils_win.h"
#include "content/public/common/content_switches.h"

namespace {

const char kMainThreadIdSwitch[] = "main-thread-id";
const char kOnIninitializedEventHandleSwitch[] = "on-initialized-event-handle";
const char kParentHandleSwitch[] = "parent-handle";

void AppendHandleSwitch(const std::string& switch_name,
                        HANDLE handle,
                        base::CommandLine* command_line) {
  command_line->AppendSwitchASCII(
      switch_name, base::UintToString(base::win::HandleToUint32(handle)));
}

uint32_t ReadUintSwitch(const base::CommandLine& command_line,
                            const std::string& switch_name) {
  std::string switch_string = command_line.GetSwitchValueASCII(switch_name);
  unsigned int switch_uint = 0;
  if (switch_string.empty() ||
      !base::StringToUint(switch_string, &switch_uint)) {
    DLOG(ERROR) << "Missing or invalid " << switch_name << " argument.";
    return 0;
  }
  return switch_uint;
}

HANDLE ReadHandleFromSwitch(const base::CommandLine& command_line,
                            const std::string& switch_name) {
  return reinterpret_cast<HANDLE>(ReadUintSwitch(command_line, switch_name));
}

}  // namespace

ChromeWatcherCommandLineGenerator::ChromeWatcherCommandLineGenerator(
    const base::FilePath& chrome_exe) : chrome_exe_(chrome_exe) {
}

ChromeWatcherCommandLineGenerator::~ChromeWatcherCommandLineGenerator() {
}

bool ChromeWatcherCommandLineGenerator::SetOnInitializedEventHandle(
    HANDLE on_initialized_event_handle) {
  return SetHandle(on_initialized_event_handle, &on_initialized_event_handle_);
}

bool ChromeWatcherCommandLineGenerator::SetParentProcessHandle(
    HANDLE parent_process_handle) {
  return SetHandle(parent_process_handle, &parent_process_handle_);
}

// Generates a command-line representing this configuration.
base::CommandLine ChromeWatcherCommandLineGenerator::GenerateCommandLine() {
  // TODO(chrisha): Get rid of the following function and move the
  // implementation here.
  return GenerateChromeWatcherCommandLine(
      chrome_exe_, parent_process_handle_.Get(), ::GetCurrentThreadId(),
      on_initialized_event_handle_.Get());
}

void ChromeWatcherCommandLineGenerator::GetInheritedHandles(
    std::vector<HANDLE>* inherited_handles) const {
  if (on_initialized_event_handle_.IsValid())
    inherited_handles->push_back(on_initialized_event_handle_.Get());
  if (parent_process_handle_.IsValid())
    inherited_handles->push_back(parent_process_handle_.Get());
}

bool ChromeWatcherCommandLineGenerator::SetHandle(
    HANDLE handle, base::win::ScopedHandle* scoped_handle) {
  // Create a duplicate handle that is inheritable.
  HANDLE proc = ::GetCurrentProcess();
  HANDLE new_handle = 0;
  if (!::DuplicateHandle(proc, handle, proc, &new_handle, 0, TRUE,
                         DUPLICATE_SAME_ACCESS)) {
    return false;
  }

  scoped_handle->Set(new_handle);
  return true;
}

ChromeWatcherCommandLine::ChromeWatcherCommandLine(
    HANDLE on_initialized_event_handle,
    HANDLE parent_process_handle,
    DWORD main_thread_id)
    : on_initialized_event_handle_(on_initialized_event_handle),
      parent_process_handle_(parent_process_handle),
      main_thread_id_(main_thread_id) {
}

ChromeWatcherCommandLine::~ChromeWatcherCommandLine() {
  // If any handles were not taken then die violently.
  CHECK(!on_initialized_event_handle_.IsValid() &&
        !parent_process_handle_.IsValid())
      << "Handles left untaken.";
}

scoped_ptr<ChromeWatcherCommandLine>
ChromeWatcherCommandLine::InterpretCommandLine(
    const base::CommandLine& command_line) {
  base::win::ScopedHandle on_initialized_event_handle;
  base::win::ScopedHandle parent_process_handle;
  DWORD main_thread_id = 0;

  // TODO(chrisha): Get rid of the following function and move the
  // implementation here.
  if (!InterpretChromeWatcherCommandLine(
      command_line, &parent_process_handle, &main_thread_id,
      &on_initialized_event_handle))
    return scoped_ptr<ChromeWatcherCommandLine>();

  return scoped_ptr<ChromeWatcherCommandLine>(new ChromeWatcherCommandLine(
      on_initialized_event_handle.Take(), parent_process_handle.Take(),
      main_thread_id));
}

base::win::ScopedHandle
ChromeWatcherCommandLine::TakeOnInitializedEventHandle() {
  return std::move(on_initialized_event_handle_);
}

base::win::ScopedHandle ChromeWatcherCommandLine::TakeParentProcessHandle() {
  return std::move(parent_process_handle_);
}

base::CommandLine GenerateChromeWatcherCommandLine(
    const base::FilePath& chrome_exe,
    HANDLE parent_process,
    DWORD main_thread_id,
    HANDLE on_initialized_event) {
  base::CommandLine command_line(chrome_exe);
  command_line.AppendSwitchASCII(switches::kProcessType,
                                 switches::kWatcherProcess);
  command_line.AppendSwitchASCII(kMainThreadIdSwitch,
                                 base::UintToString(main_thread_id));
  AppendHandleSwitch(kOnIninitializedEventHandleSwitch, on_initialized_event,
                     &command_line);
  AppendHandleSwitch(kParentHandleSwitch, parent_process, &command_line);

#if defined(OS_WIN)
  if (startup_metric_utils::GetPreReadOptions().use_prefetch_argument)
    command_line.AppendArg(switches::kPrefetchArgumentWatcher);
#endif  // defined(OS_WIN)

  return command_line;
}

bool InterpretChromeWatcherCommandLine(
    const base::CommandLine& command_line,
    base::win::ScopedHandle* parent_process,
    DWORD* main_thread_id,
    base::win::ScopedHandle* on_initialized_event) {
  DCHECK(on_initialized_event);
  DCHECK(parent_process);

  // For consistency, always close any existing HANDLEs here.
  on_initialized_event->Close();
  parent_process->Close();

  HANDLE parent_handle =
      ReadHandleFromSwitch(command_line, kParentHandleSwitch);
  HANDLE on_initialized_event_handle =
      ReadHandleFromSwitch(command_line, kOnIninitializedEventHandleSwitch);
  *main_thread_id = ReadUintSwitch(command_line, kMainThreadIdSwitch);

  if (parent_handle) {
    // Initial test of the handle, a zero PID indicates invalid handle, or not
    // a process handle. In this case, parsing fails and we avoid closing the
    // handle.
    DWORD process_pid = ::GetProcessId(parent_handle);
    if (process_pid == 0) {
      DLOG(ERROR) << "Invalid " << kParentHandleSwitch
                  << " argument. Can't get parent PID.";
    } else {
      parent_process->Set(parent_handle);
    }
  }

  if (on_initialized_event_handle) {
    DWORD result = ::WaitForSingleObject(on_initialized_event_handle, 0);
    if (result == WAIT_FAILED) {
      DPLOG(ERROR)
          << "Unexpected error while testing the initialization event.";
    } else if (result != WAIT_TIMEOUT) {
      DLOG(ERROR) << "Unexpected result while testing the initialization event "
                     "with WaitForSingleObject: " << result;
    } else {
      on_initialized_event->Set(on_initialized_event_handle);
    }
  }

  if (!*main_thread_id || !on_initialized_event->IsValid() ||
      !parent_process->IsValid()) {
    // If one was valid and not the other, free the valid one.
    on_initialized_event->Close();
    parent_process->Close();
    *main_thread_id = 0;
    return false;
  }

  return true;
}
