chromium/headless/BUILD.gn

# Copyright 2015 The Chromium Authors
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

import("//build/config/c++/c++.gni")
import("//build/config/chrome_build.gni")
import("//build/config/python.gni")
import("//build/util/lastchange.gni")
import("//build/util/process_version.gni")
import("//headless/headless.gni")
import("//mojo/public/tools/bindings/mojom.gni")
import("//pdf/features.gni")
import("//printing/buildflags/buildflags.gni")
import("//testing/test.gni")
import("//third_party/closure_compiler/compile_js.gni")
import("//third_party/inspector_protocol/inspector_protocol.gni")
import("//tools/grit/grit_rule.gni")
import("//tools/grit/repack.gni")
import("//tools/v8_context_snapshot/v8_context_snapshot.gni")

assert(!is_ios && !is_android)

if (headless_use_policy) {
  assert(headless_use_prefs,
         "'headless_use_policy' requires 'headless_use_prefs'.")
}

if (headless_enable_commands) {
  assert(
      !headless_use_embedded_resources,
      "'headless_enable_commands' is not compatible with 'headless_use_embedded_resources'.")
}

bundle_hyphen_data = (is_linux || is_win) && !headless_use_embedded_resources
should_strip_binary = is_chrome_for_testing && is_linux

if (should_strip_binary) {
  import("//build/linux/strip_binary.gni")
}

# If supported, field trials need to be enabled by --enable-field-trial-config switch.
headless_support_field_trials = headless_use_prefs

# Headless defines config applied to every target below.
config("headless_defines_config") {
  defines = []

  if (headless_enable_commands) {
    defines += [ "HEADLESS_ENABLE_COMMANDS" ]
  }

  if (headless_use_prefs) {
    defines += [ "HEADLESS_USE_PREFS" ]
  }

  if (headless_use_policy) {
    defines += [ "HEADLESS_USE_POLICY" ]
  }

  if (headless_mode_policy_supported) {
    defines += [ "HEADLESS_MODE_POLICY_SUPPORTED" ]
  }

  if (headless_support_field_trials) {
    defines += [ "HEADLESS_SUPPORT_FIELD_TRIALS" ]
  }
}

# For code inside the build component "headless".
config("inside_headless_component") {
  defines = [ "HEADLESS_IMPLEMENTATION" ]
}

group("headless_lib") {
  deps = [ ":headless_non_renderer" ]
}

repack("resource_pack_data") {
  sources = [
    "$root_gen_dir/components/components_resources.pak",
    "$root_gen_dir/content/content_resources.pak",
    "$root_gen_dir/net/net_resources.pak",
    "$root_gen_dir/third_party/blink/public/resources/blink_resources.pak",
    "$root_gen_dir/third_party/blink/public/resources/blink_scaled_resources_100_percent.pak",
    "$root_gen_dir/ui/resources/ui_resources_100_percent.pak",
    "$root_gen_dir/ui/resources/webui_resources.pak",
  ]

  deps = [
    "//components/resources:components_resources",
    "//content:content_resources",
    "//net:net_resources",
    "//third_party/blink/public:resources",
    "//third_party/blink/public:scaled_resources_100_percent",
    "//ui/resources",
  ]

  output = "$root_out_dir/headless_lib_data.pak"
}

repack("resource_pack_strings") {
  sources = [
    "$root_gen_dir/components/strings/components_strings_en-US.pak",
    "$root_gen_dir/third_party/blink/public/strings/blink_strings_en-US.pak",
    "$root_gen_dir/ui/strings/app_locale_settings_en-US.pak",
    "$root_gen_dir/ui/strings/ax_strings_en-US.pak",
    "$root_gen_dir/ui/strings/ui_strings_en-US.pak",
  ]

  sources += [ "${root_gen_dir}/components/strings/components_${branding_path_product}_strings_en-US.pak" ]

  deps = [
    "//components/strings",
    "//third_party/blink/public/strings",
    "//ui/strings",
  ]

  if (!is_fuchsia) {
    sources +=
        [ "$root_gen_dir/content/browser/devtools/devtools_resources.pak" ]
    deps += [ "//content/browser/devtools:devtools_resources" ]
  }

  output = "$root_out_dir/headless_lib_strings.pak"
}

action("embedded_resource_pack_data") {
  # TODO(altimin): Consider zipping file here, it can reduce size up to 80%.
  script = "lib/embed_data.py"

  inputs = [ "$root_out_dir/headless_lib_data.pak" ]

  outputs = [
    "$root_gen_dir/headless/embedded_resource_pack_data.cc",
    "$root_gen_dir/headless/embedded_resource_pack_data.h",
  ]

  args = [
    "--data_file",
    rebase_path("$root_out_dir/headless_lib_data.pak", root_build_dir),
    "--gendir",
    rebase_path("$root_gen_dir", root_build_dir),
    "--header_file",
    "headless/embedded_resource_pack_data.h",
    "--source_file",
    "headless/embedded_resource_pack_data.cc",
    "--namespace",
    "headless",
    "--variable_name",
    "kHeadlessResourcePackData",
  ]

  deps = [ ":resource_pack_data" ]
}

action("embedded_resource_pack_strings") {
  # TODO(altimin): Consider zipping file here, it can reduce size up to 80%.
  script = "lib/embed_data.py"

  inputs = [ "$root_out_dir/headless_lib_strings.pak" ]

  outputs = [
    "$root_gen_dir/headless/embedded_resource_pack_strings.cc",
    "$root_gen_dir/headless/embedded_resource_pack_strings.h",
  ]

  args = [
    "--data_file",
    rebase_path("$root_out_dir/headless_lib_strings.pak", root_build_dir),
    "--gendir",
    rebase_path("$root_gen_dir", root_build_dir),
    "--header_file",
    "headless/embedded_resource_pack_strings.h",
    "--source_file",
    "headless/embedded_resource_pack_strings.cc",
    "--namespace",
    "headless",
    "--variable_name",
    "kHeadlessResourcePackStrings",
  ]

  deps = [ ":resource_pack_strings" ]
}

inspector_protocol_generate("protocol_sources") {
  visibility = [ ":backend_cdp_bindings" ]
  deps = [ "//third_party/blink/public/devtools_protocol:protocol_version" ]
  _blink_protocol_path = rebase_path(
          "$root_gen_dir/third_party/blink/public/devtools_protocol/protocol.json",
          root_build_dir)

  inspector_protocol_dir = "//third_party/inspector_protocol"
  out_dir = target_gen_dir
  config_file = "protocol_config.json"
  config_values = [ "protocol.path=$_blink_protocol_path" ]
  use_embedder_types = true

  inputs = [
    "$root_gen_dir/third_party/blink/public/devtools_protocol/protocol.json",
    config_file,
  ]

  # These are relative to $target_gen_dir.
  outputs = [
    "lib/browser/protocol/browser.cc",
    "lib/browser/protocol/browser.h",
    "lib/browser/protocol/headless_experimental.cc",
    "lib/browser/protocol/headless_experimental.h",
    "lib/browser/protocol/page.cc",
    "lib/browser/protocol/page.h",
    "lib/browser/protocol/target.cc",
    "lib/browser/protocol/target.h",
    "lib/browser/protocol/protocol.h",
  ]
}

static_library("backend_cdp_bindings") {
  deps = [
    ":protocol_sources",
    "//base",
    "//third_party/inspector_protocol:crdtp",
  ]
  sources = get_target_outputs(":protocol_sources")
  visibility = [ ":headless_non_renderer" ]
  configs += [
    "//build/config/compiler:wexit_time_destructors",
    ":headless_defines_config",
    ":inside_headless_component",
  ]
}

# Code that is not needed in a renderer process.
component("headless_non_renderer") {
  sources = [
    "lib/browser/command_line_handler.cc",
    "lib/browser/command_line_handler.h",
    "lib/browser/directory_enumerator.cc",
    "lib/browser/directory_enumerator.h",
    "lib/browser/headless_browser_context_impl.cc",
    "lib/browser/headless_browser_context_impl.h",
    "lib/browser/headless_browser_context_options.cc",
    "lib/browser/headless_browser_context_options.h",
    "lib/browser/headless_browser_impl.cc",
    "lib/browser/headless_browser_impl.h",
    "lib/browser/headless_browser_main_parts.cc",
    "lib/browser/headless_browser_main_parts.h",
    "lib/browser/headless_client_hints_controller_delegate.cc",
    "lib/browser/headless_client_hints_controller_delegate.h",
    "lib/browser/headless_content_browser_client.cc",
    "lib/browser/headless_content_browser_client.h",
    "lib/browser/headless_devtools.cc",
    "lib/browser/headless_devtools.h",
    "lib/browser/headless_devtools_manager_delegate.cc",
    "lib/browser/headless_devtools_manager_delegate.h",
    "lib/browser/headless_permission_manager.cc",
    "lib/browser/headless_permission_manager.h",
    "lib/browser/headless_platform_event_source.cc",
    "lib/browser/headless_platform_event_source.h",
    "lib/browser/headless_request_context_manager.cc",
    "lib/browser/headless_request_context_manager.h",
    "lib/browser/headless_screen.cc",
    "lib/browser/headless_screen.h",
    "lib/browser/headless_web_contents_impl.cc",
    "lib/browser/headless_web_contents_impl.h",
    "lib/browser/headless_window_tree_host.h",
    "lib/browser/protocol/browser_handler.cc",
    "lib/browser/protocol/browser_handler.h",
    "lib/browser/protocol/domain_handler.h",
    "lib/browser/protocol/headless_devtools_session.cc",
    "lib/browser/protocol/headless_devtools_session.h",
    "lib/browser/protocol/headless_handler.cc",
    "lib/browser/protocol/headless_handler.h",
    "lib/browser/protocol/page_handler.cc",
    "lib/browser/protocol/page_handler.h",
    "lib/browser/protocol/target_handler.cc",
    "lib/browser/protocol/target_handler.h",
    "lib/headless_content_client.cc",
    "lib/headless_content_client.h",
    "lib/headless_content_main_delegate.cc",
    "lib/headless_content_main_delegate.h",
    "lib/renderer/allowlist.cc",
    "lib/renderer/allowlist.h",
    "lib/renderer/headless_content_renderer_client.cc",
    "lib/renderer/headless_content_renderer_client.h",
    "lib/utility/headless_content_utility_client.cc",
    "lib/utility/headless_content_utility_client.h",
    "public/headless_browser.h",
    "public/headless_browser_context.h",
    "public/headless_export.h",
    "public/headless_web_contents.h",
    "public/internal/message_dispatcher.h",
    "public/internal/value_conversions.h",
    "public/switches.h",
    "public/util/user_agent.cc",
    "public/util/user_agent.h",
  ]

  configs += [ "//build/config/compiler:wexit_time_destructors" ]

  if (is_mac) {
    sources += [
      "lib/browser/headless_browser_impl_mac.mm",
      "lib/browser/headless_shell_application_mac.h",
      "lib/browser/headless_shell_application_mac.mm",
      "lib/headless_content_main_delegate_mac.mm",
    ]
  }

  if (is_posix) {
    sources += [ "lib/browser/headless_browser_main_parts_posix.cc" ]
  }

  if (use_aura) {
    sources += [
      "lib/browser/headless_browser_impl_aura.cc",
      "lib/browser/headless_focus_client.cc",
      "lib/browser/headless_focus_client.h",
      "lib/browser/headless_window_parenting_client.cc",
      "lib/browser/headless_window_parenting_client.h",
      "lib/browser/headless_window_tree_host.cc",
    ]
  }

  public_deps = [
    "//base",
    "//net",
  ]

  data_deps = []
  data = []
  defines = []

  if (enable_printing) {
    public_deps += [ "//skia" ]
    sources += [
      "lib/renderer/headless_print_render_frame_helper_delegate.cc",
      "lib/renderer/headless_print_render_frame_helper_delegate.h",
    ]
  }

  deps = [
    ":backend_cdp_bindings",
    "//base:base_static",
    "//build:branding_buildflags",
    "//build:chromeos_buildflags",
    "//components/cookie_config",
    "//components/crash/core/common:common",
    "//components/devtools/devtools_pipe",
    "//components/embedder_support",
    "//components/embedder_support:browser_util",
    "//components/embedder_support:embedder_support",
    "//components/embedder_support/origin_trials",
    "//components/headless/clipboard",
    "//components/headless/command_handler:switches",
    "//components/headless/select_file_dialog",
    "//components/keyed_service/content",
    "//components/origin_trials:browser",
    "//components/origin_trials:common",
    "//components/os_crypt/sync",
    "//components/policy:generated",
    "//components/policy/content",
    "//components/policy/core/common:common_constants",
    "//components/pref_registry",
    "//components/prefs",
    "//components/profile_metrics",
    "//components/security_state/core",
    "//components/version_info",
    "//content/public/app",
    "//content/public/browser",
    "//content/public/common",
    "//content/public/renderer",
    "//content/public/utility",
    "//printing/buildflags",
    "//services/cert_verifier/public/mojom",
    "//services/device/public/cpp/geolocation",
    "//services/service_manager/public/cpp",
    "//third_party/inspector_protocol:crdtp",
    "//ui/base",
    "//ui/compositor",
    "//ui/display",
    "//ui/events/devices",
    "//ui/gfx",
    "//url",
  ]

  if (headless_use_policy) {
    sources += [
      "lib/browser/policy/headless_browser_policy_connector.cc",
      "lib/browser/policy/headless_browser_policy_connector.h",
      "lib/browser/policy/headless_policies.cc",
      "lib/browser/policy/headless_policies.h",
      "lib/browser/policy/headless_prefs.cc",
      "lib/browser/policy/headless_prefs.h",
    ]
    deps += [
      "//components/headless/policy",
      "//components/policy/content",
      "//components/policy/core/browser",
      "//components/policy/core/common:policy_path_constants",
    ]
  }

  if (headless_support_field_trials) {
    sources += [
      "lib/browser/headless_field_trials.cc",
      "lib/browser/headless_field_trials.h",
    ]
    deps += [
      "//components/metrics",
      "//components/variations",
      "//components/variations/service",
    ]
  }

  if (enable_printing) {
    deps += [
      "//components/printing/browser",
      "//components/printing/browser/headless",
      "//components/printing/browser/print_to_pdf",
      "//components/printing/common:mojo_interfaces",
      "//components/printing/renderer:renderer",
      "//components/services/print_compositor",
      "//components/services/print_compositor/public/mojom",
      "//printing",
      "//printing/mojom",
    ]
  }

  if (use_ozone) {
    deps += [ "//ui/ozone" ]
  }

  if (headless_use_prefs) {
    deps += [
      "//components/origin_trials:browser",
      "//components/origin_trials:common",
      "//components/user_prefs",
      "//third_party/blink/public/common",
    ]
  }

  if (is_component_build) {
    deps += [
      "//components/crash/core/common",
      "//components/security_state/content",
      "//gin",
      "//third_party/blink/public:blink",
      "//ui/gl",
      "//v8",
    ]

    if (enable_printing) {
      deps += [
        "//components/printing/browser",
        "//components/printing/renderer",
        "//components/services/print_compositor",
        "//components/services/print_compositor/public/mojom",
      ]
    }

    if (headless_use_prefs) {
      deps += [ "//components/os_crypt/sync" ]
    }
  }

  if (!is_fuchsia) {
    deps += [
      "//components/crash/content/browser",
      "//components/crash/core/app",
    ]
    sources += [
      "lib/headless_crash_reporter_client.cc",
      "lib/headless_crash_reporter_client.h",
    ]
  }

  if (is_win) {
    deps += [ "//sandbox" ]
  }

  if (is_linux || is_chromeos) {
    data_deps += [ "//components/crash/core/app:chrome_crashpad_handler" ]
  }

  # Normally set to false (see build/args/headless.gn), but we can optionally
  # use external v8 startup data too.
  if ((!is_win || is_component_build) && v8_use_external_startup_data) {
    public_deps += [ "//v8" ]
    if (use_v8_context_snapshot) {
      data += [ "$root_out_dir/$v8_context_snapshot_filename" ]
      data_deps += [ "//tools/v8_context_snapshot" ]
    }
    if (!use_v8_context_snapshot || include_both_v8_snapshots) {
      data += [ "$root_out_dir/snapshot_blob.bin" ]
    }
  }

  if (is_mac) {
    deps += [ ":mac_helpers" ]
    frameworks = [
      "AppKit.framework",
      "CoreFoundation.framework",
    ]
  } else {
    deps += [ "//ui/aura" ]
  }

  if (headless_use_embedded_resources) {
    defines += [ "HEADLESS_USE_EMBEDDED_RESOURCES" ]
    deps += [
      ":embedded_resource_pack_data",
      ":embedded_resource_pack_strings",
    ]
    sources += [
      "$root_gen_dir/headless/embedded_resource_pack_data.cc",
      "$root_gen_dir/headless/embedded_resource_pack_data.h",
      "$root_gen_dir/headless/embedded_resource_pack_strings.cc",
      "$root_gen_dir/headless/embedded_resource_pack_strings.h",
    ]
  } else {
    deps += [
      ":resource_pack_data",
      ":resource_pack_strings",
    ]
  }

  if (use_dbus) {
    defines += [ "USE_DBUS" ]
    deps += [ "//device/bluetooth" ]
  }

  configs += [ ":inside_headless_component" ]
  configs += [ ":headless_defines_config" ]
}

group("headless_tests") {
  testonly = true

  deps = [
    ":headless_browsertests",
    ":headless_unittests",
  ]
}

test("headless_unittests") {
  sources = [
    "lib/browser/headless_browser_impl_unittest.cc",
    "lib/browser/headless_client_hints_controller_delegate_unittest.cc",
    "lib/renderer/allowlist_unittest.cc",
  ]

  defines = []

  deps = [
    ":headless_non_renderer",
    ":headless_shell_lib",
    "//base/test:run_all_unittests",
    "//base/test:test_support",
    "//components/embedder_support",
    "//components/embedder_support:browser_util",
    "//components/embedder_support/origin_trials",
    "//components/security_state/content",
    "//content/public/app",
    "//content/public/child:child",
    "//content/public/common",
    "//testing/gmock",
    "//testing/gtest",
    "//ui/gfx:test_support",
  ]

  if (is_win) {
    deps += [ "//components/crash/core/app:crash_export_thunks" ]
  }

  if (enable_printing) {
    deps += [
      "//components/printing/browser",
      "//components/printing/browser/headless",
      "//printing",
      "//printing/buildflags",
      "//third_party/blink/public:blink",
    ]
  }

  configs += [ ":headless_defines_config" ]
}

if (is_mac) {
  copy("mac_helpers") {
    sources = [ "$root_out_dir/chrome_crashpad_handler" ]

    deps = [ "//components/crash/core/app:chrome_crashpad_handler" ]

    outputs = [ "$root_out_dir/Helpers/{{source_file_part}}" ]
  }
}

test("headless_browsertests") {
  configs += [
    "//net:net_test_config",
    "//v8:external_startup_data",
  ]
  sources = [
    "test/headless_browser_browsertest.cc",
    "test/headless_browser_context_browsertest.cc",
    "test/headless_browser_test.cc",
    "test/headless_browser_test.h",
    "test/headless_browser_test_utils.cc",
    "test/headless_browser_test_utils.h",
    "test/headless_browser_user_agent_metadata_browsertest.cc",
    "test/headless_client_browsertest.cc",
    "test/headless_devtooled_browsertest.cc",
    "test/headless_devtooled_browsertest.h",
    "test/headless_devtools_client_browsertest.cc",
    "test/headless_origin_trials_browsertest.cc",
    "test/headless_test_launcher.cc",
    "test/headless_web_contents_browsertest.cc",
    "test/test_network_interceptor.cc",
    "test/test_network_interceptor.h",
  ]

  if (enable_printing && enable_pdf) {
    sources += [ "test/headless_printtopdf_browsertest.cc" ]
  }

  if (headless_use_policy) {
    sources += [ "test/headless_policy_browsertest.cc" ]
  }

  if (headless_enable_commands) {
    sources += [ "test/headless_command_browsertest.cc" ]
  }

  # TODO(crbug.com/40222911): Enable on Fuchsia when no longer flakily timeout.
  if (!is_fuchsia) {
    sources += [
      "test/headless_compositor_browsertest.cc",
      "test/headless_protocol_browsertest.cc",
      "test/headless_protocol_browsertest.h",
    ]
  }

  data = [
    "test/data/",
    "test/dom_tree_extraction_expected_nodes.txt",
    "test/dom_tree_extraction_expected_styles.txt",
    "$root_out_dir/headless_lib_data.pak",
    "$root_out_dir/headless_lib_strings.pak",
    "//net/tools/testserver/",
    "//third_party/blink/web_tests/http/tests/inspector-protocol/",
    "//third_party/pywebsocket3/",
  ]

  if (bundle_hyphen_data) {
    data += [ "$root_out_dir/hyphen-data/hyph-en-us.hyb" ]
  }

  data_deps = []

  if (headless_enable_commands) {
    data += [ "$root_out_dir/headless_command_resources.pak" ]
    data_deps += [ "//components/headless/command_handler" ]
  }

  if (is_fuchsia) {
    additional_manifest_fragments = [
      "//build/config/fuchsia/test/fonts.shard.test-cml",

      # TODO(crbug.com/40055105): Investigate removing the requirement
      # for VmexResource.
      "//build/config/fuchsia/test/mark_vmo_executable.shard.test-cml",
      "//build/config/fuchsia/test/network.shard.test-cml",
      "//third_party/fuchsia-sdk/sdk/pkg/vulkan/client.shard.cml",
    ]
  }

  if (is_mac) {
    data_deps += [ ":mac_helpers" ]
  }

  defines = [ "HAS_OUT_OF_PROC_TEST_RUNNER" ]

  if (headless_use_embedded_resources) {
    defines += [ "HEADLESS_USE_EMBEDDED_RESOURCES" ]
  }

  deps = [
    ":headless_shell_lib",
    "//base",
    "//cc:test_support",
    "//components/devtools/simple_devtools_protocol_client",
    "//components/embedder_support",
    "//components/embedder_support:browser_util",
    "//components/embedder_support:embedder_support",
    "//components/headless/select_file_dialog",
    "//components/headless/test",
    "//components/infobars/content",
    "//components/infobars/core",
    "//components/policy/core/browser",
    "//components/security_state/content",
    "//components/version_info",
    "//content/test:test_support",
    "//gin",
    "//net:test_support",
    "//pdf:buildflags",
    "//printing/buildflags",
    "//services/device/public/cpp:test_support",
    "//services/network/public/mojom",
    "//testing/gmock",
    "//testing/gtest",
    "//tools/v8_context_snapshot:buildflags",
    "//ui/base/clipboard",
    "//ui/shell_dialogs",
  ]

  if (is_mac) {
    deps += [ "//services/device/public/cpp:test_support" ]
  }

  if (!is_fuchsia) {
    deps += [ "//third_party/crashpad/crashpad/client" ]
  }

  if (enable_printing) {
    deps += [
      "//components/headless/command_handler:switches",
      "//components/printing/browser",
      "//printing",
    ]

    if (enable_pdf) {
      deps += [ "//pdf" ]
    }
  }

  if (headless_use_policy) {
    deps += [
      "//components/headless/policy",
      "//components/policy/core/common:test_support",
    ]
  }

  if (headless_enable_commands) {
    deps += [
      "//components/headless/command_handler",
      "//components/headless/command_handler:switches",
    ]
  }

  if (bundle_hyphen_data) {
    deps += [ "//third_party/hyphenation-patterns:bundle_hyphen_data" ]
  }

  configs += [ ":headless_defines_config" ]
}

if (is_win) {
  # Headless library with only browser dependencies. This is used when no child
  # dependencies are needed in the target (e.g. chrome:main_dll).
  static_library("headless_shell_browser_lib") {
    sources = [
      "app/headless_shell.cc",
      "public/headless_shell.h",
    ]
    deps = [
      ":headless_non_renderer",
      "//base/version_info",
      "//build:branding_buildflags",
      "//components/crash/core/app:app",
      "//components/crash/core/app:run_as_crashpad_handler",
      "//components/devtools/simple_devtools_protocol_client",
      "//components/embedder_support",
      "//content:sandbox_helper_win",
      "//content/public/app",
      "//content/public/browser",
      "//content/public/common",
      "//net",
      "//printing/buildflags",
      "//sandbox",
    ]
    if (headless_use_policy) {
      deps += [
        "//components/headless/policy",
        "//components/policy/content",
      ]
    }
    if (enable_printing) {
      deps += [ "//components/printing/browser/headless:headless" ]
    }
    if (headless_enable_commands) {
      deps += [ "//components/headless/command_handler" ]
    }

    configs += [
      ":headless_defines_config",
      "//build/config/compiler:wexit_time_destructors",
    ]
  }
}

# Headless library with all included dependencies. Use this library unless you
# have browser/child dependencies restrictions.
static_library("headless_shell_lib") {
  sources = [
    "app/headless_shell.cc",
    "public/headless_shell.h",
  ]
  defines = []

  if (!is_component_build) {
    sources += [
      "lib/utility/headless_content_utility_client.cc",
      "lib/utility/headless_content_utility_client.h",
    ]
  }

  deps = [
    "//base/version_info",
    "//build:branding_buildflags",
    "//components/devtools/simple_devtools_protocol_client",
    "//components/embedder_support",
    "//components/policy/content",
    "//components/security_state/content",
    "//content",
    "//content/public/app",
    "//content/public/browser",
    "//content/public/child:child",
    "//content/public/common",
    "//content/public/utility",
    "//printing/buildflags",
  ]

  public_deps = [
    ":headless_non_renderer",
    "//base",
    "//third_party/inspector_protocol:crdtp",
  ]

  if (!is_component_build) {
    public_deps += [ ":headless_non_renderer" ]
  }

  if (!is_fuchsia) {
    deps += [ "//components/crash/content/browser" ]
  }

  if (enable_printing) {
    deps += [
      "//components/printing/browser",
      "//components/printing/browser/headless:headless",
      "//components/printing/renderer",
      "//components/services/print_compositor",
      "//components/services/print_compositor/public/mojom",
    ]
  }

  if (headless_use_policy) {
    deps += [
      "//components/headless/policy",
      "//components/policy/content",
    ]
  }

  if (headless_enable_commands) {
    deps += [ "//components/headless/command_handler" ]
  }

  if (is_win) {
    defines = [ "HEADLESS_USE_CRASHPAD" ]

    deps += [
      "//components/crash/core/app:run_as_crashpad_handler",
      "//content:sandbox_helper_win",
      "//sandbox",
    ]
  }

  if (is_mac) {
    deps += [ "//components/os_crypt/sync" ]
  }

  if (is_win || (is_posix && !is_mac)) {
    deps += [ "//components/crash/core/app" ]
  }

  configs += [
    ":headless_defines_config",
    "//build/config/compiler:wexit_time_destructors",
  ]
}

action("generate_headless_shell_license_file") {
  script = "//tools/licenses/licenses.py"
  _license_path = "$root_out_dir/LICENSE.headless_shell"
  args = [
    "license_file",
    rebase_path(_license_path, root_build_dir),
    "--gn-target",
    "//headless:headless_shell",
    "--gn-out-dir",
    ".",
  ]
  outputs = [ _license_path ]
}

if (should_strip_binary) {
  strip_binary("strip_headless_shell_binary") {
    binary_input = "$root_out_dir/headless_shell"
    deps = [ ":headless_shell" ]
  }

  group("strip_chrome_for_testing_linux_files") {
    deps = [ ":strip_headless_shell_binary" ]
  }
}

executable("headless_shell") {
  configs -= [ "//build/config/compiler:thinlto_optimize_default" ]
  configs += [ "//build/config/compiler:thinlto_optimize_max" ]

  sources = [ "app/headless_shell_main.cc" ]
  defines = []

  deps = [ ":headless_shell_lib" ]

  if (proprietary_codecs) {
    deps += [ ":generate_headless_shell_license_file" ]
  }

  if (!headless_use_embedded_resources) {
    data = [
      "$root_out_dir/headless_lib_data.pak",
      "$root_out_dir/headless_lib_strings.pak",
    ]
  }

  if (is_win) {
    deps += [
      "//build/win:default_exe_manifest",
      "//content/public/app",
    ]
    configs += [ "//build/config/win:delayloads" ]
  }

  if (is_mac) {
    deps += [ "//sandbox/mac:seatbelt" ]
  }

  if (bundle_hyphen_data) {
    deps += [ "//third_party/hyphenation-patterns:bundle_hyphen_data" ]
  }

  configs += [
    ":headless_defines_config",
    "//build/config/compiler:wexit_time_destructors",
  ]
}