Compare commits
14 Commits
02b371879b
...
48f3ef63e2
Author | SHA1 | Date |
---|---|---|
Marshall Greenblatt | 48f3ef63e2 | |
Marshall Greenblatt | 7268dc8cd3 | |
Marshall Greenblatt | 45861b1b08 | |
Marshall Greenblatt | efe558cd28 | |
Marshall Greenblatt | f1e634393f | |
Marshall Greenblatt | 0187046a2e | |
Marshall Greenblatt | 6f4c2bf8df | |
Marshall Greenblatt | de2da368c6 | |
Marshall Greenblatt | 4797681694 | |
Nik Pavlov | ffbc53a9e6 | |
Marshall Greenblatt | 92f14410ae | |
Nik Pavlov | e68b0169a1 | |
Nik Pavlov | 1fd6000c70 | |
Marshall Greenblatt | 5e348cb1fc |
|
@ -288,6 +288,8 @@
|
|||
'tests/cefclient/browser/urlrequest_test.h',
|
||||
'tests/cefclient/browser/views_menu_bar.cc',
|
||||
'tests/cefclient/browser/views_menu_bar.h',
|
||||
'tests/cefclient/browser/views_overlay_browser.cc',
|
||||
'tests/cefclient/browser/views_overlay_browser.h',
|
||||
'tests/cefclient/browser/views_overlay_controls.cc',
|
||||
'tests/cefclient/browser/views_overlay_controls.h',
|
||||
'tests/cefclient/browser/views_style.cc',
|
||||
|
|
|
@ -33,7 +33,7 @@
|
|||
// by hand. See the translator.README.txt file in the tools directory for
|
||||
// more information.
|
||||
//
|
||||
// $hash=7c786570b1c7af912a31c6f0c3d742e8aeb38fd8$
|
||||
// $hash=e9f34d90eb4af614e35cbb29da0639b62acec7fd$
|
||||
//
|
||||
|
||||
#ifndef CEF_INCLUDE_CAPI_CEF_BROWSER_CAPI_H_
|
||||
|
@ -301,29 +301,62 @@ typedef struct _cef_browser_host_t {
|
|||
struct _cef_browser_host_t* self);
|
||||
|
||||
///
|
||||
/// Request that the browser close. The JavaScript 'onbeforeunload' event will
|
||||
/// be fired. If |force_close| is false (0) the event handler, if any, will be
|
||||
/// allowed to prompt the user and the user can optionally cancel the close.
|
||||
/// If |force_close| is true (1) the prompt will not be displayed and the
|
||||
/// close will proceed. Results in a call to
|
||||
/// cef_life_span_handler_t::do_close() if the event handler allows the close
|
||||
/// or if |force_close| is true (1). See cef_life_span_handler_t::do_close()
|
||||
/// documentation for additional usage information.
|
||||
/// Request that the browser close. Closing a browser is a multi-stage process
|
||||
/// that may complete either synchronously or asynchronously, and involves
|
||||
/// callbacks such as cef_life_span_handler_t::DoClose (Alloy style only),
|
||||
/// cef_life_span_handler_t::OnBeforeClose, and a top-level window close
|
||||
/// handler such as cef_window_delegate_t::CanClose (or platform-specific
|
||||
/// equivalent). In some cases a close request may be delayed or canceled by
|
||||
/// the user. Using try_close_browser() instead of close_browser() is
|
||||
/// recommended for most use cases. See cef_life_span_handler_t::do_close()
|
||||
/// documentation for detailed usage and examples.
|
||||
///
|
||||
/// If |force_close| is false (0) then JavaScript unload handlers, if any, may
|
||||
/// be fired and the close may be delayed or canceled by the user. If
|
||||
/// |force_close| is true (1) then the user will not be prompted and the close
|
||||
/// will proceed immediately (possibly asynchronously). If browser close is
|
||||
/// delayed and not canceled the default behavior is to call the top-level
|
||||
/// window close handler once the browser is ready to be closed. This default
|
||||
/// behavior can be changed for Alloy style browsers by implementing
|
||||
/// cef_life_span_handler_t::do_close(). is_ready_to_be_closed() can be used
|
||||
/// to detect mandatory browser close events when customizing close behavior
|
||||
/// on the browser process UI thread.
|
||||
///
|
||||
void(CEF_CALLBACK* close_browser)(struct _cef_browser_host_t* self,
|
||||
int force_close);
|
||||
|
||||
///
|
||||
/// Helper for closing a browser. Call this function from the top-level window
|
||||
/// close handler (if any). Internally this calls CloseBrowser(false (0)) if
|
||||
/// the close has not yet been initiated. This function returns false (0)
|
||||
/// while the close is pending and true (1) after the close has completed. See
|
||||
/// close_browser() and cef_life_span_handler_t::do_close() documentation for
|
||||
/// additional usage information. This function must be called on the browser
|
||||
/// process UI thread.
|
||||
/// Helper for closing a browser. This is similar in behavior to
|
||||
/// CLoseBrowser(false (0)) but returns a boolean to reflect the immediate
|
||||
/// close status. Call this function from a top-level window close handler
|
||||
/// such as cef_window_delegate_t::CanClose (or platform-specific equivalent)
|
||||
/// to request that the browser close, and return the result to indicate if
|
||||
/// the window close should proceed. Returns false (0) if the close will be
|
||||
/// delayed (JavaScript unload handlers triggered but still pending) or true
|
||||
/// (1) if the close will proceed immediately (possibly asynchronously). See
|
||||
/// close_browser() documentation for additional usage information. This
|
||||
/// function must be called on the browser process UI thread.
|
||||
///
|
||||
int(CEF_CALLBACK* try_close_browser)(struct _cef_browser_host_t* self);
|
||||
|
||||
///
|
||||
/// Returns true (1) if the browser is ready to be closed, meaning that the
|
||||
/// close has already been initiated and that JavaScript unload handlers have
|
||||
/// already executed or should be ignored. This can be used from a top-level
|
||||
/// window close handler such as cef_window_delegate_t::CanClose (or platform-
|
||||
/// specific equivalent) to distringuish between potentially cancelable
|
||||
/// browser close events (like the user clicking the top-level window close
|
||||
/// button before browser close has started) and mandatory browser close
|
||||
/// events (like JavaScript `window.close()` or after browser close has
|
||||
/// started in response to [Try]close_browser()). Not completing the browser
|
||||
/// close for mandatory close events (when this function returns true (1))
|
||||
/// will leave the browser in a partially closed state that interferes with
|
||||
/// proper functioning. See close_browser() documentation for additional usage
|
||||
/// information. This function must be called on the browser process UI
|
||||
/// thread.
|
||||
///
|
||||
int(CEF_CALLBACK* is_ready_to_be_closed)(struct _cef_browser_host_t* self);
|
||||
|
||||
///
|
||||
/// Set whether the browser is focused.
|
||||
///
|
||||
|
|
|
@ -33,7 +33,7 @@
|
|||
// by hand. See the translator.README.txt file in the tools directory for
|
||||
// more information.
|
||||
//
|
||||
// $hash=5232dd6bf16af9b6d195a47bb41de0dfb880a65e$
|
||||
// $hash=6aad2ccf30a6c519bbeee64d83866e82a41a48d8$
|
||||
//
|
||||
|
||||
#ifndef CEF_INCLUDE_CAPI_CEF_LIFE_SPAN_HANDLER_CAPI_H_
|
||||
|
@ -138,35 +138,44 @@ typedef struct _cef_life_span_handler_t {
|
|||
struct _cef_browser_t* browser);
|
||||
|
||||
///
|
||||
/// Called when a browser has received a request to close. This may result
|
||||
/// directly from a call to cef_browser_host_t::*close_browser() or indirectly
|
||||
/// if the browser is parented to a top-level window created by CEF and the
|
||||
/// user attempts to close that window (by clicking the 'X', for example). The
|
||||
/// do_close() function will be called after the JavaScript 'onunload' event
|
||||
/// has been fired.
|
||||
/// Called when an Alloy style browser is ready to be closed, meaning that the
|
||||
/// close has already been initiated and that JavaScript unload handlers have
|
||||
/// already executed or should be ignored. This may result directly from a
|
||||
/// call to cef_browser_host_t::[Try]close_browser() or indirectly if the
|
||||
/// browser's top-level parent window was created by CEF and the user attempts
|
||||
/// to close that window (by clicking the 'X', for example). do_close() will
|
||||
/// not be called if the browser's host window/view has already been destroyed
|
||||
/// (via parent window/view hierarchy tear-down, for example), as it is no
|
||||
/// longer possible to customize the close behavior at that point.
|
||||
///
|
||||
/// An application should handle top-level owner window close notifications by
|
||||
/// calling cef_browser_host_t::try_close_browser() or
|
||||
/// An application should handle top-level parent window close notifications
|
||||
/// by calling cef_browser_host_t::try_close_browser() or
|
||||
/// cef_browser_host_t::CloseBrowser(false (0)) instead of allowing the window
|
||||
/// to close immediately (see the examples below). This gives CEF an
|
||||
/// opportunity to process the 'onbeforeunload' event and optionally cancel
|
||||
/// opportunity to process JavaScript unload handlers and optionally cancel
|
||||
/// the close before do_close() is called.
|
||||
///
|
||||
/// When windowed rendering is enabled CEF will internally create a window or
|
||||
/// view to host the browser. In that case returning false (0) from do_close()
|
||||
/// will send the standard close notification to the browser's top-level owner
|
||||
/// window (e.g. WM_CLOSE on Windows, performClose: on OS X, "delete_event" on
|
||||
/// Linux or cef_window_delegate_t::can_close() callback from Views). If the
|
||||
/// browser's host window/view has already been destroyed (via view hierarchy
|
||||
/// tear-down, for example) then do_close() will not be called for that
|
||||
/// browser since is no longer possible to cancel the close.
|
||||
/// When windowed rendering is enabled CEF will create an internal child
|
||||
/// window/view to host the browser. In that case returning false (0) from
|
||||
/// do_close() will send the standard close notification to the browser's top-
|
||||
/// level parent window (e.g. WM_CLOSE on Windows, performClose: on OS X,
|
||||
/// "delete_event" on Linux or cef_window_delegate_t::can_close() callback
|
||||
/// from Views).
|
||||
///
|
||||
/// When windowed rendering is disabled returning false (0) from do_close()
|
||||
/// will cause the browser object to be destroyed immediately.
|
||||
/// When windowed rendering is disabled there is no internal window/view and
|
||||
/// returning false (0) from do_close() will cause the browser object to be
|
||||
/// destroyed immediately.
|
||||
///
|
||||
/// If the browser's top-level owner window requires a non-standard close
|
||||
/// If the browser's top-level parent window requires a non-standard close
|
||||
/// notification then send that notification from do_close() and return true
|
||||
/// (1).
|
||||
/// (1). You are still required to complete the browser close as soon as
|
||||
/// possible (either by calling [Try]close_browser() or by proceeding with
|
||||
/// window/view hierarchy tear-down), otherwise the browser will be left in a
|
||||
/// partially closed state that interferes with proper functioning. Top-level
|
||||
/// windows created on the browser process UI thread can alternately call
|
||||
/// cef_browser_host_t::is_ready_to_be_closed() in the close handler to check
|
||||
/// close status instead of relying on custom do_close() handling. See
|
||||
/// documentation on that function for additional details.
|
||||
///
|
||||
/// The cef_life_span_handler_t::on_before_close() function will be called
|
||||
/// after do_close() (if do_close() is called) and immediately before the
|
||||
|
@ -182,22 +191,26 @@ typedef struct _cef_life_span_handler_t {
|
|||
/// which sends a close notification
|
||||
/// to the application's top-level window.
|
||||
/// 2. Application's top-level window receives the close notification and
|
||||
/// calls TryCloseBrowser() (which internally calls CloseBrowser(false)).
|
||||
/// calls TryCloseBrowser() (similar to calling CloseBrowser(false)).
|
||||
/// TryCloseBrowser() returns false so the client cancels the window
|
||||
/// close.
|
||||
/// 3. JavaScript 'onbeforeunload' handler executes and shows the close
|
||||
/// confirmation dialog (which can be overridden via
|
||||
/// CefJSDialogHandler::OnBeforeUnloadDialog()).
|
||||
/// 4. User approves the close. 5. JavaScript 'onunload' handler executes.
|
||||
/// 6. CEF sends a close notification to the application's top-level window
|
||||
/// (because DoClose() returned false by default).
|
||||
/// 7. Application's top-level window receives the close notification and
|
||||
/// 6. Application's do_close() handler is called and returns false (0) by
|
||||
/// default.
|
||||
/// 7. CEF sends a close notification to the application's top-level window
|
||||
/// (because DoClose() returned false).
|
||||
/// 8. Application's top-level window receives the close notification and
|
||||
/// calls TryCloseBrowser(). TryCloseBrowser() returns true so the client
|
||||
/// allows the window close.
|
||||
/// 8. Application's top-level window is destroyed. 9. Application's
|
||||
/// on_before_close() handler is called and the browser object
|
||||
/// 9. Application's top-level window is destroyed, triggering destruction
|
||||
/// of the child browser window.
|
||||
/// 10. Application's on_before_close() handler is called and the browser
|
||||
/// object
|
||||
/// is destroyed.
|
||||
/// 10. Application exits by calling cef_quit_message_loop() if no other
|
||||
/// 11. Application exits by calling cef_quit_message_loop() if no other
|
||||
/// browsers
|
||||
/// exist.
|
||||
///
|
||||
|
@ -215,13 +228,17 @@ typedef struct _cef_life_span_handler_t {
|
|||
/// CefJSDialogHandler::OnBeforeUnloadDialog()).
|
||||
/// 4. User approves the close. 5. JavaScript 'onunload' handler executes.
|
||||
/// 6. Application's do_close() handler is called. Application will:
|
||||
/// A. Set a flag to indicate that the next close attempt will be allowed.
|
||||
/// A. Set a flag to indicate that the next top-level window close attempt
|
||||
/// will be allowed.
|
||||
/// B. Return false.
|
||||
/// 7. CEF sends an close notification to the application's top-level window.
|
||||
/// 7. CEF sends a close notification to the application's top-level window
|
||||
/// (because DoClose() returned false).
|
||||
/// 8. Application's top-level window receives the close notification and
|
||||
/// allows the window to close based on the flag from #6B.
|
||||
/// 9. Application's top-level window is destroyed. 10. Application's
|
||||
/// on_before_close() handler is called and the browser object
|
||||
/// allows the window to close based on the flag from #6A.
|
||||
/// 9. Application's top-level window is destroyed, triggering destruction
|
||||
/// of the child browser window.
|
||||
/// 10. Application's on_before_close() handler is called and the browser
|
||||
/// object
|
||||
/// is destroyed.
|
||||
/// 11. Application exits by calling cef_quit_message_loop() if no other
|
||||
/// browsers
|
||||
|
|
|
@ -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 "9717d7221d63adfd79ee52e2a31c9ac7acdd6d50"
|
||||
#define CEF_API_HASH_UNIVERSAL "676af077d6826353caf40425f5f2bae1262347ea"
|
||||
#if defined(OS_WIN)
|
||||
#define CEF_API_HASH_PLATFORM "072a4fe61a512f21fd0d664495902fca6ec2193b"
|
||||
#define CEF_API_HASH_PLATFORM "51848171cdea10858c4e0fca0f7099b0fdc759f9"
|
||||
#elif defined(OS_MAC)
|
||||
#define CEF_API_HASH_PLATFORM "ee7f0e9247add8df0827d02da32559e38e8079d0"
|
||||
#define CEF_API_HASH_PLATFORM "8cc826c5f5fe97c275dfa3b9c020470678a5d2fd"
|
||||
#elif defined(OS_LINUX)
|
||||
#define CEF_API_HASH_PLATFORM "88996e58ee062016efd054bfbafd03dd3daa99ed"
|
||||
#define CEF_API_HASH_PLATFORM "0aec2348de1bf14fafa7a23baa0df942d342d409"
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
|
|
@ -331,30 +331,63 @@ class CefBrowserHost : public virtual CefBaseRefCounted {
|
|||
virtual CefRefPtr<CefBrowser> GetBrowser() = 0;
|
||||
|
||||
///
|
||||
/// Request that the browser close. The JavaScript 'onbeforeunload' event will
|
||||
/// be fired. If |force_close| is false the event handler, if any, will be
|
||||
/// allowed to prompt the user and the user can optionally cancel the close.
|
||||
/// If |force_close| is true the prompt will not be displayed and the close
|
||||
/// will proceed. Results in a call to CefLifeSpanHandler::DoClose() if the
|
||||
/// event handler allows the close or if |force_close| is true. See
|
||||
/// CefLifeSpanHandler::DoClose() documentation for additional usage
|
||||
/// information.
|
||||
/// Request that the browser close. Closing a browser is a multi-stage process
|
||||
/// that may complete either synchronously or asynchronously, and involves
|
||||
/// callbacks such as CefLifeSpanHandler::DoClose (Alloy style only),
|
||||
/// CefLifeSpanHandler::OnBeforeClose, and a top-level window close handler
|
||||
/// such as CefWindowDelegate::CanClose (or platform-specific equivalent). In
|
||||
/// some cases a close request may be delayed or canceled by the user. Using
|
||||
/// TryCloseBrowser() instead of CloseBrowser() is recommended for most use
|
||||
/// cases. See CefLifeSpanHandler::DoClose() documentation for detailed usage
|
||||
/// and examples.
|
||||
///
|
||||
/// If |force_close| is false then JavaScript unload handlers, if any, may be
|
||||
/// fired and the close may be delayed or canceled by the user. If
|
||||
/// |force_close| is true then the user will not be prompted and the close
|
||||
/// will proceed immediately (possibly asynchronously). If browser close is
|
||||
/// delayed and not canceled the default behavior is to call the top-level
|
||||
/// window close handler once the browser is ready to be closed. This default
|
||||
/// behavior can be changed for Alloy style browsers by implementing
|
||||
/// CefLifeSpanHandler::DoClose(). IsReadyToBeClosed() can be used to detect
|
||||
/// mandatory browser close events when customizing close behavior on the
|
||||
/// browser process UI thread.
|
||||
///
|
||||
/*--cef()--*/
|
||||
virtual void CloseBrowser(bool force_close) = 0;
|
||||
|
||||
///
|
||||
/// Helper for closing a browser. Call this method from the top-level window
|
||||
/// close handler (if any). Internally this calls CloseBrowser(false) if the
|
||||
/// close has not yet been initiated. This method returns false while the
|
||||
/// close is pending and true after the close has completed. See
|
||||
/// CloseBrowser() and CefLifeSpanHandler::DoClose() documentation for
|
||||
/// additional usage information. This method must be called on the browser
|
||||
/// process UI thread.
|
||||
/// Helper for closing a browser. This is similar in behavior to
|
||||
/// CLoseBrowser(false) but returns a boolean to reflect the immediate close
|
||||
/// status. Call this method from a top-level window close handler such as
|
||||
/// CefWindowDelegate::CanClose (or platform-specific equivalent) to request
|
||||
/// that the browser close, and return the result to indicate if the window
|
||||
/// close should proceed. Returns false if the close will be delayed
|
||||
/// (JavaScript unload handlers triggered but still pending) or true if the
|
||||
/// close will proceed immediately (possibly asynchronously). See
|
||||
/// CloseBrowser() documentation for additional usage information. This method
|
||||
/// must be called on the browser process UI thread.
|
||||
///
|
||||
/*--cef()--*/
|
||||
virtual bool TryCloseBrowser() = 0;
|
||||
|
||||
///
|
||||
/// Returns true if the browser is ready to be closed, meaning that the close
|
||||
/// has already been initiated and that JavaScript unload handlers have
|
||||
/// already executed or should be ignored. This can be used from a top-level
|
||||
/// window close handler such as CefWindowDelegate::CanClose (or
|
||||
/// platform-specific equivalent) to distringuish between potentially
|
||||
/// cancelable browser close events (like the user clicking the top-level
|
||||
/// window close button before browser close has started) and mandatory
|
||||
/// browser close events (like JavaScript `window.close()` or after browser
|
||||
/// close has started in response to [Try]CloseBrowser()). Not completing the
|
||||
/// browser close for mandatory close events (when this method returns true)
|
||||
/// will leave the browser in a partially closed state that interferes with
|
||||
/// proper functioning. See CloseBrowser() documentation for additional usage
|
||||
/// information. This method must be called on the browser process UI thread.
|
||||
///
|
||||
/*--cef()--*/
|
||||
virtual bool IsReadyToBeClosed() = 0;
|
||||
|
||||
///
|
||||
/// Set whether the browser is focused.
|
||||
///
|
||||
|
|
|
@ -131,34 +131,44 @@ class CefLifeSpanHandler : public virtual CefBaseRefCounted {
|
|||
virtual void OnAfterCreated(CefRefPtr<CefBrowser> browser) {}
|
||||
|
||||
///
|
||||
/// Called when a browser has received a request to close. This may result
|
||||
/// directly from a call to CefBrowserHost::*CloseBrowser() or indirectly if
|
||||
/// the browser is parented to a top-level window created by CEF and the user
|
||||
/// attempts to close that window (by clicking the 'X', for example). The
|
||||
/// DoClose() method will be called after the JavaScript 'onunload' event has
|
||||
/// been fired.
|
||||
/// Called when an Alloy style browser is ready to be closed, meaning that the
|
||||
/// close has already been initiated and that JavaScript unload handlers have
|
||||
/// already executed or should be ignored. This may result directly from a
|
||||
/// call to CefBrowserHost::[Try]CloseBrowser() or indirectly if the browser's
|
||||
/// top-level parent window was created by CEF and the user attempts to
|
||||
/// close that window (by clicking the 'X', for example). DoClose() will not
|
||||
/// be called if the browser's host window/view has already been destroyed
|
||||
/// (via parent window/view hierarchy tear-down, for example), as it is no
|
||||
/// longer possible to customize the close behavior at that point.
|
||||
///
|
||||
/// An application should handle top-level owner window close notifications by
|
||||
/// calling CefBrowserHost::TryCloseBrowser() or
|
||||
/// An application should handle top-level parent window close notifications
|
||||
/// by calling CefBrowserHost::TryCloseBrowser() or
|
||||
/// CefBrowserHost::CloseBrowser(false) instead of allowing the window to
|
||||
/// close immediately (see the examples below). This gives CEF an opportunity
|
||||
/// to process the 'onbeforeunload' event and optionally cancel the close
|
||||
/// to process JavaScript unload handlers and optionally cancel the close
|
||||
/// before DoClose() is called.
|
||||
///
|
||||
/// When windowed rendering is enabled CEF will internally create a window or
|
||||
/// view to host the browser. In that case returning false from DoClose() will
|
||||
/// send the standard close notification to the browser's top-level owner
|
||||
/// window (e.g. WM_CLOSE on Windows, performClose: on OS X, "delete_event" on
|
||||
/// Linux or CefWindowDelegate::CanClose() callback from Views). If the
|
||||
/// browser's host window/view has already been destroyed (via view hierarchy
|
||||
/// tear-down, for example) then DoClose() will not be called for that browser
|
||||
/// since is no longer possible to cancel the close.
|
||||
/// When windowed rendering is enabled CEF will create an internal child
|
||||
/// window/view to host the browser. In that case returning false from
|
||||
/// DoClose() will send the standard close notification to the browser's
|
||||
/// top-level parent window (e.g. WM_CLOSE on Windows, performClose: on OS X,
|
||||
/// "delete_event" on Linux or CefWindowDelegate::CanClose() callback from
|
||||
/// Views).
|
||||
///
|
||||
/// When windowed rendering is disabled returning false from DoClose() will
|
||||
/// cause the browser object to be destroyed immediately.
|
||||
/// When windowed rendering is disabled there is no internal window/view
|
||||
/// and returning false from DoClose() will cause the browser object to be
|
||||
/// destroyed immediately.
|
||||
///
|
||||
/// If the browser's top-level owner window requires a non-standard close
|
||||
/// If the browser's top-level parent window requires a non-standard close
|
||||
/// notification then send that notification from DoClose() and return true.
|
||||
/// You are still required to complete the browser close as soon as possible
|
||||
/// (either by calling [Try]CloseBrowser() or by proceeding with window/view
|
||||
/// hierarchy tear-down), otherwise the browser will be left in a partially
|
||||
/// closed state that interferes with proper functioning. Top-level windows
|
||||
/// created on the browser process UI thread can alternately call
|
||||
/// CefBrowserHost::IsReadyToBeClosed() in the close handler to check close
|
||||
/// status instead of relying on custom DoClose() handling. See documentation
|
||||
/// on that method for additional details.
|
||||
///
|
||||
/// The CefLifeSpanHandler::OnBeforeClose() method will be called after
|
||||
/// DoClose() (if DoClose() is called) and immediately before the browser
|
||||
|
@ -174,7 +184,7 @@ class CefLifeSpanHandler : public virtual CefBaseRefCounted {
|
|||
/// 1. User clicks the window close button which sends a close notification
|
||||
/// to the application's top-level window.
|
||||
/// 2. Application's top-level window receives the close notification and
|
||||
/// calls TryCloseBrowser() (which internally calls CloseBrowser(false)).
|
||||
/// calls TryCloseBrowser() (similar to calling CloseBrowser(false)).
|
||||
/// TryCloseBrowser() returns false so the client cancels the window
|
||||
/// close.
|
||||
/// 3. JavaScript 'onbeforeunload' handler executes and shows the close
|
||||
|
@ -182,15 +192,18 @@ class CefLifeSpanHandler : public virtual CefBaseRefCounted {
|
|||
/// CefJSDialogHandler::OnBeforeUnloadDialog()).
|
||||
/// 4. User approves the close.
|
||||
/// 5. JavaScript 'onunload' handler executes.
|
||||
/// 6. CEF sends a close notification to the application's top-level window
|
||||
/// (because DoClose() returned false by default).
|
||||
/// 7. Application's top-level window receives the close notification and
|
||||
/// 6. Application's DoClose() handler is called and returns false by
|
||||
/// default.
|
||||
/// 7. CEF sends a close notification to the application's top-level window
|
||||
/// (because DoClose() returned false).
|
||||
/// 8. Application's top-level window receives the close notification and
|
||||
/// calls TryCloseBrowser(). TryCloseBrowser() returns true so the client
|
||||
/// allows the window close.
|
||||
/// 8. Application's top-level window is destroyed.
|
||||
/// 9. Application's OnBeforeClose() handler is called and the browser object
|
||||
/// 9. Application's top-level window is destroyed, triggering destruction
|
||||
/// of the child browser window.
|
||||
/// 10. Application's OnBeforeClose() handler is called and the browser object
|
||||
/// is destroyed.
|
||||
/// 10. Application exits by calling CefQuitMessageLoop() if no other browsers
|
||||
/// 11. Application exits by calling CefQuitMessageLoop() if no other browsers
|
||||
/// exist.
|
||||
///
|
||||
/// Example 2: Using CefBrowserHost::CloseBrowser(false) and implementing the
|
||||
|
@ -208,12 +221,15 @@ class CefLifeSpanHandler : public virtual CefBaseRefCounted {
|
|||
/// 4. User approves the close.
|
||||
/// 5. JavaScript 'onunload' handler executes.
|
||||
/// 6. Application's DoClose() handler is called. Application will:
|
||||
/// A. Set a flag to indicate that the next close attempt will be allowed.
|
||||
/// A. Set a flag to indicate that the next top-level window close attempt
|
||||
/// will be allowed.
|
||||
/// B. Return false.
|
||||
/// 7. CEF sends an close notification to the application's top-level window.
|
||||
/// 7. CEF sends a close notification to the application's top-level window
|
||||
/// (because DoClose() returned false).
|
||||
/// 8. Application's top-level window receives the close notification and
|
||||
/// allows the window to close based on the flag from #6B.
|
||||
/// 9. Application's top-level window is destroyed.
|
||||
/// allows the window to close based on the flag from #6A.
|
||||
/// 9. Application's top-level window is destroyed, triggering destruction
|
||||
/// of the child browser window.
|
||||
/// 10. Application's OnBeforeClose() handler is called and the browser object
|
||||
/// is destroyed.
|
||||
/// 11. Application exits by calling CefQuitMessageLoop() if no other browsers
|
||||
|
|
|
@ -452,6 +452,20 @@ bool CefBrowserHostBase::HasView() {
|
|||
return is_views_hosted_;
|
||||
}
|
||||
|
||||
bool CefBrowserHostBase::IsReadyToBeClosed() {
|
||||
if (!CEF_CURRENTLY_ON_UIT()) {
|
||||
DCHECK(false) << "called on invalid thread";
|
||||
return false;
|
||||
}
|
||||
|
||||
if (auto web_contents = GetWebContents()) {
|
||||
return static_cast<content::RenderFrameHostImpl*>(
|
||||
web_contents->GetPrimaryMainFrame())
|
||||
->IsPageReadyToBeClosed();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void CefBrowserHostBase::SetFocus(bool focus) {
|
||||
if (!CEF_CURRENTLY_ON_UIT()) {
|
||||
CEF_POST_TASK(CEF_UIT,
|
||||
|
|
|
@ -218,6 +218,7 @@ class CefBrowserHostBase : public CefBrowserHost,
|
|||
double GetZoomLevel() override;
|
||||
void SetZoomLevel(double zoomLevel) override;
|
||||
bool HasView() override;
|
||||
bool IsReadyToBeClosed() override;
|
||||
void SetFocus(bool focus) override;
|
||||
void RunFileDialog(FileDialogMode mode,
|
||||
const CefString& title,
|
||||
|
|
|
@ -63,6 +63,10 @@ class PopupWindowDelegate : public CefWindowDelegate {
|
|||
return true;
|
||||
}
|
||||
|
||||
cef_runtime_style_t GetWindowRuntimeStyle() override {
|
||||
return browser_view_->GetRuntimeStyle();
|
||||
}
|
||||
|
||||
private:
|
||||
CefRefPtr<CefBrowserView> browser_view_;
|
||||
|
||||
|
@ -195,8 +199,9 @@ void CefBrowserPlatformDelegate::PopupWebContentsCreated(
|
|||
}
|
||||
|
||||
CefRefPtr<CefBrowserViewDelegate> new_delegate;
|
||||
|
||||
CefRefPtr<CefBrowserViewDelegate> opener_delegate;
|
||||
cef_runtime_style_t opener_runtime_style = CEF_RUNTIME_STYLE_DEFAULT;
|
||||
|
||||
auto browser_view = GetBrowserView();
|
||||
if (browser_view) {
|
||||
// When |this| (the popup opener) is Views-hosted use the current delegate.
|
||||
|
@ -212,12 +217,22 @@ void CefBrowserPlatformDelegate::PopupWebContentsCreated(
|
|||
browser_view, settings, client, is_devtools);
|
||||
}
|
||||
|
||||
if (browser_view) {
|
||||
opener_runtime_style = browser_view->GetRuntimeStyle();
|
||||
} else if (opener_delegate) {
|
||||
opener_runtime_style = opener_delegate->GetBrowserRuntimeStyle();
|
||||
}
|
||||
|
||||
// Create a new BrowserView for the popup.
|
||||
CefRefPtr<CefBrowserViewImpl> new_browser_view =
|
||||
CefBrowserViewImpl::CreateForPopup(settings, new_delegate, is_devtools);
|
||||
CefBrowserViewImpl::CreateForPopup(settings, new_delegate, is_devtools,
|
||||
opener_runtime_style);
|
||||
|
||||
// Associate the PlatformDelegate with the new BrowserView.
|
||||
new_platform_delegate->SetBrowserView(new_browser_view);
|
||||
|
||||
// Keep the BrowserView alive until PopupBrowserCreated() is called.
|
||||
new_browser_view->AddRef();
|
||||
}
|
||||
|
||||
void CefBrowserPlatformDelegate::PopupBrowserCreated(
|
||||
|
@ -255,6 +270,9 @@ void CefBrowserPlatformDelegate::PopupBrowserCreated(
|
|||
CefWindow::CreateTopLevelWindow(
|
||||
new PopupWindowDelegate(new_browser_view.get()));
|
||||
}
|
||||
|
||||
// Release the reference added in PopupWebContentsCreated().
|
||||
new_browser_view->Release();
|
||||
}
|
||||
|
||||
CefRefPtr<CefBrowserViewDelegate>
|
||||
|
|
|
@ -165,14 +165,47 @@ void ChromeBrowserHostImpl::OnSetFocus(cef_focus_source_t source) {
|
|||
}
|
||||
|
||||
void ChromeBrowserHostImpl::CloseBrowser(bool force_close) {
|
||||
if (!CEF_CURRENTLY_ON_UIT()) {
|
||||
CEF_POST_TASK(CEF_UIT, base::BindOnce(&ChromeBrowserHostImpl::CloseBrowser,
|
||||
this, force_close));
|
||||
return;
|
||||
}
|
||||
|
||||
if (!force_close) {
|
||||
TryCloseBrowser();
|
||||
return;
|
||||
}
|
||||
|
||||
// Always do this asynchronously because TabStripModel is not re-entrant.
|
||||
CEF_POST_TASK(CEF_UIT, base::BindOnce(&ChromeBrowserHostImpl::DoCloseBrowser,
|
||||
this, force_close));
|
||||
CEF_POST_TASK(CEF_UIT,
|
||||
base::BindOnce(&ChromeBrowserHostImpl::DoCloseBrowser, this));
|
||||
}
|
||||
|
||||
bool ChromeBrowserHostImpl::TryCloseBrowser() {
|
||||
// TODO(chrome): Handle the case where the browser may not close immediately.
|
||||
CloseBrowser(true);
|
||||
if (!CEF_CURRENTLY_ON_UIT()) {
|
||||
DCHECK(false) << "called on invalid thread";
|
||||
return false;
|
||||
}
|
||||
|
||||
if (auto* web_contents = GetWebContents()) {
|
||||
// This check works as follows:
|
||||
// 1. Returns false if the main frame is ready to close
|
||||
// (IsPageReadyToBeClosed returns true).
|
||||
// 2. Otherwise returns true if any frame in the frame tree needs to run
|
||||
// beforeunload or unload-time event handlers.
|
||||
// 3. Otherwise returns false.
|
||||
if (web_contents->NeedToFireBeforeUnloadOrUnloadEvents()) {
|
||||
// Will result in a call to Browser::BeforeUnloadFired and, if the close
|
||||
// isn't canceled, Browser::CloseContents which indirectly calls
|
||||
// TabStripModel::CloseWebContentsAt (similar to DoCloseBrowser but
|
||||
// without CLOSE_USER_GESTURE). Additional calls to DispatchBeforeUnload
|
||||
// while the unload is pending will be ignored.
|
||||
web_contents->DispatchBeforeUnload(/*auto_cancel=*/false);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
CloseBrowser(/*force_close=*/true);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -551,7 +584,7 @@ void ChromeBrowserHostImpl::DestroyBrowser() {
|
|||
// WebContents first. See comments on CefBrowserHostBase::DestroyBrowser.
|
||||
if (GetWebContents()) {
|
||||
// Triggers a call to OnWebContentsDestroyed.
|
||||
DoCloseBrowser(/*force_close=*/true);
|
||||
DoCloseBrowser();
|
||||
DCHECK(!GetWebContents());
|
||||
}
|
||||
|
||||
|
@ -565,15 +598,13 @@ void ChromeBrowserHostImpl::DestroyBrowser() {
|
|||
CefBrowserHostBase::DestroyBrowser();
|
||||
}
|
||||
|
||||
void ChromeBrowserHostImpl::DoCloseBrowser(bool force_close) {
|
||||
void ChromeBrowserHostImpl::DoCloseBrowser() {
|
||||
CEF_REQUIRE_UIT();
|
||||
if (browser_) {
|
||||
// Like chrome::CloseTab() but specifying the WebContents.
|
||||
const int tab_index = GetCurrentTabIndex();
|
||||
if (tab_index != TabStripModel::kNoTab) {
|
||||
// This will trigger destruction of the Browser and WebContents.
|
||||
// TODO(chrome): Handle the case where this method returns false,
|
||||
// indicating that the contents were not closed immediately.
|
||||
browser_->tab_strip_model()->CloseWebContentsAt(
|
||||
tab_index, TabCloseTypes::CLOSE_CREATE_HISTORICAL_TAB |
|
||||
TabCloseTypes::CLOSE_USER_GESTURE);
|
||||
|
|
|
@ -169,7 +169,7 @@ class ChromeBrowserHostImpl : public CefBrowserHostBase {
|
|||
bool WillBeDestroyed() const override;
|
||||
void DestroyBrowser() override;
|
||||
|
||||
void DoCloseBrowser(bool force_close);
|
||||
void DoCloseBrowser();
|
||||
|
||||
// Returns the current tab index for the associated WebContents, or
|
||||
// TabStripModel::kNoTab if not found.
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
|
||||
#if BUILDFLAG(IS_LINUX)
|
||||
#include "base/linux_util.h"
|
||||
#include "cef/libcef/browser/printing/print_dialog_linux.h"
|
||||
#endif
|
||||
|
||||
#if BUILDFLAG(IS_WIN)
|
||||
|
@ -83,4 +84,11 @@ void ChromeBrowserMainExtraPartsCef::ToolkitInitialized() {
|
|||
// Override the default Chrome client.
|
||||
SetConstrainedWindowViewsClient(CreateAlloyConstrainedWindowViewsClient(
|
||||
CreateChromeConstrainedWindowViewsClient()));
|
||||
|
||||
#if BUILDFLAG(IS_LINUX)
|
||||
auto printing_delegate = new CefPrintingContextLinuxDelegate();
|
||||
auto default_delegate =
|
||||
ui::PrintingContextLinuxDelegate::SetInstance(printing_delegate);
|
||||
printing_delegate->SetDefaultDelegate(default_delegate);
|
||||
#endif // BUILDFLAG(IS_LINUX)
|
||||
}
|
||||
|
|
|
@ -24,7 +24,8 @@ void CefBrowserPlatformDelegateChromeViews::SetBrowserView(
|
|||
CefRefPtr<CefBrowserView> browser_view) {
|
||||
DCHECK(!browser_view_);
|
||||
DCHECK(browser_view);
|
||||
browser_view_ = static_cast<CefBrowserViewImpl*>(browser_view.get());
|
||||
browser_view_ =
|
||||
static_cast<CefBrowserViewImpl*>(browser_view.get())->GetWeakPtr();
|
||||
}
|
||||
|
||||
void CefBrowserPlatformDelegateChromeViews::WebContentsCreated(
|
||||
|
@ -37,7 +38,10 @@ void CefBrowserPlatformDelegateChromeViews::WebContentsCreated(
|
|||
void CefBrowserPlatformDelegateChromeViews::WebContentsDestroyed(
|
||||
content::WebContents* web_contents) {
|
||||
CefBrowserPlatformDelegateChrome::WebContentsDestroyed(web_contents);
|
||||
browser_view_->WebContentsDestroyed(web_contents);
|
||||
// |browser_view_| may be destroyed before this callback arrives.
|
||||
if (browser_view_) {
|
||||
browser_view_->WebContentsDestroyed(web_contents);
|
||||
}
|
||||
}
|
||||
|
||||
void CefBrowserPlatformDelegateChromeViews::BrowserCreated(
|
||||
|
@ -48,7 +52,7 @@ void CefBrowserPlatformDelegateChromeViews::BrowserCreated(
|
|||
|
||||
void CefBrowserPlatformDelegateChromeViews::NotifyBrowserCreated() {
|
||||
if (auto delegate = browser_view_->delegate()) {
|
||||
delegate->OnBrowserCreated(browser_view_, browser_.get());
|
||||
delegate->OnBrowserCreated(browser_view_.get(), browser_.get());
|
||||
|
||||
// DevTools windows hide the notification bubble by default. However, we
|
||||
// don't currently have the ability to intercept WebContents creation via
|
||||
|
@ -75,8 +79,9 @@ void CefBrowserPlatformDelegateChromeViews::NotifyBrowserCreated() {
|
|||
}
|
||||
|
||||
void CefBrowserPlatformDelegateChromeViews::NotifyBrowserDestroyed() {
|
||||
if (browser_view_->delegate()) {
|
||||
browser_view_->delegate()->OnBrowserDestroyed(browser_view_,
|
||||
// |browser_view_| may be destroyed before this callback arrives.
|
||||
if (browser_view_ && browser_view_->delegate()) {
|
||||
browser_view_->delegate()->OnBrowserDestroyed(browser_view_.get(),
|
||||
browser_.get());
|
||||
}
|
||||
}
|
||||
|
@ -84,7 +89,11 @@ void CefBrowserPlatformDelegateChromeViews::NotifyBrowserDestroyed() {
|
|||
void CefBrowserPlatformDelegateChromeViews::BrowserDestroyed(
|
||||
CefBrowserHostBase* browser) {
|
||||
CefBrowserPlatformDelegateChrome::BrowserDestroyed(browser);
|
||||
browser_view_->BrowserDestroyed(browser);
|
||||
// |browser_view_| may be destroyed before this callback arrives.
|
||||
if (browser_view_) {
|
||||
browser_view_->BrowserDestroyed(browser);
|
||||
}
|
||||
browser_view_ = nullptr;
|
||||
}
|
||||
|
||||
void CefBrowserPlatformDelegateChromeViews::CloseHostWindow() {
|
||||
|
@ -100,7 +109,7 @@ CefWindowHandle CefBrowserPlatformDelegateChromeViews::GetHostWindowHandle()
|
|||
}
|
||||
|
||||
views::Widget* CefBrowserPlatformDelegateChromeViews::GetWindowWidget() const {
|
||||
if (browser_view_->root_view()) {
|
||||
if (browser_view_ && browser_view_->root_view()) {
|
||||
return browser_view_->root_view()->GetWidget();
|
||||
}
|
||||
return nullptr;
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
#ifndef CEF_LIBCEF_BROWSER_CHROME_VIEWS_BROWSER_PLATFORM_DELEGATE_CHROME_VIEWS_H_
|
||||
#define CEF_LIBCEF_BROWSER_CHROME_VIEWS_BROWSER_PLATFORM_DELEGATE_CHROME_VIEWS_H_
|
||||
|
||||
#include "base/memory/weak_ptr.h"
|
||||
#include "cef/libcef/browser/chrome/browser_platform_delegate_chrome.h"
|
||||
#include "cef/libcef/browser/views/browser_view_impl.h"
|
||||
|
||||
|
@ -33,12 +34,17 @@ class CefBrowserPlatformDelegateChromeViews
|
|||
void SetBrowserView(CefRefPtr<CefBrowserView> browser_view) override;
|
||||
bool IsViewsHosted() const override;
|
||||
|
||||
CefRefPtr<CefBrowserViewImpl> browser_view() const { return browser_view_; }
|
||||
CefBrowserViewImpl* browser_view() const { return browser_view_.get(); }
|
||||
|
||||
private:
|
||||
CefWindowImpl* GetWindowImpl() const;
|
||||
|
||||
CefRefPtr<CefBrowserViewImpl> browser_view_;
|
||||
// Holding a weak reference here because we want the CefBrowserViewImpl to be
|
||||
// destroyed first if all references are released by the client.
|
||||
// CefBrowserViewImpl destruction will then trigger destruction of any
|
||||
// associated CefBrowserHostBase (which owns this CefBrowserPlatformDelegate
|
||||
// object).
|
||||
base::WeakPtr<CefBrowserViewImpl> browser_view_;
|
||||
};
|
||||
|
||||
#endif // CEF_LIBCEF_BROWSER_CHROME_VIEWS_BROWSER_PLATFORM_DELEGATE_CHROME_VIEWS_H_
|
||||
|
|
|
@ -11,6 +11,13 @@ ChromeBrowserView::ChromeBrowserView(CefBrowserViewImpl* cef_browser_view)
|
|||
: ParentClass(cef_browser_view->delegate()),
|
||||
cef_browser_view_(cef_browser_view) {}
|
||||
|
||||
ChromeBrowserView::~ChromeBrowserView() {
|
||||
if (cef_toolbar_) {
|
||||
WillDestroyToolbar();
|
||||
cef_toolbar_ = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void ChromeBrowserView::InitBrowser(std::unique_ptr<Browser> browser) {
|
||||
DCHECK(!web_view_);
|
||||
|
||||
|
|
|
@ -30,6 +30,7 @@ class ChromeBrowserView
|
|||
|
||||
// |cef_browser_view| is non-nullptr and will outlive this object.
|
||||
explicit ChromeBrowserView(CefBrowserViewImpl* cef_browser_view);
|
||||
~ChromeBrowserView() override;
|
||||
|
||||
ChromeBrowserView(const ChromeBrowserView&) = delete;
|
||||
ChromeBrowserView& operator=(const ChromeBrowserView&) = delete;
|
||||
|
|
|
@ -449,9 +449,6 @@ void CefMainRunner::StartShutdownOnUIThread(
|
|||
content::BrowserTaskExecutor::RunAllPendingTasksOnThreadForTesting(
|
||||
content::BrowserThread::IO);
|
||||
|
||||
static_cast<content::ContentMainRunnerImpl*>(main_runner_.get())
|
||||
->ShutdownOnUIThread();
|
||||
|
||||
std::move(shutdown_on_ui_thread).Run();
|
||||
BeforeUIThreadShutdown();
|
||||
}
|
||||
|
@ -462,6 +459,9 @@ void CefMainRunner::FinishShutdownOnUIThread() {
|
|||
// It is safe to call multiple times.
|
||||
ChromeProcessSingleton::DeleteInstance();
|
||||
}
|
||||
|
||||
static_cast<content::ContentMainRunnerImpl*>(main_runner_.get())
|
||||
->ShutdownOnUIThread();
|
||||
}
|
||||
|
||||
void CefMainRunner::BeforeUIThreadInitialize() {
|
||||
|
|
|
@ -27,7 +27,8 @@ void CefBrowserPlatformDelegateViews::SetBrowserView(
|
|||
CefRefPtr<CefBrowserView> browser_view) {
|
||||
DCHECK(!browser_view_);
|
||||
DCHECK(browser_view);
|
||||
browser_view_ = static_cast<CefBrowserViewImpl*>(browser_view.get());
|
||||
browser_view_ =
|
||||
static_cast<CefBrowserViewImpl*>(browser_view.get())->GetWeakPtr();
|
||||
}
|
||||
|
||||
void CefBrowserPlatformDelegateViews::WebContentsCreated(
|
||||
|
@ -41,7 +42,10 @@ void CefBrowserPlatformDelegateViews::WebContentsCreated(
|
|||
void CefBrowserPlatformDelegateViews::WebContentsDestroyed(
|
||||
content::WebContents* web_contents) {
|
||||
CefBrowserPlatformDelegateAlloy::WebContentsDestroyed(web_contents);
|
||||
browser_view_->WebContentsCreated(web_contents);
|
||||
// |browser_view_| may be destroyed before this callback arrives.
|
||||
if (browser_view_) {
|
||||
browser_view_->WebContentsDestroyed(web_contents);
|
||||
}
|
||||
native_delegate_->WebContentsDestroyed(web_contents);
|
||||
}
|
||||
|
||||
|
@ -57,15 +61,16 @@ void CefBrowserPlatformDelegateViews::NotifyBrowserCreated() {
|
|||
DCHECK(browser_view_);
|
||||
DCHECK(browser_);
|
||||
if (browser_view_->delegate()) {
|
||||
browser_view_->delegate()->OnBrowserCreated(browser_view_, browser_.get());
|
||||
browser_view_->delegate()->OnBrowserCreated(browser_view_.get(),
|
||||
browser_.get());
|
||||
}
|
||||
}
|
||||
|
||||
void CefBrowserPlatformDelegateViews::NotifyBrowserDestroyed() {
|
||||
DCHECK(browser_view_);
|
||||
DCHECK(browser_);
|
||||
if (browser_view_->delegate()) {
|
||||
browser_view_->delegate()->OnBrowserDestroyed(browser_view_,
|
||||
// |browser_view_| may be destroyed before this callback arrives.
|
||||
if (browser_view_ && browser_view_->delegate()) {
|
||||
browser_view_->delegate()->OnBrowserDestroyed(browser_view_.get(),
|
||||
browser_.get());
|
||||
}
|
||||
}
|
||||
|
@ -74,7 +79,10 @@ void CefBrowserPlatformDelegateViews::BrowserDestroyed(
|
|||
CefBrowserHostBase* browser) {
|
||||
CefBrowserPlatformDelegateAlloy::BrowserDestroyed(browser);
|
||||
|
||||
browser_view_->BrowserDestroyed(browser);
|
||||
// |browser_view_| may be destroyed before this callback arrives.
|
||||
if (browser_view_) {
|
||||
browser_view_->BrowserDestroyed(browser);
|
||||
}
|
||||
browser_view_ = nullptr;
|
||||
native_delegate_->BrowserDestroyed(browser);
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
#ifndef CEF_LIBCEF_BROWSER_VIEWS_BROWSER_PLATFORM_DELEGATE_VIEWS_H_
|
||||
#define CEF_LIBCEF_BROWSER_VIEWS_BROWSER_PLATFORM_DELEGATE_VIEWS_H_
|
||||
|
||||
#include "base/memory/weak_ptr.h"
|
||||
#include "cef/libcef/browser/alloy/browser_platform_delegate_alloy.h"
|
||||
#include "cef/libcef/browser/native/browser_platform_delegate_native.h"
|
||||
#include "cef/libcef/browser/views/browser_view_impl.h"
|
||||
|
@ -65,7 +66,13 @@ class CefBrowserPlatformDelegateViews
|
|||
|
||||
private:
|
||||
std::unique_ptr<CefBrowserPlatformDelegateNative> native_delegate_;
|
||||
CefRefPtr<CefBrowserViewImpl> browser_view_;
|
||||
|
||||
// Holding a weak reference here because we want the CefBrowserViewImpl to be
|
||||
// destroyed first if all references are released by the client.
|
||||
// CefBrowserViewImpl destruction will then trigger destruction of any
|
||||
// associated CefBrowserHostBase (which owns this CefBrowserPlatformDelegate
|
||||
// object).
|
||||
base::WeakPtr<CefBrowserViewImpl> browser_view_;
|
||||
};
|
||||
|
||||
#endif // CEF_LIBCEF_BROWSER_VIEWS_BROWSER_PLATFORM_DELEGATE_VIEWS_H_
|
||||
|
|
|
@ -35,30 +35,39 @@ std::optional<cef_gesture_command_t> GetGestureCommand(
|
|||
return std::nullopt;
|
||||
}
|
||||
|
||||
bool ComputeAlloyStyle(CefBrowserViewDelegate* cef_delegate,
|
||||
bool is_devtools_popup) {
|
||||
// Alloy style is not supported with Chrome DevTools popups.
|
||||
const bool supports_alloy_style = !is_devtools_popup;
|
||||
const auto default_style = CEF_RUNTIME_STYLE_CHROME;
|
||||
|
||||
auto result_style = default_style;
|
||||
|
||||
if (cef_delegate) {
|
||||
auto requested_style = cef_delegate->GetBrowserRuntimeStyle();
|
||||
if (requested_style == CEF_RUNTIME_STYLE_ALLOY) {
|
||||
if (supports_alloy_style) {
|
||||
result_style = requested_style;
|
||||
} else {
|
||||
LOG(ERROR) << "GetBrowserRuntimeStyle() requested Alloy style; only "
|
||||
"Chrome style is supported";
|
||||
}
|
||||
} else if (requested_style == CEF_RUNTIME_STYLE_CHROME) {
|
||||
// Chrome style is always supported.
|
||||
result_style = requested_style;
|
||||
bool ComputeAlloyStyle(
|
||||
CefBrowserViewDelegate* cef_delegate,
|
||||
bool is_devtools_popup,
|
||||
std::optional<cef_runtime_style_t> opener_runtime_style) {
|
||||
if (is_devtools_popup) {
|
||||
// Alloy style is not supported with Chrome DevTools popups.
|
||||
if (cef_delegate &&
|
||||
cef_delegate->GetBrowserRuntimeStyle() == CEF_RUNTIME_STYLE_ALLOY) {
|
||||
LOG(ERROR) << "GetBrowserRuntimeStyle() requested Alloy style; only "
|
||||
"Chrome style is supported for DevTools popups";
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
return result_style == CEF_RUNTIME_STYLE_ALLOY;
|
||||
if (opener_runtime_style) {
|
||||
// Popup style must match the opener style.
|
||||
const bool opener_alloy_style =
|
||||
*opener_runtime_style == CEF_RUNTIME_STYLE_ALLOY;
|
||||
if (cef_delegate) {
|
||||
const auto requested_style = cef_delegate->GetBrowserRuntimeStyle();
|
||||
if (requested_style != CEF_RUNTIME_STYLE_DEFAULT &&
|
||||
requested_style != (opener_alloy_style ? CEF_RUNTIME_STYLE_ALLOY
|
||||
: CEF_RUNTIME_STYLE_CHROME)) {
|
||||
LOG(ERROR)
|
||||
<< "GetBrowserRuntimeStyle() for popups must match opener style";
|
||||
}
|
||||
}
|
||||
return opener_alloy_style;
|
||||
}
|
||||
|
||||
// Chrome style is the default unless Alloy is specifically requested.
|
||||
return cef_delegate &&
|
||||
cef_delegate->GetBrowserRuntimeStyle() == CEF_RUNTIME_STYLE_ALLOY;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
@ -111,7 +120,8 @@ CefRefPtr<CefBrowserViewImpl> CefBrowserViewImpl::Create(
|
|||
}
|
||||
|
||||
CefRefPtr<CefBrowserViewImpl> browser_view =
|
||||
new CefBrowserViewImpl(delegate, /*is_devtools_popup=*/false);
|
||||
new CefBrowserViewImpl(delegate, /*is_devtools_popup=*/false,
|
||||
/*opener_runtime_style=*/std::nullopt);
|
||||
browser_view->SetPendingBrowserCreateParams(
|
||||
window_info, client, url, settings, extra_info, request_context);
|
||||
browser_view->Initialize();
|
||||
|
@ -123,16 +133,38 @@ CefRefPtr<CefBrowserViewImpl> CefBrowserViewImpl::Create(
|
|||
CefRefPtr<CefBrowserViewImpl> CefBrowserViewImpl::CreateForPopup(
|
||||
const CefBrowserSettings& settings,
|
||||
CefRefPtr<CefBrowserViewDelegate> delegate,
|
||||
bool is_devtools) {
|
||||
bool is_devtools,
|
||||
cef_runtime_style_t opener_runtime_style) {
|
||||
CEF_REQUIRE_UIT_RETURN(nullptr);
|
||||
|
||||
CefRefPtr<CefBrowserViewImpl> browser_view =
|
||||
new CefBrowserViewImpl(delegate, is_devtools);
|
||||
new CefBrowserViewImpl(delegate, is_devtools, opener_runtime_style);
|
||||
browser_view->Initialize();
|
||||
browser_view->SetDefaults(settings);
|
||||
return browser_view;
|
||||
}
|
||||
|
||||
CefBrowserViewImpl::~CefBrowserViewImpl() {
|
||||
// We want no further callbacks to this object.
|
||||
weak_ptr_factory_.InvalidateWeakPtrs();
|
||||
|
||||
// |browser_| may exist here if the BrowserView was removed from the Views
|
||||
// hierarchy prior to tear-down and the last BrowserView reference was
|
||||
// released. In that case DisassociateFromWidget() will be called when the
|
||||
// BrowserView is removed from the Window but Detach() will not be called
|
||||
// because the BrowserView was not destroyed via the Views hierarchy
|
||||
// tear-down.
|
||||
DCHECK(!cef_widget_);
|
||||
if (browser_ && !browser_->WillBeDestroyed()) {
|
||||
// With Alloy style |browser_| will disappear when WindowDestroyed()
|
||||
// indirectly calls BrowserDestroyed() so keep a reference.
|
||||
CefRefPtr<CefBrowserHostBase> browser = browser_;
|
||||
|
||||
// Force the browser to be destroyed.
|
||||
browser->WindowDestroyed();
|
||||
}
|
||||
}
|
||||
|
||||
void CefBrowserViewImpl::WebContentsCreated(
|
||||
content::WebContents* web_contents) {
|
||||
if (web_view()) {
|
||||
|
@ -269,8 +301,8 @@ void CefBrowserViewImpl::AddedToWidget() {
|
|||
CefWidget* cef_widget = CefWidget::GetForWidget(widget);
|
||||
DCHECK(cef_widget);
|
||||
|
||||
if (!browser_) {
|
||||
if (cef_widget->IsAlloyStyle() && !is_alloy_style_) {
|
||||
if (!browser_ && !is_alloy_style_) {
|
||||
if (cef_widget->IsAlloyStyle()) {
|
||||
LOG(ERROR) << "Cannot add Chrome style BrowserView to Alloy style Window";
|
||||
return;
|
||||
}
|
||||
|
@ -337,9 +369,12 @@ bool CefBrowserViewImpl::OnGestureEvent(ui::GestureEvent* event) {
|
|||
|
||||
CefBrowserViewImpl::CefBrowserViewImpl(
|
||||
CefRefPtr<CefBrowserViewDelegate> delegate,
|
||||
bool is_devtools_popup)
|
||||
bool is_devtools_popup,
|
||||
std::optional<cef_runtime_style_t> opener_runtime_style)
|
||||
: ParentClass(delegate),
|
||||
is_alloy_style_(ComputeAlloyStyle(delegate.get(), is_devtools_popup)),
|
||||
is_alloy_style_(ComputeAlloyStyle(delegate.get(),
|
||||
is_devtools_popup,
|
||||
opener_runtime_style)),
|
||||
weak_ptr_factory_(this) {}
|
||||
|
||||
void CefBrowserViewImpl::SetPendingBrowserCreateParams(
|
||||
|
|
|
@ -6,6 +6,8 @@
|
|||
#define CEF_LIBCEF_BROWSER_VIEWS_BROWSER_VIEW_IMPL_H_
|
||||
#pragma once
|
||||
|
||||
#include <optional>
|
||||
|
||||
#include "base/functional/callback_forward.h"
|
||||
#include "base/memory/raw_ptr.h"
|
||||
#include "base/memory/weak_ptr.h"
|
||||
|
@ -33,6 +35,8 @@ class CefBrowserViewImpl
|
|||
CefBrowserViewImpl(const CefBrowserViewImpl&) = delete;
|
||||
CefBrowserViewImpl& operator=(const CefBrowserViewImpl&) = delete;
|
||||
|
||||
~CefBrowserViewImpl() override;
|
||||
|
||||
// Create a new CefBrowserView instance. |delegate| may be nullptr.
|
||||
// |window_info| will only be used when creating a Chrome child window.
|
||||
static CefRefPtr<CefBrowserViewImpl> Create(
|
||||
|
@ -49,7 +53,8 @@ class CefBrowserViewImpl
|
|||
static CefRefPtr<CefBrowserViewImpl> CreateForPopup(
|
||||
const CefBrowserSettings& settings,
|
||||
CefRefPtr<CefBrowserViewDelegate> delegate,
|
||||
bool is_devtools);
|
||||
bool is_devtools,
|
||||
cef_runtime_style_t opener_runtime_style);
|
||||
|
||||
// Called from CefBrowserPlatformDelegate[Chrome]Views.
|
||||
void WebContentsCreated(content::WebContents* web_contents);
|
||||
|
@ -96,12 +101,17 @@ class CefBrowserViewImpl
|
|||
bool IsAlloyStyle() const { return is_alloy_style_; }
|
||||
bool IsChromeStyle() const { return !is_alloy_style_; }
|
||||
|
||||
base::WeakPtr<CefBrowserViewImpl> GetWeakPtr() {
|
||||
return weak_ptr_factory_.GetWeakPtr();
|
||||
}
|
||||
|
||||
private:
|
||||
// Create a new implementation object.
|
||||
// Always call Initialize() after creation.
|
||||
// |delegate| may be nullptr.
|
||||
CefBrowserViewImpl(CefRefPtr<CefBrowserViewDelegate> delegate,
|
||||
bool is_devtools_popup);
|
||||
bool is_devtools_popup,
|
||||
std::optional<cef_runtime_style_t> opener_runtime_style);
|
||||
|
||||
void SetPendingBrowserCreateParams(
|
||||
const CefWindowInfo& window_info,
|
||||
|
|
|
@ -52,6 +52,7 @@ class CefNativeWidgetMac : public views::NativeWidgetMac {
|
|||
bool IsCefWindowInitialized() const;
|
||||
|
||||
raw_ptr<BrowserView, AcrossTasksDanglingUntriaged> browser_view_ = nullptr;
|
||||
bool initialized_ = false;
|
||||
};
|
||||
|
||||
#endif // CEF_LIBCEF_BROWSER_VIEWS_NATIVE_WIDGET_MAC_H_
|
||||
|
|
|
@ -138,7 +138,12 @@ void CefNativeWidgetMac::OnWindowFullscreenTransitionComplete() {
|
|||
}
|
||||
|
||||
void CefNativeWidgetMac::OnWindowInitialized() {
|
||||
if (!browser_view_) {
|
||||
// This connects the native widget with the command dispatcher so accelerators
|
||||
// work even if a browser_view_ is not created later.
|
||||
// The initialized_ check is necessary because the method can be called twice:
|
||||
// 1. From NativeWidgetMac::InitNativeWidget
|
||||
// 2. From ChromeBrowserFrame::Init
|
||||
if (initialized_) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -146,10 +151,12 @@ void CefNativeWidgetMac::OnWindowInitialized() {
|
|||
if (auto* bridge = GetInProcessNSWindowBridge()) {
|
||||
bridge->SetCommandDispatcher([[ChromeCommandDispatcherDelegate alloc] init],
|
||||
[[BrowserWindowCommandHandler alloc] init]);
|
||||
} else {
|
||||
initialized_ = true;
|
||||
} else if (browser_view_) {
|
||||
if (auto* host = GetHostForBrowser(browser_view_->browser())) {
|
||||
host->GetAppShim()->CreateCommandDispatcherForWidget(
|
||||
GetNSWindowHost()->bridged_native_widget_id());
|
||||
initialized_ = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -280,18 +280,17 @@ void CefOverlayViewHost::SetOverlayBounds(const gfx::Rect& bounds) {
|
|||
return;
|
||||
}
|
||||
|
||||
gfx::Rect new_bounds = bounds;
|
||||
|
||||
// Keep the result inside the widget.
|
||||
new_bounds.Intersect(window_view_->bounds());
|
||||
|
||||
if (new_bounds == bounds_) {
|
||||
// Empty bounds are not allowed.
|
||||
if (bounds.IsEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
bounds_changing_ = true;
|
||||
bounds_ = bounds;
|
||||
|
||||
// Keep the result inside the widget.
|
||||
bounds_.Intersect(window_view_->bounds());
|
||||
|
||||
bounds_ = new_bounds;
|
||||
if (view_->size() != bounds_.size()) {
|
||||
view_->SetSize(bounds_.size());
|
||||
}
|
||||
|
@ -313,6 +312,11 @@ void CefOverlayViewHost::OnViewBoundsChanged(views::View* observed_view) {
|
|||
MoveIfNecessary();
|
||||
}
|
||||
|
||||
void CefOverlayViewHost::OnViewIsDeleting(views::View* observed_view) {
|
||||
view_ = nullptr;
|
||||
Cleanup();
|
||||
}
|
||||
|
||||
gfx::Rect CefOverlayViewHost::ComputeBounds() const {
|
||||
// This method is only used with corner docking.
|
||||
DCHECK_NE(docking_mode_, CEF_DOCKING_MODE_CUSTOM);
|
||||
|
|
|
@ -44,6 +44,7 @@ class CefOverlayViewHost : public views::WidgetDelegate,
|
|||
|
||||
// views::ViewObserver methods:
|
||||
void OnViewBoundsChanged(views::View* observed_view) override;
|
||||
void OnViewIsDeleting(views::View* observed_view) override;
|
||||
|
||||
cef_docking_mode_t docking_mode() const { return docking_mode_; }
|
||||
CefRefPtr<CefOverlayController> controller() const { return cef_controller_; }
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
// implementations. See the translator.README.txt file in the tools directory
|
||||
// for more information.
|
||||
//
|
||||
// $hash=434a753c90262b051077f7a79f3106ac52ffbf75$
|
||||
// $hash=8a2a8a4853c3869876ffad3e6c175945ac1c5021$
|
||||
//
|
||||
|
||||
#include "libcef_dll/cpptoc/browser_host_cpptoc.h"
|
||||
|
@ -191,6 +191,24 @@ browser_host_try_close_browser(struct _cef_browser_host_t* self) {
|
|||
return _retval;
|
||||
}
|
||||
|
||||
int CEF_CALLBACK
|
||||
browser_host_is_ready_to_be_closed(struct _cef_browser_host_t* self) {
|
||||
shutdown_checker::AssertNotShutdown();
|
||||
|
||||
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
|
||||
|
||||
DCHECK(self);
|
||||
if (!self) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Execute
|
||||
bool _retval = CefBrowserHostCppToC::Get(self)->IsReadyToBeClosed();
|
||||
|
||||
// Return type: bool
|
||||
return _retval;
|
||||
}
|
||||
|
||||
void CEF_CALLBACK browser_host_set_focus(struct _cef_browser_host_t* self,
|
||||
int focus) {
|
||||
shutdown_checker::AssertNotShutdown();
|
||||
|
@ -1514,6 +1532,7 @@ CefBrowserHostCppToC::CefBrowserHostCppToC() {
|
|||
GetStruct()->get_browser = browser_host_get_browser;
|
||||
GetStruct()->close_browser = browser_host_close_browser;
|
||||
GetStruct()->try_close_browser = browser_host_try_close_browser;
|
||||
GetStruct()->is_ready_to_be_closed = browser_host_is_ready_to_be_closed;
|
||||
GetStruct()->set_focus = browser_host_set_focus;
|
||||
GetStruct()->get_window_handle = browser_host_get_window_handle;
|
||||
GetStruct()->get_opener_window_handle = browser_host_get_opener_window_handle;
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
// implementations. See the translator.README.txt file in the tools directory
|
||||
// for more information.
|
||||
//
|
||||
// $hash=dac19ba091b3acf3e1587b176e28bc9f9c8c8dd0$
|
||||
// $hash=2319d794dd3a38c448908114d1b4ea37b34f89dd$
|
||||
//
|
||||
|
||||
#include "libcef_dll/ctocpp/browser_host_ctocpp.h"
|
||||
|
@ -131,6 +131,23 @@ NO_SANITIZE("cfi-icall") bool CefBrowserHostCToCpp::TryCloseBrowser() {
|
|||
return _retval ? true : false;
|
||||
}
|
||||
|
||||
NO_SANITIZE("cfi-icall") bool CefBrowserHostCToCpp::IsReadyToBeClosed() {
|
||||
shutdown_checker::AssertNotShutdown();
|
||||
|
||||
cef_browser_host_t* _struct = GetStruct();
|
||||
if (CEF_MEMBER_MISSING(_struct, is_ready_to_be_closed)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
|
||||
|
||||
// Execute
|
||||
int _retval = _struct->is_ready_to_be_closed(_struct);
|
||||
|
||||
// Return type: bool
|
||||
return _retval ? true : false;
|
||||
}
|
||||
|
||||
NO_SANITIZE("cfi-icall") void CefBrowserHostCToCpp::SetFocus(bool focus) {
|
||||
shutdown_checker::AssertNotShutdown();
|
||||
|
||||
|
@ -1111,8 +1128,8 @@ void CefBrowserHostCToCpp::DragSourceSystemDragEnded() {
|
|||
}
|
||||
|
||||
NO_SANITIZE("cfi-icall")
|
||||
CefRefPtr<
|
||||
CefNavigationEntry> CefBrowserHostCToCpp::GetVisibleNavigationEntry() {
|
||||
CefRefPtr<CefNavigationEntry>
|
||||
CefBrowserHostCToCpp::GetVisibleNavigationEntry() {
|
||||
shutdown_checker::AssertNotShutdown();
|
||||
|
||||
cef_browser_host_t* _struct = GetStruct();
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
// implementations. See the translator.README.txt file in the tools directory
|
||||
// for more information.
|
||||
//
|
||||
// $hash=9f40e4ce3e46a895b5bf644bebdc2d802c9b598b$
|
||||
// $hash=73d8659f17a4ae3319b5bf20807d5c69a1759c04$
|
||||
//
|
||||
|
||||
#ifndef CEF_LIBCEF_DLL_CTOCPP_BROWSER_HOST_CTOCPP_H_
|
||||
|
@ -41,6 +41,7 @@ class CefBrowserHostCToCpp : public CefCToCppRefCounted<CefBrowserHostCToCpp,
|
|||
CefRefPtr<CefBrowser> GetBrowser() override;
|
||||
void CloseBrowser(bool force_close) override;
|
||||
bool TryCloseBrowser() override;
|
||||
bool IsReadyToBeClosed() override;
|
||||
void SetFocus(bool focus) override;
|
||||
CefWindowHandle GetWindowHandle() override;
|
||||
CefWindowHandle GetOpenerWindowHandle() override;
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
|
||||
#include "include/wrapper/cef_message_router.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <limits>
|
||||
#include <map>
|
||||
#include <set>
|
||||
|
|
|
@ -4,8 +4,16 @@
|
|||
|
||||
#include "tests/cefclient/browser/default_client_handler.h"
|
||||
|
||||
#include "tests/cefclient/browser/main_context.h"
|
||||
#include "tests/cefclient/browser/root_window_manager.h"
|
||||
|
||||
namespace client {
|
||||
|
||||
DefaultClientHandler::DefaultClientHandler(std::optional<bool> use_alloy_style)
|
||||
: use_alloy_style_(
|
||||
use_alloy_style.value_or(MainContext::Get()->UseAlloyStyleGlobal())) {
|
||||
}
|
||||
|
||||
// static
|
||||
CefRefPtr<DefaultClientHandler> DefaultClientHandler::GetForClient(
|
||||
CefRefPtr<CefClient> client) {
|
||||
|
@ -16,4 +24,39 @@ CefRefPtr<DefaultClientHandler> DefaultClientHandler::GetForClient(
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
bool DefaultClientHandler::OnBeforePopup(
|
||||
CefRefPtr<CefBrowser> browser,
|
||||
CefRefPtr<CefFrame> frame,
|
||||
const CefString& target_url,
|
||||
const CefString& target_frame_name,
|
||||
CefLifeSpanHandler::WindowOpenDisposition target_disposition,
|
||||
bool user_gesture,
|
||||
const CefPopupFeatures& popupFeatures,
|
||||
CefWindowInfo& windowInfo,
|
||||
CefRefPtr<CefClient>& client,
|
||||
CefBrowserSettings& settings,
|
||||
CefRefPtr<CefDictionaryValue>& extra_info,
|
||||
bool* no_javascript_access) {
|
||||
CEF_REQUIRE_UI_THREAD();
|
||||
|
||||
if (target_disposition == CEF_WOD_NEW_PICTURE_IN_PICTURE) {
|
||||
// Use default handling for document picture-in-picture popups.
|
||||
client = nullptr;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Used to configure default values.
|
||||
RootWindowConfig config(/*command_line=*/nullptr);
|
||||
|
||||
// Potentially create a new RootWindow for the popup browser that will be
|
||||
// created asynchronously.
|
||||
MainContext::Get()->GetRootWindowManager()->CreateRootWindowAsPopup(
|
||||
config.use_views, use_alloy_style_, config.with_controls,
|
||||
/*is_osr=*/false, /*is_devtools=*/false, popupFeatures, windowInfo,
|
||||
client, settings);
|
||||
|
||||
// Allow popup creation.
|
||||
return false;
|
||||
}
|
||||
|
||||
} // namespace client
|
||||
|
|
|
@ -6,6 +6,8 @@
|
|||
#define CEF_TESTS_CEFCLIENT_BROWSER_DEFAULT_CLIENT_HANDLER_H_
|
||||
#pragma once
|
||||
|
||||
#include <optional>
|
||||
|
||||
#include "tests/cefclient/browser/base_client_handler.h"
|
||||
|
||||
namespace client {
|
||||
|
@ -14,18 +16,37 @@ namespace client {
|
|||
// style only.
|
||||
class DefaultClientHandler : public BaseClientHandler {
|
||||
public:
|
||||
DefaultClientHandler() = default;
|
||||
// If |use_alloy_style| is nullopt the global default will be used.
|
||||
explicit DefaultClientHandler(
|
||||
std::optional<bool> use_alloy_style = std::nullopt);
|
||||
|
||||
// Returns the DefaultClientHandler for |client|, or nullptr if |client| is
|
||||
// not a DefaultClientHandler.
|
||||
static CefRefPtr<DefaultClientHandler> GetForClient(
|
||||
CefRefPtr<CefClient> client);
|
||||
|
||||
protected:
|
||||
bool OnBeforePopup(
|
||||
CefRefPtr<CefBrowser> browser,
|
||||
CefRefPtr<CefFrame> frame,
|
||||
const CefString& target_url,
|
||||
const CefString& target_frame_name,
|
||||
CefLifeSpanHandler::WindowOpenDisposition target_disposition,
|
||||
bool user_gesture,
|
||||
const CefPopupFeatures& popupFeatures,
|
||||
CefWindowInfo& windowInfo,
|
||||
CefRefPtr<CefClient>& client,
|
||||
CefBrowserSettings& settings,
|
||||
CefRefPtr<CefDictionaryValue>& extra_info,
|
||||
bool* no_javascript_access) override;
|
||||
|
||||
private:
|
||||
// Used to determine the object type.
|
||||
virtual const void* GetTypeKey() const override { return &kTypeKey; }
|
||||
static constexpr int kTypeKey = 0;
|
||||
|
||||
const bool use_alloy_style_;
|
||||
|
||||
IMPLEMENT_REFCOUNTING(DefaultClientHandler);
|
||||
DISALLOW_COPY_AND_ASSIGN(DefaultClientHandler);
|
||||
};
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
#define IDC_NAV_STOP 203
|
||||
#define ID_QUIT 32500
|
||||
#define ID_FIND 32501
|
||||
#define ID_POPOUT_OVERLAY 32502
|
||||
#define ID_TESTS_FIRST 32700
|
||||
#define ID_TESTS_GETSOURCE 32700
|
||||
#define ID_TESTS_GETTEXT 32701
|
||||
|
|
|
@ -134,8 +134,11 @@ scoped_refptr<RootWindow> RootWindowManager::CreateRootWindowAsPopup(
|
|||
|
||||
if (MainContext::Get()->UseDefaultPopup() || (is_devtools && !use_views)) {
|
||||
// Use default window creation for the popup. A new |client| instance is
|
||||
// still required by cefclient architecture.
|
||||
client = new DefaultClientHandler();
|
||||
// required by cefclient architecture if the type is not already
|
||||
// DefaultClientHandler.
|
||||
if (!DefaultClientHandler::GetForClient(client)) {
|
||||
client = new DefaultClientHandler(use_alloy_style);
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,315 @@
|
|||
// Copyright (c) 2024 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 "tests/cefclient/browser/views_overlay_browser.h"
|
||||
|
||||
#include "include/views/cef_window.h"
|
||||
#include "tests/cefclient/browser/resource.h"
|
||||
#include "tests/cefclient/browser/views_window.h"
|
||||
|
||||
namespace client {
|
||||
|
||||
namespace {
|
||||
|
||||
void AddPopOutAccelerator(CefRefPtr<CefWindow> window) {
|
||||
// Add an accelerator to toggle the BrowserView popout. OnAccelerator will be
|
||||
// called when the accelerator is triggered.
|
||||
window->SetAccelerator(ID_POPOUT_OVERLAY, 'O', /*shift_pressed=*/false,
|
||||
/*ctrl_pressed=*/false, /*alt_pressed=*/true,
|
||||
/*high_priority=*/true);
|
||||
}
|
||||
|
||||
// Popout window delegate implementation.
|
||||
class PopoutWindowDelegate : public CefWindowDelegate {
|
||||
public:
|
||||
PopoutWindowDelegate(base::WeakPtr<ViewsOverlayBrowser> overlay,
|
||||
CefRefPtr<CefBrowserView> browser_view)
|
||||
: overlay_(overlay), browser_view_(browser_view) {}
|
||||
|
||||
PopoutWindowDelegate(const PopoutWindowDelegate&) = delete;
|
||||
PopoutWindowDelegate& operator=(const PopoutWindowDelegate&) = delete;
|
||||
|
||||
static PopoutWindowDelegate* GetForWindow(CefRefPtr<CefWindow> window) {
|
||||
return static_cast<PopoutWindowDelegate*>(window->GetDelegate().get());
|
||||
}
|
||||
|
||||
void OnWindowCreated(CefRefPtr<CefWindow> window) override {
|
||||
window->AddChildView(browser_view_);
|
||||
window->Show();
|
||||
|
||||
// Add the popout accelerator to the popout Window.
|
||||
AddPopOutAccelerator(window);
|
||||
|
||||
browser_view_->RequestFocus();
|
||||
}
|
||||
|
||||
bool CanClose(CefRefPtr<CefWindow> window) override {
|
||||
CefRefPtr<CefBrowser> browser =
|
||||
browser_view_ ? browser_view_->GetBrowser() : nullptr;
|
||||
|
||||
if (overlay_ && browser && !browser->GetHost()->IsReadyToBeClosed()) {
|
||||
// Proceed with the window close, but don't close the browser. The browser
|
||||
// will be returned to the overlay in OnWindowClosing().
|
||||
return_to_overlay_ = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (browser) {
|
||||
// We must close the browser, either because the popout Window is the
|
||||
// final owner of the BrowserView, or because the browser is ready to be
|
||||
// closed internally (e.g. `window.close()` was called).
|
||||
return browser->GetHost()->TryCloseBrowser();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void OnWindowClosing(CefRefPtr<CefWindow> window) override {
|
||||
if (overlay_ && return_to_overlay_) {
|
||||
// Give the browser back to the overlay.
|
||||
overlay_->ToggleBrowserView();
|
||||
}
|
||||
}
|
||||
|
||||
void OnWindowDestroyed(CefRefPtr<CefWindow> window) override {
|
||||
if (overlay_) {
|
||||
overlay_->PopOutWindowDestroyed();
|
||||
overlay_ = nullptr;
|
||||
}
|
||||
browser_view_ = nullptr;
|
||||
}
|
||||
|
||||
cef_runtime_style_t GetWindowRuntimeStyle() override {
|
||||
return browser_view_->GetRuntimeStyle();
|
||||
}
|
||||
|
||||
bool OnAccelerator(CefRefPtr<CefWindow> window, int command_id) override {
|
||||
if (overlay_) {
|
||||
return overlay_->OnAccelerator(window, command_id);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
[[nodiscard]] CefRefPtr<CefBrowserView> DetachBrowserView() {
|
||||
overlay_ = nullptr;
|
||||
auto browser_view = browser_view_;
|
||||
browser_view_ = nullptr;
|
||||
return browser_view;
|
||||
}
|
||||
|
||||
void OverlayDestroyed() { overlay_ = nullptr; }
|
||||
|
||||
private:
|
||||
base::WeakPtr<ViewsOverlayBrowser> overlay_;
|
||||
CefRefPtr<CefBrowserView> browser_view_;
|
||||
bool return_to_overlay_ = false;
|
||||
|
||||
IMPLEMENT_REFCOUNTING(PopoutWindowDelegate);
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
ViewsOverlayBrowser::ViewsOverlayBrowser(ViewsWindow* owner_window)
|
||||
: owner_window_(owner_window) {}
|
||||
|
||||
void ViewsOverlayBrowser::Initialize(
|
||||
CefRefPtr<CefWindow> window,
|
||||
CefRefPtr<CefClient> client,
|
||||
const std::string& url,
|
||||
const CefBrowserSettings& settings,
|
||||
CefRefPtr<CefRequestContext> request_context) {
|
||||
CHECK(!window_);
|
||||
window_ = window;
|
||||
CHECK(window_);
|
||||
|
||||
// Add the accelerator to the main window.
|
||||
AddPopOutAccelerator(window_);
|
||||
|
||||
browser_view_ = CefBrowserView::CreateBrowserView(
|
||||
client, url, settings, nullptr, request_context, this);
|
||||
CHECK(browser_view_);
|
||||
|
||||
// Add the BrowserView to an overlay in the main window.
|
||||
controller_ = window_->AddOverlayView(browser_view_, CEF_DOCKING_MODE_CUSTOM,
|
||||
/*can_activate=*/true);
|
||||
CHECK(controller_);
|
||||
}
|
||||
|
||||
void ViewsOverlayBrowser::Destroy() {
|
||||
window_ = nullptr;
|
||||
|
||||
if (popout_window_) {
|
||||
// The BrowserView is popped out, and the main Window is closed first.
|
||||
// Let the popout Window handle BrowserView destruction.
|
||||
PopoutWindowDelegate::GetForWindow(popout_window_)->OverlayDestroyed();
|
||||
popout_window_->Close();
|
||||
popout_window_ = nullptr;
|
||||
}
|
||||
|
||||
if (controller_) {
|
||||
if (controller_->IsValid()) {
|
||||
controller_->Destroy();
|
||||
}
|
||||
controller_ = nullptr;
|
||||
owner_window_->UpdateDraggableRegions();
|
||||
}
|
||||
|
||||
if (browser_view_) {
|
||||
// We hold the last reference to the BrowserView, and releasing it will
|
||||
// trigger overlay Browser destruction. OnBeforeClose for that Browser may
|
||||
// be called synchronously or asynchronously depending on whether
|
||||
// beforeunload needs to be dispatched.
|
||||
DCHECK(browser_view_->HasOneRef());
|
||||
browser_view_ = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
bool ViewsOverlayBrowser::IsValid() const {
|
||||
// Intentionally not checking |popout_window_->IsValid()| here because the
|
||||
// pop-in behavior will be triggered by |popout_window_| closing.
|
||||
return (controller_ && controller_->IsValid()) || popout_window_;
|
||||
}
|
||||
|
||||
void ViewsOverlayBrowser::ToggleBrowserView() {
|
||||
if (browser_view_) {
|
||||
PopOutBrowserView();
|
||||
} else {
|
||||
PopInBrowserView();
|
||||
}
|
||||
|
||||
owner_window_->UpdateDraggableRegions();
|
||||
}
|
||||
|
||||
void ViewsOverlayBrowser::PopOutBrowserView() {
|
||||
CHECK(browser_view_);
|
||||
|
||||
DCHECK(controller_ && controller_->IsValid());
|
||||
controller_->Destroy();
|
||||
controller_ = nullptr;
|
||||
|
||||
// We hold the only reference to the BrowserView.
|
||||
DCHECK(browser_view_->HasOneRef());
|
||||
|
||||
// Create a new popout Window and pass ownership of the BrowserView.
|
||||
CHECK(!popout_window_);
|
||||
popout_window_ = CefWindow::CreateTopLevelWindow(
|
||||
new PopoutWindowDelegate(weak_ptr_factory_.GetWeakPtr(), browser_view_));
|
||||
browser_view_ = nullptr;
|
||||
}
|
||||
|
||||
void ViewsOverlayBrowser::PopInBrowserView() {
|
||||
CHECK(!browser_view_);
|
||||
|
||||
// Resume ownership of the BrowserView and close the popout Window.
|
||||
CHECK(popout_window_);
|
||||
browser_view_ =
|
||||
PopoutWindowDelegate::GetForWindow(popout_window_)->DetachBrowserView();
|
||||
popout_window_->RemoveChildView(browser_view_);
|
||||
popout_window_->Close();
|
||||
popout_window_ = nullptr;
|
||||
|
||||
// We hold the only reference to the BrowserView.
|
||||
DCHECK(browser_view_->HasOneRef());
|
||||
|
||||
// Add the BrowserView to an overlay in the main window.
|
||||
controller_ = window_->AddOverlayView(browser_view_, CEF_DOCKING_MODE_CUSTOM,
|
||||
/*can_activate=*/true);
|
||||
CHECK(controller_);
|
||||
|
||||
// Make sure the overlay is positioned correctly.
|
||||
UpdateBounds(last_insets_);
|
||||
}
|
||||
|
||||
void ViewsOverlayBrowser::UpdateBounds(CefInsets insets) {
|
||||
last_insets_ = insets;
|
||||
|
||||
if (!controller_) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Update location bar size, position and visibility.
|
||||
const auto window_bounds = window_->GetBounds();
|
||||
|
||||
// Client coordinates with insets.
|
||||
CefRect bounds;
|
||||
bounds.x = insets.left;
|
||||
bounds.width = window_bounds.width - insets.left - insets.right;
|
||||
bounds.y = insets.top;
|
||||
bounds.height = window_bounds.height - insets.top - insets.bottom;
|
||||
|
||||
const auto min_size = browser_view_->GetMinimumSize();
|
||||
if (bounds.width < min_size.width || bounds.height < min_size.height) {
|
||||
// Not enough space.
|
||||
controller_->SetVisible(false);
|
||||
} else {
|
||||
controller_->SetSize(CefSize(bounds.width, bounds.height));
|
||||
controller_->SetBounds(bounds);
|
||||
controller_->SetVisible(true);
|
||||
}
|
||||
}
|
||||
|
||||
void ViewsOverlayBrowser::UpdateDraggableRegions(
|
||||
std::vector<CefDraggableRegion>& window_regions) {
|
||||
if (controller_ && controller_->IsVisible()) {
|
||||
window_regions.emplace_back(controller_->GetBounds(),
|
||||
/*draggable=*/false);
|
||||
}
|
||||
}
|
||||
|
||||
bool ViewsOverlayBrowser::OnAccelerator(CefRefPtr<CefWindow> window,
|
||||
int command_id) {
|
||||
if (IsValid() && command_id == ID_POPOUT_OVERLAY) {
|
||||
ToggleBrowserView();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void ViewsOverlayBrowser::PopOutWindowDestroyed() {
|
||||
popout_window_ = nullptr;
|
||||
}
|
||||
|
||||
CefSize ViewsOverlayBrowser::GetMinimumSize(CefRefPtr<CefView> view) {
|
||||
return CefSize(200, 200);
|
||||
}
|
||||
|
||||
void ViewsOverlayBrowser::OnBrowserDestroyed(
|
||||
CefRefPtr<CefBrowserView> browser_view,
|
||||
CefRefPtr<CefBrowser> browser) {
|
||||
// Might be popped out currently.
|
||||
if (!controller_) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Destroy the overlay controller if the browser is destroyed first (e.g. via
|
||||
// `window.close()`).
|
||||
controller_->Destroy();
|
||||
controller_ = nullptr;
|
||||
owner_window_->UpdateDraggableRegions();
|
||||
}
|
||||
|
||||
CefRefPtr<CefBrowserViewDelegate>
|
||||
ViewsOverlayBrowser::GetDelegateForPopupBrowserView(
|
||||
CefRefPtr<CefBrowserView> browser_view,
|
||||
const CefBrowserSettings& settings,
|
||||
CefRefPtr<CefClient> client,
|
||||
bool is_devtools) {
|
||||
return owner_window_->GetDelegateForPopupBrowserView(browser_view, settings,
|
||||
client, is_devtools);
|
||||
}
|
||||
|
||||
bool ViewsOverlayBrowser::OnPopupBrowserViewCreated(
|
||||
CefRefPtr<CefBrowserView> browser_view,
|
||||
CefRefPtr<CefBrowserView> popup_browser_view,
|
||||
bool is_devtools) {
|
||||
return owner_window_->OnPopupBrowserViewCreated(
|
||||
browser_view, popup_browser_view, is_devtools);
|
||||
}
|
||||
|
||||
cef_runtime_style_t ViewsOverlayBrowser::GetBrowserRuntimeStyle() {
|
||||
// Overlay browser view must always be Alloy style.
|
||||
return CEF_RUNTIME_STYLE_ALLOY;
|
||||
}
|
||||
|
||||
} // namespace client
|
|
@ -0,0 +1,86 @@
|
|||
// Copyright (c) 2024 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_TESTS_CEFCLIENT_BROWSER_VIEWS_OVERLAY_BROWSER_H_
|
||||
#define CEF_TESTS_CEFCLIENT_BROWSER_VIEWS_OVERLAY_BROWSER_H_
|
||||
#pragma once
|
||||
|
||||
#include "include/base/cef_weak_ptr.h"
|
||||
#include "include/views/cef_browser_view.h"
|
||||
#include "include/views/cef_browser_view_delegate.h"
|
||||
#include "include/views/cef_overlay_controller.h"
|
||||
|
||||
namespace client {
|
||||
|
||||
class ViewsWindow;
|
||||
|
||||
// Implements a browser view that receives absolute positioning on top of the
|
||||
// main browser view. All methods must be called on the browser process UI
|
||||
// thread.
|
||||
class ViewsOverlayBrowser : public CefBrowserViewDelegate {
|
||||
public:
|
||||
explicit ViewsOverlayBrowser(ViewsWindow* owner_window);
|
||||
|
||||
void Initialize(CefRefPtr<CefWindow> window,
|
||||
CefRefPtr<CefClient> client,
|
||||
const std::string& url,
|
||||
const CefBrowserSettings& settings,
|
||||
CefRefPtr<CefRequestContext> request_context);
|
||||
void Destroy();
|
||||
|
||||
bool IsValid() const;
|
||||
|
||||
// Move the overlay BrowserView to/from a popout Window.
|
||||
void ToggleBrowserView();
|
||||
|
||||
// Update browser bounds.
|
||||
void UpdateBounds(CefInsets insets);
|
||||
|
||||
// Exclude all regions obscured by overlays.
|
||||
void UpdateDraggableRegions(std::vector<CefDraggableRegion>& window_regions);
|
||||
|
||||
bool OnAccelerator(CefRefPtr<CefWindow> window, int command_id);
|
||||
|
||||
void PopOutWindowDestroyed();
|
||||
|
||||
private:
|
||||
// CefViewDelegate methods:
|
||||
CefSize GetMinimumSize(CefRefPtr<CefView> view) override;
|
||||
|
||||
// CefBrowserViewDelegate methods:
|
||||
void OnBrowserDestroyed(CefRefPtr<CefBrowserView> browser_view,
|
||||
CefRefPtr<CefBrowser> browser) override;
|
||||
CefRefPtr<CefBrowserViewDelegate> GetDelegateForPopupBrowserView(
|
||||
CefRefPtr<CefBrowserView> browser_view,
|
||||
const CefBrowserSettings& settings,
|
||||
CefRefPtr<CefClient> client,
|
||||
bool is_devtools) override;
|
||||
bool OnPopupBrowserViewCreated(CefRefPtr<CefBrowserView> browser_view,
|
||||
CefRefPtr<CefBrowserView> popup_browser_view,
|
||||
bool is_devtools) override;
|
||||
cef_runtime_style_t GetBrowserRuntimeStyle() override;
|
||||
|
||||
// Move the BrowserView to a new top-level Window.
|
||||
void PopOutBrowserView();
|
||||
|
||||
// Return the BrowserView to the overlay.
|
||||
void PopInBrowserView();
|
||||
|
||||
ViewsWindow* const owner_window_;
|
||||
CefRefPtr<CefWindow> window_;
|
||||
CefRefPtr<CefBrowserView> browser_view_;
|
||||
CefRefPtr<CefOverlayController> controller_;
|
||||
CefInsets last_insets_;
|
||||
|
||||
CefRefPtr<CefWindow> popout_window_;
|
||||
|
||||
base::WeakPtrFactory<ViewsOverlayBrowser> weak_ptr_factory_{this};
|
||||
|
||||
IMPLEMENT_REFCOUNTING(ViewsOverlayBrowser);
|
||||
DISALLOW_COPY_AND_ASSIGN(ViewsOverlayBrowser);
|
||||
};
|
||||
|
||||
} // namespace client
|
||||
|
||||
#endif // CEF_TESTS_CEFCLIENT_BROWSER_VIEWS_OVERLAY_BROWSER_H_
|
|
@ -12,6 +12,7 @@
|
|||
#include "include/cef_i18n_util.h"
|
||||
#include "include/views/cef_box_layout.h"
|
||||
#include "include/wrapper/cef_helpers.h"
|
||||
#include "tests/cefclient/browser/default_client_handler.h"
|
||||
#include "tests/cefclient/browser/main_context.h"
|
||||
#include "tests/cefclient/browser/resource.h"
|
||||
#include "tests/cefclient/browser/views_style.h"
|
||||
|
@ -146,6 +147,14 @@ CefRefPtr<ViewsWindow> ViewsWindow::Create(
|
|||
CefRefPtr<ViewsWindow> views_window =
|
||||
new ViewsWindow(type, delegate, nullptr, command_line);
|
||||
|
||||
// Only create an overlay browser for a primary window.
|
||||
if (command_line->HasSwitch(switches::kShowOverlayBrowser)) {
|
||||
views_window->with_overlay_browser_ = true;
|
||||
views_window->initial_url_ = url;
|
||||
views_window->settings_ = settings;
|
||||
views_window->request_context_ = request_context;
|
||||
}
|
||||
|
||||
const auto expected_browser_runtime_style = views_window->use_alloy_style_
|
||||
? CEF_RUNTIME_STYLE_ALLOY
|
||||
: CEF_RUNTIME_STYLE_CHROME;
|
||||
|
@ -345,6 +354,8 @@ void ViewsWindow::SetDraggableRegions(
|
|||
return;
|
||||
}
|
||||
|
||||
last_regions_ = regions;
|
||||
|
||||
// Convert the regions from BrowserView to Window coordinates.
|
||||
std::vector<CefDraggableRegion> window_regions = regions;
|
||||
for (auto& region : window_regions) {
|
||||
|
@ -359,6 +370,11 @@ void ViewsWindow::SetDraggableRegions(
|
|||
overlay_controls_->UpdateDraggableRegions(window_regions);
|
||||
}
|
||||
|
||||
if (overlay_browser_) {
|
||||
// Exclude all regions obscured by overlays.
|
||||
overlay_browser_->UpdateDraggableRegions(window_regions);
|
||||
}
|
||||
|
||||
window_->SetDraggableRegions(window_regions);
|
||||
}
|
||||
|
||||
|
@ -434,6 +450,10 @@ void ViewsWindow::SetTitlebarHeight(const std::optional<float>& height) {
|
|||
NudgeWindow();
|
||||
}
|
||||
|
||||
void ViewsWindow::UpdateDraggableRegions() {
|
||||
SetDraggableRegions(last_regions_);
|
||||
}
|
||||
|
||||
CefRefPtr<CefBrowserViewDelegate> ViewsWindow::GetDelegateForPopupBrowserView(
|
||||
CefRefPtr<CefBrowserView> browser_view,
|
||||
const CefBrowserSettings& settings,
|
||||
|
@ -900,6 +920,8 @@ bool ViewsWindow::OnAccelerator(CefRefPtr<CefWindow> window, int command_id) {
|
|||
if (command_id == ID_QUIT) {
|
||||
delegate_->OnExit();
|
||||
return true;
|
||||
} else if (overlay_browser_) {
|
||||
return overlay_browser_->OnAccelerator(window, command_id);
|
||||
}
|
||||
|
||||
return false;
|
||||
|
@ -1001,6 +1023,19 @@ void ViewsWindow::OnWindowChanged(CefRefPtr<CefView> view, bool added) {
|
|||
CreateLocationBar(),
|
||||
chrome_toolbar_type_ != CEF_CTT_NONE);
|
||||
}
|
||||
|
||||
if (with_overlay_browser_) {
|
||||
overlay_browser_ = new ViewsOverlayBrowser(this);
|
||||
|
||||
// Use default behavior for the overlay browser. A new |client| instance
|
||||
// is still required by cefclient architecture.
|
||||
CefRefPtr<CefClient> client =
|
||||
new DefaultClientHandler(/*use_alloy_style=*/true);
|
||||
|
||||
overlay_browser_->Initialize(window_, client, initial_url_, settings_,
|
||||
request_context_);
|
||||
request_context_ = nullptr;
|
||||
}
|
||||
} else {
|
||||
// Remove any controls that may include the Chrome toolbar before removing
|
||||
// the BrowserView.
|
||||
|
@ -1015,6 +1050,10 @@ void ViewsWindow::OnWindowChanged(CefRefPtr<CefView> view, bool added) {
|
|||
location_bar_ = nullptr;
|
||||
}
|
||||
}
|
||||
if (overlay_browser_) {
|
||||
overlay_browser_->Destroy();
|
||||
overlay_browser_ = nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1028,6 +1067,12 @@ void ViewsWindow::OnLayoutChanged(CefRefPtr<CefView> view,
|
|||
if (overlay_controls_) {
|
||||
overlay_controls_->UpdateControls();
|
||||
}
|
||||
|
||||
if (overlay_browser_) {
|
||||
// TODO: Consider modifying insets based on toolbar visibility.
|
||||
CefInsets window_insets(200, 200, 200, 200);
|
||||
overlay_browser_->UpdateBounds(window_insets);
|
||||
}
|
||||
}
|
||||
|
||||
void ViewsWindow::OnThemeChanged(CefRefPtr<CefView> view) {
|
||||
|
@ -1064,9 +1109,9 @@ ViewsWindow::ViewsWindow(WindowType type,
|
|||
with_controls_ = is_normal_type && delegate_->WithControls();
|
||||
|
||||
const bool hide_frame = command_line->HasSwitch(switches::kHideFrame);
|
||||
const bool hide_overlays =
|
||||
!is_normal_type || command_line->HasSwitch(switches::kHideOverlays);
|
||||
const bool hide_toolbar = hide_overlays && !with_controls_;
|
||||
const bool show_overlays = is_normal_type && hide_frame && !with_controls_ &&
|
||||
!command_line->HasSwitch(switches::kHideOverlays);
|
||||
const bool hide_toolbar = !show_overlays && !with_controls_;
|
||||
const bool show_window_buttons =
|
||||
command_line->HasSwitch(switches::kShowWindowButtons);
|
||||
accepts_first_mouse_ = command_line->HasSwitch(switches::kAcceptsFirstMouse);
|
||||
|
@ -1075,7 +1120,7 @@ ViewsWindow::ViewsWindow(WindowType type,
|
|||
frameless_ = hide_frame;
|
||||
|
||||
// With an overlay that mimics window controls.
|
||||
with_overlay_controls_ = hide_frame && !hide_overlays && !with_controls_;
|
||||
with_overlay_controls_ = show_overlays;
|
||||
|
||||
// If window has frame or flag passed explicitly
|
||||
with_standard_buttons_ = !frameless_ || show_window_buttons;
|
||||
|
@ -1313,12 +1358,12 @@ void ViewsWindow::SetMenuFocusable(bool focusable) {
|
|||
|
||||
if (menu_bar_) {
|
||||
menu_bar_->SetMenuFocusable(focusable);
|
||||
} else {
|
||||
window_->GetViewForID(ID_MENU_BUTTON)->SetFocusable(focusable);
|
||||
} else if (menu_button_) {
|
||||
menu_button_->SetFocusable(focusable);
|
||||
|
||||
if (focusable) {
|
||||
// Give focus to menu button.
|
||||
window_->GetViewForID(ID_MENU_BUTTON)->RequestFocus();
|
||||
menu_button_->RequestFocus();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
#include "tests/cefclient/browser/image_cache.h"
|
||||
#include "tests/cefclient/browser/root_window.h"
|
||||
#include "tests/cefclient/browser/views_menu_bar.h"
|
||||
#include "tests/cefclient/browser/views_overlay_browser.h"
|
||||
#include "tests/cefclient/browser/views_overlay_controls.h"
|
||||
|
||||
namespace client {
|
||||
|
@ -128,6 +129,8 @@ class ViewsWindow : public CefBrowserViewDelegate,
|
|||
std::optional<CefRect>& dip_bounds);
|
||||
void SetTitlebarHeight(const std::optional<float>& height);
|
||||
|
||||
void UpdateDraggableRegions();
|
||||
|
||||
// CefBrowserViewDelegate methods:
|
||||
CefRefPtr<CefBrowserViewDelegate> GetDelegateForPopupBrowserView(
|
||||
CefRefPtr<CefBrowserView> browser_view,
|
||||
|
@ -251,7 +254,7 @@ class ViewsWindow : public CefBrowserViewDelegate,
|
|||
void NudgeWindow();
|
||||
|
||||
const WindowType type_;
|
||||
Delegate* delegate_; // Not owned by this object.
|
||||
Delegate* const delegate_; // Not owned by this object.
|
||||
const bool use_alloy_style_;
|
||||
bool use_alloy_style_window_;
|
||||
CefRefPtr<CefBrowserView> browser_view_;
|
||||
|
@ -280,6 +283,13 @@ class ViewsWindow : public CefBrowserViewDelegate,
|
|||
|
||||
CefRefPtr<ViewsOverlayControls> overlay_controls_;
|
||||
|
||||
// Overlay browser view state.
|
||||
bool with_overlay_browser_ = false;
|
||||
std::string initial_url_;
|
||||
CefBrowserSettings settings_;
|
||||
CefRefPtr<CefRequestContext> request_context_;
|
||||
CefRefPtr<ViewsOverlayBrowser> overlay_browser_;
|
||||
|
||||
std::optional<float> default_titlebar_height_;
|
||||
std::optional<float> override_titlebar_height_;
|
||||
|
||||
|
@ -293,6 +303,8 @@ class ViewsWindow : public CefBrowserViewDelegate,
|
|||
bool can_go_back_ = false;
|
||||
bool can_go_forward_ = false;
|
||||
|
||||
std::vector<CefDraggableRegion> last_regions_;
|
||||
|
||||
IMPLEMENT_REFCOUNTING(ViewsWindow);
|
||||
DISALLOW_COPY_AND_ASSIGN(ViewsWindow);
|
||||
};
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
#include "include/test/cef_test_helpers.h"
|
||||
#include "include/wrapper/cef_closure_task.h"
|
||||
#include "tests/ceftests/routing_test_handler.h"
|
||||
#include "tests/ceftests/test_util.h"
|
||||
#include "tests/gtest/include/gtest/gtest.h"
|
||||
|
||||
namespace {
|
||||
|
@ -58,6 +59,8 @@ class LifeSpanTestHandler : public RoutingTestHandler {
|
|||
}
|
||||
|
||||
bool DoClose(CefRefPtr<CefBrowser> browser) override {
|
||||
EXPECT_TRUE(browser->GetHost()->IsReadyToBeClosed());
|
||||
|
||||
if (executing_delay_close_) {
|
||||
return false;
|
||||
}
|
||||
|
@ -75,6 +78,8 @@ class LifeSpanTestHandler : public RoutingTestHandler {
|
|||
}
|
||||
|
||||
void OnBeforeClose(CefRefPtr<CefBrowser> browser) override {
|
||||
EXPECT_TRUE(browser->GetHost()->IsReadyToBeClosed());
|
||||
|
||||
if (!executing_delay_close_) {
|
||||
got_before_close_.yes();
|
||||
EXPECT_TRUE(browser->IsSame(GetBrowser()));
|
||||
|
@ -87,6 +92,8 @@ class LifeSpanTestHandler : public RoutingTestHandler {
|
|||
const CefString& message_text,
|
||||
bool is_reload,
|
||||
CefRefPtr<CefJSDialogCallback> callback) override {
|
||||
EXPECT_FALSE(browser->GetHost()->IsReadyToBeClosed());
|
||||
|
||||
if (executing_delay_close_) {
|
||||
callback->Continue(true, CefString());
|
||||
return true;
|
||||
|
@ -124,6 +131,8 @@ class LifeSpanTestHandler : public RoutingTestHandler {
|
|||
CefExecuteJavaScriptWithUserGestureForTests(frame, CefString());
|
||||
}
|
||||
|
||||
EXPECT_FALSE(browser->GetHost()->IsReadyToBeClosed());
|
||||
|
||||
// Attempt to close the browser.
|
||||
CloseBrowser(browser, settings_.force_close);
|
||||
}
|
||||
|
@ -180,12 +189,15 @@ class LifeSpanTestHandler : public RoutingTestHandler {
|
|||
|
||||
TEST(LifeSpanTest, DoCloseAllow) {
|
||||
LifeSpanTestHandler::Settings settings;
|
||||
settings.allow_do_close = true;
|
||||
CefRefPtr<LifeSpanTestHandler> handler = new LifeSpanTestHandler(settings);
|
||||
handler->ExecuteTest();
|
||||
|
||||
EXPECT_TRUE(handler->got_after_created_);
|
||||
EXPECT_TRUE(handler->got_do_close_);
|
||||
if (handler->use_alloy_style_browser()) {
|
||||
EXPECT_TRUE(handler->got_do_close_);
|
||||
} else {
|
||||
EXPECT_FALSE(handler->got_do_close_);
|
||||
}
|
||||
EXPECT_TRUE(handler->got_before_close_);
|
||||
EXPECT_FALSE(handler->got_before_unload_dialog_);
|
||||
EXPECT_TRUE(handler->got_unload_message_);
|
||||
|
@ -197,13 +209,16 @@ TEST(LifeSpanTest, DoCloseAllow) {
|
|||
|
||||
TEST(LifeSpanTest, DoCloseAllowForce) {
|
||||
LifeSpanTestHandler::Settings settings;
|
||||
settings.allow_do_close = true;
|
||||
settings.force_close = true;
|
||||
CefRefPtr<LifeSpanTestHandler> handler = new LifeSpanTestHandler(settings);
|
||||
handler->ExecuteTest();
|
||||
|
||||
EXPECT_TRUE(handler->got_after_created_);
|
||||
EXPECT_TRUE(handler->got_do_close_);
|
||||
if (handler->use_alloy_style_browser()) {
|
||||
EXPECT_TRUE(handler->got_do_close_);
|
||||
} else {
|
||||
EXPECT_FALSE(handler->got_do_close_);
|
||||
}
|
||||
EXPECT_TRUE(handler->got_before_close_);
|
||||
EXPECT_FALSE(handler->got_before_unload_dialog_);
|
||||
EXPECT_TRUE(handler->got_unload_message_);
|
||||
|
@ -214,6 +229,11 @@ TEST(LifeSpanTest, DoCloseAllowForce) {
|
|||
}
|
||||
|
||||
TEST(LifeSpanTest, DoCloseDisallow) {
|
||||
// Test not supported with Chrome style browser.
|
||||
if (!UseAlloyStyleBrowserGlobal()) {
|
||||
return;
|
||||
}
|
||||
|
||||
LifeSpanTestHandler::Settings settings;
|
||||
settings.allow_do_close = false;
|
||||
CefRefPtr<LifeSpanTestHandler> handler = new LifeSpanTestHandler(settings);
|
||||
|
@ -231,6 +251,11 @@ TEST(LifeSpanTest, DoCloseDisallow) {
|
|||
}
|
||||
|
||||
TEST(LifeSpanTest, DoCloseDisallowForce) {
|
||||
// Test not supported with Chrome style browser.
|
||||
if (!UseAlloyStyleBrowserGlobal()) {
|
||||
return;
|
||||
}
|
||||
|
||||
LifeSpanTestHandler::Settings settings;
|
||||
settings.allow_do_close = false;
|
||||
settings.force_close = true;
|
||||
|
@ -249,6 +274,11 @@ TEST(LifeSpanTest, DoCloseDisallowForce) {
|
|||
}
|
||||
|
||||
TEST(LifeSpanTest, DoCloseDisallowWithOnUnloadAllow) {
|
||||
// Test not supported with Chrome style browser.
|
||||
if (!UseAlloyStyleBrowserGlobal()) {
|
||||
return;
|
||||
}
|
||||
|
||||
LifeSpanTestHandler::Settings settings;
|
||||
settings.allow_do_close = false;
|
||||
settings.add_onunload_handler = true;
|
||||
|
@ -269,14 +299,17 @@ TEST(LifeSpanTest, DoCloseDisallowWithOnUnloadAllow) {
|
|||
|
||||
TEST(LifeSpanTest, DoCloseAllowWithOnUnloadForce) {
|
||||
LifeSpanTestHandler::Settings settings;
|
||||
settings.allow_do_close = true;
|
||||
settings.add_onunload_handler = true;
|
||||
settings.force_close = true;
|
||||
CefRefPtr<LifeSpanTestHandler> handler = new LifeSpanTestHandler(settings);
|
||||
handler->ExecuteTest();
|
||||
|
||||
EXPECT_TRUE(handler->got_after_created_);
|
||||
EXPECT_TRUE(handler->got_do_close_);
|
||||
if (handler->use_alloy_style_browser()) {
|
||||
EXPECT_TRUE(handler->got_do_close_);
|
||||
} else {
|
||||
EXPECT_FALSE(handler->got_do_close_);
|
||||
}
|
||||
EXPECT_TRUE(handler->got_before_close_);
|
||||
EXPECT_TRUE(handler->got_before_unload_dialog_);
|
||||
EXPECT_TRUE(handler->got_unload_message_);
|
||||
|
@ -287,6 +320,11 @@ TEST(LifeSpanTest, DoCloseAllowWithOnUnloadForce) {
|
|||
}
|
||||
|
||||
TEST(LifeSpanTest, DoCloseDisallowWithOnUnloadForce) {
|
||||
// Test not supported with Chrome style browser.
|
||||
if (!UseAlloyStyleBrowserGlobal()) {
|
||||
return;
|
||||
}
|
||||
|
||||
LifeSpanTestHandler::Settings settings;
|
||||
settings.allow_do_close = false;
|
||||
settings.add_onunload_handler = true;
|
||||
|
@ -313,7 +351,11 @@ TEST(LifeSpanTest, OnUnloadAllow) {
|
|||
handler->ExecuteTest();
|
||||
|
||||
EXPECT_TRUE(handler->got_after_created_);
|
||||
EXPECT_TRUE(handler->got_do_close_);
|
||||
if (handler->use_alloy_style_browser()) {
|
||||
EXPECT_TRUE(handler->got_do_close_);
|
||||
} else {
|
||||
EXPECT_FALSE(handler->got_do_close_);
|
||||
}
|
||||
EXPECT_TRUE(handler->got_before_close_);
|
||||
EXPECT_TRUE(handler->got_before_unload_dialog_);
|
||||
EXPECT_TRUE(handler->got_unload_message_);
|
||||
|
|
|
@ -322,6 +322,8 @@ void TestHandler::OnAfterCreated(CefRefPtr<CefBrowser> browser) {
|
|||
void TestHandler::OnBeforeClose(CefRefPtr<CefBrowser> browser) {
|
||||
EXPECT_UI_THREAD();
|
||||
|
||||
EXPECT_TRUE(browser->GetHost()->IsReadyToBeClosed());
|
||||
|
||||
// Free the browser pointer so that the browser can be destroyed.
|
||||
const int browser_id = browser->GetIdentifier();
|
||||
BrowserMap::iterator it = browser_map_.find(browser_id);
|
||||
|
|
|
@ -522,68 +522,21 @@ void WindowIconFramelessImpl(CefRefPtr<CefWaitableEvent> event) {
|
|||
TestWindowDelegate::RunTest(event, std::move(config));
|
||||
}
|
||||
|
||||
const int kChar = 'A';
|
||||
const int kCloseWindowId = 2;
|
||||
constexpr int kChar = 'A';
|
||||
constexpr int kCloseWindowId = 2;
|
||||
bool got_accelerator;
|
||||
int got_key_event_alt_count;
|
||||
bool got_key_event_char;
|
||||
|
||||
void TriggerAccelerator(CefRefPtr<CefWindow> window) {
|
||||
window->SendKeyPress(kChar, EVENTFLAG_ALT_DOWN);
|
||||
}
|
||||
|
||||
bool OnKeyEvent(CefRefPtr<CefWindow> window, const CefKeyEvent& event) {
|
||||
if (event.type != KEYEVENT_RAWKEYDOWN) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (event.windows_key_code == VK_MENU) {
|
||||
// First we get the ALT key press in all cases.
|
||||
EXPECT_FALSE(got_key_event_char);
|
||||
if (got_key_event_alt_count == 0) {
|
||||
EXPECT_FALSE(got_accelerator);
|
||||
} else {
|
||||
EXPECT_TRUE(got_accelerator);
|
||||
}
|
||||
|
||||
EXPECT_EQ(EVENTFLAG_ALT_DOWN, static_cast<int>(event.modifiers));
|
||||
got_key_event_alt_count++;
|
||||
} else if (event.windows_key_code == kChar) {
|
||||
// Then we get the char key press with the ALT modifier if the accelerator
|
||||
// isn't registered.
|
||||
EXPECT_TRUE(got_accelerator);
|
||||
EXPECT_EQ(got_key_event_alt_count, 2);
|
||||
EXPECT_FALSE(got_key_event_char);
|
||||
|
||||
EXPECT_EQ(EVENTFLAG_ALT_DOWN, static_cast<int>(event.modifiers));
|
||||
got_key_event_char = true;
|
||||
|
||||
// Call this method just to make sure it doesn't crash.
|
||||
window->RemoveAllAccelerators();
|
||||
|
||||
// End the test by closing the Window.
|
||||
window->Close();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool OnAccelerator(CefRefPtr<CefWindow> window, int command_id) {
|
||||
EXPECT_FALSE(got_accelerator);
|
||||
EXPECT_EQ(got_key_event_alt_count, 1);
|
||||
EXPECT_FALSE(got_key_event_char);
|
||||
|
||||
EXPECT_EQ(kCloseWindowId, command_id);
|
||||
got_accelerator = true;
|
||||
|
||||
// Remove the accelerator.
|
||||
window->RemoveAccelerator(kCloseWindowId);
|
||||
|
||||
// Now send the event without the accelerator registered. Should result in a
|
||||
// call to OnKeyEvent.
|
||||
TriggerAccelerator(window);
|
||||
window->Close();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -598,25 +551,15 @@ void RunWindowAccelerator(CefRefPtr<CefWindow> window) {
|
|||
|
||||
void VerifyWindowAccelerator(CefRefPtr<CefWindow> window) {
|
||||
EXPECT_TRUE(got_accelerator);
|
||||
EXPECT_EQ(got_key_event_alt_count, 2);
|
||||
EXPECT_TRUE(got_key_event_char);
|
||||
}
|
||||
|
||||
// Expected order of events:
|
||||
// 1. OnKeyEvent for ALT key press.
|
||||
// 2. OnAccelerator for ALT+Char key press (with accelerator registered).
|
||||
// 3. OnKeyEvent for ALT key press.
|
||||
// 4. OnKeyEvent for ALT+Char key press (without accelerator registered).
|
||||
void WindowAcceleratorImpl(CefRefPtr<CefWaitableEvent> event) {
|
||||
got_accelerator = false;
|
||||
got_key_event_alt_count = 0;
|
||||
got_key_event_char = false;
|
||||
|
||||
auto config = std::make_unique<TestWindowDelegate::Config>();
|
||||
config->on_window_created = base::BindOnce(RunWindowAccelerator);
|
||||
config->on_window_destroyed = base::BindOnce(VerifyWindowAccelerator);
|
||||
config->on_accelerator = base::BindRepeating(OnAccelerator);
|
||||
config->on_key_event = base::BindRepeating(OnKeyEvent);
|
||||
config->close_window = false;
|
||||
TestWindowDelegate::RunTest(event, std::move(config));
|
||||
}
|
||||
|
|
|
@ -58,5 +58,6 @@ const char kHideWindowOnClose[] = "hide-window-on-close";
|
|||
const char kAcceptsFirstMouse[] = "accepts-first-mouse";
|
||||
const char kUseAlloyStyle[] = "use-alloy-style";
|
||||
const char kUseChromeStyleWindow[] = "use-chrome-style-window";
|
||||
const char kShowOverlayBrowser[] = "show-overlay-browser";
|
||||
|
||||
} // namespace client::switches
|
||||
|
|
|
@ -52,6 +52,7 @@ extern const char kHideWindowOnClose[];
|
|||
extern const char kAcceptsFirstMouse[];
|
||||
extern const char kUseAlloyStyle[];
|
||||
extern const char kUseChromeStyleWindow[];
|
||||
extern const char kShowOverlayBrowser[];
|
||||
|
||||
} // namespace client::switches
|
||||
|
||||
|
|
Loading…
Reference in New Issue