Compare commits

...

34 Commits
6998 ... 6723

Author SHA1 Message Date
Marshall Greenblatt
5c0b03a4ba Pin depot_tools version for out-of-support branch 2024-11-19 13:37:48 -05:00
Marshall Greenblatt
5a7e5ed359 Update to Chromium version 130.0.6723.117 2024-11-06 14:20:43 +00:00
Marshall Greenblatt
34b05bb541 win: Reland screen_1443650 changes (fixes #3489)
Use ScaleToRoundedRect instead of ScaleToEnclosedRect.
2024-11-05 12:42:02 -05:00
Marshall Greenblatt
de32089516 cefclient: Add RootWindowManager tracking of other browsers (see #3790)
The message loop should not quit until all browsers have closed,
including browsers that are not directly associated with a RootWindow.
2024-11-04 17:16:27 -05:00
Marshall Greenblatt
16488e5564 Free CefMenuRunnerViews on BrowserView destruction (see #3790)
CefMenuRunnerViews holds a raw_ptr<CefBrowserViewImpl> that must be
cleared during CefBrowserViewImpl destruction.
2024-11-04 17:16:18 -05:00
Marshall Greenblatt
7bb6b2569c mac: Fix accelerators in overlay BrowserView (see #3188)
CefWindowImpl::CanHandleAccelerators was returning false for
accelerators triggered in the overlay BrowserView due to
IsWindowKey (called from NativeWidgetMac::IsActive) returning
false. View::CanHandleAccelerators, on the other hand, only
checks IsActive for Aura (non-MacOS) windows. We therefore
delegate to the View implementation for consistent handling.
2024-11-04 17:16:10 -05:00
Marshall Greenblatt
7a98b3fece Execute HandleExternalProtocolHelper on the UI thread (fixes #3821) 2024-11-04 12:01:19 -05:00
Marshall Greenblatt
3470f6ade4 Update to Chromium version 130.0.6723.92 2024-10-31 15:33:29 +00:00
Marshall Greenblatt
fc4256797d win: Revert screen_1443650 changes (fixes #3744)
This change broke tooltip display at 125% scale factor on Windows 10
with high-dpi display.

Reopening the original issue #3489.
2024-10-23 14:33:13 -04:00
Marshall Greenblatt
3dedcced94 Update to Chromium version 130.0.6723.70 2024-10-23 12:50:40 +00:00
Marshall Greenblatt
59f3b143ef mac: cefclient: Fix window.close() with --hide-window-on-close (fixes #3660) 2024-10-22 16:19:53 -04:00
Marshall Greenblatt
6514b929c4 Fix raw_ptr leak of main frame RFH during WebContents close (see #3660) 2024-10-22 16:19:45 -04:00
Mike Bragg
a747221b01 Implement PrintCrossProcessSubframe for AlloyBrowserHostImpl (fixes #3768) 2024-10-22 16:06:43 -04:00
Marshall Greenblatt
351ea86650 win: Add SHA256 impl for Sid::FromNamedCapability (fixes #3791)
The cef_sandbox build can't use the default BoringSSL implementation
so we add an alternative implementation using the Crypto API.
2024-10-22 13:12:13 -04:00
Marshall Greenblatt
06c1602d18 Update to Chromium version 130.0.6723.59 2024-10-21 15:25:21 +00:00
Marshall Greenblatt
48f3ef63e2 linux: Fix callbacks to CefPrintHandler (fixes #3729)
Out-of-process printing must also be disabled by passing
`--disable-features=EnableOopPrintDrivers`.
2024-10-18 15:04:17 -04:00
Marshall Greenblatt
7268dc8cd3 cefclient: views: Add ability to pop out the overlay Browser (see #3790)
When running with the overlay Browser enabled (`--show-overlay-browser`),
pressing Alt+O will move the overlay Browser to a new top-level Window.
Pressing Alt+O again or closing the new Window via the close button will
return the Browser to the overlay. Closing the Browser via `window.close()`
(in the new Window or overlay) will dismiss the overlay completely as
required to maintain consistent internal state. Detection of this state is
supported by the new CefBrowserHost::IsReadyToBeClosed method.

Draggable regions in the main Browser are updated to account for the
presence or absence of the overlay Browser. Support for draggable regions
in the overlay Browser in not implemented in cefclient.

Behavior with multiple overlays, `window.close()` and draggable regions
can be tested by adding `--hide-frame --hide-controls`.
2024-10-18 15:04:08 -04:00
Marshall Greenblatt
45861b1b08 chrome: Support unload handlers with TryCloseBrowser
TryCloseBrowser should potentially trigger JavaScript unload handlers
and return false. Add CefBrowserHost::IsReadyToBeClosed for detecting
mandatory close state. Enable, for Chrome style browsers, LifeSpanTest
that don't require DoClose(). Update related documentation.
2024-10-18 15:03:59 -04:00
Marshall Greenblatt
efe558cd28 views: Fix dangling raw_ptr on CefToolbarViewView destruction 2024-10-18 15:03:49 -04:00
Marshall Greenblatt
f1e634393f views: cefclient: Fix crash when ID_MENU_BUTTON doesn't exist 2024-10-18 15:03:40 -04:00
Marshall Greenblatt
0187046a2e views: Trigger CefBrowser destruction on CefBrowserView release (see #3790)
Avoid a circular ownership dependency between CefBrowserViewImpl and
CefBrowserPlatformDelegate[Chrome]Views (owned by CefBrowserHostBase).
Trigger CefBrowserHostBase destruction when the last CefBrowserViewImpl
reference is released.

This fixes a number of shutdown crashes related to overlay CefBrowsers
still existing at CefShutdown.
2024-10-18 15:03:29 -04:00
Marshall Greenblatt
6f4c2bf8df Fix DiscardableSharedMemoryManager destruction timing
Move DiscardableSharedMemoryManager destruction to the end of UI thread
shutdown, after Mojo messages have stopped arriving. See related comments
at https://chromium-review.googlesource.com/c/chromium/src/+/5925441
2024-10-18 15:03:19 -04:00
Marshall Greenblatt
de2da368c6 cefclient: views: Add overlay BrowserView demo (see #3790)
Adds new `--show-overlay-browser` command-line flag that creates an
overlay containing an Alloy-style BrowserView.  The main BrowserView
may be Chrome- (default) or Alloy-style (add `--use-alloy-style`).
This overlay will only be added to standalone (non-popup) windows.

Popups triggered via the overlay will receive standard Alloy-style
handling in cefclient (e.g. Views-hosted window). Add
`--use-default-popup` for default popup handling.
2024-10-18 15:03:08 -04:00
Marshall Greenblatt
4797681694 views: Fix style calculation for popup BrowserViews (fixes #3499)
Don't depend on a CefBrowserViewDelegate for popup BrowserView style.
Popup style must always match the opener style.
2024-10-18 15:02:57 -04:00
Nik Pavlov
ffbc53a9e6 views: Fix overlay bounds outside of window (fixes #3457) 2024-10-18 15:02:46 -04:00
Marshall Greenblatt
92f14410ae wrapper: Add missing algorithm include (fixes #3804) 2024-10-18 15:02:35 -04:00
Nik Pavlov
e68b0169a1 ceftests: Simplify ViewsWindowTest.WindowAccelerator test (see #3188)
Remove the CefWindowDelegate::OnKeyEvent check as that method
is not currently triggered with the Chrome runtime (see #3797).
2024-10-18 15:02:24 -04:00
Nik Pavlov
1fd6000c70 mac: views: Always initialize CommandDispatcher (see #3188)
ChromeCommandDispatcherDelegate forwards accelerator events to
the FocusManager through NativeWidgetMacNSWindowHost::
HandleAccelerator. Always initialize it so that accelerators also
work in a CefWindow without a BrowserView.
2024-10-18 15:02:14 -04:00
Marshall Greenblatt
5e348cb1fc cefclient: Fix toolbar visibility with --hide-controls (fixes #3745) 2024-10-18 15:02:01 -04:00
Marshall Greenblatt
02b371879b Update to Chromium version 130.0.6723.44 2024-10-11 16:27:48 +00:00
Marshall Greenblatt
3f4d8297f2 Update to Chromium version 130.0.6723.31 2024-10-09 16:36:31 +00:00
Marshall Greenblatt
057c1b1409 cmake: Fix set_property argument (fixes #3775) 2024-09-30 12:49:22 -04:00
Marshall Greenblatt
96ddcee086 Fix dangling ptr in RenderProcessHostTaskProvider (fixes #3758) 2024-09-30 12:19:33 -04:00
Marshall Greenblatt
625ea52a4b Update to Chromium version 130.0.6723.19 2024-09-27 15:50:51 -04:00
72 changed files with 1365 additions and 397 deletions

View File

@@ -7,5 +7,6 @@
# https://bitbucket.org/chromiumembedded/cef/wiki/BranchesAndBuilding
{
'chromium_checkout': 'refs/tags/130.0.6723.0'
'chromium_checkout': 'refs/tags/130.0.6723.117',
'depot_tools_checkout': 'c22f4dc74f'
}

View File

@@ -142,7 +142,7 @@ set(CMAKE_CONFIGURATION_TYPES Debug Release)
project(cef)
# Use folders in the resulting project files.
set_property(GLOBAL PROPERTY OS_FOLDERS ON)
set_property(GLOBAL PROPERTY USE_FOLDERS ON)
#

View File

@@ -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',

View File

@@ -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.
///

View File

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

View File

@@ -42,13 +42,13 @@
// way that may cause binary incompatibility with other builds. The universal
// hash value will change if any platform is affected whereas the platform hash
// values will change only if that particular platform is affected.
#define CEF_API_HASH_UNIVERSAL "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

View File

@@ -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.
///

View File

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

View File

@@ -35,6 +35,7 @@
#include "chrome/browser/picture_in_picture/picture_in_picture_window_manager.h"
#include "chrome/common/webui_url_constants.h"
#include "components/input/native_web_keyboard_event.h"
#include "components/printing/browser/print_composite_client.h"
#include "components/zoom/page_zoom.h"
#include "content/browser/gpu/compositor_util.h"
#include "content/public/browser/desktop_media_id.h"
@@ -550,6 +551,10 @@ void AlloyBrowserHostImpl::WindowDestroyed() {
CEF_REQUIRE_UIT();
DCHECK(!window_destroyed_);
window_destroyed_ = true;
// Destroy objects that may reference the window.
menu_manager_.reset(nullptr);
CloseBrowser(true);
}
@@ -922,6 +927,17 @@ bool AlloyBrowserHostImpl::IsAudioMuted() {
// content::WebContentsDelegate methods.
// -----------------------------------------------------------------------------
void AlloyBrowserHostImpl::PrintCrossProcessSubframe(
content::WebContents* web_contents,
const gfx::Rect& rect,
int document_cookie,
content::RenderFrameHost* subframe_host) const {
auto* client = printing::PrintCompositeClient::FromWebContents(web_contents);
if (client) {
client->PrintCrossProcessSubframe(rect, document_cookie, subframe_host);
}
}
content::WebContents* AlloyBrowserHostImpl::OpenURLFromTab(
content::WebContents* source,
const content::OpenURLParams& params,

View File

@@ -174,6 +174,10 @@ class AlloyBrowserHostImpl : public CefBrowserHostBase,
DestructionState destruction_state() const { return destruction_state_; }
// content::WebContentsDelegate methods.
void PrintCrossProcessSubframe(content::WebContents* web_contents,
const gfx::Rect& rect,
int document_cookie,
content::RenderFrameHost* subframe_host) const override;
content::WebContents* OpenURLFromTab(
content::WebContents* source,
const content::OpenURLParams& params,

View File

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

View File

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

View File

@@ -277,11 +277,14 @@ void CefBrowserInfo::RemoveFrame(content::RenderFrameHost* host) {
{
auto it2 = frame_info_set_.find(frame_info);
// Explicitly Detach everything but the current main frame.
// Explicitly Detach everything.
const auto& other_frame_info = *it2;
if (other_frame_info->frame_ && !other_frame_info->IsCurrentMainFrame()) {
if (other_frame_info->frame_) {
const bool is_current_main_frame = other_frame_info->IsCurrentMainFrame();
if (other_frame_info->frame_->Detach(
CefFrameHostImpl::DetachReason::RENDER_FRAME_DELETED)) {
CefFrameHostImpl::DetachReason::RENDER_FRAME_DELETED,
is_current_main_frame)) {
DCHECK(!is_current_main_frame);
MaybeNotifyFrameDetached(browser_, other_frame_info->frame_);
}
}
@@ -477,7 +480,8 @@ void CefBrowserInfo::SetMainFrame(CefRefPtr<CefBrowserHostBase> browser,
CefRefPtr<CefFrameHostImpl> old_frame;
if (main_frame_) {
old_frame = main_frame_;
if (old_frame->Detach(CefFrameHostImpl::DetachReason::NEW_MAIN_FRAME)) {
if (old_frame->Detach(CefFrameHostImpl::DetachReason::NEW_MAIN_FRAME,
/*is_current_main_frame=*/false)) {
MaybeNotifyFrameDetached(browser, old_frame);
}
}
@@ -556,11 +560,14 @@ void CefBrowserInfo::RemoveAllFrames(
frame_id_map_.clear();
frame_token_to_id_map_.clear();
// Explicitly Detach everything but the current main frame.
// Explicitly Detach everything.
for (auto& info : frame_info_set_) {
if (info->frame_ && !info->IsCurrentMainFrame()) {
if (info->frame_) {
const bool is_current_main_frame = info->IsCurrentMainFrame();
if (info->frame_->Detach(
CefFrameHostImpl::DetachReason::BROWSER_DESTROYED)) {
CefFrameHostImpl::DetachReason::BROWSER_DESTROYED,
is_current_main_frame)) {
DCHECK(!is_current_main_frame);
MaybeNotifyFrameDetached(old_browser, info->frame_);
}
}

View File

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

View File

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

View File

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

View File

@@ -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)
}

View File

@@ -59,6 +59,8 @@ void HandleExternalProtocolHelper(
const network::ResourceRequest& resource_request,
const std::optional<url::Origin>& initiating_origin,
content::WeakDocumentPtr initiator_document) {
CEF_REQUIRE_UIT();
// May return nullptr if frame has been deleted or a cross-document navigation
// has committed in the same RenderFrameHost.
auto initiator_rfh = initiator_document.AsRenderFrameHostIfValid();

View File

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

View File

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

View File

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

View File

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

View File

@@ -495,7 +495,7 @@ bool CefFrameHostImpl::IsDetached() const {
return !GetRenderFrameHost();
}
bool CefFrameHostImpl::Detach(DetachReason reason) {
bool CefFrameHostImpl::Detach(DetachReason reason, bool is_current_main_frame) {
CEF_REQUIRE_UIT();
if (VLOG_IS_ON(1)) {
@@ -516,24 +516,29 @@ bool CefFrameHostImpl::Detach(DetachReason reason) {
<< ", is_connected=" << render_frame_.is_bound() << ")";
}
// May be called multiple times (e.g. from CefBrowserInfo SetMainFrame and
// RemoveFrame).
bool first_detach = false;
// This method may be called multiple times (e.g. from CefBrowserInfo
// SetMainFrame and RemoveFrame).
bool is_first_complete_detach = false;
// Should not be called for temporary frames.
CHECK(!is_temporary());
{
base::AutoLock lock_scope(state_lock_);
if (browser_info_) {
first_detach = true;
browser_info_ = nullptr;
}
}
// Must be a main frame if |is_current_main_frame| is true.
CHECK(!is_current_main_frame || is_main_frame_);
// In case we never attached, clean up.
while (!queued_renderer_actions_.empty()) {
queued_renderer_actions_.pop();
if (!is_current_main_frame) {
{
base::AutoLock lock_scope(state_lock_);
if (browser_info_) {
is_first_complete_detach = true;
browser_info_ = nullptr;
}
}
// In case we never attached, clean up.
while (!queued_renderer_actions_.empty()) {
queued_renderer_actions_.pop();
}
}
if (render_frame_.is_bound()) {
@@ -543,7 +548,7 @@ bool CefFrameHostImpl::Detach(DetachReason reason) {
render_frame_.reset();
render_frame_host_ = nullptr;
return first_detach;
return is_first_complete_detach;
}
void CefFrameHostImpl::MaybeReAttach(

View File

@@ -136,9 +136,11 @@ class CefFrameHostImpl : public CefFrame, public cef::mojom::BrowserFrame {
// Owned frame objects will be detached explicitly when the associated
// RenderFrame is deleted. Temporary frame objects will be detached
// implicitly via CefBrowserInfo::browser() returning nullptr. Returns true
// if this was the first call to Detach() for the frame.
bool Detach(DetachReason reason);
// implicitly via CefBrowserInfo::browser() returning nullptr. If
// |is_current_main_frame| is true then only the RenderFrameHost references
// will be released as we want the frame object itself to remain valid.
// Returns true if the frame is completely detached for the first time.
bool Detach(DetachReason reason, bool is_current_main_frame);
// A frame has swapped to active status from prerendering or the back-forward
// cache. We may need to re-attach if the RFH has changed. See

View File

@@ -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() {

View File

@@ -1116,7 +1116,7 @@ class InterceptedRequestHandlerWrapper : public InterceptedRequestHandler {
init_state_->browser_, init_state_->frame_,
state->pending_request_.get(), allow_os_execution);
if (allow_os_execution && init_state_->unhandled_request_callback_) {
init_state_->unhandled_request_callback_.Run();
CEF_POST_TASK(TID_UI, init_state_->unhandled_request_callback_);
}
}
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -500,8 +500,8 @@ bool CefWindowImpl::AcceleratorPressed(const ui::Accelerator& accelerator) {
}
bool CefWindowImpl::CanHandleAccelerators() const {
if (delegate() && widget_) {
return widget_->IsActive();
if (delegate() && widget_ && root_view()) {
return root_view()->CanHandleAccelerators();
}
return false;
}

View File

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

View File

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

View File

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

View File

@@ -4,6 +4,7 @@
#include "include/wrapper/cef_message_router.h"
#include <algorithm>
#include <limits>
#include <map>
#include <set>

View File

@@ -518,6 +518,10 @@ patches = [
# https://github.com/llvm/llvm-project/issues/57364
#
# Avoid usage of PartitionAlloc assertions (PA_BASE_CHECK) in raw_ptr.h.
#
# win: Add SHA256 implementation for Sid::FromNamedCapability using the
# Crypto API.
# https://github.com/chromiumembedded/cef/issues/3791
'name': 'base_sandbox_2743',
},
{
@@ -756,5 +760,11 @@ patches = [
# win: Add missing <limits> include for cef_sandbox build.
# https://chromium-review.googlesource.com/c/chromium/src/+/5891459
'name': 'win_base_pa_oom_5891459'
},
{
# Fix dangling RenderProcessHost ptr in RenderProcessHostTaskProvider.
# https://github.com/chromiumembedded/cef/issues/3758
# https://chromium-review.googlesource.com/c/chromium/src/+/5894650
'name': 'chrome_browser_task_manager_5894650'
}
]

View File

@@ -1,5 +1,5 @@
diff --git base/BUILD.gn base/BUILD.gn
index d6dbc2c38b401..0e0a5cc086291 100644
index 9247e9b3f4c92..290dae31b7b7c 100644
--- base/BUILD.gn
+++ base/BUILD.gn
@@ -41,6 +41,7 @@ import("//build/nocompile.gni")
@@ -207,18 +207,10 @@ index ea33ca66f384c..33f4cc76f76bd 100644
return lhs.token_ == rhs.token_;
#else
diff --git base/win/sid.cc base/win/sid.cc
index 2f250ba9bf79d..8a269af206051 100644
index 2f250ba9bf79d..0af427e779266 100644
--- base/win/sid.cc
+++ base/win/sid.cc
@@ -22,6 +22,7 @@
#include <utility>
#include "base/check.h"
+#include "base/notreached.h"
#include "base/no_destructor.h"
#include "base/rand_util.h"
#include "base/ranges/algorithm.h"
@@ -29,7 +30,11 @@
@@ -29,12 +29,56 @@
#include "base/win/scoped_handle.h"
#include "base/win/scoped_localalloc.h"
#include "base/win/windows_version.h"
@@ -226,25 +218,52 @@ index 2f250ba9bf79d..8a269af206051 100644
+
+#if !BUILDFLAG(IS_CEF_SANDBOX_BUILD)
#include "third_party/boringssl/src/include/openssl/sha.h"
+#else
+#include <wincrypt.h>
+#endif
namespace base::win {
@@ -130,6 +135,7 @@ Sid Sid::FromNamedCapability(const std::wstring& capability_name) {
if (known_cap != known_capabilities->end()) {
return FromKnownCapability(known_cap->second);
}
+#if !BUILDFLAG(IS_CEF_SANDBOX_BUILD)
static_assert((SHA256_DIGEST_LENGTH / sizeof(DWORD)) ==
SECURITY_APP_PACKAGE_RID_COUNT);
DWORD rids[(SHA256_DIGEST_LENGTH / sizeof(DWORD)) + 2];
@@ -141,6 +147,9 @@ Sid Sid::FromNamedCapability(const std::wstring& capability_name) {
reinterpret_cast<uint8_t*>(&rids[2]));
return FromSubAuthorities(SECURITY_APP_PACKAGE_AUTHORITY, std::size(rids),
rids);
+#else
+ NOTREACHED();
+#endif
}
namespace {
Sid Sid::FromKnownSid(WellKnownSid type) {
+#if BUILDFLAG(IS_CEF_SANDBOX_BUILD)
+
+#define SHA256_DIGEST_LENGTH 32
+
+bool SHA256(const uint8_t* InData, size_t InDataLen, uint8_t* OutHash) {
+ HCRYPTPROV hProv = 0;
+ HCRYPTHASH hHash = 0;
+
+ if (!CryptAcquireContext(&hProv, nullptr, nullptr, PROV_RSA_AES,
+ CRYPT_VERIFYCONTEXT)) {
+ return false;
+ }
+
+ if (!CryptCreateHash(hProv, CALG_SHA_256, 0, 0, &hHash)) {
+ CryptReleaseContext(hProv, 0);
+ return false;
+ }
+
+ if (!CryptHashData(hHash, InData, static_cast<DWORD>(InDataLen), 0)) {
+ CryptDestroyHash(hHash);
+ CryptReleaseContext(hProv, 0);
+ return false;
+ }
+
+ DWORD dwHashLen = SHA256_DIGEST_LENGTH;
+ if (!CryptGetHashParam(hHash, HP_HASHVAL, OutHash, &dwHashLen, 0)) {
+ CryptDestroyHash(hHash);
+ CryptReleaseContext(hProv, 0);
+ return false;
+ }
+
+ CryptDestroyHash(hHash);
+ CryptReleaseContext(hProv, 0);
+ return true;
+}
+
+#endif // BUILDFLAG(IS_CEF_SANDBOX_BUILD)
+
template <typename Iterator>
Sid FromSubAuthorities(const SID_IDENTIFIER_AUTHORITY& identifier_authority,
size_t sub_authority_count,

View File

@@ -88,10 +88,10 @@ index f5191b804bc07..aadb7d66ba4c3 100644
+
#endif // BASE_TEST_TEST_TRACE_PROCESSOR_EXPORT_H_
diff --git content/shell/BUILD.gn content/shell/BUILD.gn
index 67a897af9cee3..f48b22d8f2e00 100644
index ff1d38784abeb..2a29a80a19551 100644
--- content/shell/BUILD.gn
+++ content/shell/BUILD.gn
@@ -912,7 +912,6 @@ if (is_mac) {
@@ -911,7 +911,6 @@ if (is_mac) {
# Specify a sensible install_name for static builds. The library is
# dlopen()ed so this is not used to resolve the module.
ldflags = [ "-Wl,-install_name,@executable_path/../Frameworks/$output_name.framework/$output_name" ]

View File

@@ -21,10 +21,10 @@ index 1bf903af89b3c..5471355376272 100644
// Make an exception to allow most visited tiles to commit in
diff --git content/browser/renderer_host/navigation_request.cc content/browser/renderer_host/navigation_request.cc
index e6b11183c78bd..e6082d8873a0b 100644
index 22bb23e6a84d3..512b8ac76cf77 100644
--- content/browser/renderer_host/navigation_request.cc
+++ content/browser/renderer_host/navigation_request.cc
@@ -8210,10 +8210,22 @@ NavigationRequest::GetOriginForURLLoaderFactoryBeforeResponseWithDebugInfo(
@@ -8214,10 +8214,22 @@ NavigationRequest::GetOriginForURLLoaderFactoryBeforeResponseWithDebugInfo(
bool use_opaque_origin =
(sandbox_flags & network::mojom::WebSandboxFlags::kOrigin) ==
network::mojom::WebSandboxFlags::kOrigin;
@@ -48,7 +48,7 @@ index e6b11183c78bd..e6082d8873a0b 100644
}
return origin_and_debug_info;
@@ -8321,6 +8333,15 @@ NavigationRequest::GetOriginForURLLoaderFactoryAfterResponseWithDebugInfo() {
@@ -8325,6 +8337,15 @@ NavigationRequest::GetOriginForURLLoaderFactoryAfterResponseWithDebugInfo() {
DetermineInitiatorRelationship(initiator_rfh,
frame_tree_node_->current_frame_host()));

View File

@@ -1,8 +1,8 @@
diff --git build/config/compiler/BUILD.gn build/config/compiler/BUILD.gn
index 5ec7492e06838..b22b50e8f175d 100644
index 765345a16d112..69a961128115d 100644
--- build/config/compiler/BUILD.gn
+++ build/config/compiler/BUILD.gn
@@ -134,6 +134,9 @@ declare_args() {
@@ -133,6 +133,9 @@ declare_args() {
# The cache can lead to non-determinism: https://crbug.com/1486045
thin_lto_enable_cache = true
@@ -12,7 +12,7 @@ index 5ec7492e06838..b22b50e8f175d 100644
# Initialize all local variables with a pattern. This flag will fill
# uninitialized floating-point types (and 32-bit pointers) with 0xFF and the
# rest with 0xAA. This makes behavior of uninitialized memory bugs consistent,
@@ -2267,11 +2270,13 @@ config("export_dynamic") {
@@ -2266,11 +2269,13 @@ config("export_dynamic") {
config("thin_archive") {
# The macOS and iOS default linker ld64 does not support reading thin
# archives.

View File

@@ -1,5 +1,5 @@
diff --git chrome/browser/BUILD.gn chrome/browser/BUILD.gn
index dd5c9db43d693..9a158633310fc 100644
index 7f1c26990d8d4..751f36b931f65 100644
--- chrome/browser/BUILD.gn
+++ chrome/browser/BUILD.gn
@@ -12,6 +12,7 @@ import("//build/config/compiler/pgo/pgo.gni")

View File

@@ -1,5 +1,5 @@
diff --git chrome/browser/renderer_context_menu/render_view_context_menu.cc chrome/browser/renderer_context_menu/render_view_context_menu.cc
index 348128d804493..5d893c71e55ea 100644
index aa0d1cc1d45fe..9329872580f9b 100644
--- chrome/browser/renderer_context_menu/render_view_context_menu.cc
+++ chrome/browser/renderer_context_menu/render_view_context_menu.cc
@@ -360,6 +360,18 @@ base::OnceCallback<void(RenderViewContextMenu*)>* GetMenuShownCallback() {
@@ -32,7 +32,7 @@ index 348128d804493..5d893c71e55ea 100644
id = CollapseCommandsForUMA(id);
const auto& map = GetIdcToUmaMap(type);
auto it = map.find(id);
@@ -902,6 +918,14 @@ RenderViewContextMenu::RenderViewContextMenu(
@@ -907,6 +923,14 @@ RenderViewContextMenu::RenderViewContextMenu(
: nullptr;
#endif // BUILDFLAG(IS_CHROMEOS_ASH)
@@ -47,7 +47,7 @@ index 348128d804493..5d893c71e55ea 100644
observers_.AddObserver(&autofill_context_menu_manager_);
}
@@ -1358,6 +1382,12 @@ void RenderViewContextMenu::InitMenu() {
@@ -1363,6 +1387,12 @@ void RenderViewContextMenu::InitMenu() {
autofill_client->HideAutofillSuggestions(
autofill::SuggestionHidingReason::kContextMenuOpened);
}
@@ -60,7 +60,7 @@ index 348128d804493..5d893c71e55ea 100644
}
Profile* RenderViewContextMenu::GetProfile() const {
@@ -3648,6 +3678,26 @@ void RenderViewContextMenu::RegisterExecutePluginActionCallbackForTesting(
@@ -3645,6 +3675,26 @@ void RenderViewContextMenu::RegisterExecutePluginActionCallbackForTesting(
execute_plugin_action_callback_ = std::move(cb);
}
@@ -88,7 +88,7 @@ index 348128d804493..5d893c71e55ea 100644
RenderViewContextMenu::GetHandlersForLinkUrl() {
custom_handlers::ProtocolHandlerRegistry::ProtocolHandlerList handlers =
diff --git chrome/browser/renderer_context_menu/render_view_context_menu.h chrome/browser/renderer_context_menu/render_view_context_menu.h
index 6b3874524e87b..4e0fd1d7297f1 100644
index 91de5780521af..571ad0260b4f7 100644
--- chrome/browser/renderer_context_menu/render_view_context_menu.h
+++ chrome/browser/renderer_context_menu/render_view_context_menu.h
@@ -153,7 +153,21 @@ class RenderViewContextMenu
@@ -113,7 +113,7 @@ index 6b3874524e87b..4e0fd1d7297f1 100644
Profile* GetProfile() const;
// This may return nullptr (e.g. for WebUI dialogs). Virtual to allow tests to
@@ -477,6 +491,9 @@ class RenderViewContextMenu
@@ -478,6 +492,9 @@ class RenderViewContextMenu
// built.
bool is_protocol_submenu_valid_ = false;

View File

@@ -34,10 +34,10 @@ index 4007e26f780c3..26d0d492cf176 100644
WebViewGuestDelegate* ChromeExtensionsAPIClient::CreateWebViewGuestDelegate(
diff --git chrome/browser/extensions/api/tabs/tabs_api.cc chrome/browser/extensions/api/tabs/tabs_api.cc
index faefffb1010e8..ee3c11ffda006 100644
index aa6acb2e58acc..8b27e0debf930 100644
--- chrome/browser/extensions/api/tabs/tabs_api.cc
+++ chrome/browser/extensions/api/tabs/tabs_api.cc
@@ -1577,7 +1577,7 @@ ExtensionFunction::ResponseAction TabsUpdateFunction::Run() {
@@ -1592,7 +1592,7 @@ ExtensionFunction::ResponseAction TabsUpdateFunction::Run() {
return RespondNow(Error(tabs_constants::kTabStripNotEditableError));
}
@@ -46,7 +46,7 @@ index faefffb1010e8..ee3c11ffda006 100644
tab_strip->ActivateTabAt(tab_index);
DCHECK_EQ(contents, tab_strip->GetActiveWebContents());
}
@@ -1591,7 +1591,7 @@ ExtensionFunction::ResponseAction TabsUpdateFunction::Run() {
@@ -1606,7 +1606,7 @@ ExtensionFunction::ResponseAction TabsUpdateFunction::Run() {
}
bool highlighted = *params->update_properties.highlighted;
@@ -55,7 +55,7 @@ index faefffb1010e8..ee3c11ffda006 100644
tab_strip->ToggleSelectionAt(tab_index);
}
}
@@ -1604,7 +1604,7 @@ ExtensionFunction::ResponseAction TabsUpdateFunction::Run() {
@@ -1619,7 +1619,7 @@ ExtensionFunction::ResponseAction TabsUpdateFunction::Run() {
base::NumberToString(tab_id))));
}
@@ -64,7 +64,7 @@ index faefffb1010e8..ee3c11ffda006 100644
int opener_id = *params->update_properties.opener_tab_id;
WebContents* opener_contents = nullptr;
if (opener_id == tab_id) {
@@ -1638,7 +1638,7 @@ ExtensionFunction::ResponseAction TabsUpdateFunction::Run() {
@@ -1653,7 +1653,7 @@ ExtensionFunction::ResponseAction TabsUpdateFunction::Run() {
->SetAutoDiscardable(state);
}
@@ -73,7 +73,7 @@ index faefffb1010e8..ee3c11ffda006 100644
// Bug fix for crbug.com/1197888. Don't let the extension update the tab if
// the user is dragging tabs.
if (!ExtensionTabUtil::IsTabStripEditable()) {
@@ -1659,8 +1659,9 @@ ExtensionFunction::ResponseAction TabsUpdateFunction::Run() {
@@ -1674,8 +1674,9 @@ ExtensionFunction::ResponseAction TabsUpdateFunction::Run() {
// Navigate the tab to a new location if the url is different.
if (params->update_properties.url) {
std::string updated_url = *params->update_properties.url;
@@ -85,7 +85,7 @@ index faefffb1010e8..ee3c11ffda006 100644
return RespondNow(Error(ErrorUtils::FormatErrorMessage(
tabs_constants::kURLsNotAllowedInIncognitoError, updated_url)));
}
@@ -1674,7 +1675,7 @@ ExtensionFunction::ResponseAction TabsUpdateFunction::Run() {
@@ -1689,7 +1690,7 @@ ExtensionFunction::ResponseAction TabsUpdateFunction::Run() {
return RespondNow(Error(std::move(error)));
}

View File

@@ -0,0 +1,27 @@
diff --git chrome/browser/task_manager/providers/render_process_host_task_provider.cc chrome/browser/task_manager/providers/render_process_host_task_provider.cc
index 11b05cbfc6077..45a5b11158a21 100644
--- chrome/browser/task_manager/providers/render_process_host_task_provider.cc
+++ chrome/browser/task_manager/providers/render_process_host_task_provider.cc
@@ -110,18 +110,14 @@ void RenderProcessHostTaskProvider::OnRenderProcessHostCreated(
void RenderProcessHostTaskProvider::RenderProcessExited(
content::RenderProcessHost* host,
const content::ChildProcessTerminationInfo& info) {
- if (is_updating_) {
- DeleteTask(host->GetID());
- host_observation_.RemoveObservation(host);
- }
+ DeleteTask(host->GetID());
+ host_observation_.RemoveObservation(host);
}
void RenderProcessHostTaskProvider::RenderProcessHostDestroyed(
content::RenderProcessHost* host) {
- if (is_updating_) {
- DeleteTask(host->GetID());
- host_observation_.RemoveObservation(host);
- }
+ DeleteTask(host->GetID());
+ host_observation_.RemoveObservation(host);
}
} // namespace task_manager

View File

@@ -248,7 +248,7 @@ index ac1361bd6bc2e..a303ca169c7f7 100644
base::PathService::OverrideAndCreateIfNeeded(
diff --git chrome/browser/chrome_browser_main.cc chrome/browser/chrome_browser_main.cc
index b85539a24653f..48c74152428cf 100644
index dbce369a3e8bd..a7fbe297c56d1 100644
--- chrome/browser/chrome_browser_main.cc
+++ chrome/browser/chrome_browser_main.cc
@@ -53,6 +53,7 @@
@@ -259,7 +259,7 @@ index b85539a24653f..48c74152428cf 100644
#include "chrome/browser/about_flags.h"
#include "chrome/browser/active_use_util.h"
#include "chrome/browser/after_startup_task_utils.h"
@@ -530,7 +531,7 @@ void ProcessSingletonNotificationCallbackImpl(
@@ -531,7 +532,7 @@ void ProcessSingletonNotificationCallbackImpl(
return;
}
@@ -268,7 +268,7 @@ index b85539a24653f..48c74152428cf 100644
// The uninstall command-line switch is handled by the origin process; see
// ChromeMainDelegate::PostEarlyInitialization(...). The other process won't
// be able to become the singleton process and will display a window asking
@@ -843,7 +844,7 @@ int ChromeBrowserMainParts::PreEarlyInitialization() {
@@ -846,7 +847,7 @@ int ChromeBrowserMainParts::PreEarlyInitialization() {
return content::RESULT_CODE_NORMAL_EXIT;
}
@@ -277,7 +277,7 @@ index b85539a24653f..48c74152428cf 100644
// If we are running stale binaries then relaunch and exit immediately.
if (upgrade_util::IsRunningOldChrome()) {
if (!upgrade_util::RelaunchChromeBrowser(
@@ -856,7 +857,7 @@ int ChromeBrowserMainParts::PreEarlyInitialization() {
@@ -859,7 +860,7 @@ int ChromeBrowserMainParts::PreEarlyInitialization() {
// result in browser startup bailing.
return chrome::RESULT_CODE_NORMAL_EXIT_UPGRADE_RELAUNCHED;
}
@@ -286,7 +286,7 @@ index b85539a24653f..48c74152428cf 100644
return load_local_state_result;
}
@@ -966,7 +967,7 @@ int ChromeBrowserMainParts::OnLocalStateLoaded(
@@ -969,7 +970,7 @@ int ChromeBrowserMainParts::OnLocalStateLoaded(
browser_process_->local_state());
platform_management_service->RefreshCache(base::NullCallback());
@@ -295,7 +295,7 @@ index b85539a24653f..48c74152428cf 100644
if (first_run::IsChromeFirstRun()) {
bool stats_default;
if (GoogleUpdateSettings::GetCollectStatsConsentDefault(&stats_default)) {
@@ -979,7 +980,7 @@ int ChromeBrowserMainParts::OnLocalStateLoaded(
@@ -982,7 +983,7 @@ int ChromeBrowserMainParts::OnLocalStateLoaded(
: metrics::EnableMetricsDefault::OPT_IN);
}
}
@@ -304,7 +304,7 @@ index b85539a24653f..48c74152428cf 100644
std::string locale =
startup_data_->chrome_feature_list_creator()->actual_locale();
@@ -1012,6 +1013,7 @@ int ChromeBrowserMainParts::ApplyFirstRunPrefs() {
@@ -1015,6 +1016,7 @@ int ChromeBrowserMainParts::ApplyFirstRunPrefs() {
#if !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_CHROMEOS_ASH)
master_prefs_ = std::make_unique<first_run::MasterPrefs>();
@@ -312,7 +312,7 @@ index b85539a24653f..48c74152428cf 100644
std::unique_ptr<installer::InitialPreferences> installer_initial_prefs =
startup_data_->chrome_feature_list_creator()->TakeInitialPrefs();
if (!installer_initial_prefs)
@@ -1045,6 +1047,7 @@ int ChromeBrowserMainParts::ApplyFirstRunPrefs() {
@@ -1048,6 +1050,7 @@ int ChromeBrowserMainParts::ApplyFirstRunPrefs() {
master_prefs_->confirm_to_quit);
}
#endif // BUILDFLAG(IS_MAC)
@@ -320,7 +320,7 @@ index b85539a24653f..48c74152428cf 100644
#endif // !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_CHROMEOS_ASH)
return content::RESULT_CODE_NORMAL_EXIT;
}
@@ -1106,6 +1109,7 @@ int ChromeBrowserMainParts::PreCreateThreadsImpl() {
@@ -1109,6 +1112,7 @@ int ChromeBrowserMainParts::PreCreateThreadsImpl() {
browser_process_->browser_policy_connector()->OnResourceBundleCreated();
@@ -328,7 +328,7 @@ index b85539a24653f..48c74152428cf 100644
// Android does first run in Java instead of native.
// Chrome OS has its own out-of-box-experience code.
#if !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_CHROMEOS_ASH)
@@ -1127,6 +1131,7 @@ int ChromeBrowserMainParts::PreCreateThreadsImpl() {
@@ -1130,6 +1134,7 @@ int ChromeBrowserMainParts::PreCreateThreadsImpl() {
#endif // BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
}
#endif // !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_CHROMEOS_ASH)
@@ -336,7 +336,7 @@ index b85539a24653f..48c74152428cf 100644
#if BUILDFLAG(IS_MAC)
#if defined(ARCH_CPU_X86_64)
@@ -1498,6 +1503,7 @@ int ChromeBrowserMainParts::PreMainMessageLoopRunImpl() {
@@ -1501,6 +1506,7 @@ int ChromeBrowserMainParts::PreMainMessageLoopRunImpl() {
browser_process_->PreMainMessageLoopRun();
#if BUILDFLAG(IS_WIN)
@@ -344,7 +344,7 @@ index b85539a24653f..48c74152428cf 100644
// If the command line specifies 'uninstall' then we need to work here
// unless we detect another chrome browser running.
if (base::CommandLine::ForCurrentProcess()->HasSwitch(switches::kUninstall)) {
@@ -1509,6 +1515,7 @@ int ChromeBrowserMainParts::PreMainMessageLoopRunImpl() {
@@ -1512,6 +1518,7 @@ int ChromeBrowserMainParts::PreMainMessageLoopRunImpl() {
return ChromeBrowserMainPartsWin::HandleIconsCommands(
*base::CommandLine::ForCurrentProcess());
}
@@ -352,7 +352,7 @@ index b85539a24653f..48c74152428cf 100644
ui::SelectFileDialog::SetFactory(
std::make_unique<ChromeSelectFileDialogFactory>());
@@ -1534,6 +1541,7 @@ int ChromeBrowserMainParts::PreMainMessageLoopRunImpl() {
@@ -1537,6 +1544,7 @@ int ChromeBrowserMainParts::PreMainMessageLoopRunImpl() {
}
#endif // BUILDFLAG(CHROME_FOR_TESTING)
@@ -360,7 +360,7 @@ index b85539a24653f..48c74152428cf 100644
if (base::CommandLine::ForCurrentProcess()->HasSwitch(
switches::kMakeDefaultBrowser)) {
bool is_managed = g_browser_process->local_state()->IsManagedPreference(
@@ -1547,18 +1555,22 @@ int ChromeBrowserMainParts::PreMainMessageLoopRunImpl() {
@@ -1550,18 +1558,22 @@ int ChromeBrowserMainParts::PreMainMessageLoopRunImpl() {
? static_cast<int>(content::RESULT_CODE_NORMAL_EXIT)
: static_cast<int>(chrome::RESULT_CODE_SHELL_INTEGRATION_FAILED);
}
@@ -383,7 +383,7 @@ index b85539a24653f..48c74152428cf 100644
#if !BUILDFLAG(IS_ANDROID) && BUILDFLAG(ENABLE_DOWNGRADE_PROCESSING)
// Begin relaunch processing immediately if User Data migration is required
@@ -1597,7 +1609,7 @@ int ChromeBrowserMainParts::PreMainMessageLoopRunImpl() {
@@ -1600,7 +1612,7 @@ int ChromeBrowserMainParts::PreMainMessageLoopRunImpl() {
}
#endif // !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_CHROMEOS)
@@ -392,7 +392,7 @@ index b85539a24653f..48c74152428cf 100644
// Check if there is any machine level Chrome installed on the current
// machine. If yes and the current Chrome process is user level, we do not
// allow the user level Chrome to run. So we notify the user and uninstall
@@ -1606,7 +1618,7 @@ int ChromeBrowserMainParts::PreMainMessageLoopRunImpl() {
@@ -1609,7 +1621,7 @@ int ChromeBrowserMainParts::PreMainMessageLoopRunImpl() {
// obtained but before potentially creating the first run sentinel).
if (ChromeBrowserMainPartsWin::CheckMachineLevelInstall())
return chrome::RESULT_CODE_MACHINE_LEVEL_INSTALL_EXISTS;
@@ -401,7 +401,7 @@ index b85539a24653f..48c74152428cf 100644
// Desktop construction occurs here, (required before profile creation).
PreProfileInit();
@@ -1679,6 +1691,7 @@ int ChromeBrowserMainParts::PreMainMessageLoopRunImpl() {
@@ -1682,6 +1694,7 @@ int ChromeBrowserMainParts::PreMainMessageLoopRunImpl() {
// Call `PostProfileInit()`and set it up for profiles created later.
profile_init_manager_ = std::make_unique<ProfileInitManager>(this, profile);
@@ -409,7 +409,7 @@ index b85539a24653f..48c74152428cf 100644
#if !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_CHROMEOS_ASH)
// Execute first run specific code after the PrefService has been initialized
// and preferences have been registered since some of the import code depends
@@ -1718,6 +1731,7 @@ int ChromeBrowserMainParts::PreMainMessageLoopRunImpl() {
@@ -1721,6 +1734,7 @@ int ChromeBrowserMainParts::PreMainMessageLoopRunImpl() {
*base::CommandLine::ForCurrentProcess());
}
#endif // BUILDFLAG(IS_WIN)
@@ -417,7 +417,7 @@ index b85539a24653f..48c74152428cf 100644
// Configure modules that need access to resources.
net::NetModule::SetResourceProvider(ChromeNetResourceProvider);
@@ -1809,6 +1823,11 @@ int ChromeBrowserMainParts::PreMainMessageLoopRunImpl() {
@@ -1812,6 +1826,11 @@ int ChromeBrowserMainParts::PreMainMessageLoopRunImpl() {
g_browser_process->profile_manager()->GetLastOpenedProfiles();
}
#endif // BUILDFLAG(IS_CHROMEOS_ASH)
@@ -429,7 +429,7 @@ index b85539a24653f..48c74152428cf 100644
// This step is costly.
if (browser_creator_->Start(*base::CommandLine::ForCurrentProcess(),
base::FilePath(), profile_info,
@@ -1841,11 +1860,14 @@ int ChromeBrowserMainParts::PreMainMessageLoopRunImpl() {
@@ -1844,11 +1863,14 @@ int ChromeBrowserMainParts::PreMainMessageLoopRunImpl() {
// Create the RunLoop for MainMessageLoopRun() to use and transfer
// ownership of the browser's lifetime to the BrowserProcess.
@@ -654,7 +654,7 @@ index 8a96e0b26a27a..2442bf7e7f88c 100644
#endif
diff --git chrome/browser/prefs/browser_prefs.cc chrome/browser/prefs/browser_prefs.cc
index e408ae181c2eb..8a68d4556adf8 100644
index 921f99a4ee22d..8f059c28244cd 100644
--- chrome/browser/prefs/browser_prefs.cc
+++ chrome/browser/prefs/browser_prefs.cc
@@ -16,6 +16,7 @@
@@ -676,7 +676,7 @@ index e408ae181c2eb..8a68d4556adf8 100644
#if BUILDFLAG(ENABLE_EXTENSIONS)
#include "chrome/browser/accessibility/animation_policy_prefs.h"
#include "chrome/browser/apps/platform_apps/shortcut_manager.h"
@@ -1801,7 +1806,8 @@ void RegisterLocalState(PrefRegistrySimple* registry) {
@@ -1813,7 +1818,8 @@ void RegisterLocalState(PrefRegistrySimple* registry) {
#endif // BUILDFLAG(GOOGLE_CHROME_BRANDING)
#endif // BUILDFLAG(IS_WIN)
@@ -686,7 +686,7 @@ index e408ae181c2eb..8a68d4556adf8 100644
downgrade::RegisterPrefs(registry);
#endif
@@ -1854,6 +1860,11 @@ void RegisterLocalState(PrefRegistrySimple* registry) {
@@ -1866,6 +1872,11 @@ void RegisterLocalState(PrefRegistrySimple* registry) {
// This is intentionally last.
RegisterLocalStatePrefsForMigration(registry);
@@ -698,7 +698,7 @@ index e408ae181c2eb..8a68d4556adf8 100644
}
// Register prefs applicable to all profiles.
@@ -2305,6 +2316,10 @@ void RegisterUserProfilePrefs(user_prefs::PrefRegistrySyncable* registry,
@@ -2317,6 +2328,10 @@ void RegisterUserProfilePrefs(user_prefs::PrefRegistrySyncable* registry,
const std::string& locale) {
RegisterProfilePrefs(registry, locale);

View File

@@ -721,7 +721,7 @@ index 6fa57160f7193..4e10786e2c5a4 100644
// Do not friend BrowserViewLayout. Use the BrowserViewLayoutDelegate
// interface to keep these two classes decoupled and testable.
diff --git chrome/browser/ui/views/frame/browser_view_layout.cc chrome/browser/ui/views/frame/browser_view_layout.cc
index 80dcf5b08c67c..d0aef3fc40b07 100644
index cb14b46b727ca..eef3da9247c54 100644
--- chrome/browser/ui/views/frame/browser_view_layout.cc
+++ chrome/browser/ui/views/frame/browser_view_layout.cc
@@ -53,6 +53,10 @@
@@ -755,16 +755,16 @@ index 80dcf5b08c67c..d0aef3fc40b07 100644
return gfx::Point(middle_x - size.width() / 2, top);
}
@@ -162,7 +170,7 @@ class BrowserViewLayout::WebContentsModalDialogHostViews
@@ -137,7 +145,7 @@ class BrowserViewLayout::WebContentsModalDialogHostViews
// universally.
views::View* view = browser_view_layout_->contents_container_;
gfx::Rect content_area = view->ConvertRectToWidget(view->GetLocalBounds());
- const int top = browser_view_layout_->dialog_top_y_;
+ const int top = GetDialogTopY();
return gfx::Size(content_area.width(), content_area.bottom() - top);
#endif
}
@@ -192,6 +200,13 @@ class BrowserViewLayout::WebContentsModalDialogHostViews
@@ -166,6 +174,13 @@ class BrowserViewLayout::WebContentsModalDialogHostViews
return host_widget ? host_widget->GetNativeView() : nullptr;
}
@@ -778,7 +778,7 @@ index 80dcf5b08c67c..d0aef3fc40b07 100644
// Add/remove observer.
void AddObserver(ModalDialogHostObserver* observer) override {
observer_list_.AddObserver(observer);
@@ -513,6 +528,8 @@ void BrowserViewLayout::Layout(views::View* browser_view) {
@@ -487,6 +502,8 @@ void BrowserViewLayout::Layout(views::View* browser_view) {
if (exclusive_access_bubble)
exclusive_access_bubble->RepositionIfVisible();
@@ -787,7 +787,7 @@ index 80dcf5b08c67c..d0aef3fc40b07 100644
// Adjust any hosted dialogs if the browser's dialog hosting bounds changed.
const gfx::Rect dialog_bounds(dialog_host_->GetDialogPosition(gfx::Size()),
dialog_host_->GetMaximumDialogSize());
@@ -526,6 +543,7 @@ void BrowserViewLayout::Layout(views::View* browser_view) {
@@ -500,6 +517,7 @@ void BrowserViewLayout::Layout(views::View* browser_view) {
latest_dialog_bounds_in_screen_ = dialog_bounds_in_screen;
dialog_host_->NotifyPositionRequiresUpdate();
}
@@ -795,7 +795,7 @@ index 80dcf5b08c67c..d0aef3fc40b07 100644
}
gfx::Size BrowserViewLayout::GetPreferredSize(
@@ -667,6 +685,13 @@ int BrowserViewLayout::LayoutWebUITabStrip(int top) {
@@ -641,6 +659,13 @@ int BrowserViewLayout::LayoutWebUITabStrip(int top) {
int BrowserViewLayout::LayoutToolbar(int top) {
TRACE_EVENT0("ui", "BrowserViewLayout::LayoutToolbar");
@@ -839,7 +839,7 @@ index 71445bfab1824..c77750ea2a820 100644
ContentsWebView::~ContentsWebView() {
diff --git chrome/browser/ui/views/frame/picture_in_picture_browser_frame_view.cc chrome/browser/ui/views/frame/picture_in_picture_browser_frame_view.cc
index 9dddf71ef05bd..18c43631ea288 100644
index 04ad8415b5e95..eb5f7161d72e0 100644
--- chrome/browser/ui/views/frame/picture_in_picture_browser_frame_view.cc
+++ chrome/browser/ui/views/frame/picture_in_picture_browser_frame_view.cc
@@ -619,6 +619,11 @@ PictureInPictureBrowserFrameView::PictureInPictureBrowserFrameView(
@@ -915,7 +915,7 @@ index 9dddf71ef05bd..18c43631ea288 100644
top_bar_container_view_->SetBoundsRect(top_bar);
#if !BUILDFLAG(IS_ANDROID)
if (auto_pip_setting_overlay_) {
@@ -1371,7 +1401,8 @@ gfx::Insets PictureInPictureBrowserFrameView::ResizeBorderInsets() const {
@@ -1372,7 +1402,8 @@ gfx::Insets PictureInPictureBrowserFrameView::ResizeBorderInsets() const {
}
int PictureInPictureBrowserFrameView::GetTopAreaHeight() const {

View File

@@ -139,7 +139,7 @@ index 784e0a5166d6b..1fd1e9ee107f3 100644
// started.
virtual void SetRuntimeFeaturesDefaultsBeforeBlinkInitialization() {}
diff --git content/renderer/render_thread_impl.cc content/renderer/render_thread_impl.cc
index 34d250220f97f..2576aa09f5c44 100644
index 8fbed3f73560e..909a4d3e1eae5 100644
--- content/renderer/render_thread_impl.cc
+++ content/renderer/render_thread_impl.cc
@@ -573,6 +573,8 @@ void RenderThreadImpl::Init() {

View File

@@ -12,7 +12,7 @@ index 44a11ec90ec9b..4c35b35a97f28 100644
# https://crbug.com/474506.
"//clank/java/BUILD.gn",
diff --git BUILD.gn BUILD.gn
index 097e59f46d07a..54096982660c6 100644
index b1a8b7eaabaf4..89038f28c70c9 100644
--- BUILD.gn
+++ BUILD.gn
@@ -20,6 +20,7 @@ import("//build/config/sanitizers/sanitizers.gni")

View File

@@ -1,8 +1,8 @@
diff --git content/browser/renderer_host/render_frame_host_impl.cc content/browser/renderer_host/render_frame_host_impl.cc
index 0236631b56d79..aedc1c65a20f4 100644
index a0d5a983bb46a..e1c7fd08bc104 100644
--- content/browser/renderer_host/render_frame_host_impl.cc
+++ content/browser/renderer_host/render_frame_host_impl.cc
@@ -11277,6 +11277,7 @@ void RenderFrameHostImpl::CommitNavigation(
@@ -11407,6 +11407,7 @@ void RenderFrameHostImpl::CommitNavigation(
auto browser_calc_origin_to_commit =
navigation_request->GetOriginToCommitWithDebugInfo();
if (!process_lock.is_error_page() && !is_mhtml_subframe &&

View File

@@ -1,5 +1,5 @@
diff --git ui/display/screen.cc ui/display/screen.cc
index 3090a05e91f31..7fac1b23ffb62 100644
index 3090a05e91f31..d9667f9526278 100644
--- ui/display/screen.cc
+++ ui/display/screen.cc
@@ -108,13 +108,13 @@ base::TimeDelta Screen::CalculateIdleTime() const {
@@ -7,19 +7,19 @@ index 3090a05e91f31..7fac1b23ffb62 100644
const gfx::Rect& screen_rect) const {
float scale = GetDisplayNearestWindow(window).device_scale_factor();
- return ScaleToEnclosingRect(screen_rect, 1.0f / scale);
+ return ScaleToEnclosedRect(screen_rect, 1.0f / scale);
+ return ScaleToRoundedRect(screen_rect, 1.0f / scale);
}
gfx::Rect Screen::DIPToScreenRectInWindow(gfx::NativeWindow window,
const gfx::Rect& dip_rect) const {
float scale = GetDisplayNearestWindow(window).device_scale_factor();
- return ScaleToEnclosingRect(dip_rect, scale);
+ return ScaleToEnclosedRect(dip_rect, scale);
+ return ScaleToRoundedRect(dip_rect, scale);
}
bool Screen::GetDisplayWithDisplayId(int64_t display_id,
diff --git ui/display/win/screen_win.cc ui/display/win/screen_win.cc
index db01034339fda..84cd0ee222ef0 100644
index db01034339fda..59bfd0e2f75c4 100644
--- ui/display/win/screen_win.cc
+++ ui/display/win/screen_win.cc
@@ -619,7 +619,7 @@ gfx::Rect ScreenWin::ScreenToDIPRect(HWND hwnd, const gfx::Rect& pixel_bounds) {
@@ -27,7 +27,7 @@ index db01034339fda..84cd0ee222ef0 100644
const float scale_factor =
1.0f / screen_win_display.display().device_scale_factor();
- return {origin, ScaleToEnclosingRect(pixel_bounds, scale_factor).size()};
+ return {origin, ScaleToEnclosedRect(pixel_bounds, scale_factor).size()};
+ return {origin, ScaleToRoundedRect(pixel_bounds, scale_factor).size()};
}
// static
@@ -36,7 +36,7 @@ index db01034339fda..84cd0ee222ef0 100644
display::win::DIPToScreenPoint(dip_bounds.origin(), screen_win_display);
const float scale_factor = screen_win_display.display().device_scale_factor();
- return {origin, ScaleToEnclosingRect(dip_bounds, scale_factor).size()};
+ return {origin, ScaleToEnclosedRect(dip_bounds, scale_factor).size()};
+ return {origin, ScaleToRoundedRect(dip_bounds, scale_factor).size()};
}
// static

View File

@@ -4,6 +4,9 @@
#include "tests/cefclient/browser/base_client_handler.h"
#include "tests/cefclient/browser/main_context.h"
#include "tests/cefclient/browser/root_window_manager.h"
namespace client {
BaseClientHandler::BaseClientHandler() {
@@ -49,6 +52,10 @@ void BaseClientHandler::OnAfterCreated(CefRefPtr<CefBrowser> browser) {
message_router_->AddHandler(message_handler, false);
}
}
if (track_as_other_browser_) {
MainContext::Get()->GetRootWindowManager()->OtherBrowserCreated();
}
}
void BaseClientHandler::OnBeforeClose(CefRefPtr<CefBrowser> browser) {
@@ -63,6 +70,10 @@ void BaseClientHandler::OnBeforeClose(CefRefPtr<CefBrowser> browser) {
message_handler_set_.clear();
message_router_ = nullptr;
}
if (track_as_other_browser_) {
MainContext::Get()->GetRootWindowManager()->OtherBrowserClosed();
}
}
bool BaseClientHandler::OnBeforeBrowse(CefRefPtr<CefBrowser> browser,

View File

@@ -103,7 +103,13 @@ class BaseClientHandler : public CefClient,
return resource_manager_;
}
void set_track_as_other_browser(bool val) { track_as_other_browser_ = val; }
private:
// True if this handler should call
// RootWindowManager::OtherBrowser[Created|Closed].
bool track_as_other_browser_ = true;
// The current number of browsers using this handler.
int browser_count_ = 0;

View File

@@ -464,6 +464,10 @@ ClientHandler::ClientHandler(Delegate* delegate,
startup_url_(startup_url),
delegate_(delegate),
console_log_file_(MainContext::Get()->GetConsoleLogPath()) {
// This handler is used with RootWindows that are explicitly tracked by
// RootWindowManager.
set_track_as_other_browser(false);
DCHECK(!console_log_file_.empty());
// Read command line settings.

View File

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

View File

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

View File

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

View File

@@ -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;
}
@@ -199,6 +202,31 @@ void RootWindowManager::CloseAllWindows(bool force) {
}
}
void RootWindowManager::OtherBrowserCreated() {
if (!CURRENTLY_ON_MAIN_THREAD()) {
// Execute this method on the main thread.
MAIN_POST_CLOSURE(base::BindOnce(&RootWindowManager::OtherBrowserCreated,
base::Unretained(this)));
return;
}
other_browser_ct_++;
}
void RootWindowManager::OtherBrowserClosed() {
if (!CURRENTLY_ON_MAIN_THREAD()) {
// Execute this method on the main thread.
MAIN_POST_CLOSURE(base::BindOnce(&RootWindowManager::OtherBrowserClosed,
base::Unretained(this)));
return;
}
DCHECK_GT(other_browser_ct_, 0);
other_browser_ct_--;
MaybeCleanup();
}
void RootWindowManager::OnRootWindowCreated(
scoped_refptr<RootWindow> root_window) {
if (!CURRENTLY_ON_MAIN_THREAD()) {
@@ -315,11 +343,7 @@ void RootWindowManager::OnRootWindowDestroyed(RootWindow* root_window) {
active_root_window_ = nullptr;
}
if (terminate_when_all_windows_closed_ && root_windows_.empty()) {
// All windows have closed. Clean up on the UI thread.
CefPostTask(TID_UI, base::BindOnce(&RootWindowManager::CleanupOnUIThread,
base::Unretained(this)));
}
MaybeCleanup();
}
void RootWindowManager::OnRootWindowActivated(RootWindow* root_window) {
@@ -332,6 +356,16 @@ void RootWindowManager::OnRootWindowActivated(RootWindow* root_window) {
active_root_window_ = root_window;
}
void RootWindowManager::MaybeCleanup() {
REQUIRE_MAIN_THREAD();
if (terminate_when_all_windows_closed_ && root_windows_.empty() &&
other_browser_ct_ == 0) {
// All windows and browsers have closed. Clean up on the UI thread.
CefPostTask(TID_UI, base::BindOnce(&RootWindowManager::CleanupOnUIThread,
base::Unretained(this)));
}
}
void RootWindowManager::CleanupOnUIThread() {
CEF_REQUIRE_UI_THREAD();

View File

@@ -62,6 +62,10 @@ class RootWindowManager : public RootWindow::Delegate {
return request_context_per_browser_;
}
// Track other browsers that are not directly associated with a RootWindow.
void OtherBrowserCreated();
void OtherBrowserClosed();
private:
// Allow deletion via std::unique_ptr only.
friend std::default_delete<RootWindowManager>;
@@ -83,6 +87,7 @@ class RootWindowManager : public RootWindow::Delegate {
CefRefPtr<CefRequestContext> CreateRequestContext(
RequestContextCallback callback);
void MaybeCleanup();
void CleanupOnUIThread();
const bool terminate_when_all_windows_closed_;
@@ -93,6 +98,9 @@ class RootWindowManager : public RootWindow::Delegate {
typedef std::set<scoped_refptr<RootWindow>> RootWindowSet;
RootWindowSet root_windows_;
// Count of other browsers. Only accessed on the main thread.
int other_browser_ct_ = 0;
// The currently active/foreground RootWindow. Only accessed on the main
// thread.
scoped_refptr<RootWindow> active_root_window_;

View File

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

View File

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

View File

@@ -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,
@@ -797,9 +817,11 @@ void ViewsWindow::OnWindowBoundsChanged(CefRefPtr<CefWindow> window,
bool ViewsWindow::CanClose(CefRefPtr<CefWindow> window) {
CEF_REQUIRE_UI_THREAD();
CefRefPtr<CefBrowser> browser = browser_view_->GetBrowser();
#if defined(OS_MAC)
// On MacOS we might hide the window instead of closing it.
if (hide_on_close_) {
if (hide_on_close_ && browser && !browser->GetHost()->IsReadyToBeClosed()) {
if (window->IsFullscreen()) {
// Need to exit fullscreen mode before hiding the window.
// Execution continues in OnWindowFullscreenTransition.
@@ -813,7 +835,6 @@ bool ViewsWindow::CanClose(CefRefPtr<CefWindow> window) {
#endif
// Allow the window to close if the browser says it's OK.
CefRefPtr<CefBrowser> browser = browser_view_->GetBrowser();
if (browser) {
return browser->GetHost()->TryCloseBrowser();
}
@@ -900,6 +921,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 +1024,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 +1051,10 @@ void ViewsWindow::OnWindowChanged(CefRefPtr<CefView> view, bool added) {
location_bar_ = nullptr;
}
}
if (overlay_browser_) {
overlay_browser_->Destroy();
overlay_browser_ = nullptr;
}
}
}
@@ -1028,6 +1068,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 +1110,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 +1121,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 +1359,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();
}
}

View File

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

View File

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

View File

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

View File

@@ -951,12 +951,8 @@ class V8RendererTest : public ClientAppRenderer::Delegate,
static const char* kName = "val";
static const char* kGetException = "My get exception";
static const char* kSetException = "My set exception";
static const char* kGetExceptionMsg =
"Uncaught Error: Failed to read the 'val' property from 'Object': My "
"get exception";
static const char* kSetExceptionMsg =
"Uncaught Error: Failed to set the 'val' property on 'Object': My set "
"exception";
static const char* kGetExceptionMsg = "Uncaught Error: My get exception";
static const char* kSetExceptionMsg = "Uncaught Error: My set exception";
class Accessor : public CefV8Accessor {
public:
@@ -1497,17 +1493,13 @@ class V8RendererTest : public ClientAppRenderer::Delegate,
static const char* kSetByIndexException = "My set_byindex exception";
static const char* kGetByNameExceptionMsg =
"Uncaught Error: Failed to read a named property 'val' from 'Object': "
"My get_byname exception";
"Uncaught Error: My get_byname exception";
static const char* kGetByIndexExceptionMsg =
"Uncaught Error: Failed to read an indexed property [1] from 'Object': "
"My get_byindex exception";
"Uncaught Error: My get_byindex exception";
static const char* kSetByNameExceptionMsg =
"Uncaught Error: Failed to set a named property 'val' on 'Object': My "
"set_byname exception";
"Uncaught Error: My set_byname exception";
static const char* kSetByIndexExceptionMsg =
"Uncaught Error: Failed to set an indexed property [1] on 'Object': My "
"set_byindex exception";
"Uncaught Error: My set_byindex exception";
class Interceptor : public CefV8Interceptor {
public:

View File

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

View File

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

View File

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