Add initial chrome runtime support (see issue #2969)

Running `cefsimple --enable-chrome-runtime` will create and run a
Chrome browser window using the CEF app methods, and call
CefApp::OnContextInitialized as expected. CEF task methods also
work as expected in the main process. No browser-related methods or
callbacks are currently supported for the Chrome window, and the
application will exit when the last Chrome window closes.

The Chrome runtime requires resources.pak, chrome_100_percent.pak
and chrome_200_percent.pak files which were not previously built
with CEF. It shares the existing locales pak files which have been
updated to include additional Chrome-specific strings.

On Linux, the Chrome runtime requires GTK so use_gtk=true must be
specified via GN_DEFINES when building.

This change also refactors the CEF runtime, which can be tested in
the various supported modes by running:
$ cefclient
$ cefclient --multi-threaded-message-loop
$ cefclient --external-message-pump
This commit is contained in:
Marshall Greenblatt 2020-06-24 22:34:12 -04:00
parent 049caf9131
commit 1174994211
37 changed files with 994 additions and 158 deletions

View File

@ -430,6 +430,10 @@ static_library("libcef_static") {
"libcef/browser/browser_platform_delegate_create.cc",
"libcef/browser/browser_util.cc",
"libcef/browser/browser_util.h",
"libcef/browser/chrome/chrome_browser_main_extra_parts_cef.cc",
"libcef/browser/chrome/chrome_browser_main_extra_parts_cef.h",
"libcef/browser/chrome/chrome_content_browser_client_cef.cc",
"libcef/browser/chrome/chrome_content_browser_client_cef.h",
"libcef/browser/chrome_browser_process_stub.cc",
"libcef/browser/chrome_browser_process_stub.h",
"libcef/browser/chrome_crash_reporter_client_stub.cc",
@ -645,6 +649,10 @@ static_library("libcef_static") {
"libcef/common/cef_messages.h",
"libcef/common/cef_switches.cc",
"libcef/common/cef_switches.h",
"libcef/common/chrome/chrome_main_delegate_cef.cc",
"libcef/common/chrome/chrome_main_delegate_cef.h",
"libcef/common/chrome/chrome_main_runner_delegate.cc",
"libcef/common/chrome/chrome_main_runner_delegate.h",
"libcef/common/command_line_impl.cc",
"libcef/common/command_line_impl.h",
"libcef/common/content_client.cc",
@ -669,6 +677,8 @@ static_library("libcef_static") {
"libcef/common/json_impl.cc",
"libcef/common/main_delegate.cc",
"libcef/common/main_delegate.h",
"libcef/common/main_runner_delegate.h",
"libcef/common/main_runner_handler.h",
"libcef/common/net/http_header_utils.cc",
"libcef/common/net/http_header_utils.h",
"libcef/common/net/net_resource_provider.cc",
@ -703,6 +713,8 @@ static_library("libcef_static") {
"libcef/common/task_impl.cc",
"libcef/common/task_runner_impl.cc",
"libcef/common/task_runner_impl.h",
"libcef/common/task_runner_manager.cc",
"libcef/common/task_runner_manager.h",
"libcef/common/test/translator_test_impl.cc",
"libcef/common/thread_impl.cc",
"libcef/common/thread_impl.h",
@ -719,6 +731,7 @@ static_library("libcef_static") {
"libcef/common/waitable_event_impl.h",
"libcef/common/widevine_loader.cc",
"libcef/common/widevine_loader.h",
"libcef/features/chrome_cef.h",
"libcef/renderer/browser_impl.cc",
"libcef/renderer/browser_impl.h",
"libcef/renderer/content_renderer_client.cc",
@ -748,6 +761,10 @@ static_library("libcef_static") {
"libcef/renderer/url_loader_throttle_provider_impl.h",
"libcef/renderer/v8_impl.cc",
"libcef/renderer/v8_impl.h",
# For Chrome runtime support.
"//chrome/app/chrome_main_delegate.cc",
"//chrome/app/chrome_main_delegate.h",
]
configs += [
@ -790,12 +807,12 @@ static_library("libcef_static") {
"//base:base_static",
"//base/third_party/dynamic_annotations",
"//cc",
"//chrome/browser",
"//chrome/child",
"//chrome/common",
"//chrome/renderer",
"//chrome:browser_dependencies",
"//chrome:child_dependencies",
"//chrome:packed_resources",
"//chrome:resources",
"//chrome:strings",
"//chrome/services/printing:lib",
"//chrome/utility",
"//components/cdm/renderer",
"//components/certificate_transparency",
"//components/content_settings/core/browser",
@ -970,6 +987,10 @@ static_library("libcef_static") {
"libcef/browser/osr/browser_platform_delegate_osr_mac.mm",
"libcef/common/util_mac.h",
"libcef/common/util_mac.mm",
# For Chrome runtime support.
"//chrome/app/chrome_main_mac.h",
"//chrome/app/chrome_main_mac.mm",
]
}
@ -1519,6 +1540,7 @@ make_pack_header("strings") {
"$root_gen_dir/chrome/grit/generated_resources.h",
"$root_gen_dir/chrome/grit/locale_settings.h",
"$root_gen_dir/chrome/grit/platform_locale_settings.h",
"$root_gen_dir/components/strings/grit/components_chromium_strings.h",
"$root_gen_dir/components/strings/grit/components_strings.h",
"$root_gen_dir/extensions/strings/grit/extensions_strings.h",
"$root_gen_dir/services/strings/grit/services_strings.h",

View File

@ -34,6 +34,7 @@ template("_repack_one_locale") {
"${root_gen_dir}/chrome/generated_resources_${locale}.pak",
"${root_gen_dir}/chrome/locale_settings_${locale}.pak",
"${root_gen_dir}/chrome/platform_locale_settings_${locale}.pak",
"${root_gen_dir}/components/strings/components_chromium_strings_${locale}.pak",
"${root_gen_dir}/components/strings/components_locale_settings_${locale}.pak",
"${root_gen_dir}/components/strings/components_strings_${locale}.pak",
"${root_gen_dir}/extensions/strings/extensions_strings_${locale}.pak",
@ -52,6 +53,7 @@ template("_repack_one_locale") {
"//chrome/app:generated_resources",
"//chrome/app/resources:locale_settings",
"//chrome/app/resources:platform_locale_settings",
"//components/strings:components_chromium_strings",
"//components/strings:components_locale_settings",
"//components/strings:components_strings",
"//extensions/strings",

View File

@ -42,13 +42,13 @@
// way that may cause binary incompatibility with other builds. The universal
// hash value will change if any platform is affected whereas the platform hash
// values will change only if that particular platform is affected.
#define CEF_API_HASH_UNIVERSAL "eb44c98407c9286a64b8d872f49c772b3fa3eb63"
#define CEF_API_HASH_UNIVERSAL "74ccf587a0aab55a284b42ee0f68e506441213ee"
#if defined(OS_WIN)
#define CEF_API_HASH_PLATFORM "365b52117c7adf0a8bb6d96638954eb313168ff7"
#define CEF_API_HASH_PLATFORM "ae24a93d1d41a9cf2e5405dc02e62bf9c0eb95b8"
#elif defined(OS_MACOSX)
#define CEF_API_HASH_PLATFORM "1d1bca66ca61d742f507c08d4efda9884c94baff"
#define CEF_API_HASH_PLATFORM "aec384331cfba6541bc267f5a1587931e33cb632"
#elif defined(OS_LINUX)
#define CEF_API_HASH_PLATFORM "a87fd1ea68d4e79c838538fa78d79f8dd05acab2"
#define CEF_API_HASH_PLATFORM "775c9c45cd801ff0b462acc181660f271152ac61"
#endif
#ifdef __cplusplus

View File

@ -192,6 +192,13 @@ typedef struct _cef_settings_t {
///
cef_string_t main_bundle_path;
///
// Set to true (1) to enable use of the Chrome runtime in CEF. This feature is
// considered experimental and is not recommended for most users at this time.
// See issue #2969 for details.
///
int chrome_runtime;
///
// Set to true (1) to have the browser process message loop run in a separate
// thread. If false (0) than the CefDoMessageLoopWork() function must be

View File

@ -569,6 +569,7 @@ struct CefSettingsTraits {
&target->framework_dir_path, copy);
cef_string_set(src->main_bundle_path.str, src->main_bundle_path.length,
&target->main_bundle_path, copy);
target->chrome_runtime = src->chrome_runtime;
target->multi_threaded_message_loop = src->multi_threaded_message_loop;
target->external_message_pump = src->external_message_pump;
target->windowless_rendering_enabled = src->windowless_rendering_enabled;

View File

@ -0,0 +1,23 @@
// Copyright 2019 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 "libcef/browser/chrome/chrome_browser_main_extra_parts_cef.h"
#include "base/task/post_task.h"
ChromeBrowserMainExtraPartsCef::ChromeBrowserMainExtraPartsCef() = default;
ChromeBrowserMainExtraPartsCef::~ChromeBrowserMainExtraPartsCef() = default;
void ChromeBrowserMainExtraPartsCef::PostMainMessageLoopRun() {
background_task_runner_ = base::CreateSingleThreadTaskRunner(
{base::ThreadPool(), base::TaskPriority::BEST_EFFORT,
base::TaskShutdownBehavior::BLOCK_SHUTDOWN, base::MayBlock()});
user_visible_task_runner_ = base::CreateSingleThreadTaskRunner(
{base::ThreadPool(), base::TaskPriority::USER_VISIBLE,
base::TaskShutdownBehavior::BLOCK_SHUTDOWN, base::MayBlock()});
user_blocking_task_runner_ = base::CreateSingleThreadTaskRunner(
{base::ThreadPool(), base::TaskPriority::USER_BLOCKING,
base::TaskShutdownBehavior::BLOCK_SHUTDOWN, base::MayBlock()});
}

View File

@ -0,0 +1,45 @@
// Copyright 2019 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.
#ifndef CEF_LIBCEF_BROWSER_CHROME_CHROME_BROWSER_MAIN_EXTRA_PARTS_CEF_H_
#define CEF_LIBCEF_BROWSER_CHROME_CHROME_BROWSER_MAIN_EXTRA_PARTS_CEF_H_
#include <memory>
#include "base/macros.h"
#include "base/single_thread_task_runner.h"
#include "chrome/browser/chrome_browser_main_extra_parts.h"
// Wrapper that owns and initialize the browser memory-related extra parts.
class ChromeBrowserMainExtraPartsCef : public ChromeBrowserMainExtraParts {
public:
ChromeBrowserMainExtraPartsCef();
~ChromeBrowserMainExtraPartsCef() override;
scoped_refptr<base::SingleThreadTaskRunner> background_task_runner() const {
return background_task_runner_;
}
scoped_refptr<base::SingleThreadTaskRunner> user_visible_task_runner() const {
return user_visible_task_runner_;
}
scoped_refptr<base::SingleThreadTaskRunner> user_blocking_task_runner()
const {
return user_blocking_task_runner_;
}
private:
// ChromeBrowserMainExtraParts overrides.
void PostMainMessageLoopRun() override;
// Blocking task runners exposed via CefTaskRunner. For consistency with
// previous named thread behavior always execute all pending tasks before
// shutdown (e.g. to make sure critical data is saved to disk).
scoped_refptr<base::SingleThreadTaskRunner> background_task_runner_;
scoped_refptr<base::SingleThreadTaskRunner> user_visible_task_runner_;
scoped_refptr<base::SingleThreadTaskRunner> user_blocking_task_runner_;
DISALLOW_COPY_AND_ASSIGN(ChromeBrowserMainExtraPartsCef);
};
#endif // CEF_LIBCEF_BROWSER_CHROME_CHROME_BROWSER_MAIN_EXTRA_PARTS_CEF_H_

View File

@ -0,0 +1,53 @@
// Copyright 2020 The Chromium Embedded Framework Authors.
// Portions copyright 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "libcef/browser/chrome/chrome_content_browser_client_cef.h"
#include "libcef/browser/chrome/chrome_browser_main_extra_parts_cef.h"
#include "libcef/common/cef_switches.h"
#include "base/command_line.h"
#include "chrome/browser/chrome_browser_main.h"
ChromeContentBrowserClientCef::ChromeContentBrowserClientCef(
StartupData* startup_data)
: ChromeContentBrowserClient(startup_data) {}
ChromeContentBrowserClientCef::~ChromeContentBrowserClientCef() = default;
std::unique_ptr<content::BrowserMainParts>
ChromeContentBrowserClientCef::CreateBrowserMainParts(
const content::MainFunctionParams& parameters) {
auto main_parts =
ChromeContentBrowserClient::CreateBrowserMainParts(parameters);
browser_main_parts_ = new ChromeBrowserMainExtraPartsCef;
static_cast<ChromeBrowserMainParts*>(main_parts.get())
->AddParts(browser_main_parts_);
return main_parts;
}
void ChromeContentBrowserClientCef::AppendExtraCommandLineSwitches(
base::CommandLine* command_line,
int child_process_id) {
ChromeContentBrowserClient::AppendExtraCommandLineSwitches(command_line,
child_process_id);
// Necessary to launch sub-processes in the correct mode.
command_line->AppendSwitch(switches::kEnableChromeRuntime);
}
scoped_refptr<base::SingleThreadTaskRunner>
ChromeContentBrowserClientCef::background_task_runner() const {
return browser_main_parts_->background_task_runner();
}
scoped_refptr<base::SingleThreadTaskRunner>
ChromeContentBrowserClientCef::user_visible_task_runner() const {
return browser_main_parts_->user_visible_task_runner();
}
scoped_refptr<base::SingleThreadTaskRunner>
ChromeContentBrowserClientCef::user_blocking_task_runner() const {
return browser_main_parts_->user_blocking_task_runner();
}

View File

@ -0,0 +1,38 @@
// Copyright 2020 The Chromium Embedded Framework Authors.
// Portions copyright 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CEF_LIBCEF_BROWSER_CHROME_CHROME_CONTENT_BROWSER_CLIENT_CEF_
#define CEF_LIBCEF_BROWSER_CHROME_CHROME_CONTENT_BROWSER_CLIENT_CEF_
#include <memory>
#include "base/macros.h"
#include "chrome/browser/chrome_content_browser_client.h"
class ChromeBrowserMainExtraPartsCef;
// CEF override of ChromeContentBrowserClient
class ChromeContentBrowserClientCef : public ChromeContentBrowserClient {
public:
explicit ChromeContentBrowserClientCef(StartupData* startup_data = nullptr);
~ChromeContentBrowserClientCef() override;
// ChromeContentBrowserClient overrides.
std::unique_ptr<content::BrowserMainParts> CreateBrowserMainParts(
const content::MainFunctionParams& parameters) override;
void AppendExtraCommandLineSwitches(base::CommandLine* command_line,
int child_process_id) override;
scoped_refptr<base::SingleThreadTaskRunner> background_task_runner() const;
scoped_refptr<base::SingleThreadTaskRunner> user_visible_task_runner() const;
scoped_refptr<base::SingleThreadTaskRunner> user_blocking_task_runner() const;
private:
ChromeBrowserMainExtraPartsCef* browser_main_parts_ = nullptr;
DISALLOW_COPY_AND_ASSIGN(ChromeContentBrowserClientCef);
};
#endif // CEF_LIBCEF_BROWSER_CHROME_CHROME_CONTENT_BROWSER_CLIENT_CEF_

View File

@ -533,8 +533,7 @@ void PopulateChromeFrameBinders(
} // namespace
CefContentBrowserClient::CefContentBrowserClient()
: browser_main_parts_(nullptr) {
CefContentBrowserClient::CefContentBrowserClient() {
plugin_service_filter_.reset(new CefPluginServiceFilter);
content::PluginServiceImpl::GetInstance()->SetFilter(
plugin_service_filter_.get());

View File

@ -224,7 +224,7 @@ class CefContentBrowserClient : public content::ContentBrowserClient {
const extensions::Extension* GetExtension(
content::SiteInstance* site_instance);
CefBrowserMainParts* browser_main_parts_;
CefBrowserMainParts* browser_main_parts_ = nullptr;
std::unique_ptr<content::PluginServiceFilter> plugin_service_filter_;
};

View File

@ -23,7 +23,6 @@
#include "base/strings/utf_string_conversions.h"
#include "chrome/chrome_elf/chrome_elf_main.h"
#include "chrome/install_static/initialize_from_primary_module.h"
#include "components/crash/core/app/crashpad.h"
#endif
namespace {
@ -267,8 +266,7 @@ void CefRunMessageLoop() {
return;
}
base::RunLoop run_loop;
run_loop.Run();
g_context->RunMessageLoop();
}
void CefQuitMessageLoop() {
@ -284,8 +282,7 @@ void CefQuitMessageLoop() {
return;
}
// Quit the CefBrowserMessageLoop.
base::RunLoop::QuitCurrentWhenIdleDeprecated();
g_context->QuitMessageLoop();
}
void CefSetOSModalLoop(bool osModalLoop) {
@ -321,6 +318,7 @@ bool CefContext::Initialize(const CefMainArgs& args,
void* windows_sandbox_info) {
init_thread_id_ = base::PlatformThread::CurrentId();
settings_ = settings;
application_ = application;
#if !(defined(OS_WIN) || defined(OS_LINUX))
if (settings.multi_threaded_message_loop) {
@ -361,6 +359,21 @@ bool CefContext::Initialize(const CefMainArgs& args,
base::Unretained(this)));
}
void CefContext::RunMessageLoop() {
// Must always be called on the same thread as Initialize.
DCHECK(OnInitThread());
// Blocks until QuitMessageLoop() is called.
main_runner_->RunMessageLoop();
}
void CefContext::QuitMessageLoop() {
// Must always be called on the same thread as Initialize.
DCHECK(OnInitThread());
main_runner_->QuitMessageLoop();
}
void CefContext::Shutdown() {
// Must always be called on the same thread as Initialize.
DCHECK(OnInitThread());
@ -457,11 +470,10 @@ void CefContext::OnContextInitialized() {
CEF_REQUIRE_UIT();
// Notify the handler.
CefRefPtr<CefApp> app = CefContentClient::Get()->application();
if (app.get()) {
if (application_) {
CefRefPtr<CefBrowserProcessHandler> handler =
app->GetBrowserProcessHandler();
if (handler.get())
application_->GetBrowserProcessHandler();
if (handler)
handler->OnContextInitialized();
}
}
@ -480,4 +492,5 @@ void CefContext::ShutdownOnUIThread() {
void CefContext::FinalizeShutdown() {
browser_info_manager_.reset(nullptr);
application_ = nullptr;
}

View File

@ -47,6 +47,8 @@ class CefContext {
const CefSettings& settings,
CefRefPtr<CefApp> application,
void* windows_sandbox_info);
void RunMessageLoop();
void QuitMessageLoop();
void Shutdown();
// Returns true if the current thread is the initialization thread.
@ -106,6 +108,7 @@ class CefContext {
base::PlatformThreadId init_thread_id_;
CefSettings settings_;
CefRefPtr<CefApp> application_;
std::unique_ptr<CefMainRunner> main_runner_;
std::unique_ptr<CefTraceSubscriber> trace_subscriber_;

View File

@ -7,7 +7,10 @@
#include "libcef/browser/browser_message_loop.h"
#include "libcef/browser/thread_util.h"
#include "libcef/renderer/content_renderer_client.h"
#include "libcef/common/cef_switches.h"
#include "libcef/common/chrome/chrome_main_runner_delegate.h"
#include "libcef/common/main_delegate.h"
#include "libcef/features/chrome_cef.h"
#include "base/at_exit.h"
#include "base/base_switches.h"
@ -38,6 +41,27 @@
namespace {
enum class RuntimeType {
UNINITIALIZED,
CEF,
CHROME,
};
RuntimeType g_runtime_type = RuntimeType::UNINITIALIZED;
std::unique_ptr<CefMainRunnerDelegate> MakeDelegate(
RuntimeType type,
CefMainRunnerHandler* runner,
CefSettings* settings,
CefRefPtr<CefApp> application) {
if (type == RuntimeType::CEF) {
g_runtime_type = RuntimeType::CEF;
return std::make_unique<CefMainDelegate>(runner, settings, application);
} else {
g_runtime_type = RuntimeType::CHROME;
return std::make_unique<ChromeMainRunnerDelegate>(runner);
}
}
#if defined(OS_MACOSX) || defined(OS_WIN)
// Based on components/crash/core/app/run_as_crashpad_handler_win.cc
@ -91,8 +115,8 @@ int RunAsCrashpadHandler(const base::CommandLine& command_line) {
// Used to run the UI on a separate thread.
class CefUIThread : public base::PlatformThread::Delegate {
public:
explicit CefUIThread(base::OnceClosure setup_callback)
: setup_callback_(std::move(setup_callback)) {}
CefUIThread(CefMainRunner* runner, base::OnceClosure setup_callback)
: runner_(runner), setup_callback_(std::move(setup_callback)) {}
~CefUIThread() override { Stop(); }
void Start() {
@ -109,8 +133,8 @@ class CefUIThread : public base::PlatformThread::Delegate {
if (!stopping_) {
stopping_ = true;
CEF_POST_TASK(CEF_UIT, base::BindOnce(&CefUIThread::ThreadQuitHelper,
base::Unretained(this)));
CEF_POST_TASK(CEF_UIT, base::BindOnce(&CefMainRunner::QuitMessageLoop,
base::Unretained(runner_)));
}
// Can't join if the |thread_| is either already gone or is non-joinable.
@ -152,12 +176,10 @@ class CefUIThread : public base::PlatformThread::Delegate {
std::move(setup_callback_).Run();
base::RunLoop run_loop;
run_loop_ = &run_loop;
run_loop.Run();
runner_->RunMessageLoop();
browser_runner_->Shutdown();
browser_runner_.reset(nullptr);
browser_runner_.reset();
content::BrowserTaskExecutor::Shutdown();
@ -169,17 +191,12 @@ class CefUIThread : public base::PlatformThread::Delegate {
// be balanced by a corresponding call to CoUninitialize.
CoUninitialize();
#endif
run_loop_ = nullptr;
}
void ThreadQuitHelper() {
DCHECK(run_loop_);
run_loop_->QuitWhenIdle();
}
CefMainRunner* const runner_;
base::OnceClosure setup_callback_;
std::unique_ptr<content::BrowserMainRunner> browser_runner_;
base::OnceClosure setup_callback_;
bool stopping_ = false;
@ -187,8 +204,6 @@ class CefUIThread : public base::PlatformThread::Delegate {
base::PlatformThreadHandle thread_;
mutable base::Lock thread_lock_; // Protects |thread_|.
base::RunLoop* run_loop_ = nullptr;
mutable base::WaitableEvent start_event_;
// This class is not thread-safe, use this to verify access from the owning
@ -209,7 +224,10 @@ bool CefMainRunner::Initialize(CefSettings* settings,
void* windows_sandbox_info,
bool* initialized,
base::OnceClosure context_initialized) {
CefRuntimeInitialize(settings, application);
DCHECK(!main_delegate_);
main_delegate_ = MakeDelegate(
settings->chrome_runtime ? RuntimeType::CHROME : RuntimeType::CEF, this,
settings, application);
const int exit_code =
ContentMainInitialize(args, windows_sandbox_info, &settings->no_sandbox);
@ -254,6 +272,25 @@ void CefMainRunner::Shutdown(base::OnceClosure shutdown_on_ui_thread,
}
}
void CefMainRunner::RunMessageLoop() {
base::RunLoop run_loop;
DCHECK(quit_when_idle_callback_.is_null());
quit_when_idle_callback_ = run_loop.QuitWhenIdleClosure();
main_delegate_->BeforeMainMessageLoopRun(&run_loop);
// Blocks until QuitMessageLoop() is called.
run_loop.Run();
}
void CefMainRunner::QuitMessageLoop() {
if (!quit_when_idle_callback_.is_null()) {
main_delegate_->BeforeMainMessageLoopQuit();
std::move(quit_when_idle_callback_).Run();
}
}
// static
int CefMainRunner::RunAsHelperProcess(const CefMainArgs& args,
CefRefPtr<CefApp> application,
@ -276,16 +313,25 @@ int CefMainRunner::RunAsHelperProcess(const CefMainArgs& args,
if (process_type.empty())
return -1;
auto runtime_type = command_line.HasSwitch(switches::kEnableChromeRuntime)
? RuntimeType::CHROME
: RuntimeType::CEF;
auto main_delegate = MakeDelegate(runtime_type, /*runner=*/nullptr,
/*settings=*/nullptr, application);
main_delegate->BeforeExecuteProcess(args);
int result;
#if defined(OS_MACOSX) || defined(OS_WIN)
if (process_type == crash_reporter::switches::kCrashpadHandler)
return RunAsCrashpadHandler(command_line);
if (process_type == crash_reporter::switches::kCrashpadHandler) {
result = RunAsCrashpadHandler(command_line);
main_delegate->AfterExecuteProcess();
return result;
}
#endif
std::unique_ptr<content::ContentMainDelegate> main_delegate;
main_delegate.reset(new CefMainDelegate(/*context=*/nullptr,
/*settings=*/nullptr, application));
// Execute the secondary process.
// Execute the secondary process.
content::ContentMainParams params(main_delegate->GetContentMainDelegate());
#if defined(OS_WIN)
sandbox::SandboxInterfaceInfo sandbox_info = {0};
if (windows_sandbox_info == nullptr) {
@ -293,38 +339,27 @@ int CefMainRunner::RunAsHelperProcess(const CefMainArgs& args,
windows_sandbox_info = &sandbox_info;
}
content::ContentMainParams params(main_delegate.get());
params.instance = args.instance;
params.sandbox_info =
static_cast<sandbox::SandboxInterfaceInfo*>(windows_sandbox_info);
return content::ContentMain(params);
#else
content::ContentMainParams params(main_delegate.get());
params.argc = args.argc;
params.argv = const_cast<const char**>(args.argv);
return content::ContentMain(params);
#endif
}
result = content::ContentMain(params);
void CefMainRunner::CefRuntimeInitialize(CefSettings* settings,
CefRefPtr<CefApp> app) {
DCHECK_EQ(RuntimeType::UNINITIALIZED, runtime_type_);
DCHECK(!main_delegate_);
main_delegate->AfterExecuteProcess();
runtime_type_ = RuntimeType::CEF;
CefMainDelegate::CefInitialize();
main_delegate_.reset(new CefMainDelegate(this, settings, app));
return result;
}
int CefMainRunner::ContentMainInitialize(const CefMainArgs& args,
void* windows_sandbox_info,
int* no_sandbox) {
DCHECK(main_delegate_);
main_delegate_->BeforeMainThreadInitialize(args);
// Initialize the content runner.
content::ContentMainParams params(main_delegate_.get());
content::ContentMainParams params(main_delegate_->GetContentMainDelegate());
#if defined(OS_WIN)
sandbox::SandboxInterfaceInfo sandbox_info = {0};
if (windows_sandbox_info == nullptr) {
@ -355,8 +390,7 @@ int CefMainRunner::ContentMainInitialize(const CefMainArgs& args,
bool CefMainRunner::ContentMainRun(bool* initialized,
base::OnceClosure context_initialized) {
if (IsCefRuntime())
CefMainDelegate::MainThreadInitialize();
main_delegate_->BeforeMainThreadRun();
if (multi_threaded_message_loop_) {
base::WaitableEvent uithread_startup_event(
@ -424,7 +458,7 @@ int CefMainRunner::RunMainProcess(
bool CefMainRunner::CreateUIThread(base::OnceClosure setup_callback) {
DCHECK(!ui_thread_);
ui_thread_.reset(new CefUIThread(std::move(setup_callback)));
ui_thread_.reset(new CefUIThread(this, std::move(setup_callback)));
ui_thread_->Start();
ui_thread_->WaitUntilThreadStarted();
@ -437,8 +471,8 @@ bool CefMainRunner::CreateUIThread(base::OnceClosure setup_callback) {
void CefMainRunner::OnContextInitialized(
base::OnceClosure context_initialized) {
CEF_REQUIRE_UIT();
if (IsCefRuntime())
CefMainDelegate::UIThreadInitialize();
main_delegate_->AfterUIThreadInitialize();
std::move(context_initialized).Run();
}
@ -450,22 +484,18 @@ void CefMainRunner::FinishShutdownOnUIThread(
sm_main_delegate_->ShutdownOnUIThread();
std::move(shutdown_on_ui_thread).Run();
if (IsCefRuntime())
CefMainDelegate::UIThreadShutdown();
main_delegate_->AfterUIThreadShutdown();
if (uithread_shutdown_event)
uithread_shutdown_event->Signal();
}
void CefMainRunner::FinalizeShutdown(base::OnceClosure finalize_shutdown) {
if (content::RenderProcessHost::run_renderer_in_process() && IsCefRuntime()) {
// Blocks until RenderProcess cleanup is complete.
CefContentRendererClient::Get()->RunSingleProcessCleanup();
}
main_delegate_->BeforeMainThreadShutdown();
if (browser_runner_.get()) {
browser_runner_->Shutdown();
browser_runner_.reset(nullptr);
browser_runner_.reset();
}
if (ui_thread_.get()) {
@ -477,13 +507,25 @@ void CefMainRunner::FinalizeShutdown(base::OnceClosure finalize_shutdown) {
// Shut down the content runner.
service_manager::MainShutdown(*sm_main_params_);
sm_main_params_.reset(nullptr);
sm_main_delegate_.reset(nullptr);
sm_main_params_.reset();
sm_main_delegate_.reset();
std::move(finalize_shutdown).Run();
if (IsCefRuntime())
CefMainDelegate::MainThreadShutdown();
main_delegate_->AfterMainThreadShutdown();
main_delegate_.reset(nullptr);
runtime_type_ = RuntimeType::UNINITIALIZED;
main_delegate_.reset();
g_runtime_type = RuntimeType::UNINITIALIZED;
}
// From libcef/features/chrome_cef.h:
namespace cef {
bool IsCefRuntimeEnabled() {
return g_runtime_type == RuntimeType::CEF;
}
bool IsChromeRuntimeEnabled() {
return g_runtime_type == RuntimeType::CHROME;
}
} // namespace cef

View File

@ -7,9 +7,11 @@
#define CEF_LIBCEF_BROWSER_MAIN_RUNNER_H_
#pragma once
#include "libcef/common/main_delegate.h"
#include "include/cef_app.h"
#include "libcef/common/main_runner_delegate.h"
#include "libcef/common/main_runner_handler.h"
#include "base/callback_forward.h"
#include "base/callback.h"
#include "base/macros.h"
#include "content/public/browser/browser_main_runner.h"
@ -30,7 +32,7 @@ struct MainParams;
class CefUIThread;
// Manages the main process lifespan and related objects.
class CefMainRunner : public CefMainDelegate::Runner {
class CefMainRunner : public CefMainRunnerHandler {
public:
CefMainRunner(bool multi_threaded_message_loop, bool external_message_pump);
~CefMainRunner();
@ -47,7 +49,8 @@ class CefMainRunner : public CefMainDelegate::Runner {
void Shutdown(base::OnceClosure shutdown_on_ui_thread,
base::OnceClosure finalize_shutdown);
bool IsCefRuntime() const { return runtime_type_ == RuntimeType::CEF; }
void RunMessageLoop();
void QuitMessageLoop();
// Called from CefExecuteProcess.
static int RunAsHelperProcess(const CefMainArgs& args,
@ -56,13 +59,12 @@ class CefMainRunner : public CefMainDelegate::Runner {
private:
// Called from Initialize().
void CefRuntimeInitialize(CefSettings* settings, CefRefPtr<CefApp> app);
int ContentMainInitialize(const CefMainArgs& args,
void* windows_sandbox_info,
int* no_sandbox);
bool ContentMainRun(bool* initialized, base::OnceClosure context_initialized);
// CefMainDelegate::Runner methods:
// CefMainRunnerHandler methods:
void PreCreateMainMessageLoop() override;
int RunMainProcess(
const content::MainFunctionParams& main_function_params) override;
@ -84,19 +86,16 @@ class CefMainRunner : public CefMainDelegate::Runner {
const bool multi_threaded_message_loop_;
const bool external_message_pump_;
enum class RuntimeType {
UNINITIALIZED,
CEF,
};
RuntimeType runtime_type_ = RuntimeType::UNINITIALIZED;
std::unique_ptr<content::ContentMainDelegate> main_delegate_;
std::unique_ptr<CefMainRunnerDelegate> main_delegate_;
std::unique_ptr<content::ContentServiceManagerMainDelegate> sm_main_delegate_;
std::unique_ptr<service_manager::MainParams> sm_main_params_;
std::unique_ptr<content::BrowserMainRunner> browser_runner_;
std::unique_ptr<CefUIThread> ui_thread_;
// Used to quit the current base::RunLoop.
base::OnceClosure quit_when_idle_callback_;
DISALLOW_COPY_AND_ASSIGN(CefMainRunner);
};

View File

@ -122,6 +122,9 @@ const char kDisableNewBrowserInfoTimeout[] = "disable-new-browser-info-timeout";
// File used for logging DevTools protocol messages.
const char kDevToolsProtocolLogFile[] = "devtools-protocol-log-file";
// Enable use of the Chrome runtime in CEF. See issue #2969 for details.
const char kEnableChromeRuntime[] = "enable-chrome-runtime";
#if defined(OS_MACOSX)
// Path to the framework directory.
const char kFrameworkDirPath[] = "framework-dir-path";

View File

@ -54,6 +54,7 @@ extern const char kEnablePreferenceTesting[];
extern const char kEnablePrintPreview[];
extern const char kDisableNewBrowserInfoTimeout[];
extern const char kDevToolsProtocolLogFile[];
extern const char kEnableChromeRuntime[];
#if defined(OS_MACOSX)
extern const char kFrameworkDirPath[];

View File

@ -0,0 +1,86 @@
// Copyright 2020 The Chromium Embedded Framework Authors.
// Portions copyright 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "libcef/common/chrome/chrome_main_delegate_cef.h"
#include "libcef/browser/chrome/chrome_content_browser_client_cef.h"
ChromeMainDelegateCef::ChromeMainDelegateCef(CefMainRunnerHandler* runner)
: ChromeMainDelegate(base::TimeTicks::Now()), runner_(runner) {}
ChromeMainDelegateCef::~ChromeMainDelegateCef() = default;
void ChromeMainDelegateCef::PreCreateMainMessageLoop() {
// The parent ChromeMainDelegate implementation creates the NSApplication
// instance on macOS, and we intentionally don't want to do that here.
runner_->PreCreateMainMessageLoop();
}
int ChromeMainDelegateCef::RunProcess(
const std::string& process_type,
const content::MainFunctionParams& main_function_params) {
if (process_type.empty()) {
return runner_->RunMainProcess(main_function_params);
}
return ChromeMainDelegate::RunProcess(process_type, main_function_params);
}
content::ContentBrowserClient*
ChromeMainDelegateCef::CreateContentBrowserClient() {
// Match the logic in the parent ChromeMainDelegate implementation, but create
// our own object type.
if (chrome_content_browser_client_ == nullptr) {
DCHECK(!startup_data_);
startup_data_ = std::make_unique<StartupData>();
chrome_content_browser_client_ =
std::make_unique<ChromeContentBrowserClientCef>(startup_data_.get());
}
return chrome_content_browser_client_.get();
}
scoped_refptr<base::SingleThreadTaskRunner>
ChromeMainDelegateCef::GetBackgroundTaskRunner() {
auto browser_client = content_browser_client();
if (browser_client)
return browser_client->background_task_runner();
return nullptr;
}
scoped_refptr<base::SingleThreadTaskRunner>
ChromeMainDelegateCef::GetUserVisibleTaskRunner() {
auto browser_client = content_browser_client();
if (browser_client)
return browser_client->user_visible_task_runner();
return nullptr;
}
scoped_refptr<base::SingleThreadTaskRunner>
ChromeMainDelegateCef::GetUserBlockingTaskRunner() {
auto browser_client = content_browser_client();
if (browser_client)
return browser_client->user_blocking_task_runner();
return nullptr;
}
scoped_refptr<base::SingleThreadTaskRunner>
ChromeMainDelegateCef::GetRenderTaskRunner() {
// TODO: Implement.
NOTREACHED();
return nullptr;
}
scoped_refptr<base::SingleThreadTaskRunner>
ChromeMainDelegateCef::GetWebWorkerTaskRunner() {
// TODO: Implement.
NOTREACHED();
return nullptr;
}
ChromeContentBrowserClientCef* ChromeMainDelegateCef::content_browser_client()
const {
return static_cast<ChromeContentBrowserClientCef*>(
chrome_content_browser_client_.get());
}

View File

@ -0,0 +1,55 @@
// Copyright 2020 The Chromium Embedded Framework Authors.
// Portions copyright 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CEF_LIBCEF_COMMON_CHROME_CHROME_MAIN_DELEGATE_CEF_
#define CEF_LIBCEF_COMMON_CHROME_CHROME_MAIN_DELEGATE_CEF_
#include <memory>
#include "include/cef_base.h"
#include "libcef/common/main_runner_handler.h"
#include "libcef/common/task_runner_manager.h"
#include "base/macros.h"
#include "chrome/app/chrome_main_delegate.h"
class ChromeContentBrowserClientCef;
// CEF override of ChromeMainDelegate
class ChromeMainDelegateCef : public ChromeMainDelegate,
public CefTaskRunnerManager {
public:
// |runner| will be non-nullptr for the main process only, and will outlive
// this object.
explicit ChromeMainDelegateCef(CefMainRunnerHandler* runner);
~ChromeMainDelegateCef() override;
// ChromeMainDelegate overrides.
void PreCreateMainMessageLoop() override;
int RunProcess(
const std::string& process_type,
const content::MainFunctionParams& main_function_params) override;
content::ContentBrowserClient* CreateContentBrowserClient() override;
protected:
// CefTaskRunnerManager overrides.
scoped_refptr<base::SingleThreadTaskRunner> GetBackgroundTaskRunner()
override;
scoped_refptr<base::SingleThreadTaskRunner> GetUserVisibleTaskRunner()
override;
scoped_refptr<base::SingleThreadTaskRunner> GetUserBlockingTaskRunner()
override;
scoped_refptr<base::SingleThreadTaskRunner> GetRenderTaskRunner() override;
scoped_refptr<base::SingleThreadTaskRunner> GetWebWorkerTaskRunner() override;
private:
ChromeContentBrowserClientCef* content_browser_client() const;
CefMainRunnerHandler* const runner_;
DISALLOW_COPY_AND_ASSIGN(ChromeMainDelegateCef);
};
#endif // CEF_LIBCEF_COMMON_CHROME_CHROME_MAIN_DELEGATE_CEF_

View File

@ -0,0 +1,84 @@
// Copyright 2020 The Chromium Embedded Framework Authors.
// Portions copyright 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "libcef/common/chrome/chrome_main_runner_delegate.h"
#include "libcef/common/chrome/chrome_main_delegate_cef.h"
#include "base/command_line.h"
#include "base/run_loop.h"
#include "chrome/browser/browser_process_impl.h"
#include "chrome/common/profiler/main_thread_stack_sampling_profiler.h"
#include "components/keep_alive_registry/keep_alive_types.h"
#include "components/keep_alive_registry/scoped_keep_alive.h"
#if defined(OS_MACOSX)
#include "chrome/app/chrome_main_mac.h"
#endif
ChromeMainRunnerDelegate::ChromeMainRunnerDelegate(CefMainRunnerHandler* runner)
: runner_(runner) {}
ChromeMainRunnerDelegate::~ChromeMainRunnerDelegate() = default;
content::ContentMainDelegate*
ChromeMainRunnerDelegate::GetContentMainDelegate() {
if (!main_delegate_) {
main_delegate_ = std::make_unique<ChromeMainDelegateCef>(runner_);
}
return main_delegate_.get();
}
void ChromeMainRunnerDelegate::BeforeMainThreadInitialize(
const CefMainArgs& args) {
#if defined(OS_WIN)
base::CommandLine::Init(0, nullptr);
#else
base::CommandLine::Init(args.argc, args.argv);
#endif
#if defined(OS_MACOSX)
SetUpBundleOverrides();
#endif
sampling_profiler_ = std::make_unique<MainThreadStackSamplingProfiler>();
}
void ChromeMainRunnerDelegate::BeforeMainMessageLoopRun(
base::RunLoop* run_loop) {
// The ScopedKeepAlive instance triggers shutdown logic when released on the
// UI thread before terminating the message loop (e.g. from CefQuitMessageLoop
// or FinishShutdownOnUIThread when running with multi-threaded message loop).
// TODO(chrome-runtime): Enable this once browser life-span notifications are
// in place. In the mean time, closing the last Chrome browser instance will
// exit the app.
/*
keep_alive_ = std::make_unique<ScopedKeepAlive>(
KeepAliveOrigin::APP_CONTROLLER, KeepAliveRestartOption::DISABLED);
*/
// The idle callback will be executed from BrowserProcessImpl::Unpin() via
// KeepAliveRegistry when the last ScopedKeepAlive is released.
// ScopedKeepAlives are also held by Browser objects.
DCHECK(g_browser_process);
static_cast<BrowserProcessImpl*>(g_browser_process)
->SetQuitClosure(run_loop->QuitWhenIdleClosure());
}
void ChromeMainRunnerDelegate::BeforeMainMessageLoopQuit() {
// May be called multiple times. See comments in RunMainMessageLoopBefore.
keep_alive_.reset();
}
void ChromeMainRunnerDelegate::AfterMainThreadShutdown() {
sampling_profiler_.reset();
}
void ChromeMainRunnerDelegate::BeforeExecuteProcess(const CefMainArgs& args) {
BeforeMainThreadInitialize(args);
}
void ChromeMainRunnerDelegate::AfterExecuteProcess() {
AfterMainThreadShutdown();
}

View File

@ -0,0 +1,47 @@
// Copyright 2020 The Chromium Embedded Framework Authors.
// Portions copyright 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CEF_LIBCEF_COMMON_CHROME_CHROME_MAIN_RUNNER_DELEGATE_CEF_
#define CEF_LIBCEF_COMMON_CHROME_CHROME_MAIN_RUNNER_DELEGATE_CEF_
#include <memory>
#include "include/cef_base.h"
#include "libcef/common/main_runner_delegate.h"
#include "libcef/common/main_runner_handler.h"
class ChromeMainDelegateCef;
class MainThreadStackSamplingProfiler;
class ScopedKeepAlive;
class ChromeMainRunnerDelegate : public CefMainRunnerDelegate {
public:
// |runner| will be non-nullptr for the main process only, and will outlive
// this object.
explicit ChromeMainRunnerDelegate(CefMainRunnerHandler* runner);
~ChromeMainRunnerDelegate() override;
protected:
// CefMainRunnerDelegate overrides.
content::ContentMainDelegate* GetContentMainDelegate() override;
void BeforeMainThreadInitialize(const CefMainArgs& args) override;
void BeforeMainMessageLoopRun(base::RunLoop* run_loop) override;
void BeforeMainMessageLoopQuit() override;
void AfterMainThreadShutdown() override;
void BeforeExecuteProcess(const CefMainArgs& args) override;
void AfterExecuteProcess() override;
private:
std::unique_ptr<ChromeMainDelegateCef> main_delegate_;
std::unique_ptr<MainThreadStackSamplingProfiler> sampling_profiler_;
std::unique_ptr<ScopedKeepAlive> keep_alive_;
CefMainRunnerHandler* const runner_;
DISALLOW_COPY_AND_ASSIGN(ChromeMainRunnerDelegate);
};
#endif // CEF_LIBCEF_COMMON_CHROME_CHROME_MAIN_RUNNER_DELEGATE_CEF_

View File

@ -321,7 +321,7 @@ void OverrideAssetPath() {
} // namespace
CefMainDelegate::CefMainDelegate(Runner* runner,
CefMainDelegate::CefMainDelegate(CefMainRunnerHandler* runner,
CefSettings* settings,
CefRefPtr<CefApp> application)
: runner_(runner), settings_(settings), content_client_(application) {
@ -719,18 +719,15 @@ content::ContentUtilityClient* CefMainDelegate::CreateContentUtilityClient() {
return utility_client_.get();
}
// static
void CefMainDelegate::CefInitialize() {
void CefMainDelegate::BeforeMainThreadInitialize(const CefMainArgs& args) {
g_browser_process = new ChromeBrowserProcessStub();
}
// static
void CefMainDelegate::MainThreadInitialize() {
void CefMainDelegate::BeforeMainThreadRun() {
static_cast<ChromeBrowserProcessStub*>(g_browser_process)->Initialize();
}
// static
void CefMainDelegate::UIThreadInitialize() {
void CefMainDelegate::AfterUIThreadInitialize() {
#if BUILDFLAG(ENABLE_WIDEVINE) && BUILDFLAG(ENABLE_LIBRARY_CDMS)
CefWidevineLoader::GetInstance()->OnContextInitialized();
#endif
@ -739,18 +736,60 @@ void CefMainDelegate::UIThreadInitialize() {
->OnContextInitialized();
}
// static
void CefMainDelegate::UIThreadShutdown() {
void CefMainDelegate::AfterUIThreadShutdown() {
static_cast<ChromeBrowserProcessStub*>(g_browser_process)
->CleanupOnUIThread();
ui::ResourceBundle::GetSharedInstance().CleanupOnUIThread();
}
// static
void CefMainDelegate::MainThreadShutdown() {
delete g_browser_process;
g_browser_process = nullptr;
void CefMainDelegate::BeforeMainThreadShutdown() {
if (content::RenderProcessHost::run_renderer_in_process()) {
// Blocks until RenderProcess cleanup is complete.
CefContentRendererClient::Get()->RunSingleProcessCleanup();
}
}
void CefMainDelegate::AfterMainThreadShutdown() {
if (g_browser_process) {
delete g_browser_process;
g_browser_process = nullptr;
}
}
scoped_refptr<base::SingleThreadTaskRunner>
CefMainDelegate::GetBackgroundTaskRunner() {
if (browser_client_)
return browser_client_->background_task_runner();
return nullptr;
}
scoped_refptr<base::SingleThreadTaskRunner>
CefMainDelegate::GetUserVisibleTaskRunner() {
if (browser_client_)
return browser_client_->user_visible_task_runner();
return nullptr;
}
scoped_refptr<base::SingleThreadTaskRunner>
CefMainDelegate::GetUserBlockingTaskRunner() {
if (browser_client_)
return browser_client_->user_blocking_task_runner();
return nullptr;
}
scoped_refptr<base::SingleThreadTaskRunner>
CefMainDelegate::GetRenderTaskRunner() {
if (renderer_client_)
return renderer_client_->render_task_runner();
return nullptr;
}
scoped_refptr<base::SingleThreadTaskRunner>
CefMainDelegate::GetWebWorkerTaskRunner() {
if (renderer_client_)
return renderer_client_->GetCurrentTaskRunner();
return nullptr;
}
void CefMainDelegate::InitializeResourceBundle() {

View File

@ -10,6 +10,9 @@
#include "include/cef_app.h"
#include "libcef/common/content_client.h"
#include "libcef/common/main_runner_delegate.h"
#include "libcef/common/main_runner_handler.h"
#include "libcef/common/task_runner_manager.h"
#include "base/compiler_specific.h"
#include "content/public/app/content_main_delegate.h"
@ -23,25 +26,18 @@ class CefContentRendererClient;
class ChromeContentUtilityClient;
// Manages state specific to the CEF runtime.
class CefMainDelegate : public content::ContentMainDelegate {
class CefMainDelegate : public content::ContentMainDelegate,
public CefMainRunnerDelegate,
public CefTaskRunnerManager {
public:
class Runner {
public:
virtual void PreCreateMainMessageLoop() = 0;
virtual int RunMainProcess(
const content::MainFunctionParams& main_function_params) = 0;
protected:
virtual ~Runner() {}
};
// |runner| and |settings| will be non-nullptr for the main process only,
// and will outlive this object.
CefMainDelegate(Runner* runner,
CefMainDelegate(CefMainRunnerHandler* runner,
CefSettings* settings,
CefRefPtr<CefApp> application);
~CefMainDelegate() override;
// content::ContentMainDelegate overrides.
void PreCreateMainMessageLoop() override;
bool BasicStartupComplete(int* exit_code) override;
void PreSandboxStartup() override;
@ -60,18 +56,32 @@ class CefMainDelegate : public content::ContentMainDelegate {
CefContentBrowserClient* browser_client() { return browser_client_.get(); }
CefContentClient* content_client() { return &content_client_; }
// Called from MainRunner at various initialization/shutdown stages to create
// and clean up global state.
static void CefInitialize();
static void MainThreadInitialize();
static void UIThreadInitialize();
static void UIThreadShutdown();
static void MainThreadShutdown();
protected:
// CefMainRunnerDelegate overrides.
content::ContentMainDelegate* GetContentMainDelegate() override {
return this;
}
void BeforeMainThreadInitialize(const CefMainArgs& args) override;
void BeforeMainThreadRun() override;
void AfterUIThreadInitialize() override;
void AfterUIThreadShutdown() override;
void BeforeMainThreadShutdown() override;
void AfterMainThreadShutdown() override;
// CefTaskRunnerManager overrides.
scoped_refptr<base::SingleThreadTaskRunner> GetBackgroundTaskRunner()
override;
scoped_refptr<base::SingleThreadTaskRunner> GetUserVisibleTaskRunner()
override;
scoped_refptr<base::SingleThreadTaskRunner> GetUserBlockingTaskRunner()
override;
scoped_refptr<base::SingleThreadTaskRunner> GetRenderTaskRunner() override;
scoped_refptr<base::SingleThreadTaskRunner> GetWebWorkerTaskRunner() override;
private:
void InitializeResourceBundle();
Runner* const runner_;
CefMainRunnerHandler* const runner_;
CefSettings* const settings_;
std::unique_ptr<CefContentBrowserClient> browser_client_;

View File

@ -0,0 +1,37 @@
// Copyright 2020 The Chromium Embedded Framework Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CEF_LIBCEF_COMMON_MAIN_RUNNER_DELEGATE_H_
#define CEF_LIBCEF_COMMON_MAIN_RUNNER_DELEGATE_H_
#pragma once
#include "include/cef_app.h"
namespace base {
class RunLoop;
}
namespace content {
class ContentMainDelegate;
}
class CefMainRunnerDelegate {
public:
virtual content::ContentMainDelegate* GetContentMainDelegate() = 0;
virtual void BeforeMainThreadInitialize(const CefMainArgs& args) {}
virtual void BeforeMainThreadRun() {}
virtual void BeforeMainMessageLoopRun(base::RunLoop* run_loop) {}
virtual void BeforeMainMessageLoopQuit() {}
virtual void AfterUIThreadInitialize() {}
virtual void AfterUIThreadShutdown() {}
virtual void BeforeMainThreadShutdown() {}
virtual void AfterMainThreadShutdown() {}
virtual void BeforeExecuteProcess(const CefMainArgs& args) {}
virtual void AfterExecuteProcess() {}
virtual ~CefMainRunnerDelegate() {}
};
#endif // CEF_LIBCEF_COMMON_MAIN_RUNNER_DELEGATE_H_

View File

@ -0,0 +1,24 @@
// Copyright 2020 The Chromium Embedded Framework Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CEF_LIBCEF_COMMON_MAIN_RUNNER_HANDLER_H_
#define CEF_LIBCEF_COMMON_MAIN_RUNNER_HANDLER_H_
#pragma once
namespace content {
struct MainFunctionParams;
}
// Handles running of the main process.
class CefMainRunnerHandler {
public:
virtual void PreCreateMainMessageLoop() = 0;
virtual int RunMainProcess(
const content::MainFunctionParams& main_function_params) = 0;
protected:
virtual ~CefMainRunnerHandler() {}
};
#endif // CEF_LIBCEF_COMMON_MAIN_RUNNER_HANDLER_H_

View File

@ -3,14 +3,13 @@
// can be found in the LICENSE file.
#include "libcef/common/task_runner_impl.h"
#include "libcef/browser/content_browser_client.h"
#include "libcef/common/content_client.h"
#include "libcef/renderer/content_renderer_client.h"
#include "libcef/common/task_runner_manager.h"
#include "base/bind.h"
#include "base/location.h"
#include "base/logging.h"
#include "base/message_loop/message_loop.h"
#include "base/task/post_task.h"
#include "base/threading/thread_task_runner_handle.h"
#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
@ -51,17 +50,8 @@ CefTaskRunnerImpl::CefTaskRunnerImpl(
// static
scoped_refptr<base::SingleThreadTaskRunner> CefTaskRunnerImpl::GetTaskRunner(
CefThreadId threadId) {
// Render process.
if (threadId == TID_RENDERER) {
CefContentRendererClient* client = CefContentRendererClient::Get();
if (client)
return client->render_task_runner();
return nullptr;
}
// Browser process.
CefContentBrowserClient* client = CefContentBrowserClient::Get();
if (!client)
auto* manager = CefTaskRunnerManager::Get();
if (!manager)
return nullptr;
int id = -1;
@ -70,16 +60,18 @@ scoped_refptr<base::SingleThreadTaskRunner> CefTaskRunnerImpl::GetTaskRunner(
id = BrowserThread::UI;
break;
case TID_FILE_BACKGROUND:
return client->background_task_runner();
return manager->GetBackgroundTaskRunner();
case TID_FILE_USER_VISIBLE:
return client->user_visible_task_runner();
return manager->GetUserVisibleTaskRunner();
case TID_FILE_USER_BLOCKING:
return client->user_blocking_task_runner();
return manager->GetUserBlockingTaskRunner();
case TID_PROCESS_LAUNCHER:
return content::GetProcessLauncherTaskRunner();
case TID_IO:
id = BrowserThread::IO;
break;
case TID_RENDERER:
return manager->GetRenderTaskRunner();
default:
break;
};
@ -99,6 +91,10 @@ scoped_refptr<base::SingleThreadTaskRunner> CefTaskRunnerImpl::GetTaskRunner(
// static
scoped_refptr<base::SingleThreadTaskRunner>
CefTaskRunnerImpl::GetCurrentTaskRunner() {
auto* manager = CefTaskRunnerManager::Get();
if (!manager)
return nullptr;
scoped_refptr<base::SingleThreadTaskRunner> task_runner;
// For named browser process threads return the same TaskRunner as
@ -120,9 +116,7 @@ CefTaskRunnerImpl::GetCurrentTaskRunner() {
if (!task_runner.get()) {
// Check for a WebWorker thread.
CefContentRendererClient* client = CefContentRendererClient::Get();
if (client)
task_runner = client->GetCurrentTaskRunner();
return manager->GetWebWorkerTaskRunner();
}
return task_runner;

View File

@ -0,0 +1,28 @@
// Copyright 2020 The Chromium Embedded Framework 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 "libcef/common/task_runner_manager.h"
#include "base/logging.h"
namespace {
CefTaskRunnerManager* g_manager = nullptr;
} // namespace
// static
CefTaskRunnerManager* CefTaskRunnerManager::Get() {
return g_manager;
}
CefTaskRunnerManager::CefTaskRunnerManager() {
// Only a single instance should exist.
DCHECK(!g_manager);
g_manager = this;
}
CefTaskRunnerManager::~CefTaskRunnerManager() {
g_manager = nullptr;
}

View File

@ -0,0 +1,37 @@
// Copyright 2020 The Chromium Embedded Framework Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CEF_LIBCEF_COMMON_TASK_RUNNER_MANAGER_H_
#define CEF_LIBCEF_COMMON_TASK_RUNNER_MANAGER_H_
#pragma once
#include "base/single_thread_task_runner.h"
// Exposes global sequenced task runners in the main and render processes.
// Prefer using base::ThreadPool for tasks that do not need to be globally
// sequenced and CefTaskRunner for retrieving named CefThreadId runners.
class CefTaskRunnerManager {
public:
// Returns the singleton instance that is scoped to CEF lifespan.
static CefTaskRunnerManager* Get();
// Available in the main process:
virtual scoped_refptr<base::SingleThreadTaskRunner>
GetBackgroundTaskRunner() = 0;
virtual scoped_refptr<base::SingleThreadTaskRunner>
GetUserVisibleTaskRunner() = 0;
virtual scoped_refptr<base::SingleThreadTaskRunner>
GetUserBlockingTaskRunner() = 0;
// Available in the render process:
virtual scoped_refptr<base::SingleThreadTaskRunner> GetRenderTaskRunner() = 0;
virtual scoped_refptr<base::SingleThreadTaskRunner>
GetWebWorkerTaskRunner() = 0;
protected:
CefTaskRunnerManager();
virtual ~CefTaskRunnerManager();
};
#endif // CEF_LIBCEF_COMMON_TASK_RUNNER_MANAGER_H_

View File

@ -0,0 +1,41 @@
// Copyright 2020 The Chromium Embedded Framework Authors. All rights
// reserved. Use of this source code is governed by a BSD-style license that
// can be found in the LICENSE file.
#ifndef CEF_LIBCEF_FEATURES_CHROME_CEF_H_
#define CEF_LIBCEF_FEATURES_CHROME_CEF_H_
#pragma once
#include "cef/libcef/features/features.h"
namespace cef {
#if BUILDFLAG(ENABLE_CEF)
inline bool IsCefBuildEnabled() {
return true;
}
// True if CEF was initialized with the CEF runtime.
bool IsCefRuntimeEnabled();
// True if CEF was initialized with the Chrome runtime.
bool IsChromeRuntimeEnabled();
#else
inline bool IsCefBuildEnabled() {
return false;
}
inline bool IsCefRuntimeEnabled() {
return false;
}
inline bool IsChromeRuntimeEnabled() {
return false;
}
#endif
} // namespace cef
#endif // CEF_LIBCEF_FEATURES_CHROME_CEF_H_

View File

@ -206,6 +206,11 @@ patches = [
# Support CEF changes in chrome/renderer.
'name': 'chrome_renderer',
},
{
# Changes to support the Chrome runtime in CEF.
# https://bitbucket.org/chromiumembedded/cef/issues/2969
'name': 'chrome_runtime',
},
{
# Don't initialize ExtensionSystemFactory when extensions are disabled.
# https://bitbucket.org/chromiumembedded/cef/issues/2359
@ -501,5 +506,11 @@ patches = [
# ChromeBrowserMainExtraPartsViewsLinux::ToolkitInitialized.
# https://bugs.chromium.org/p/chromium/issues/detail?id=1085806
'name': 'linux_chrome_views_1085806',
},
{
# Linux: Fix undefined symbol: ResourceMapper::MapToJavaDrawableId in
# ChromePageInfoClient::GetJavaResourceId.
# https://bugs.chromium.org/p/chromium/issues/detail?id=1099927
'name': 'linux_chrome_page_info_1099927',
}
]

View File

@ -0,0 +1,48 @@
diff --git chrome/browser/chrome_browser_main.cc chrome/browser/chrome_browser_main.cc
index c06585b15b8f..b5ed3518c0fd 100644
--- chrome/browser/chrome_browser_main.cc
+++ chrome/browser/chrome_browser_main.cc
@@ -49,6 +49,7 @@
#include "build/branding_buildflags.h"
#include "build/build_config.h"
#include "cc/base/switches.h"
+#include "cef/libcef/features/chrome_cef.h"
#include "chrome/browser/about_flags.h"
#include "chrome/browser/active_use_util.h"
#include "chrome/browser/after_startup_task_utils.h"
@@ -885,8 +886,10 @@ int ChromeBrowserMainParts::PreCreateThreadsImpl() {
#if !defined(OS_ANDROID)
// Create the RunLoop for MainMessageLoopRun() to use, and pass a copy of
// its QuitClosure to the BrowserProcessImpl to call when it is time to exit.
+ // CEF with the Chrome runtime will create and manage its own RunLoop.
DCHECK(!g_run_loop);
- g_run_loop = new base::RunLoop;
+ if (!cef::IsChromeRuntimeEnabled())
+ g_run_loop = new base::RunLoop;
// These members must be initialized before returning from this function.
// Android doesn't use StartupBrowserCreator.
@@ -1613,7 +1616,9 @@ int ChromeBrowserMainParts::PreMainMessageLoopRunImpl() {
#endif // defined(OS_MACOSX)
// Transfer ownership of the browser's lifetime to the BrowserProcess.
- browser_process_->SetQuitClosure(g_run_loop->QuitWhenIdleClosure());
+ // CEF with the Chrome runtime will create and manage its own RunLoop.
+ if (g_run_loop)
+ browser_process_->SetQuitClosure(g_run_loop->QuitWhenIdleClosure());
DCHECK(!run_message_loop_);
run_message_loop_ = true;
}
diff --git ui/gtk/select_file_dialog_impl_kde.cc ui/gtk/select_file_dialog_impl_kde.cc
index f09501d6cd8e..edfc2a4c9bb5 100644
--- ui/gtk/select_file_dialog_impl_kde.cc
+++ ui/gtk/select_file_dialog_impl_kde.cc
@@ -6,6 +6,8 @@
#include <gtk/gtk.h>
#include <stddef.h>
+#undef Success
+
#include <memory>
#include <set>

View File

@ -0,0 +1,14 @@
diff --git chrome/browser/ui/page_info/chrome_page_info_client.cc chrome/browser/ui/page_info/chrome_page_info_client.cc
index e2972da9e548..2f356616ed97 100644
--- chrome/browser/ui/page_info/chrome_page_info_client.cc
+++ chrome/browser/ui/page_info/chrome_page_info_client.cc
@@ -17,5 +17,9 @@ std::unique_ptr<PageInfoDelegate> ChromePageInfoClient::CreatePageInfoDelegate(
}
int ChromePageInfoClient::GetJavaResourceId(int native_resource_id) {
+#if defined(OS_ANDROID)
return ResourceMapper::MapToJavaDrawableId(native_resource_id);
+#else
+ return 0;
+#endif
}

View File

@ -1,16 +1,16 @@
diff --git chrome/browser/net/profile_network_context_service.cc chrome/browser/net/profile_network_context_service.cc
index 75a5ee192358..bc97cbf684c0 100644
index 75a5ee192358..379e0bdd11b1 100644
--- chrome/browser/net/profile_network_context_service.cc
+++ chrome/browser/net/profile_network_context_service.cc
@@ -18,6 +18,7 @@
#include "base/strings/string_split.h"
#include "base/task/post_task.h"
#include "base/task/thread_pool.h"
+#include "cef/libcef/features/features.h"
+#include "cef/libcef/features/chrome_cef.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/content_settings/cookie_settings_factory.h"
#include "chrome/browser/content_settings/host_content_settings_map_factory.h"
@@ -661,9 +662,22 @@ void ProfileNetworkContextService::ConfigureNetworkContextParamsInternal(
@@ -661,9 +662,23 @@ void ProfileNetworkContextService::ConfigureNetworkContextParamsInternal(
network_context_params->cookie_manager_params =
CreateCookieManagerParams(profile_, *cookie_settings_);
@ -18,8 +18,8 @@ index 75a5ee192358..bc97cbf684c0 100644
+
// Configure on-disk storage for non-OTR profiles. OTR profiles just use
// default behavior (in memory storage, default sizes).
if (!in_memory) {
+#if BUILDFLAG(ENABLE_CEF)
- if (!in_memory) {
+ if (!in_memory && cef::IsCefRuntimeEnabled()) {
+ PrefService* prefs = profile_->GetPrefs();
+ // Configure the HTTP cache path and size.
+ const base::FilePath& base_cache_path =
@ -29,18 +29,22 @@ index 75a5ee192358..bc97cbf684c0 100644
+ base_cache_path.Append(chrome::kCacheDirname);
+ network_context_params->http_cache_max_size =
+ prefs->GetInteger(prefs::kDiskCacheSize);
+#else
+ }
+
+ if (!in_memory && !cef::IsCefRuntimeEnabled()) {
PrefService* local_state = g_browser_process->local_state();
// Configure the HTTP cache path and size.
base::FilePath base_cache_path;
@@ -676,6 +690,7 @@ void ProfileNetworkContextService::ConfigureNetworkContextParamsInternal(
@@ -676,7 +691,9 @@ void ProfileNetworkContextService::ConfigureNetworkContextParamsInternal(
base_cache_path.Append(chrome::kCacheDirname);
network_context_params->http_cache_max_size =
local_state->GetInteger(prefs::kDiskCacheSize);
+#endif
+ }
+ if (!in_memory) {
// Currently this just contains HttpServerProperties, but that will likely
// change.
network_context_params->http_server_properties_path =
diff --git chrome/browser/profiles/profile.h chrome/browser/profiles/profile.h
index a48ead96b3f7..967a5975c330 100644
--- chrome/browser/profiles/profile.h

View File

@ -9,6 +9,7 @@
#endif
#include "include/base/cef_logging.h"
#include "include/cef_command_line.h"
#if defined(CEF_X11)
namespace {
@ -52,9 +53,18 @@ int main(int argc, char* argv[]) {
XSetIOErrorHandler(XIOErrorHandlerImpl);
#endif
// Parse command-line arguments for use in this method.
CefRefPtr<CefCommandLine> command_line = CefCommandLine::CreateCommandLine();
command_line->InitFromArgv(argc, argv);
// Specify CEF global settings here.
CefSettings settings;
if (command_line->HasSwitch("enable-chrome-runtime")) {
// Enable experimental Chrome runtime. See issue #2969 for details.
settings.chrome_runtime = true;
}
// When generating projects with CMake the CEF_USE_SANDBOX value will be defined
// automatically. Pass -DUSE_SANDBOX=OFF to the CMake command-line to disable
// use of the sandbox.

View File

@ -4,6 +4,7 @@
#include <windows.h>
#include "include/cef_command_line.h"
#include "include/cef_sandbox_win.h"
#include "tests/cefsimple/simple_app.h"
@ -51,9 +52,18 @@ int APIENTRY wWinMain(HINSTANCE hInstance,
return exit_code;
}
// Parse command-line arguments for use in this method.
CefRefPtr<CefCommandLine> command_line = CefCommandLine::CreateCommandLine();
command_line->InitFromString(::GetCommandLineW());
// Specify CEF global settings here.
CefSettings settings;
if (command_line->HasSwitch("enable-chrome-runtime")) {
// Enable experimental Chrome runtime. See issue #2969 for details.
settings.chrome_runtime = true;
}
#if !defined(CEF_USE_SANDBOX)
settings.no_sandbox = true;
#endif

View File

@ -85,6 +85,11 @@ void SimpleApp::OnContextInitialized() {
CefRefPtr<CefCommandLine> command_line =
CefCommandLine::GetGlobalCommandLine();
const bool enable_chrome_runtime =
command_line->HasSwitch("enable-chrome-runtime");
if (enable_chrome_runtime)
return;
#if defined(OS_WIN) || defined(OS_LINUX)
// Create the browser using the Views framework if "--use-views" is specified
// via the command-line. Otherwise, create the browser using the native

View File

@ -232,6 +232,10 @@ def GetRecommendedDefaultArgs():
# TODO(cef): Remove this flag once we require a newer host system.
result['fatal_linker_warnings'] = False
# GTK is enabled by default for the Chrome runtime (see issue #2969).
# Disable GTK when building the CEF runtime only (see issue #2014).
result['use_gtk'] = False
return result
@ -266,9 +270,6 @@ def GetRequiredArgs():
# can't be enforced by assert().
result['enable_linux_installer'] = False
# Build without GTK dependencies (see issue #2014).
result['use_gtk'] = False
if platform == 'macosx':
# Always generate dSYM files. The make_distrib script will fail if
# enable_dsyms=true is not explicitly set when is_official_build=false.