mirror of
https://bitbucket.org/chromiumembedded/cef
synced 2025-06-05 21:39:12 +02:00
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:
@@ -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,
|
||||
|
@@ -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_;
|
||||
|
43
libcef/browser/chrome/chrome_startup_browser_creator.cc
Normal file
43
libcef/browser/chrome/chrome_startup_browser_creator.cc
Normal 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
|
16
libcef/browser/chrome/chrome_startup_browser_creator.h
Normal file
16
libcef/browser/chrome/chrome_startup_browser_creator.h
Normal 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_
|
@@ -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() {
|
||||
|
@@ -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() {
|
||||
|
@@ -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;
|
||||
|
Reference in New Issue
Block a user