// Copyright (c) 2013 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/test/chromedriver/chrome_launcher.h"

#include <stddef.h>
#include <stdint.h>
#include <algorithm>
#include <utility>
#include <vector>

#include "base/base64.h"
#include "base/bind.h"
#include "base/command_line.h"
#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/files/scoped_file.h"
#include "base/format_macros.h"
#include "base/json/json_reader.h"
#include "base/json/json_writer.h"
#include "base/logging.h"
#include "base/process/kill.h"
#include "base/process/launch.h"
#include "base/process/process.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "base/threading/platform_thread.h"
#include "base/time/time.h"
#include "base/values.h"
#include "build/build_config.h"
#include "chrome/common/chrome_constants.h"
#include "chrome/test/chromedriver/chrome/chrome_android_impl.h"
#include "chrome/test/chromedriver/chrome/chrome_desktop_impl.h"
#include "chrome/test/chromedriver/chrome/chrome_finder.h"
#include "chrome/test/chromedriver/chrome/chrome_remote_impl.h"
#include "chrome/test/chromedriver/chrome/device_manager.h"
#include "chrome/test/chromedriver/chrome/devtools_client_impl.h"
#include "chrome/test/chromedriver/chrome/devtools_event_listener.h"
#include "chrome/test/chromedriver/chrome/devtools_http_client.h"
#include "chrome/test/chromedriver/chrome/embedded_automation_extension.h"
#include "chrome/test/chromedriver/chrome/status.h"
#include "chrome/test/chromedriver/chrome/user_data_dir.h"
#include "chrome/test/chromedriver/chrome/version.h"
#include "chrome/test/chromedriver/chrome/web_view.h"
#include "chrome/test/chromedriver/net/port_server.h"
#include "chrome/test/chromedriver/net/url_request_context_getter.h"
#include "crypto/rsa_private_key.h"
#include "crypto/sha2.h"
#include "third_party/zlib/google/zip.h"

#if defined(OS_POSIX)
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#elif defined(OS_WIN)
#include "chrome/test/chromedriver/keycode_text_conversion.h"
#endif

namespace {

const char* const kCommonSwitches[] = {
    "disable-popup-blocking", "enable-automation", "ignore-certificate-errors",
    "metrics-recording-only",
};

const char* const kDesktopSwitches[] = {
    "disable-hang-monitor",
    "disable-prompt-on-repost",
    "disable-sync",
    "no-first-run",
    "disable-background-networking",
    "disable-web-resources",
    "safebrowsing-disable-auto-update",
    "disable-client-side-phishing-detection",
    "disable-default-apps",
    "enable-logging",
    "log-level=0",
    "password-store=basic",
    "use-mock-keychain",
    "test-type=webdriver",
};

const char* const kAndroidSwitches[] = {
    "disable-fre", "enable-remote-debugging",
};

#if defined(OS_LINUX)
const char kEnableCrashReport[] = "enable-crash-reporter-for-testing";
#endif

Status UnpackAutomationExtension(const base::FilePath& temp_dir,
                                 base::FilePath* automation_extension) {
  std::string decoded_extension;
  if (!base::Base64Decode(kAutomationExtension, &decoded_extension))
    return Status(kUnknownError, "failed to base64decode automation extension");

  base::FilePath extension_zip = temp_dir.AppendASCII("internal.zip");
  int size = static_cast<int>(decoded_extension.length());
  if (base::WriteFile(extension_zip, decoded_extension.c_str(), size)
      != size) {
    return Status(kUnknownError, "failed to write automation extension zip");
  }

  base::FilePath extension_dir = temp_dir.AppendASCII("internal");
  if (!zip::Unzip(extension_zip, extension_dir))
    return Status(kUnknownError, "failed to unzip automation extension");

  *automation_extension = extension_dir;
  return Status(kOk);
}

Status PrepareCommandLine(uint16_t port,
                          const Capabilities& capabilities,
                          base::CommandLine* prepared_command,
                          base::ScopedTempDir* user_data_dir,
                          base::ScopedTempDir* extension_dir,
                          std::vector<std::string>* extension_bg_pages) {
  base::FilePath program = capabilities.binary;
  if (program.empty()) {
    if (!FindChrome(&program))
      return Status(kUnknownError, "cannot find Chrome binary");
  } else if (!base::PathExists(program)) {
    return Status(kUnknownError,
                  base::StringPrintf("no chrome binary at %" PRFilePath,
                                     program.value().c_str()));
  }
  base::CommandLine command(program);
  Switches switches;

  for (auto* common_switch : kCommonSwitches)
    switches.SetUnparsedSwitch(common_switch);
  for (auto* desktop_switch : kDesktopSwitches)
    switches.SetUnparsedSwitch(desktop_switch);
  switches.SetSwitch("remote-debugging-port", base::UintToString(port));
  for (const auto& excluded_switch : capabilities.exclude_switches) {
    switches.RemoveSwitch(excluded_switch);
  }
  switches.SetFromSwitches(capabilities.switches);

  base::FilePath user_data_dir_path;
  if (switches.HasSwitch("user-data-dir")) {
    user_data_dir_path = base::FilePath(
        switches.GetSwitchValueNative("user-data-dir"));
  } else {
    command.AppendArg("data:,");
    if (!user_data_dir->CreateUniqueTempDir())
      return Status(kUnknownError, "cannot create temp dir for user data dir");
    switches.SetSwitch("user-data-dir", user_data_dir->GetPath().value());
    user_data_dir_path = user_data_dir->GetPath();
  }

  Status status = internal::PrepareUserDataDir(user_data_dir_path,
                                               capabilities.prefs.get(),
                                               capabilities.local_state.get());
  if (status.IsError())
    return status;

  if (!extension_dir->CreateUniqueTempDir()) {
    return Status(kUnknownError,
                  "cannot create temp dir for unpacking extensions");
  }
  status = internal::ProcessExtensions(capabilities.extensions,
                                       extension_dir->GetPath(), true,
                                       &switches, extension_bg_pages);
  if (status.IsError())
    return status;
  switches.AppendToCommandLine(&command);
  *prepared_command = command;
  return Status(kOk);
}

Status WaitForDevToolsAndCheckVersion(
    const NetAddress& address,
    URLRequestContextGetter* context_getter,
    const SyncWebSocketFactory& socket_factory,
    const Capabilities* capabilities,
    std::unique_ptr<DevToolsHttpClient>* user_client) {
  std::unique_ptr<DeviceMetrics> device_metrics;
  if (capabilities && capabilities->device_metrics)
    device_metrics.reset(new DeviceMetrics(*capabilities->device_metrics));

  std::unique_ptr<std::set<WebViewInfo::Type>> window_types;
  if (capabilities && !capabilities->window_types.empty()) {
    window_types.reset(
        new std::set<WebViewInfo::Type>(capabilities->window_types));
  } else {
    window_types.reset(new std::set<WebViewInfo::Type>());
  }

  std::unique_ptr<DevToolsHttpClient> client(new DevToolsHttpClient(
      address, context_getter, socket_factory, std::move(device_metrics),
      std::move(window_types), capabilities->page_load_strategy));
  base::TimeTicks deadline =
      base::TimeTicks::Now() + base::TimeDelta::FromSeconds(60);
  Status status = client->Init(deadline - base::TimeTicks::Now());
  if (status.IsError())
    return status;

  const BrowserInfo* browser_info = client->browser_info();
  if (browser_info->is_android &&
      browser_info->android_package != capabilities->android_package) {
    // DevTools from Chrome 30 and earlier did not provide an Android-Package
    // key, so skip the package check for WebView on KitKat and older.
    // TODO(samuong): Make this unconditional once we stop supporting Android
    // KitKat WebView apps.
    if (!(browser_info->browser_name == "webview" &&
          browser_info->major_version <= 30 &&
          browser_info->android_package.empty())) {
      return Status(
          kSessionNotCreatedException,
          base::StringPrintf("please close '%s' and try again",
                             browser_info->android_package.c_str()));
    }
  }

  base::CommandLine* cmd_line = base::CommandLine::ForCurrentProcess();
  if (cmd_line->HasSwitch("disable-build-check")) {
    LOG(WARNING) << "You are using an unsupported command-line switch: "
                    "--disable-build-check. Please don't report bugs that "
                    "cannot be reproduced with this switch removed.";
  } else if (browser_info->build_no < kMinimumSupportedChromeBuildNo) {
    return Status(kUnknownError, "Chrome version must be >= " +
        GetMinimumSupportedChromeVersion());
  }

  while (base::TimeTicks::Now() < deadline) {
    WebViewsInfo views_info;
    client->GetWebViewsInfo(&views_info);
    for (size_t i = 0; i < views_info.GetSize(); ++i) {
      if (views_info.Get(i).type == WebViewInfo::kPage) {
        *user_client = std::move(client);
        return Status(kOk);
      }
    }
    base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(50));
  }
  return Status(kUnknownError, "unable to discover open pages");
}

Status CreateBrowserwideDevToolsClientAndConnect(
    const NetAddress& address,
    const PerfLoggingPrefs& perf_logging_prefs,
    const SyncWebSocketFactory& socket_factory,
    const ScopedVector<DevToolsEventListener>& devtools_event_listeners,
    std::unique_ptr<DevToolsClient>* browser_client) {
  std::unique_ptr<DevToolsClient> client(new DevToolsClientImpl(
      socket_factory, base::StringPrintf("ws://%s/devtools/browser/",
                                         address.ToString().c_str()),
      DevToolsClientImpl::kBrowserwideDevToolsClientId));
  for (ScopedVector<DevToolsEventListener>::const_iterator it =
          devtools_event_listeners.begin();
      it != devtools_event_listeners.end();
      ++it) {
    // Only add listeners that subscribe to the browser-wide |DevToolsClient|.
    // Otherwise, listeners will think this client is associated with a webview,
    // and will send unrecognized commands to it.
    if ((*it)->subscribes_to_browser())
      client->AddListener(*it);
  }
  // Provide the client regardless of whether it connects, so that Chrome always
  // has a valid |devtools_websocket_client_|. If not connected, no listeners
  // will be notified, and client will just return kDisconnected errors if used.
  *browser_client = std::move(client);
  // To avoid unnecessary overhead, only connect if tracing is enabled, since
  // the browser-wide client is currently only used for tracing.
  if (!perf_logging_prefs.trace_categories.empty()) {
    Status status = (*browser_client)->ConnectIfNecessary();
    if (status.IsError())
      return status;
  }
  return Status(kOk);
}

Status LaunchRemoteChromeSession(
    URLRequestContextGetter* context_getter,
    const SyncWebSocketFactory& socket_factory,
    const Capabilities& capabilities,
    ScopedVector<DevToolsEventListener>* devtools_event_listeners,
    std::unique_ptr<Chrome>* chrome) {
  Status status(kOk);
  std::unique_ptr<DevToolsHttpClient> devtools_http_client;
  status = WaitForDevToolsAndCheckVersion(
      capabilities.debugger_address, context_getter, socket_factory,
      &capabilities, &devtools_http_client);
  if (status.IsError()) {
    return Status(kUnknownError, "cannot connect to chrome at " +
                      capabilities.debugger_address.ToString(),
                  status);
  }

  std::unique_ptr<DevToolsClient> devtools_websocket_client;
  status = CreateBrowserwideDevToolsClientAndConnect(
      capabilities.debugger_address, capabilities.perf_logging_prefs,
      socket_factory, *devtools_event_listeners, &devtools_websocket_client);
  if (status.IsError()) {
    LOG(WARNING) << "Browser-wide DevTools client failed to connect: "
                 << status.message();
  }

  chrome->reset(new ChromeRemoteImpl(std::move(devtools_http_client),
                                     std::move(devtools_websocket_client),
                                     *devtools_event_listeners,
                                     capabilities.page_load_strategy));
  return Status(kOk);
}

Status LaunchDesktopChrome(
    URLRequestContextGetter* context_getter,
    uint16_t port,
    std::unique_ptr<PortReservation> port_reservation,
    const SyncWebSocketFactory& socket_factory,
    const Capabilities& capabilities,
    ScopedVector<DevToolsEventListener>* devtools_event_listeners,
    std::unique_ptr<Chrome>* chrome,
    bool w3c_compliant) {
  base::CommandLine command(base::CommandLine::NO_PROGRAM);
  base::ScopedTempDir user_data_dir;
  base::ScopedTempDir extension_dir;
  std::vector<std::string> extension_bg_pages;
  Status status = PrepareCommandLine(port,
                                     capabilities,
                                     &command,
                                     &user_data_dir,
                                     &extension_dir,
                                     &extension_bg_pages);
  if (status.IsError())
    return status;

  base::LaunchOptions options;

#if defined(OS_LINUX)
  // If minidump path is set in the capability, enable minidump for crashes.
  if (!capabilities.minidump_path.empty()) {
    VLOG(0) << "Minidump generation specified. Will save dumps to: "
            << capabilities.minidump_path;

    options.environ["CHROME_HEADLESS"] = 1;
    options.environ["BREAKPAD_DUMP_LOCATION"] = capabilities.minidump_path;

    if (!command.HasSwitch(kEnableCrashReport))
      command.AppendSwitch(kEnableCrashReport);
  }

  // We need to allow new privileges so that chrome's setuid sandbox can run.
  options.allow_new_privs = true;
#endif

#if !defined(OS_WIN)
  if (!capabilities.log_path.empty())
    options.environ["CHROME_LOG_FILE"] = capabilities.log_path;
  if (capabilities.detach)
    options.new_process_group = true;
#endif

#if defined(OS_POSIX)
  base::FileHandleMappingVector no_stderr;
  base::ScopedFD devnull;
  if (!base::CommandLine::ForCurrentProcess()->HasSwitch("verbose")) {
    // Redirect stderr to /dev/null, so that Chrome log spew doesn't confuse
    // users.
    devnull.reset(HANDLE_EINTR(open("/dev/null", O_WRONLY)));
    if (!devnull.is_valid())
      return Status(kUnknownError, "couldn't open /dev/null");
    no_stderr.push_back(std::make_pair(devnull.get(), STDERR_FILENO));
    options.fds_to_remap = &no_stderr;
  }
#elif defined(OS_WIN)
  if (!SwitchToUSKeyboardLayout())
    VLOG(0) << "Cannot switch to US keyboard layout - some keys may be "
        "interpreted incorrectly";
#endif

#if defined(OS_WIN)
  std::string command_string = base::WideToUTF8(command.GetCommandLineString());
#else
  std::string command_string = command.GetCommandLineString();
#endif
  VLOG(0) << "Launching chrome: " << command_string;
  base::Process process = base::LaunchProcess(command, options);
  if (!process.IsValid())
    return Status(kUnknownError, "chrome failed to start");

  std::unique_ptr<DevToolsHttpClient> devtools_http_client;
  status = WaitForDevToolsAndCheckVersion(
      NetAddress(port), context_getter, socket_factory, &capabilities,
      &devtools_http_client);

  if (status.IsError()) {
    int exit_code;
    base::TerminationStatus chrome_status =
        base::GetTerminationStatus(process.Handle(), &exit_code);
    if (chrome_status != base::TERMINATION_STATUS_STILL_RUNNING) {
      std::string termination_reason;
      switch (chrome_status) {
        case base::TERMINATION_STATUS_NORMAL_TERMINATION:
          termination_reason = "exited normally";
          break;
        case base::TERMINATION_STATUS_ABNORMAL_TERMINATION:
          termination_reason = "exited abnormally";
          break;
        case base::TERMINATION_STATUS_PROCESS_WAS_KILLED:
#if defined(OS_CHROMEOS)
        case base::TERMINATION_STATUS_PROCESS_WAS_KILLED_BY_OOM:
#endif
          termination_reason = "was killed";
          break;
        case base::TERMINATION_STATUS_PROCESS_CRASHED:
          termination_reason = "crashed";
          break;
        case base::TERMINATION_STATUS_LAUNCH_FAILED:
          termination_reason = "failed to launch";
          break;
        default:
          termination_reason = "unknown";
          break;
      }
      return Status(kUnknownError,
                    "Chrome failed to start: " + termination_reason);
    }
    if (!process.Terminate(0, true)) {
      int exit_code;
      if (base::GetTerminationStatus(process.Handle(), &exit_code) ==
          base::TERMINATION_STATUS_STILL_RUNNING)
        return Status(kUnknownError, "cannot kill Chrome", status);
    }
    return status;
  }

  std::unique_ptr<DevToolsClient> devtools_websocket_client;
  status = CreateBrowserwideDevToolsClientAndConnect(
      NetAddress(port), capabilities.perf_logging_prefs, socket_factory,
      *devtools_event_listeners, &devtools_websocket_client);
  if (status.IsError()) {
    LOG(WARNING) << "Browser-wide DevTools client failed to connect: "
                 << status.message();
  }

  std::unique_ptr<ChromeDesktopImpl> chrome_desktop(
      new ChromeDesktopImpl(std::move(devtools_http_client),
                            std::move(devtools_websocket_client),
                            *devtools_event_listeners,
                            std::move(port_reservation),
                            capabilities.page_load_strategy,
                            std::move(process),
                            command,
                            &user_data_dir,
                            &extension_dir,
                            capabilities.network_emulation_enabled));
  for (size_t i = 0; i < extension_bg_pages.size(); ++i) {
    VLOG(0) << "Waiting for extension bg page load: " << extension_bg_pages[i];
    std::unique_ptr<WebView> web_view;
    Status status = chrome_desktop->WaitForPageToLoad(
        extension_bg_pages[i], base::TimeDelta::FromSeconds(10),
        &web_view, w3c_compliant);
    if (status.IsError()) {
      return Status(kUnknownError,
                    "failed to wait for extension background page to load: " +
                        extension_bg_pages[i],
                    status);
    }
  }
  *chrome = std::move(chrome_desktop);
  return Status(kOk);
}

Status LaunchAndroidChrome(
    URLRequestContextGetter* context_getter,
    uint16_t port,
    std::unique_ptr<PortReservation> port_reservation,
    const SyncWebSocketFactory& socket_factory,
    const Capabilities& capabilities,
    ScopedVector<DevToolsEventListener>* devtools_event_listeners,
    DeviceManager* device_manager,
    std::unique_ptr<Chrome>* chrome) {
  Status status(kOk);
  std::unique_ptr<Device> device;
  if (capabilities.android_device_serial.empty()) {
    status = device_manager->AcquireDevice(&device);
  } else {
    status = device_manager->AcquireSpecificDevice(
        capabilities.android_device_serial, &device);
  }
  if (status.IsError())
    return status;

  Switches switches(capabilities.switches);
  for (auto* common_switch : kCommonSwitches)
    switches.SetUnparsedSwitch(common_switch);
  for (auto* android_switch : kAndroidSwitches)
    switches.SetUnparsedSwitch(android_switch);
  for (auto excluded_switch : capabilities.exclude_switches)
    switches.RemoveSwitch(excluded_switch);
  status = device->SetUp(capabilities.android_package,
                         capabilities.android_activity,
                         capabilities.android_process,
                         switches.ToString(),
                         capabilities.android_use_running_app,
                         port);
  if (status.IsError()) {
    device->TearDown();
    return status;
  }

  std::unique_ptr<DevToolsHttpClient> devtools_http_client;
  status = WaitForDevToolsAndCheckVersion(NetAddress(port),
                                          context_getter,
                                          socket_factory,
                                          &capabilities,
                                          &devtools_http_client);
  if (status.IsError()) {
    device->TearDown();
    return status;
  }

  std::unique_ptr<DevToolsClient> devtools_websocket_client;
  status = CreateBrowserwideDevToolsClientAndConnect(
      NetAddress(port), capabilities.perf_logging_prefs, socket_factory,
      *devtools_event_listeners, &devtools_websocket_client);
  if (status.IsError()) {
    LOG(WARNING) << "Browser-wide DevTools client failed to connect: "
                 << status.message();
  }

  chrome->reset(new ChromeAndroidImpl(std::move(devtools_http_client),
                                      std::move(devtools_websocket_client),
                                      *devtools_event_listeners,
                                      std::move(port_reservation),
                                      capabilities.page_load_strategy,
                                      std::move(device)));
  return Status(kOk);
}

}  // namespace

Status LaunchChrome(
    URLRequestContextGetter* context_getter,
    const SyncWebSocketFactory& socket_factory,
    DeviceManager* device_manager,
    PortServer* port_server,
    PortManager* port_manager,
    const Capabilities& capabilities,
    ScopedVector<DevToolsEventListener>* devtools_event_listeners,
    std::unique_ptr<Chrome>* chrome,
    bool w3c_compliant) {
  if (capabilities.IsRemoteBrowser()) {
    return LaunchRemoteChromeSession(
        context_getter, socket_factory,
        capabilities, devtools_event_listeners, chrome);
  }

  uint16_t port = 0;
  std::unique_ptr<PortReservation> port_reservation;
  Status port_status(kOk);

  if (capabilities.IsAndroid()) {
    if (port_server)
      port_status = port_server->ReservePort(&port, &port_reservation);
    else
      port_status = port_manager->ReservePortFromPool(&port, &port_reservation);
    if (port_status.IsError())
      return Status(kUnknownError, "cannot reserve port for Chrome",
                    port_status);
    return LaunchAndroidChrome(
        context_getter, port, std::move(port_reservation), socket_factory,
        capabilities, devtools_event_listeners, device_manager, chrome);
  } else {
    if (port_server)
      port_status = port_server->ReservePort(&port, &port_reservation);
    else
      port_status = port_manager->ReservePort(&port, &port_reservation);
    if (port_status.IsError())
      return Status(kUnknownError, "cannot reserve port for Chrome",
                    port_status);
    return LaunchDesktopChrome(context_getter, port,
                               std::move(port_reservation), socket_factory,
                               capabilities, devtools_event_listeners, chrome,
                               w3c_compliant);
  }
}

namespace internal {

void ConvertHexadecimalToIDAlphabet(std::string* id) {
  for (size_t i = 0; i < id->size(); ++i) {
    int val;
    if (base::HexStringToInt(base::StringPiece(id->begin() + i,
                                               id->begin() + i + 1),
                             &val)) {
      (*id)[i] = val + 'a';
    } else {
      (*id)[i] = 'a';
    }
  }
}

std::string GenerateExtensionId(const std::string& input) {
  uint8_t hash[16];
  crypto::SHA256HashString(input, hash, sizeof(hash));
  std::string output = base::ToLowerASCII(base::HexEncode(hash, sizeof(hash)));
  ConvertHexadecimalToIDAlphabet(&output);
  return output;
}

Status GetExtensionBackgroundPage(const base::DictionaryValue* manifest,
                                  const std::string& id,
                                  std::string* bg_page) {
  std::string bg_page_name;
  bool persistent = true;
  manifest->GetBoolean("background.persistent", &persistent);
  const base::Value* unused_value;
  if (manifest->Get("background.scripts", &unused_value))
    bg_page_name = "_generated_background_page.html";
  manifest->GetString("background.page", &bg_page_name);
  manifest->GetString("background_page", &bg_page_name);
  if (bg_page_name.empty() || !persistent)
    return Status(kOk);
  *bg_page = "chrome-extension://" + id + "/" + bg_page_name;
  return Status(kOk);
}

Status ProcessExtension(const std::string& extension,
                        const base::FilePath& temp_dir,
                        base::FilePath* path,
                        std::string* bg_page) {
  // Decodes extension string.
  // Some WebDriver client base64 encoders follow RFC 1521, which require that
  // 'encoded lines be no more than 76 characters long'. Just remove any
  // newlines.
  std::string extension_base64;
  base::RemoveChars(extension, "\n", &extension_base64);
  std::string decoded_extension;
  if (!base::Base64Decode(extension_base64, &decoded_extension))
    return Status(kUnknownError, "cannot base64 decode");

  // If the file is a crx file, extract the extension's ID from its public key.
  // Otherwise generate a random public key and use its derived extension ID.
  std::string public_key;
  std::string magic_header = decoded_extension.substr(0, 4);
  if (magic_header.size() != 4)
    return Status(kUnknownError, "cannot extract magic number");

  const bool is_crx_file = magic_header == "Cr24";

  if (is_crx_file) {
    // Assume a CRX v2 file - see https://developer.chrome.com/extensions/crx.
    std::string key_len_str = decoded_extension.substr(8, 4);
    if (key_len_str.size() != 4)
      return Status(kUnknownError, "cannot extract public key length");
    uint32_t key_len = *reinterpret_cast<const uint32_t*>(key_len_str.c_str());
    public_key = decoded_extension.substr(16, key_len);
    if (key_len != public_key.size())
      return Status(kUnknownError, "invalid public key length");
  } else {
    // Not a CRX file. Generate RSA keypair to get a valid extension id.
    std::unique_ptr<crypto::RSAPrivateKey> key_pair(
        crypto::RSAPrivateKey::Create(2048));
    if (!key_pair)
      return Status(kUnknownError, "cannot generate RSA key pair");
    std::vector<uint8_t> public_key_vector;
    if (!key_pair->ExportPublicKey(&public_key_vector))
      return Status(kUnknownError, "cannot extract public key");
    public_key =
        std::string(reinterpret_cast<char*>(&public_key_vector.front()),
                    public_key_vector.size());
  }
  std::string public_key_base64;
  base::Base64Encode(public_key, &public_key_base64);
  std::string id = GenerateExtensionId(public_key);

  // Unzip the crx file.
  base::ScopedTempDir temp_crx_dir;
  if (!temp_crx_dir.CreateUniqueTempDir())
    return Status(kUnknownError, "cannot create temp dir");
  base::FilePath extension_crx = temp_crx_dir.GetPath().AppendASCII("temp.crx");
  int size = static_cast<int>(decoded_extension.length());
  if (base::WriteFile(extension_crx, decoded_extension.c_str(), size) !=
      size) {
    return Status(kUnknownError, "cannot write file");
  }
  base::FilePath extension_dir = temp_dir.AppendASCII("extension_" + id);
  if (!zip::Unzip(extension_crx, extension_dir))
    return Status(kUnknownError, "cannot unzip");

  // Parse the manifest and set the 'key' if not already present.
  base::FilePath manifest_path(extension_dir.AppendASCII("manifest.json"));
  std::string manifest_data;
  if (!base::ReadFileToString(manifest_path, &manifest_data))
    return Status(kUnknownError, "cannot read manifest");
  std::unique_ptr<base::Value> manifest_value =
      base::JSONReader::Read(manifest_data);
  base::DictionaryValue* manifest;
  if (!manifest_value || !manifest_value->GetAsDictionary(&manifest))
    return Status(kUnknownError, "invalid manifest");

  std::string manifest_key_base64;
  if (manifest->GetString("key", &manifest_key_base64)) {
    // If there is a key in both the header and the manifest, use the key in the
    // manifest. This allows chromedriver users users who generate dummy crxs
    // to set the manifest key and have a consistent ID.
    std::string manifest_key;
    if (!base::Base64Decode(manifest_key_base64, &manifest_key))
      return Status(kUnknownError, "'key' in manifest is not base64 encoded");
    std::string manifest_id = GenerateExtensionId(manifest_key);
    if (id != manifest_id) {
      if (is_crx_file) {
        LOG(WARNING)
            << "Public key in crx header is different from key in manifest"
            << std::endl << "key from header:   " << public_key_base64
            << std::endl << "key from manifest: " << manifest_key_base64
            << std::endl << "generated extension id from header key:   " << id
            << std::endl << "generated extension id from manifest key: "
            << manifest_id;
      }
      id = manifest_id;
    }
  } else {
    manifest->SetString("key", public_key_base64);
    base::JSONWriter::Write(*manifest, &manifest_data);
    if (base::WriteFile(
            manifest_path, manifest_data.c_str(), manifest_data.size()) !=
        static_cast<int>(manifest_data.size())) {
      return Status(kUnknownError, "cannot add 'key' to manifest");
    }
  }

  // Get extension's background page URL, if there is one.
  std::string bg_page_tmp;
  Status status = GetExtensionBackgroundPage(manifest, id, &bg_page_tmp);
  if (status.IsError())
    return status;

  *path = extension_dir;
  if (bg_page_tmp.size())
    *bg_page = bg_page_tmp;
  return Status(kOk);
}

void UpdateExtensionSwitch(Switches* switches,
                           const char name[],
                           const base::FilePath::StringType& extension) {
  base::FilePath::StringType value = switches->GetSwitchValueNative(name);
  if (value.length())
    value += FILE_PATH_LITERAL(",");
  value += extension;
  switches->SetSwitch(name, value);
}

Status ProcessExtensions(const std::vector<std::string>& extensions,
                         const base::FilePath& temp_dir,
                         bool include_automation_extension,
                         Switches* switches,
                         std::vector<std::string>* bg_pages) {
  std::vector<std::string> bg_pages_tmp;
  std::vector<base::FilePath::StringType> extension_paths;
  for (size_t i = 0; i < extensions.size(); ++i) {
    base::FilePath path;
    std::string bg_page;
    Status status = ProcessExtension(extensions[i], temp_dir, &path, &bg_page);
    if (status.IsError()) {
      return Status(
          kUnknownError,
          base::StringPrintf("cannot process extension #%" PRIuS, i + 1),
          status);
    }
    extension_paths.push_back(path.value());
    if (bg_page.length())
      bg_pages_tmp.push_back(bg_page);
  }

  if (include_automation_extension) {
    base::FilePath automation_extension;
    Status status = UnpackAutomationExtension(temp_dir, &automation_extension);
    if (status.IsError())
      return status;
    if (switches->HasSwitch("disable-extensions")) {
      UpdateExtensionSwitch(switches, "disable-extensions-except",
                            automation_extension.value());
      // TODO(samuong): Stop using --load-component-extension when ChromeDriver
      // stops supporting Chrome 56. For backwards compatibility, Chrome 57 and
      // 58 interprets --load-component-extension as --load-extension.
      UpdateExtensionSwitch(switches, "load-component-extension",
                            automation_extension.value());
    } else {
#if defined(OS_WIN) || defined(OS_MACOSX)
      // On Chrome 56 for Windows and Mac, a "Disable developer
      // mode extensions" dialog appears for the automation extension. Suppress
      // this by loading it as a component extension.
      UpdateExtensionSwitch(switches, "load-component-extension",
                            automation_extension.value());
#else
      extension_paths.push_back(automation_extension.value());
#endif
    }
  }

  if (extension_paths.size()) {
    base::FilePath::StringType extension_paths_value = base::JoinString(
        extension_paths, base::FilePath::StringType(1, ','));
    UpdateExtensionSwitch(switches, "load-extension", extension_paths_value);
  }
  bg_pages->swap(bg_pages_tmp);
  return Status(kOk);
}

Status WritePrefsFile(
    const std::string& template_string,
    const base::DictionaryValue* custom_prefs,
    const base::FilePath& path) {
  int code;
  std::string error_msg;
  std::unique_ptr<base::Value> template_value =
      base::JSONReader::ReadAndReturnError(template_string, 0, &code,
                                           &error_msg);
  base::DictionaryValue* prefs;
  if (!template_value || !template_value->GetAsDictionary(&prefs)) {
    return Status(kUnknownError,
                  "cannot parse internal JSON template: " + error_msg);
  }

  if (custom_prefs) {
    for (base::DictionaryValue::Iterator it(*custom_prefs); !it.IsAtEnd();
         it.Advance()) {
      prefs->Set(it.key(), it.value().DeepCopy());
    }
  }

  std::string prefs_str;
  base::JSONWriter::Write(*prefs, &prefs_str);
  VLOG(0) << "Populating " << path.BaseName().value()
          << " file: " << PrettyPrintValue(*prefs);
  if (static_cast<int>(prefs_str.length()) != base::WriteFile(
          path, prefs_str.c_str(), prefs_str.length())) {
    return Status(kUnknownError, "failed to write prefs file");
  }
  return Status(kOk);
}

Status PrepareUserDataDir(
    const base::FilePath& user_data_dir,
    const base::DictionaryValue* custom_prefs,
    const base::DictionaryValue* custom_local_state) {
  base::FilePath default_dir =
      user_data_dir.AppendASCII(chrome::kInitialProfile);
  if (!base::CreateDirectory(default_dir))
    return Status(kUnknownError, "cannot create default profile directory");

  std::string preferences;
  base::FilePath preferences_path =
      default_dir.Append(chrome::kPreferencesFilename);

  if (base::PathExists(preferences_path))
    base::ReadFileToString(preferences_path, &preferences);
  else
    preferences = kPreferences;

  Status status =
      WritePrefsFile(preferences,
                     custom_prefs,
                     default_dir.Append(chrome::kPreferencesFilename));
  if (status.IsError())
    return status;

  std::string local_state;
  base::FilePath local_state_path =
      user_data_dir.Append(chrome::kLocalStateFilename);

  if (base::PathExists(local_state_path))
    base::ReadFileToString(local_state_path, &local_state);
  else
    local_state = kLocalState;

  status = WritePrefsFile(local_state,
                          custom_local_state,
                          user_data_dir.Append(chrome::kLocalStateFilename));
  if (status.IsError())
    return status;

  // Write empty "First Run" file, otherwise Chrome will wipe the default
  // profile that was written.
  if (base::WriteFile(
          user_data_dir.Append(chrome::kFirstRunSentinel), "", 0) != 0) {
    return Status(kUnknownError, "failed to write first run file");
  }
  return Status(kOk);
}

}  // namespace internal
