chrome: Add callback for already running app relaunch (fixes #3609)

Adds a new CefBrowserProcessHandler::OnAlreadyRunningAppRelaunch
callback for when an already running app is relaunched with the
same CefSettings.root_cache_path.

Client apps should check the CefInitialize() return value for early
exit of the relaunch source process.
This commit is contained in:
Marshall Greenblatt 2023-11-28 20:33:44 -05:00
parent d6af79e7a6
commit a25f89f9e4
45 changed files with 553 additions and 178 deletions

View File

@ -524,6 +524,8 @@ source_set("libcef_static") {
"libcef/browser/chrome/chrome_content_browser_client_cef.h",
"libcef/browser/chrome/chrome_context_menu_handler.cc",
"libcef/browser/chrome/chrome_context_menu_handler.h",
"libcef/browser/chrome/chrome_startup_browser_creator.cc",
"libcef/browser/chrome/chrome_startup_browser_creator.h",
"libcef/browser/chrome_crash_reporter_client_stub.cc",
"libcef/browser/chrome/extensions/chrome_mime_handler_view_guest_delegate_cef.cc",
"libcef/browser/chrome/extensions/chrome_mime_handler_view_guest_delegate_cef.h",

View File

@ -33,7 +33,7 @@
// by hand. See the translator.README.txt file in the tools directory for
// more information.
//
// $hash=9b523fbf312a8a0cb1c743a3c8aca7bc9cc22bbc$
// $hash=692f2719fc029131ce17a7c90abca178daadb63e$
//
#ifndef CEF_INCLUDE_CAPI_CEF_APP_CAPI_H_
@ -133,10 +133,13 @@ CEF_EXPORT int cef_execute_process(const cef_main_args_t* args,
///
/// This function should be called on the main application thread to initialize
/// the CEF browser process. The |application| parameter may be NULL. A return
/// value of true (1) indicates that it succeeded and false (0) indicates that
/// it failed. The |windows_sandbox_info| parameter is only used on Windows and
/// may be NULL (see cef_sandbox_win.h for details).
/// the CEF browser process. The |application| parameter may be NULL. Returns
/// true (1) if initialization succeeds. Returns false (0) if initialization
/// fails or if early exit is desired (for example, due to process singleton
/// relaunch behavior). If this function returns false (0) then the application
/// should exit immediately without calling any other CEF functions. The
/// |windows_sandbox_info| parameter is only used on Windows and may be NULL
/// (see cef_sandbox_win.h for details).
///
CEF_EXPORT int cef_initialize(const cef_main_args_t* args,
const struct _cef_settings_t* settings,
@ -145,7 +148,8 @@ CEF_EXPORT int cef_initialize(const cef_main_args_t* args,
///
/// This function should be called on the main application thread to shut down
/// the CEF browser process before the application exits.
/// the CEF browser process before the application exits. Do not call any other
/// CEF functions after calling this function.
///
CEF_EXPORT void cef_shutdown(void);

View File

@ -33,7 +33,7 @@
// by hand. See the translator.README.txt file in the tools directory for
// more information.
//
// $hash=a146316e075450f0a6f37cb45d14e15e0ac7be08$
// $hash=9e91adb231d67a65ce02294a0806d7effd40d280$
//
#ifndef CEF_INCLUDE_CAPI_CEF_BROWSER_PROCESS_HANDLER_CAPI_H_
@ -106,6 +106,30 @@ typedef struct _cef_browser_process_handler_t {
struct _cef_browser_process_handler_t* self,
struct _cef_command_line_t* command_line);
///
/// Implement this function to provide app-specific behavior when an already
/// running app is relaunched with the same CefSettings.root_cache_path value.
/// For example, activate an existing app window or create a new app window.
/// |command_line| will be read-only. Do not keep a reference to
/// |command_line| outside of this function. Return true (1) if the relaunch
/// is handled or false (0) for default relaunch behavior. Default behavior
/// will create a new default styled Chrome window.
///
/// To avoid cache corruption only a single app instance is allowed to run for
/// a given CefSettings.root_cache_path value. On relaunch the app checks a
/// process singleton lock and then forwards the new launch arguments to the
/// already running app process before exiting early. Client apps should
/// therefore check the cef_initialize() return value for early exit before
/// proceeding.
///
/// This function will be called on the browser process UI thread. Currently
/// only used with the chrome runtime.
///
int(CEF_CALLBACK* on_already_running_app_relaunch)(
struct _cef_browser_process_handler_t* self,
struct _cef_command_line_t* command_line,
const cef_string_t* current_directory);
///
/// Called from any thread when work has been scheduled for the browser
/// process main (UI) thread. This callback is used in combination with

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 "09b1cc5ff57703ab04bd555c4b24e8bc7c660cb6"
#define CEF_API_HASH_UNIVERSAL "bbdc07e7c5ed2ae5398efdebdd1ed08801bc91ab"
#if defined(OS_WIN)
#define CEF_API_HASH_PLATFORM "64478d96e4841bd34db245d65d390f2d25759e5e"
#define CEF_API_HASH_PLATFORM "002e3391fd68b0a444dbb6cd1b2a19a4c181d935"
#elif defined(OS_MAC)
#define CEF_API_HASH_PLATFORM "8596f11f53a9100d69757d82208bb3d89d5bf524"
#define CEF_API_HASH_PLATFORM "3e4f2433692dc8bb779314dce84b81d81d39d2c2"
#elif defined(OS_LINUX)
#define CEF_API_HASH_PLATFORM "2f53b2bbce606c42c0c462be1b1e16199962d6b7"
#define CEF_API_HASH_PLATFORM "4e707370d08d4639c41e7c8aa8027c4a6090eace"
#endif
#ifdef __cplusplus

View File

@ -67,10 +67,13 @@ int CefExecuteProcess(const CefMainArgs& args,
///
/// This function should be called on the main application thread to initialize
/// the CEF browser process. The |application| parameter may be empty. A return
/// value of true indicates that it succeeded and false indicates that it
/// failed. The |windows_sandbox_info| parameter is only used on Windows and may
/// be NULL (see cef_sandbox_win.h for details).
/// the CEF browser process. The |application| parameter may be empty. Returns
/// true if initialization succeeds. Returns false if initialization fails or if
/// early exit is desired (for example, due to process singleton relaunch
/// behavior). If this function returns false then the application should exit
/// immediately without calling any other CEF functions. The
/// |windows_sandbox_info| parameter is only used on Windows and may be NULL
/// (see cef_sandbox_win.h for details).
///
/*--cef(api_hash_check,optional_param=application,
optional_param=windows_sandbox_info)--*/
@ -81,7 +84,8 @@ bool CefInitialize(const CefMainArgs& args,
///
/// This function should be called on the main application thread to shut down
/// the CEF browser process before the application exits.
/// the CEF browser process before the application exits. Do not call any
/// other CEF functions after calling this function.
///
/*--cef()--*/
void CefShutdown();

View File

@ -97,6 +97,32 @@ class CefBrowserProcessHandler : public virtual CefBaseRefCounted {
virtual void OnBeforeChildProcessLaunch(
CefRefPtr<CefCommandLine> command_line) {}
///
/// Implement this method to provide app-specific behavior when an already
/// running app is relaunched with the same CefSettings.root_cache_path value.
/// For example, activate an existing app window or create a new app window.
/// |command_line| will be read-only. Do not keep a reference to
/// |command_line| outside of this method. Return true if the relaunch is
/// handled or false for default relaunch behavior. Default behavior will
/// create a new default styled Chrome window.
///
/// To avoid cache corruption only a single app instance is allowed to run for
/// a given CefSettings.root_cache_path value. On relaunch the app checks a
/// process singleton lock and then forwards the new launch arguments to the
/// already running app process before exiting early. Client apps should
/// therefore check the CefInitialize() return value for early exit before
/// proceeding.
///
/// This method will be called on the browser process UI thread. Currently
/// only used with the chrome runtime.
///
/*--cef(optional_param=current_directory)--*/
virtual bool OnAlreadyRunningAppRelaunch(
CefRefPtr<CefCommandLine> command_line,
const CefString& current_directory) {
return false;
}
///
/// Called from any thread when work has been scheduled for the browser
/// process main (UI) thread. This callback is used in combination with

View File

@ -5,6 +5,7 @@
#include "libcef/browser/chrome/chrome_browser_main_extra_parts_cef.h"
#include "libcef/browser/chrome/chrome_context_menu_handler.h"
#include "libcef/browser/chrome/chrome_startup_browser_creator.h"
#include "libcef/browser/context.h"
#include "libcef/browser/file_dialog_runner.h"
#include "libcef/browser/net/chrome_scheme_handler.h"
@ -13,6 +14,10 @@
#include "base/task/thread_pool.h"
#include "chrome/browser/profiles/profile.h"
#if BUILDFLAG(IS_LINUX)
#include "base/linux_util.h"
#endif
#if BUILDFLAG(IS_WIN)
#include "chrome/browser/win/app_icon.h"
#endif
@ -38,6 +43,18 @@ void ChromeBrowserMainExtraPartsCef::PostProfileInit(Profile* profile,
CefRequestContextImpl::CreateGlobalRequestContext(settings);
}
void ChromeBrowserMainExtraPartsCef::PostBrowserStart() {
// Register the callback before ChromeBrowserMainParts::PostBrowserStart
// allows ProcessSingleton to begin processing messages.
startup_browser_creator::RegisterProcessCommandLineCallback();
#if BUILDFLAG(IS_LINUX)
// This may be called indirectly via StartupBrowserCreator::LaunchBrowser.
// Call it here before blocking is disallowed to avoid assertions.
base::GetLinuxDistro();
#endif
}
void ChromeBrowserMainExtraPartsCef::PreMainMessageLoopRun() {
background_task_runner_ = base::ThreadPool::CreateSingleThreadTaskRunner(
{base::TaskPriority::BEST_EFFORT,

View File

@ -42,6 +42,7 @@ class ChromeBrowserMainExtraPartsCef : public ChromeBrowserMainExtraParts {
private:
// ChromeBrowserMainExtraParts overrides.
void PostProfileInit(Profile* profile, bool is_initial_profile) override;
void PostBrowserStart() override;
void PreMainMessageLoopRun() override;
CefRefPtr<CefRequestContextImpl> global_request_context_;

View File

@ -0,0 +1,43 @@
// Copyright (c) 2023 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/browser/chrome/chrome_startup_browser_creator.h"
#include <tuple>
#include "libcef/browser/browser_context.h"
#include "libcef/common/app_manager.h"
#include "libcef/common/command_line_impl.h"
#include "chrome/browser/ui/startup/startup_browser_creator.h"
namespace startup_browser_creator {
namespace {
bool ProcessCommandLineCallback(const base::CommandLine& command_line,
const base::FilePath& cur_dir) {
bool handled = false;
if (auto app = CefAppManager::Get()->GetApplication()) {
if (auto handler = app->GetBrowserProcessHandler()) {
CefRefPtr<CefCommandLineImpl> commandLinePtr(
new CefCommandLineImpl(command_line));
handled = handler->OnAlreadyRunningAppRelaunch(commandLinePtr.get(),
cur_dir.value());
std::ignore = commandLinePtr->Detach(nullptr);
}
}
return handled;
}
} // namespace
void RegisterProcessCommandLineCallback() {
StartupBrowserCreator::RegisterProcessCommandLineCallback(
base::BindRepeating(&ProcessCommandLineCallback));
}
} // namespace startup_browser_creator

View File

@ -0,0 +1,16 @@
// Copyright (c) 2023 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_BROWSER_CHROME_CHROME_STARTUP_BROWSER_CREATOR_H_
#define CEF_LIBCEF_BROWSER_CHROME_CHROME_STARTUP_BROWSER_CREATOR_H_
#pragma once
namespace startup_browser_creator {
// Register the process launch command line callback.
void RegisterProcessCommandLineCallback();
} // namespace startup_browser_creator
#endif // CEF_LIBCEF_BROWSER_CHROME_CHROME_STARTUP_BROWSER_CREATOR_H_

View File

@ -307,8 +307,15 @@ bool CefInitialize(const CefMainArgs& args,
g_context = new CefContext();
// Initialize the global context.
return g_context->Initialize(args, settings, application,
windows_sandbox_info);
if (!g_context->Initialize(args, settings, application,
windows_sandbox_info)) {
// Initialization failed. Delete the global context object.
delete g_context;
g_context = nullptr;
return false;
}
return true;
}
void CefShutdown() {
@ -469,10 +476,16 @@ bool CefContext::Initialize(const CefMainArgs& args,
main_runner_.reset(new CefMainRunner(settings_.multi_threaded_message_loop,
settings_.external_message_pump));
return main_runner_->Initialize(
&settings_, application, args, windows_sandbox_info, &initialized_,
base::BindOnce(&CefContext::OnContextInitialized,
base::Unretained(this)));
if (!main_runner_->Initialize(
&settings_, application, args, windows_sandbox_info, &initialized_,
base::BindOnce(&CefContext::OnContextInitialized,
base::Unretained(this)))) {
shutting_down_ = true;
FinalizeShutdown();
return false;
}
return true;
}
void CefContext::RunMessageLoop() {

View File

@ -21,6 +21,7 @@
#include "base/synchronization/lock.h"
#include "base/synchronization/waitable_event.h"
#include "base/threading/thread.h"
#include "chrome/common/chrome_result_codes.h"
#include "components/crash/core/app/crash_switches.h"
#include "content/app/content_main_runner_impl.h"
#include "content/browser/scheduler/browser_task_executor.h"
@ -227,15 +228,21 @@ bool CefMainRunner::Initialize(CefSettings* settings,
settings->chrome_runtime ? RuntimeType::CHROME : RuntimeType::ALLOY, this,
settings, application);
const int exit_code =
int exit_code =
ContentMainInitialize(args, windows_sandbox_info, &settings->no_sandbox);
if (exit_code >= 0) {
DCHECK(false) << "ContentMainInitialize failed";
LOG(ERROR) << "ContentMainInitialize failed with exit code " << exit_code;
return false;
}
if (!ContentMainRun(initialized, std::move(context_initialized))) {
DCHECK(false) << "ContentMainRun failed";
exit_code = ContentMainRun(initialized, std::move(context_initialized));
if (exit_code != content::RESULT_CODE_NORMAL_EXIT) {
// Some exit codes are used to exit early, but are otherwise a normal
// result. Don't log for those codes.
if (!chrome::IsNormalResultCode(
static_cast<chrome::ResultCode>(exit_code))) {
LOG(ERROR) << "ContentMainRun failed with exit code " << exit_code;
}
return false;
}
@ -383,10 +390,12 @@ int CefMainRunner::ContentMainInitialize(const CefMainArgs& args,
main_runner_.get());
}
bool CefMainRunner::ContentMainRun(bool* initialized,
base::OnceClosure context_initialized) {
int CefMainRunner::ContentMainRun(bool* initialized,
base::OnceClosure context_initialized) {
main_delegate_->BeforeMainThreadRun(multi_threaded_message_loop_);
int exit_code = -1;
if (multi_threaded_message_loop_) {
// Detach the CommandLine from the main thread so that it can be
// attached and modified from the UI thread going forward.
@ -397,14 +406,15 @@ bool CefMainRunner::ContentMainRun(bool* initialized,
base::WaitableEvent::InitialState::NOT_SIGNALED);
if (!CreateUIThread(base::BindOnce(
[](CefMainRunner* runner, base::WaitableEvent* event) {
[](CefMainRunner* runner, base::WaitableEvent* event,
int* exit_code) {
runner->main_delegate_->BeforeUIThreadInitialize();
content::ContentMainRun(runner->main_runner_.get());
*exit_code = content::ContentMainRun(runner->main_runner_.get());
event->Signal();
},
base::Unretained(this),
base::Unretained(&uithread_startup_event)))) {
return false;
base::Unretained(this), base::Unretained(&uithread_startup_event),
base::Unretained(&exit_code)))) {
return exit_code;
}
*initialized = true;
@ -414,19 +424,23 @@ bool CefMainRunner::ContentMainRun(bool* initialized,
} else {
*initialized = true;
main_delegate_->BeforeUIThreadInitialize();
content::ContentMainRun(main_runner_.get());
exit_code = content::ContentMainRun(main_runner_.get());
}
if (CEF_CURRENTLY_ON_UIT()) {
OnContextInitialized(std::move(context_initialized));
} else {
// Continue initialization on the UI thread.
CEF_POST_TASK(CEF_UIT, base::BindOnce(&CefMainRunner::OnContextInitialized,
base::Unretained(this),
std::move(context_initialized)));
if (exit_code == content::RESULT_CODE_NORMAL_EXIT) {
// content::ContentMainRun was successful and we're not exiting early.
if (CEF_CURRENTLY_ON_UIT()) {
OnContextInitialized(std::move(context_initialized));
} else {
// Continue initialization on the UI thread.
CEF_POST_TASK(CEF_UIT,
base::BindOnce(&CefMainRunner::OnContextInitialized,
base::Unretained(this),
std::move(context_initialized)));
}
}
return true;
return exit_code;
}
void CefMainRunner::PreBrowserMain() {

View File

@ -59,7 +59,7 @@ class CefMainRunner : public CefMainRunnerHandler {
int ContentMainInitialize(const CefMainArgs& args,
void* windows_sandbox_info,
int* no_sandbox);
bool ContentMainRun(bool* initialized, base::OnceClosure context_initialized);
int ContentMainRun(bool* initialized, base::OnceClosure context_initialized);
// CefMainRunnerHandler methods:
void PreBrowserMain() override;

View File

@ -18,6 +18,11 @@ CefCommandLineImpl::CefCommandLineImpl(base::CommandLine* value,
read_only,
nullptr) {}
CefCommandLineImpl::CefCommandLineImpl(const base::CommandLine& value)
: CefCommandLineImpl(const_cast<base::CommandLine*>(&value),
/*will_delete=*/false,
/*read_only=*/true) {}
bool CefCommandLineImpl::IsValid() {
return !detached();
}

View File

@ -15,10 +15,16 @@
class CefCommandLineImpl
: public CefValueBase<CefCommandLine, base::CommandLine> {
public:
// If |will_delete=false| make sure to call |std::ignore =
// obj->Detach(nullptr);| to invalidate this object when the client should no
// longer be accessing it.
CefCommandLineImpl(base::CommandLine* value,
bool will_delete,
bool read_only);
// Shortcut for |will_delete=false|, |read_only=true|.
explicit CefCommandLineImpl(const base::CommandLine& value);
CefCommandLineImpl(const CefCommandLineImpl&) = delete;
CefCommandLineImpl& operator=(const CefCommandLineImpl&) = delete;

View File

@ -9,7 +9,7 @@
// implementations. See the translator.README.txt file in the tools directory
// for more information.
//
// $hash=5b13f3f4cac21266cab10ca5153ccebe99d6869b$
// $hash=257c836d87c9caa665028dde1ff768569bef816b$
//
#include "libcef_dll/cpptoc/browser_process_handler_cpptoc.h"
@ -79,6 +79,33 @@ void CEF_CALLBACK browser_process_handler_on_before_child_process_launch(
CefCommandLineCToCpp::Wrap(command_line));
}
int CEF_CALLBACK browser_process_handler_on_already_running_app_relaunch(
struct _cef_browser_process_handler_t* self,
struct _cef_command_line_t* command_line,
const cef_string_t* current_directory) {
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
DCHECK(self);
if (!self) {
return 0;
}
// Verify param: command_line; type: refptr_diff
DCHECK(command_line);
if (!command_line) {
return 0;
}
// Unverified params: current_directory
// Execute
bool _retval =
CefBrowserProcessHandlerCppToC::Get(self)->OnAlreadyRunningAppRelaunch(
CefCommandLineCToCpp::Wrap(command_line),
CefString(current_directory));
// Return type: bool
return _retval;
}
void CEF_CALLBACK browser_process_handler_on_schedule_message_pump_work(
struct _cef_browser_process_handler_t* self,
int64_t delay_ms) {
@ -122,6 +149,8 @@ CefBrowserProcessHandlerCppToC::CefBrowserProcessHandlerCppToC() {
browser_process_handler_on_context_initialized;
GetStruct()->on_before_child_process_launch =
browser_process_handler_on_before_child_process_launch;
GetStruct()->on_already_running_app_relaunch =
browser_process_handler_on_already_running_app_relaunch;
GetStruct()->on_schedule_message_pump_work =
browser_process_handler_on_schedule_message_pump_work;
GetStruct()->get_default_client = browser_process_handler_get_default_client;

View File

@ -9,7 +9,7 @@
// implementations. See the translator.README.txt file in the tools directory
// for more information.
//
// $hash=533775387bf1001675aeb94a62bc4ece1eb11125$
// $hash=8a552c517824da5047969cf0ef19a9258596e3b9$
//
#include "libcef_dll/ctocpp/browser_process_handler_ctocpp.h"
@ -79,6 +79,33 @@ void CefBrowserProcessHandlerCToCpp::OnBeforeChildProcessLaunch(
_struct, CefCommandLineCppToC::Wrap(command_line));
}
NO_SANITIZE("cfi-icall")
bool CefBrowserProcessHandlerCToCpp::OnAlreadyRunningAppRelaunch(
CefRefPtr<CefCommandLine> command_line,
const CefString& current_directory) {
cef_browser_process_handler_t* _struct = GetStruct();
if (CEF_MEMBER_MISSING(_struct, on_already_running_app_relaunch)) {
return false;
}
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
// Verify param: command_line; type: refptr_diff
DCHECK(command_line.get());
if (!command_line.get()) {
return false;
}
// Unverified params: current_directory
// Execute
int _retval = _struct->on_already_running_app_relaunch(
_struct, CefCommandLineCppToC::Wrap(command_line),
current_directory.GetStruct());
// Return type: bool
return _retval ? true : false;
}
NO_SANITIZE("cfi-icall")
void CefBrowserProcessHandlerCToCpp::OnScheduleMessagePumpWork(
int64_t delay_ms) {

View File

@ -9,7 +9,7 @@
// implementations. See the translator.README.txt file in the tools directory
// for more information.
//
// $hash=5dd3fc70331d85a1c7ce5e402bc1e2f050fbe467$
// $hash=d70cd8684eceea74a617559d5573b1875392cfaf$
//
#ifndef CEF_LIBCEF_DLL_CTOCPP_BROWSER_PROCESS_HANDLER_CTOCPP_H_
@ -41,6 +41,8 @@ class CefBrowserProcessHandlerCToCpp
void OnContextInitialized() override;
void OnBeforeChildProcessLaunch(
CefRefPtr<CefCommandLine> command_line) override;
bool OnAlreadyRunningAppRelaunch(CefRefPtr<CefCommandLine> command_line,
const CefString& current_directory) override;
void OnScheduleMessagePumpWork(int64_t delay_ms) override;
CefRefPtr<CefClient> GetDefaultClient() override;
};

View File

@ -279,6 +279,11 @@ patches = [
# https://github.com/chromiumembedded/cef/issues/3581
'name': 'chrome_browser_policy',
},
{
# Support override of Chrome process singleton behavior.
# https://github.com/chromiumembedded/cef/issues/3609
'name': 'chrome_browser_startup',
},
{
# alloy: Don't initialize ExtensionSystemFactory when extensions are
# disabled.

View File

@ -1,5 +1,5 @@
diff --git chrome/browser/BUILD.gn chrome/browser/BUILD.gn
index bce36d7ffb408..33fdb680fb20a 100644
index bce36d7ffb408..3e8fd566a375c 100644
--- chrome/browser/BUILD.gn
+++ chrome/browser/BUILD.gn
@@ -11,6 +11,7 @@ import("//build/config/compiler/pgo/pgo.gni")
@ -10,17 +10,7 @@ index bce36d7ffb408..33fdb680fb20a 100644
import("//chrome/browser/buildflags.gni")
import("//chrome/browser/downgrade/buildflags.gni")
import("//chrome/common/features.gni")
@@ -110,7 +111,8 @@ buildflag_header("buildflags") {
# Android and ChromeOS don't support multiple browser processes, so they don't
# employ ProcessSingleton.
- if (is_android || is_chromeos) {
+ # Also disable for CEF (see issue #3609).
+ if (is_android || is_chromeos || enable_cef) {
flags += [ "ENABLE_PROCESS_SINGLETON=0" ]
} else {
flags += [ "ENABLE_PROCESS_SINGLETON=1" ]
@@ -2073,6 +2075,7 @@ static_library("browser") {
@@ -2073,6 +2074,7 @@ static_library("browser") {
"//build/config/chromebox_for_meetings:buildflags",
"//build/config/compiler:compiler_buildflags",
"//cc",
@ -28,7 +18,7 @@ index bce36d7ffb408..33fdb680fb20a 100644
"//chrome:extra_resources",
"//chrome:resources",
"//chrome:strings",
@@ -2729,6 +2732,10 @@ static_library("browser") {
@@ -2729,6 +2731,10 @@ static_library("browser") {
]
}
@ -39,37 +29,3 @@ index bce36d7ffb408..33fdb680fb20a 100644
if (is_android) {
sources += [
"accessibility/accessibility_prefs/android/accessibility_prefs_controller.cc",
diff --git chrome/browser/browser_process_platform_part_win.cc chrome/browser/browser_process_platform_part_win.cc
index 66fa1aa8b10b3..9b506f6d153ae 100644
--- chrome/browser/browser_process_platform_part_win.cc
+++ chrome/browser/browser_process_platform_part_win.cc
@@ -9,6 +9,7 @@
BrowserProcessPlatformPart::BrowserProcessPlatformPart() = default;
BrowserProcessPlatformPart::~BrowserProcessPlatformPart() = default;
+#if BUILDFLAG(ENABLE_PROCESS_SINGLETON)
void BrowserProcessPlatformPart::OnBrowserLaunch() {
if constexpr (kShouldRecordActiveUse) {
if (!did_run_updater_) {
@@ -16,3 +17,4 @@ void BrowserProcessPlatformPart::OnBrowserLaunch() {
}
}
}
+#endif // BUILDFLAG(ENABLE_PROCESS_SINGLETON)
diff --git chrome/browser/browser_process_platform_part_win.h chrome/browser/browser_process_platform_part_win.h
index fc4b9808f3f6e..92cef9459811f 100644
--- chrome/browser/browser_process_platform_part_win.h
+++ chrome/browser/browser_process_platform_part_win.h
@@ -18,10 +18,12 @@ class BrowserProcessPlatformPart : public BrowserProcessPlatformPartBase {
~BrowserProcessPlatformPart() override;
// BrowserProcessPlatformPartBase:
+#if BUILDFLAG(ENABLE_PROCESS_SINGLETON)
void OnBrowserLaunch() override;
private:
absl::optional<DidRunUpdater> did_run_updater_;
+#endif // BUILDFLAG(ENABLE_PROCESS_SINGLETON)
};
#endif // CHROME_BROWSER_BROWSER_PROCESS_PLATFORM_PART_WIN_H_

View File

@ -0,0 +1,70 @@
diff --git chrome/browser/ui/startup/startup_browser_creator.cc chrome/browser/ui/startup/startup_browser_creator.cc
index cef85a137d3e2..985d716ec7549 100644
--- chrome/browser/ui/startup/startup_browser_creator.cc
+++ chrome/browser/ui/startup/startup_browser_creator.cc
@@ -578,6 +578,14 @@ void OpenNewWindowForFirstRun(
is_first_run, std::move(launch_mode_recorder));
}
#endif // BUILDFLAG(IS_CHROMEOS_LACROS) || BUILDFLAG(ENABLE_DICE_SUPPORT)
+
+StartupBrowserCreator::ProcessCommandLineCallback*
+GetProcessCommandLineCallback() {
+ static base::NoDestructor<StartupBrowserCreator::ProcessCommandLineCallback>
+ callback;
+ return callback.get();
+}
+
} // namespace
StartupProfileMode StartupProfileModeFromReason(
@@ -1441,6 +1449,12 @@ void StartupBrowserCreator::ProcessCommandLineWithProfile(
{profile, mode}, last_opened_profiles);
}
+// static
+void StartupBrowserCreator::RegisterProcessCommandLineCallback(
+ ProcessCommandLineCallback cb) {
+ *GetProcessCommandLineCallback() = cb;
+}
+
// static
void StartupBrowserCreator::ProcessCommandLineAlreadyRunning(
const base::CommandLine& command_line,
@@ -1450,6 +1464,11 @@ void StartupBrowserCreator::ProcessCommandLineAlreadyRunning(
return;
}
+ auto* cb = GetProcessCommandLineCallback();
+ if (!cb->is_null() && cb->Run(command_line, cur_dir)) {
+ return;
+ }
+
Profile* profile = nullptr;
StartupProfileMode mode =
StartupProfileModeFromReason(profile_path_info.reason);
diff --git chrome/browser/ui/startup/startup_browser_creator.h chrome/browser/ui/startup/startup_browser_creator.h
index e22ea9b782910..68724228e79f5 100644
--- chrome/browser/ui/startup/startup_browser_creator.h
+++ chrome/browser/ui/startup/startup_browser_creator.h
@@ -9,6 +9,7 @@
#include <vector>
#include "base/files/file_path.h"
+#include "base/functional/callback.h"
#include "base/gtest_prod_util.h"
#include "base/memory/raw_ptr.h"
#include "build/build_config.h"
@@ -136,6 +137,13 @@ class StartupBrowserCreator {
StartupProfileInfo profile_info,
const Profiles& last_opened_profiles);
+ // Registers a callback that will be executed each time
+ // ProcessCommandLineAlreadyRunning is called.
+ using ProcessCommandLineCallback = base::RepeatingCallback<bool(
+ const base::CommandLine& command_line,
+ const base::FilePath& cur_dir)>;
+ static void RegisterProcessCommandLineCallback(ProcessCommandLineCallback cb);
+
// This function performs command-line handling and is invoked only after
// start up (for example when we get a start request for another process).
// |command_line| holds the command line we need to process.

View File

@ -1,5 +1,5 @@
diff --git chrome/app/chrome_main_delegate.cc chrome/app/chrome_main_delegate.cc
index dc84cbd4c97d1..b8a1dd5a19be1 100644
index dc84cbd4c97d1..696af79e6cec5 100644
--- chrome/app/chrome_main_delegate.cc
+++ chrome/app/chrome_main_delegate.cc
@@ -41,6 +41,7 @@
@ -30,6 +30,15 @@ index dc84cbd4c97d1..b8a1dd5a19be1 100644
absl::optional<int> ChromeMainDelegate::PostEarlyInitialization(
InvokedIn invoked_in) {
DCHECK(base::ThreadPoolInstance::Get());
@@ -782,7 +789,7 @@ absl::optional<int> ChromeMainDelegate::PostEarlyInitialization(
// future session's metrics.
DeferBrowserMetrics(user_data_dir);
-#if BUILDFLAG(IS_WIN)
+#if BUILDFLAG(IS_WIN) && !BUILDFLAG(ENABLE_CEF)
// In the case the process is not the singleton process, the uninstall tasks
// need to be executed here. A window will be displayed asking to close all
// running instances.
@@ -946,7 +953,8 @@ absl::optional<int> ChromeMainDelegate::PostEarlyInitialization(
if (base::FeatureList::IsEnabled(
@ -126,7 +135,7 @@ index 176b6248f18e8..1360e8c209eba 100644
#if BUILDFLAG(IS_CHROMEOS_LACROS)
std::unique_ptr<chromeos::LacrosService> lacros_service_;
diff --git chrome/browser/chrome_browser_main.cc chrome/browser/chrome_browser_main.cc
index e819129536dc0..d0f1e684ae019 100644
index e819129536dc0..e9287f6e03a88 100644
--- chrome/browser/chrome_browser_main.cc
+++ chrome/browser/chrome_browser_main.cc
@@ -52,6 +52,7 @@
@ -137,6 +146,15 @@ index e819129536dc0..d0f1e684ae019 100644
#include "chrome/browser/about_flags.h"
#include "chrome/browser/active_use_util.h"
#include "chrome/browser/after_startup_task_utils.h"
@@ -486,7 +487,7 @@ void ProcessSingletonNotificationCallbackImpl(
return;
}
-#if BUILDFLAG(IS_WIN)
+#if BUILDFLAG(IS_WIN) && !BUILDFLAG(ENABLE_CEF)
// The uninstall command-line switch is handled by the origin process; see
// ChromeMainDelegate::PostEarlyInitialization(...). The other process won't
// be able to become the singleton process and will display a window asking
@@ -774,7 +775,7 @@ int ChromeBrowserMainParts::PreEarlyInitialization() {
return content::RESULT_CODE_NORMAL_EXIT;
}

View File

@ -11,6 +11,8 @@
#include "include/cef_file_util.h"
#include "tests/cefclient/browser/client_prefs.h"
#include "tests/cefclient/browser/default_client_handler.h"
#include "tests/cefclient/browser/main_context.h"
#include "tests/cefclient/browser/root_window_manager.h"
#include "tests/shared/common/client_switches.h"
namespace client {
@ -62,6 +64,20 @@ class ClientBrowserDelegate : public ClientAppBrowser::Delegate {
}
}
bool OnAlreadyRunningAppRelaunch(
CefRefPtr<ClientAppBrowser> app,
CefRefPtr<CefCommandLine> command_line,
const CefString& current_directory) override {
// Create a new root window based on |command_line|.
auto config = std::make_unique<RootWindowConfig>(command_line->Copy());
MainContext::Get()->GetRootWindowManager()->CreateRootWindow(
std::move(config));
// Relaunch was handled.
return true;
}
CefRefPtr<CefClient> GetDefaultClient(
CefRefPtr<ClientAppBrowser> app) override {
// Default client handler for unmanaged browser windows. Used with the

View File

@ -1423,12 +1423,15 @@ bool ClientHandler::CreatePopupWindow(CefRefPtr<CefBrowser> browser,
CefBrowserSettings& settings) {
CEF_REQUIRE_UI_THREAD();
auto parent_window = RootWindow::GetForBrowser(browser->GetIdentifier());
CHECK(parent_window);
// The popup browser will be parented to a new native window.
// Don't show URL bar and navigation buttons on DevTools windows.
// May return nullptr if UseDefaultPopup() returns true.
return !!MainContext::Get()->GetRootWindowManager()->CreateRootWindowAsPopup(
with_controls_ && !is_devtools, is_osr_, popupFeatures, windowInfo,
client, settings);
parent_window, with_controls_ && !is_devtools, is_osr_, popupFeatures,
windowInfo, client, settings);
}
void ClientHandler::NotifyBrowserCreated(CefRefPtr<CefBrowser> browser) {

View File

@ -10,6 +10,7 @@
#include "include/base/cef_macros.h"
#include "include/base/cef_ref_counted.h"
#include "include/cef_command_line.h"
#include "include/internal/cef_types_wrappers.h"
#include "tests/cefclient/browser/osr_renderer_settings.h"
@ -24,6 +25,9 @@ class MainContext {
// Returns the singleton instance of this object.
static MainContext* Get();
// Returns the global command-line.
virtual CefRefPtr<CefCommandLine> GetCommandLine() = 0;
// Returns the full path to the console log file.
virtual std::string GetConsoleLogPath() = 0;
@ -33,8 +37,8 @@ class MainContext {
// Returns the app working directory including trailing path separator.
virtual std::string GetAppWorkingDirectory() = 0;
// Returns the main application URL.
virtual std::string GetMainURL() = 0;
// Returns the main application URL based on |command_line| and global state.
virtual std::string GetMainURL(CefRefPtr<CefCommandLine> command_line) = 0;
// Returns the background color.
virtual cef_color_t GetBackgroundColor() = 0;

View File

@ -46,14 +46,6 @@ MainContextImpl::MainContextImpl(CefRefPtr<CefCommandLine> command_line,
terminate_when_all_windows_closed_(terminate_when_all_windows_closed) {
DCHECK(command_line_.get());
// Set the main URL.
if (command_line_->HasSwitch(switches::kUrl)) {
main_url_ = command_line_->GetSwitchValue(switches::kUrl);
}
if (main_url_.empty()) {
main_url_ = kDefaultUrl;
}
// Whether windowless (off-screen) rendering will be used.
use_windowless_rendering_ =
command_line_->HasSwitch(switches::kOffScreenRenderingEnabled);
@ -127,12 +119,6 @@ MainContextImpl::MainContextImpl(CefRefPtr<CefCommandLine> command_line,
}
#endif // !(defined(OS_WIN) || defined(OS_LINUX))
if (use_views_ && command_line->HasSwitch(switches::kHideFrame) &&
!command_line_->HasSwitch(switches::kUrl)) {
// Use the draggable regions test as the default URL for frameless windows.
main_url_ = test_runner::GetTestURL("draggable");
}
if (command_line_->HasSwitch(switches::kBackgroundColor)) {
// Parse the background color value.
background_color_ =
@ -159,12 +145,28 @@ MainContextImpl::~MainContextImpl() {
DCHECK(!initialized_ || shutdown_);
}
CefRefPtr<CefCommandLine> MainContextImpl::GetCommandLine() {
return command_line_;
}
std::string MainContextImpl::GetConsoleLogPath() {
return GetAppWorkingDirectory() + "console.log";
}
std::string MainContextImpl::GetMainURL() {
return main_url_;
std::string MainContextImpl::GetMainURL(
CefRefPtr<CefCommandLine> command_line) {
if (!command_line) {
command_line = command_line_;
}
std::string main_url = kDefaultUrl;
if (command_line->HasSwitch(switches::kUrl)) {
main_url = command_line->GetSwitchValue(switches::kUrl);
} else if (use_views_ && command_line->HasSwitch(switches::kHideFrame)) {
// Use the draggable regions test as the default URL for frameless windows.
main_url = test_runner::GetTestURL("draggable");
}
return main_url;
}
cef_color_t MainContextImpl::GetBackgroundColor() {

View File

@ -23,10 +23,11 @@ class MainContextImpl : public MainContext {
bool terminate_when_all_windows_closed);
// MainContext members.
CefRefPtr<CefCommandLine> GetCommandLine() override;
std::string GetConsoleLogPath() override;
std::string GetDownloadPath(const std::string& file_name) override;
std::string GetAppWorkingDirectory() override;
std::string GetMainURL() override;
std::string GetMainURL(CefRefPtr<CefCommandLine> command_line) override;
cef_color_t GetBackgroundColor() override;
bool UseChromeRuntime() override;
bool UseChromeRuntimeNative() override;
@ -69,7 +70,6 @@ class MainContextImpl : public MainContext {
bool initialized_ = false;
bool shutdown_ = false;
std::string main_url_;
cef_color_t background_color_ = 0;
cef_color_t browser_background_color_ = 0;
bool use_windowless_rendering_;

View File

@ -8,10 +8,14 @@
#include "tests/cefclient/browser/main_context.h"
#include "tests/cefclient/browser/root_window_manager.h"
#include "tests/shared/common/client_switches.h"
namespace client {
RootWindowConfig::RootWindowConfig() : url(MainContext::Get()->GetMainURL()) {}
RootWindowConfig::RootWindowConfig(CefRefPtr<CefCommandLine> cmd)
: command_line(cmd ? cmd : MainContext::Get()->GetCommandLine()),
with_controls(!command_line->HasSwitch(switches::kHideControls)),
url(MainContext::Get()->GetMainURL(command_line)) {}
RootWindow::RootWindow() : delegate_(nullptr) {}

View File

@ -13,6 +13,7 @@
#include "include/base/cef_callback_forward.h"
#include "include/base/cef_ref_counted.h"
#include "include/cef_browser.h"
#include "include/cef_command_line.h"
#include "include/views/cef_window.h"
#include "tests/cefclient/browser/client_types.h"
#include "tests/cefclient/browser/image_cache.h"
@ -35,7 +36,13 @@ enum class WindowType {
// Used to configure how a RootWindow is created.
struct RootWindowConfig {
RootWindowConfig();
// |command_line| will be non-nullptr when used for new window creation
// via OnAlreadyRunningAppRelaunch (chrome runtime only). Otherwise, the
// global command-line will be used.
RootWindowConfig(CefRefPtr<CefCommandLine> command_line = nullptr);
// Associated command-line.
CefRefPtr<CefCommandLine> command_line;
// Configure the window type.
WindowType window_type = WindowType::NORMAL;
@ -59,18 +66,18 @@ struct RootWindowConfig {
// Position of the UI element that triggered the window creation. If |bounds|
// is empty and |source_bounds| is non-empty the new window will be positioned
// relative to |source_bounds|. This is currently only implemented for Views-
// based windows when |initially_hidden| is also true.
// hosted windows when |initially_hidden| is also true.
CefRect source_bounds;
// Requested window show state. Only used when |bounds| is non-empty and
// |initially_hidden| is false.
cef_show_state_t show_state = CEF_SHOW_STATE_NORMAL;
// Parent window. Only used for Views-based windows.
// Parent window. Only used for Views-hosted windows.
CefRefPtr<CefWindow> parent_window;
// Callback to be executed when the window is closed. Will be executed on the
// main thread. This is currently only implemented for Views-based windows.
// main thread. This is currently only implemented for Views-hosted windows.
base::OnceClosure close_callback;
// Initial URL to load.
@ -128,13 +135,19 @@ class RootWindow
// Create a new RootWindow object. This method may be called on any thread.
// Use RootWindowManager::CreateRootWindow() or CreateRootWindowAsPopup()
// instead of calling this method directly. |use_views| will be true if the
// Views framework should be used.
static scoped_refptr<RootWindow> Create(bool use_views);
// Views framework should be used. |parent_window| will be non-nullptr for
// popup browsers with a RootWindow parent (on the UI thread only).
static scoped_refptr<RootWindow> Create(
bool use_views,
scoped_refptr<RootWindow> parent_window);
// Returns the RootWindow associated with the specified |browser_id|. Must be
// called on the main thread.
static scoped_refptr<RootWindow> GetForBrowser(int browser_id);
// Returns true if the RootWindow is Views-hosted.
virtual bool IsViewsHosted() const { return false; }
// Initialize as a normal window. This will create and show a native window
// hosting a single browser instance. This method may be called on any thread.
// |delegate| must be non-nullptr and outlive this object.

View File

@ -17,9 +17,13 @@
namespace client {
// static
scoped_refptr<RootWindow> RootWindow::Create(bool use_views) {
scoped_refptr<RootWindow> RootWindow::Create(
bool use_views,
scoped_refptr<RootWindow> parent_window) {
if (use_views) {
return new RootWindowViews();
CHECK(!parent_window || parent_window->IsViewsHosted());
return new RootWindowViews(
static_cast<RootWindowViews*>(parent_window.get()));
}
#if defined(OS_WIN)

View File

@ -62,7 +62,8 @@ class ClientRequestContextHandler : public CefRequestContextHandler,
// Allow the startup URL to create popups that bypass the popup blocker.
// For example, via Tests > New Popup from the top menu. This applies for
// for the Chrome runtime only.
const auto& startup_url = MainContext::Get()->GetMainURL();
const auto& startup_url =
MainContext::Get()->GetMainURL(/*command_line=*/nullptr);
request_context->SetContentSetting(startup_url, startup_url,
CEF_CONTENT_SETTING_TYPE_POPUPS,
CEF_CONTENT_SETTING_VALUE_ALLOW);
@ -121,8 +122,8 @@ scoped_refptr<RootWindow> RootWindowManager::CreateRootWindow(
CefBrowserSettings settings;
MainContext::Get()->PopulateBrowserSettings(&settings);
scoped_refptr<RootWindow> root_window =
RootWindow::Create(MainContext::Get()->UseViews());
scoped_refptr<RootWindow> root_window = RootWindow::Create(
MainContext::Get()->UseViews(), /*parent_window=*/nullptr);
root_window->Init(this, std::move(config), settings);
// Store a reference to the root window on the main thread.
@ -132,6 +133,7 @@ scoped_refptr<RootWindow> RootWindowManager::CreateRootWindow(
}
scoped_refptr<RootWindow> RootWindowManager::CreateRootWindowAsPopup(
scoped_refptr<RootWindow> parent_window,
bool with_controls,
bool with_osr,
const CefPopupFeatures& popupFeatures,
@ -155,8 +157,11 @@ scoped_refptr<RootWindow> RootWindowManager::CreateRootWindowAsPopup(
temp_window_.reset(new TempWindow());
}
const bool use_views = parent_window ? parent_window->IsViewsHosted()
: MainContext::Get()->UseViews();
scoped_refptr<RootWindow> root_window =
RootWindow::Create(MainContext::Get()->UseViews());
RootWindow::Create(use_views, parent_window);
root_window->InitAsPopup(this, with_controls, with_osr, popupFeatures,
windowInfo, client, settings);

View File

@ -36,6 +36,7 @@ class RootWindowManager : public RootWindow::Delegate {
// This method is called from ClientHandler::CreatePopupWindow() to
// create a new popup or DevTools window. Must be called on the UI thread.
scoped_refptr<RootWindow> CreateRootWindowAsPopup(
scoped_refptr<RootWindow> parent_window,
bool with_controls,
bool with_osr,
const CefPopupFeatures& popupFeatures,

View File

@ -22,7 +22,17 @@ static const char* kDefaultImageCache[] = {"menu_icon", "window_icon"};
} // namespace
RootWindowViews::RootWindowViews() = default;
RootWindowViews::RootWindowViews(RootWindowViews* parent_window) {
// |parent_window| will be non-nullptr for popups only.
if (parent_window) {
CEF_REQUIRE_UI_THREAD();
// Initialize |config_| for values that are not passed to InitAsPopup().
config_ = std::make_unique<RootWindowConfig>(
parent_window->config_->command_line);
DCHECK(config_->command_line);
}
}
RootWindowViews::~RootWindowViews() {
REQUIRE_MAIN_THREAD();
@ -38,6 +48,7 @@ void RootWindowViews::Init(RootWindow::Delegate* delegate,
std::unique_ptr<RootWindowConfig> config,
const CefBrowserSettings& settings) {
DCHECK(delegate);
DCHECK(config->command_line);
DCHECK(!config->with_osr); // Windowless rendering is not supported.
DCHECK(!initialized_);
@ -65,7 +76,9 @@ void RootWindowViews::InitAsPopup(RootWindow::Delegate* delegate,
DCHECK(!initialized_);
delegate_ = delegate;
config_ = std::make_unique<RootWindowConfig>();
// |config_| should be created in the constructor.
DCHECK(config_);
config_->with_controls = with_controls;
if (popupFeatures.xSet) {
@ -556,7 +569,7 @@ void RootWindowViews::CreateViewsWindow(
// Create the ViewsWindow. It will show itself after creation.
ViewsWindow::Create(config_->window_type, this, client_handler_, config_->url,
settings, request_context);
settings, request_context, config_->command_line);
}
void RootWindowViews::NotifyViewsWindowDestroyed() {

View File

@ -22,13 +22,16 @@ class RootWindowViews : public RootWindow,
public ClientHandler::Delegate,
public ViewsWindow::Delegate {
public:
// Constructor may be called on any thread.
RootWindowViews();
// Constructor may be called on any thread. |parent_window| will be
// non-nullptr for popup browsers with a RootWindow parent (called on the UI
// thread only).
explicit RootWindowViews(RootWindowViews* parent_window);
~RootWindowViews();
void SetTitlebarHeight(const std::optional<float>& height);
// RootWindow methods:
bool IsViewsHosted() const override { return true; }
void Init(RootWindow::Delegate* delegate,
std::unique_ptr<RootWindowConfig> config,
const CefBrowserSettings& settings) override;

View File

@ -137,13 +137,14 @@ CefRefPtr<ViewsWindow> ViewsWindow::Create(
CefRefPtr<CefClient> client,
const CefString& url,
const CefBrowserSettings& settings,
CefRefPtr<CefRequestContext> request_context) {
CefRefPtr<CefRequestContext> request_context,
CefRefPtr<CefCommandLine> command_line) {
CEF_REQUIRE_UI_THREAD();
DCHECK(delegate);
// Create a new ViewsWindow.
CefRefPtr<ViewsWindow> views_window =
new ViewsWindow(type, delegate, nullptr);
new ViewsWindow(type, delegate, nullptr, command_line);
// Create a new BrowserView.
CefRefPtr<CefBrowserView> browser_view = CefBrowserView::CreateBrowserView(
@ -473,7 +474,7 @@ CefRefPtr<CefBrowserViewDelegate> ViewsWindow::GetDelegateForPopupBrowserView(
// Create a new ViewsWindow for the popup BrowserView.
return new ViewsWindow(
is_devtools ? WindowType::DEVTOOLS : WindowType::NORMAL, popup_delegate,
nullptr);
nullptr, command_line_);
}
bool ViewsWindow::OnPopupBrowserViewCreated(
@ -1037,19 +1038,19 @@ void ViewsWindow::MenuBarExecuteCommand(CefRefPtr<CefMenuModel> menu_model,
ViewsWindow::ViewsWindow(WindowType type,
Delegate* delegate,
CefRefPtr<CefBrowserView> browser_view)
CefRefPtr<CefBrowserView> browser_view,
CefRefPtr<CefCommandLine> command_line)
: type_(type),
delegate_(delegate),
command_line_(command_line),
menu_has_focus_(false),
last_focused_view_(false) {
DCHECK(delegate_);
if (browser_view) {
SetBrowserView(browser_view);
}
CefRefPtr<CefCommandLine> command_line =
CefCommandLine::GetGlobalCommandLine();
const bool is_normal_type = type_ == WindowType::NORMAL;
with_controls_ = is_normal_type && delegate_->WithControls();

View File

@ -34,7 +34,7 @@ namespace client {
typedef std::set<CefRefPtr<CefExtension>> ExtensionSet;
// Implements a CefWindow that hosts a single CefBrowserView and optional
// Views-based controls. All methods must be called on the browser process UI
// Views-hosted controls. All methods must be called on the browser process UI
// thread.
class ViewsWindow : public CefBrowserViewDelegate,
public CefMenuButtonDelegate,
@ -105,7 +105,8 @@ class ViewsWindow : public CefBrowserViewDelegate,
CefRefPtr<CefClient> client,
const CefString& url,
const CefBrowserSettings& settings,
CefRefPtr<CefRequestContext> request_context);
CefRefPtr<CefRequestContext> request_context,
CefRefPtr<CefCommandLine> command_line);
void Show();
void Hide();
@ -213,7 +214,8 @@ class ViewsWindow : public CefBrowserViewDelegate,
// called.
ViewsWindow(WindowType type,
Delegate* delegate,
CefRefPtr<CefBrowserView> browser_view);
CefRefPtr<CefBrowserView> browser_view,
CefRefPtr<CefCommandLine> command_line);
void SetBrowserView(CefRefPtr<CefBrowserView> browser_view);
@ -254,6 +256,7 @@ class ViewsWindow : public CefBrowserViewDelegate,
const WindowType type_;
Delegate* delegate_; // Not owned by this object.
CefRefPtr<CefBrowserView> browser_view_;
CefRefPtr<CefCommandLine> command_line_;
bool frameless_;
bool with_controls_;
bool with_overlay_controls_;

View File

@ -115,8 +115,12 @@ int RunMain(int argc, char* argv[]) {
message_loop.reset(new MainMessageLoopStd);
}
// Initialize CEF.
context->Initialize(main_args, settings, app, nullptr);
// Initialize the CEF browser process. May return false if initialization
// fails or if early exit is desired (for example, due to process singleton
// relaunch behavior).
if (!context->Initialize(main_args, settings, app, nullptr)) {
return 1;
}
// Force Gtk to use Xwayland (in case a Wayland compositor is being used).
gdk_set_allowed_backends("x11");
@ -140,8 +144,6 @@ int RunMain(int argc, char* argv[]) {
auto window_config = std::make_unique<RootWindowConfig>();
window_config->always_on_top =
command_line->HasSwitch(switches::kAlwaysOnTop);
window_config->with_controls =
!command_line->HasSwitch(switches::kHideControls);
window_config->with_osr =
settings.windowless_rendering_enabled ? true : false;

View File

@ -52,11 +52,10 @@ void RemoveMenuItem(NSMenu* menu, SEL action_selector) {
// Receives notifications from the application. Will delete itself when done.
@interface ClientAppDelegate : NSObject <NSApplicationDelegate> {
@private
bool with_controls_;
bool with_osr_;
}
- (id)initWithControls:(bool)with_controls andOsr:(bool)with_osr;
- (id)initWithOsr:(bool)with_osr;
- (void)createApplication:(id)object;
- (void)tryToTerminateApplication:(NSApplication*)app;
- (void)testsItemSelected:(int)command_id;
@ -162,9 +161,8 @@ void RemoveMenuItem(NSMenu* menu, SEL action_selector) {
@implementation ClientAppDelegate
- (id)initWithControls:(bool)with_controls andOsr:(bool)with_osr {
- (id)initWithOsr:(bool)with_osr {
if (self = [super init]) {
with_controls_ = with_controls;
with_osr_ = with_osr;
}
return self;
@ -230,7 +228,6 @@ void RemoveMenuItem(NSMenu* menu, SEL action_selector) {
}
auto window_config = std::make_unique<client::RootWindowConfig>();
window_config->with_controls = with_controls_;
window_config->with_osr = with_osr_;
// Create the first window.
@ -570,16 +567,19 @@ int RunMain(int argc, char* argv[]) {
message_loop.reset(new MainMessageLoopStd);
}
// Initialize CEF.
context->Initialize(main_args, settings, app, nullptr);
// Initialize the CEF browser process. May return false if initialization
// fails or if early exit is desired (for example, due to process singleton
// relaunch behavior).
if (!context->Initialize(main_args, settings, app, nullptr)) {
return 1;
}
// Register scheme handlers.
test_runner::RegisterSchemeHandlers();
// Create the application delegate and window.
ClientAppDelegate* delegate = [[ClientAppDelegate alloc]
initWithControls:!command_line->HasSwitch(switches::kHideControls)
andOsr:settings.windowless_rendering_enabled ? true : false];
initWithOsr:settings.windowless_rendering_enabled ? true : false];
[delegate performSelectorOnMainThread:@selector(createApplication:)
withObject:nil
waitUntilDone:NO];

View File

@ -95,8 +95,12 @@ int RunMain(HINSTANCE hInstance, int nCmdShow) {
message_loop.reset(new MainMessageLoopStd);
}
// Initialize CEF.
context->Initialize(main_args, settings, app, sandbox_info);
// Initialize the CEF browser process. May return false if initialization
// fails or if early exit is desired (for example, due to process singleton
// relaunch behavior).
if (!context->Initialize(main_args, settings, app, sandbox_info)) {
return 1;
}
// Register scheme handlers.
test_runner::RegisterSchemeHandlers();
@ -104,8 +108,6 @@ int RunMain(HINSTANCE hInstance, int nCmdShow) {
auto window_config = std::make_unique<RootWindowConfig>();
window_config->always_on_top =
command_line->HasSwitch(switches::kAlwaysOnTop);
window_config->with_controls =
!command_line->HasSwitch(switches::kHideControls);
window_config->with_osr =
settings.windowless_rendering_enabled ? true : false;

View File

@ -77,8 +77,12 @@ int main(int argc, char* argv[]) {
// CEF has initialized.
CefRefPtr<SimpleApp> app(new SimpleApp);
// Initialize CEF for the browser process.
CefInitialize(main_args, settings, app.get(), nullptr);
// Initialize the CEF browser process. May return false if initialization
// fails or if early exit is desired (for example, due to process singleton
// relaunch behavior).
if (!CefInitialize(main_args, settings, app.get(), nullptr)) {
return 1;
}
// Run the CEF message loop. This will block until CefQuitMessageLoop() is
// called.

View File

@ -159,8 +159,12 @@ int main(int argc, char* argv[]) {
// CEF has initialized.
CefRefPtr<SimpleApp> app(new SimpleApp);
// Initialize CEF for the browser process.
CefInitialize(main_args, settings, app.get(), nullptr);
// Initialize the CEF browser process. May return false if initialization
// fails or if early exit is desired (for example, due to process singleton
// relaunch behavior).
if (!CefInitialize(main_args, settings, app.get(), nullptr)) {
return 1;
}
// Create the application delegate.
NSObject* delegate = [[SimpleAppDelegate alloc] init];

View File

@ -88,8 +88,12 @@ int APIENTRY wWinMain(HINSTANCE hInstance,
// CEF has initialized.
CefRefPtr<SimpleApp> app(new SimpleApp);
// Initialize CEF.
CefInitialize(main_args, settings, app.get(), sandbox_info);
// Initialize the CEF browser process. May return false if initialization
// fails or if early exit is desired (for example, due to process singleton
// relaunch behavior).
if (!CefInitialize(main_args, settings, app.get(), sandbox_info)) {
return 1;
}
// Run the CEF message loop. This will block until CefQuitMessageLoop() is
// called.

View File

@ -31,9 +31,6 @@ namespace {
// 4. FrameNavTestHandler retrieves the URL to load via
// FrameNavExpectationsBrowser::GetMainURL and calls either CreateBrowser
// (for the first navigation) or LoadURL (for the following navigations).
// 5. If the renderer process does not already exist CEF creates it with
// command-line arguments that specify the FrameNavFactoryId via
// FrameNavBrowserTest::OnBeforeChildProcessLaunch.
//
// In the renderer process:
// 6. If the renderer process is newly created FrameNavRendererTest calls

View File

@ -94,11 +94,16 @@ void ClientAppBrowser::OnContextInitialized() {
}
}
void ClientAppBrowser::OnBeforeChildProcessLaunch(
CefRefPtr<CefCommandLine> command_line) {
bool ClientAppBrowser::OnAlreadyRunningAppRelaunch(
CefRefPtr<CefCommandLine> command_line,
const CefString& current_directory) {
for (auto& delegate : delegates_) {
delegate->OnBeforeChildProcessLaunch(this, command_line);
if (delegate->OnAlreadyRunningAppRelaunch(this, command_line,
current_directory)) {
return true;
}
}
return false;
}
void ClientAppBrowser::OnScheduleMessagePumpWork(int64_t delay) {

View File

@ -31,9 +31,12 @@ class ClientAppBrowser : public ClientApp, public CefBrowserProcessHandler {
virtual void OnContextInitialized(CefRefPtr<ClientAppBrowser> app) {}
virtual void OnBeforeChildProcessLaunch(
virtual bool OnAlreadyRunningAppRelaunch(
CefRefPtr<ClientAppBrowser> app,
CefRefPtr<CefCommandLine> command_line) {}
CefRefPtr<CefCommandLine> command_line,
const CefString& current_directory) {
return false;
}
virtual CefRefPtr<CefClient> GetDefaultClient(
CefRefPtr<ClientAppBrowser> app) {
@ -73,8 +76,8 @@ class ClientAppBrowser : public ClientApp, public CefBrowserProcessHandler {
cef_preferences_type_t type,
CefRawPtr<CefPreferenceRegistrar> registrar) override;
void OnContextInitialized() override;
void OnBeforeChildProcessLaunch(
CefRefPtr<CefCommandLine> command_line) override;
bool OnAlreadyRunningAppRelaunch(CefRefPtr<CefCommandLine> command_line,
const CefString& current_directory) override;
void OnScheduleMessagePumpWork(int64_t delay) override;
CefRefPtr<CefClient> GetDefaultClient() override;