// Copyright (c) 2012 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/browser/extensions/api/messaging/native_process_launcher.h"

#include <windows.h>

#include "base/command_line.h"
#include "base/logging.h"
#include "base/process/kill.h"
#include "base/process/launch.h"
#include "base/strings/string16.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "base/win/registry.h"
#include "base/win/scoped_handle.h"
#include "crypto/random.h"

namespace extensions {

const wchar_t kNativeMessagingRegistryKey[] =
    L"SOFTWARE\\Google\\Chrome\\NativeMessagingHosts";

namespace {

// Reads path to the native messaging host manifest from the registry. Returns
// empty string if the path isn't found.
string16 GetManifestPath(const string16& native_host_name, DWORD flags) {
  base::win::RegKey key;
  string16 result;

  if (key.Open(HKEY_LOCAL_MACHINE, kNativeMessagingRegistryKey,
               KEY_QUERY_VALUE | flags) != ERROR_SUCCESS ||
      key.OpenKey(native_host_name.c_str(),
                  KEY_QUERY_VALUE | flags) != ERROR_SUCCESS ||
      key.ReadValue(NULL, &result) != ERROR_SUCCESS) {
    return string16();
  }

  return result;
}

}  // namespace

// static
base::FilePath NativeProcessLauncher::FindManifest(
    const std::string& native_host_name,
    std::string* error_message) {
  string16 native_host_name_wide = UTF8ToUTF16(native_host_name);

  // First check 32-bit registry and then try 64-bit.
  string16 manifest_path_str =
      GetManifestPath(native_host_name_wide, KEY_WOW64_32KEY);
  if (manifest_path_str.empty())
    manifest_path_str = GetManifestPath(native_host_name_wide, KEY_WOW64_64KEY);

  if (manifest_path_str.empty()) {
    *error_message = "Native messaging host " + native_host_name +
        " is not registered";
    return base::FilePath();
  }

  base::FilePath manifest_path(manifest_path_str);
  if (!manifest_path.IsAbsolute()) {
    *error_message = "Path to native messaging host manifest must be absolute.";
    return base::FilePath();
  }

  return manifest_path;
}

// static
bool NativeProcessLauncher::LaunchNativeProcess(
    const CommandLine& command_line,
    base::ProcessHandle* process_handle,
    base::PlatformFile* read_file,
    base::PlatformFile* write_file) {
  // Timeout for the IO pipes.
  const DWORD kTimeoutMs = 5000;

  // Windows will use default buffer size when 0 is passed to
  // CreateNamedPipeW().
  const DWORD kBufferSize = 0;

  if (!command_line.GetProgram().IsAbsolute()) {
    LOG(ERROR) << "Native Messaging host path must be absolute.";
    return false;
  }

  uint64 pipe_name_token;
  crypto::RandBytes(&pipe_name_token, sizeof(pipe_name_token));
  string16 out_pipe_name = base::StringPrintf(
      L"\\\\.\\pipe\\chrome.nativeMessaging.out.%llx", pipe_name_token);
  string16 in_pipe_name = base::StringPrintf(
      L"\\\\.\\pipe\\chrome.nativeMessaging.in.%llx", pipe_name_token);

  // Create the pipes to read and write from.
  base::win::ScopedHandle stdout_pipe(
      CreateNamedPipeW(out_pipe_name.c_str(),
                       PIPE_ACCESS_INBOUND | FILE_FLAG_OVERLAPPED |
                           FILE_FLAG_FIRST_PIPE_INSTANCE,
                       PIPE_TYPE_BYTE, 1, kBufferSize, kBufferSize,
                       kTimeoutMs, NULL));
  if (!stdout_pipe.IsValid()) {
    LOG(ERROR) << "Failed to create pipe " << out_pipe_name;
    return false;
  }

  base::win::ScopedHandle stdin_pipe(
      CreateNamedPipeW(in_pipe_name.c_str(),
                       PIPE_ACCESS_OUTBOUND | FILE_FLAG_OVERLAPPED |
                           FILE_FLAG_FIRST_PIPE_INSTANCE,
                       PIPE_TYPE_BYTE, 1, kBufferSize, kBufferSize,
                       kTimeoutMs, NULL));
  if (!stdin_pipe.IsValid()) {
    LOG(ERROR) << "Failed to create pipe " << in_pipe_name;
    return false;
  }

  DWORD comspec_length = ::GetEnvironmentVariable(L"COMSPEC", NULL, 0);
  if (comspec_length == 0) {
    LOG(ERROR) << "COMSPEC is not set";
    return false;
  }
  scoped_ptr<wchar_t[]> comspec(new wchar_t[comspec_length]);
  ::GetEnvironmentVariable(L"COMSPEC", comspec.get(), comspec_length);

  string16 command_line_string = command_line.GetCommandLineString();

  string16 command = base::StringPrintf(
      L"%ls /c %ls < %ls > %ls",
      comspec.get(), command_line_string.c_str(),
      in_pipe_name.c_str(), out_pipe_name.c_str());

  base::LaunchOptions options;
  options.start_hidden = true;
  base::win::ScopedHandle cmd_handle;
  if (!base::LaunchProcess(command.c_str(), options, &cmd_handle)) {
    LOG(ERROR) << "Error launching process "
               << command_line.GetProgram().MaybeAsASCII();
    return false;
  }

  bool stdout_connected = ConnectNamedPipe(stdout_pipe.Get(), NULL) ?
      TRUE : GetLastError() == ERROR_PIPE_CONNECTED;
  bool stdin_connected = ConnectNamedPipe(stdin_pipe.Get(), NULL) ?
      TRUE : GetLastError() == ERROR_PIPE_CONNECTED;
  if (!stdout_connected || !stdin_connected) {
    base::KillProcess(cmd_handle.Get(), 0, false);
    LOG(ERROR) << "Failed to connect IO pipes when starting "
               << command_line.GetProgram().MaybeAsASCII();
    return false;
  }

  *process_handle = cmd_handle.Take();
  *read_file = stdout_pipe.Take();
  *write_file = stdin_pipe.Take();

  return true;
}

}  // namespace extensions
