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

@@ -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;