mirror of
https://bitbucket.org/chromiumembedded/cef
synced 2025-06-05 21:39:12 +02:00
alloy: Add callback for already running app relaunch (fixes #3615)
Executes CefBrowserProcessHandler::OnAlreadyRunningAppRelaunch callback for when an already running app is relaunched with the same CefSettings.root_cache_path. Adds "Root Cache Path" value and related explainer text to chrome://version. Adds a LOG(WARNING) that will be output on startup if CefSettings.root_cache_path is unset in the client app.
This commit is contained in:
@ -33,7 +33,7 @@
|
|||||||
// by hand. See the translator.README.txt file in the tools directory for
|
// by hand. See the translator.README.txt file in the tools directory for
|
||||||
// more information.
|
// more information.
|
||||||
//
|
//
|
||||||
// $hash=9e91adb231d67a65ce02294a0806d7effd40d280$
|
// $hash=dad764dddf92655cc580e0e7e85d3f3c34bdd46d$
|
||||||
//
|
//
|
||||||
|
|
||||||
#ifndef CEF_INCLUDE_CAPI_CEF_BROWSER_PROCESS_HANDLER_CAPI_H_
|
#ifndef CEF_INCLUDE_CAPI_CEF_BROWSER_PROCESS_HANDLER_CAPI_H_
|
||||||
@ -122,8 +122,7 @@ typedef struct _cef_browser_process_handler_t {
|
|||||||
/// therefore check the cef_initialize() return value for early exit before
|
/// therefore check the cef_initialize() return value for early exit before
|
||||||
/// proceeding.
|
/// proceeding.
|
||||||
///
|
///
|
||||||
/// This function will be called on the browser process UI thread. Currently
|
/// This function will be called on the browser process UI thread.
|
||||||
/// only used with the chrome runtime.
|
|
||||||
///
|
///
|
||||||
int(CEF_CALLBACK* on_already_running_app_relaunch)(
|
int(CEF_CALLBACK* on_already_running_app_relaunch)(
|
||||||
struct _cef_browser_process_handler_t* self,
|
struct _cef_browser_process_handler_t* self,
|
||||||
|
@ -113,8 +113,7 @@ class CefBrowserProcessHandler : public virtual CefBaseRefCounted {
|
|||||||
/// therefore check the CefInitialize() return value for early exit before
|
/// therefore check the CefInitialize() return value for early exit before
|
||||||
/// proceeding.
|
/// proceeding.
|
||||||
///
|
///
|
||||||
/// This method will be called on the browser process UI thread. Currently
|
/// This method will be called on the browser process UI thread.
|
||||||
/// only used with the chrome runtime.
|
|
||||||
///
|
///
|
||||||
/*--cef(optional_param=current_directory)--*/
|
/*--cef(optional_param=current_directory)--*/
|
||||||
virtual bool OnAlreadyRunningAppRelaunch(
|
virtual bool OnAlreadyRunningAppRelaunch(
|
||||||
|
@ -279,31 +279,46 @@ typedef struct _cef_settings_t {
|
|||||||
int command_line_args_disabled;
|
int command_line_args_disabled;
|
||||||
|
|
||||||
///
|
///
|
||||||
/// The location where data for the global browser cache will be stored on
|
/// The directory where data for the global browser cache will be stored on
|
||||||
/// disk. If this value is non-empty then it must be an absolute path that is
|
/// disk. If this value is non-empty then it must be an absolute path that is
|
||||||
/// either equal to or a child directory of CefSettings.root_cache_path. If
|
/// either equal to or a child directory of CefSettings.root_cache_path. If
|
||||||
/// this value is empty then browsers will be created in "incognito mode"
|
/// this value is empty then browsers will be created in "incognito mode"
|
||||||
/// where in-memory caches are used for storage and no data is persisted to
|
/// where in-memory caches are used for storage and no profile-specific data
|
||||||
/// disk. HTML5 databases such as localStorage will only persist across
|
/// is persisted to disk (installation-specific data will still be persisted
|
||||||
/// sessions if a cache path is specified. Can be overridden for individual
|
/// in root_cache_path). HTML5 databases such as localStorage will only
|
||||||
/// CefRequestContext instances via the CefRequestContextSettings.cache_path
|
/// persist across sessions if a cache path is specified. Can be overridden
|
||||||
/// value. When using the Chrome runtime the "default" profile will be used if
|
/// for individual CefRequestContext instances via the
|
||||||
/// |cache_path| and |root_cache_path| have the same value.
|
/// CefRequestContextSettings.cache_path value. When using the Chrome runtime
|
||||||
|
/// any child directory value will be ignored and the "default" profile (also
|
||||||
|
/// a child directory) will be used instead.
|
||||||
///
|
///
|
||||||
cef_string_t cache_path;
|
cef_string_t cache_path;
|
||||||
|
|
||||||
///
|
///
|
||||||
/// The root directory that all CefSettings.cache_path and
|
/// The root directory for installation-specific data and the parent directory
|
||||||
/// CefRequestContextSettings.cache_path values must have in common. If this
|
/// for profile-specific data. All CefSettings.cache_path and
|
||||||
/// value is empty and CefSettings.cache_path is non-empty then it will
|
/// CefRequestContextSettings.cache_path values must have this parent
|
||||||
/// default to the CefSettings.cache_path value. If both values are empty
|
/// directory in common. If this value is empty and CefSettings.cache_path is
|
||||||
/// then the default platform-specific directory will be used
|
/// non-empty then it will default to the CefSettings.cache_path value. Any
|
||||||
|
/// non-empty value must be an absolute path. If both values are empty then
|
||||||
|
/// the default platform-specific directory will be used
|
||||||
/// ("~/.config/cef_user_data" directory on Linux, "~/Library/Application
|
/// ("~/.config/cef_user_data" directory on Linux, "~/Library/Application
|
||||||
/// Support/CEF/User Data" directory on MacOS, "AppData\Local\CEF\User Data"
|
/// Support/CEF/User Data" directory on MacOS, "AppData\Local\CEF\User Data"
|
||||||
/// directory under the user profile directory on Windows). If this value is
|
/// directory under the user profile directory on Windows). Use of the default
|
||||||
/// non-empty then it must be an absolute path. Failure to set this value
|
/// directory is not recommended in production applications (see below).
|
||||||
/// correctly may result in the sandbox blocking read/write access to certain
|
///
|
||||||
/// files.
|
/// Multiple application instances writing to the same root_cache_path
|
||||||
|
/// directory could result in data corruption. A process singleton lock based
|
||||||
|
/// on the root_cache_path value is therefore used to protect against this.
|
||||||
|
/// This singleton behavior applies to all CEF-based applications using
|
||||||
|
/// version 120 or newer. You should customize root_cache_path for your
|
||||||
|
/// application and implement CefBrowserProcessHandler::
|
||||||
|
/// OnAlreadyRunningAppRelaunch, which will then be called on any app relaunch
|
||||||
|
/// with the same root_cache_path value.
|
||||||
|
///
|
||||||
|
/// Failure to set the root_cache_path value correctly may result in startup
|
||||||
|
/// crashes or other unexpected behaviors (for example, the sandbox blocking
|
||||||
|
/// read/write access to certain files).
|
||||||
///
|
///
|
||||||
cef_string_t root_cache_path;
|
cef_string_t root_cache_path;
|
||||||
|
|
||||||
@ -506,14 +521,15 @@ typedef struct _cef_request_context_settings_t {
|
|||||||
size_t size;
|
size_t size;
|
||||||
|
|
||||||
///
|
///
|
||||||
/// The location where cache data for this request context will be stored on
|
/// The directory where cache data for this request context will be stored on
|
||||||
/// disk. If this value is non-empty then it must be an absolute path that is
|
/// disk. If this value is non-empty then it must be an absolute path that is
|
||||||
/// either equal to or a child directory of CefSettings.root_cache_path. If
|
/// either equal to or a child directory of CefSettings.root_cache_path. If
|
||||||
/// this value is empty then browsers will be created in "incognito mode"
|
/// this value is empty then browsers will be created in "incognito mode"
|
||||||
/// where in-memory caches are used for storage and no data is persisted to
|
/// where in-memory caches are used for storage and no profile-specific data
|
||||||
/// disk. HTML5 databases such as localStorage will only persist across
|
/// is persisted to disk (installation-specific data will still be persisted
|
||||||
/// sessions if a cache path is specified. To share the global browser cache
|
/// in root_cache_path). HTML5 databases such as localStorage will only
|
||||||
/// and related configuration set this value to match the
|
/// persist across sessions if a cache path is specified. To share the global
|
||||||
|
/// browser cache and related configuration set this value to match the
|
||||||
/// CefSettings.cache_path value.
|
/// CefSettings.cache_path value.
|
||||||
///
|
///
|
||||||
cef_string_t cache_path;
|
cef_string_t cache_path;
|
||||||
|
@ -19,6 +19,7 @@
|
|||||||
#include "libcef/browser/permission_prompt.h"
|
#include "libcef/browser/permission_prompt.h"
|
||||||
#include "libcef/browser/thread_util.h"
|
#include "libcef/browser/thread_util.h"
|
||||||
#include "libcef/common/app_manager.h"
|
#include "libcef/common/app_manager.h"
|
||||||
|
#include "libcef/common/command_line_impl.h"
|
||||||
#include "libcef/common/extensions/extensions_util.h"
|
#include "libcef/common/extensions/extensions_util.h"
|
||||||
#include "libcef/common/net/net_resource_provider.h"
|
#include "libcef/common/net/net_resource_provider.h"
|
||||||
|
|
||||||
@ -27,6 +28,7 @@
|
|||||||
#include "base/strings/string_number_conversions.h"
|
#include "base/strings/string_number_conversions.h"
|
||||||
#include "base/task/thread_pool.h"
|
#include "base/task/thread_pool.h"
|
||||||
#include "chrome/browser/browser_process.h"
|
#include "chrome/browser/browser_process.h"
|
||||||
|
#include "chrome/browser/chrome_process_singleton.h"
|
||||||
#include "chrome/browser/media/router/chrome_media_router_factory.h"
|
#include "chrome/browser/media/router/chrome_media_router_factory.h"
|
||||||
#include "chrome/browser/net/system_network_context_manager.h"
|
#include "chrome/browser/net/system_network_context_manager.h"
|
||||||
#include "chrome/browser/ui/color/chrome_color_mixers.h"
|
#include "chrome/browser/ui/color/chrome_color_mixers.h"
|
||||||
@ -141,6 +143,56 @@ ui::LinuxUi* GetLinuxUI() {
|
|||||||
|
|
||||||
#endif // BUILDFLAG(IS_LINUX)
|
#endif // BUILDFLAG(IS_LINUX)
|
||||||
|
|
||||||
|
void ProcessSingletonNotificationCallbackImpl(
|
||||||
|
const base::CommandLine& command_line,
|
||||||
|
const base::FilePath& current_directory) {
|
||||||
|
// Drop the request if the browser process is already shutting down.
|
||||||
|
if (!CONTEXT_STATE_VALID()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
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(),
|
||||||
|
current_directory.value());
|
||||||
|
std::ignore = commandLinePtr->Detach(nullptr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!handled) {
|
||||||
|
LOG(WARNING) << "Unhandled app relaunch; implement "
|
||||||
|
"CefBrowserProcessHandler::OnAlreadyRunningAppRelaunch.";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Based on ChromeBrowserMainParts::ProcessSingletonNotificationCallback.
|
||||||
|
bool ProcessSingletonNotificationCallback(
|
||||||
|
const base::CommandLine& command_line,
|
||||||
|
const base::FilePath& current_directory) {
|
||||||
|
// Drop the request if the browser process is already shutting down.
|
||||||
|
// Note that we're going to post an async task below. Even if the browser
|
||||||
|
// process isn't shutting down right now, it could be by the time the task
|
||||||
|
// starts running. So, an additional check needs to happen when it starts.
|
||||||
|
// But regardless of any future check, there is no reason to post the task
|
||||||
|
// now if we know we're already shutting down.
|
||||||
|
if (!CONTEXT_STATE_VALID()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// In order to handle this request on Windows, there is platform specific
|
||||||
|
// code in browser_finder.cc that requires making outbound COM calls to
|
||||||
|
// cross-apartment shell objects (via IVirtualDesktopManager). That is not
|
||||||
|
// allowed within a SendMessage handler, which this function is a part of.
|
||||||
|
// So, we post a task to asynchronously finish the command line processing.
|
||||||
|
return base::SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
|
||||||
|
FROM_HERE, base::BindOnce(&ProcessSingletonNotificationCallbackImpl,
|
||||||
|
command_line, current_directory));
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
AlloyBrowserMainParts::AlloyBrowserMainParts() = default;
|
AlloyBrowserMainParts::AlloyBrowserMainParts() = default;
|
||||||
@ -262,6 +314,10 @@ int AlloyBrowserMainParts::PreCreateThreads() {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void AlloyBrowserMainParts::PostCreateThreads() {
|
||||||
|
ChromeProcessSingleton::GetInstance()->StartWatching();
|
||||||
|
}
|
||||||
|
|
||||||
int AlloyBrowserMainParts::PreMainMessageLoopRun() {
|
int AlloyBrowserMainParts::PreMainMessageLoopRun() {
|
||||||
#if defined(USE_AURA)
|
#if defined(USE_AURA)
|
||||||
screen_ = views::CreateDesktopScreen();
|
screen_ = views::CreateDesktopScreen();
|
||||||
@ -339,6 +395,12 @@ int AlloyBrowserMainParts::PreMainMessageLoopRun() {
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// Allow ProcessSingleton to process messages.
|
||||||
|
// This is done here instead of just relying on the main message loop's start
|
||||||
|
// to avoid rendezvous in RunLoops that may precede MainMessageLoopRun.
|
||||||
|
ChromeProcessSingleton::GetInstance()->Unlock(
|
||||||
|
base::BindRepeating(&ProcessSingletonNotificationCallback));
|
||||||
|
|
||||||
return content::RESULT_CODE_NORMAL_EXIT;
|
return content::RESULT_CODE_NORMAL_EXIT;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -346,6 +408,8 @@ void AlloyBrowserMainParts::PostMainMessageLoopRun() {
|
|||||||
// NOTE: Destroy objects in reverse order of creation.
|
// NOTE: Destroy objects in reverse order of creation.
|
||||||
CefDevToolsManagerDelegate::StopHttpHandler();
|
CefDevToolsManagerDelegate::StopHttpHandler();
|
||||||
|
|
||||||
|
ChromeProcessSingleton::GetInstance()->Cleanup();
|
||||||
|
|
||||||
// There should be no additional references to the global CefRequestContext
|
// There should be no additional references to the global CefRequestContext
|
||||||
// during shutdown. Did you forget to release a CefBrowser reference?
|
// during shutdown. Did you forget to release a CefBrowser reference?
|
||||||
DCHECK(global_request_context_->HasOneRef());
|
DCHECK(global_request_context_->HasOneRef());
|
||||||
|
@ -49,6 +49,7 @@ class AlloyBrowserMainParts : public content::BrowserMainParts {
|
|||||||
void PreCreateMainMessageLoop() override;
|
void PreCreateMainMessageLoop() override;
|
||||||
void PostCreateMainMessageLoop() override;
|
void PostCreateMainMessageLoop() override;
|
||||||
int PreCreateThreads() override;
|
int PreCreateThreads() override;
|
||||||
|
void PostCreateThreads() override;
|
||||||
int PreMainMessageLoopRun() override;
|
int PreMainMessageLoopRun() override;
|
||||||
void PostMainMessageLoopRun() override;
|
void PostMainMessageLoopRun() override;
|
||||||
void PostDestroyThreads() override;
|
void PostDestroyThreads() override;
|
||||||
|
@ -35,6 +35,7 @@
|
|||||||
#include "chrome/browser/ui/webui/chrome_untrusted_web_ui_configs.h"
|
#include "chrome/browser/ui/webui/chrome_untrusted_web_ui_configs.h"
|
||||||
#include "chrome/browser/ui/webui/chrome_web_ui_controller_factory.h"
|
#include "chrome/browser/ui/webui/chrome_web_ui_controller_factory.h"
|
||||||
#include "chrome/browser/ui/webui/theme_source.h"
|
#include "chrome/browser/ui/webui/theme_source.h"
|
||||||
|
#include "chrome/common/chrome_paths.h"
|
||||||
#include "chrome/common/url_constants.h"
|
#include "chrome/common/url_constants.h"
|
||||||
#include "content/browser/renderer_host/debug_urls.h"
|
#include "content/browser/renderer_host/debug_urls.h"
|
||||||
#include "content/public/browser/browser_url_handler.h"
|
#include "content/public/browser/browser_url_handler.h"
|
||||||
@ -385,6 +386,9 @@ bool OnVersionUI(Profile* profile,
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
base::FilePath user_data_dir =
|
||||||
|
base::PathService::CheckedGet(chrome::DIR_USER_DATA);
|
||||||
|
|
||||||
TemplateParser parser;
|
TemplateParser parser;
|
||||||
parser.Add("YEAR", MAKE_STRING(COPYRIGHT_YEAR));
|
parser.Add("YEAR", MAKE_STRING(COPYRIGHT_YEAR));
|
||||||
parser.Add("CEF", CEF_VERSION);
|
parser.Add("CEF", CEF_VERSION);
|
||||||
@ -400,6 +404,7 @@ bool OnVersionUI(Profile* profile,
|
|||||||
CefAppManager::Get()->GetContentClient()->browser()->GetUserAgent());
|
CefAppManager::Get()->GetContentClient()->browser()->GetUserAgent());
|
||||||
parser.Add("COMMANDLINE", GetCommandLine());
|
parser.Add("COMMANDLINE", GetCommandLine());
|
||||||
parser.Add("MODULEPATH", GetModulePath());
|
parser.Add("MODULEPATH", GetModulePath());
|
||||||
|
parser.Add("ROOTCACHEPATH", CefString(user_data_dir.value()));
|
||||||
parser.Add("CACHEPATH", CefString(profile->GetPath().value()));
|
parser.Add("CACHEPATH", CefString(profile->GetPath().value()));
|
||||||
|
|
||||||
parser.Parse(&tmpl);
|
parser.Parse(&tmpl);
|
||||||
|
@ -24,16 +24,22 @@
|
|||||||
#include "base/strings/string_number_conversions.h"
|
#include "base/strings/string_number_conversions.h"
|
||||||
#include "base/strings/string_split.h"
|
#include "base/strings/string_split.h"
|
||||||
#include "base/strings/string_util.h"
|
#include "base/strings/string_util.h"
|
||||||
|
#include "base/strings/sys_string_conversions.h"
|
||||||
|
#include "base/strings/utf_string_conversions.h"
|
||||||
#include "base/synchronization/waitable_event.h"
|
#include "base/synchronization/waitable_event.h"
|
||||||
#include "chrome/browser/browser_process.h"
|
#include "chrome/browser/browser_process.h"
|
||||||
|
#include "chrome/browser/chrome_process_singleton.h"
|
||||||
#include "chrome/child/pdf_child_init.h"
|
#include "chrome/child/pdf_child_init.h"
|
||||||
#include "chrome/common/chrome_constants.h"
|
#include "chrome/common/chrome_constants.h"
|
||||||
#include "chrome/common/chrome_paths.h"
|
#include "chrome/common/chrome_paths.h"
|
||||||
|
#include "chrome/common/chrome_result_codes.h"
|
||||||
#include "chrome/common/chrome_switches.h"
|
#include "chrome/common/chrome_switches.h"
|
||||||
|
#include "chrome/grit/generated_resources.h"
|
||||||
#include "chrome/utility/chrome_content_utility_client.h"
|
#include "chrome/utility/chrome_content_utility_client.h"
|
||||||
#include "components/component_updater/component_updater_paths.h"
|
#include "components/component_updater/component_updater_paths.h"
|
||||||
#include "components/content_settings/core/common/content_settings_pattern.h"
|
#include "components/content_settings/core/common/content_settings_pattern.h"
|
||||||
#include "components/embedder_support/switches.h"
|
#include "components/embedder_support/switches.h"
|
||||||
|
#include "components/metrics/persistent_histograms.h"
|
||||||
#include "components/viz/common/features.h"
|
#include "components/viz/common/features.h"
|
||||||
#include "content/public/common/content_features.h"
|
#include "content/public/common/content_features.h"
|
||||||
#include "content/public/common/content_switches.h"
|
#include "content/public/common/content_switches.h"
|
||||||
@ -45,7 +51,9 @@
|
|||||||
#include "services/network/public/cpp/features.h"
|
#include "services/network/public/cpp/features.h"
|
||||||
#include "third_party/blink/public/common/features.h"
|
#include "third_party/blink/public/common/features.h"
|
||||||
#include "third_party/blink/public/common/switches.h"
|
#include "third_party/blink/public/common/switches.h"
|
||||||
|
#include "ui/base/l10n/l10n_util.h"
|
||||||
#include "ui/base/resource/resource_bundle.h"
|
#include "ui/base/resource/resource_bundle.h"
|
||||||
|
#include "ui/base/resource/scoped_startup_resource_bundle.h"
|
||||||
#include "ui/base/ui_base_features.h"
|
#include "ui/base/ui_base_features.h"
|
||||||
#include "ui/base/ui_base_paths.h"
|
#include "ui/base/ui_base_paths.h"
|
||||||
#include "ui/base/ui_base_switches.h"
|
#include "ui/base/ui_base_switches.h"
|
||||||
@ -69,6 +77,46 @@ const char* const kNonWildcardDomainNonPortSchemes[] = {
|
|||||||
const size_t kNonWildcardDomainNonPortSchemesSize =
|
const size_t kNonWildcardDomainNonPortSchemesSize =
|
||||||
std::size(kNonWildcardDomainNonPortSchemes);
|
std::size(kNonWildcardDomainNonPortSchemes);
|
||||||
|
|
||||||
|
absl::optional<int> AcquireProcessSingleton(
|
||||||
|
const base::FilePath& user_data_dir) {
|
||||||
|
// Take the Chrome process singleton lock. The process can become the
|
||||||
|
// Browser process if it succeed to take the lock. Otherwise, the
|
||||||
|
// command-line is sent to the actual Browser process and the current
|
||||||
|
// process can be exited.
|
||||||
|
ChromeProcessSingleton::CreateInstance(user_data_dir);
|
||||||
|
|
||||||
|
ProcessSingleton::NotifyResult notify_result =
|
||||||
|
ChromeProcessSingleton::GetInstance()->NotifyOtherProcessOrCreate();
|
||||||
|
switch (notify_result) {
|
||||||
|
case ProcessSingleton::PROCESS_NONE:
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ProcessSingleton::PROCESS_NOTIFIED: {
|
||||||
|
// Ensure there is an instance of ResourceBundle that is initialized for
|
||||||
|
// localized string resource accesses.
|
||||||
|
ui::ScopedStartupResourceBundle startup_resource_bundle;
|
||||||
|
printf("%s\n", base::SysWideToNativeMB(
|
||||||
|
base::UTF16ToWide(l10n_util::GetStringUTF16(
|
||||||
|
IDS_USED_EXISTING_BROWSER)))
|
||||||
|
.c_str());
|
||||||
|
return chrome::RESULT_CODE_NORMAL_EXIT_PROCESS_NOTIFIED;
|
||||||
|
}
|
||||||
|
|
||||||
|
case ProcessSingleton::PROFILE_IN_USE:
|
||||||
|
return chrome::RESULT_CODE_PROFILE_IN_USE;
|
||||||
|
|
||||||
|
case ProcessSingleton::LOCK_ERROR:
|
||||||
|
LOG(ERROR) << "Failed to create a ProcessSingleton for your profile "
|
||||||
|
"directory. This means that running multiple instances "
|
||||||
|
"would start multiple browser processes rather than "
|
||||||
|
"opening a new window in the existing process. Aborting "
|
||||||
|
"now to avoid profile corruption.";
|
||||||
|
return chrome::RESULT_CODE_PROFILE_IN_USE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return absl::nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
AlloyMainDelegate::AlloyMainDelegate(CefMainRunnerHandler* runner,
|
AlloyMainDelegate::AlloyMainDelegate(CefMainRunnerHandler* runner,
|
||||||
@ -87,6 +135,35 @@ absl::optional<int> AlloyMainDelegate::PreBrowserMain() {
|
|||||||
return absl::nullopt;
|
return absl::nullopt;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
absl::optional<int> AlloyMainDelegate::PostEarlyInitialization(
|
||||||
|
InvokedIn invoked_in) {
|
||||||
|
const auto* invoked_in_browser =
|
||||||
|
absl::get_if<InvokedInBrowserProcess>(&invoked_in);
|
||||||
|
if (!invoked_in_browser) {
|
||||||
|
return absl::nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Based on ChromeMainDelegate::PostEarlyInitialization.
|
||||||
|
// The User Data dir is guaranteed to be valid as per PreSandboxStartup.
|
||||||
|
base::FilePath user_data_dir =
|
||||||
|
base::PathService::CheckedGet(chrome::DIR_USER_DATA);
|
||||||
|
|
||||||
|
// On platforms that support the process rendezvous, acquire the process
|
||||||
|
// singleton. In case of failure, it means there is already a running browser
|
||||||
|
// instance that handled the command-line.
|
||||||
|
if (auto process_singleton_result = AcquireProcessSingleton(user_data_dir);
|
||||||
|
process_singleton_result.has_value()) {
|
||||||
|
// To ensure that the histograms emitted in this process are reported in
|
||||||
|
// case of early exit, report the metrics accumulated this session with a
|
||||||
|
// future session's metrics.
|
||||||
|
DeferBrowserMetrics(user_data_dir);
|
||||||
|
|
||||||
|
return process_singleton_result;
|
||||||
|
}
|
||||||
|
|
||||||
|
return absl::nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
absl::optional<int> AlloyMainDelegate::BasicStartupComplete() {
|
absl::optional<int> AlloyMainDelegate::BasicStartupComplete() {
|
||||||
base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
|
base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
|
||||||
std::string process_type =
|
std::string process_type =
|
||||||
|
@ -47,6 +47,7 @@ class AlloyMainDelegate : public content::ContentMainDelegate,
|
|||||||
|
|
||||||
// content::ContentMainDelegate overrides.
|
// content::ContentMainDelegate overrides.
|
||||||
absl::optional<int> PreBrowserMain() override;
|
absl::optional<int> PreBrowserMain() override;
|
||||||
|
absl::optional<int> PostEarlyInitialization(InvokedIn invoked_in) override;
|
||||||
absl::optional<int> BasicStartupComplete() override;
|
absl::optional<int> BasicStartupComplete() override;
|
||||||
void PreSandboxStartup() override;
|
void PreSandboxStartup() override;
|
||||||
absl::variant<int, content::MainFunctionParams> RunProcess(
|
absl::variant<int, content::MainFunctionParams> RunProcess(
|
||||||
|
@ -13,6 +13,7 @@
|
|||||||
#include "base/command_line.h"
|
#include "base/command_line.h"
|
||||||
#include "base/files/file_path.h"
|
#include "base/files/file_path.h"
|
||||||
#include "base/files/file_util.h"
|
#include "base/files/file_util.h"
|
||||||
|
#include "base/logging.h"
|
||||||
#include "base/notreached.h"
|
#include "base/notreached.h"
|
||||||
#include "base/path_service.h"
|
#include "base/path_service.h"
|
||||||
#include "chrome/common/chrome_constants.h"
|
#include "chrome/common/chrome_constants.h"
|
||||||
@ -89,6 +90,10 @@ base::FilePath GetUserDataPath(CefSettings* settings,
|
|||||||
}
|
}
|
||||||
if (!root_cache_path.empty()) {
|
if (!root_cache_path.empty()) {
|
||||||
return base::FilePath(root_cache_path);
|
return base::FilePath(root_cache_path);
|
||||||
|
} else {
|
||||||
|
LOG(WARNING) << "Please customize CefSettings.root_cache_path for your "
|
||||||
|
"application. Use of the default value may lead to "
|
||||||
|
"unintended process singleton behavior.";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -43,6 +43,10 @@ body {
|
|||||||
content: ':';
|
content: ':';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.footnote {
|
||||||
|
font-size: 0.8em;
|
||||||
|
}
|
||||||
|
|
||||||
#logo {
|
#logo {
|
||||||
float: right;
|
float: right;
|
||||||
margin-left: 40px;
|
margin-left: 40px;
|
||||||
@ -109,9 +113,26 @@ body {
|
|||||||
<td class="value">$$MODULEPATH$$</td>
|
<td class="value">$$MODULEPATH$$</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td class="label" valign="top">Cache Path</td>
|
<td class="label" valign="top">Root Cache Path <sup>[1][2]</sup></td>
|
||||||
|
<td class="value">$$ROOTCACHEPATH$$</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="label" valign="top">Cache Path <sup>[1]</sup></td>
|
||||||
<td class="value">$$CACHEPATH$$</td>
|
<td class="value">$$CACHEPATH$$</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="2" class="footnote">
|
||||||
|
<br>[1] In <a href="https://chromium.googlesource.com/chromium/src/+/master/docs/user_data_dir.md" target="_new">Chromium terminology</a>,
|
||||||
|
"Root Cache Path" (<a href="https://cef-builds.spotifycdn.com/docs/beta.html?structcef__settings__t.html#a2e2be03f34ddd93de90e1cf196757a19" target="_new">CefSettings.root_cache_path</a>)
|
||||||
|
is the "User Data Directory" and "Cache Path" (<a href="https://cef-builds.spotifycdn.com/docs/beta.html?structcef__settings__t.html#ad1644a7eb23cad969181db010f007710" target="_new">CefSettings.cache_path</a>)
|
||||||
|
is the "Profile Path". An empty "Cache Path" value means that the browser is using an <a href="https://support.google.com/chrome/answer/9845881" target="_new">Incognito Profile</a>.
|
||||||
|
Even in Incognito mode, some per-installation data will still be written to the "Root Cache Path" directory.
|
||||||
|
<br/><br/>[2] Chromium's <a href="https://chromium.googlesource.com/chromium/src/+/master/chrome/browser/process_singleton.h#35" target="_new">process singleton lock</a>
|
||||||
|
protects against multiple app instances writing to the same "Root Cache Path" directory.
|
||||||
|
Implement <a href="https://cef-builds.spotifycdn.com/docs/beta.html?classCefBrowserProcessHandler.html#a052a91639483467c0b546d57a05c2f06" target="_new">CefBrowserProcessHandler:: OnAlreadyRunningAppRelaunch</a>
|
||||||
|
to handle the case of app relaunch with the same directory.
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
</body>
|
</body>
|
||||||
|
@ -68,6 +68,21 @@ class ClientBrowserDelegate : public ClientAppBrowser::Delegate {
|
|||||||
CefRefPtr<ClientAppBrowser> app,
|
CefRefPtr<ClientAppBrowser> app,
|
||||||
CefRefPtr<CefCommandLine> command_line,
|
CefRefPtr<CefCommandLine> command_line,
|
||||||
const CefString& current_directory) override {
|
const CefString& current_directory) override {
|
||||||
|
// Add logging for some common switches that the user may attempt to use.
|
||||||
|
static const char* kIgnoredSwitches[] = {
|
||||||
|
switches::kEnableChromeRuntime,
|
||||||
|
switches::kMultiThreadedMessageLoop,
|
||||||
|
switches::kOffScreenRenderingEnabled,
|
||||||
|
switches::kUseViews,
|
||||||
|
};
|
||||||
|
for (size_t i = 0;
|
||||||
|
i < sizeof(kIgnoredSwitches) / sizeof(kIgnoredSwitches[0]); ++i) {
|
||||||
|
if (command_line->HasSwitch(kIgnoredSwitches[i])) {
|
||||||
|
LOG(WARNING) << "The --" << kIgnoredSwitches[i]
|
||||||
|
<< " command-line switch is ignored on app relaunch.";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Create a new root window based on |command_line|.
|
// Create a new root window based on |command_line|.
|
||||||
auto config = std::make_unique<RootWindowConfig>(command_line->Copy());
|
auto config = std::make_unique<RootWindowConfig>(command_line->Copy());
|
||||||
|
|
||||||
|
@ -36,9 +36,9 @@ enum class WindowType {
|
|||||||
|
|
||||||
// Used to configure how a RootWindow is created.
|
// Used to configure how a RootWindow is created.
|
||||||
struct RootWindowConfig {
|
struct RootWindowConfig {
|
||||||
// |command_line| will be non-nullptr when used for new window creation
|
// |command_line| will be non-nullptr when used for new window creation via
|
||||||
// via OnAlreadyRunningAppRelaunch (chrome runtime only). Otherwise, the
|
// OnAlreadyRunningAppRelaunch. Otherwise, the global command-line will be
|
||||||
// global command-line will be used.
|
// used.
|
||||||
RootWindowConfig(CefRefPtr<CefCommandLine> command_line = nullptr);
|
RootWindowConfig(CefRefPtr<CefCommandLine> command_line = nullptr);
|
||||||
|
|
||||||
// Associated command-line.
|
// Associated command-line.
|
||||||
|
Reference in New Issue
Block a user