Compare commits

...

17 Commits
7103 ... 6045

Author SHA1 Message Date
Marshall Greenblatt
55e15c8dee cmake: Fix docs for CMake and Xcode version 2023-12-06 13:20:07 -05:00
Marshall Greenblatt
9d567e22ba linux: Disable compiler TLS in libxml2 (fixes #3616) 2023-12-06 12:51:27 -05:00
Marshall Greenblatt
848712f89e tests: Remove accidental C++20 dependency (see #3611) 2023-12-06 12:50:19 -05:00
Marshall Greenblatt
5d1e039e05 Update to Chromium version 119.0.6045.199 2023-11-29 16:37:39 +00:00
Marshall Greenblatt
c76a3b9f2e Update to Chromium version 119.0.6045.159 2023-11-15 15:42:47 +00:00
Marshall Greenblatt
2d7731bda2 tools: Fix typo in make_distrib.py 2023-11-14 12:38:38 -05:00
Nik Pavlov
ae23bbc63c Remove virtual attribute from CefStringBase destructor (fixes #3587) 2023-11-14 12:38:38 -05:00
Marshall Greenblatt
81e35b9277 chrome: Support Chrome and DevTools command execution (fixes #3282, fixes #3600)
Add new CefBrowserHost::[Can]ExecuteChromeCommand methods for executing
arbitrary Chrome commands.

Add support for existing CefBrowserHost::ShowDevTools, CloseDevTools and
HasDevTools methods.

DevTools windows now support the same Views callbacks as normal popup
windows with the new CefLifeSpanHandler::OnBeforeDevToolsPopup callback
as the DevTools-specific equivalent of OnBeforePopup.

Always create DevTools as an undocked window to support use of
ShowDevTools with default Chrome browser windows.

To test:

Run `ceftests --enable-chrome-runtime [--use-views]
     --gtest_filter=V8Test.OnUncaughtExceptionDevTools`

OR:

1. Run `cefclient --enable-chrome-runtime [--use-native]`
2. Select "Show DevTools", "Close DevTools" or "Inspect" from the
   right-click menu.
3. Notice that the DevTools window is Views-hosted (or native-hosted)
   and works as expected.

Add --use-default-popup to get a default styled popup in step 3.
2023-11-14 12:38:38 -05:00
Marshall Greenblatt
f768881e64 Update to Chromium version 119.0.6045.124 2023-11-10 16:45:57 +00:00
Marshall Greenblatt
9499fd03b6 views: Support per-accelerator priority config (fixes #3598) 2023-11-08 14:31:25 -05:00
Marshall Greenblatt
f2646ea38e Add workaround for https://crbug.com/1500371 (see #3597) 2023-11-07 18:02:23 -05:00
Marshall Greenblatt
c49b21c407 mac: Update CSS on fullscreen window exit (fixes #3597) 2023-11-07 18:02:17 -05:00
Marshall Greenblatt
fe622e7aa0 chrome: Hit-test PiP draggable regions before resize border (see #3566) 2023-11-06 16:02:02 -05:00
Marshall Greenblatt
26778307c8 Update to Chromium version 119.0.6045.105 2023-11-01 21:50:59 +00:00
Marshall Greenblatt
ef03e9636e Update to Chromium version 119.0.6045.59 2023-10-27 17:21:24 +00:00
Nik Pavlov
612d63af73 Add binary format support to CefMessageRouter (fixes #3502) 2023-10-25 14:23:04 -04:00
Marshall Greenblatt
e8fb169bed Update to Chromium version 119.0.6045.33 2023-10-24 11:52:47 -04:00
109 changed files with 3724 additions and 871 deletions

View File

@@ -7,5 +7,6 @@
# https://bitbucket.org/chromiumembedded/cef/wiki/BranchesAndBuilding
{
'chromium_checkout': 'refs/tags/119.0.6045.0'
'chromium_checkout': 'refs/tags/119.0.6045.199',
'depot_tools_checkout': '744bfd2a7b'
}

View File

@@ -12,7 +12,7 @@
# distribution include:
#
# Linux: Ninja, GCC 7.5.0+, Unix Makefiles
# MacOS: Ninja, Xcode 12.2 to 13.0
# MacOS: Ninja, Xcode 12.2 to 15.0
# Windows: Ninja, Visual Studio 2022
#
# Ninja is a cross-platform open-source tool for running fast builds using
@@ -36,7 +36,7 @@
#
# The below requirements must be met to build this CEF binary distribution.
#
# - CMake version 3.19 or newer.
# - CMake version 3.21 or newer.
#
# - Linux requirements:
# Currently supported distributions include Debian 10 (Buster), Ubuntu 18
@@ -48,7 +48,7 @@
# libgtk3.0-dev (required by the cefclient target only)
#
# - MacOS requirements:
# Xcode 12.2 to 13.4 building on MacOS 10.15.4 (Catalina) or newer. Only
# Xcode 12.2 to 15.0 building on MacOS 10.15.4 (Catalina) or newer. Only
# 64-bit builds are supported. The Xcode command-line tools must also be
# installed. Newer Xcode versions may not have been been tested and are not
# recommended.

View File

@@ -147,6 +147,8 @@
'libcef_dll/wrapper/cef_byte_read_handler.cc',
'libcef_dll/wrapper/cef_closure_task.cc',
'libcef_dll/wrapper/cef_message_router.cc',
'libcef_dll/wrapper/cef_message_router_utils.cc',
'libcef_dll/wrapper/cef_message_router_utils.h',
'libcef_dll/wrapper/cef_resource_manager.cc',
'libcef_dll/wrapper/cef_scoped_temp_dir.cc',
'libcef_dll/wrapper/cef_stream_resource_handler.cc',
@@ -218,6 +220,8 @@
'tests/shared/browser/util_win.h',
],
'cefclient_sources_browser': [
'tests/cefclient/browser/binary_transfer_test.cc',
'tests/cefclient/browser/binary_transfer_test.h',
'tests/cefclient/browser/binding_test.cc',
'tests/cefclient/browser/binding_test.h',
'tests/cefclient/browser/browser_window.cc',
@@ -309,6 +313,7 @@
'tests/cefclient/resources/dialogs.html',
'tests/cefclient/resources/draggable.html',
'tests/cefclient/resources/ipc_performance.html',
'tests/cefclient/resources/binary_transfer.html',
'tests/cefclient/resources/localstorage.html',
'tests/cefclient/resources/logo.png',
'tests/cefclient/resources/media_router.html',
@@ -496,6 +501,7 @@
'tests/ceftests/jsdialog_unittest.cc',
'tests/ceftests/life_span_unittest.cc',
'tests/ceftests/media_access_unittest.cc',
'tests/ceftests/message_router_binary_unittest.cc',
'tests/ceftests/message_router_harness_unittest.cc',
'tests/ceftests/message_router_multi_query_unittest.cc',
'tests/ceftests/message_router_single_query_unittest.cc',
@@ -603,6 +609,7 @@
'tests/ceftests/dom_unittest.cc',
'tests/ceftests/frame_unittest.cc',
'tests/ceftests/media_access_unittest.cc',
'tests/ceftests/message_router_binary_unittest.cc',
'tests/ceftests/message_router_harness_unittest.cc',
'tests/ceftests/message_router_multi_query_unittest.cc',
'tests/ceftests/message_router_single_query_unittest.cc',

View File

@@ -33,7 +33,7 @@
// by hand. See the translator.README.txt file in the tools directory for
// more information.
//
// $hash=db4fce1215cb4f69346ef2d048974ba34187b2b1$
// $hash=eed525e9abcbf8e8b959067e0056ca470c5210c7$
//
#ifndef CEF_INCLUDE_CAPI_CEF_BROWSER_CAPI_H_
@@ -932,6 +932,48 @@ typedef struct _cef_browser_host_t {
/// be called on the UI thread.
///
int(CEF_CALLBACK* is_audio_muted)(struct _cef_browser_host_t* self);
///
/// Returns true (1) if the renderer is currently in browser fullscreen. This
/// differs from window fullscreen in that browser fullscreen is entered using
/// the JavaScript Fullscreen API and modifies CSS attributes such as the
/// ::backdrop pseudo-element and :fullscreen pseudo-structure. This function
/// can only be called on the UI thread.
///
int(CEF_CALLBACK* is_fullscreen)(struct _cef_browser_host_t* self);
///
/// Requests the renderer to exit browser fullscreen. In most cases exiting
/// window fullscreen should also exit browser fullscreen. With the Alloy
/// runtime this function should be called in response to a user action such
/// as clicking the green traffic light button on MacOS
/// (cef_window_delegate_t::OnWindowFullscreenTransition callback) or pressing
/// the "ESC" key (cef_keyboard_handler_t::OnPreKeyEvent callback). With the
/// Chrome runtime these standard exit actions are handled internally but
/// new/additional user actions can use this function. Set |will_cause_resize|
/// to true (1) if exiting browser fullscreen will cause a view resize.
///
void(CEF_CALLBACK* exit_fullscreen)(struct _cef_browser_host_t* self,
int will_cause_resize);
///
/// Returns true (1) if a Chrome command is supported and enabled. Values for
/// |command_id| can be found in the cef_command_ids.h file. This function can
/// only be called on the UI thread. Only used with the Chrome runtime.
///
int(CEF_CALLBACK* can_execute_chrome_command)(
struct _cef_browser_host_t* self,
int command_id);
///
/// Execute a Chrome command. Values for |command_id| can be found in the
/// cef_command_ids.h file. |disposition| provides information about the
/// intended command target. Only used with the Chrome runtime.
///
void(CEF_CALLBACK* execute_chrome_command)(
struct _cef_browser_host_t* self,
int command_id,
cef_window_open_disposition_t disposition);
} cef_browser_host_t;
///

View File

@@ -33,7 +33,7 @@
// by hand. See the translator.README.txt file in the tools directory for
// more information.
//
// $hash=1c807597b96889f44a1e5199e860e8db4948b473$
// $hash=32a0c21a71aa7137fa9660b942f597705bc8b05e$
//
#ifndef CEF_INCLUDE_CAPI_CEF_LIFE_SPAN_HANDLER_CAPI_H_
@@ -100,6 +100,34 @@ typedef struct _cef_life_span_handler_t {
struct _cef_dictionary_value_t** extra_info,
int* no_javascript_access);
///
/// Called on the UI thread before a new DevTools popup browser is created.
/// The |browser| value represents the source of the popup request. Optionally
/// modify |windowInfo|, |client|, |settings| and |extra_info| values. The
/// |client|, |settings| and |extra_info| values will default to the source
/// browser's values. Any modifications to |windowInfo| will be ignored if the
/// parent browser is Views-hosted (wrapped in a cef_browser_view_t).
///
/// The |extra_info| parameter provides an opportunity to specify extra
/// information specific to the created popup browser that will be passed to
/// cef_render_process_handler_t::on_browser_created() in the render process.
/// The existing |extra_info| object, if any, will be read-only but may be
/// replaced with a new object.
///
/// Views-hosted source browsers will create Views-hosted DevTools popups
/// unless |use_default_window| is set to to true (1). DevTools popups can be
/// blocked by returning true (1) from cef_command_handler_t::OnChromeCommand
/// for IDC_DEV_TOOLS. Only used with the Chrome runtime.
///
void(CEF_CALLBACK* on_before_dev_tools_popup)(
struct _cef_life_span_handler_t* self,
struct _cef_browser_t* browser,
struct _cef_window_info_t* windowInfo,
struct _cef_client_t** client,
struct _cef_browser_settings_t* settings,
struct _cef_dictionary_value_t** extra_info,
int* use_default_window);
///
/// Called after a new browser is created. It is now safe to begin performing
/// actions with |browser|. cef_frame_handler_t callbacks related to initial

View File

@@ -33,7 +33,7 @@
// by hand. See the translator.README.txt file in the tools directory for
// more information.
//
// $hash=42de7c0e6f5ec529d9182fe4cbf2c1edfacd7392$
// $hash=865ca5bff4a0867d0c25cb41bd2aa808cf3fddbd$
//
#ifndef CEF_INCLUDE_CAPI_CEF_V8_CAPI_H_
@@ -679,6 +679,19 @@ typedef struct _cef_v8value_t {
///
int(CEF_CALLBACK* neuter_array_buffer)(struct _cef_v8value_t* self);
///
/// Returns the length (in bytes) of the ArrayBuffer.
///
size_t(CEF_CALLBACK* get_array_buffer_byte_length)(
struct _cef_v8value_t* self);
///
/// Returns a pointer to the beginning of the memory block for this
/// ArrayBuffer backing store. The returned pointer is valid as long as the
/// cef_v8value_t is alive.
///
void*(CEF_CALLBACK* get_array_buffer_data)(struct _cef_v8value_t* self);
///
/// Returns the function name.
///

View File

@@ -33,7 +33,7 @@
// by hand. See the translator.README.txt file in the tools directory for
// more information.
//
// $hash=1b8f7f620685c30b91c8fa656e1a01d182684ae6$
// $hash=7b8fee9d4a0530782ed62f5741820708f110e24e$
//
#ifndef CEF_INCLUDE_CAPI_CEF_VALUES_CAPI_H_
@@ -265,6 +265,12 @@ typedef struct _cef_binary_value_t {
struct _cef_binary_value_t*(CEF_CALLBACK* copy)(
struct _cef_binary_value_t* self);
///
/// Returns a pointer to the beginning of the memory block. The returned
/// pointer is valid as long as the cef_binary_value_t is alive.
///
const void*(CEF_CALLBACK* get_raw_data)(struct _cef_binary_value_t* self);
///
/// Returns the data size.
///

View File

@@ -33,7 +33,7 @@
// by hand. See the translator.README.txt file in the tools directory for
// more information.
//
// $hash=f72e94f6bd63b6ea623c4d3170b5ad4333c136d6$
// $hash=bc80e7f1e467a4e0943dcbf7ea6d08366817d5ca$
//
#ifndef CEF_INCLUDE_CAPI_VIEWS_CEF_BROWSER_VIEW_CAPI_H_
@@ -77,13 +77,19 @@ typedef struct _cef_browser_view_t {
struct _cef_browser_view_t* self);
///
/// Sets whether accelerators registered with cef_window_t::SetAccelerator are
/// triggered before or after the event is sent to the cef_browser_t. If
/// |prefer_accelerators| is true (1) then the matching accelerator will be
/// triggered immediately and the event will not be sent to the cef_browser_t.
/// If |prefer_accelerators| is false (0) then the matching accelerator will
/// only be triggered if the event is not handled by web content or by
/// cef_keyboard_handler_t. The default value is false (0).
/// Sets whether normal priority accelerators are first forwarded to the web
/// content (`keydown` event handler) or cef_keyboard_handler_t. Normal
/// priority accelerators can be registered via cef_window_t::SetAccelerator
/// (with |high_priority|=false (0)) or internally for standard accelerators
/// supported by the Chrome runtime. If |prefer_accelerators| is true (1) then
/// the matching accelerator will be triggered immediately (calling
/// cef_window_delegate_t::OnAccelerator or
/// cef_command_handler_t::OnChromeCommand respectively) and the event will
/// not be forwarded to the web content or cef_keyboard_handler_t first. If
/// |prefer_accelerators| is false (0) then the matching accelerator will only
/// be triggered if the event is not handled by web content (`keydown` event
/// handler that calls `event.preventDefault()`) or by cef_keyboard_handler_t.
/// The default value is false (0).
///
void(CEF_CALLBACK* set_prefer_accelerators)(struct _cef_browser_view_t* self,
int prefer_accelerators);

View File

@@ -33,7 +33,7 @@
// by hand. See the translator.README.txt file in the tools directory for
// more information.
//
// $hash=4b43fe0b493d860e8b28d7a6d892db49d1135b34$
// $hash=a48904fcd0f6be07e27839922d8feb07271ed2b5$
//
#ifndef CEF_INCLUDE_CAPI_VIEWS_CEF_WINDOW_CAPI_H_
@@ -332,16 +332,25 @@ typedef struct _cef_window_t {
///
/// Set the keyboard accelerator for the specified |command_id|. |key_code|
/// can be any virtual key or character value.
/// can be any virtual key or character value. Required modifier keys are
/// specified by |shift_pressed|, |ctrl_pressed| and/or |alt_pressed|.
/// cef_window_delegate_t::OnAccelerator will be called if the keyboard
/// combination is triggered while this window has focus.
///
/// The |high_priority| value will be considered if a child cef_browser_view_t
/// has focus when the keyboard combination is triggered. If |high_priority|
/// is true (1) then the key event will not be forwarded to the web content
/// (`keydown` event handler) or cef_keyboard_handler_t first. If
/// |high_priority| is false (0) then the behavior will depend on the
/// cef_browser_view_t::SetPreferAccelerators configuration.
///
void(CEF_CALLBACK* set_accelerator)(struct _cef_window_t* self,
int command_id,
int key_code,
int shift_pressed,
int ctrl_pressed,
int alt_pressed);
int alt_pressed,
int high_priority);
///
/// Remove the keyboard accelerator for the specified |command_id|.

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 "647a2df6b870951e70487997f30e75960d609632"
#define CEF_API_HASH_UNIVERSAL "ce9401699c6753553cba867b1f5c329f759d2c67"
#if defined(OS_WIN)
#define CEF_API_HASH_PLATFORM "4a22d727f3f1f625844191f0f5adf297a2f17fa7"
#define CEF_API_HASH_PLATFORM "e094f42b7a60d2c8c9bcb3db51907a3b42f51d04"
#elif defined(OS_MAC)
#define CEF_API_HASH_PLATFORM "84a450a85c81d6cb16dda55d7f07047264d1e205"
#define CEF_API_HASH_PLATFORM "6ce44bd7182aa7e9544f5ca33c310f2a096ab638"
#elif defined(OS_LINUX)
#define CEF_API_HASH_PLATFORM "b7cbd7d044e02cb1854184cc1d5d621605b8476b"
#define CEF_API_HASH_PLATFORM "8e9886cd490aefc89283d65f5f7d104a51e2d289"
#endif
#ifdef __cplusplus

View File

@@ -964,6 +964,48 @@ class CefBrowserHost : public virtual CefBaseRefCounted {
///
/*--cef()--*/
virtual bool IsAudioMuted() = 0;
///
/// Returns true if the renderer is currently in browser fullscreen. This
/// differs from window fullscreen in that browser fullscreen is entered using
/// the JavaScript Fullscreen API and modifies CSS attributes such as the
/// ::backdrop pseudo-element and :fullscreen pseudo-class. This method can
/// only be called on the UI thread.
///
/*--cef()--*/
virtual bool IsFullscreen() = 0;
///
/// Requests the renderer to exit browser fullscreen. In most cases exiting
/// window fullscreen should also exit browser fullscreen. With the Alloy
/// runtime this method should be called in response to a user action such as
/// clicking the green traffic light button on MacOS
/// (CefWindowDelegate::OnWindowFullscreenTransition callback) or pressing the
/// "ESC" key (CefKeyboardHandler::OnPreKeyEvent callback). With the Chrome
/// runtime these standard exit actions are handled internally but
/// new/additional user actions can use this method. Set |will_cause_resize|
/// to true if exiting browser fullscreen will cause a view resize.
///
/*--cef()--*/
virtual void ExitFullscreen(bool will_cause_resize) = 0;
///
/// Returns true if a Chrome command is supported and enabled. Values for
/// |command_id| can be found in the cef_command_ids.h file. This method can
/// only be called on the UI thread. Only used with the Chrome runtime.
///
/*--cef()--*/
virtual bool CanExecuteChromeCommand(int command_id) = 0;
///
/// Execute a Chrome command. Values for |command_id| can be found in the
/// cef_command_ids.h file. |disposition| provides information about the
/// intended command target. Only used with the Chrome runtime.
///
/*--cef()--*/
virtual void ExecuteChromeCommand(
int command_id,
cef_window_open_disposition_t disposition) = 0;
};
#endif // CEF_INCLUDE_CEF_BROWSER_H_

View File

@@ -94,6 +94,33 @@ class CefLifeSpanHandler : public virtual CefBaseRefCounted {
return false;
}
///
/// Called on the UI thread before a new DevTools popup browser is created.
/// The |browser| value represents the source of the popup request. Optionally
/// modify |windowInfo|, |client|, |settings| and |extra_info| values. The
/// |client|, |settings| and |extra_info| values will default to the source
/// browser's values. Any modifications to |windowInfo| will be ignored if the
/// parent browser is Views-hosted (wrapped in a CefBrowserView).
///
/// The |extra_info| parameter provides an opportunity to specify extra
/// information specific to the created popup browser that will be passed to
/// CefRenderProcessHandler::OnBrowserCreated() in the render process. The
/// existing |extra_info| object, if any, will be read-only but may be
/// replaced with a new object.
///
/// Views-hosted source browsers will create Views-hosted DevTools popups
/// unless |use_default_window| is set to to true. DevTools popups can be
/// blocked by returning true from CefCommandHandler::OnChromeCommand for
/// IDC_DEV_TOOLS. Only used with the Chrome runtime.
///
/*--cef()--*/
virtual void OnBeforeDevToolsPopup(CefRefPtr<CefBrowser> browser,
CefWindowInfo& windowInfo,
CefRefPtr<CefClient>& client,
CefBrowserSettings& settings,
CefRefPtr<CefDictionaryValue>& extra_info,
bool* use_default_window) {}
///
/// Called after a new browser is created. It is now safe to begin performing
/// actions with |browser|. CefFrameHandler callbacks related to initial main

View File

@@ -520,7 +520,7 @@ class CefV8Value : public virtual CefBaseRefCounted {
/// or CefV8Accessor callback, or in combination with calling Enter() and
/// Exit() on a stored CefV8Context reference.
///
/*--cef()--*/
/*--cef(optional_param=buffer)--*/
static CefRefPtr<CefV8Value> CreateArrayBuffer(
void* buffer,
size_t length,
@@ -866,6 +866,20 @@ class CefV8Value : public virtual CefBaseRefCounted {
/*--cef()--*/
virtual bool NeuterArrayBuffer() = 0;
///
/// Returns the length (in bytes) of the ArrayBuffer.
///
/*--cef()--*/
virtual size_t GetArrayBufferByteLength() = 0;
///
/// Returns a pointer to the beginning of the memory block for this
/// ArrayBuffer backing store. The returned pointer is valid as long as the
/// CefV8Value is alive.
///
/*--cef()--*/
virtual void* GetArrayBufferData() = 0;
// FUNCTION METHODS - These methods are only available on functions.
///

View File

@@ -278,6 +278,13 @@ class CefBinaryValue : public virtual CefBaseRefCounted {
/*--cef()--*/
virtual CefRefPtr<CefBinaryValue> Copy() = 0;
///
/// Returns a pointer to the beginning of the memory block.
/// The returned pointer is valid as long as the CefBinaryValue is alive.
///
/*--cef()--*/
virtual const void* GetRawData() = 0;
///
/// Returns the data size.
///

View File

@@ -353,7 +353,7 @@ struct CefStringTraitsUTF16 {
/// modifying CEF strings from multiple threads.
///
template <class traits>
class CefStringBase {
class CefStringBase final {
public:
typedef typename traits::char_type char_type;
typedef typename traits::struct_type struct_type;
@@ -442,7 +442,7 @@ class CefStringBase {
Attach(const_cast<struct_type*>(src), false);
}
virtual ~CefStringBase() { ClearAndFree(); }
~CefStringBase() { ClearAndFree(); }
/// The following methods are named for compatibility with the standard
/// library string template types.

View File

@@ -1004,52 +1004,52 @@ typedef enum {
/// renumbered.
///
typedef enum {
WOD_UNKNOWN,
CEF_WOD_UNKNOWN,
///
/// Current tab. This is the default in most cases.
///
WOD_CURRENT_TAB,
CEF_WOD_CURRENT_TAB,
///
/// Indicates that only one tab with the url should exist in the same window.
///
WOD_SINGLETON_TAB,
CEF_WOD_SINGLETON_TAB,
///
/// Shift key + Middle mouse button or meta/ctrl key while clicking.
///
WOD_NEW_FOREGROUND_TAB,
CEF_WOD_NEW_FOREGROUND_TAB,
///
/// Middle mouse button or meta/ctrl key while clicking.
///
WOD_NEW_BACKGROUND_TAB,
CEF_WOD_NEW_BACKGROUND_TAB,
///
/// New popup window.
///
WOD_NEW_POPUP,
CEF_WOD_NEW_POPUP,
///
/// Shift key while clicking.
///
WOD_NEW_WINDOW,
CEF_WOD_NEW_WINDOW,
///
/// Alt key while clicking.
///
WOD_SAVE_TO_DISK,
CEF_WOD_SAVE_TO_DISK,
///
/// New off-the-record (incognito) window.
///
WOD_OFF_THE_RECORD,
CEF_WOD_OFF_THE_RECORD,
///
/// Special case error condition from the renderer.
///
WOD_IGNORE_ACTION,
CEF_WOD_IGNORE_ACTION,
///
/// Activates an existing tab containing the url, rather than navigating.
@@ -1059,12 +1059,14 @@ typedef enum {
/// no session history; and behaves like CURRENT_TAB instead of
/// NEW_FOREGROUND_TAB when no existing tab is found.
///
WOD_SWITCH_TO_TAB,
CEF_WOD_SWITCH_TO_TAB,
///
/// Creates a new document picture-in-picture window showing a child WebView.
///
WOD_NEW_PICTURE_IN_PICTURE,
CEF_WOD_NEW_PICTURE_IN_PICTURE,
CEF_WOD_MAX_VALUE = CEF_WOD_NEW_PICTURE_IN_PICTURE,
} cef_window_open_disposition_t;
///

View File

@@ -92,13 +92,18 @@ class CefBrowserView : public CefView {
virtual CefRefPtr<CefView> GetChromeToolbar() = 0;
///
/// Sets whether accelerators registered with CefWindow::SetAccelerator are
/// triggered before or after the event is sent to the CefBrowser. If
/// |prefer_accelerators| is true then the matching accelerator will be
/// triggered immediately and the event will not be sent to the CefBrowser. If
/// |prefer_accelerators| is false then the matching accelerator will only be
/// triggered if the event is not handled by web content or by
/// CefKeyboardHandler. The default value is false.
/// Sets whether normal priority accelerators are first forwarded to the web
/// content (`keydown` event handler) or CefKeyboardHandler. Normal priority
/// accelerators can be registered via CefWindow::SetAccelerator (with
/// |high_priority|=false) or internally for standard accelerators supported
/// by the Chrome runtime. If |prefer_accelerators| is true then the matching
/// accelerator will be triggered immediately (calling
/// CefWindowDelegate::OnAccelerator or CefCommandHandler::OnChromeCommand
/// respectively) and the event will not be forwarded to the web content or
/// CefKeyboardHandler first. If |prefer_accelerators| is false then the
/// matching accelerator will only be triggered if the event is not handled by
/// web content (`keydown` event handler that calls `event.preventDefault()`)
/// or by CefKeyboardHandler. The default value is false.
///
/*--cef()--*/
virtual void SetPreferAccelerators(bool prefer_accelerators) = 0;

View File

@@ -344,16 +344,25 @@ class CefWindow : public CefPanel {
///
/// Set the keyboard accelerator for the specified |command_id|. |key_code|
/// can be any virtual key or character value.
/// can be any virtual key or character value. Required modifier keys are
/// specified by |shift_pressed|, |ctrl_pressed| and/or |alt_pressed|.
/// CefWindowDelegate::OnAccelerator will be called if the keyboard
/// combination is triggered while this window has focus.
///
/// The |high_priority| value will be considered if a child CefBrowserView has
/// focus when the keyboard combination is triggered. If |high_priority| is
/// true then the key event will not be forwarded to the web content
/// (`keydown` event handler) or CefKeyboardHandler first. If |high_priority|
/// is false then the behavior will depend on the
/// CefBrowserView::SetPreferAccelerators configuration.
///
/*--cef()--*/
virtual void SetAccelerator(int command_id,
int key_code,
bool shift_pressed,
bool ctrl_pressed,
bool alt_pressed) = 0;
bool alt_pressed,
bool high_priority) = 0;
///
/// Remove the keyboard accelerator for the specified |command_id|.

View File

@@ -219,6 +219,38 @@ struct CefMessageRouterConfig {
size_t message_size_threshold;
};
///
/// This class acts as a container for managing binary data. It retains
/// references to the underlying backing store, ensuring it is valid as long as
/// the CefBinaryBuffer exists. This allows efficient, zero-copy access to data
/// received from another process.
///
/// This class is not designed to be thread-safe, and it is the user's
/// responsibility to synchronize access from multiple threads to ensure data
/// integrity.
///
class CefBinaryBuffer : public CefBaseRefCounted {
public:
///
/// Returns the read-only pointer to the memory. Returns nullptr if
/// |GetSize()| returns zero. The returned pointer is only valid for the life
/// span of this object.
///
virtual const void* GetData() const = 0;
///
/// Returns the writable pointer to the memory. Returns nullptr if
/// |GetSize()| returns zero. The returned pointer is only valid for the life
/// span of this object.
///
virtual void* GetData() = 0;
///
/// Returns the size of the data.
///
virtual size_t GetSize() const = 0;
};
///
/// Implements the browser side of query routing. The methods of this class may
/// be called on any browser process thread unless otherwise indicated.
@@ -238,10 +270,17 @@ class CefMessageRouterBrowserSide
public:
///
/// Notify the associated JavaScript onSuccess callback that the query has
/// completed successfully with the specified |response|.
/// completed successfully with the specified string |response|.
///
virtual void Success(const CefString& response) = 0;
///
/// Notify the associated JavaScript onSuccess callback that the query has
/// completed successfully with binary data. A |data| pointer to the binary
/// data can be nullptr only if the |size| is 0.
///
virtual void Success(const void* data, size_t size) = 0;
///
/// Notify the associated JavaScript onFailure callback that the query has
/// failed with the specified |error_code| and |error_message|.
@@ -276,6 +315,25 @@ class CefMessageRouterBrowserSide
return false;
}
///
/// Executed when a new query is received. |query_id| uniquely identifies
/// the query for the life span of the router. Return true to handle the
/// query or false to propagate the query to other registered handlers, if
/// any. If no handlers return true from this method then the query will be
/// automatically canceled with an error code of -1 delivered to the
/// JavaScript onFailure callback. If this method returns true then a
/// Callback method must be executed either in this method or asynchronously
/// to complete the query.
///
virtual bool OnQuery(CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
int64_t query_id,
CefRefPtr<const CefBinaryBuffer> request,
bool persistent,
CefRefPtr<Callback> callback) {
return false;
}
///
/// Executed when a query has been canceled either explicitly using the
/// JavaScript cancel function or implicitly due to browser destruction,

View File

@@ -57,33 +57,6 @@ using content::KeyboardEventProcessingResult;
namespace {
class ShowDevToolsHelper {
public:
ShowDevToolsHelper(CefRefPtr<AlloyBrowserHostImpl> browser,
const CefWindowInfo& windowInfo,
CefRefPtr<CefClient> client,
const CefBrowserSettings& settings,
const CefPoint& inspect_element_at)
: browser_(browser),
window_info_(windowInfo),
client_(client),
settings_(settings),
inspect_element_at_(inspect_element_at) {}
CefRefPtr<AlloyBrowserHostImpl> browser_;
CefWindowInfo window_info_;
CefRefPtr<CefClient> client_;
CefBrowserSettings settings_;
CefPoint inspect_element_at_;
};
void ShowDevToolsWithHelper(ShowDevToolsHelper* helper) {
helper->browser_->ShowDevTools(helper->window_info_, helper->client_,
helper->settings_,
helper->inspect_element_at_);
delete helper;
}
static constexpr base::TimeDelta kRecentlyAudibleTimeout = base::Seconds(2);
} // namespace
@@ -358,22 +331,15 @@ void AlloyBrowserHostImpl::StopFinding(bool clearSelection) {
}
}
void AlloyBrowserHostImpl::ShowDevTools(const CefWindowInfo& windowInfo,
CefRefPtr<CefClient> client,
const CefBrowserSettings& settings,
const CefPoint& inspect_element_at) {
if (!CEF_CURRENTLY_ON_UIT()) {
ShowDevToolsHelper* helper = new ShowDevToolsHelper(
this, windowInfo, client, settings, inspect_element_at);
CEF_POST_TASK(CEF_UIT, base::BindOnce(ShowDevToolsWithHelper, helper));
return;
}
void AlloyBrowserHostImpl::ShowDevToolsOnUIThread(
std::unique_ptr<CefShowDevToolsParams> params) {
CEF_REQUIRE_UIT();
if (!EnsureDevToolsManager()) {
return;
}
devtools_manager_->ShowDevTools(windowInfo, client, settings,
inspect_element_at);
devtools_manager_->ShowDevTools(params->window_info_, params->client_,
params->settings_,
params->inspect_element_at_);
}
void AlloyBrowserHostImpl::CloseDevTools() {
@@ -438,6 +404,16 @@ bool AlloyBrowserHostImpl::IsBackgroundHost() {
return is_background_host_;
}
bool AlloyBrowserHostImpl::CanExecuteChromeCommand(int command_id) {
return false;
}
void AlloyBrowserHostImpl::ExecuteChromeCommand(
int command_id,
cef_window_open_disposition_t disposition) {
NOTIMPLEMENTED();
}
bool AlloyBrowserHostImpl::IsWindowRenderingDisabled() {
return IsWindowless();
}

View File

@@ -85,10 +85,6 @@ class AlloyBrowserHostImpl : public CefBrowserHostBase,
bool matchCase,
bool findNext) override;
void StopFinding(bool clearSelection) override;
void ShowDevTools(const CefWindowInfo& windowInfo,
CefRefPtr<CefClient> client,
const CefBrowserSettings& settings,
const CefPoint& inspect_element_at) override;
void CloseDevTools() override;
bool HasDevTools() override;
bool IsWindowRenderingDisabled() override;
@@ -127,6 +123,9 @@ class AlloyBrowserHostImpl : public CefBrowserHostBase,
const CefSize& max_size) override;
CefRefPtr<CefExtension> GetExtension() override;
bool IsBackgroundHost() override;
bool CanExecuteChromeCommand(int command_id) override;
void ExecuteChromeCommand(int command_id,
cef_window_open_disposition_t disposition) override;
// Returns true if windowless rendering is enabled.
bool IsWindowless() const override;
@@ -285,6 +284,10 @@ class AlloyBrowserHostImpl : public CefBrowserHostBase,
override;
void WebContentsDestroyed() override;
protected:
void ShowDevToolsOnUIThread(
std::unique_ptr<CefShowDevToolsParams> params) override;
private:
friend class CefBrowserPlatformDelegateAlloy;

View File

@@ -39,20 +39,15 @@ content::WebContents* CefBrowserPlatformDelegateAlloy::CreateWebContents(
REQUIRE_ALLOY_RUNTIME();
DCHECK(primary_);
// Get or create the request context and browser context.
CefRefPtr<CefRequestContextImpl> request_context_impl =
CefRequestContextImpl::GetOrCreateForRequestContext(
create_params.request_context);
CHECK(request_context_impl);
auto cef_browser_context = request_context_impl->GetBrowserContext();
CHECK(cef_browser_context);
auto browser_context = cef_browser_context->AsBrowserContext();
if (!create_params.request_context) {
// Using the global request context.
create_params.request_context = request_context_impl.get();
create_params.request_context = CefRequestContext::GetGlobalContext();
}
auto* browser_context =
CefRequestContextImpl::GetBrowserContext(create_params.request_context);
CHECK(browser_context);
scoped_refptr<content::SiteInstance> site_instance;
if (extensions::ExtensionsEnabled() && !create_params.url.empty()) {
GURL gurl = url_util::MakeGURL(create_params.url, /*fixup=*/true);

View File

@@ -505,6 +505,22 @@ void CefBrowserHostBase::PrintToPDF(const CefString& path,
print_util::PrintToPDF(web_contents, path, settings, callback);
}
void CefBrowserHostBase::ShowDevTools(const CefWindowInfo& windowInfo,
CefRefPtr<CefClient> client,
const CefBrowserSettings& settings,
const CefPoint& inspect_element_at) {
auto params = std::make_unique<CefShowDevToolsParams>(
windowInfo, client, settings, inspect_element_at);
if (!CEF_CURRENTLY_ON_UIT()) {
CEF_POST_TASK(CEF_UIT,
base::BindOnce(&CefBrowserHostBase::ShowDevToolsOnUIThread,
this, std::move(params)));
} else {
ShowDevToolsOnUIThread(std::move(params));
}
}
bool CefBrowserHostBase::SendDevToolsMessage(const void* message,
size_t message_size) {
if (!message || message_size == 0) {
@@ -633,6 +649,31 @@ void CefBrowserHostBase::NotifyMoveOrResizeStarted() {
#endif
}
bool CefBrowserHostBase::IsFullscreen() {
if (!CEF_CURRENTLY_ON_UIT()) {
DCHECK(false) << "called on invalid thread";
return false;
}
if (auto web_contents = GetWebContents()) {
return web_contents->IsFullscreen();
}
return false;
}
void CefBrowserHostBase::ExitFullscreen(bool will_cause_resize) {
if (!CEF_CURRENTLY_ON_UIT()) {
CEF_POST_TASK(CEF_UIT, base::BindOnce(&CefBrowserHostBase::ExitFullscreen,
this, will_cause_resize));
return;
}
auto web_contents = GetWebContents();
if (web_contents && web_contents->IsFullscreen()) {
web_contents->ExitFullscreen(will_cause_resize);
}
}
void CefBrowserHostBase::ReplaceMisspelling(const CefString& word) {
if (!CEF_CURRENTLY_ON_UIT()) {
CEF_POST_TASK(

View File

@@ -94,6 +94,23 @@ struct CefBrowserCreateParams {
extensions::mojom::ViewType::kInvalid;
};
// Parameters passed to ShowDevToolsOnUIThread().
struct CefShowDevToolsParams {
CefShowDevToolsParams(const CefWindowInfo& windowInfo,
CefRefPtr<CefClient> client,
const CefBrowserSettings& settings,
const CefPoint& inspect_element_at)
: window_info_(windowInfo),
client_(client),
settings_(settings),
inspect_element_at_(inspect_element_at) {}
CefWindowInfo window_info_;
CefRefPtr<CefClient> client_;
CefBrowserSettings settings_;
CefPoint inspect_element_at_;
};
// Base class for CefBrowserHost implementations. Includes functionality that is
// shared by the alloy and chrome runtimes. All methods are thread-safe unless
// otherwise indicated.
@@ -191,6 +208,10 @@ class CefBrowserHostBase : public CefBrowserHost,
void PrintToPDF(const CefString& path,
const CefPdfPrintSettings& settings,
CefRefPtr<CefPdfPrintCallback> callback) override;
void ShowDevTools(const CefWindowInfo& windowInfo,
CefRefPtr<CefClient> client,
const CefBrowserSettings& settings,
const CefPoint& inspect_element_at) override;
void ReplaceMisspelling(const CefString& word) override;
void AddWordToDictionary(const CefString& word) override;
void SendKeyEvent(const CefKeyEvent& event) override;
@@ -212,6 +233,8 @@ class CefBrowserHostBase : public CefBrowserHost,
bool current_only) override;
CefRefPtr<CefNavigationEntry> GetVisibleNavigationEntry() override;
void NotifyMoveOrResizeStarted() override;
bool IsFullscreen() override;
void ExitFullscreen(bool will_cause_resize) override;
// CefBrowser methods:
bool IsValid() override;
@@ -344,6 +367,10 @@ class CefBrowserHostBase : public CefBrowserHost,
// Called from LoadMainFrameURL to perform the actual navigation.
virtual bool Navigate(const content::OpenURLParams& params);
// Called from ShowDevTools to perform the actual show.
virtual void ShowDevToolsOnUIThread(
std::unique_ptr<CefShowDevToolsParams> params) = 0;
// Create the CefFileDialogManager if it doesn't already exist.
bool EnsureFileDialogManager();

View File

@@ -33,6 +33,16 @@ CefBrowserInfo::CefBrowserInfo(int browser_id,
is_windowless_(is_windowless),
extra_info_(extra_info) {
DCHECK_GT(browser_id, 0);
if (extra_info_ && !extra_info_->IsReadOnly()) {
// |extra_info_| should always be read-only to avoid accidental future
// modification. Take a copy instead of modifying the passed-in object for
// backwards compatibility.
extra_info_ = extra_info_->Copy(/*exclude_empty_children=*/false);
auto extra_info_impl =
static_cast<CefDictionaryValueImpl*>(extra_info_.get());
extra_info_impl->MarkReadOnly();
}
}
CefBrowserInfo::~CefBrowserInfo() {

View File

@@ -193,15 +193,8 @@ bool CefBrowserInfoManager::CanCreateWindow(
pending_popup->use_default_browser_creation = true;
}
// In most cases, Views-hosted browsers should create Views-hosted popups
// and native browsers should use default popup handling. With the Chrome
// runtime, we should additionally use default handling (a) when using an
// external parent and (b) when using default Browser creation.
create_params.popup_with_views_hosted_opener =
browser->HasView() &&
!browser->platform_delegate()->HasExternalParent() &&
!pending_popup->use_default_browser_creation;
create_params.popup_with_views_hosted_opener = ShouldCreateViewsHostedPopup(
browser, pending_popup->use_default_browser_creation);
create_params.settings = pending_popup->settings;
create_params.client = pending_popup->client;
create_params.extra_info = pending_popup->extra_info;
@@ -420,6 +413,19 @@ bool CefBrowserInfoManager::MaybeAllowNavigation(
return true;
}
// static
bool CefBrowserInfoManager::ShouldCreateViewsHostedPopup(
CefRefPtr<CefBrowserHostBase> opener,
bool use_default_browser_creation) {
// In most cases, Views-hosted browsers should create Views-hosted popups
// and native browsers should use default popup handling. With the Chrome
// runtime, we should additionally use default handling (a) when using an
// external parent and (b) when using default Browser creation.
return opener->HasView() &&
!opener->platform_delegate()->HasExternalParent() &&
!use_default_browser_creation;
}
CefBrowserInfoManager::BrowserInfoList
CefBrowserInfoManager::GetBrowserInfoList() {
base::AutoLock lock_scope(browser_info_lock_);

View File

@@ -143,6 +143,9 @@ class CefBrowserInfoManager : public content::RenderProcessHostObserver {
const content::OpenURLParams& params,
CefRefPtr<CefBrowserHostBase>& browser) const;
static bool ShouldCreateViewsHostedPopup(CefRefPtr<CefBrowserHostBase> opener,
bool use_default_browser_creation);
private:
// RenderProcessHostObserver methods:
void RenderProcessHostDestroyed(content::RenderProcessHost* host) override;

View File

@@ -16,6 +16,7 @@
#include "ui/base/window_open_disposition.h"
class Browser;
class Profile;
namespace cef {
@@ -40,6 +41,14 @@ class BrowserDelegate : public content::WebContentsDelegate {
~BrowserDelegate() override {}
// Optionally override Browser creation in
// DevToolsWindow::CreateDevToolsBrowser. The returned Browser, if any, will
// take ownership of |devtools_contents|.
virtual Browser* CreateDevToolsBrowser(
Profile* profile,
Browser* opener,
std::unique_ptr<content::WebContents>& devtools_contents) = 0;
// Optionally override chrome::AddWebContents behavior. This is most often
// called via Browser::AddNewContents for new popup browsers and provides an
// opportunity for CEF to create a new Browser instead of proceeding with

View File

@@ -12,6 +12,7 @@
#include "libcef/browser/browser_platform_delegate.h"
#include "libcef/browser/chrome/chrome_browser_host_impl.h"
#include "libcef/browser/chrome/views/chrome_browser_view.h"
#include "libcef/browser/chrome/views/chrome_child_window.h"
#include "libcef/browser/media_access_query.h"
#include "libcef/browser/request_context_impl.h"
#include "libcef/browser/views/browser_view_impl.h"
@@ -24,6 +25,8 @@
#include "chrome/browser/ui/browser_tabstrip.h"
#include "content/public/browser/global_routing_id.h"
#include "content/public/browser/keyboard_event_processing_result.h"
#include "content/public/browser/render_widget_host.h"
#include "content/public/browser/render_widget_host_view.h"
#include "content/public/common/input/native_web_keyboard_event.h"
using content::KeyboardEventProcessingResult;
@@ -36,7 +39,8 @@ ChromeBrowserDelegate::ChromeBrowserDelegate(
DCHECK(browser_);
if (opener) {
DCHECK(browser->is_type_picture_in_picture());
DCHECK(browser->is_type_picture_in_picture() ||
browser->is_type_devtools());
auto opener_host = ChromeBrowserHostImpl::GetBrowserForBrowser(opener);
DCHECK(opener_host);
if (opener_host) {
@@ -47,6 +51,134 @@ ChromeBrowserDelegate::ChromeBrowserDelegate(
ChromeBrowserDelegate::~ChromeBrowserDelegate() = default;
Browser* ChromeBrowserDelegate::CreateDevToolsBrowser(
Profile* profile,
Browser* opener,
std::unique_ptr<content::WebContents>& devtools_contents) {
// |opener| is the same value that will be passed to the ChromeBrowserDelegate
// constructor for the new popup Browser. It may be nullptr in certain rare
// situations (e.g. if DevTools is launched for a WebContents that is not a
// Browser Tab). In that case, the popup browser host will instead be created
// via SetAsDelegate.
auto opener_browser_host =
opener ? ChromeBrowserHostImpl::GetBrowserForBrowser(opener) : nullptr;
if (!opener_browser_host) {
return nullptr;
}
// We expect openers and popups to have the same Profile.
CHECK_EQ(
CefRequestContextImpl::GetProfile(opener_browser_host->request_context()),
profile);
//
// 1. Get configuration settings from the user and create the new platform
// delegate. Logical equivalent of CefBrowserInfoManager::CanCreateWindow()
// for normal popups.
//
auto opener_client = opener_browser_host->GetClient();
auto life_span_handler =
opener_client ? opener_client->GetLifeSpanHandler() : nullptr;
CefBrowserCreateParams create_params;
CefWindowInfo window_info;
// If |client| is empty, or if the user clears |client| in
// OnBeforeDevToolsPopup, we'll use the result of GetDefaultClient() later on
// in CreateBrowserHost().
if (pending_show_devtools_params_) {
// Start with the params passed to CefBrowserHost::ShowDevTools().
create_params.client = pending_show_devtools_params_->client_;
create_params.settings = pending_show_devtools_params_->settings_;
window_info = pending_show_devtools_params_->window_info_;
// Pending params are only used a single time.
pending_show_devtools_params_.reset();
} else {
// Start with the same client and settings as the opener.
create_params.client = opener_client;
create_params.settings = opener_browser_host->settings();
#if BUILDFLAG(IS_WIN)
window_info.SetAsPopup(nullptr, CefString());
#endif
}
// Start with the same extra info as the opener, for consistency with
// current Alloy runtime behavior (see CefDevToolsFrontend::Show). This
// value, if non-empty, will be read-only.
create_params.extra_info = opener_browser_host->browser_info()->extra_info();
DCHECK(!create_params.extra_info || create_params.extra_info->IsReadOnly());
// Use default (non-Views-hosted) window if OnBeforeDevToolsPopup is
// unhandled.
bool use_default_window = !life_span_handler;
if (life_span_handler) {
life_span_handler->OnBeforeDevToolsPopup(
opener_browser_host.get(), window_info, create_params.client,
create_params.settings, create_params.extra_info, &use_default_window);
}
if (opener_browser_host->platform_delegate()->HasExternalParent()) {
// A parent window handle for DevTools creation is only supported if the
// opener also has an external parent.
create_params.MaybeSetWindowInfo(window_info);
} else if (chrome_child_window::HasParentHandle(window_info)) {
LOG(ERROR) << "Parent window handle not supported for this DevTools window";
}
create_params.popup_with_views_hosted_opener =
CefBrowserInfoManager::ShouldCreateViewsHostedPopup(opener_browser_host,
use_default_window);
auto platform_delegate = CefBrowserPlatformDelegate::Create(create_params);
CHECK(platform_delegate);
//
// 2. Create the new browser host. Logical equivalent of WebContentsCreated()
// for normal popups.
//
// Create a new browser host that remains alive until the associated
// WebContents is destroyed. Associate that browser host with the WebContents
// and execute initial client callbacks. Deliver required information to the
// renderer process.
auto browser_host = CreateBrowserHostForPopup(
devtools_contents.get(), create_params.settings, create_params.client,
create_params.extra_info, std::move(platform_delegate),
/*is_devtools_popup=*/true, opener_browser_host);
//
// 3. Create the new Browser. Logical equivalent of AddWebContents() for
// normal popups.
//
// Use Browser creation params specific to DevTools popups.
auto chrome_params = Browser::CreateParams::CreateForDevTools(profile);
// Pass |opener| to the ChromeBrowserDelegate constructor for the new popup
// Browser.
chrome_params.opener = opener;
// Create a new Browser and give it ownership of the new WebContents.
// Results in a call to SetAsDelegate to associate the Browser with the
// browser host.
browser_host->AddNewContents(std::move(devtools_contents),
std::move(chrome_params));
// Give the opener browser a reference to the new DevTools browser. Do this
// last because don't want the client to attempt access to the DevTools
// browser via opener browser methods (e.g. ShowDevTools, CloseDevTools, etc)
// while creation is still in progress.
opener_browser_host->SetDevToolsBrowserHost(browser_host->GetWeakPtr());
auto browser = browser_host->browser();
CHECK(browser);
return browser;
}
std::unique_ptr<content::WebContents> ChromeBrowserDelegate::AddWebContents(
std::unique_ptr<content::WebContents> new_contents) {
if (CefBrowserInfoManager::GetInstance()->AddWebContents(
@@ -56,7 +188,9 @@ std::unique_ptr<content::WebContents> ChromeBrowserDelegate::AddWebContents(
ChromeBrowserHostImpl::GetBrowserForContents(new_contents.get());
if (new_browser) {
// Create a new Browser and give it ownership of the new WebContents.
new_browser->AddNewContents(std::move(new_contents));
// Results in a call to SetAsDelegate to associate the Browser with the
// browser host.
new_browser->AddNewContents(std::move(new_contents), std::nullopt);
} else {
LOG(ERROR) << "No host found for chrome popup browser";
}
@@ -90,19 +224,26 @@ void ChromeBrowserDelegate::SetAsDelegate(content::WebContents* web_contents,
return;
}
const bool is_devtools_popup = browser_->is_type_devtools();
// We should never reach here for DevTools popups that have an opener, as
// CreateDevToolsBrowser should have already created the browser host.
DCHECK(!is_devtools_popup || !opener_host_);
auto platform_delegate = CefBrowserPlatformDelegate::Create(create_params_);
CHECK(platform_delegate);
auto browser_info = CefBrowserInfoManager::GetInstance()->CreateBrowserInfo(
/*is_popup=*/false, /*is_windowless=*/false, create_params_.extra_info);
is_devtools_popup, /*is_windowless=*/false, create_params_.extra_info);
auto request_context_impl =
CefRequestContextImpl::GetOrCreateForRequestContext(
create_params_.request_context);
CreateBrowser(web_contents, create_params_.settings, create_params_.client,
std::move(platform_delegate), browser_info, /*opener=*/nullptr,
request_context_impl);
CreateBrowserHost(web_contents, create_params_.settings,
create_params_.client, std::move(platform_delegate),
browser_info, is_devtools_popup, /*opener=*/nullptr,
request_context_impl);
}
bool ChromeBrowserDelegate::ShowStatusBubble(bool show_by_default) {
@@ -123,6 +264,11 @@ bool ChromeBrowserDelegate::ShowStatusBubble(bool show_by_default) {
bool ChromeBrowserDelegate::HandleCommand(int command_id,
WindowOpenDisposition disposition) {
// Verify that our enum matches Chromium's values.
static_assert(static_cast<int>(CEF_WOD_MAX_VALUE) ==
static_cast<int>(WindowOpenDisposition::MAX_VALUE),
"enum mismatch");
if (auto browser = ChromeBrowserHostImpl::GetBrowserForBrowser(browser_)) {
if (auto client = browser->GetClient()) {
if (auto handler = client->GetCommandHandler()) {
@@ -299,19 +445,13 @@ void ChromeBrowserDelegate::WebContentsCreated(
return;
}
auto browser_info =
CefBrowserInfoManager::GetInstance()->CreatePopupBrowserInfo(
new_contents, /*is_windowless=*/false, extra_info);
CHECK(browser_info->is_popup());
// Popups must share the same RequestContext as the parent.
auto request_context_impl = opener->request_context();
CHECK(request_context_impl);
// We don't officially own |new_contents| until AddNewContents() is called.
// However, we need to install observers/delegates here.
CreateBrowser(new_contents, settings, client, std::move(platform_delegate),
browser_info, opener, request_context_impl);
// Create a new browser host that remains alive until the associated
// WebContents is destroyed. Associate that browser host with the WebContents
// and execute initial client callbacks. Deliver required information to the
// renderer process.
CreateBrowserHostForPopup(new_contents, settings, client, extra_info,
std::move(platform_delegate),
/*is_devtools_popup=*/false, opener);
}
content::WebContents* ChromeBrowserDelegate::OpenURLFromTab(
@@ -379,6 +519,14 @@ void ChromeBrowserDelegate::ExitFullscreenModeForTab(
if (auto delegate = GetDelegateForWebContents(web_contents)) {
delegate->ExitFullscreenModeForTab(web_contents);
}
// Workaround for https://crbug.com/1500371. Ensure WebContents exits
// fullscreen state by explicitly sending a resize message.
if (auto* rwhv = web_contents->GetRenderWidgetHostView()) {
if (auto* render_widget_host = rwhv->GetRenderWidgetHost()) {
render_widget_host->SynchronizeVisualProperties();
}
}
}
void ChromeBrowserDelegate::CanDownload(
@@ -413,12 +561,19 @@ bool ChromeBrowserDelegate::HandleKeyboardEvent(
return false;
}
void ChromeBrowserDelegate::CreateBrowser(
void ChromeBrowserDelegate::SetPendingShowDevToolsParams(
std::unique_ptr<CefShowDevToolsParams> params) {
DCHECK(!pending_show_devtools_params_);
pending_show_devtools_params_ = std::move(params);
}
CefRefPtr<ChromeBrowserHostImpl> ChromeBrowserDelegate::CreateBrowserHost(
content::WebContents* web_contents,
CefBrowserSettings settings,
const CefBrowserSettings& settings,
CefRefPtr<CefClient> client,
std::unique_ptr<CefBrowserPlatformDelegate> platform_delegate,
scoped_refptr<CefBrowserInfo> browser_info,
bool is_devtools_popup,
CefRefPtr<ChromeBrowserHostImpl> opener,
CefRefPtr<CefRequestContextImpl> request_context_impl) {
CEF_REQUIRE_UIT();
@@ -454,12 +609,40 @@ void ChromeBrowserDelegate::CreateBrowser(
CefRefPtr<ChromeBrowserHostImpl> browser_host =
new ChromeBrowserHostImpl(settings, client, std::move(platform_delegate),
browser_info, request_context_impl);
browser_host->Attach(web_contents, opener);
browser_host->Attach(web_contents, is_devtools_popup, opener);
// The Chrome browser for a popup won't be created until AddNewContents().
// The Chrome browser for a normal popup won't be created until
// AddNewContents().
if (!opener) {
browser_host->SetBrowser(browser_);
}
return browser_host;
}
CefRefPtr<ChromeBrowserHostImpl>
ChromeBrowserDelegate::CreateBrowserHostForPopup(
content::WebContents* web_contents,
const CefBrowserSettings& settings,
CefRefPtr<CefClient> client,
CefRefPtr<CefDictionaryValue> extra_info,
std::unique_ptr<CefBrowserPlatformDelegate> platform_delegate,
bool is_devtools_popup,
CefRefPtr<ChromeBrowserHostImpl> opener) {
auto browser_info =
CefBrowserInfoManager::GetInstance()->CreatePopupBrowserInfo(
web_contents, /*is_windowless=*/false, extra_info);
CHECK(browser_info->is_popup());
// Popups must share the same RequestContext as the parent.
auto request_context_impl = opener->request_context();
CHECK(request_context_impl);
// We don't officially own |web_contents| until AddNewContents() is called.
// However, we need to install observers/delegates here.
return CreateBrowserHost(web_contents, settings, client,
std::move(platform_delegate), browser_info,
is_devtools_popup, opener, request_context_impl);
}
CefBrowserContentsDelegate* ChromeBrowserDelegate::GetDelegateForWebContents(

View File

@@ -39,6 +39,9 @@ class ChromeBrowserHostImpl;
// but the Browser object will change when the tab is dragged between windows.
class ChromeBrowserDelegate : public cef::BrowserDelegate {
public:
// The |create_params| and |opener| values are specified via the
// Browser::CreateParams passed to Browser::Create. |opener| will only be
// specified for certain special Browser types.
ChromeBrowserDelegate(Browser* browser,
const CefBrowserCreateParams& create_params,
const Browser* opener);
@@ -49,6 +52,10 @@ class ChromeBrowserDelegate : public cef::BrowserDelegate {
~ChromeBrowserDelegate() override;
// cef::BrowserDelegate methods:
Browser* CreateDevToolsBrowser(
Profile* profile,
Browser* opener,
std::unique_ptr<content::WebContents>& devtools_contents) override;
std::unique_ptr<content::WebContents> AddWebContents(
std::unique_ptr<content::WebContents> new_contents) override;
void OnWebContentsCreated(content::WebContents* new_contents) override;
@@ -104,18 +111,31 @@ class ChromeBrowserDelegate : public cef::BrowserDelegate {
content::WebContents* source,
const content::NativeWebKeyboardEvent& event) override;
void SetPendingShowDevToolsParams(
std::unique_ptr<CefShowDevToolsParams> params);
Browser* browser() const { return browser_; }
private:
void CreateBrowser(
CefRefPtr<ChromeBrowserHostImpl> CreateBrowserHost(
content::WebContents* web_contents,
CefBrowserSettings settings,
const CefBrowserSettings& settings,
CefRefPtr<CefClient> client,
std::unique_ptr<CefBrowserPlatformDelegate> platform_delegate,
scoped_refptr<CefBrowserInfo> browser_info,
bool is_devtools_popup,
CefRefPtr<ChromeBrowserHostImpl> opener,
CefRefPtr<CefRequestContextImpl> request_context_impl);
CefRefPtr<ChromeBrowserHostImpl> CreateBrowserHostForPopup(
content::WebContents* web_contents,
const CefBrowserSettings& settings,
CefRefPtr<CefClient> client,
CefRefPtr<CefDictionaryValue> extra_info,
std::unique_ptr<CefBrowserPlatformDelegate> platform_delegate,
bool is_devtools_popup,
CefRefPtr<ChromeBrowserHostImpl> opener);
CefBrowserContentsDelegate* GetDelegateForWebContents(
content::WebContents* web_contents);
@@ -130,6 +150,8 @@ class ChromeBrowserDelegate : public cef::BrowserDelegate {
absl::optional<bool> show_status_bubble_;
absl::optional<SkRegion> draggable_region_;
mutable absl::optional<bool> frameless_pip_;
std::unique_ptr<CefShowDevToolsParams> pending_show_devtools_params_;
};
#endif // CEF_LIBCEF_BROWSER_CHROME_CHROME_BROWSER_DELEGATE_H_

View File

@@ -6,6 +6,7 @@
#include "libcef/browser/browser_platform_delegate.h"
#include "libcef/browser/chrome/browser_platform_delegate_chrome.h"
#include "libcef/browser/chrome/chrome_browser_delegate.h"
#include "libcef/browser/thread_util.h"
#include "libcef/browser/views/browser_view_impl.h"
#include "libcef/common/net/url_util.h"
@@ -13,8 +14,8 @@
#include "base/logging.h"
#include "base/notreached.h"
#include "chrome/browser/devtools/devtools_window.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/browser_commands.h"
#include "chrome/browser/ui/browser_navigator.h"
#include "chrome/browser/ui/browser_tabstrip.h"
@@ -28,7 +29,7 @@
// static
CefRefPtr<ChromeBrowserHostImpl> ChromeBrowserHostImpl::Create(
const CefBrowserCreateParams& params) {
auto browser = CreateBrowser(params);
auto browser = CreateBrowser(params, std::nullopt);
GURL url = url_util::MakeGURL(params.url, /*fixup=*/true);
if (url.is_empty()) {
@@ -99,7 +100,8 @@ CefRefPtr<ChromeBrowserHostImpl> ChromeBrowserHostImpl::GetBrowserForBrowser(
ChromeBrowserHostImpl::~ChromeBrowserHostImpl() = default;
void ChromeBrowserHostImpl::AddNewContents(
std::unique_ptr<content::WebContents> contents) {
std::unique_ptr<content::WebContents> contents,
std::optional<Browser::CreateParams> browser_create_params) {
DCHECK(contents);
DCHECK(!browser_);
@@ -111,7 +113,7 @@ void ChromeBrowserHostImpl::AddNewContents(
params.browser_view = GetBrowserView();
// Create the new Browser representation.
auto browser = CreateBrowser(params);
auto browser = CreateBrowser(params, std::move(browser_create_params));
// Add the WebContents to the Browser.
browser->tab_strip_model()->AddWebContents(
@@ -199,20 +201,66 @@ void ChromeBrowserHostImpl::StopFinding(bool clearSelection) {
NOTIMPLEMENTED();
}
void ChromeBrowserHostImpl::ShowDevTools(const CefWindowInfo& windowInfo,
CefRefPtr<CefClient> client,
const CefBrowserSettings& settings,
const CefPoint& inspect_element_at) {
NOTIMPLEMENTED();
void ChromeBrowserHostImpl::ShowDevToolsOnUIThread(
std::unique_ptr<CefShowDevToolsParams> params) {
CEF_REQUIRE_UIT();
if (!browser_) {
return;
}
auto* web_contents = GetWebContents();
if (!web_contents) {
return;
}
auto* profile = CefRequestContextImpl::GetProfile(request_context());
if (!DevToolsWindow::AllowDevToolsFor(profile, web_contents)) {
LOG(WARNING) << "DevTools is not allowed for this browser";
return;
}
auto inspect_element_at = params->inspect_element_at_;
if (!devtools_browser_host_) {
// Configure parameters for ChromeBrowserDelegate::CreateDevToolsBrowser
// which will be called indirectly to create the DevTools window.
auto chrome_browser_delegate =
static_cast<ChromeBrowserDelegate*>(browser_->cef_delegate());
chrome_browser_delegate->SetPendingShowDevToolsParams(std::move(params));
}
// Focus the existing DevTools window or create a new one.
if (!inspect_element_at.IsEmpty()) {
DevToolsWindow::InspectElement(web_contents->GetPrimaryMainFrame(),
inspect_element_at.x, inspect_element_at.y);
} else {
DevToolsWindow::OpenDevToolsWindow(web_contents, profile);
}
// The DevTools browser host should now exist.
DCHECK(devtools_browser_host_);
}
void ChromeBrowserHostImpl::CloseDevTools() {
NOTIMPLEMENTED();
if (!CEF_CURRENTLY_ON_UIT()) {
CEF_POST_TASK(CEF_UIT,
base::BindOnce(&ChromeBrowserHostImpl::CloseDevTools, this));
return;
}
if (devtools_browser_host_) {
devtools_browser_host_->TryCloseBrowser();
}
}
bool ChromeBrowserHostImpl::HasDevTools() {
NOTIMPLEMENTED();
return false;
if (!CEF_CURRENTLY_ON_UIT()) {
DCHECK(false) << "called on invalid thread";
return false;
}
return !!devtools_browser_host_;
}
bool ChromeBrowserHostImpl::IsWindowRenderingDisabled() {
@@ -332,6 +380,36 @@ bool ChromeBrowserHostImpl::IsBackgroundHost() {
return false;
}
bool ChromeBrowserHostImpl::CanExecuteChromeCommand(int command_id) {
// Verify that this method is being called on the UI thread.
if (!CEF_CURRENTLY_ON_UIT()) {
DCHECK(false) << "called on invalid thread";
return false;
}
if (browser_) {
return chrome::SupportsCommand(browser_, command_id) &&
chrome::IsCommandEnabled(browser_, command_id);
}
return false;
}
void ChromeBrowserHostImpl::ExecuteChromeCommand(
int command_id,
cef_window_open_disposition_t disposition) {
if (!CEF_CURRENTLY_ON_UIT()) {
CEF_POST_TASK(CEF_UIT,
base::BindOnce(&ChromeBrowserHostImpl::ExecuteChromeCommand,
this, command_id, disposition));
return;
}
if (browser_) {
chrome::ExecuteCommandWithDisposition(
browser_, command_id, static_cast<WindowOpenDisposition>(disposition));
}
}
ChromeBrowserView* ChromeBrowserHostImpl::chrome_browser_view() const {
if (browser_ && is_views_hosted_) {
return static_cast<ChromeBrowserView*>(browser_->window());
@@ -389,19 +467,16 @@ ChromeBrowserHostImpl::ChromeBrowserHostImpl(
// static
Browser* ChromeBrowserHostImpl::CreateBrowser(
const CefBrowserCreateParams& params) {
// Get or create the request context and profile.
CefRefPtr<CefRequestContextImpl> request_context_impl =
CefRequestContextImpl::GetOrCreateForRequestContext(
params.request_context);
CHECK(request_context_impl);
auto cef_browser_context = request_context_impl->GetBrowserContext();
CHECK(cef_browser_context);
auto profile = cef_browser_context->AsProfile();
CHECK(profile);
Browser::CreateParams chrome_params =
Browser::CreateParams(profile, /*user_gesture=*/false);
const CefBrowserCreateParams& params,
std::optional<Browser::CreateParams> browser_create_params) {
Browser::CreateParams chrome_params = [&params, &browser_create_params]() {
if (!browser_create_params.has_value()) {
auto* profile = CefRequestContextImpl::GetProfile(params.request_context);
return Browser::CreateParams(profile, /*user_gesture=*/false);
} else {
return std::move(*browser_create_params);
}
}();
// Pass |params| to cef::BrowserDelegate::Create from the Browser constructor.
chrome_params.cef_params = base::MakeRefCounted<DelegateCreateParams>(params);
@@ -412,10 +487,12 @@ Browser* ChromeBrowserHostImpl::CreateBrowser(
// documentation.
ChromeBrowserView* chrome_browser_view = nullptr;
if (params.browser_view) {
// Don't show most controls.
chrome_params.type = Browser::TYPE_POPUP;
// Don't show title bar or address.
chrome_params.trusted_source = true;
if (chrome_params.type == Browser::TYPE_NORMAL) {
// Don't show most controls.
chrome_params.type = Browser::TYPE_POPUP;
// Don't show title bar or address.
chrome_params.trusted_source = true;
}
auto view_impl =
static_cast<CefBrowserViewImpl*>(params.browser_view.get());
@@ -456,6 +533,7 @@ Browser* ChromeBrowserHostImpl::CreateBrowser(
}
void ChromeBrowserHostImpl::Attach(content::WebContents* web_contents,
bool is_devtools_popup,
CefRefPtr<ChromeBrowserHostImpl> opener) {
DCHECK(web_contents);
@@ -464,7 +542,7 @@ void ChromeBrowserHostImpl::Attach(content::WebContents* web_contents,
// new browser's platform delegate.
opener->platform_delegate_->PopupWebContentsCreated(
settings_, client_, web_contents, platform_delegate_.get(),
/*is_devtools_popup=*/false);
is_devtools_popup);
}
platform_delegate_->WebContentsCreated(web_contents,
@@ -480,7 +558,7 @@ void ChromeBrowserHostImpl::Attach(content::WebContents* web_contents,
// Notify that the browser has been created. These must be delivered in the
// expected order.
if (opener && opener->platform_delegate_) {
if (opener) {
// 1. Notify the opener browser's platform delegate. With Views this will
// result in a call to CefBrowserViewDelegate::OnPopupBrowserViewCreated().
// We want to call this method first because the implementation will often
@@ -488,9 +566,7 @@ void ChromeBrowserHostImpl::Attach(content::WebContents* web_contents,
// CefBrowserHost::GetWindowHandle() will return kNullWindowHandle in
// OnAfterCreated(), which breaks client expectations (e.g. clients expect
// everything about the browser to be valid at that time).
opener->platform_delegate_->PopupBrowserCreated(
this,
/*is_devtools_popup=*/false);
opener->platform_delegate_->PopupBrowserCreated(this, is_devtools_popup);
}
// 2. Notify the browser's LifeSpanHandler. This must always be the first
@@ -509,14 +585,27 @@ void ChromeBrowserHostImpl::Attach(content::WebContents* web_contents,
void ChromeBrowserHostImpl::SetBrowser(Browser* browser) {
CEF_REQUIRE_UIT();
if (browser == browser_) {
return;
}
browser_ = browser;
static_cast<CefBrowserPlatformDelegateChrome*>(platform_delegate_.get())
->set_chrome_browser(browser);
if (browser_) {
host_window_handle_ = platform_delegate_->GetHostWindowHandle();
} else {
host_window_handle_ = kNullWindowHandle;
}
}
void ChromeBrowserHostImpl::SetDevToolsBrowserHost(
base::WeakPtr<ChromeBrowserHostImpl> devtools_browser_host) {
CEF_REQUIRE_UIT();
DCHECK(!devtools_browser_host_);
devtools_browser_host_ = devtools_browser_host;
}
void ChromeBrowserHostImpl::WindowDestroyed() {
CEF_REQUIRE_UIT();
if (auto view = chrome_browser_view()) {

View File

@@ -12,8 +12,8 @@
#include "libcef/browser/chrome/browser_delegate.h"
#include "base/memory/weak_ptr.h"
#include "chrome/browser/ui/browser.h"
class Browser;
class ChromeBrowserDelegate;
class ChromeBrowserView;
@@ -72,10 +72,6 @@ class ChromeBrowserHostImpl : public CefBrowserHostBase {
bool matchCase,
bool findNext) override;
void StopFinding(bool clearSelection) override;
void ShowDevTools(const CefWindowInfo& windowInfo,
CefRefPtr<CefClient> client,
const CefBrowserSettings& settings,
const CefPoint& inspect_element_at) override;
void CloseDevTools() override;
bool HasDevTools() override;
bool IsWindowRenderingDisabled() override;
@@ -114,6 +110,9 @@ class ChromeBrowserHostImpl : public CefBrowserHostBase {
const CefSize& max_size) override;
CefRefPtr<CefExtension> GetExtension() override;
bool IsBackgroundHost() override;
bool CanExecuteChromeCommand(int command_id) override;
void ExecuteChromeCommand(int command_id,
cef_window_open_disposition_t disposition) override;
Browser* browser() const { return browser_; }
@@ -126,6 +125,8 @@ class ChromeBrowserHostImpl : public CefBrowserHostBase {
protected:
bool Navigate(const content::OpenURLParams& params) override;
void ShowDevToolsOnUIThread(
std::unique_ptr<CefShowDevToolsParams> params) override;
private:
friend class ChromeBrowserDelegate;
@@ -138,22 +139,32 @@ class ChromeBrowserHostImpl : public CefBrowserHostBase {
CefRefPtr<CefRequestContextImpl> request_context);
// Create a new Browser without initializing the WebContents.
static Browser* CreateBrowser(const CefBrowserCreateParams& params);
// |browser_create_params| may be empty for default Browser creation behavior.
static Browser* CreateBrowser(
const CefBrowserCreateParams& params,
std::optional<Browser::CreateParams> browser_create_params);
// Called from ChromeBrowserDelegate::CreateBrowser when this object is first
// created. Must be called on the UI thread.
void Attach(content::WebContents* web_contents,
bool is_devtools_popup,
CefRefPtr<ChromeBrowserHostImpl> opener);
// Called from ChromeBrowserDelegate::AddNewContents to take ownership of a
// popup WebContents.
void AddNewContents(std::unique_ptr<content::WebContents> contents);
// popup WebContents. |browser_create_params| may be empty for default Browser
// creation behavior.
void AddNewContents(
std::unique_ptr<content::WebContents> contents,
std::optional<Browser::CreateParams> browser_create_params);
// Called when this object changes Browser ownership (e.g. initially created,
// dragging between windows, etc). The old Browser, if any, will be cleared
// before the new Browser is added. Must be called on the UI thread.
void SetBrowser(Browser* browser);
void SetDevToolsBrowserHost(
base::WeakPtr<ChromeBrowserHostImpl> devtools_browser_host);
// CefBrowserHostBase methods:
void WindowDestroyed() override;
bool WillBeDestroyed() const override;
@@ -168,6 +179,8 @@ class ChromeBrowserHostImpl : public CefBrowserHostBase {
Browser* browser_ = nullptr;
CefWindowHandle host_window_handle_ = kNullWindowHandle;
base::WeakPtr<ChromeBrowserHostImpl> devtools_browser_host_;
base::WeakPtrFactory<ChromeBrowserHostImpl> weak_ptr_factory_{this};
};

View File

@@ -4,6 +4,8 @@
#include "libcef/browser/chrome/views/chrome_browser_frame.h"
#include "libcef/browser/chrome/chrome_browser_host_impl.h"
#include "chrome/browser/themes/theme_service.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/browser_commands.h"
@@ -57,3 +59,24 @@ ChromeBrowserFrame::CreateNonClientFrameView() {
// Bypass the BrowserFrame implementation.
return views::Widget::CreateNonClientFrameView();
}
void ChromeBrowserFrame::Activate() {
if (browser_view_ && browser_view_->browser() &&
browser_view_->browser()->is_type_devtools()) {
if (auto browser_host = ChromeBrowserHostImpl::GetBrowserForBrowser(
browser_view_->browser())) {
if (browser_host->platform_delegate()->HasExternalParent()) {
// Handle activation of DevTools with external parent via the platform
// delegate. On Windows the default platform implementation
// (HWNDMessageHandler::Activate) will call SetForegroundWindow but that
// doesn't seem to work for DevTools windows when activated via the
// right-click context menu.
browser_host->SetFocus(true);
return;
}
}
}
// Proceed with default handling.
BrowserFrame::Activate();
}

View File

@@ -103,6 +103,7 @@ class ChromeBrowserFrame : public BrowserFrame {
views::internal::RootView* CreateRootView() override;
std::unique_ptr<views::NonClientFrameView> CreateNonClientFrameView()
override;
void Activate() override;
BrowserView* browser_view() const { return browser_view_; }

View File

@@ -126,8 +126,6 @@ class ChildBrowserViewDelegate : public CefBrowserViewDelegate {
bool OnPopupBrowserViewCreated(CefRefPtr<CefBrowserView> browser_view,
CefRefPtr<CefBrowserView> popup_browser_view,
bool is_devtools) override {
DCHECK(!is_devtools);
auto new_browser = static_cast<CefBrowserHostBase*>(
popup_browser_view->GetBrowser().get());
auto new_platform_delegate = new_browser->platform_delegate();

View File

@@ -202,14 +202,8 @@ class CefBrowserURLRequest::Context
scoped_refptr<base::SequencedTaskRunner> task_runner) {
CEF_REQUIRE_UIT();
// Get or create the request context and browser context.
CefRefPtr<CefRequestContextImpl> request_context_impl =
CefRequestContextImpl::GetOrCreateForRequestContext(request_context);
CHECK(request_context_impl);
CefBrowserContext* cef_browser_context =
request_context_impl->GetBrowserContext();
CHECK(cef_browser_context);
auto browser_context = cef_browser_context->AsBrowserContext();
auto* browser_context =
CefRequestContextImpl::GetBrowserContext(request_context);
CHECK(browser_context);
scoped_refptr<net_service::URLLoaderFactoryGetter> loader_factory_getter;

View File

@@ -89,6 +89,17 @@ class ResolveHostHelper : public network::ResolveHostClientBase {
mojo::Receiver<network::mojom::ResolveHostClient> receiver_{this};
};
CefBrowserContext* GetCefBrowserContext(
CefRefPtr<CefRequestContext> request_context) {
CEF_REQUIRE_UIT();
CefRefPtr<CefRequestContextImpl> request_context_impl =
CefRequestContextImpl::GetOrCreateForRequestContext(request_context);
CHECK(request_context_impl);
auto* cef_browser_context = request_context_impl->GetBrowserContext();
CHECK(cef_browser_context);
return cef_browser_context;
}
} // namespace
// CefBrowserContext
@@ -184,6 +195,21 @@ CefRequestContextImpl::GetOrCreateForRequestContext(
return CefRequestContextImpl::GetOrCreateRequestContext(config);
}
content::BrowserContext* CefRequestContextImpl::GetBrowserContext(
CefRefPtr<CefRequestContext> request_context) {
auto* browser_context =
GetCefBrowserContext(request_context)->AsBrowserContext();
CHECK(browser_context);
return browser_context;
}
Profile* CefRequestContextImpl::GetProfile(
CefRefPtr<CefRequestContext> request_context) {
auto* profile = GetCefBrowserContext(request_context)->AsProfile();
CHECK(profile);
return profile;
}
bool CefRequestContextImpl::VerifyBrowserContext() const {
if (!CEF_CURRENTLY_ON_UIT()) {
DCHECK(false) << "called on invalid thread";

View File

@@ -38,6 +38,15 @@ class CefRequestContextImpl : public CefRequestContext {
static CefRefPtr<CefRequestContextImpl> GetOrCreateForRequestContext(
CefRefPtr<CefRequestContext> request_context);
// Returns the BrowserContext for the specified |request_context|. Will return
// the global BrowserContext if |request_context| is NULL.
static content::BrowserContext* GetBrowserContext(
CefRefPtr<CefRequestContext> request_context);
// Returns the Profile for the specified |request_context|. Will return the
// global Profile if |request_context| is NULL.
static Profile* GetProfile(CefRefPtr<CefRequestContext> request_context);
// Verify that the browser context can be directly accessed (e.g. on the UI
// thread and initialized).
bool VerifyBrowserContext() const;

View File

@@ -121,12 +121,18 @@ void CefNativeWidgetMac::OnWindowFullscreenTransitionStart() {
views::NativeWidgetMac::OnWindowFullscreenTransitionStart();
if (IsCefWindowInitialized()) {
window_delegate_->OnWindowFullscreenTransition(window_, false);
if (browser_view_) {
browser_view_->FullscreenStateChanging();
}
}
}
void CefNativeWidgetMac::OnWindowFullscreenTransitionComplete() {
views::NativeWidgetMac::OnWindowFullscreenTransitionComplete();
if (IsCefWindowInitialized()) {
if (browser_view_) {
browser_view_->FullscreenStateChanged();
}
window_delegate_->OnWindowFullscreenTransition(window_, true);
}
}

View File

@@ -669,7 +669,8 @@ void CefWindowImpl::SetAccelerator(int command_id,
int key_code,
bool shift_pressed,
bool ctrl_pressed,
bool alt_pressed) {
bool alt_pressed,
bool high_priority) {
CEF_REQUIRE_VALID_RETURN_VOID();
if (!widget_) {
return;
@@ -698,7 +699,10 @@ void CefWindowImpl::SetAccelerator(int command_id,
views::FocusManager* focus_manager = widget_->GetFocusManager();
DCHECK(focus_manager);
focus_manager->RegisterAccelerator(
accelerator, ui::AcceleratorManager::kNormalPriority, this);
accelerator,
high_priority ? ui::AcceleratorManager::kHighPriority
: ui::AcceleratorManager::kNormalPriority,
this);
}
void CefWindowImpl::RemoveAccelerator(int command_id) {

View File

@@ -86,7 +86,8 @@ class CefWindowImpl
int key_code,
bool shift_pressed,
bool ctrl_pressed,
bool alt_pressed) override;
bool alt_pressed,
bool high_priority) override;
void RemoveAccelerator(int command_id) override;
void RemoveAllAccelerators() override;

View File

@@ -296,6 +296,13 @@ class CefValueBase : public CefType, public CefValueController::Object {
// True if access to the underlying value is read-only.
inline bool read_only() const { return read_only_; }
// Convert a writable value to read-only. The reverse could be surprising and
// is therefore not supported.
void MarkReadOnly() {
DCHECK(!read_only_);
read_only_ = true;
}
// True if the underlying value has been detached.
inline bool detached() const { return !controller_.get(); }

View File

@@ -606,6 +606,11 @@ CefRefPtr<CefBinaryValue> CefBinaryValueImpl::Copy() {
return new CefBinaryValueImpl(const_value().Clone());
}
const void* CefBinaryValueImpl::GetRawData() {
CEF_VALUE_VERIFY_RETURN(false, nullptr);
return const_value().GetBlob().data();
}
size_t CefBinaryValueImpl::GetSize() {
CEF_VALUE_VERIFY_RETURN(false, 0);
return const_value().GetBlob().size();

View File

@@ -177,6 +177,7 @@ class CefBinaryValueImpl : public CefValueBase<CefBinaryValue, base::Value> {
bool IsSame(CefRefPtr<CefBinaryValue> that) override;
bool IsEqual(CefRefPtr<CefBinaryValue> that) override;
CefRefPtr<CefBinaryValue> Copy() override;
const void* GetRawData() override;
size_t GetSize() override;
size_t GetData(void* buffer, size_t buffer_size, size_t data_offset) override;

View File

@@ -2368,6 +2368,61 @@ bool CefV8ValueImpl::NeuterArrayBuffer() {
return true;
}
size_t CefV8ValueImpl::GetArrayBufferByteLength() {
size_t rv = 0;
CEF_V8_REQUIRE_ISOLATE_RETURN(rv);
if (type_ != TYPE_OBJECT) {
DCHECK(false) << "V8 value is not an object";
return rv;
}
v8::Isolate* isolate = handle_->isolate();
v8::HandleScope handle_scope(isolate);
v8::Local<v8::Context> context = isolate->GetCurrentContext();
if (context.IsEmpty()) {
DCHECK(false) << "not currently in a V8 context";
return rv;
}
v8::Local<v8::Value> value = handle_->GetNewV8Handle(false);
if (!value->IsArrayBuffer()) {
DCHECK(false) << "V8 value is not an array buffer";
return rv;
}
v8::Local<v8::Object> obj = value->ToObject(context).ToLocalChecked();
return v8::Local<v8::ArrayBuffer>::Cast(obj)->ByteLength();
}
void* CefV8ValueImpl::GetArrayBufferData() {
void* rv = nullptr;
CEF_V8_REQUIRE_ISOLATE_RETURN(rv);
if (type_ != TYPE_OBJECT) {
DCHECK(false) << "V8 value is not an object";
return rv;
}
v8::Isolate* isolate = handle_->isolate();
v8::HandleScope handle_scope(isolate);
v8::Local<v8::Context> context = isolate->GetCurrentContext();
if (context.IsEmpty()) {
DCHECK(false) << "not currently in a V8 context";
return rv;
}
v8::Local<v8::Value> value = handle_->GetNewV8Handle(false);
if (!value->IsArrayBuffer()) {
DCHECK(false) << "V8 value is not an array buffer";
return rv;
}
v8::Local<v8::Object> obj = value->ToObject(context).ToLocalChecked();
v8::Local<v8::ArrayBuffer> arr = v8::Local<v8::ArrayBuffer>::Cast(obj);
return arr->Data();
}
CefString CefV8ValueImpl::GetFunctionName() {
CefString rv;
CEF_V8_REQUIRE_OBJECT_RETURN(rv);

View File

@@ -274,6 +274,8 @@ class CefV8ValueImpl : public CefV8Value {
CefRefPtr<CefV8ArrayBufferReleaseCallback> GetArrayBufferReleaseCallback()
override;
bool NeuterArrayBuffer() override;
size_t GetArrayBufferByteLength() override;
void* GetArrayBufferData() override;
CefString GetFunctionName() override;
CefRefPtr<CefV8Handler> GetFunctionHandler() override;
CefRefPtr<CefV8Value> ExecuteFunction(

View File

@@ -9,7 +9,7 @@
// implementations. See the translator.README.txt file in the tools directory
// for more information.
//
// $hash=905b24443e08e2d3e2464d5f4138e97904be3e9e$
// $hash=8da36dc268f2f9beb26abc105656f3b04b1d46ed$
//
#include "libcef_dll/cpptoc/binary_value_cpptoc.h"
@@ -140,6 +140,25 @@ binary_value_copy(struct _cef_binary_value_t* self) {
return CefBinaryValueCppToC::Wrap(_retval);
}
const void* CEF_CALLBACK
binary_value_get_raw_data(struct _cef_binary_value_t* self) {
shutdown_checker::AssertNotShutdown();
DCHECK(self);
if (!self) {
return NULL;
}
// This manual implementation can be removed once support for 'const void*'
// is integrated into the CEF translator tool (issue #3591).
// Execute
const void* _retval = CefBinaryValueCppToC::Get(self)->GetRawData();
// Return type: simple_byaddr
return _retval;
}
size_t CEF_CALLBACK binary_value_get_size(struct _cef_binary_value_t* self) {
shutdown_checker::AssertNotShutdown();
@@ -193,6 +212,7 @@ CefBinaryValueCppToC::CefBinaryValueCppToC() {
GetStruct()->is_same = binary_value_is_same;
GetStruct()->is_equal = binary_value_is_equal;
GetStruct()->copy = binary_value_copy;
GetStruct()->get_raw_data = binary_value_get_raw_data;
GetStruct()->get_size = binary_value_get_size;
GetStruct()->get_data = binary_value_get_data;
}

View File

@@ -9,7 +9,7 @@
// implementations. See the translator.README.txt file in the tools directory
// for more information.
//
// $hash=497607653318fe0245cbe18c8911e39867e16249$
// $hash=a5c3b05b23c536eba7ce2e7242c3840e93729b29$
//
#include "libcef_dll/cpptoc/browser_host_cpptoc.h"
@@ -1435,6 +1435,77 @@ int CEF_CALLBACK browser_host_is_audio_muted(struct _cef_browser_host_t* self) {
return _retval;
}
int CEF_CALLBACK browser_host_is_fullscreen(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)->IsFullscreen();
// Return type: bool
return _retval;
}
void CEF_CALLBACK browser_host_exit_fullscreen(struct _cef_browser_host_t* self,
int will_cause_resize) {
shutdown_checker::AssertNotShutdown();
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
DCHECK(self);
if (!self) {
return;
}
// Execute
CefBrowserHostCppToC::Get(self)->ExitFullscreen(will_cause_resize ? true
: false);
}
int CEF_CALLBACK
browser_host_can_execute_chrome_command(struct _cef_browser_host_t* self,
int command_id) {
shutdown_checker::AssertNotShutdown();
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
DCHECK(self);
if (!self) {
return 0;
}
// Execute
bool _retval =
CefBrowserHostCppToC::Get(self)->CanExecuteChromeCommand(command_id);
// Return type: bool
return _retval;
}
void CEF_CALLBACK
browser_host_execute_chrome_command(struct _cef_browser_host_t* self,
int command_id,
cef_window_open_disposition_t disposition) {
shutdown_checker::AssertNotShutdown();
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
DCHECK(self);
if (!self) {
return;
}
// Execute
CefBrowserHostCppToC::Get(self)->ExecuteChromeCommand(command_id,
disposition);
}
} // namespace
// CONSTRUCTOR - Do not edit by hand.
@@ -1512,6 +1583,11 @@ CefBrowserHostCppToC::CefBrowserHostCppToC() {
GetStruct()->is_background_host = browser_host_is_background_host;
GetStruct()->set_audio_muted = browser_host_set_audio_muted;
GetStruct()->is_audio_muted = browser_host_is_audio_muted;
GetStruct()->is_fullscreen = browser_host_is_fullscreen;
GetStruct()->exit_fullscreen = browser_host_exit_fullscreen;
GetStruct()->can_execute_chrome_command =
browser_host_can_execute_chrome_command;
GetStruct()->execute_chrome_command = browser_host_execute_chrome_command;
}
// DESTRUCTOR - Do not edit by hand.

View File

@@ -9,7 +9,7 @@
// implementations. See the translator.README.txt file in the tools directory
// for more information.
//
// $hash=e96fe0660b55afa20c3bb5fdebc85635ccc53d09$
// $hash=4990c06888649a2cb06ba7028f16f9cd762f3ad0$
//
#include "libcef_dll/cpptoc/life_span_handler_cpptoc.h"
@@ -169,6 +169,126 @@ int CEF_CALLBACK life_span_handler_on_before_popup(
return _retval;
}
void CEF_CALLBACK life_span_handler_on_before_dev_tools_popup(
struct _cef_life_span_handler_t* self,
cef_browser_t* browser,
cef_window_info_t* windowInfo,
cef_client_t** client,
struct _cef_browser_settings_t* settings,
struct _cef_dictionary_value_t** extra_info,
int* use_default_window) {
shutdown_checker::AssertNotShutdown();
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
DCHECK(self);
if (!self) {
return;
}
// Verify param: browser; type: refptr_diff
DCHECK(browser);
if (!browser) {
return;
}
// Verify param: windowInfo; type: struct_byref
DCHECK(windowInfo);
if (!windowInfo) {
return;
}
if (!template_util::has_valid_size(windowInfo)) {
DCHECK(false) << "invalid windowInfo->[base.]size";
return;
}
// Verify param: client; type: refptr_same_byref
DCHECK(client);
if (!client) {
return;
}
// Verify param: settings; type: struct_byref
DCHECK(settings);
if (!settings) {
return;
}
if (!template_util::has_valid_size(settings)) {
DCHECK(false) << "invalid settings->[base.]size";
return;
}
// Verify param: extra_info; type: refptr_diff_byref
DCHECK(extra_info);
if (!extra_info) {
return;
}
// Verify param: use_default_window; type: bool_byaddr
DCHECK(use_default_window);
if (!use_default_window) {
return;
}
// Translate param: windowInfo; type: struct_byref
CefWindowInfo windowInfoObj;
if (windowInfo) {
windowInfoObj.AttachTo(*windowInfo);
}
// Translate param: client; type: refptr_same_byref
CefRefPtr<CefClient> clientPtr;
if (client && *client) {
clientPtr = CefClientCppToC::Unwrap(*client);
}
CefClient* clientOrig = clientPtr.get();
// Translate param: settings; type: struct_byref
CefBrowserSettings settingsObj;
if (settings) {
settingsObj.AttachTo(*settings);
}
// Translate param: extra_info; type: refptr_diff_byref
CefRefPtr<CefDictionaryValue> extra_infoPtr;
if (extra_info && *extra_info) {
extra_infoPtr = CefDictionaryValueCToCpp::Wrap(*extra_info);
}
CefDictionaryValue* extra_infoOrig = extra_infoPtr.get();
// Translate param: use_default_window; type: bool_byaddr
bool use_default_windowBool =
(use_default_window && *use_default_window) ? true : false;
// Execute
CefLifeSpanHandlerCppToC::Get(self)->OnBeforeDevToolsPopup(
CefBrowserCToCpp::Wrap(browser), windowInfoObj, clientPtr, settingsObj,
extra_infoPtr, &use_default_windowBool);
// Restore param: windowInfo; type: struct_byref
if (windowInfo) {
windowInfoObj.DetachTo(*windowInfo);
}
// Restore param: client; type: refptr_same_byref
if (client) {
if (clientPtr.get()) {
if (clientPtr.get() != clientOrig) {
*client = CefClientCppToC::Wrap(clientPtr);
}
} else {
*client = nullptr;
}
}
// Restore param: settings; type: struct_byref
if (settings) {
settingsObj.DetachTo(*settings);
}
// Restore param: extra_info; type: refptr_diff_byref
if (extra_info) {
if (extra_infoPtr.get()) {
if (extra_infoPtr.get() != extra_infoOrig) {
*extra_info = CefDictionaryValueCToCpp::Unwrap(extra_infoPtr);
}
} else {
*extra_info = nullptr;
}
}
// Restore param: use_default_window; type: bool_byaddr
if (use_default_window) {
*use_default_window = use_default_windowBool ? true : false;
}
}
void CEF_CALLBACK
life_span_handler_on_after_created(struct _cef_life_span_handler_t* self,
cef_browser_t* browser) {
@@ -244,6 +364,8 @@ life_span_handler_on_before_close(struct _cef_life_span_handler_t* self,
CefLifeSpanHandlerCppToC::CefLifeSpanHandlerCppToC() {
GetStruct()->on_before_popup = life_span_handler_on_before_popup;
GetStruct()->on_before_dev_tools_popup =
life_span_handler_on_before_dev_tools_popup;
GetStruct()->on_after_created = life_span_handler_on_after_created;
GetStruct()->do_close = life_span_handler_do_close;
GetStruct()->on_before_close = life_span_handler_on_before_close;

View File

@@ -9,7 +9,7 @@
// implementations. See the translator.README.txt file in the tools directory
// for more information.
//
// $hash=3bc6db85e54dc87c1e592291be01820547e0989f$
// $hash=4356ad718a385149741e4c8bbbe5d5290466ed40$
//
#include "libcef_dll/cpptoc/shared_memory_region_cpptoc.h"
@@ -64,6 +64,9 @@ shared_memory_region_memory(struct _cef_shared_memory_region_t* self) {
return NULL;
}
// This manual implementation can be removed once support for 'void*'
// is integrated into the CEF translator tool (issue #3591).
// Execute
void* _retval = CefSharedMemoryRegionCppToC::Get(self)->Memory();

View File

@@ -9,7 +9,7 @@
// implementations. See the translator.README.txt file in the tools directory
// for more information.
//
// $hash=ecd6caa0c415b57e93bc66f3c7a4cfb547f022c1$
// $hash=21d8fb47eb282f40fb9d602f44b8c1fd4ff44dea$
//
#include "libcef_dll/cpptoc/v8value_cpptoc.h"
@@ -138,16 +138,12 @@ CEF_EXPORT cef_v8value_t* cef_v8value_create_array_buffer(
cef_v8array_buffer_release_callback_t* release_callback) {
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
// Verify param: buffer; type: simple_byaddr
DCHECK(buffer);
if (!buffer) {
return NULL;
}
// Verify param: release_callback; type: refptr_diff
DCHECK(release_callback);
if (!release_callback) {
return NULL;
}
// Unverified params: buffer
// Execute
CefRefPtr<CefV8Value> _retval = CefV8Value::CreateArrayBuffer(
@@ -948,6 +944,38 @@ int CEF_CALLBACK v8value_neuter_array_buffer(struct _cef_v8value_t* self) {
return _retval;
}
size_t CEF_CALLBACK
v8value_get_array_buffer_byte_length(struct _cef_v8value_t* self) {
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
DCHECK(self);
if (!self) {
return 0;
}
// Execute
size_t _retval = CefV8ValueCppToC::Get(self)->GetArrayBufferByteLength();
// Return type: simple
return _retval;
}
void* CEF_CALLBACK v8value_get_array_buffer_data(struct _cef_v8value_t* self) {
DCHECK(self);
if (!self) {
return NULL;
}
// This manual implementation can be removed once support for 'void*'
// is integrated into the CEF translator tool (issue #3591).
// Execute
void* _retval = CefV8ValueCppToC::Get(self)->GetArrayBufferData();
// Return type: simple_byaddr
return _retval;
}
cef_string_userfree_t CEF_CALLBACK
v8value_get_function_name(struct _cef_v8value_t* self) {
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
@@ -1153,6 +1181,9 @@ CefV8ValueCppToC::CefV8ValueCppToC() {
GetStruct()->get_array_buffer_release_callback =
v8value_get_array_buffer_release_callback;
GetStruct()->neuter_array_buffer = v8value_neuter_array_buffer;
GetStruct()->get_array_buffer_byte_length =
v8value_get_array_buffer_byte_length;
GetStruct()->get_array_buffer_data = v8value_get_array_buffer_data;
GetStruct()->get_function_name = v8value_get_function_name;
GetStruct()->get_function_handler = v8value_get_function_handler;
GetStruct()->execute_function = v8value_execute_function;

View File

@@ -9,7 +9,7 @@
// implementations. See the translator.README.txt file in the tools directory
// for more information.
//
// $hash=23777aea864e9abf38c2e2c5d79a40d6bd22876d$
// $hash=38a50bca35881beb6400f3ad5d81b0a5ec86331d$
//
#include "libcef_dll/cpptoc/views/window_cpptoc.h"
@@ -672,7 +672,8 @@ void CEF_CALLBACK window_set_accelerator(struct _cef_window_t* self,
int key_code,
int shift_pressed,
int ctrl_pressed,
int alt_pressed) {
int alt_pressed,
int high_priority) {
shutdown_checker::AssertNotShutdown();
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
@@ -685,7 +686,8 @@ void CEF_CALLBACK window_set_accelerator(struct _cef_window_t* self,
// Execute
CefWindowCppToC::Get(self)->SetAccelerator(
command_id, key_code, shift_pressed ? true : false,
ctrl_pressed ? true : false, alt_pressed ? true : false);
ctrl_pressed ? true : false, alt_pressed ? true : false,
high_priority ? true : false);
}
void CEF_CALLBACK window_remove_accelerator(struct _cef_window_t* self,

View File

@@ -9,7 +9,7 @@
// implementations. See the translator.README.txt file in the tools directory
// for more information.
//
// $hash=caaf5dfe8d56c784e213b1590c21194f08084b70$
// $hash=f42bab3d9e4ff45faf1fd8071646a8e5bed64177$
//
#include "libcef_dll/ctocpp/binary_value_ctocpp.h"
@@ -139,6 +139,24 @@ CefRefPtr<CefBinaryValue> CefBinaryValueCToCpp::Copy() {
return CefBinaryValueCToCpp::Wrap(_retval);
}
NO_SANITIZE("cfi-icall") const void* CefBinaryValueCToCpp::GetRawData() {
shutdown_checker::AssertNotShutdown();
cef_binary_value_t* _struct = GetStruct();
if (CEF_MEMBER_MISSING(_struct, get_raw_data)) {
return nullptr;
}
// This manual implementation can be removed once support for 'const void*'
// is integrated into the CEF translator tool (issue #3591).
// Execute
const void* _retval = _struct->get_raw_data(_struct);
// Return type: simple_byaddr
return _retval;
}
NO_SANITIZE("cfi-icall") size_t CefBinaryValueCToCpp::GetSize() {
shutdown_checker::AssertNotShutdown();

View File

@@ -9,7 +9,7 @@
// implementations. See the translator.README.txt file in the tools directory
// for more information.
//
// $hash=b6f011a6c26b4264084eb68dae0d63032c07013c$
// $hash=2e0ac9b73ba6bdb4b07ee0f8c445974359c5862f$
//
#ifndef CEF_LIBCEF_DLL_CTOCPP_BINARY_VALUE_CTOCPP_H_
@@ -39,6 +39,7 @@ class CefBinaryValueCToCpp : public CefCToCppRefCounted<CefBinaryValueCToCpp,
bool IsSame(CefRefPtr<CefBinaryValue> that) override;
bool IsEqual(CefRefPtr<CefBinaryValue> that) override;
CefRefPtr<CefBinaryValue> Copy() override;
const void* GetRawData() override;
size_t GetSize() override;
size_t GetData(void* buffer, size_t buffer_size, size_t data_offset) override;
};

View File

@@ -9,7 +9,7 @@
// implementations. See the translator.README.txt file in the tools directory
// for more information.
//
// $hash=cd4e4aa1670f0c887090e23f5e7e3a01e5de9d13$
// $hash=b06e3bbc86769bbc2485d4ab9530b5c39dc73243$
//
#include "libcef_dll/ctocpp/browser_host_ctocpp.h"
@@ -1229,6 +1229,73 @@ NO_SANITIZE("cfi-icall") bool CefBrowserHostCToCpp::IsAudioMuted() {
return _retval ? true : false;
}
NO_SANITIZE("cfi-icall") bool CefBrowserHostCToCpp::IsFullscreen() {
shutdown_checker::AssertNotShutdown();
cef_browser_host_t* _struct = GetStruct();
if (CEF_MEMBER_MISSING(_struct, is_fullscreen)) {
return false;
}
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
// Execute
int _retval = _struct->is_fullscreen(_struct);
// Return type: bool
return _retval ? true : false;
}
NO_SANITIZE("cfi-icall")
void CefBrowserHostCToCpp::ExitFullscreen(bool will_cause_resize) {
shutdown_checker::AssertNotShutdown();
cef_browser_host_t* _struct = GetStruct();
if (CEF_MEMBER_MISSING(_struct, exit_fullscreen)) {
return;
}
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
// Execute
_struct->exit_fullscreen(_struct, will_cause_resize);
}
NO_SANITIZE("cfi-icall")
bool CefBrowserHostCToCpp::CanExecuteChromeCommand(int command_id) {
shutdown_checker::AssertNotShutdown();
cef_browser_host_t* _struct = GetStruct();
if (CEF_MEMBER_MISSING(_struct, can_execute_chrome_command)) {
return false;
}
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
// Execute
int _retval = _struct->can_execute_chrome_command(_struct, command_id);
// Return type: bool
return _retval ? true : false;
}
NO_SANITIZE("cfi-icall")
void CefBrowserHostCToCpp::ExecuteChromeCommand(
int command_id,
cef_window_open_disposition_t disposition) {
shutdown_checker::AssertNotShutdown();
cef_browser_host_t* _struct = GetStruct();
if (CEF_MEMBER_MISSING(_struct, execute_chrome_command)) {
return;
}
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
// Execute
_struct->execute_chrome_command(_struct, command_id, disposition);
}
// CONSTRUCTOR - Do not edit by hand.
CefBrowserHostCToCpp::CefBrowserHostCToCpp() {}

View File

@@ -9,7 +9,7 @@
// implementations. See the translator.README.txt file in the tools directory
// for more information.
//
// $hash=b4e11c91197cd5d6ccbe3a0d96aaae3792a6e05c$
// $hash=e07873b7e67c06fb54dafa370eca83d2c698ffb9$
//
#ifndef CEF_LIBCEF_DLL_CTOCPP_BROWSER_HOST_CTOCPP_H_
@@ -134,6 +134,11 @@ class CefBrowserHostCToCpp : public CefCToCppRefCounted<CefBrowserHostCToCpp,
bool IsBackgroundHost() override;
void SetAudioMuted(bool mute) override;
bool IsAudioMuted() override;
bool IsFullscreen() override;
void ExitFullscreen(bool will_cause_resize) override;
bool CanExecuteChromeCommand(int command_id) override;
void ExecuteChromeCommand(int command_id,
cef_window_open_disposition_t disposition) override;
};
#endif // CEF_LIBCEF_DLL_CTOCPP_BROWSER_HOST_CTOCPP_H_

View File

@@ -9,7 +9,7 @@
// implementations. See the translator.README.txt file in the tools directory
// for more information.
//
// $hash=d141b95304de99ab093db8f6c524a05e26f4edb5$
// $hash=d85695db88a025b1f7e4e4604f3085da29d5eabf$
//
#include "libcef_dll/ctocpp/life_span_handler_ctocpp.h"
@@ -109,6 +109,76 @@ bool CefLifeSpanHandlerCToCpp::OnBeforePopup(
return _retval ? true : false;
}
NO_SANITIZE("cfi-icall")
void CefLifeSpanHandlerCToCpp::OnBeforeDevToolsPopup(
CefRefPtr<CefBrowser> browser,
CefWindowInfo& windowInfo,
CefRefPtr<CefClient>& client,
CefBrowserSettings& settings,
CefRefPtr<CefDictionaryValue>& extra_info,
bool* use_default_window) {
shutdown_checker::AssertNotShutdown();
cef_life_span_handler_t* _struct = GetStruct();
if (CEF_MEMBER_MISSING(_struct, on_before_dev_tools_popup)) {
return;
}
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
// Verify param: browser; type: refptr_diff
DCHECK(browser.get());
if (!browser.get()) {
return;
}
// Verify param: use_default_window; type: bool_byaddr
DCHECK(use_default_window);
if (!use_default_window) {
return;
}
// Translate param: client; type: refptr_same_byref
cef_client_t* clientStruct = NULL;
if (client.get()) {
clientStruct = CefClientCToCpp::Unwrap(client);
}
cef_client_t* clientOrig = clientStruct;
// Translate param: extra_info; type: refptr_diff_byref
cef_dictionary_value_t* extra_infoStruct = NULL;
if (extra_info.get()) {
extra_infoStruct = CefDictionaryValueCppToC::Wrap(extra_info);
}
cef_dictionary_value_t* extra_infoOrig = extra_infoStruct;
// Translate param: use_default_window; type: bool_byaddr
int use_default_windowInt = use_default_window ? *use_default_window : 0;
// Execute
_struct->on_before_dev_tools_popup(_struct, CefBrowserCppToC::Wrap(browser),
&windowInfo, &clientStruct, &settings,
&extra_infoStruct, &use_default_windowInt);
// Restore param:client; type: refptr_same_byref
if (clientStruct) {
if (clientStruct != clientOrig) {
client = CefClientCToCpp::Wrap(clientStruct);
}
} else {
client = nullptr;
}
// Restore param:extra_info; type: refptr_diff_byref
if (extra_infoStruct) {
if (extra_infoStruct != extra_infoOrig) {
extra_info = CefDictionaryValueCppToC::Unwrap(extra_infoStruct);
}
} else {
extra_info = nullptr;
}
// Restore param:use_default_window; type: bool_byaddr
if (use_default_window) {
*use_default_window = use_default_windowInt ? true : false;
}
}
NO_SANITIZE("cfi-icall")
void CefLifeSpanHandlerCToCpp::OnAfterCreated(CefRefPtr<CefBrowser> browser) {
shutdown_checker::AssertNotShutdown();

View File

@@ -9,7 +9,7 @@
// implementations. See the translator.README.txt file in the tools directory
// for more information.
//
// $hash=229117f1ecb1cc27b5ab5eebd79e64c30d73a855$
// $hash=53f00e60e361c79c69a8f19474a234d5011454f5$
//
#ifndef CEF_LIBCEF_DLL_CTOCPP_LIFE_SPAN_HANDLER_CTOCPP_H_
@@ -49,6 +49,12 @@ class CefLifeSpanHandlerCToCpp
CefBrowserSettings& settings,
CefRefPtr<CefDictionaryValue>& extra_info,
bool* no_javascript_access) override;
void OnBeforeDevToolsPopup(CefRefPtr<CefBrowser> browser,
CefWindowInfo& windowInfo,
CefRefPtr<CefClient>& client,
CefBrowserSettings& settings,
CefRefPtr<CefDictionaryValue>& extra_info,
bool* use_default_window) override;
void OnAfterCreated(CefRefPtr<CefBrowser> browser) override;
bool DoClose(CefRefPtr<CefBrowser> browser) override;
void OnBeforeClose(CefRefPtr<CefBrowser> browser) override;

View File

@@ -9,7 +9,7 @@
// implementations. See the translator.README.txt file in the tools directory
// for more information.
//
// $hash=31516110398f9fe682988645d74ac8789b712181$
// $hash=a396f422ed18fe4aae90d4fef3750b4726279c7e$
//
#include "libcef_dll/ctocpp/shared_memory_region_ctocpp.h"
@@ -59,6 +59,9 @@ NO_SANITIZE("cfi-icall") void* CefSharedMemoryRegionCToCpp::Memory() {
return NULL;
}
// This manual implementation can be removed once support for 'void*'
// is integrated into the CEF translator tool (issue #3591).
// Execute
void* _retval = _struct->memory(_struct);

View File

@@ -9,7 +9,7 @@
// implementations. See the translator.README.txt file in the tools directory
// for more information.
//
// $hash=459c331b0c02f55c4b700761ad2132d7320fd467$
// $hash=f67b0996d7e2133f3f28f2d8ba5446c5ff40aaba$
//
#include "libcef_dll/ctocpp/v8value_ctocpp.h"
@@ -147,16 +147,12 @@ CefRefPtr<CefV8Value> CefV8Value::CreateArrayBuffer(
CefRefPtr<CefV8ArrayBufferReleaseCallback> release_callback) {
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
// Verify param: buffer; type: simple_byaddr
DCHECK(buffer);
if (!buffer) {
return nullptr;
}
// Verify param: release_callback; type: refptr_diff
DCHECK(release_callback.get());
if (!release_callback.get()) {
return nullptr;
}
// Unverified params: buffer
// Execute
cef_v8value_t* _retval = cef_v8value_create_array_buffer(
@@ -957,6 +953,37 @@ NO_SANITIZE("cfi-icall") bool CefV8ValueCToCpp::NeuterArrayBuffer() {
return _retval ? true : false;
}
NO_SANITIZE("cfi-icall") size_t CefV8ValueCToCpp::GetArrayBufferByteLength() {
cef_v8value_t* _struct = GetStruct();
if (CEF_MEMBER_MISSING(_struct, get_array_buffer_byte_length)) {
return 0;
}
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
// Execute
size_t _retval = _struct->get_array_buffer_byte_length(_struct);
// Return type: simple
return _retval;
}
NO_SANITIZE("cfi-icall") void* CefV8ValueCToCpp::GetArrayBufferData() {
cef_v8value_t* _struct = GetStruct();
if (CEF_MEMBER_MISSING(_struct, get_array_buffer_data)) {
return nullptr;
}
// This manual implementation can be removed once support for 'void*'
// is integrated into the CEF translator tool (issue #3591).
// Execute
void* _retval = _struct->get_array_buffer_data(_struct);
// Return type: simple_byaddr
return _retval;
}
NO_SANITIZE("cfi-icall") CefString CefV8ValueCToCpp::GetFunctionName() {
cef_v8value_t* _struct = GetStruct();
if (CEF_MEMBER_MISSING(_struct, get_function_name)) {

View File

@@ -9,7 +9,7 @@
// implementations. See the translator.README.txt file in the tools directory
// for more information.
//
// $hash=cab5b018f6706a3c8496865e0c9f30fcbc94cdd8$
// $hash=c81cc0910be6678c0512c5423b8fc5dc1df42743$
//
#ifndef CEF_LIBCEF_DLL_CTOCPP_V8VALUE_CTOCPP_H_
@@ -83,6 +83,8 @@ class CefV8ValueCToCpp
CefRefPtr<CefV8ArrayBufferReleaseCallback> GetArrayBufferReleaseCallback()
override;
bool NeuterArrayBuffer() override;
size_t GetArrayBufferByteLength() override;
void* GetArrayBufferData() override;
CefString GetFunctionName() override;
CefRefPtr<CefV8Handler> GetFunctionHandler() override;
CefRefPtr<CefV8Value> ExecuteFunction(

View File

@@ -9,7 +9,7 @@
// implementations. See the translator.README.txt file in the tools directory
// for more information.
//
// $hash=b6b0a2a563b475163aa71b20af6ec2ac8c1f0cae$
// $hash=c8f164d20875c8071837c04abb44e09672d894af$
//
#include "libcef_dll/ctocpp/views/window_ctocpp.h"
@@ -663,7 +663,8 @@ void CefWindowCToCpp::SetAccelerator(int command_id,
int key_code,
bool shift_pressed,
bool ctrl_pressed,
bool alt_pressed) {
bool alt_pressed,
bool high_priority) {
shutdown_checker::AssertNotShutdown();
cef_window_t* _struct = GetStruct();
@@ -675,7 +676,7 @@ void CefWindowCToCpp::SetAccelerator(int command_id,
// Execute
_struct->set_accelerator(_struct, command_id, key_code, shift_pressed,
ctrl_pressed, alt_pressed);
ctrl_pressed, alt_pressed, high_priority);
}
NO_SANITIZE("cfi-icall")

View File

@@ -9,7 +9,7 @@
// implementations. See the translator.README.txt file in the tools directory
// for more information.
//
// $hash=2a7aaed7d4296e29dca74345cf2b2d4db221a738$
// $hash=d0c31c38bf29c9b44f645e69a912b6b8a4030066$
//
#ifndef CEF_LIBCEF_DLL_CTOCPP_VIEWS_WINDOW_CTOCPP_H_
@@ -83,7 +83,8 @@ class CefWindowCToCpp
int key_code,
bool shift_pressed,
bool ctrl_pressed,
bool alt_pressed) override;
bool alt_pressed,
bool high_priority) override;
void RemoveAccelerator(int command_id) override;
void RemoveAllAccelerators() override;

View File

@@ -9,11 +9,11 @@
#include <set>
#include "include/base/cef_callback.h"
#include "include/cef_shared_process_message_builder.h"
#include "include/cef_task.h"
#include "include/wrapper/cef_closure_task.h"
#include "include/wrapper/cef_helpers.h"
#include "libcef_dll/wrapper/cef_browser_info_map.h"
#include "libcef_dll/wrapper/cef_message_router_utils.h"
namespace {
@@ -47,126 +47,7 @@ bool ValidateConfig(CefMessageRouterConfig& config) {
return true;
}
struct MessageHeader {
int context_id;
int request_id;
bool is_success;
};
struct ParsedMessage {
int context_id;
int request_id;
bool success;
int error_code;
CefString message;
};
size_t GetByteLength(const CefString& value) {
return value.size() * sizeof(CefString::char_type);
}
size_t GetMessageSize(const CefString& response) {
return sizeof(MessageHeader) + GetByteLength(response);
}
void CopyResponseIntoMemory(void* memory, const CefString& response) {
const size_t bytes = response.size() * sizeof(CefString::char_type);
void* dest = static_cast<uint8_t*>(memory) + sizeof(MessageHeader);
memcpy(dest, response.c_str(), bytes);
}
CefString GetStringFromMemory(const void* memory, size_t size) {
const size_t bytes = size - sizeof(MessageHeader);
const size_t string_len = bytes / sizeof(CefString::char_type);
const CefString::char_type* src =
reinterpret_cast<const CefString::char_type*>(
static_cast<const uint8_t*>(memory) + sizeof(MessageHeader));
constexpr bool copy = true;
CefString result;
result.FromString(src, string_len, copy);
return result;
}
CefRefPtr<CefProcessMessage> BuildListMessage(const std::string& message_name,
int context_id,
int request_id,
const CefString& response) {
auto message = CefProcessMessage::Create(message_name);
CefRefPtr<CefListValue> args = message->GetArgumentList();
args->SetInt(0, context_id);
args->SetInt(1, request_id);
args->SetBool(2, true); // Indicates a success result.
args->SetString(3, response);
return message;
}
CefRefPtr<CefProcessMessage> BuildBinaryMessage(const std::string& message_name,
int context_id,
int request_id,
const CefString& response) {
const size_t message_size = GetMessageSize(response);
auto builder =
CefSharedProcessMessageBuilder::Create(message_name, message_size);
if (!builder->IsValid()) {
LOG(ERROR) << "Failed to allocate shared memory region of size "
<< message_size;
// Use list message as a fallback
return BuildListMessage(message_name, context_id, request_id, response);
}
auto header = static_cast<MessageHeader*>(builder->Memory());
header->context_id = context_id;
header->request_id = request_id;
header->is_success = true;
CopyResponseIntoMemory(builder->Memory(), response);
return builder->Build();
}
CefRefPtr<CefProcessMessage> BuildMessage(size_t threshold,
const std::string& message_name,
int context_id,
int request_id,
const CefString& response) {
if (GetByteLength(response) <= threshold) {
return BuildListMessage(message_name, context_id, request_id, response);
} else {
return BuildBinaryMessage(message_name, context_id, request_id, response);
}
}
ParsedMessage ParseMessage(const CefRefPtr<CefProcessMessage>& message) {
if (auto args = message->GetArgumentList()) {
DCHECK_GT(args->GetSize(), 3U);
const int context_id = args->GetInt(0);
const int request_id = args->GetInt(1);
const bool is_success = args->GetBool(2);
if (is_success) {
return ParsedMessage{context_id, request_id, is_success, 0,
args->GetString(3)};
}
DCHECK_EQ(args->GetSize(), 5U);
return ParsedMessage{context_id, request_id, is_success, args->GetInt(3),
args->GetString(4)};
}
if (const auto region = message->GetSharedMemoryRegion()) {
if (region->IsValid()) {
DCHECK_GE(region->Size(), sizeof(MessageHeader));
auto header = static_cast<const MessageHeader*>(region->Memory());
DCHECK(header->is_success);
return ParsedMessage{
header->context_id, header->request_id, header->is_success, 0,
GetStringFromMemory(region->Memory(), region->Size())};
}
}
return ParsedMessage{};
}
namespace cmru = cef_message_router_utils;
/**
* @brief A helper template for generating ID values.
@@ -204,11 +85,15 @@ class CefMessageRouterBrowserSideImpl : public CefMessageRouterBrowserSide {
CallbackImpl(CefRefPtr<CefMessageRouterBrowserSideImpl> router,
int browser_id,
int64_t query_id,
bool persistent)
bool persistent,
size_t message_size_threshold,
const std::string& query_message_name)
: router_(router),
browser_id_(browser_id),
query_id_(query_id),
persistent_(persistent) {}
persistent_(persistent),
message_size_threshold_(message_size_threshold),
query_message_name_(query_message_name) {}
CallbackImpl(const CallbackImpl&) = delete;
CallbackImpl& operator=(const CallbackImpl&) = delete;
@@ -221,44 +106,36 @@ class CefMessageRouterBrowserSideImpl : public CefMessageRouterBrowserSide {
}
void Success(const CefString& response) override {
if (!CefCurrentlyOn(TID_UI)) {
// Must execute on the UI thread to access member variables.
CefPostTask(TID_UI,
base::BindOnce(&CallbackImpl::Success, this, response));
return;
}
auto builder = cmru::CreateBrowserResponseBuilder(
message_size_threshold_, query_message_name_, response);
if (router_) {
CefPostTask(
TID_UI,
base::BindOnce(&CefMessageRouterBrowserSideImpl::OnCallbackSuccess,
router_.get(), browser_id_, query_id_, response));
// We need to post task here for two reasons:
// 1) To safely access member variables.
// 2) To let the router to persist the query information before
// the Success callback is executed.
CefPostTask(TID_UI,
base::BindOnce(&CallbackImpl::SuccessImpl, this, builder));
}
if (!persistent_) {
// Non-persistent callbacks are only good for a single use.
router_ = nullptr;
}
}
void Success(const void* data, size_t size) override {
auto builder = cmru::CreateBrowserResponseBuilder(
message_size_threshold_, query_message_name_, data, size);
// We need to post task here for two reasons:
// 1) To safely access member variables.
// 2) To let the router to persist the query information before
// the Success callback is executed.
CefPostTask(TID_UI,
base::BindOnce(&CallbackImpl::SuccessImpl, this, builder));
}
void Failure(int error_code, const CefString& error_message) override {
if (!CefCurrentlyOn(TID_UI)) {
// Must execute on the UI thread to access member variables.
CefPostTask(TID_UI, base::BindOnce(&CallbackImpl::Failure, this,
error_code, error_message));
return;
}
if (router_) {
CefPostTask(
TID_UI,
base::BindOnce(&CefMessageRouterBrowserSideImpl::OnCallbackFailure,
router_.get(), browser_id_, query_id_, error_code,
error_message));
// Failure always invalidates the callback.
router_ = nullptr;
}
// We need to post task here for two reasons:
// 1) To safely access member variables.
// 2) To give previosly submitted tasks by the Success calls to execute
// before we invalidate the callback.
CefPostTask(TID_UI, base::BindOnce(&CallbackImpl::FailureImpl, this,
error_code, error_message));
}
void Detach() {
@@ -267,10 +144,37 @@ class CefMessageRouterBrowserSideImpl : public CefMessageRouterBrowserSide {
}
private:
void SuccessImpl(const CefRefPtr<cmru::BrowserResponseBuilder>& builder) {
if (!router_) {
return;
}
router_->OnCallbackSuccess(browser_id_, query_id_, builder);
if (!persistent_) {
// Non-persistent callbacks are only good for a single use.
router_ = nullptr;
}
}
void FailureImpl(int error_code, const CefString& error_message) {
if (!router_) {
return;
}
router_->OnCallbackFailure(browser_id_, query_id_, error_code,
error_message);
// Failure always invalidates the callback.
router_ = nullptr;
}
CefRefPtr<CefMessageRouterBrowserSideImpl> router_;
const int browser_id_;
const int64_t query_id_;
const bool persistent_;
const size_t message_size_threshold_;
const std::string query_message_name_;
IMPLEMENT_REFCOUNTING(CallbackImpl);
};
@@ -388,13 +292,10 @@ class CefMessageRouterBrowserSideImpl : public CefMessageRouterBrowserSide {
const std::string& message_name = message->GetName();
if (message_name == query_message_name_) {
CefRefPtr<CefListValue> args = message->GetArgumentList();
DCHECK_EQ(args->GetSize(), 4U);
const int context_id = args->GetInt(0);
const int request_id = args->GetInt(1);
const CefString& request = args->GetString(2);
const bool persistent = args->GetBool(3);
cmru::RendererMessage content = cmru::ParseRendererMessage(message);
const int context_id = content.context_id;
const int request_id = content.request_id;
const bool persistent = content.is_persistent;
if (handler_set_.empty()) {
// No handlers so cancel the query.
@@ -405,40 +306,38 @@ class CefMessageRouterBrowserSideImpl : public CefMessageRouterBrowserSide {
const int browser_id = browser->GetIdentifier();
const int64_t query_id = query_id_generator_.GetNextId();
CefRefPtr<CallbackImpl> callback(
new CallbackImpl(this, browser_id, query_id, persistent));
CefRefPtr<CallbackImpl> callback =
new CallbackImpl(this, browser_id, query_id, persistent,
config_.message_size_threshold, query_message_name_);
// Make a copy of the handler list in case the user adds or removes a
// handler while we're iterating.
HandlerSet handler_set = handler_set_;
const HandlerSet handlers = handler_set_;
bool handled = false;
HandlerSet::const_iterator it_handler = handler_set.begin();
for (; it_handler != handler_set.end(); ++it_handler) {
handled = (*it_handler)
->OnQuery(browser, frame, query_id, request, persistent,
callback.get());
if (handled) {
break;
}
}
Handler* handler = std::visit(
[&](const auto& arg) -> CefMessageRouterBrowserSide::Handler* {
for (auto handler : handlers) {
bool handled = handler->OnQuery(browser, frame, query_id, arg,
persistent, callback.get());
if (handled) {
return handler;
}
}
return nullptr;
},
content.payload);
// If the query isn't handled nothing should be keeping a reference to
// the callback.
DCHECK(handled || callback->HasOneRef());
DCHECK(handler != nullptr || callback->HasOneRef());
if (handled) {
if (handler) {
// Persist the query information until the callback executes.
// It's safe to do this here because the callback will execute
// asynchronously.
QueryInfo* info = new QueryInfo;
info->browser = browser;
info->frame = frame;
info->context_id = context_id;
info->request_id = request_id;
info->persistent = persistent;
info->callback = callback;
info->handler = *(it_handler);
QueryInfo* info =
new QueryInfo{browser, frame, context_id, request_id,
persistent, callback, handler};
browser_query_info_map_.Add(browser_id, query_id, info);
} else {
// Invalidate the callback.
@@ -527,15 +426,17 @@ class CefMessageRouterBrowserSideImpl : public CefMessageRouterBrowserSide {
}
// Called by CallbackImpl on success.
void OnCallbackSuccess(int browser_id,
int64_t query_id,
const CefString& response) {
void OnCallbackSuccess(
int browser_id,
int64_t query_id,
const CefRefPtr<cmru::BrowserResponseBuilder>& builder) {
CEF_REQUIRE_UI_THREAD();
bool removed;
QueryInfo* info = GetQueryInfo(browser_id, query_id, false, &removed);
if (info) {
SendQuerySuccess(info, response);
SendQuerySuccess(info->browser, info->frame, info->context_id,
info->request_id, builder);
if (removed) {
delete info;
}
@@ -558,19 +459,13 @@ class CefMessageRouterBrowserSideImpl : public CefMessageRouterBrowserSide {
}
}
void SendQuerySuccess(QueryInfo* info, const CefString& response) {
SendQuerySuccess(info->browser, info->frame, info->context_id,
info->request_id, response);
}
void SendQuerySuccess(CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
int context_id,
int request_id,
const CefString& response) {
if (auto message =
BuildMessage(config_.message_size_threshold, query_message_name_,
context_id, request_id, response)) {
void SendQuerySuccess(
CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
int context_id,
int request_id,
const CefRefPtr<cmru::BrowserResponseBuilder>& builder) {
if (auto message = builder->Build(context_id, request_id)) {
frame->SendProcessMessage(PID_RENDERER, message);
}
}
@@ -758,10 +653,16 @@ class CefMessageRouterRendererSideImpl : public CefMessageRouterRendererSide {
CefRefPtr<CefV8Value> arg = arguments[0];
CefRefPtr<CefV8Value> requestVal = arg->GetValue(kMemberRequest);
if (!requestVal.get() || !requestVal->IsString()) {
if (!requestVal.get()) {
exception = "Invalid arguments; object member '" +
std::string(kMemberRequest) + "' is required";
return true;
}
if (!requestVal->IsString() && !requestVal->IsArrayBuffer()) {
exception = "Invalid arguments; object member '" +
std::string(kMemberRequest) +
"' is required and must have type string";
"' must have type string or ArrayBuffer";
return true;
}
@@ -804,9 +705,11 @@ class CefMessageRouterRendererSideImpl : public CefMessageRouterRendererSide {
(persistentVal.get() && persistentVal->GetBoolValue());
const int request_id = router_->SendQuery(
context->GetBrowser(), context->GetFrame(), context_id,
requestVal->GetStringValue(), persistent, successVal, failureVal);
context->GetBrowser(), context->GetFrame(), context_id, requestVal,
persistent, successVal, failureVal);
retval = CefV8Value::CreateInt(request_id);
return true;
} else if (name == config_.js_cancel_function) {
if (arguments.size() != 1 || !arguments[0]->IsInt()) {
@@ -958,29 +861,26 @@ class CefMessageRouterRendererSideImpl : public CefMessageRouterRendererSide {
CefRefPtr<CefProcessMessage> message) override {
CEF_REQUIRE_RENDERER_THREAD();
const std::string& message_name = message->GetName();
if (message_name == query_message_name_) {
auto content = ParseMessage(message);
if (content.success) {
CefPostTask(
TID_RENDERER,
base::BindOnce(
&CefMessageRouterRendererSideImpl::ExecuteSuccessCallback, this,
browser->GetIdentifier(), content.context_id,
content.request_id, content.message));
} else {
CefPostTask(
TID_RENDERER,
base::BindOnce(
&CefMessageRouterRendererSideImpl::ExecuteFailureCallback, this,
browser->GetIdentifier(), content.context_id,
content.request_id, content.error_code, content.message));
}
return true;
if (message->GetName() != query_message_name_) {
return false;
}
return false;
cmru::BrowserMessage content = cmru::ParseBrowserMessage(message);
if (content.is_success) {
std::visit(
[&](const auto& arg) {
ExecuteSuccessCallback(browser->GetIdentifier(), content.context_id,
content.request_id, arg);
},
content.payload);
} else {
ExecuteFailureCallback(browser->GetIdentifier(), content.context_id,
content.request_id, content.error_code,
std::get<CefString>(content.payload));
}
return true;
}
private:
@@ -1039,7 +939,7 @@ class CefMessageRouterRendererSideImpl : public CefMessageRouterRendererSide {
int SendQuery(CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
int context_id,
const CefString& request,
CefRefPtr<CefV8Value> request,
bool persistent,
CefRefPtr<CefV8Value> success_callback,
CefRefPtr<CefV8Value> failure_callback) {
@@ -1053,14 +953,9 @@ class CefMessageRouterRendererSideImpl : public CefMessageRouterRendererSide {
browser_request_info_map_.Add(browser->GetIdentifier(),
std::make_pair(context_id, request_id), info);
CefRefPtr<CefProcessMessage> message =
CefProcessMessage::Create(query_message_name_);
CefRefPtr<CefListValue> args = message->GetArgumentList();
args->SetInt(0, context_id);
args->SetInt(1, request_id);
args->SetString(2, request);
args->SetBool(3, persistent);
CefRefPtr<CefProcessMessage> message = cmru::BuildRendererMsg(
config_.message_size_threshold, query_message_name_, context_id,
request_id, request, persistent);
frame->SendProcessMessage(PID_BROWSER, message);
@@ -1162,6 +1057,41 @@ class CefMessageRouterRendererSideImpl : public CefMessageRouterRendererSide {
}
}
// Execute the onSuccess JavaScript callback.
void ExecuteSuccessCallback(int browser_id,
int context_id,
int request_id,
const CefRefPtr<CefBinaryBuffer>& response) {
CEF_REQUIRE_RENDERER_THREAD();
bool removed;
RequestInfo* info =
GetRequestInfo(browser_id, context_id, request_id, false, &removed);
if (!info) {
return;
}
CefRefPtr<CefV8Context> context = GetContextByID(context_id);
if (context && info->success_callback && context->Enter()) {
CefRefPtr<cmru::BinaryValueABRCallback> release_callback =
new cmru::BinaryValueABRCallback(response);
CefRefPtr<CefV8Value> value = CefV8Value::CreateArrayBuffer(
response->GetData(), response->GetSize(), release_callback);
context->Exit();
CefV8ValueList args;
args.push_back(value);
info->success_callback->ExecuteFunctionWithContext(context, nullptr,
args);
}
if (removed) {
delete info;
}
}
// Execute the onFailure JavaScript callback.
void ExecuteFailureCallback(int browser_id,
int context_id,

View File

@@ -0,0 +1,525 @@
// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
// reserved. Use of this source code is governed by a BSD-style license that
// can be found in the LICENSE file.
#include "libcef_dll/wrapper/cef_message_router_utils.h"
#include "include/cef_shared_process_message_builder.h"
#include <type_traits>
namespace cef_message_router_utils {
namespace {
constexpr int kNoError = 0;
constexpr size_t kContextId = 0;
constexpr size_t kRequestId = 1;
constexpr size_t kRendererPayload = 2;
constexpr size_t kIsSuccess = 2;
constexpr size_t kBrowserPayload = 3;
constexpr size_t kIsPersistent = 3;
struct BrowserMsgHeader {
int context_id;
int request_id;
bool is_binary;
};
static_assert(
std::is_trivially_copyable_v<BrowserMsgHeader>,
"Copying non-trivially-copyable object across memory spaces is dangerous");
struct RendererMsgHeader {
int context_id;
int request_id;
bool is_persistent;
bool is_binary;
};
static_assert(
std::is_trivially_copyable_v<RendererMsgHeader>,
"Copying non-trivially-copyable object across memory spaces is dangerous");
//
// This is a workaround for handling empty CefBinaryValues, as it's not possible
// to create an empty one directly. We use this empty struct as a tag to invoke
// the SetNull function within the BuildBrowserListMsg and BuildRendererListMsg
// functions.
//
struct Empty {};
size_t GetByteLength(const CefString& value) {
return value.size() * sizeof(CefString::char_type);
}
size_t GetByteLength(const CefRefPtr<CefV8Value>& value) {
return value->GetArrayBufferByteLength();
}
const CefString& GetListRepresentation(const CefString& value) {
return value;
}
CefRefPtr<CefBinaryValue> GetListRepresentation(
const CefRefPtr<CefV8Value>& value) {
return CefBinaryValue::Create(value->GetArrayBufferData(),
value->GetArrayBufferByteLength());
}
template <class Header, class T>
size_t GetMessageSize(const T& value) {
return sizeof(Header) + GetByteLength(value);
}
template <class Header>
void CopyIntoMemory(void* memory, const void* data, size_t bytes) {
if (bytes > 0) {
void* dest = static_cast<uint8_t*>(memory) + sizeof(Header);
memcpy(dest, data, bytes);
}
}
template <class Header>
void CopyIntoMemory(void* memory, const CefRefPtr<CefV8Value>& value) {
CopyIntoMemory<Header>(memory, value->GetArrayBufferData(),
value->GetArrayBufferByteLength());
}
template <class Header>
void CopyIntoMemory(void* memory, const CefString& value) {
const size_t bytes = GetByteLength(value);
CopyIntoMemory<Header>(memory, value.c_str(), bytes);
}
template <class Header>
CefString GetStringFromMemory(const void* memory, size_t size) {
const size_t bytes = size - sizeof(Header);
const size_t string_len = bytes / sizeof(CefString::char_type);
const void* string_data =
static_cast<const uint8_t*>(memory) + sizeof(Header);
const CefString::char_type* src =
static_cast<const CefString::char_type*>(string_data);
CefString result;
result.FromString(src, string_len, /*copy=*/true);
return result;
}
template <typename T>
constexpr bool IsCefString() {
return std::is_same_v<std::remove_cv_t<T>, CefString>;
}
template <typename T>
constexpr bool IsEmpty() {
return std::is_same_v<std::remove_cv_t<T>, Empty>;
}
template <class ResponseType>
CefRefPtr<CefProcessMessage> BuildBrowserListMsg(const CefString& name,
int context_id,
int request_id,
const ResponseType& response) {
auto message = CefProcessMessage::Create(name);
CefRefPtr<CefListValue> args = message->GetArgumentList();
args->SetInt(kContextId, context_id);
args->SetInt(kRequestId, request_id);
args->SetBool(kIsSuccess, true);
if constexpr (IsCefString<ResponseType>()) {
args->SetString(kBrowserPayload, response);
} else if constexpr (IsEmpty<ResponseType>()) {
args->SetNull(kBrowserPayload);
} else {
args->SetBinary(kBrowserPayload, response);
}
return message;
}
class EmptyResponseBuilder final : public BrowserResponseBuilder {
public:
explicit EmptyResponseBuilder(const std::string& name) : name_(name) {}
EmptyResponseBuilder(const EmptyResponseBuilder&) = delete;
EmptyResponseBuilder& operator=(const EmptyResponseBuilder&) = delete;
CefRefPtr<CefProcessMessage> Build(int context_id, int request_id) override {
return BuildBrowserListMsg(name_, context_id, request_id, Empty{});
}
private:
const CefString name_;
IMPLEMENT_REFCOUNTING(EmptyResponseBuilder);
};
class BinaryResponseBuilder final : public BrowserResponseBuilder {
public:
BinaryResponseBuilder(const std::string& name, const void* data, size_t size)
: name_(name), value_(CefBinaryValue::Create(data, size)) {}
BinaryResponseBuilder(const BinaryResponseBuilder&) = delete;
BinaryResponseBuilder& operator=(const BinaryResponseBuilder&) = delete;
CefRefPtr<CefProcessMessage> Build(int context_id, int request_id) override {
return BuildBrowserListMsg(name_, context_id, request_id, value_);
}
private:
const CefString name_;
const CefRefPtr<CefBinaryValue> value_;
IMPLEMENT_REFCOUNTING(BinaryResponseBuilder);
};
class StringResponseBuilder final : public BrowserResponseBuilder {
public:
StringResponseBuilder(const std::string& name, const CefString& value)
: name_(name), value_(value) {}
StringResponseBuilder(const StringResponseBuilder&) = delete;
StringResponseBuilder& operator=(const StringResponseBuilder&) = delete;
CefRefPtr<CefProcessMessage> Build(int context_id, int request_id) override {
return BuildBrowserListMsg(name_, context_id, request_id, value_);
}
private:
const CefString name_;
const CefString value_;
IMPLEMENT_REFCOUNTING(StringResponseBuilder);
};
// SharedProcessMessageResponseBuilder
class SPMResponseBuilder final : public BrowserResponseBuilder {
public:
SPMResponseBuilder(const SPMResponseBuilder&) = delete;
SPMResponseBuilder& operator=(const SPMResponseBuilder&) = delete;
static CefRefPtr<BrowserResponseBuilder> Create(const std::string& name,
const void* data,
size_t size) {
const size_t message_size = sizeof(BrowserMsgHeader) + size;
auto builder = CefSharedProcessMessageBuilder::Create(name, message_size);
if (!builder->IsValid()) {
LOG(ERROR) << "Failed to allocate shared memory region of size "
<< message_size;
return new BinaryResponseBuilder(name, data, size);
}
CopyIntoMemory<BrowserMsgHeader>(builder->Memory(), data, size);
return new SPMResponseBuilder(builder, /*is_binary=*/true);
}
static CefRefPtr<BrowserResponseBuilder> Create(const std::string& name,
const CefString& value) {
const size_t message_size = GetMessageSize<BrowserMsgHeader>(value);
auto builder = CefSharedProcessMessageBuilder::Create(name, message_size);
if (!builder->IsValid()) {
LOG(ERROR) << "Failed to allocate shared memory region of size "
<< message_size;
return new StringResponseBuilder(name, value);
}
CopyIntoMemory<BrowserMsgHeader>(builder->Memory(), value);
return new SPMResponseBuilder(builder, /*is_binary=*/false);
}
CefRefPtr<CefProcessMessage> Build(int context_id, int request_id) override {
auto header = static_cast<BrowserMsgHeader*>(builder_->Memory());
header->context_id = context_id;
header->request_id = request_id;
header->is_binary = is_binary_;
return builder_->Build();
}
private:
explicit SPMResponseBuilder(
const CefRefPtr<CefSharedProcessMessageBuilder>& builder,
bool is_binary)
: builder_(builder), is_binary_(is_binary) {}
CefRefPtr<CefSharedProcessMessageBuilder> builder_;
const bool is_binary_;
IMPLEMENT_REFCOUNTING(SPMResponseBuilder);
};
class EmptyBinaryBuffer final : public CefBinaryBuffer {
public:
EmptyBinaryBuffer() = default;
EmptyBinaryBuffer(const EmptyBinaryBuffer&) = delete;
EmptyBinaryBuffer& operator=(const EmptyBinaryBuffer&) = delete;
const void* GetData() const override { return nullptr; }
void* GetData() override { return nullptr; }
size_t GetSize() const override { return 0; }
private:
IMPLEMENT_REFCOUNTING(EmptyBinaryBuffer);
};
class BinaryValueBuffer final : public CefBinaryBuffer {
public:
BinaryValueBuffer(CefRefPtr<CefProcessMessage> message,
CefRefPtr<CefBinaryValue> value)
: message_(std::move(message)), value_(std::move(value)) {}
BinaryValueBuffer(const BinaryValueBuffer&) = delete;
BinaryValueBuffer& operator=(const BinaryValueBuffer&) = delete;
const void* GetData() const override { return value_->GetRawData(); }
void* GetData() override {
// This is not UB as long as underlying storage is vector<uint8_t>
return const_cast<void*>(value_->GetRawData());
}
size_t GetSize() const override { return value_->GetSize(); }
private:
const CefRefPtr<CefProcessMessage> message_;
const CefRefPtr<CefBinaryValue> value_;
IMPLEMENT_REFCOUNTING(BinaryValueBuffer);
};
class SharedMemoryRegionBuffer final : public CefBinaryBuffer {
public:
SharedMemoryRegionBuffer(const CefRefPtr<CefSharedMemoryRegion>& region,
size_t offset)
: region_(region),
data_(static_cast<uint8_t*>(region->Memory()) + offset),
size_(region->Size() - offset) {}
SharedMemoryRegionBuffer(const SharedMemoryRegionBuffer&) = delete;
SharedMemoryRegionBuffer& operator=(const SharedMemoryRegionBuffer&) = delete;
const void* GetData() const override { return data_; }
void* GetData() override { return data_; }
size_t GetSize() const override { return size_; }
private:
const CefRefPtr<CefSharedMemoryRegion> region_;
void* const data_;
const size_t size_;
IMPLEMENT_REFCOUNTING(SharedMemoryRegionBuffer);
};
template <class RequestType>
CefRefPtr<CefProcessMessage> BuildRendererListMsg(const std::string& name,
int context_id,
int request_id,
const RequestType& request,
bool persistent) {
auto message = CefProcessMessage::Create(name);
CefRefPtr<CefListValue> args = message->GetArgumentList();
args->SetInt(kContextId, context_id);
args->SetInt(kRequestId, request_id);
if constexpr (IsCefString<RequestType>()) {
args->SetString(kRendererPayload, request);
} else if constexpr (IsEmpty<RequestType>()) {
args->SetNull(kRendererPayload);
} else {
args->SetBinary(kRendererPayload, request);
}
args->SetBool(kIsPersistent, persistent);
return message;
}
template <class RequestType>
CefRefPtr<CefProcessMessage> BuildRendererSharedMsg(const std::string& name,
int context_id,
int request_id,
const RequestType& request,
bool persistent) {
const size_t message_size = GetMessageSize<RendererMsgHeader>(request);
auto builder = CefSharedProcessMessageBuilder::Create(name, message_size);
if (!builder->IsValid()) {
LOG(ERROR) << "Failed to allocate shared memory region of size "
<< message_size;
return BuildRendererListMsg(name, context_id, request_id,
GetListRepresentation(request), persistent);
}
auto header = static_cast<RendererMsgHeader*>(builder->Memory());
header->context_id = context_id;
header->request_id = request_id;
header->is_persistent = persistent;
header->is_binary = !IsCefString<RequestType>();
CopyIntoMemory<RendererMsgHeader>(builder->Memory(), request);
return builder->Build();
}
CefRefPtr<CefProcessMessage> BuildRendererMsg(size_t threshold,
const std::string& name,
int context_id,
int request_id,
const CefString& request,
bool persistent) {
if (GetByteLength(request) < threshold) {
return BuildRendererListMsg(name, context_id, request_id, request,
persistent);
}
return BuildRendererSharedMsg(name, context_id, request_id, request,
persistent);
}
} // namespace
CefRefPtr<BrowserResponseBuilder> CreateBrowserResponseBuilder(
size_t threshold,
const std::string& name,
const CefString& response) {
if (GetByteLength(response) < threshold) {
return new StringResponseBuilder(name, response);
}
return SPMResponseBuilder::Create(name, response);
}
CefRefPtr<BrowserResponseBuilder> CreateBrowserResponseBuilder(
size_t threshold,
const std::string& name,
const void* data,
size_t size) {
if (size == 0) {
return new EmptyResponseBuilder(name);
}
if (size < threshold) {
return new BinaryResponseBuilder(name, data, size);
}
return SPMResponseBuilder::Create(name, data, size);
}
CefRefPtr<CefProcessMessage> BuildRendererMsg(
size_t threshold,
const std::string& name,
int context_id,
int request_id,
const CefRefPtr<CefV8Value>& request,
bool persistent) {
if (request->IsString()) {
return BuildRendererMsg(threshold, name, context_id, request_id,
request->GetStringValue(), persistent);
}
const auto size = request->GetArrayBufferByteLength();
if (size == 0) {
return BuildRendererListMsg(name, context_id, request_id, Empty{},
persistent);
}
if (size < threshold) {
return BuildRendererListMsg(name, context_id, request_id,
GetListRepresentation(request), persistent);
}
return BuildRendererSharedMsg(name, context_id, request_id, request,
persistent);
}
BrowserMessage ParseBrowserMessage(
const CefRefPtr<CefProcessMessage>& message) {
if (auto args = message->GetArgumentList()) {
DCHECK_GT(args->GetSize(), 3U);
const int context_id = args->GetInt(kContextId);
const int request_id = args->GetInt(kRequestId);
const bool is_success = args->GetBool(kIsSuccess);
if (is_success) {
DCHECK_EQ(args->GetSize(), 4U);
const auto payload_type = args->GetType(kBrowserPayload);
if (payload_type == CefValueType::VTYPE_STRING) {
return {context_id, request_id, is_success, kNoError,
args->GetString(kBrowserPayload)};
}
if (payload_type == CefValueType::VTYPE_BINARY) {
return {
context_id, request_id, is_success, kNoError,
new BinaryValueBuffer(message, args->GetBinary(kBrowserPayload))};
}
DCHECK(payload_type == CefValueType::VTYPE_NULL);
return {context_id, request_id, is_success, kNoError,
new EmptyBinaryBuffer()};
}
DCHECK_EQ(args->GetSize(), 5U);
return {context_id, request_id, is_success, args->GetInt(3),
args->GetString(4)};
}
const auto region = message->GetSharedMemoryRegion();
if (region && region->IsValid()) {
DCHECK_GE(region->Size(), sizeof(BrowserMsgHeader));
auto header = static_cast<const BrowserMsgHeader*>(region->Memory());
if (header->is_binary) {
return {header->context_id, header->request_id, true, kNoError,
new SharedMemoryRegionBuffer(region, sizeof(BrowserMsgHeader))};
}
return {header->context_id, header->request_id, true, kNoError,
GetStringFromMemory<BrowserMsgHeader>(region->Memory(),
region->Size())};
}
NOTREACHED();
return {};
}
RendererMessage ParseRendererMessage(
const CefRefPtr<CefProcessMessage>& message) {
if (auto args = message->GetArgumentList()) {
DCHECK_EQ(args->GetSize(), 4U);
const int context_id = args->GetInt(kContextId);
const int request_id = args->GetInt(kRequestId);
const auto payload_type = args->GetType(kRendererPayload);
const bool persistent = args->GetBool(kIsPersistent);
if (payload_type == CefValueType::VTYPE_STRING) {
return {context_id, request_id, persistent,
args->GetString(kRendererPayload)};
}
if (payload_type == CefValueType::VTYPE_BINARY) {
return {
context_id, request_id, persistent,
new BinaryValueBuffer(message, args->GetBinary(kRendererPayload))};
}
DCHECK(payload_type == CefValueType::VTYPE_NULL);
return {context_id, request_id, persistent, new EmptyBinaryBuffer()};
}
const auto region = message->GetSharedMemoryRegion();
if (region && region->IsValid()) {
DCHECK_GE(region->Size(), sizeof(RendererMsgHeader));
auto header = static_cast<const RendererMsgHeader*>(region->Memory());
if (header->is_binary) {
return {header->context_id, header->request_id, header->is_persistent,
new SharedMemoryRegionBuffer(region, sizeof(RendererMsgHeader))};
}
return {
header->context_id,
header->request_id,
header->is_persistent,
GetStringFromMemory<RendererMsgHeader>(region->Memory(),
region->Size()),
};
}
NOTREACHED();
return {};
}
} // namespace cef_message_router_utils

View File

@@ -0,0 +1,92 @@
// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
// reserved. Use of this source code is governed by a BSD-style license that
// can be found in the LICENSE file.
#ifndef CEF_LIBCEF_DLL_WRAPPER_CEF_MESSAGE_ROUTER_UTILS_H_
#define CEF_LIBCEF_DLL_WRAPPER_CEF_MESSAGE_ROUTER_UTILS_H_
#pragma once
#include <variant>
#include "include/wrapper/cef_message_router.h"
namespace cef_message_router_utils {
///
/// This class handles the task of copying user data, such as CefString or
/// binary values like (void*, size_t), directly to an appropriate buffer based
/// on the user data type and size.
///
/// There are four specializations of this abstract class. The appropriate
/// specialization is chosen by the `CreateBrowserResponseBuilder` function,
/// based on the provided data type and size. For instance, for a "short"
/// CefString, a StringResponseBuilder specialization is used, and for an empty
/// binary value - EmptyResponseBuilder.
///
class BrowserResponseBuilder : public CefBaseRefCounted {
public:
///
/// Creates a new CefProcessMessage from the data provided to the builder.
/// Returns nullptr for invalid instances. Invalidates this builder instance.
///
virtual CefRefPtr<CefProcessMessage> Build(int context_id,
int request_id) = 0;
};
struct BrowserMessage {
int context_id;
int request_id;
bool is_success;
int error_code;
std::variant<CefString, CefRefPtr<CefBinaryBuffer>> payload;
};
struct RendererMessage {
int context_id;
int request_id;
bool is_persistent;
std::variant<CefString, CefRefPtr<const CefBinaryBuffer>> payload;
};
class BinaryValueABRCallback final : public CefV8ArrayBufferReleaseCallback {
public:
explicit BinaryValueABRCallback(CefRefPtr<CefBinaryBuffer> value)
: value_(std::move(value)) {}
BinaryValueABRCallback(const BinaryValueABRCallback&) = delete;
BinaryValueABRCallback& operator=(const BinaryValueABRCallback&) = delete;
void ReleaseBuffer(void* buffer) override {}
private:
const CefRefPtr<CefBinaryBuffer> value_;
IMPLEMENT_REFCOUNTING(BinaryValueABRCallback);
};
CefRefPtr<BrowserResponseBuilder> CreateBrowserResponseBuilder(
size_t threshold,
const std::string& name,
const CefString& response);
CefRefPtr<BrowserResponseBuilder> CreateBrowserResponseBuilder(
size_t threshold,
const std::string& name,
const void* data,
size_t size);
CefRefPtr<CefProcessMessage> BuildRendererMsg(
size_t threshold,
const std::string& name,
int context_id,
int request_id,
const CefRefPtr<CefV8Value>& request,
bool persistent);
BrowserMessage ParseBrowserMessage(const CefRefPtr<CefProcessMessage>& message);
RendererMessage ParseRendererMessage(
const CefRefPtr<CefProcessMessage>& message);
} // namespace cef_message_router_utils
#endif // CEF_LIBCEF_DLL_WRAPPER_CEF_MESSAGE_ROUTER_UTILS_H_

View File

@@ -117,6 +117,10 @@ patches = [
# Windows: Fix incorrect DIPToScreenRect usage in DesktopWindowTreeHostWin
# when |has_external_parent_| is true.
# https://github.com/chromiumembedded/cef/issues/3359
#
# chrome: Allow override of Widget::Activate() to support activation of
# DevTools windows with external parent.
# https://github.com/chromiumembedded/cef/issues/3282
'name': 'views_widget',
},
{
@@ -674,5 +678,10 @@ patches = [
# https://chromium-review.googlesource.com/c/chromium/src/+/4829483
# https://bugs.chromium.org/p/chromium/issues/detail?id=1470837#c22
'name': 'rfh_navigation_4829483'
},
{
# linux: Disable compiler TLS in libxml2.
# https://github.com/chromiumembedded/cef/issues/3616
'name': 'linux_libxml_tls_3616'
}
]

View File

@@ -20,10 +20,10 @@ index 401eb0cd40ee2..5e7ac0b6d9d0a 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 68b50260715c2..79d9cd4558848 100644
index 8ba07ea436976..12baff0903754 100644
--- content/browser/renderer_host/navigation_request.cc
+++ content/browser/renderer_host/navigation_request.cc
@@ -7463,10 +7463,22 @@ NavigationRequest::GetOriginForURLLoaderFactoryBeforeResponseWithDebugInfo(
@@ -7464,10 +7464,22 @@ NavigationRequest::GetOriginForURLLoaderFactoryBeforeResponseWithDebugInfo(
bool use_opaque_origin =
(sandbox_flags & network::mojom::WebSandboxFlags::kOrigin) ==
network::mojom::WebSandboxFlags::kOrigin;
@@ -47,7 +47,7 @@ index 68b50260715c2..79d9cd4558848 100644
}
return origin_and_debug_info;
@@ -7572,6 +7584,15 @@ NavigationRequest::GetOriginForURLLoaderFactoryAfterResponseWithDebugInfo() {
@@ -7573,6 +7585,15 @@ NavigationRequest::GetOriginForURLLoaderFactoryAfterResponseWithDebugInfo() {
DetermineInitiatorRelationship(initiator_rfh,
frame_tree_node_->current_frame_host()));

View File

@@ -1,5 +1,5 @@
diff --git chrome/browser/BUILD.gn chrome/browser/BUILD.gn
index 157ee5cadc0a7..9906a3cc24dd0 100644
index 7cb8d3fc03da2..e643e73f80930 100644
--- chrome/browser/BUILD.gn
+++ chrome/browser/BUILD.gn
@@ -11,6 +11,7 @@ import("//build/config/compiler/pgo/pgo.gni")
@@ -18,7 +18,7 @@ index 157ee5cadc0a7..9906a3cc24dd0 100644
"//chrome:extra_resources",
"//chrome:resources",
"//chrome:strings",
@@ -2694,6 +2696,10 @@ static_library("browser") {
@@ -2696,6 +2698,10 @@ static_library("browser") {
]
}

View File

@@ -12,8 +12,70 @@ index 2480282a19d12..dbd1fbf8a15b5 100644
return false;
}
diff --git chrome/browser/devtools/devtools_window.cc chrome/browser/devtools/devtools_window.cc
index 4d99a769d6069..0ebd577182dc6 100644
--- chrome/browser/devtools/devtools_window.cc
+++ chrome/browser/devtools/devtools_window.cc
@@ -31,6 +31,7 @@
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/task_manager/web_contents_tags.h"
#include "chrome/browser/ui/browser.h"
+#include "chrome/browser/ui/browser_finder.h"
#include "chrome/browser/ui/browser_list.h"
#include "chrome/browser/ui/browser_tabstrip.h"
#include "chrome/browser/ui/browser_window.h"
@@ -1162,6 +1163,13 @@ DevToolsWindow* DevToolsWindow::Create(
!browser->is_type_normal()) {
can_dock = false;
}
+
+#if BUILDFLAG(ENABLE_CEF)
+ if (can_dock && browser && browser->cef_delegate()) {
+ // Don't dock DevTools for CEF-managed browsers.
+ can_dock = false;
+ }
+#endif
}
// Create WebContents with devtools.
@@ -1738,12 +1746,29 @@ void DevToolsWindow::CreateDevToolsBrowser() {
Browser::CreationStatus::kOk) {
return;
}
- browser_ =
- Browser::Create(Browser::CreateParams::CreateForDevTools(profile_));
- browser_->tab_strip_model()->AddWebContents(
- OwnedMainWebContents::TakeWebContents(
- std::move(owned_main_web_contents_)),
- -1, ui::PAGE_TRANSITION_AUTO_TOPLEVEL, AddTabTypes::ADD_ACTIVE);
+
+ auto opener = chrome::FindBrowserWithWebContents(GetInspectedWebContents());
+ auto devtools_contents = OwnedMainWebContents::TakeWebContents(
+ std::move(owned_main_web_contents_));
+
+#if BUILDFLAG(ENABLE_CEF)
+ if (opener && opener->cef_delegate()) {
+ // If a Browser is created, it will take ownership of |devtools_contents|.
+ browser_ = opener->cef_delegate()->CreateDevToolsBrowser(
+ profile_, opener, devtools_contents);
+ }
+#endif
+
+ if (!browser_) {
+ auto create_params = Browser::CreateParams::CreateForDevTools(profile_);
+ create_params.opener = opener;
+
+ browser_ = Browser::Create(std::move(create_params));
+ browser_->tab_strip_model()->AddWebContents(
+ std::move(devtools_contents),
+ -1, ui::PAGE_TRANSITION_AUTO_TOPLEVEL, AddTabTypes::ADD_ACTIVE);
+ }
+
OverrideAndSyncDevToolsRendererPrefs();
}
diff --git chrome/browser/ui/BUILD.gn chrome/browser/ui/BUILD.gn
index eca90c39e0d44..2157b6d86ab02 100644
index d5bc836ec888d..4da459c08e7af 100644
--- chrome/browser/ui/BUILD.gn
+++ chrome/browser/ui/BUILD.gn
@@ -9,6 +9,7 @@ import("//build/config/compiler/compiler.gni")
@@ -61,7 +123,7 @@ index eca90c39e0d44..2157b6d86ab02 100644
"views/apps/app_info_dialog/app_info_dialog_container.cc",
"views/apps/app_info_dialog/app_info_dialog_container.h",
"views/apps/app_info_dialog/app_info_dialog_views.cc",
@@ -6392,6 +6398,7 @@ static_library("ui") {
@@ -6393,6 +6399,7 @@ static_library("ui") {
if (enable_printing) {
deps += [
"//components/printing/browser",
@@ -333,7 +395,7 @@ index 9ba2025634365..b6ceaa7f0b531 100644
case TYPE_NORMAL:
return NormalBrowserSupportsWindowFeature(feature, check_can_support);
diff --git chrome/browser/ui/browser.h chrome/browser/ui/browser.h
index db37e861d2546..c47dfc31131f7 100644
index db37e861d2546..ea85b9966267d 100644
--- chrome/browser/ui/browser.h
+++ chrome/browser/ui/browser.h
@@ -22,6 +22,7 @@
@@ -364,7 +426,7 @@ index db37e861d2546..c47dfc31131f7 100644
+ scoped_refptr<cef::BrowserDelegate::CreateParams> cef_params;
+
+ // Specify the Browser that is opening this popup.
+ // Currently only used with TYPE_PICTURE_IN_PICTURE.
+ // Currently only used with TYPE_PICTURE_IN_PICTURE and TYPE_DEVTOOLS.
+ raw_ptr<Browser, DanglingUntriaged> opener = nullptr;
+#endif
+

View File

@@ -1,8 +1,8 @@
diff --git chrome/browser/renderer_context_menu/render_view_context_menu.cc chrome/browser/renderer_context_menu/render_view_context_menu.cc
index 9ed9d3b43c45b..845bb4ff858ef 100644
index b4a12d129fa52..a8caaab873d3c 100644
--- chrome/browser/renderer_context_menu/render_view_context_menu.cc
+++ chrome/browser/renderer_context_menu/render_view_context_menu.cc
@@ -344,6 +344,13 @@ base::OnceCallback<void(RenderViewContextMenu*)>* GetMenuShownCallback() {
@@ -345,6 +345,13 @@ base::OnceCallback<void(RenderViewContextMenu*)>* GetMenuShownCallback() {
return callback.get();
}
@@ -16,7 +16,7 @@ index 9ed9d3b43c45b..845bb4ff858ef 100644
enum class UmaEnumIdLookupType {
GeneralEnumId,
ContextSpecificEnumId,
@@ -593,6 +600,10 @@ int FindUMAEnumValueForCommand(int id, UmaEnumIdLookupType type) {
@@ -594,6 +601,10 @@ int FindUMAEnumValueForCommand(int id, UmaEnumIdLookupType type) {
if (ContextMenuMatcher::IsExtensionsCustomCommandId(id))
return 1;
@@ -27,7 +27,7 @@ index 9ed9d3b43c45b..845bb4ff858ef 100644
id = CollapseCommandsForUMA(id);
const auto& map = GetIdcToUmaMap(type);
auto it = map.find(id);
@@ -816,6 +827,14 @@ RenderViewContextMenu::RenderViewContextMenu(
@@ -817,6 +828,14 @@ RenderViewContextMenu::RenderViewContextMenu(
pdf_ocr_submenu_model_ = std::make_unique<ui::SimpleMenuModel>(this);
#endif // BUILDFLAG(ENABLE_SCREEN_AI_SERVICE)
@@ -42,7 +42,7 @@ index 9ed9d3b43c45b..845bb4ff858ef 100644
observers_.AddObserver(&autofill_context_menu_manager_);
}
@@ -1278,6 +1297,12 @@ void RenderViewContextMenu::InitMenu() {
@@ -1280,6 +1299,12 @@ void RenderViewContextMenu::InitMenu() {
autofill::PopupHidingReason::kContextMenuOpened);
}
}
@@ -55,7 +55,7 @@ index 9ed9d3b43c45b..845bb4ff858ef 100644
}
Profile* RenderViewContextMenu::GetProfile() const {
@@ -3334,6 +3359,12 @@ void RenderViewContextMenu::RegisterExecutePluginActionCallbackForTesting(
@@ -3315,6 +3340,12 @@ void RenderViewContextMenu::RegisterExecutePluginActionCallbackForTesting(
execute_plugin_action_callback_ = std::move(cb);
}
@@ -69,7 +69,7 @@ index 9ed9d3b43c45b..845bb4ff858ef 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 45f2a2a82cb03..5abee00109363 100644
index 2d38d86a07d98..3f16e2bf696c1 100644
--- chrome/browser/renderer_context_menu/render_view_context_menu.h
+++ chrome/browser/renderer_context_menu/render_view_context_menu.h
@@ -152,6 +152,12 @@ class RenderViewContextMenu
@@ -85,7 +85,7 @@ index 45f2a2a82cb03..5abee00109363 100644
protected:
Profile* GetProfile() const;
@@ -437,6 +443,9 @@ class RenderViewContextMenu
@@ -441,6 +447,9 @@ class RenderViewContextMenu
// built.
bool is_protocol_submenu_valid_ = false;

View File

@@ -1,5 +1,5 @@
diff --git chrome/browser/themes/theme_service.cc chrome/browser/themes/theme_service.cc
index dbd628982e216..d77a39111e254 100644
index d0e1d573c1fca..65ab5fc0a6388 100644
--- chrome/browser/themes/theme_service.cc
+++ chrome/browser/themes/theme_service.cc
@@ -29,6 +29,7 @@
@@ -10,7 +10,7 @@ index dbd628982e216..d77a39111e254 100644
#include "chrome/browser/browser_features.h"
#include "chrome/browser/extensions/extension_service.h"
#include "chrome/browser/extensions/theme_installed_infobar_delegate.h"
@@ -69,6 +70,10 @@
@@ -70,6 +71,10 @@
#include "ui/color/color_provider_manager.h"
#include "ui/native_theme/native_theme.h"
@@ -21,7 +21,7 @@ index dbd628982e216..d77a39111e254 100644
#if BUILDFLAG(ENABLE_EXTENSIONS)
#include "base/scoped_observation.h"
#include "extensions/browser/extension_registry_observer.h"
@@ -270,11 +275,19 @@ void ThemeService::Init() {
@@ -271,11 +276,19 @@ void ThemeService::Init() {
// OnExtensionServiceReady. Otherwise, the ThemeObserver won't be
// constructed in time to observe the corresponding events.
#if BUILDFLAG(ENABLE_EXTENSIONS)

View File

@@ -233,7 +233,7 @@ index a509d0b37e953..0d48c4a1f1daf 100644
+#endif
}
diff --git chrome/browser/chrome_content_browser_client.cc chrome/browser/chrome_content_browser_client.cc
index 54053dfc9b86d..19c11cf71046d 100644
index 9b845c0e331c4..6a2128ae2b562 100644
--- chrome/browser/chrome_content_browser_client.cc
+++ chrome/browser/chrome_content_browser_client.cc
@@ -42,6 +42,7 @@
@@ -295,7 +295,7 @@ index 54053dfc9b86d..19c11cf71046d 100644
}
std::vector<base::FilePath>
@@ -7652,10 +7664,10 @@ void ChromeContentBrowserClient::OnKeepaliveRequestStarted(
@@ -7653,10 +7665,10 @@ void ChromeContentBrowserClient::OnKeepaliveRequestStarted(
const auto now = base::TimeTicks::Now();
const auto timeout = GetKeepaliveTimerTimeout(context);
keepalive_deadline_ = std::max(keepalive_deadline_, now + timeout);
@@ -308,7 +308,7 @@ index 54053dfc9b86d..19c11cf71046d 100644
FROM_HERE, keepalive_deadline_ - now,
base::BindOnce(
&ChromeContentBrowserClient::OnKeepaliveTimerFired,
@@ -7674,7 +7686,8 @@ void ChromeContentBrowserClient::OnKeepaliveRequestFinished() {
@@ -7675,7 +7687,8 @@ void ChromeContentBrowserClient::OnKeepaliveRequestFinished() {
--num_keepalive_requests_;
if (num_keepalive_requests_ == 0) {
DVLOG(1) << "Stopping the keepalive timer";
@@ -318,7 +318,7 @@ index 54053dfc9b86d..19c11cf71046d 100644
// This deletes the keep alive handle attached to the timer function and
// unblock the shutdown sequence.
}
@@ -7816,7 +7829,7 @@ void ChromeContentBrowserClient::OnKeepaliveTimerFired(
@@ -7817,7 +7830,7 @@ void ChromeContentBrowserClient::OnKeepaliveTimerFired(
const auto now = base::TimeTicks::Now();
const auto then = keepalive_deadline_;
if (now < then) {

View File

@@ -231,7 +231,7 @@ index 59024587ef6b7..0c30aa71768cf 100644
void FindBarHost::RegisterAccelerators() {
diff --git chrome/browser/ui/views/frame/browser_frame.cc chrome/browser/ui/views/frame/browser_frame.cc
index bb4b3821bcfda..9734fe4aaffcf 100644
index bb4b3821bcfda..4014f61a7057f 100644
--- chrome/browser/ui/views/frame/browser_frame.cc
+++ chrome/browser/ui/views/frame/browser_frame.cc
@@ -114,15 +114,23 @@ ui::ColorProviderKey::SchemeVariant GetSchemeVariant(
@@ -260,7 +260,7 @@ index bb4b3821bcfda..9734fe4aaffcf 100644
}
BrowserFrame::~BrowserFrame() {}
@@ -228,6 +236,12 @@ void BrowserFrame::LayoutWebAppWindowTitle(
@@ -228,10 +236,20 @@ void BrowserFrame::LayoutWebAppWindowTitle(
}
int BrowserFrame::GetTopInset() const {
@@ -273,7 +273,15 @@ index bb4b3821bcfda..9734fe4aaffcf 100644
return browser_frame_view_->GetTopInset(false);
}
@@ -240,6 +254,8 @@ BrowserNonClientFrameView* BrowserFrame::GetFrameView() const {
void BrowserFrame::UpdateThrobber(bool running) {
+ if (!browser_frame_view_) {
+ // Not supported with CEF Views-hosted DevTools windows.
+ return;
+ }
browser_frame_view_->UpdateThrobber(running);
}
@@ -240,6 +258,8 @@ BrowserNonClientFrameView* BrowserFrame::GetFrameView() const {
}
bool BrowserFrame::UseCustomFrame() const {
@@ -282,7 +290,7 @@ index bb4b3821bcfda..9734fe4aaffcf 100644
return native_browser_frame_->UseCustomFrame();
}
@@ -253,20 +269,30 @@ bool BrowserFrame::ShouldDrawFrameHeader() const {
@@ -253,20 +273,30 @@ bool BrowserFrame::ShouldDrawFrameHeader() const {
void BrowserFrame::GetWindowPlacement(gfx::Rect* bounds,
ui::WindowShowState* show_state) const {
@@ -313,7 +321,7 @@ index bb4b3821bcfda..9734fe4aaffcf 100644
browser_frame_view_->OnBrowserViewInitViewsComplete();
}
@@ -367,6 +393,8 @@ ui::ColorProviderKey::ThemeInitializerSupplier* BrowserFrame::GetCustomTheme()
@@ -367,6 +397,8 @@ ui::ColorProviderKey::ThemeInitializerSupplier* BrowserFrame::GetCustomTheme()
}
void BrowserFrame::OnNativeWidgetWorkspaceChanged() {
@@ -322,7 +330,7 @@ index bb4b3821bcfda..9734fe4aaffcf 100644
chrome::SaveWindowWorkspace(browser_view_->browser(), GetWorkspace());
chrome::SaveWindowVisibleOnAllWorkspaces(browser_view_->browser(),
IsVisibleOnAllWorkspaces());
@@ -478,6 +506,8 @@ void BrowserFrame::OnNativeThemeUpdated(ui::NativeTheme* observed_theme) {
@@ -478,6 +510,8 @@ void BrowserFrame::OnNativeThemeUpdated(ui::NativeTheme* observed_theme) {
ui::ColorProviderKey BrowserFrame::GetColorProviderKey() const {
auto key = Widget::GetColorProviderKey();
@@ -331,7 +339,7 @@ index bb4b3821bcfda..9734fe4aaffcf 100644
key.app_controller = browser_view_->browser()->app_controller();
@@ -632,5 +662,8 @@ bool BrowserFrame::RegenerateFrameOnThemeChange(
@@ -632,5 +666,8 @@ bool BrowserFrame::RegenerateFrameOnThemeChange(
}
bool BrowserFrame::IsIncognitoBrowser() const {
@@ -711,7 +719,7 @@ index 8267a265a8e10..ee08f18e96a34 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 b9b50af047993..30793a69c4942 100644
index b9b50af047993..70ece4c81ff04 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
@@ -573,6 +573,11 @@ PictureInPictureBrowserFrameView::PictureInPictureBrowserFrameView(
@@ -726,7 +734,7 @@ index b9b50af047993..30793a69c4942 100644
}
PictureInPictureBrowserFrameView::~PictureInPictureBrowserFrameView() {
@@ -669,17 +674,20 @@ gfx::Rect PictureInPictureBrowserFrameView::GetWindowBoundsForClientBounds(
@@ -669,18 +674,42 @@ gfx::Rect PictureInPictureBrowserFrameView::GetWindowBoundsForClientBounds(
int PictureInPictureBrowserFrameView::NonClientHitTest(
const gfx::Point& point) {
@@ -735,18 +743,14 @@ index b9b50af047993..30793a69c4942 100644
- GetBackToTabControlsBounds().Contains(point) ||
- GetCloseControlsBounds().Contains(point)) {
- return HTCLIENT;
- }
-
- for (size_t i = 0; i < content_setting_views_.size(); i++) {
- if (GetContentSettingViewBounds(i).Contains(point)) {
+ const bool frameless = !top_bar_container_view_->GetVisible();
+ if (!frameless) {
+ // Allow interacting with the buttons.
+ if (GetLocationIconViewBounds().Contains(point) ||
+ GetBackToTabControlsBounds().Contains(point) ||
+ GetCloseControlsBounds().Contains(point)) {
return HTCLIENT;
}
+ return HTCLIENT;
+ }
+
+ for (size_t i = 0; i < content_setting_views_.size(); i++) {
+ if (GetContentSettingViewBounds(i).Contains(point)) {
@@ -755,11 +759,9 @@ index b9b50af047993..30793a69c4942 100644
+ }
}
// Allow dragging and resizing the window.
@@ -689,6 +697,27 @@ int PictureInPictureBrowserFrameView::NonClientHitTest(
if (window_component != HTNOWHERE)
return window_component;
- for (size_t i = 0; i < content_setting_views_.size(); i++) {
- if (GetContentSettingViewBounds(i).Contains(point)) {
- return HTCLIENT;
+#if BUILDFLAG(ENABLE_CEF)
+ if (frameless) {
+ // Match logic in BrowserView::ShouldDescendIntoChildForEventHandling.
@@ -777,13 +779,12 @@ index b9b50af047993..30793a69c4942 100644
+ point_in_contents_web_view_coords.y())) {
+ return HTCAPTION;
+ }
+ }
+ }
}
}
+#endif // BUILDFLAG(ENABLE_CEF)
+
// Allow interacting with the web contents.
int frame_component = frame()->client_view()->NonClientHitTest(point);
if (frame_component != HTNOWHERE)
// Allow dragging and resizing the window.
int window_component = GetHTComponentForFrame(
@@ -747,7 +776,8 @@ void PictureInPictureBrowserFrameView::Layout() {
gfx::Rect content_area = GetLocalBounds();
content_area.Inset(FrameBorderInsets());

View File

@@ -12,10 +12,10 @@ index 34cacda8ef225..e0465b8ac1185 100644
version.Set("V8-Version", V8_VERSION_STRING);
std::string host = info.GetHeaderValue("host");
diff --git content/browser/loader/navigation_url_loader_impl.cc content/browser/loader/navigation_url_loader_impl.cc
index 3b58e4f2de295..e0348501c83d8 100644
index 3558cbc360714..267abf8a9abd5 100644
--- content/browser/loader/navigation_url_loader_impl.cc
+++ content/browser/loader/navigation_url_loader_impl.cc
@@ -774,6 +774,17 @@ NavigationURLLoaderImpl::PrepareForNonInterceptedRequest() {
@@ -753,6 +753,17 @@ NavigationURLLoaderImpl::PrepareForNonInterceptedRequest() {
resource_request_->has_user_gesture, initiating_origin,
initiator_document_.AsRenderFrameHostIfValid(), &loader_factory);
@@ -145,7 +145,7 @@ index 3c3ebfeec280e..b239506a39b43 100644
base::BindRepeating(&RenderThreadImpl::OnRendererInterfaceReceiver,
base::Unretained(this)));
diff --git content/renderer/renderer_blink_platform_impl.cc content/renderer/renderer_blink_platform_impl.cc
index cddb519c4c893..68b5fc0f60d9c 100644
index 4ed1a50637e40..ce57912529596 100644
--- content/renderer/renderer_blink_platform_impl.cc
+++ content/renderer/renderer_blink_platform_impl.cc
@@ -941,6 +941,15 @@ SkBitmap* RendererBlinkPlatformImpl::GetSadPageBitmap() {

View File

@@ -0,0 +1,13 @@
diff --git third_party/libxml/linux/config.h third_party/libxml/linux/config.h
index c064071ce1545..65110af9a78f5 100644
--- third_party/libxml/linux/config.h
+++ third_party/libxml/linux/config.h
@@ -171,7 +171,7 @@
/* #undef XML_SOCKLEN_T */
/* TLS specifier */
-#define XML_THREAD_LOCAL _Thread_local
+/* #undef XML_THREAD_LOCAL */
/* Define for Solaris 2.5.1 so the uint32_t typedef from <sys/synch.h>,
<pthread.h>, or <semaphore.h> is not used. If the typedef were allowed, the

View File

@@ -41,10 +41,10 @@ index afefe3cd83dee..6668463247644 100644
} // namespace content
diff --git content/browser/renderer_host/render_widget_host_impl.cc content/browser/renderer_host/render_widget_host_impl.cc
index 7a99c04fcf5bb..2ed7d26f2d047 100644
index d7b85d4a6adbe..6bd3035c313b3 100644
--- content/browser/renderer_host/render_widget_host_impl.cc
+++ content/browser/renderer_host/render_widget_host_impl.cc
@@ -3261,6 +3261,11 @@ void RenderWidgetHostImpl::OnInvalidInputEventSource() {
@@ -3271,6 +3271,11 @@ void RenderWidgetHostImpl::OnInvalidInputEventSource() {
GetProcess(), bad_message::INPUT_ROUTER_INVALID_EVENT_SOURCE);
}

View File

@@ -12,10 +12,10 @@ index 5cb6e6463767d..84a9de1dfc6f0 100644
RenderFrameHostImpl::FromFrameToken(
process_id, initiator_frame_token->value())) {
diff --git content/browser/renderer_host/render_frame_host_impl.cc content/browser/renderer_host/render_frame_host_impl.cc
index f9295c24641e9..118e86979c5c7 100644
index 44ab3ea5a90eb..9962e033ab103 100644
--- content/browser/renderer_host/render_frame_host_impl.cc
+++ content/browser/renderer_host/render_frame_host_impl.cc
@@ -10086,6 +10086,7 @@ void RenderFrameHostImpl::CommitNavigation(
@@ -10100,6 +10100,7 @@ void RenderFrameHostImpl::CommitNavigation(
auto browser_calc_origin_to_commit =
navigation_request->GetOriginToCommitWithDebugInfo();
if (!process_lock.is_error_page() && !is_mhtml_subframe &&

View File

@@ -21,7 +21,7 @@ index 0a6c1f498b8fc..79e0cf27a7715 100644
// If the corresponding Connector policy isn't set, don't perform scans.
if (!service || !service->IsConnectorEnabled(connector))
diff --git chrome/browser/net/profile_network_context_service.cc chrome/browser/net/profile_network_context_service.cc
index 1200475275e91..d32195f01c7ed 100644
index 6271f349464b9..caa45362f52cc 100644
--- chrome/browser/net/profile_network_context_service.cc
+++ chrome/browser/net/profile_network_context_service.cc
@@ -22,6 +22,7 @@
@@ -45,7 +45,7 @@ index 1200475275e91..d32195f01c7ed 100644
DisableQuicIfNotAllowed();
@@ -480,6 +483,9 @@ void ProfileNetworkContextService::OnTruncatedCookieBlockingChanged() {
@@ -490,6 +493,9 @@ void ProfileNetworkContextService::OnTruncatedCookieBlockingChanged() {
void ProfileNetworkContextService::OnFirstPartySetsEnabledChanged(
bool enabled) {
@@ -55,7 +55,7 @@ index 1200475275e91..d32195f01c7ed 100644
// Update all FPS Access Delegates on the FPS service to be `enabled`.
first_party_sets::FirstPartySetsPolicyServiceFactory::GetForBrowserContext(
profile_)
@@ -866,9 +872,26 @@ void ProfileNetworkContextService::ConfigureNetworkContextParamsInternal(
@@ -881,9 +887,26 @@ void ProfileNetworkContextService::ConfigureNetworkContextParamsInternal(
network_context_params->cookie_manager_params =
CreateCookieManagerParams(profile_, *cookie_settings_);
@@ -83,7 +83,7 @@ index 1200475275e91..d32195f01c7ed 100644
PrefService* local_state = g_browser_process->local_state();
// Configure the HTTP cache path and size.
base::FilePath base_cache_path;
@@ -877,15 +900,14 @@ void ProfileNetworkContextService::ConfigureNetworkContextParamsInternal(
@@ -892,15 +915,14 @@ void ProfileNetworkContextService::ConfigureNetworkContextParamsInternal(
local_state->GetFilePath(prefs::kDiskCacheDir);
if (!disk_cache_dir.empty())
base_cache_path = disk_cache_dir.Append(base_cache_path.BaseName());
@@ -103,7 +103,7 @@ index 1200475275e91..d32195f01c7ed 100644
network_context_params->file_paths->data_directory =
path.Append(chrome::kNetworkDataDirname);
network_context_params->file_paths->unsandboxed_data_path = path;
@@ -1038,6 +1060,7 @@ void ProfileNetworkContextService::ConfigureNetworkContextParamsInternal(
@@ -1053,6 +1075,7 @@ void ProfileNetworkContextService::ConfigureNetworkContextParamsInternal(
network_context_params->block_trust_tokens =
anti_abuse_content_setting == CONTENT_SETTING_BLOCK;
@@ -111,7 +111,7 @@ index 1200475275e91..d32195f01c7ed 100644
network_context_params->first_party_sets_access_delegate_params =
network::mojom::FirstPartySetsAccessDelegateParams::New();
network_context_params->first_party_sets_access_delegate_params->enabled =
@@ -1054,6 +1077,7 @@ void ProfileNetworkContextService::ConfigureNetworkContextParamsInternal(
@@ -1069,6 +1092,7 @@ void ProfileNetworkContextService::ConfigureNetworkContextParamsInternal(
GetForBrowserContext(profile_);
DCHECK(fps_service);
fps_service->AddRemoteAccessDelegate(std::move(fps_access_delegate_remote));
@@ -223,7 +223,7 @@ index 61fd008fc067e..73909be088278 100644
// reset to null.
const CookieAccessDelegate* cookie_access_delegate() const {
diff --git services/network/cookie_manager.cc services/network/cookie_manager.cc
index 6c804ec1092af..605ff3b32b0b8 100644
index b43998a09b981..6249ece59ae77 100644
--- services/network/cookie_manager.cc
+++ services/network/cookie_manager.cc
@@ -297,14 +297,9 @@ void CookieManager::AllowFileSchemeCookies(

View File

@@ -414,7 +414,7 @@ index 2f552f72074e3..3f057242d198c 100644
}
diff --git ui/views/widget/widget.h ui/views/widget/widget.h
index 419b75d0608b2..d772dc17d165c 100644
index 419b75d0608b2..57bb1fca770ed 100644
--- ui/views/widget/widget.h
+++ ui/views/widget/widget.h
@@ -351,6 +351,8 @@ class VIEWS_EXPORT Widget : public internal::NativeWidgetDelegate,
@@ -426,6 +426,15 @@ index 419b75d0608b2..d772dc17d165c 100644
// Specifies the initial bounds of the Widget. Default is empty, which means
// the NativeWidget may specify a default size. If the parent is specified,
// |bounds| is in the parent's coordinate system. If the parent is not
@@ -742,7 +744,7 @@ class VIEWS_EXPORT Widget : public internal::NativeWidgetDelegate,
void ShowInactive();
// Activates the widget, assuming it already exists and is visible.
- void Activate();
+ virtual void Activate();
// Deactivates the widget, making the next window in the Z order the active
// window.
diff --git ui/views/widget/widget_delegate.h ui/views/widget/widget_delegate.h
index 6d87be86ae8b3..02fe7a11958d0 100644
--- ui/views/widget/widget_delegate.h

View File

@@ -11,7 +11,7 @@ index 8a18ecf567cd3..9697d43bbbfb9 100644
// Cancels and hides the current popup (datetime, select...) if any.
virtual void CancelPagePopup() = 0;
diff --git third_party/blink/renderer/core/exported/web_view_impl.cc third_party/blink/renderer/core/exported/web_view_impl.cc
index acb43e9f5471e..d78498411ec92 100644
index 866af04a935f8..0223a58e5d475 100644
--- third_party/blink/renderer/core/exported/web_view_impl.cc
+++ third_party/blink/renderer/core/exported/web_view_impl.cc
@@ -249,8 +249,13 @@ void WebView::SetUseExternalPopupMenus(bool use_external_popup_menus) {

View File

@@ -0,0 +1,60 @@
// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
// reserved. Use of this source code is governed by a BSD-style license that
// can be found in the LICENSE file.
#include "tests/cefclient/browser/binary_transfer_test.h"
#include <algorithm>
#include <string>
namespace {
const char kTestUrlPath[] = "/binary_transfer";
// Handle messages in the browser process.
class Handler final : public CefMessageRouterBrowserSide::Handler {
public:
// Called due to cefQuery execution in binary_transfer.html.
bool OnQuery(CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
int64_t query_id,
const CefString& request,
bool persistent,
CefRefPtr<Callback> callback) override {
// Only handle messages from the test URL.
const std::string& url = frame->GetURL();
if (!client::test_runner::IsTestURL(url, kTestUrlPath)) {
return false;
}
callback->Success(request);
return true;
}
// Called due to cefQuery execution in binary_transfer.html.
bool OnQuery(CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
int64_t query_id,
CefRefPtr<const CefBinaryBuffer> request,
bool persistent,
CefRefPtr<Callback> callback) override {
// Only handle messages from the test URL.
const std::string& url = frame->GetURL();
if (!client::test_runner::IsTestURL(url, kTestUrlPath)) {
return false;
}
callback->Success(request->GetData(), request->GetSize());
return true;
}
};
} // namespace
namespace client::binary_transfer_test {
void CreateMessageHandlers(test_runner::MessageHandlerSet& handlers) {
handlers.insert(new Handler());
}
} // namespace client::binary_transfer_test

View File

@@ -0,0 +1,17 @@
// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
// reserved. Use of this source code is governed by a BSD-style license that
// can be found in the LICENSE file.
#ifndef CEF_TESTS_CEFCLIENT_BROWSER_BINARY_TRANSFER_TEST_H_
#define CEF_TESTS_CEFCLIENT_BROWSER_BINARY_TRANSFER_TEST_H_
#pragma once
#include "tests/cefclient/browser/test_runner.h"
namespace client::binary_transfer_test {
void CreateMessageHandlers(test_runner::MessageHandlerSet& handlers);
} // namespace client::binary_transfer_test
#endif // CEF_TESTS_CEFCLIENT_BROWSER_BINARY_TRANSFER_TEST_H_

View File

@@ -583,7 +583,7 @@ bool ClientHandler::OnChromeCommand(CefRefPtr<CefBrowser> browser,
} else if (!with_controls_) {
// If controls are hidden, block all commands that don't target the current
// tab or aren't specifically allowed.
block = disposition != WOD_CURRENT_TAB || !allowed;
block = disposition != CEF_WOD_CURRENT_TAB || !allowed;
}
if (block) {
@@ -644,11 +644,12 @@ void ClientHandler::OnBeforeContextMenu(CefRefPtr<CefBrowser> browser,
model->AddSeparator();
}
// Add DevTools items to all context menus.
model->AddItem(CLIENT_ID_SHOW_DEVTOOLS, "&Show DevTools");
model->AddItem(CLIENT_ID_CLOSE_DEVTOOLS, "Close DevTools");
if (!use_chrome_runtime) {
// TODO(chrome-runtime): Add support for this.
// Add DevTools items to all context menus.
model->AddItem(CLIENT_ID_SHOW_DEVTOOLS, "&Show DevTools");
model->AddItem(CLIENT_ID_CLOSE_DEVTOOLS, "Close DevTools");
// Chrome runtime already gives us an "Inspect" menu item.
model->AddSeparator();
model->AddItem(CLIENT_ID_INSPECT_ELEMENT, "Inspect Element");
}
@@ -938,15 +939,36 @@ bool ClientHandler::OnBeforePopup(
bool* no_javascript_access) {
CEF_REQUIRE_UI_THREAD();
if (target_disposition == WOD_NEW_PICTURE_IN_PICTURE) {
if (target_disposition == CEF_WOD_NEW_PICTURE_IN_PICTURE) {
// Use default handling for document picture-in-picture popups.
client = nullptr;
return false;
}
// Return true to cancel the popup window.
return !CreatePopupWindow(browser, false, popupFeatures, windowInfo, client,
settings);
// Potentially create a new RootWindow for the popup browser that will be
// created asynchronously.
CreatePopupWindow(browser, /*is_devtools=*/false, popupFeatures, windowInfo,
client, settings);
// Allow popup creation.
return false;
}
void ClientHandler::OnBeforeDevToolsPopup(
CefRefPtr<CefBrowser> browser,
CefWindowInfo& windowInfo,
CefRefPtr<CefClient>& client,
CefBrowserSettings& settings,
CefRefPtr<CefDictionaryValue>& extra_info,
bool* use_default_window) {
CEF_REQUIRE_UI_THREAD();
// Potentially create a new RootWindow for the DevTools popup browser that
// will be created immediately after this method returns.
if (!CreatePopupWindow(browser, /*is_devtools=*/true, CefPopupFeatures(),
windowInfo, client, settings)) {
*use_default_window = true;
}
}
void ClientHandler::OnAfterCreated(CefRefPtr<CefBrowser> browser) {
@@ -1081,8 +1103,8 @@ bool ClientHandler::OnOpenURLFromTab(
const CefString& target_url,
CefRequestHandler::WindowOpenDisposition target_disposition,
bool user_gesture) {
if (target_disposition == WOD_NEW_BACKGROUND_TAB ||
target_disposition == WOD_NEW_FOREGROUND_TAB) {
if (target_disposition == CEF_WOD_NEW_BACKGROUND_TAB ||
target_disposition == CEF_WOD_NEW_FOREGROUND_TAB) {
// Handle middle-click and ctrl + left-click by opening the URL in a new
// browser window.
auto config = std::make_unique<RootWindowConfig>();
@@ -1303,25 +1325,21 @@ void ClientHandler::ShowDevTools(CefRefPtr<CefBrowser> browser,
CefRefPtr<CefClient> client;
CefBrowserSettings settings;
MainContext::Get()->PopulateBrowserSettings(&settings);
CefRefPtr<CefBrowserHost> host = browser->GetHost();
// Test if the DevTools browser already exists.
bool has_devtools = host->HasDevTools();
if (!has_devtools) {
// Create a new RootWindow for the DevTools browser that will be created
// by ShowDevTools().
has_devtools = CreatePopupWindow(browser, true, CefPopupFeatures(),
windowInfo, client, settings);
if (!MainContext::Get()->UseChromeRuntime() && !host->HasDevTools()) {
// Potentially create a new RootWindow for the DevTools browser that will be
// created by ShowDevTools(). For Chrome runtime this occurs in
// OnBeforeDevToolsPopup instead.
CreatePopupWindow(browser, /*is_devtools=*/true, CefPopupFeatures(),
windowInfo, client, settings);
}
if (has_devtools) {
// Create the DevTools browser if it doesn't already exist.
// Otherwise, focus the existing DevTools browser and inspect the element
// at |inspect_element_at| if non-empty.
host->ShowDevTools(windowInfo, client, settings, inspect_element_at);
}
// Create the DevTools browser if it doesn't already exist.
// Otherwise, focus the existing DevTools browser and inspect the element
// at |inspect_element_at| if non-empty.
host->ShowDevTools(windowInfo, client, settings, inspect_element_at);
}
void ClientHandler::CloseDevTools(CefRefPtr<CefBrowser> browser) {
@@ -1407,11 +1425,10 @@ bool ClientHandler::CreatePopupWindow(CefRefPtr<CefBrowser> browser,
// The popup browser will be parented to a new native window.
// Don't show URL bar and navigation buttons on DevTools windows.
MainContext::Get()->GetRootWindowManager()->CreateRootWindowAsPopup(
// May return nullptr if UseDefaultPopup() returns true.
return !!MainContext::Get()->GetRootWindowManager()->CreateRootWindowAsPopup(
with_controls_ && !is_devtools, is_osr_, popupFeatures, windowInfo,
client, settings);
return true;
}
void ClientHandler::NotifyBrowserCreated(CefRefPtr<CefBrowser> browser) {

View File

@@ -224,6 +224,12 @@ class ClientHandler : public CefClient,
CefBrowserSettings& settings,
CefRefPtr<CefDictionaryValue>& extra_info,
bool* no_javascript_access) override;
void OnBeforeDevToolsPopup(CefRefPtr<CefBrowser> browser,
CefWindowInfo& windowInfo,
CefRefPtr<CefClient>& client,
CefBrowserSettings& settings,
CefRefPtr<CefDictionaryValue>& extra_info,
bool* use_default_window) override;
void OnAfterCreated(CefRefPtr<CefBrowser> browser) override;
bool DoClose(CefRefPtr<CefBrowser> browser) override;
void OnBeforeClose(CefRefPtr<CefBrowser> browser) override;
@@ -348,9 +354,8 @@ class ClientHandler : public CefClient,
friend class ClientDownloadImageCallback;
// Create a new popup window using the specified information. |is_devtools|
// will be true if the window will be used for DevTools. Return true to
// proceed with popup browser creation or false to cancel the popup browser.
// May be called on any thead.
// will be true if the window will be used for DevTools. Returns true if a
// RootWindow was created for the popup.
bool CreatePopupWindow(CefRefPtr<CefBrowser> browser,
bool is_devtools,
const CefPopupFeatures& popupFeatures,

View File

@@ -42,6 +42,10 @@ class MainContext {
// Returns true if the Chrome runtime will be used.
virtual bool UseChromeRuntime() = 0;
// Returns true if a native parent window is being used with the Chrome
// runtime.
virtual bool UseChromeRuntimeNative() = 0;
// Returns true if the Views framework will be used.
virtual bool UseViews() = 0;

View File

@@ -111,8 +111,9 @@ MainContextImpl::MainContextImpl(CefRefPtr<CefCommandLine> command_line,
}
#if defined(OS_WIN) || defined(OS_LINUX)
if (use_chrome_runtime_ && !use_views_ &&
!command_line->HasSwitch(switches::kUseNative)) {
use_chrome_runtime_native_ =
use_chrome_runtime_ && command_line->HasSwitch(switches::kUseNative);
if (use_chrome_runtime_ && !use_views_ && !use_chrome_runtime_native_) {
LOG(WARNING) << "Chrome runtime defaults to the Views framework.";
use_views_ = true;
}
@@ -174,6 +175,10 @@ bool MainContextImpl::UseChromeRuntime() {
return use_chrome_runtime_;
}
bool MainContextImpl::UseChromeRuntimeNative() {
return use_chrome_runtime_native_;
}
bool MainContextImpl::UseViews() {
return use_views_;
}

View File

@@ -29,6 +29,7 @@ class MainContextImpl : public MainContext {
std::string GetMainURL() override;
cef_color_t GetBackgroundColor() override;
bool UseChromeRuntime() override;
bool UseChromeRuntimeNative() override;
bool UseViews() override;
bool UseWindowlessRendering() override;
bool TouchEventsEnabled() override;
@@ -74,6 +75,7 @@ class MainContextImpl : public MainContext {
bool use_windowless_rendering_;
int windowless_frame_rate_ = 0;
bool use_chrome_runtime_;
bool use_chrome_runtime_native_ = false;
bool use_views_;
std::unique_ptr<RootWindowManager> root_window_manager_;

View File

@@ -44,31 +44,32 @@
#define ID_TESTS_UNMUTE_AUDIO 32717
#define ID_TESTS_LAST 32717
#define IDC_STATIC -1
#define IDS_BINDING_HTML 1000
#define IDS_DIALOGS_HTML 1001
#define IDS_DRAGGABLE_HTML 1002
#define IDS_IPC_PERFORMANCE_HTML 1003
#define IDS_LOCALSTORAGE_HTML 1004
#define IDS_LOGO_PNG 1005
#define IDS_MEDIA_ROUTER_HTML 1006
#define IDS_MENU_ICON_1X_PNG 1007
#define IDS_MENU_ICON_2X_PNG 1008
#define IDS_OSRTEST_HTML 1009
#define IDS_OTHER_TESTS_HTML 1010
#define IDS_PDF_HTML 1011
#define IDS_PDF_PDF 1012
#define IDS_PERFORMANCE_HTML 1013
#define IDS_PERFORMANCE2_HTML 1014
#define IDS_PREFERENCES_HTML 1015
#define IDS_RESPONSE_FILTER_HTML 1016
#define IDS_SERVER_HTML 1017
#define IDS_TRANSPARENCY_HTML 1018
#define IDS_URLREQUEST_HTML 1019
#define IDS_WEBSOCKET_HTML 1020
#define IDS_WINDOW_HTML 1021
#define IDS_WINDOW_ICON_1X_PNG 1022
#define IDS_WINDOW_ICON_2X_PNG 1023
#define IDS_XMLHTTPREQUEST_HTML 1024
#define IDS_BINARY_TRANSFER_HTML 1000
#define IDS_BINDING_HTML 1001
#define IDS_DIALOGS_HTML 1002
#define IDS_DRAGGABLE_HTML 1003
#define IDS_IPC_PERFORMANCE_HTML 1004
#define IDS_LOCALSTORAGE_HTML 1005
#define IDS_LOGO_PNG 1006
#define IDS_MEDIA_ROUTER_HTML 1007
#define IDS_MENU_ICON_1X_PNG 1008
#define IDS_MENU_ICON_2X_PNG 1009
#define IDS_OSRTEST_HTML 1010
#define IDS_OTHER_TESTS_HTML 1011
#define IDS_PDF_HTML 1012
#define IDS_PDF_PDF 1013
#define IDS_PERFORMANCE_HTML 1014
#define IDS_PERFORMANCE2_HTML 1015
#define IDS_PREFERENCES_HTML 1016
#define IDS_RESPONSE_FILTER_HTML 1017
#define IDS_SERVER_HTML 1018
#define IDS_TRANSPARENCY_HTML 1019
#define IDS_URLREQUEST_HTML 1020
#define IDS_WEBSOCKET_HTML 1021
#define IDS_WINDOW_HTML 1022
#define IDS_WINDOW_ICON_1X_PNG 1023
#define IDS_WINDOW_ICON_2X_PNG 1024
#define IDS_XMLHTTPREQUEST_HTML 1025
#define IDS_EXTENSIONS_SET_PAGE_COLOR_ICON_PNG 1030
#define IDS_EXTENSIONS_SET_PAGE_COLOR_MANIFEST_JSON 1031

View File

@@ -13,7 +13,8 @@ int GetResourceId(const char* resource_name) {
static struct _resource_map {
const char* name;
int id;
} resource_map[] = {{"binding.html", IDS_BINDING_HTML},
} resource_map[] = {{"binary_transfer.html", IDS_BINARY_TRANSFER_HTML},
{"binding.html", IDS_BINDING_HTML},
{"dialogs.html", IDS_DIALOGS_HTML},
{"draggable.html", IDS_DRAGGABLE_HTML},
{"extensions/set_page_color/icon.png",

View File

@@ -28,6 +28,9 @@ enum class WindowType {
// The window is a modal dialog.
DIALOG,
// The window is a DevTools popup.
DEVTOOLS,
};
// Used to configure how a RootWindow is created.

View File

@@ -249,7 +249,7 @@ void RootWindowViews::OnViewsWindowClosing(CefRefPtr<ViewsWindow> window) {
CEF_REQUIRE_UI_THREAD();
DCHECK(window_);
if (config_->window_type != WindowType::NORMAL) {
if (!window_->SupportsWindowRestore()) {
return;
}
@@ -516,7 +516,7 @@ void RootWindowViews::InitOnUIThread(
// Initial state was specified via the config object.
initial_bounds_ = config_->bounds;
initial_show_state_ = config_->show_state;
} else if (config_->window_type == WindowType::NORMAL) {
} else if (ViewsWindow::SupportsWindowRestore(config_->window_type)) {
// Initial state may be specified via the command-line or global
// preferences.
std::optional<CefRect> bounds;

View File

@@ -16,6 +16,7 @@
#include "include/views/cef_browser_view.h"
#include "include/wrapper/cef_closure_task.h"
#include "include/wrapper/cef_stream_resource_handler.h"
#include "tests/cefclient/browser/binary_transfer_test.h"
#include "tests/cefclient/browser/binding_test.h"
#include "tests/cefclient/browser/client_handler.h"
#include "tests/cefclient/browser/dialog_test.h"
@@ -842,6 +843,9 @@ bool IsTestURL(const std::string& url, const std::string& path) {
void CreateMessageHandlers(MessageHandlerSet& handlers) {
handlers.insert(new PromptHandler);
// Create the binary trasfer test handlers.
binary_transfer_test::CreateMessageHandlers(handlers);
// Create the binding test handlers.
binding_test::CreateMessageHandlers(handlers);

View File

@@ -399,10 +399,21 @@ void ViewsWindow::OnExtensionsChanged(const ExtensionSet& extensions) {
base::BindOnce(&ViewsWindow::OnExtensionIconsLoaded, this, extensions));
}
// static
bool ViewsWindow::SupportsWindowRestore(WindowType type) {
// Only support window restore with normal windows.
return type == WindowType::NORMAL;
}
bool ViewsWindow::SupportsWindowRestore() const {
return SupportsWindowRestore(type_);
}
bool ViewsWindow::GetWindowRestorePreferences(
cef_show_state_t& show_state,
std::optional<CefRect>& dip_bounds) {
CEF_REQUIRE_UI_THREAD();
DCHECK(SupportsWindowRestore());
if (!window_) {
return false;
}
@@ -460,7 +471,9 @@ CefRefPtr<CefBrowserViewDelegate> ViewsWindow::GetDelegateForPopupBrowserView(
DCHECK(popup_delegate != delegate_);
// Create a new ViewsWindow for the popup BrowserView.
return new ViewsWindow(WindowType::NORMAL, popup_delegate, nullptr);
return new ViewsWindow(
is_devtools ? WindowType::DEVTOOLS : WindowType::NORMAL, popup_delegate,
nullptr);
}
bool ViewsWindow::OnPopupBrowserViewCreated(
@@ -651,6 +664,18 @@ void ViewsWindow::OnWindowFullscreenTransition(CefRefPtr<CefWindow> window,
if (should_change && with_controls_) {
ShowTopControls(!window->IsFullscreen());
}
// With Alloy runtime we need to explicitly exit browser fullscreen when
// exiting window fullscreen. Chrome runtime handles this internally.
if (!MainContext::Get()->UseChromeRuntime() && should_change &&
!window->IsFullscreen()) {
CefRefPtr<CefBrowser> browser = browser_view_->GetBrowser();
if (browser && browser->GetHost()->IsFullscreen()) {
// Will not cause a resize because the fullscreen transition has already
// begun.
browser->GetHost()->ExitFullscreen(/*will_cause_resize=*/false);
}
}
}
void ViewsWindow::OnWindowCreated(CefRefPtr<CefWindow> window) {
@@ -664,12 +689,12 @@ void ViewsWindow::OnWindowCreated(CefRefPtr<CefWindow> window) {
delegate_->OnViewsWindowCreated(this);
if (type_ == WindowType::NORMAL) {
if (type_ == WindowType::NORMAL || type_ == WindowType::DEVTOOLS) {
const CefRect bounds = delegate_->GetInitialBounds();
if (bounds.IsEmpty()) {
// Size the Window and center it at the default size.
window_->CenterWindow(CefSize(kDefaultWidth, kDefaultHeight));
} else {
} else if (SupportsWindowRestore()) {
// Remember the bounds from the previous application run in case the user
// does not move or resize the window during this application run.
last_visible_bounds_ = bounds;
@@ -746,7 +771,7 @@ void ViewsWindow::OnWindowActivationChanged(CefRefPtr<CefWindow> window,
void ViewsWindow::OnWindowBoundsChanged(CefRefPtr<CefWindow> window,
const CefRect& new_bounds) {
if (type_ == WindowType::NORMAL && !window->IsMinimized() &&
if (SupportsWindowRestore() && !window->IsMinimized() &&
!window->IsMaximized() && !window->IsFullscreen()) {
// Track the last visible bounds for window restore purposes.
last_visible_bounds_ = new_bounds;
@@ -833,20 +858,18 @@ bool ViewsWindow::GetTitlebarHeight(CefRefPtr<CefWindow> window,
bool ViewsWindow::CanResize(CefRefPtr<CefWindow> window) {
CEF_REQUIRE_UI_THREAD();
// Only allow resize of normal windows.
return type_ == WindowType::NORMAL;
// Only allow resize of normal and DevTools windows.
return type_ == WindowType::NORMAL || type_ == WindowType::DEVTOOLS;
}
bool ViewsWindow::CanMaximize(CefRefPtr<CefWindow> window) {
CEF_REQUIRE_UI_THREAD();
// Only allow maximize of normal windows.
return type_ == WindowType::NORMAL;
return CanResize(window);
}
bool ViewsWindow::CanMinimize(CefRefPtr<CefWindow> window) {
CEF_REQUIRE_UI_THREAD();
// Only allow minimize of normal windows.
return type_ == WindowType::NORMAL;
return CanResize(window);
}
bool ViewsWindow::OnAccelerator(CefRefPtr<CefWindow> window, int command_id) {
@@ -1271,12 +1294,11 @@ void ViewsWindow::AddControls() {
}
void ViewsWindow::AddAccelerators() {
// Trigger accelerators without first forwarding to web content.
browser_view_->SetPreferAccelerators(true);
// Specify the accelerators to handle. OnAccelerator will be called when the
// accelerator is triggered.
window_->SetAccelerator(ID_QUIT, 'X', false, false, true);
window_->SetAccelerator(ID_QUIT, 'X', /*shift_pressed=*/false,
/*ctrl_pressed=*/false, /*alt_pressed=*/true,
/*high_priority=*/true);
}
void ViewsWindow::SetMenuFocusable(bool focusable) {

View File

@@ -127,6 +127,8 @@ class ViewsWindow : public CefBrowserViewDelegate,
void OnBeforeContextMenu(CefRefPtr<CefMenuModel> model);
void OnExtensionsChanged(const ExtensionSet& extensions);
static bool SupportsWindowRestore(WindowType type);
bool SupportsWindowRestore() const;
bool GetWindowRestorePreferences(cef_show_state_t& show_state,
std::optional<CefRect>& dip_bounds);
void SetTitlebarHeight(const std::optional<float>& height);

View File

@@ -0,0 +1,498 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>Binary vs String Transfer Benchmark</title>
<script src="https://cdn.plot.ly/plotly-2.26.0.min.js"></script>
<style>
body {
font-family: Tahoma, Serif;
font-size: 10pt;
}
.info {
font-size: 12pt;
}
.left {
text-align: left;
}
.right {
text-align: right;
}
.positive {
color: green;
font-weight: bold;
}
.negative {
color: red;
font-weight: bold;
}
.center {
text-align: center;
}
table.resultTable {
border: 1px solid black;
border-collapse: collapse;
empty-cells: show;
width: 100%;
}
table.resultTable td {
padding: 2px 4px;
border: 1px solid black;
}
table.resultTable > thead > tr {
font-weight: bold;
background: lightblue;
}
table.resultTable > tbody > tr:nth-child(odd) {
background: white;
}
table.resultTable > tbody > tr:nth-child(even) {
background: lightgray;
}
.hide {
display: none;
}
</style>
</head>
<body background-color="white">
<h1>Binary vs String Transfer Benchmark</h1>
<table>
<tr>
<td>
<p class="info">
This benchmark evaluates the message transfer speed between the
renderer process and the browser process. <br />It compares the
performance of binary and string message transfer.
</p>
<p class="info">
<b>Note:</b> There is no progress indication of the tests because it
significantly influences measurements. <br />It usually takes 30
seconds (for 300 samples) to complete the tests.
</p>
</td>
</tr>
<tr>
<td>
Samples:
<input
id="sSamples"
type="text"
value="300"
required
pattern="[0-9]+"
/>
<button id="sRun" autofocus onclick="runTestSuite()">Run</button>
</td>
</tr>
</table>
<div style="padding-top: 10px; padding-bottom: 10px">
<table id="resultTable" class="resultTable">
<thead>
<tr>
<td class="center" style="width: 8%">Message Size</td>
<td class="center" style="width: 8%">
String Round Trip Avg,&nbsp;ms
</td>
<td class="center" style="width: 8%">
Binary Round Trip Avg,&nbsp;ms
</td>
<td class="center" style="width: 10%">Relative Trip Difference</td>
<td class="center" style="width: 8%">String Speed,&nbsp;MB/s</td>
<td class="center" style="width: 8%">Binary Speed,&nbsp;MB/s</td>
<td class="center" style="width: 10%">Relative Speed Difference</td>
<td class="center" style="width: 8%">String Standard Deviation</td>
<td class="center" style="width: 8%">Binary Standard Deviation</td>
</tr>
</thead>
<tbody>
<!-- result rows here -->
</tbody>
</table>
</div>
<div id="round_trip_avg_chart">
<!-- Average round trip linear chart will be drawn inside this DIV -->
</div>
<div id="box_plot_chart">
<!-- Box plot of round trip time will be drawn inside this DIV -->
</div>
<script type="text/javascript">
let tests = [];
let box_plot_test_data = [];
let round_trip_avg_plot_data = [];
function nextTestSuite(testIndex) {
const nextTestIndex = testIndex + 1;
setTimeout(execTestSuite, 0, nextTestIndex);
}
function generateRandomString(size) {
// Symbols that will be encoded as two bytes in UTF-8
// so we compare transfer of the same amount of bytes
const characters =
"АБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯабвгдеёжзийклмнопрстуфхцчшщъыьэюя";
let randomString = "";
for (let i = 0; i < size; i++) {
const randomIndex = Math.floor(Math.random() * characters.length);
randomString += characters.charAt(randomIndex);
}
return randomString;
}
function generateRandomArrayBuffer(size) {
const buffer = new ArrayBuffer(size);
const uint8Array = new Uint8Array(buffer);
for (let i = 0; i < uint8Array.length; i++) {
uint8Array[i] = Math.floor(Math.random() * 256);
}
return buffer;
}
function reportError(errorCode, errorMessage) {
console.error(`ErrorCode:${errorCode} Message:${errorMessage}`);
}
function sendString(size, testIndex) {
const request = generateRandomString(size);
const startTime = performance.now();
const onSuccess = (response) => {
const roundTrip = performance.now() - startTime;
const test = tests[testIndex];
test.totalRoundTrip += roundTrip;
test.sample++;
box_plot_test_data[testIndex].x.push(roundTrip);
setTimeout(execTest, 0, testIndex);
};
window.cefQuery({
request: request,
onSuccess: onSuccess,
onFailure: reportError,
});
}
function sendArrayBuffer(size, testIndex) {
const request = generateRandomArrayBuffer(size);
const startTime = performance.now();
const onSuccess = (response) => {
const roundTrip = performance.now() - startTime;
const test = tests[testIndex];
test.totalRoundTrip += roundTrip;
test.sample++;
box_plot_test_data[testIndex].x.push(roundTrip);
setTimeout(execTest, 0, testIndex);
};
window.cefQuery({
request: request,
onSuccess: onSuccess,
onFailure: reportError,
});
}
function getStandardDeviation(array, mean) {
const n = array.length;
if (n < 5) return null;
return Math.sqrt(
array.map((x) => Math.pow(x - mean, 2)).reduce((a, b) => a + b) /
(n - 1)
);
}
function execTest(testIndex) {
const test = tests[testIndex];
if (test.sample >= test.totalSamples) {
return nextTestSuite(testIndex);
}
test.func(test.length, test.index);
}
function column(prepared, value) {
return (
"<td class='right'>" + (!prepared ? "-" : value.toFixed(3)) + "</td>"
);
}
function relativeDiffColumn(prepared, value, isBiggerBetter) {
if (!prepared) return "<td class='right'>-</td>";
const isPositive = value >= 0 == isBiggerBetter;
return [
"<td class='right ",
isPositive ? "positive" : "negative",
"'>",
value > 0 ? "+" : "",
value.toFixed(2),
"%</td>",
].join("");
}
function displayResult(test) {
const id = "testResultRow_" + test.index;
const markup = [
"<tr id='",
id,
"'>",
"<td class='left'>",
test.name,
"</td>",
column(test.prepared, test.avgRoundTrip),
column(test.prepared, test.avgRoundTripBin),
relativeDiffColumn(test.prepared, test.relativeTripDiff, false),
column(test.prepared, test.speed),
column(test.prepared, test.speedBinary),
relativeDiffColumn(test.prepared, test.relativeSpeedDiff, true),
"<td class='right'>",
!test.prepared || test.stdDeviation == null
? "-"
: test.stdDeviation.toFixed(3),
"</td>",
"<td class='right'>",
!test.prepared || test.stdDeviationBinary == null
? "-"
: test.stdDeviationBinary.toFixed(3),
"</td>",
"</tr>",
].join("");
const row = document.getElementById(id);
if (row) {
row.outerHTML = markup;
} else {
const tbody = document.getElementById("resultTable").tBodies[0];
tbody.insertAdjacentHTML("beforeEnd", markup);
}
}
function relativeDiff(left, right) {
if (right != 0) {
return ((left - right) / right) * 100;
}
return 0;
}
function buildTestResults(tests) {
testResults = [];
let oldRoundTrip = {
x: [],
y: [],
type: "scatter",
name: "String",
};
let newRoundTrip = {
x: [],
y: [],
type: "scatter",
name: "Binary",
};
for (let i = 0; i < tests.length / 2; i++) {
const index = testResults.length;
// Tests are in pairs - String and Binary
const test = tests[i * 2];
const testBin = tests[i * 2 + 1];
const avgRoundTrip = test.totalRoundTrip / test.totalSamples;
const avgRoundTripBin = testBin.totalRoundTrip / testBin.totalSamples;
const relativeTripDiff = relativeDiff(avgRoundTripBin, avgRoundTrip);
// In MB/s
const speed = test.byteSize / (avgRoundTrip * 1000);
const speedBinary = testBin.byteSize / (avgRoundTripBin * 1000);
const relativeSpeedDiff = relativeDiff(speedBinary, speed);
const stdDeviation = getStandardDeviation(
box_plot_test_data[test.index].x,
avgRoundTrip
);
const stdDeviationBinary = getStandardDeviation(
box_plot_test_data[testBin.index].x,
avgRoundTripBin
);
testResults.push({
name: humanFileSize(test.byteSize),
index: index,
prepared: true,
avgRoundTrip: avgRoundTrip,
avgRoundTripBin: avgRoundTripBin,
relativeTripDiff: relativeTripDiff,
speed: speed,
speedBinary: speedBinary,
relativeSpeedDiff: relativeSpeedDiff,
stdDeviation: stdDeviation,
stdDeviationBinary: stdDeviationBinary,
});
oldRoundTrip.x.push(test.byteSize);
newRoundTrip.x.push(test.byteSize);
oldRoundTrip.y.push(avgRoundTrip);
newRoundTrip.y.push(avgRoundTripBin);
}
round_trip_avg_plot_data = [oldRoundTrip, newRoundTrip];
return testResults;
}
function buildEmptyTestResults(tests) {
testResults = [];
for (let i = 0; i < tests.length / 2; i++) {
const index = testResults.length;
const test = tests[i * 2];
testResults.push({
name: humanFileSize(test.byteSize),
index: index,
prepared: false,
});
}
return testResults;
}
function resetTestsResults(totalSamples) {
if (totalSamples <= 0) totalSamples = 1;
// Reset tests results
tests.forEach((test) => {
test.sample = 0;
test.totalRoundTrip = 0;
test.totalSamples = totalSamples;
});
testResults = buildEmptyTestResults(tests);
testResults.forEach((result) => displayResult(result));
round_trip_avg_plot_data = [];
box_plot_test_data.forEach((data) => {
data.x = [];
});
}
function queueTest(name, byteSize, length, testFunc) {
const testIndex = tests.length;
test = {
name: name,
byteSize: byteSize,
length: length,
index: testIndex,
sample: 0,
totalRoundTrip: 0,
func: testFunc,
};
tests.push(test);
box_plot_test_data.push({
x: [],
type: "box",
boxpoints: "all",
name: name,
jitter: 0.3,
pointpos: -1.8,
});
}
function execTestSuite(testIndex) {
if (testIndex < tests.length) {
execTest(testIndex);
} else {
testsRunFinished();
}
}
function startTests() {
// Let the updated table render before starting the tests
setTimeout(execTestSuite, 200, 0);
}
function execQueuedTests(totalSamples) {
resetTestsResults(totalSamples);
startTests();
}
function setSettingsState(disabled) {
document.getElementById("sSamples").disabled = disabled;
document.getElementById("sRun").disabled = disabled;
}
function testsRunFinished() {
testResults = buildTestResults(tests);
testResults.forEach((result) => displayResult(result));
const round_trip_layout = {
title: "Average round trip, μs (Smaller Better)",
};
Plotly.newPlot(
"round_trip_avg_chart",
round_trip_avg_plot_data,
round_trip_layout
);
const box_plot_layout = {
title: "Round Trip Time, μs",
};
Plotly.newPlot("box_plot_chart", box_plot_test_data, box_plot_layout);
setSettingsState(false);
}
function humanFileSize(bytes) {
const step = 1024;
const originalBytes = bytes;
if (Math.abs(bytes) < step) {
return bytes + " B";
}
const units = [" KB", " MB", " GB"];
let u = -1;
let count = 0;
do {
bytes /= step;
u += 1;
count += 1;
} while (Math.abs(bytes) >= step && u < units.length - 1);
return bytes.toString() + units[u];
}
window.runTestSuite = () => {
Plotly.purge("round_trip_avg_chart");
Plotly.purge("box_plot_chart");
setSettingsState(true);
const totalSamples = parseInt(
document.getElementById("sSamples").value
);
execQueuedTests(totalSamples);
};
const totalSamples = parseInt(document.getElementById("sSamples").value);
queueTest("Empty String", 0, 0, sendString);
queueTest("Empty Binary", 0, 0, sendArrayBuffer);
for (let byteSize = 8; byteSize <= 512 * 1024; byteSize *= 2) {
// Byte size of a string is twice its length because of UTF-16 encoding
const stringLen = byteSize / 2;
queueTest(
humanFileSize(byteSize) + " String",
byteSize,
stringLen,
sendString
);
queueTest(
humanFileSize(byteSize) + " Binary",
byteSize,
byteSize,
sendArrayBuffer
);
}
resetTestsResults(totalSamples);
</script>
</body>
</html>

View File

@@ -9,6 +9,7 @@
<li><a href="http://webkit.org/blog-files/3d-transforms/poster-circle.html">Accelerated Layers</a></li>
<li><a href="https://jigsaw.w3.org/HTTP/Basic/">Authentication (Basic)</a> - credentials returned via GetAuthCredentials</li>
<li><a href="https://jigsaw.w3.org/HTTP/Digest/">Authentication (Digest)</a> - credentials returned via GetAuthCredentials</li>
<li><a href="binary_transfer">Binary vs String Transfer Benchmark</a></li>
<li><a href="http://html5advent2011.digitpaint.nl/3/index.html">Cursors</a></li>
<li><a href="dialogs">Dialogs</a></li>
<li><a href="http://html5demos.com/drag">Drag & Drop</a></li>

View File

@@ -29,6 +29,7 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
// Binary
//
IDS_BINARY_TRANSFER_HTML BINARY "..\\binary_transfer.html"
IDS_BINDING_HTML BINARY "..\\binding.html"
IDS_DIALOGS_HTML BINARY "..\\dialogs.html"
IDS_DRAGGABLE_HTML BINARY "..\\draggable.html"
@@ -228,4 +229,3 @@ END
/////////////////////////////////////////////////////////////////////////////
#endif // not APSTUDIO_INVOKED

View File

@@ -2,6 +2,12 @@
<html lang="en-US">
<head>
<title>Window Test</title>
<style>
/* Background becomes pink in fullscreen mode. */
:fullscreen {
background: pink;
}
</style>
<script>
function setup() {
if (location.hostname == 'tests' || location.hostname == 'localhost')
@@ -38,10 +44,18 @@ function restore() {
setTimeout(function() { send_message('Restore'); }, 1000);
}
function fullscreen() {
function fullscreenWindow() {
send_message('Fullscreen');
}
function fullscreenBrowser() {
if (document.fullscreenElement) {
document.exitFullscreen();
} else {
document.getElementById('form').requestFullscreen();
}
}
function position() {
var x = parseInt(document.getElementById('x').value);
var y = parseInt(document.getElementById('y').value);
@@ -68,7 +82,8 @@ Click a button to perform the associated window action.
<br/><input type="button" onclick="minimize();" value="Minimize">
<br/><input type="button" onclick="maximize();" value="Maximize">
<br/><input type="button" onclick="restore();" value="Restore"> (minimizes and then restores the window as topmost)
<br/><input type="button" onclick="fullscreen();" value="Toggle Fullscreen"> (works with Views)
<br/><input type="button" onclick="fullscreenWindow();" value="Toggle Window Fullscreen"> (works with Views)
<br/><input type="button" onclick="fullscreenBrowser();" value="Toggle Browser Fullscreen"> (uses <a href="https://developer.mozilla.org/en-US/docs/Web/API/Fullscreen_API" target="_new">Fullscreen API</a>; background turns pink)
<br/><input type="button" onclick="position();" value="Set Position">
X: <input type="text" size="4" id="x" value="200">
Y: <input type="text" size="4" id="y" value="100">

View File

@@ -0,0 +1,136 @@
// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
// reserved. Use of this source code is governed by a BSD-style license that
// can be found in the LICENSE file.
#include "tests/ceftests/message_router_unittest_utils.h"
namespace {
constexpr size_t kMsgSizeThresholdInBytes = 16000;
class BinaryTestHandler final : public SingleLoadTestHandler {
public:
explicit BinaryTestHandler(size_t message_size)
: message_size_(message_size) {}
std::string GetMainHTML() override {
return "<html><body><script>\n"
"function generateRandomArrayBuffer(size) {\n"
" const buffer = new ArrayBuffer(size);\n"
" const uint8Array = new Uint8Array(buffer);\n"
" for (let i = 0; i < uint8Array.length; i++) {\n"
" uint8Array[i] = Math.floor(Math.random() * 256);\n"
" }\n"
" return buffer;\n"
"}\n"
"function isEqualArrayBuffers(left, right) {\n"
" if (left.byteLength !== right.byteLength) { return false; }\n"
" const leftView = new DataView(left);\n"
" const rightView = new DataView(right);\n"
" for (let i = 0; i < left.byteLength; i++) {\n"
" if (leftView.getUint8(i) !== rightView.getUint8(i)) {\n"
" return false;\n"
" }\n"
" }\n"
" return true;\n"
"}\n"
"const request = generateRandomArrayBuffer(" +
std::to_string(message_size_) +
")\n"
"window." +
std::string(kJSQueryFunc) +
"({\n request: request,\n"
" persistent: false,\n"
" onSuccess: (response) => {\n"
" if (!isEqualArrayBuffers(request, response)) {\n"
" window.mrtNotify('error-ArrayBuffersDiffer');\n"
" } else {\n"
" window.mrtNotify('success');\n"
" }\n"
" },\n"
" onFailure: (errorCode, errorMessage) => {\n"
" window.mrtNotify('error-onFailureCalled');\n"
" }\n"
"});\n</script></body></html>";
}
void OnNotify(CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
const std::string& message) override {
AssertMainBrowser(browser);
AssertMainFrame(frame);
// OnNotify only be called once.
EXPECT_FALSE(got_notify_);
got_notify_.yes();
EXPECT_EQ("success", message);
DestroyTest();
}
bool OnQuery(CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
int64_t query_id,
CefRefPtr<const CefBinaryBuffer> request,
bool persistent,
CefRefPtr<Callback> callback) override {
AssertMainBrowser(browser);
AssertMainFrame(frame);
EXPECT_NE(0, query_id);
EXPECT_FALSE(persistent);
EXPECT_EQ(message_size_, request->GetSize());
got_on_query_.yes();
callback->Success(request->GetData(), request->GetSize());
return true;
}
void DestroyTest() override {
EXPECT_TRUE(got_notify_);
EXPECT_TRUE(got_on_query_);
TestHandler::DestroyTest();
}
private:
const size_t message_size_;
TrackCallback got_on_query_;
TrackCallback got_notify_;
};
using TestHandlerPtr = CefRefPtr<BinaryTestHandler>;
} // namespace
TEST(MessageRouterTest, BinaryMessageEmpty) {
const auto message_size = 0;
TestHandlerPtr handler = new BinaryTestHandler(message_size);
handler->SetMessageSizeThreshold(kMsgSizeThresholdInBytes);
handler->ExecuteTest();
ReleaseAndWaitForDestructor(handler);
}
TEST(MessageRouterTest, BinaryMessageUnderThresholdSize) {
const auto under_threshold = kMsgSizeThresholdInBytes - 1;
TestHandlerPtr handler = new BinaryTestHandler(under_threshold);
handler->SetMessageSizeThreshold(kMsgSizeThresholdInBytes);
handler->ExecuteTest();
ReleaseAndWaitForDestructor(handler);
}
TEST(MessageRouterTest, BinaryMessageOverThresholdSize) {
const auto over_threshold = kMsgSizeThresholdInBytes + 1;
TestHandlerPtr handler = new BinaryTestHandler(over_threshold);
handler->SetMessageSizeThreshold(kMsgSizeThresholdInBytes);
handler->ExecuteTest();
ReleaseAndWaitForDestructor(handler);
}

Some files were not shown because too many files have changed in this diff Show More