Commit 9d58d481 authored by Nicolas Ouellet-Payeur's avatar Nicolas Ouellet-Payeur Committed by Commit Bot

[Headless] Split browser/renderer process dependencies

This CL splits //headless:headless into 2 components:
- :headless_renderer
- :headless_non_renderer

:headless_renderer is intended for child processes, and has a smaller
footprint than :headless_non_renderer.

For release builds, this reduces the  size of chrome_child.dll by about
9.7MB.

Bug: 929408
Change-Id: I514a1bb5604f8ab8d6c6031970b5c7a965a8393d
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1570654Reviewed-by: default avatarJohn Budorick <jbudorick@chromium.org>
Reviewed-by: default avatarAndrey Kosyakov <caseq@chromium.org>
Commit-Queue: Nicolas Ouellet-Payeur <nicolaso@chromium.org>
Cr-Commit-Position: refs/heads/master@{#656433}
parent 4947e630
......@@ -219,7 +219,7 @@ group("gn_all") {
":d8_fuchsia",
"//build/fuchsia/fidlgen_js:fidlgen_js_unittests",
"//fuchsia:gn_all",
"//headless",
"//headless:headless_non_renderer",
]
}
......@@ -747,7 +747,7 @@ group("gn_all") {
if (is_linux && use_ozone) {
deps += [
"//headless",
"//headless:headless_non_renderer",
"//headless:headless_tests",
]
}
......
......@@ -24,7 +24,7 @@ config("inside_headless_component") {
group("headless_lib") {
deps = [
":headless",
":headless_non_renderer",
]
}
......@@ -227,7 +227,7 @@ if (headless_fontconfig_utils && !is_fuchsia) {
}
inspector_protocol_generate("protocol_sources") {
visibility = [ "//headless" ]
visibility = [ "//headless:headless_shared_sources" ]
deps = [
"//third_party/blink/renderer/core/inspector:protocol_version",
]
......@@ -262,10 +262,75 @@ inspector_protocol_generate("protocol_sources") {
]
}
jumbo_component("headless") {
# Code needed in both processes. Only exposed through |headless| and
# |headless_non_renderer| components.
jumbo_source_set("headless_shared_sources") {
visibility = [
"//headless:headless_non_renderer",
"//headless:headless",
]
sources = [
"app/headless_shell_switches.cc",
"app/headless_shell_switches.h",
"lib/headless_content_client.cc",
"lib/headless_content_client.h",
"public/headless_browser.cc",
"public/headless_browser.h",
"public/headless_export.h",
"public/internal/headless_devtools_client_impl.h",
"public/internal/message_dispatcher.h",
"public/internal/value_conversions.h",
"public/util/error_reporter.cc",
"public/util/error_reporter.h",
"public/util/user_agent.cc",
"public/util/user_agent.h",
]
sources += generated_devtools_api
sources += get_target_outputs(":protocol_sources")
if (!is_fuchsia) {
sources += [
"lib/headless_crash_reporter_client.cc",
"lib/headless_crash_reporter_client.h",
]
}
deps = [
":gen_devtools_client_api",
":protocol_sources",
"//base:base_static",
"//content/public/common",
"//content/public/common:service_names",
"//ui/base",
"//url",
]
if (!is_fuchsia) {
deps += [ "//components/crash/content/browser" ]
}
if (is_win) {
deps += [ "//components/crash/content/app:crash_export_thunks" ]
}
if (is_linux && !is_chromeos) {
deps += [ "//components/os_crypt" ]
}
configs += [ ":inside_headless_component" ]
}
# Code that is needed in a renderer process.
jumbo_component("headless") {
deps = [
":headless_shared_sources",
]
}
# Code that is not needed in a renderer process.
jumbo_component("headless_non_renderer") {
sources = [
"lib/browser/headless_browser_context_impl.cc",
"lib/browser/headless_browser_context_impl.h",
"lib/browser/headless_browser_context_options.cc",
......@@ -308,35 +373,13 @@ jumbo_component("headless") {
"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",
"public/headless_browser.cc",
"public/headless_browser.h",
"public/headless_browser_context.h",
"public/headless_devtools_channel.h",
"public/headless_devtools_client.h",
"public/headless_devtools_target.h",
"public/headless_export.h",
"public/headless_web_contents.h",
"public/internal/headless_devtools_client_impl.h",
"public/internal/message_dispatcher.h",
"public/internal/value_conversions.h",
"public/util/error_reporter.cc",
"public/util/error_reporter.h",
"public/util/user_agent.cc",
"public/util/user_agent.h",
]
if (!is_fuchsia) {
sources += [
"lib/headless_crash_reporter_client.cc",
"lib/headless_crash_reporter_client.h",
]
}
sources += generated_devtools_api
sources += get_target_outputs(":protocol_sources")
if (use_aura) {
sources += [
"lib/browser/headless_browser_impl_aura.cc",
......@@ -372,8 +415,7 @@ jumbo_component("headless") {
}
deps = [
":gen_devtools_client_api",
":protocol_sources",
":headless_shared_sources",
":version_header",
"//base:base_static",
"//components/cookie_config",
......@@ -389,10 +431,6 @@ jumbo_component("headless") {
"//url",
]
if (is_linux && !is_chromeos) {
deps += [ "//components/os_crypt" ]
}
if (enable_basic_printing) {
deps += [ "//components/printing/browser" ]
}
......@@ -534,7 +572,7 @@ if (!is_component_build) {
# component.
group("headless_renderer") {
deps = [
":headless",
":headless_non_renderer",
]
}
}
......@@ -567,7 +605,7 @@ test("headless_unittests") {
}
deps = [
":headless_renderer",
":headless_shell_lib",
"//base/test:run_all_unittests",
"//base/test:test_support",
"//components/security_state/content",
......@@ -719,7 +757,7 @@ test("headless_browsertests") {
}
deps = [
":headless_renderer",
":headless_shell_lib",
"//base",
"//components/security_state/content",
"//components/services/pdf_compositor/public/cpp:manifest",
......@@ -732,10 +770,7 @@ test("headless_browsertests") {
]
if (!is_fuchsia) {
deps += [
"//components/crash/content/app:test_support",
"//components/crash/content/browser",
]
deps += [ "//components/crash/content/browser" ]
}
if (is_linux) {
......@@ -774,7 +809,7 @@ if (is_win) {
"public/headless_shell.h",
]
deps = [
":headless",
":headless_non_renderer",
"//components/services/pdf_compositor/public/cpp:manifest",
"//components/services/pdf_compositor/public/interfaces",
"//content:sandbox_helper_win",
......@@ -871,6 +906,10 @@ jumbo_static_library("headless_shell_lib") {
"//base",
]
if (!is_component_build) {
public_deps += [ ":headless_non_renderer" ]
}
if (!is_fuchsia) {
deps += [ "//components/crash/content/browser" ]
}
......
......@@ -32,7 +32,7 @@
#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/lib/headless_content_main_delegate.h"
#include "headless/public/headless_devtools_target.h"
#include "net/base/filename_util.h"
#include "net/base/host_port_pair.h"
......@@ -52,6 +52,11 @@
#include "sandbox/win/src/sandbox_types.h"
#endif
#if !defined(CHROME_MULTIPLE_DLL_CHILD)
#include "headless/lib/browser/headless_browser_impl.h"
#include "headless/lib/browser/headless_devtools.h"
#endif
namespace headless {
namespace {
......@@ -137,6 +142,34 @@ base::FilePath GetSSLKeyLogFile(const base::CommandLine* command_line) {
#endif
int RunContentMain(
HeadlessBrowser::Options options,
base::OnceCallback<void(HeadlessBrowser*)> on_browser_start_callback) {
content::ContentMainParams params(nullptr);
#if defined(OS_WIN)
// Sandbox info has to be set and initialized.
CHECK(options.sandbox_info);
params.instance = options.instance;
params.sandbox_info = std::move(options.sandbox_info);
#elif !defined(OS_ANDROID)
params.argc = options.argc;
params.argv = options.argv;
#endif
// TODO(skyostil): Implement custom message pumps.
DCHECK(!options.message_pump);
#if !defined(CHROME_MULTIPLE_DLL_CHILD)
std::unique_ptr<HeadlessBrowserImpl> browser(new HeadlessBrowserImpl(
std::move(on_browser_start_callback), std::move(options)));
HeadlessContentMainDelegate delegate(std::move(browser));
#else
HeadlessContentMainDelegate delegate(std::move(options));
#endif
params.delegate = &delegate;
return content::ContentMain(params);
}
} // namespace
HeadlessShell::HeadlessShell()
......@@ -776,4 +809,50 @@ int HeadlessShellMain(const content::ContentMainParams& params) {
#endif
}
#if defined(OS_WIN)
void RunChildProcessIfNeeded(HINSTANCE instance,
sandbox::SandboxInterfaceInfo* sandbox_info) {
base::CommandLine::Init(0, nullptr);
HeadlessBrowser::Options::Builder builder(0, nullptr);
builder.SetInstance(instance);
builder.SetSandboxInfo(std::move(sandbox_info));
#else
void RunChildProcessIfNeeded(int argc, const char** argv) {
base::CommandLine::Init(argc, argv);
HeadlessBrowser::Options::Builder builder(argc, argv);
#endif // defined(OS_WIN)
const base::CommandLine& command_line(
*base::CommandLine::ForCurrentProcess());
if (!command_line.HasSwitch(::switches::kProcessType))
return;
if (command_line.HasSwitch(switches::kUserAgent)) {
std::string ua = command_line.GetSwitchValueASCII(switches::kUserAgent);
if (net::HttpUtil::IsValidHeaderValue(ua))
builder.SetUserAgent(ua);
}
exit(RunContentMain(builder.Build(),
base::OnceCallback<void(HeadlessBrowser*)>()));
}
int HeadlessBrowserMain(
HeadlessBrowser::Options options,
base::OnceCallback<void(HeadlessBrowser*)> on_browser_start_callback) {
DCHECK(!on_browser_start_callback.is_null());
#if DCHECK_IS_ON()
// The browser can only be initialized once.
static bool browser_was_initialized;
DCHECK(!browser_was_initialized);
browser_was_initialized = true;
// Child processes should not end up here.
DCHECK(!base::CommandLine::ForCurrentProcess()->HasSwitch(
::switches::kProcessType));
#endif
return RunContentMain(std::move(options),
std::move(on_browser_start_callback));
}
} // namespace headless
......@@ -34,36 +34,6 @@
#endif
namespace headless {
namespace {
int RunContentMain(
HeadlessBrowser::Options options,
base::OnceCallback<void(HeadlessBrowser*)> on_browser_start_callback) {
content::ContentMainParams params(nullptr);
#if defined(OS_WIN)
// Sandbox info has to be set and initialized.
CHECK(options.sandbox_info);
params.instance = options.instance;
params.sandbox_info = std::move(options.sandbox_info);
#elif !defined(OS_ANDROID)
params.argc = options.argc;
params.argv = options.argv;
#endif
// TODO(skyostil): Implement custom message pumps.
DCHECK(!options.message_pump);
std::unique_ptr<HeadlessBrowserImpl> browser(new HeadlessBrowserImpl(
std::move(on_browser_start_callback), std::move(options)));
HeadlessContentMainDelegate delegate(std::move(browser));
params.delegate = &delegate;
return content::ContentMain(params);
}
} // namespace
const base::FilePath::CharType kDefaultProfileName[] =
FILE_PATH_LITERAL("Default");
HeadlessBrowserImpl::HeadlessBrowserImpl(
base::OnceCallback<void(HeadlessBrowser*)> on_start_callback,
......@@ -242,50 +212,4 @@ bool HeadlessBrowserImpl::IsAttached() {
return agent_host_->IsAttached();
}
#if defined(OS_WIN)
void RunChildProcessIfNeeded(HINSTANCE instance,
sandbox::SandboxInterfaceInfo* sandbox_info) {
base::CommandLine::Init(0, nullptr);
HeadlessBrowser::Options::Builder builder(0, nullptr);
builder.SetInstance(instance);
builder.SetSandboxInfo(std::move(sandbox_info));
#else
void RunChildProcessIfNeeded(int argc, const char** argv) {
base::CommandLine::Init(argc, argv);
HeadlessBrowser::Options::Builder builder(argc, argv);
#endif // defined(OS_WIN)
const base::CommandLine& command_line(
*base::CommandLine::ForCurrentProcess());
if (!command_line.HasSwitch(::switches::kProcessType))
return;
if (command_line.HasSwitch(switches::kUserAgent)) {
std::string ua = command_line.GetSwitchValueASCII(switches::kUserAgent);
if (net::HttpUtil::IsValidHeaderValue(ua))
builder.SetUserAgent(ua);
}
exit(RunContentMain(builder.Build(),
base::OnceCallback<void(HeadlessBrowser*)>()));
}
int HeadlessBrowserMain(
HeadlessBrowser::Options options,
base::OnceCallback<void(HeadlessBrowser*)> on_browser_start_callback) {
DCHECK(!on_browser_start_callback.is_null());
#if DCHECK_IS_ON()
// The browser can only be initialized once.
static bool browser_was_initialized;
DCHECK(!browser_was_initialized);
browser_was_initialized = true;
// Child processes should not end up here.
DCHECK(!base::CommandLine::ForCurrentProcess()->HasSwitch(
::switches::kProcessType));
#endif
return RunContentMain(std::move(options),
std::move(on_browser_start_callback));
}
} // namespace headless
......@@ -66,6 +66,9 @@ const base::Feature kVirtualTime{"VirtualTime",
base::FEATURE_DISABLED_BY_DEFAULT};
}
const base::FilePath::CharType kDefaultProfileName[] =
FILE_PATH_LITERAL("Default");
namespace {
// Keep in sync with content/common/content_constants_internal.h.
#if !defined(CHROME_MULTIPLE_DLL_CHILD)
......@@ -86,10 +89,20 @@ const char kHeadlessCrashKey[] = "headless";
HeadlessContentMainDelegate::HeadlessContentMainDelegate(
std::unique_ptr<HeadlessBrowserImpl> browser)
: browser_(std::move(browser)),
headless_crash_key_(base::debug::AllocateCrashKeyString(
kHeadlessCrashKey,
base::debug::CrashKeySize::Size32)) {
: browser_(std::move(browser)) {
Init();
}
HeadlessContentMainDelegate::HeadlessContentMainDelegate(
HeadlessBrowser::Options options)
: options_(std::make_unique<HeadlessBrowser::Options>(std::move(options))) {
Init();
}
void HeadlessContentMainDelegate::Init() {
headless_crash_key_ = base::debug::AllocateCrashKeyString(
kHeadlessCrashKey, base::debug::CrashKeySize::Size32);
DCHECK(!g_current_headless_content_main_delegate);
g_current_headless_content_main_delegate = this;
......@@ -109,13 +122,13 @@ bool HeadlessContentMainDelegate::BasicStartupComplete(int* exit_code) {
if (!command_line->HasSwitch(::switches::kHeadless))
command_line->AppendSwitch(::switches::kHeadless);
if (browser_->options()->single_process_mode)
if (options()->single_process_mode)
command_line->AppendSwitch(::switches::kSingleProcess);
if (browser_->options()->disable_sandbox)
if (options()->disable_sandbox)
command_line->AppendSwitch(service_manager::switches::kNoSandbox);
if (!browser_->options()->enable_resource_scheduler)
if (!options()->enable_resource_scheduler)
command_line->AppendSwitch(::switches::kDisableResourceScheduler);
#if defined(USE_OZONE)
......@@ -134,9 +147,9 @@ bool HeadlessContentMainDelegate::BasicStartupComplete(int* exit_code) {
command_line->AppendSwitch(::switches::kDisableGpuCompositing);
}
} else {
if (!browser_->options()->gl_implementation.empty()) {
if (!options()->gl_implementation.empty()) {
command_line->AppendSwitchASCII(::switches::kUseGL,
browser_->options()->gl_implementation);
options()->gl_implementation);
} else {
command_line->AppendSwitch(::switches::kDisableGpu);
}
......@@ -195,8 +208,8 @@ void HeadlessContentMainDelegate::InitLogging(
// In release builds we should log into the user profile directory.
#ifdef NDEBUG
if (!browser_->options()->user_data_dir.empty()) {
log_path = browser_->options()->user_data_dir;
if (!options()->user_data_dir.empty()) {
log_path = options()->user_data_dir;
log_path = log_path.Append(kDefaultProfileName);
base::CreateDirectory(log_path);
log_path = log_path.Append(log_filename);
......@@ -241,12 +254,12 @@ void HeadlessContentMainDelegate::InitCrashReporter(
command_line.GetSwitchValueASCII(::switches::kProcessType);
crash_reporter::SetCrashReporterClient(g_headless_crash_client.Pointer());
g_headless_crash_client.Pointer()->set_crash_dumps_dir(
browser_->options()->crash_dumps_dir);
options()->crash_dumps_dir);
crash_reporter::InitializeCrashKeys();
#if defined(HEADLESS_USE_BREAKPAD)
if (!browser_->options()->enable_crash_reporter) {
if (!options()->enable_crash_reporter) {
DCHECK(!breakpad::IsCrashReporterEnabled());
return;
}
......@@ -353,6 +366,12 @@ HeadlessContentMainDelegate* HeadlessContentMainDelegate::GetInstance() {
return g_current_headless_content_main_delegate;
}
HeadlessBrowser::Options* HeadlessContentMainDelegate::options() {
if (browser_)
return browser_->options();
return options_.get();
}
// static
void HeadlessContentMainDelegate::InitializeResourceBundle() {
base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
......@@ -433,8 +452,8 @@ HeadlessContentMainDelegate::CreateContentRendererClient() {
content::ContentUtilityClient*
HeadlessContentMainDelegate::CreateContentUtilityClient() {
utility_client_ = std::make_unique<HeadlessContentUtilityClient>(
browser_->options()->user_agent);
utility_client_ =
std::make_unique<HeadlessContentUtilityClient>(options()->user_agent);
return utility_client_.get();
}
#endif // !defined(CHROME_MULTIPLE_DLL_BROWSER)
......
......@@ -14,10 +14,13 @@
#include "content/public/app/content_main_delegate.h"
#include "content/public/browser/content_browser_client.h"
#include "content/public/renderer/content_renderer_client.h"
#include "headless/lib/browser/headless_platform_event_source.h"
#include "headless/lib/headless_content_client.h"
#include "headless/public/headless_export.h"
#if !defined(CHROME_MULTIPLE_DLL_CHILD)
#include "headless/lib/browser/headless_platform_event_source.h"
#endif
namespace base {
namespace debug {
struct CrashKeyString;
......@@ -35,6 +38,7 @@ class HEADLESS_EXPORT HeadlessContentMainDelegate
public:
explicit HeadlessContentMainDelegate(
std::unique_ptr<HeadlessBrowserImpl> browser);
explicit HeadlessContentMainDelegate(HeadlessBrowser::Options options);
~HeadlessContentMainDelegate() override;
// content::ContentMainDelegate implementation:
......@@ -61,6 +65,10 @@ class HEADLESS_EXPORT HeadlessContentMainDelegate
private:
friend class HeadlessBrowserTest;
void Init();
HeadlessBrowser::Options* options();
static void InitializeResourceBundle();
static HeadlessContentMainDelegate* GetInstance();
......@@ -71,9 +79,13 @@ class HEADLESS_EXPORT HeadlessContentMainDelegate
std::unique_ptr<content::ContentBrowserClient> browser_client_;
std::unique_ptr<content::ContentUtilityClient> utility_client_;
HeadlessContentClient content_client_;
#if !defined(CHROME_MULTIPLE_DLL_CHILD)
HeadlessPlatformEventSource platform_event_source_;
#endif
std::unique_ptr<HeadlessBrowserImpl> browser_;
std::unique_ptr<HeadlessBrowser::Options> options_;
base::debug::CrashKeyString* headless_crash_key_; // Note: never deallocated.
DISALLOW_COPY_AND_ASSIGN(HeadlessContentMainDelegate);
......
......@@ -293,15 +293,14 @@ class HEADLESS_EXPORT HeadlessBrowser::Options::Builder {
//
// [1]
// https://chromium.googlesource.com/chromium/src/+/master/docs/linux_zygote.md
HEADLESS_EXPORT void RunChildProcessIfNeeded(int argc, const char** argv);
void RunChildProcessIfNeeded(int argc, const char** argv);
#else
// In Windows, the headless browser may need to create child processes. This is
// done by re-executing the parent process which may have been initialized with
// different libraries (e.g. child_dll). In this case, the embedder has to pass
// the appropiate HINSTANCE and initalization sandbox_info to properly launch
// the child process.
HEADLESS_EXPORT void RunChildProcessIfNeeded(
HINSTANCE instance,
void RunChildProcessIfNeeded(HINSTANCE instance,
sandbox::SandboxInterfaceInfo* sandbox_info);
#endif // !defined(OS_WIN)
......@@ -311,7 +310,7 @@ HEADLESS_EXPORT void RunChildProcessIfNeeded(
// the main loop, it will only return after HeadlessBrowser::Shutdown() is
// called, returning the exit code for the process. It is not possible to
// initialize the browser again after it has been torn down.
HEADLESS_EXPORT int HeadlessBrowserMain(
int HeadlessBrowserMain(
HeadlessBrowser::Options options,
base::OnceCallback<void(HeadlessBrowser*)> on_browser_start_callback);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment