// Copyright 2016 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 <memory>
#include <sstream>
#include <string>
#include <utility>

#include "base/base_switches.h"
#include "base/bind.h"
#include "base/callback.h"
#include "base/command_line.h"
#include "base/environment.h"
#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/json/json_writer.h"
#include "base/location.h"
#include "base/memory/weak_ptr.h"
#include "base/numerics/safe_conversions.h"
#include "base/path_service.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/utf_string_conversions.h"
#include "base/task/post_task.h"
#include "base/task_runner_util.h"
#include "build/build_config.h"
#include "cc/base/switches.h"
#include "components/os_crypt/os_crypt_switches.h"
#include "components/viz/common/switches.h"
#include "content/public/app/content_main.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/common/content_switches.h"
#include "headless/app/headless_shell.h"
#include "headless/app/headless_shell_switches.h"
#include "headless/lib/browser/headless_devtools.h"
#include "headless/public/headless_devtools_target.h"
#include "net/base/filename_util.h"
#include "net/base/host_port_pair.h"
#include "net/base/io_buffer.h"
#include "net/base/ip_address.h"
#include "net/base/net_errors.h"
#include "net/http/http_util.h"
#include "net/socket/ssl_client_socket.h"
#include "net/ssl/ssl_key_logger_impl.h"
#include "services/network/public/cpp/network_switches.h"
#include "ui/base/ui_base_switches.h"
#include "ui/gfx/geometry/size.h"

#if defined(OS_WIN)
#include "components/crash/content/app/crash_switches.h"
#include "components/crash/content/app/run_as_crashpad_handler_win.h"
#include "sandbox/win/src/sandbox_types.h"
#endif

namespace headless {

namespace {

// By default listen to incoming DevTools connections on localhost.
const char kUseLocalHostForDevToolsHttpServer[] = "localhost";
// Default file name for screenshot. Can be overriden by "--screenshot" switch.
const char kDefaultScreenshotFileName[] = "screenshot.png";
// Default file name for pdf. Can be overriden by "--print-to-pdf" switch.
const char kDefaultPDFFileName[] = "output.pdf";

bool ParseWindowSize(const std::string& window_size,
                     gfx::Size* parsed_window_size) {
  int width, height = 0;
  if (sscanf(window_size.c_str(), "%d%*[x,]%d", &width, &height) >= 2 &&
      width >= 0 && height >= 0) {
    parsed_window_size->set_width(width);
    parsed_window_size->set_height(height);
    return true;
  }
  return false;
}

bool ParseFontRenderHinting(
    const std::string& font_render_hinting_string,
    gfx::FontRenderParams::Hinting* font_render_hinting) {
  if (font_render_hinting_string == "max") {
    *font_render_hinting = gfx::FontRenderParams::Hinting::HINTING_MAX;
  } else if (font_render_hinting_string == "full") {
    *font_render_hinting = gfx::FontRenderParams::Hinting::HINTING_FULL;
  } else if (font_render_hinting_string == "medium") {
    *font_render_hinting = gfx::FontRenderParams::Hinting::HINTING_MEDIUM;
  } else if (font_render_hinting_string == "slight") {
    *font_render_hinting = gfx::FontRenderParams::Hinting::HINTING_SLIGHT;
  } else if (font_render_hinting_string == "none") {
    *font_render_hinting = gfx::FontRenderParams::Hinting::HINTING_NONE;
  } else {
    return false;
  }
  return true;
}

#if !defined(CHROME_MULTIPLE_DLL_CHILD)
GURL ConvertArgumentToURL(const base::CommandLine::StringType& arg) {
  GURL url(arg);
  if (url.is_valid() && url.has_scheme())
    return url;

  return net::FilePathToFileURL(
      base::MakeAbsoluteFilePath(base::FilePath(arg)));
}

std::vector<GURL> ConvertArgumentsToURLs(
    const base::CommandLine::StringVector& args) {
  std::vector<GURL> urls;
  urls.reserve(args.size());
  for (auto it = args.rbegin(); it != args.rend(); ++it)
    urls.push_back(ConvertArgumentToURL(*it));
  return urls;
}

// Gets file path into ssl_keylog_file from command line argument or
// environment variable. Command line argument has priority when
// both specified.
base::FilePath GetSSLKeyLogFile(const base::CommandLine* command_line) {
  if (command_line->HasSwitch(switches::kSSLKeyLogFile)) {
    base::FilePath path =
        command_line->GetSwitchValuePath(switches::kSSLKeyLogFile);
    if (!path.empty())
      return path;
    LOG(WARNING) << "ssl-key-log-file argument missing";
  }
  std::unique_ptr<base::Environment> env(base::Environment::Create());
  std::string path_str;
  env->GetVar("SSLKEYLOGFILE", &path_str);
#if defined(OS_WIN)
  // base::Environment returns environment variables in UTF-8 on Windows.
  return base::FilePath(base::UTF8ToUTF16(path_str));
#else
  return base::FilePath(path_str);
#endif
}

#endif

}  // namespace

HeadlessShell::HeadlessShell()
    : browser_(nullptr),
#if !defined(CHROME_MULTIPLE_DLL_CHILD)
      web_contents_(nullptr),
      browser_context_(nullptr),
#endif
      processed_page_ready_(false),
      weak_factory_(this) {
}

HeadlessShell::~HeadlessShell() = default;

#if !defined(CHROME_MULTIPLE_DLL_CHILD)
void HeadlessShell::OnStart(HeadlessBrowser* browser) {
  browser_ = browser;
  devtools_client_ = HeadlessDevToolsClient::Create();
  file_task_runner_ = base::CreateSequencedTaskRunnerWithTraits(
      {base::MayBlock(), base::TaskPriority::BEST_EFFORT});

  HeadlessBrowserContext::Builder context_builder =
      browser_->CreateBrowserContextBuilder();
  // TODO(eseckler): These switches should also affect BrowserContexts that
  // are created via DevTools later.
  base::FilePath ssl_keylog_file =
      GetSSLKeyLogFile(base::CommandLine::ForCurrentProcess());
  if (!ssl_keylog_file.empty()) {
    net::SSLClientSocket::SetSSLKeyLogger(
        std::make_unique<net::SSLKeyLoggerImpl>(ssl_keylog_file));
  }

  if (base::CommandLine::ForCurrentProcess()->HasSwitch(::switches::kLang)) {
    context_builder.SetAcceptLanguage(
        base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
            ::switches::kLang));
  }
  browser_context_ = context_builder.Build();
  browser_->SetDefaultBrowserContext(browser_context_);

  base::CommandLine::StringVector args =
      base::CommandLine::ForCurrentProcess()->GetArgs();

  // If no explicit URL is present, navigate to about:blank, unless we're being
  // driven by debugger.
  if (args.empty() && !base::CommandLine::ForCurrentProcess()->HasSwitch(
                          switches::kRemoteDebuggingPipe)) {
#if defined(OS_WIN)
    args.push_back(L"about:blank");
#else
    args.push_back("about:blank");
#endif
  }

  if (!args.empty()) {
    base::PostTaskAndReplyWithResult(
        file_task_runner_.get(), FROM_HERE,
        base::BindOnce(&ConvertArgumentsToURLs, args),
        base::BindOnce(&HeadlessShell::OnGotURLs, weak_factory_.GetWeakPtr()));
  }
}

void HeadlessShell::OnGotURLs(const std::vector<GURL>& urls) {
  HeadlessWebContents::Builder builder(
      browser_context_->CreateWebContentsBuilder());
  for (const auto& url : urls) {
    HeadlessWebContents* web_contents = builder.SetInitialURL(url).Build();
    if (!web_contents) {
      LOG(ERROR) << "Navigation to " << url << " failed";
      browser_->Shutdown();
      return;
    }
    if (!web_contents_ && !RemoteDebuggingEnabled()) {
      // TODO(jzfeng): Support observing multiple targets.
      url_ = url;
      web_contents_ = web_contents;
      web_contents_->AddObserver(this);
    }
  }
}

void HeadlessShell::Shutdown() {
  if (!web_contents_)
    return;
  if (!RemoteDebuggingEnabled()) {
    devtools_client_->GetEmulation()->GetExperimental()->RemoveObserver(this);
    devtools_client_->GetInspector()->GetExperimental()->RemoveObserver(this);
    devtools_client_->GetPage()->GetExperimental()->RemoveObserver(this);
    if (web_contents_->GetDevToolsTarget()) {
      web_contents_->GetDevToolsTarget()->DetachClient(devtools_client_.get());
    }
  }
  web_contents_->RemoveObserver(this);
  web_contents_ = nullptr;
  browser_context_->Close();
  browser_->Shutdown();
}

void HeadlessShell::DevToolsTargetReady() {
  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
  web_contents_->GetDevToolsTarget()->AttachClient(devtools_client_.get());
  devtools_client_->GetInspector()->GetExperimental()->AddObserver(this);
  devtools_client_->GetPage()->GetExperimental()->AddObserver(this);
  devtools_client_->GetPage()->Enable();

  devtools_client_->GetEmulation()->GetExperimental()->AddObserver(this);

  if (base::CommandLine::ForCurrentProcess()->HasSwitch(
          switches::kDefaultBackgroundColor)) {
    std::string color_hex =
        base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
            switches::kDefaultBackgroundColor);
    uint32_t color;
    CHECK(base::HexStringToUInt(color_hex, &color))
        << "Expected a hex value for --default-background-color=";
    auto rgba = dom::RGBA::Builder()
                    .SetR((color & 0xff000000) >> 24)
                    .SetG((color & 0x00ff0000) >> 16)
                    .SetB((color & 0x0000ff00) >> 8)
                    .SetA(color & 0x000000ff)
                    .Build();
    devtools_client_->GetEmulation()
        ->GetExperimental()
        ->SetDefaultBackgroundColorOverride(
            emulation::SetDefaultBackgroundColorOverrideParams::Builder()
                .SetColor(std::move(rgba))
                .Build());
  }

  if (base::CommandLine::ForCurrentProcess()->HasSwitch(
          switches::kVirtualTimeBudget)) {
    std::string budget_ms_ascii =
        base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
            switches::kVirtualTimeBudget);
    int budget_ms;
    CHECK(base::StringToInt(budget_ms_ascii, &budget_ms))
        << "Expected an integer value for --virtual-time-budget=";
    devtools_client_->GetEmulation()->GetExperimental()->SetVirtualTimePolicy(
        emulation::SetVirtualTimePolicyParams::Builder()
            .SetPolicy(
                emulation::VirtualTimePolicy::PAUSE_IF_NETWORK_FETCHES_PENDING)
            .SetBudget(budget_ms)
            .Build());
  } else {
    // Check if the document had already finished loading by the time we
    // attached.
    PollReadyState();
  }

  if (base::CommandLine::ForCurrentProcess()->HasSwitch(switches::kTimeout)) {
    std::string timeout_ms_ascii =
        base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
            switches::kTimeout);
    int timeout_ms;
    CHECK(base::StringToInt(timeout_ms_ascii, &timeout_ms))
        << "Expected an integer value for --timeout=";
    browser_->BrowserMainThread()->PostDelayedTask(
        FROM_HERE,
        base::BindOnce(&HeadlessShell::FetchTimeout,
                       weak_factory_.GetWeakPtr()),
        base::TimeDelta::FromMilliseconds(timeout_ms));
  }

  // TODO(skyostil): Implement more features to demonstrate the devtools API.
}
#endif  // !defined(CHROME_MULTIPLE_DLL_CHILD)

void HeadlessShell::FetchTimeout() {
  LOG(INFO) << "Timeout.";
  devtools_client_->GetPage()->GetExperimental()->StopLoading(
      page::StopLoadingParams::Builder().Build());
}

void HeadlessShell::OnTargetCrashed(
    const inspector::TargetCrashedParams& params) {
  LOG(ERROR) << "Abnormal renderer termination.";
  // NB this never gets called if remote debugging is enabled.
  Shutdown();
}

void HeadlessShell::PollReadyState() {
  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
  // We need to check the current location in addition to the ready state to
  // be sure the expected page is ready.
  devtools_client_->GetRuntime()->Evaluate(
      "document.readyState + ' ' + document.location.href",
      base::BindOnce(&HeadlessShell::OnReadyState, weak_factory_.GetWeakPtr()));
}

void HeadlessShell::OnReadyState(
    std::unique_ptr<runtime::EvaluateResult> result) {
  if (result->GetResult()->GetValue()->is_string()) {
    std::stringstream stream(result->GetResult()->GetValue()->GetString());
    std::string ready_state;
    std::string url;
    stream >> ready_state;
    stream >> url;

    if (ready_state == "complete" &&
        (url_.spec() == url || url != "about:blank")) {
      OnPageReady();
      return;
    }
  }
}

// emulation::Observer implementation:
void HeadlessShell::OnVirtualTimeBudgetExpired(
    const emulation::VirtualTimeBudgetExpiredParams& params) {
  OnPageReady();
}

// page::Observer implementation:
void HeadlessShell::OnLoadEventFired(const page::LoadEventFiredParams& params) {
  if (base::CommandLine::ForCurrentProcess()->HasSwitch(
          switches::kVirtualTimeBudget)) {
    return;
  }
  OnPageReady();
}

void HeadlessShell::OnPageReady() {
  if (processed_page_ready_)
    return;
  processed_page_ready_ = true;

  if (base::CommandLine::ForCurrentProcess()->HasSwitch(switches::kDumpDom)) {
    FetchDom();
  } else if (base::CommandLine::ForCurrentProcess()->HasSwitch(
                 switches::kRepl)) {
    LOG(INFO)
        << "Type a Javascript expression to evaluate or \"quit\" to exit.";
    InputExpression();
  } else if (base::CommandLine::ForCurrentProcess()->HasSwitch(
                 switches::kScreenshot)) {
    CaptureScreenshot();
  } else if (base::CommandLine::ForCurrentProcess()->HasSwitch(
                 switches::kPrintToPDF)) {
    PrintToPDF();
  } else {
    Shutdown();
  }
}

void HeadlessShell::FetchDom() {
  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
  devtools_client_->GetRuntime()->Evaluate(
      "(document.doctype ? new "
      "XMLSerializer().serializeToString(document.doctype) + '\\n' : '') + "
      "document.documentElement.outerHTML",
      base::BindOnce(&HeadlessShell::OnDomFetched, weak_factory_.GetWeakPtr()));
}

void HeadlessShell::OnDomFetched(
    std::unique_ptr<runtime::EvaluateResult> result) {
  if (result->HasExceptionDetails()) {
    LOG(ERROR) << "Failed to serialize document: "
               << result->GetExceptionDetails()->GetText();
  } else {
    printf("%s\n", result->GetResult()->GetValue()->GetString().c_str());
  }
  Shutdown();
}

void HeadlessShell::InputExpression() {
  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
  // Note that a real system should read user input asynchronously, because
  // otherwise all other browser activity is suspended (e.g., page loading).
  printf(">>> ");
  std::stringstream expression;
  while (true) {
    int c = fgetc(stdin);
    if (c == '\n')
      break;
    if (c == EOF) {
      // If there's no expression, then quit.
      if (expression.str().size() == 0) {
        printf("\n");
        Shutdown();
        return;
      }
      break;
    }
    expression << static_cast<char>(c);
  }
  if (expression.str() == "quit") {
    Shutdown();
    return;
  }
  devtools_client_->GetRuntime()->Evaluate(
      expression.str(), base::BindOnce(&HeadlessShell::OnExpressionResult,
                                       weak_factory_.GetWeakPtr()));
}

void HeadlessShell::OnExpressionResult(
    std::unique_ptr<runtime::EvaluateResult> result) {
  std::unique_ptr<base::Value> value = result->Serialize();
  std::string result_json;
  base::JSONWriter::Write(*value, &result_json);
  printf("%s\n", result_json.c_str());
  InputExpression();
}

void HeadlessShell::CaptureScreenshot() {
  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
  devtools_client_->GetPage()->GetExperimental()->CaptureScreenshot(
      page::CaptureScreenshotParams::Builder().Build(),
      base::BindOnce(&HeadlessShell::OnScreenshotCaptured,
                     weak_factory_.GetWeakPtr()));
}

void HeadlessShell::OnScreenshotCaptured(
    std::unique_ptr<page::CaptureScreenshotResult> result) {
  if (!result) {
    LOG(ERROR) << "Capture screenshot failed";
    Shutdown();
    return;
  }
  WriteFile(switches::kScreenshot, kDefaultScreenshotFileName,
            result->GetData());
}

void HeadlessShell::PrintToPDF() {
  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
  devtools_client_->GetPage()->GetExperimental()->PrintToPDF(
      page::PrintToPDFParams::Builder()
          .SetDisplayHeaderFooter(true)
          .SetPrintBackground(true)
          .SetPreferCSSPageSize(true)
          .Build(),
      base::BindOnce(&HeadlessShell::OnPDFCreated, weak_factory_.GetWeakPtr()));
}

void HeadlessShell::OnPDFCreated(
    std::unique_ptr<page::PrintToPDFResult> result) {
  if (!result) {
    LOG(ERROR) << "Print to PDF failed";
    Shutdown();
    return;
  }
  WriteFile(switches::kPrintToPDF, kDefaultPDFFileName, result->GetData());
}

void HeadlessShell::WriteFile(const std::string& file_path_switch,
                              const std::string& default_file_name,
                              const protocol::Binary& data) {
  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);

  base::FilePath file_name =
      base::CommandLine::ForCurrentProcess()->GetSwitchValuePath(
          file_path_switch);
  if (file_name.empty())
    file_name = base::FilePath().AppendASCII(default_file_name);

  file_proxy_ = std::make_unique<base::FileProxy>(file_task_runner_.get());
  if (!file_proxy_->CreateOrOpen(
          file_name, base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_WRITE,
          base::BindOnce(&HeadlessShell::OnFileOpened,
                         weak_factory_.GetWeakPtr(), data, file_name))) {
    // Operation could not be started.
    OnFileOpened(protocol::Binary(), file_name, base::File::FILE_ERROR_FAILED);
  }
}

void HeadlessShell::OnFileOpened(const protocol::Binary& data,
                                 const base::FilePath file_name,
                                 base::File::Error error_code) {
  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
  if (!file_proxy_->IsValid()) {
    LOG(ERROR) << "Writing to file " << file_name.value()
               << " was unsuccessful, could not open file: "
               << base::File::ErrorToString(error_code);
    return;
  }
  if (!file_proxy_->Write(
          0, reinterpret_cast<const char*>(data.data()), data.size(),
          base::BindOnce(&HeadlessShell::OnFileWritten,
                         weak_factory_.GetWeakPtr(), file_name, data.size()))) {
    // Operation may have completed successfully or failed.
    OnFileWritten(file_name, data.size(), base::File::FILE_ERROR_FAILED, 0);
  }
}

void HeadlessShell::OnFileWritten(const base::FilePath file_name,
                                  const size_t length,
                                  base::File::Error error_code,
                                  int write_result) {
  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
  if (write_result < static_cast<int>(length)) {
    // TODO(eseckler): Support recovering from partial writes.
    LOG(ERROR) << "Writing to file " << file_name.value()
               << " was unsuccessful: "
               << base::File::ErrorToString(error_code);
  } else {
    LOG(INFO) << "Written to file " << file_name.value() << ".";
  }
  if (!file_proxy_->Close(base::BindOnce(&HeadlessShell::OnFileClosed,
                                         weak_factory_.GetWeakPtr()))) {
    // Operation could not be started.
    OnFileClosed(base::File::FILE_ERROR_FAILED);
  }
}

void HeadlessShell::OnFileClosed(base::File::Error error_code) {
  Shutdown();
}

bool HeadlessShell::RemoteDebuggingEnabled() const {
  const base::CommandLine& command_line =
      *base::CommandLine::ForCurrentProcess();
  return (command_line.HasSwitch(switches::kRemoteDebuggingPort) ||
          command_line.HasSwitch(switches::kRemoteDebuggingPipe));
}

bool ValidateCommandLine(const base::CommandLine& command_line) {
  if (!command_line.HasSwitch(switches::kRemoteDebuggingPort) &&
      !command_line.HasSwitch(switches::kRemoteDebuggingPipe)) {
    if (command_line.GetArgs().size() <= 1)
      return true;
    LOG(ERROR) << "Open multiple tabs is only supported when "
               << "remote debugging is enabled.";
    return false;
  }
  if (command_line.HasSwitch(switches::kDefaultBackgroundColor)) {
    LOG(ERROR) << "Setting default background color is disabled "
               << "when remote debugging is enabled.";
    return false;
  }
  if (command_line.HasSwitch(switches::kDumpDom)) {
    LOG(ERROR) << "Dump DOM is disabled when remote debugging is enabled.";
    return false;
  }
  if (command_line.HasSwitch(switches::kPrintToPDF)) {
    LOG(ERROR) << "Print to PDF is disabled "
               << "when remote debugging is enabled.";
    return false;
  }
  if (command_line.HasSwitch(switches::kRepl)) {
    LOG(ERROR) << "Evaluate Javascript is disabled "
               << "when remote debugging is enabled.";
    return false;
  }
  if (command_line.HasSwitch(switches::kScreenshot)) {
    LOG(ERROR) << "Capture screenshot is disabled "
               << "when remote debugging is enabled.";
    return false;
  }
  if (command_line.HasSwitch(switches::kTimeout)) {
    LOG(ERROR) << "Navigation timeout is disabled "
               << "when remote debugging is enabled.";
    return false;
  }
  if (command_line.HasSwitch(switches::kVirtualTimeBudget)) {
    LOG(ERROR) << "Virtual time budget is disabled "
               << "when remote debugging is enabled.";
    return false;
  }
  return true;
}

#if defined(OS_WIN)
int HeadlessShellMain(HINSTANCE instance,
                      sandbox::SandboxInterfaceInfo* sandbox_info) {
  base::CommandLine::Init(0, nullptr);
#if defined(HEADLESS_USE_CRASPHAD)
  std::string process_type =
      base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
          ::switches::kProcessType);
  if (process_type == crash_reporter::switches::kCrashpadHandler) {
    return crash_reporter::RunAsCrashpadHandler(
        *base::CommandLine::ForCurrentProcess(), base::FilePath(),
        ::switches::kProcessType, switches::kUserDataDir);
  }
#endif  // defined(HEADLESS_USE_CRASPHAD)
  RunChildProcessIfNeeded(instance, sandbox_info);
  HeadlessBrowser::Options::Builder builder(0, nullptr);
  builder.SetInstance(instance);
  builder.SetSandboxInfo(std::move(sandbox_info));
#else
int HeadlessShellMain(int argc, const char** argv) {
  base::CommandLine::Init(argc, argv);
  RunChildProcessIfNeeded(argc, argv);
  HeadlessBrowser::Options::Builder builder(argc, argv);
#endif  // defined(OS_WIN)
  HeadlessShell shell;

#if defined(OS_FUCHSIA)
  // TODO(fuchsia): Remove this when GPU accelerated compositing is ready.
  base::CommandLine::ForCurrentProcess()->AppendSwitch(::switches::kDisableGpu);
#endif

  base::CommandLine& command_line(*base::CommandLine::ForCurrentProcess());
  if (!ValidateCommandLine(command_line))
    return EXIT_FAILURE;

// Crash reporting in headless mode is enabled by default in official builds.
#if defined(GOOGLE_CHROME_BUILD)
  builder.SetCrashReporterEnabled(true);
  base::FilePath dumps_path;
  base::PathService::Get(base::DIR_TEMP, &dumps_path);
  builder.SetCrashDumpsDir(dumps_path);
#endif

#if defined(OS_MACOSX)
  command_line.AppendSwitch(os_crypt::switches::kUseMockKeychain);
#endif

  if (command_line.HasSwitch(switches::kDeterministicMode)) {
    command_line.AppendSwitch(switches::kEnableBeginFrameControl);

    // Compositor flags
    command_line.AppendSwitch(::switches::kRunAllCompositorStagesBeforeDraw);
    command_line.AppendSwitch(::switches::kDisableNewContentRenderingTimeout);
    command_line.AppendSwitch(::switches::kEnableSurfaceSynchronization);
    // Ensure that image animations don't resync their animation timestamps when
    // looping back around.
    command_line.AppendSwitch(::switches::kDisableImageAnimationResync);

    // Renderer flags
    command_line.AppendSwitch(cc::switches::kDisableThreadedAnimation);
    command_line.AppendSwitch(::switches::kDisableThreadedScrolling);
    command_line.AppendSwitch(cc::switches::kDisableCheckerImaging);
  }

  if (command_line.HasSwitch(switches::kEnableBeginFrameControl))
    builder.SetEnableBeginFrameControl(true);

  if (command_line.HasSwitch(switches::kEnableCrashReporter))
    builder.SetCrashReporterEnabled(true);
  if (command_line.HasSwitch(switches::kDisableCrashReporter))
    builder.SetCrashReporterEnabled(false);
  if (command_line.HasSwitch(switches::kCrashDumpsDir)) {
    builder.SetCrashDumpsDir(
        command_line.GetSwitchValuePath(switches::kCrashDumpsDir));
  }

  // Enable devtools if requested, by specifying a port (and optional address).
  if (command_line.HasSwitch(::switches::kRemoteDebuggingPort)) {
    std::string address = kUseLocalHostForDevToolsHttpServer;
    if (command_line.HasSwitch(switches::kRemoteDebuggingAddress)) {
      address =
          command_line.GetSwitchValueASCII(switches::kRemoteDebuggingAddress);
      net::IPAddress parsed_address;
      if (!net::ParseURLHostnameToAddress(address, &parsed_address)) {
        LOG(ERROR) << "Invalid devtools server address";
        return EXIT_FAILURE;
      }
    }
    int parsed_port;
    std::string port_str =
        command_line.GetSwitchValueASCII(::switches::kRemoteDebuggingPort);
    if (!base::StringToInt(port_str, &parsed_port) ||
        !base::IsValueInRangeForNumericType<uint16_t>(parsed_port)) {
      LOG(ERROR) << "Invalid devtools server port";
      return EXIT_FAILURE;
    }
    const net::HostPortPair endpoint(address,
                                     base::checked_cast<uint16_t>(parsed_port));
    builder.EnableDevToolsServer(endpoint);
  }
  if (command_line.HasSwitch(::switches::kRemoteDebuggingPipe))
    builder.EnableDevToolsPipe();

  if (command_line.HasSwitch(switches::kProxyServer)) {
    std::string proxy_server =
        command_line.GetSwitchValueASCII(switches::kProxyServer);
    auto proxy_config = std::make_unique<net::ProxyConfig>();
    proxy_config->proxy_rules().ParseFromString(proxy_server);
    if (command_line.HasSwitch(switches::kProxyBypassList)) {
      std::string bypass_list =
          command_line.GetSwitchValueASCII(switches::kProxyBypassList);
      proxy_config->proxy_rules().bypass_rules.ParseFromString(bypass_list);
    }
    builder.SetProxyConfig(std::move(proxy_config));
  }

  if (command_line.HasSwitch(switches::kUseGL)) {
    builder.SetGLImplementation(
        command_line.GetSwitchValueASCII(switches::kUseGL));
  }

  if (command_line.HasSwitch(switches::kUserDataDir)) {
    builder.SetUserDataDir(
        command_line.GetSwitchValuePath(switches::kUserDataDir));
    builder.SetIncognitoMode(false);
  }

  if (command_line.HasSwitch(switches::kWindowSize)) {
    std::string window_size =
        command_line.GetSwitchValueASCII(switches::kWindowSize);
    gfx::Size parsed_window_size;
    if (!ParseWindowSize(window_size, &parsed_window_size)) {
      LOG(ERROR) << "Malformed window size";
      return EXIT_FAILURE;
    }
    builder.SetWindowSize(parsed_window_size);
  }

  if (command_line.HasSwitch(switches::kHideScrollbars)) {
    builder.SetOverrideWebPreferencesCallback(
        base::Bind([](WebPreferences* preferences) {
          preferences->hide_scrollbars = true;
        }));
  }

  if (command_line.HasSwitch(switches::kUserAgent)) {
    std::string ua = command_line.GetSwitchValueASCII(switches::kUserAgent);
    if (net::HttpUtil::IsValidHeaderValue(ua))
      builder.SetUserAgent(ua);
  }

  if (command_line.HasSwitch(switches::kFontRenderHinting)) {
    std::string font_render_hinting_string =
        command_line.GetSwitchValueASCII(switches::kFontRenderHinting);
    gfx::FontRenderParams::Hinting font_render_hinting;
    if (ParseFontRenderHinting(font_render_hinting_string,
                               &font_render_hinting)) {
      builder.SetFontRenderHinting(font_render_hinting);
    } else {
      LOG(ERROR) << "Unknown font-render-hinting parameter value";
      return EXIT_FAILURE;
    }
  }

  if (command_line.HasSwitch(switches::kBlockNewWebContents))
    builder.SetBlockNewWebContents(true);

  return HeadlessBrowserMain(
      builder.Build(),
      base::BindOnce(&HeadlessShell::OnStart, base::Unretained(&shell)));
}

int HeadlessShellMain(const content::ContentMainParams& params) {
#if defined(OS_WIN)
  return HeadlessShellMain(params.instance, params.sandbox_info);
#else
  return HeadlessShellMain(params.argc, params.argv);
#endif
}

}  // namespace headless
