mirror of
https://bitbucket.org/chromiumembedded/cef
synced 2025-02-16 20:20:51 +01:00
Add a shared memory variant of CefProcessMessage (fixes issue #3126)
CefSharedProcessMessageBuilder supports creation of a CefProcessMessage backed by a CefSharedMemoryRegion. Performance tests comparing the existing ArgumentList approach and the new SharedMemoryRegion approach have been added to cefclient at http://tests/ipc_performance. CefMessageRouter has been updated to use SharedMemoryRegion as transport for larger message payloads. The threshold is configurable via |CefMessageRouterConfig.message_size_threshold|. To test: run `ceftests --gtest_filter=SendSharedProcessMessageTest.*:SharedProcessMessageTest.*:MessageRouterTest.Threshold*`
This commit is contained in:
parent
a931d49f3e
commit
81e892d19e
2
BUILD.gn
2
BUILD.gn
@ -814,6 +814,8 @@ static_library("libcef_static") {
|
||||
"libcef/common/parser_impl.cc",
|
||||
"libcef/common/process_message_impl.cc",
|
||||
"libcef/common/process_message_impl.h",
|
||||
"libcef/common/process_message_smr_impl.cc",
|
||||
"libcef/common/process_message_smr_impl.h",
|
||||
"libcef/common/request_impl.cc",
|
||||
"libcef/common/request_impl.h",
|
||||
"libcef/common/resource_bundle_delegate.cc",
|
||||
|
@ -8,7 +8,7 @@
|
||||
# by hand. See the translator.README.txt file in the tools directory for
|
||||
# more information.
|
||||
#
|
||||
# $hash=f8ae899cc69a48e9878fa4db2fcc3b7e54230062$
|
||||
# $hash=f374acb217db4183917195716d5522a9eb897cdf$
|
||||
#
|
||||
|
||||
{
|
||||
@ -75,6 +75,8 @@
|
||||
'include/cef_response_filter.h',
|
||||
'include/cef_scheme.h',
|
||||
'include/cef_server.h',
|
||||
'include/cef_shared_memory_region.h',
|
||||
'include/cef_shared_process_message_builder.h',
|
||||
'include/cef_ssl_info.h',
|
||||
'include/cef_ssl_status.h',
|
||||
'include/cef_stream.h',
|
||||
@ -175,6 +177,8 @@
|
||||
'include/capi/cef_response_filter_capi.h',
|
||||
'include/capi/cef_scheme_capi.h',
|
||||
'include/capi/cef_server_capi.h',
|
||||
'include/capi/cef_shared_memory_region_capi.h',
|
||||
'include/capi/cef_shared_process_message_builder_capi.h',
|
||||
'include/capi/cef_ssl_info_capi.h',
|
||||
'include/capi/cef_ssl_status_capi.h',
|
||||
'include/capi/cef_stream_capi.h',
|
||||
@ -442,6 +446,10 @@
|
||||
'libcef_dll/ctocpp/server_handler_ctocpp.h',
|
||||
'libcef_dll/ctocpp/set_cookie_callback_ctocpp.cc',
|
||||
'libcef_dll/ctocpp/set_cookie_callback_ctocpp.h',
|
||||
'libcef_dll/cpptoc/shared_memory_region_cpptoc.cc',
|
||||
'libcef_dll/cpptoc/shared_memory_region_cpptoc.h',
|
||||
'libcef_dll/cpptoc/shared_process_message_builder_cpptoc.cc',
|
||||
'libcef_dll/cpptoc/shared_process_message_builder_cpptoc.h',
|
||||
'libcef_dll/cpptoc/stream_reader_cpptoc.cc',
|
||||
'libcef_dll/cpptoc/stream_reader_cpptoc.h',
|
||||
'libcef_dll/cpptoc/stream_writer_cpptoc.cc',
|
||||
@ -754,6 +762,10 @@
|
||||
'libcef_dll/cpptoc/server_handler_cpptoc.h',
|
||||
'libcef_dll/cpptoc/set_cookie_callback_cpptoc.cc',
|
||||
'libcef_dll/cpptoc/set_cookie_callback_cpptoc.h',
|
||||
'libcef_dll/ctocpp/shared_memory_region_ctocpp.cc',
|
||||
'libcef_dll/ctocpp/shared_memory_region_ctocpp.h',
|
||||
'libcef_dll/ctocpp/shared_process_message_builder_ctocpp.cc',
|
||||
'libcef_dll/ctocpp/shared_process_message_builder_ctocpp.h',
|
||||
'libcef_dll/ctocpp/stream_reader_ctocpp.cc',
|
||||
'libcef_dll/ctocpp/stream_reader_ctocpp.h',
|
||||
'libcef_dll/ctocpp/stream_writer_ctocpp.cc',
|
||||
|
@ -177,6 +177,8 @@
|
||||
'tests/shared/browser/resource_util.h',
|
||||
],
|
||||
'shared_sources_common': [
|
||||
'tests/shared/common/binary_value_utils.cc',
|
||||
'tests/shared/common/binary_value_utils.h',
|
||||
'tests/shared/common/client_app.cc',
|
||||
'tests/shared/common/client_app.h',
|
||||
'tests/shared/common/client_app_other.cc',
|
||||
@ -289,6 +291,8 @@
|
||||
'tests/cefclient/renderer/client_app_delegates_renderer.cc',
|
||||
'tests/cefclient/renderer/client_renderer.cc',
|
||||
'tests/cefclient/renderer/client_renderer.h',
|
||||
'tests/cefclient/renderer/ipc_performance_test.cc',
|
||||
'tests/cefclient/renderer/ipc_performance_test.h',
|
||||
'tests/cefclient/renderer/performance_test.cc',
|
||||
'tests/cefclient/renderer/performance_test.h',
|
||||
'tests/cefclient/renderer/performance_test_setup.h',
|
||||
@ -298,6 +302,7 @@
|
||||
'tests/cefclient/resources/binding.html',
|
||||
'tests/cefclient/resources/dialogs.html',
|
||||
'tests/cefclient/resources/draggable.html',
|
||||
'tests/cefclient/resources/ipc_performance.html',
|
||||
'tests/cefclient/resources/localstorage.html',
|
||||
'tests/cefclient/resources/logo.png',
|
||||
'tests/cefclient/resources/media_router.html',
|
||||
@ -476,7 +481,12 @@
|
||||
'tests/ceftests/jsdialog_unittest.cc',
|
||||
'tests/ceftests/life_span_unittest.cc',
|
||||
'tests/ceftests/media_access_unittest.cc',
|
||||
'tests/ceftests/message_router_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',
|
||||
'tests/ceftests/message_router_threshold_unittest.cc',
|
||||
'tests/ceftests/message_router_unittest_utils.cc',
|
||||
'tests/ceftests/message_router_unittest_utils.h',
|
||||
'tests/ceftests/navigation_unittest.cc',
|
||||
'tests/ceftests/os_rendering_unittest.cc',
|
||||
'tests/ceftests/osr_accessibility_unittest.cc',
|
||||
@ -499,6 +509,8 @@
|
||||
'tests/ceftests/scheme_handler_unittest.cc',
|
||||
'tests/ceftests/scoped_temp_dir_unittest.cc',
|
||||
'tests/ceftests/server_unittest.cc',
|
||||
'tests/ceftests/send_shared_process_message_unittest.cc',
|
||||
"tests/ceftests/shared_process_message_unittest.cc",
|
||||
'tests/ceftests/stream_unittest.cc',
|
||||
'tests/ceftests/stream_resource_handler_unittest.cc',
|
||||
'tests/ceftests/string_unittest.cc',
|
||||
@ -564,7 +576,12 @@
|
||||
'tests/ceftests/dom_unittest.cc',
|
||||
'tests/ceftests/frame_unittest.cc',
|
||||
'tests/ceftests/media_access_unittest.cc',
|
||||
'tests/ceftests/message_router_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',
|
||||
'tests/ceftests/message_router_threshold_unittest.cc',
|
||||
'tests/ceftests/message_router_unittest_utils.cc',
|
||||
'tests/ceftests/message_router_unittest_utils.h',
|
||||
'tests/ceftests/navigation_unittest.cc',
|
||||
'tests/ceftests/pdf_viewer_unittest.cc',
|
||||
'tests/ceftests/preference_unittest.cc',
|
||||
@ -576,6 +593,8 @@
|
||||
'tests/ceftests/routing_test_handler.cc',
|
||||
'tests/ceftests/routing_test_handler.h',
|
||||
'tests/ceftests/scheme_handler_unittest.cc',
|
||||
'tests/ceftests/send_shared_process_message_unittest.cc',
|
||||
"tests/ceftests/shared_process_message_unittest.cc",
|
||||
'tests/ceftests/urlrequest_unittest.cc',
|
||||
'tests/ceftests/test_handler.cc',
|
||||
'tests/ceftests/test_handler.h',
|
||||
|
@ -33,7 +33,7 @@
|
||||
// by hand. See the translator.README.txt file in the tools directory for
|
||||
// more information.
|
||||
//
|
||||
// $hash=2549ea10cd3a41bc04ab81bad24eb12787de68b9$
|
||||
// $hash=026a7f827962222a1df8b62a8e7bdfbf4dce27e0$
|
||||
//
|
||||
|
||||
#ifndef CEF_INCLUDE_CAPI_CEF_PROCESS_MESSAGE_CAPI_H_
|
||||
@ -41,6 +41,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "include/capi/cef_base_capi.h"
|
||||
#include "include/capi/cef_shared_memory_region_capi.h"
|
||||
#include "include/capi/cef_values_capi.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
@ -69,7 +70,8 @@ typedef struct _cef_process_message_t {
|
||||
int(CEF_CALLBACK* is_read_only)(struct _cef_process_message_t* self);
|
||||
|
||||
///
|
||||
// Returns a writable copy of this object.
|
||||
// Returns a writable copy of this object. Returns nullptr when message
|
||||
// contains a shared memory region.
|
||||
///
|
||||
struct _cef_process_message_t*(CEF_CALLBACK* copy)(
|
||||
struct _cef_process_message_t* self);
|
||||
@ -82,10 +84,18 @@ typedef struct _cef_process_message_t {
|
||||
struct _cef_process_message_t* self);
|
||||
|
||||
///
|
||||
// Returns the list of arguments.
|
||||
// Returns the list of arguments. Returns nullptr when message contains a
|
||||
// shared memory region.
|
||||
///
|
||||
struct _cef_list_value_t*(CEF_CALLBACK* get_argument_list)(
|
||||
struct _cef_process_message_t* self);
|
||||
|
||||
///
|
||||
// Returns the shared memory region. Returns nullptr when message contains an
|
||||
// argument list.
|
||||
///
|
||||
struct _cef_shared_memory_region_t*(CEF_CALLBACK* get_shared_memory_region)(
|
||||
struct _cef_process_message_t* self);
|
||||
} cef_process_message_t;
|
||||
|
||||
///
|
||||
|
79
include/capi/cef_shared_memory_region_capi.h
Normal file
79
include/capi/cef_shared_memory_region_capi.h
Normal file
@ -0,0 +1,79 @@
|
||||
// Copyright (c) 2022 Marshall A. Greenblatt. All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the name Chromium Embedded
|
||||
// Framework nor the names of its contributors may be used to endorse
|
||||
// or promote products derived from this software without specific prior
|
||||
// written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// ---------------------------------------------------------------------------
|
||||
//
|
||||
// This file was generated by the CEF translator tool and should not edited
|
||||
// by hand. See the translator.README.txt file in the tools directory for
|
||||
// more information.
|
||||
//
|
||||
// $hash=212f13ac6baeeefb86f1648d1e18ccba95fd5f79$
|
||||
//
|
||||
|
||||
#ifndef CEF_INCLUDE_CAPI_CEF_SHARED_MEMORY_REGION_CAPI_H_
|
||||
#define CEF_INCLUDE_CAPI_CEF_SHARED_MEMORY_REGION_CAPI_H_
|
||||
#pragma once
|
||||
|
||||
#include "include/capi/cef_base_capi.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
///
|
||||
// Structure that wraps platform-dependent share memory region mapping.
|
||||
///
|
||||
typedef struct _cef_shared_memory_region_t {
|
||||
///
|
||||
// Base structure.
|
||||
///
|
||||
cef_base_ref_counted_t base;
|
||||
|
||||
///
|
||||
// Returns true (1) if the mapping is valid.
|
||||
///
|
||||
int(CEF_CALLBACK* is_valid)(struct _cef_shared_memory_region_t* self);
|
||||
|
||||
///
|
||||
// Returns the size of the mapping in bytes. Returns 0 for invalid instances.
|
||||
///
|
||||
size_t(CEF_CALLBACK* size)(struct _cef_shared_memory_region_t* self);
|
||||
|
||||
///
|
||||
// Returns the pointer to the memory. Returns nullptr for invalid instances.
|
||||
// The returned pointer is only valid for the life span of this object.
|
||||
///
|
||||
const void*(CEF_CALLBACK* memory)(struct _cef_shared_memory_region_t* self);
|
||||
} cef_shared_memory_region_t;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // CEF_INCLUDE_CAPI_CEF_SHARED_MEMORY_REGION_CAPI_H_
|
101
include/capi/cef_shared_process_message_builder_capi.h
Normal file
101
include/capi/cef_shared_process_message_builder_capi.h
Normal file
@ -0,0 +1,101 @@
|
||||
// Copyright (c) 2022 Marshall A. Greenblatt. All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the name Chromium Embedded
|
||||
// Framework nor the names of its contributors may be used to endorse
|
||||
// or promote products derived from this software without specific prior
|
||||
// written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// ---------------------------------------------------------------------------
|
||||
//
|
||||
// This file was generated by the CEF translator tool and should not edited
|
||||
// by hand. See the translator.README.txt file in the tools directory for
|
||||
// more information.
|
||||
//
|
||||
// $hash=0ed88d26dab045ebef0f4f4ae209e7f11206a242$
|
||||
//
|
||||
|
||||
#ifndef CEF_INCLUDE_CAPI_CEF_SHARED_PROCESS_MESSAGE_BUILDER_CAPI_H_
|
||||
#define CEF_INCLUDE_CAPI_CEF_SHARED_PROCESS_MESSAGE_BUILDER_CAPI_H_
|
||||
#pragma once
|
||||
|
||||
#include "include/capi/cef_process_message_capi.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
///
|
||||
// Structure that builds a cef_process_message_t containing a shared memory
|
||||
// region. This structure is not thread-safe but may be used exclusively on a
|
||||
// different thread from the one which constructed it.
|
||||
///
|
||||
typedef struct _cef_shared_process_message_builder_t {
|
||||
///
|
||||
// Base structure.
|
||||
///
|
||||
cef_base_ref_counted_t base;
|
||||
|
||||
///
|
||||
// Returns true (1) if the builder is valid.
|
||||
///
|
||||
int(CEF_CALLBACK* is_valid)(
|
||||
struct _cef_shared_process_message_builder_t* self);
|
||||
|
||||
///
|
||||
// Returns the size of the shared memory region in bytes. Returns 0 for
|
||||
// invalid instances.
|
||||
///
|
||||
size_t(CEF_CALLBACK* size)(
|
||||
struct _cef_shared_process_message_builder_t* self);
|
||||
|
||||
///
|
||||
// Returns the pointer to the writable memory. Returns nullptr for invalid
|
||||
// instances. The returned pointer is only valid for the life span of this
|
||||
// object.
|
||||
///
|
||||
void*(CEF_CALLBACK* memory)(
|
||||
struct _cef_shared_process_message_builder_t* self);
|
||||
|
||||
///
|
||||
// Creates a new cef_process_message_t from the data provided to the builder.
|
||||
// Returns nullptr for invalid instances. Invalidates the builder instance.
|
||||
///
|
||||
struct _cef_process_message_t*(CEF_CALLBACK* build)(
|
||||
struct _cef_shared_process_message_builder_t* self);
|
||||
} cef_shared_process_message_builder_t;
|
||||
|
||||
///
|
||||
// Creates a new cef_shared_process_message_builder_t with the specified |name|
|
||||
// and shared memory region of specified |byte_size|.
|
||||
///
|
||||
CEF_EXPORT cef_shared_process_message_builder_t*
|
||||
cef_shared_process_message_builder_create(const cef_string_t* name,
|
||||
size_t byte_size);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // CEF_INCLUDE_CAPI_CEF_SHARED_PROCESS_MESSAGE_BUILDER_CAPI_H_
|
@ -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 "794a4cf2ad83db17558bd2ca2d721487875a37e8"
|
||||
#define CEF_API_HASH_UNIVERSAL "d3fdeba02acc73ac571a1be658789f2ff770f09c"
|
||||
#if defined(OS_WIN)
|
||||
#define CEF_API_HASH_PLATFORM "aa627f71c1cbdf13beeb3fe740337f4cc1cb5dc5"
|
||||
#define CEF_API_HASH_PLATFORM "94db0746536862260c9b47d54128a744dbb29fcf"
|
||||
#elif defined(OS_MAC)
|
||||
#define CEF_API_HASH_PLATFORM "6bda80f2ee107a22780193a7af9101eb5a4db8a0"
|
||||
#define CEF_API_HASH_PLATFORM "1c8d61e3bee1c974a2f71688bbdcfc0f6f01d457"
|
||||
#elif defined(OS_LINUX)
|
||||
#define CEF_API_HASH_PLATFORM "c83b942ce72835d0ea01bfc4cab3928b92abdb85"
|
||||
#define CEF_API_HASH_PLATFORM "6d9e52b9e54ded43a7e0dfcf80b6f40ec75f3215"
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
@ -39,6 +39,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "include/cef_base.h"
|
||||
#include "include/cef_shared_memory_region.h"
|
||||
#include "include/cef_values.h"
|
||||
|
||||
typedef cef_process_id_t CefProcessId;
|
||||
@ -71,6 +72,7 @@ class CefProcessMessage : public virtual CefBaseRefCounted {
|
||||
|
||||
///
|
||||
// Returns a writable copy of this object.
|
||||
// Returns nullptr when message contains a shared memory region.
|
||||
///
|
||||
/*--cef()--*/
|
||||
virtual CefRefPtr<CefProcessMessage> Copy() = 0;
|
||||
@ -83,9 +85,17 @@ class CefProcessMessage : public virtual CefBaseRefCounted {
|
||||
|
||||
///
|
||||
// Returns the list of arguments.
|
||||
// Returns nullptr when message contains a shared memory region.
|
||||
///
|
||||
/*--cef()--*/
|
||||
virtual CefRefPtr<CefListValue> GetArgumentList() = 0;
|
||||
|
||||
///
|
||||
// Returns the shared memory region.
|
||||
// Returns nullptr when message contains an argument list.
|
||||
///
|
||||
/*--cef()--*/
|
||||
virtual CefRefPtr<CefSharedMemoryRegion> GetSharedMemoryRegion() = 0;
|
||||
};
|
||||
|
||||
#endif // CEF_INCLUDE_CEF_MESSAGE_H_
|
||||
|
69
include/cef_shared_memory_region.h
Normal file
69
include/cef_shared_memory_region.h
Normal file
@ -0,0 +1,69 @@
|
||||
// Copyright (c) 2022 Marshall A. Greenblatt. All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the name Chromium Embedded
|
||||
// Framework nor the names of its contributors may be used to endorse
|
||||
// or promote products derived from this software without specific prior
|
||||
// written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// ---------------------------------------------------------------------------
|
||||
//
|
||||
// The contents of this file must follow a specific format in order to
|
||||
// support the CEF translator tool. See the translator.README.txt file in the
|
||||
// tools directory for more information.
|
||||
//
|
||||
|
||||
#ifndef CEF_INCLUDE_CEF_SHARED_MEMORY_REGION_H_
|
||||
#define CEF_INCLUDE_CEF_SHARED_MEMORY_REGION_H_
|
||||
#pragma once
|
||||
|
||||
#include "include/cef_base.h"
|
||||
|
||||
///
|
||||
// Class that wraps platform-dependent share memory region mapping.
|
||||
///
|
||||
/*--cef(source=library)--*/
|
||||
class CefSharedMemoryRegion : public virtual CefBaseRefCounted {
|
||||
public:
|
||||
///
|
||||
// Returns true if the mapping is valid.
|
||||
///
|
||||
/*--cef()--*/
|
||||
virtual bool IsValid() = 0;
|
||||
|
||||
///
|
||||
// Returns the size of the mapping in bytes. Returns 0 for invalid instances.
|
||||
///
|
||||
/*--cef()--*/
|
||||
virtual size_t Size() = 0;
|
||||
|
||||
///
|
||||
// Returns the pointer to the memory. Returns nullptr for invalid instances.
|
||||
// The returned pointer is only valid for the life span of this object.
|
||||
///
|
||||
/*--cef()--*/
|
||||
virtual const void* Memory() = 0;
|
||||
};
|
||||
|
||||
#endif // CEF_INCLUDE_CEF_SHARED_MEMORY_REGION_H_
|
87
include/cef_shared_process_message_builder.h
Normal file
87
include/cef_shared_process_message_builder.h
Normal file
@ -0,0 +1,87 @@
|
||||
// Copyright (c) 2022 Marshall A. Greenblatt. All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the name Chromium Embedded
|
||||
// Framework nor the names of its contributors may be used to endorse
|
||||
// or promote products derived from this software without specific prior
|
||||
// written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// ---------------------------------------------------------------------------
|
||||
//
|
||||
// The contents of this file must follow a specific format in order to
|
||||
// support the CEF translator tool. See the translator.README.txt file in the
|
||||
// tools directory for more information.
|
||||
//
|
||||
|
||||
#ifndef CEF_INCLUDE_CEF_SHARED_PROCESS_MESSAGE_BUILDER_H_
|
||||
#define CEF_INCLUDE_CEF_SHARED_PROCESS_MESSAGE_BUILDER_H_
|
||||
#pragma once
|
||||
|
||||
#include "include/cef_process_message.h"
|
||||
|
||||
///
|
||||
// Class that builds a CefProcessMessage containing a shared memory region.
|
||||
// This class is not thread-safe but may be used exclusively on a different
|
||||
// thread from the one which constructed it.
|
||||
///
|
||||
/*--cef(source=library)--*/
|
||||
class CefSharedProcessMessageBuilder : public virtual CefBaseRefCounted {
|
||||
public:
|
||||
///
|
||||
// Creates a new CefSharedProcessMessageBuilder with the specified |name| and
|
||||
// shared memory region of specified |byte_size|.
|
||||
///
|
||||
/*--cef()--*/
|
||||
static CefRefPtr<CefSharedProcessMessageBuilder> Create(const CefString& name,
|
||||
size_t byte_size);
|
||||
///
|
||||
// Returns true if the builder is valid.
|
||||
///
|
||||
/*--cef()--*/
|
||||
virtual bool IsValid() = 0;
|
||||
|
||||
///
|
||||
// Returns the size of the shared memory region in bytes. Returns 0 for
|
||||
// invalid instances.
|
||||
///
|
||||
/*--cef()--*/
|
||||
virtual size_t Size() = 0;
|
||||
|
||||
///
|
||||
// Returns the pointer to the writable memory. Returns nullptr for invalid
|
||||
// instances. The returned pointer is only valid for the life span of this
|
||||
// object.
|
||||
///
|
||||
/*--cef()--*/
|
||||
virtual void* Memory() = 0;
|
||||
|
||||
///
|
||||
// Creates a new CefProcessMessage from the data provided to the builder.
|
||||
// Returns nullptr for invalid instances. Invalidates the builder instance.
|
||||
///
|
||||
/*--cef()--*/
|
||||
virtual CefRefPtr<CefProcessMessage> Build() = 0;
|
||||
};
|
||||
|
||||
#endif // CEF_INCLUDE_CEF_SHARED_PROCESS_MESSAGE_BUILDER_H_
|
@ -207,6 +207,10 @@ struct CefMessageRouterConfig {
|
||||
// Name of the JavaScript function that will be added to the 'window' object
|
||||
// for canceling a pending query. The default value is "cefQueryCancel".
|
||||
CefString js_cancel_function;
|
||||
|
||||
// Messages of size (in bytes) larger than this threshold will be sent via
|
||||
// shared memory region.
|
||||
size_t message_size_threshold;
|
||||
};
|
||||
|
||||
///
|
||||
|
@ -42,6 +42,16 @@ void CefBrowserFrame::SendMessage(const std::string& name,
|
||||
}
|
||||
}
|
||||
|
||||
void CefBrowserFrame::SendSharedMemoryRegion(
|
||||
const std::string& name,
|
||||
base::ReadOnlySharedMemoryRegion region) {
|
||||
// Always send to the newly created RFH, which may be speculative when
|
||||
// navigating cross-origin.
|
||||
if (auto host = GetFrameHost(/*prefer_speculative=*/true)) {
|
||||
host->SendSharedMemoryRegion(name, std::move(region));
|
||||
}
|
||||
}
|
||||
|
||||
void CefBrowserFrame::FrameAttached(
|
||||
mojo::PendingRemote<cef::mojom::RenderFrame> render_frame,
|
||||
bool reattached) {
|
||||
|
@ -36,6 +36,8 @@ class CefBrowserFrame
|
||||
private:
|
||||
// cef::mojom::BrowserFrame methods:
|
||||
void SendMessage(const std::string& name, base::Value arguments) override;
|
||||
void SendSharedMemoryRegion(const std::string& name,
|
||||
base::ReadOnlySharedMemoryRegion region) override;
|
||||
void FrameAttached(mojo::PendingRemote<cef::mojom::RenderFrame> render_frame,
|
||||
bool reattached) override;
|
||||
void DidFinishFrameLoad(const GURL& validated_url,
|
||||
|
@ -13,6 +13,7 @@
|
||||
#include "libcef/common/frame_util.h"
|
||||
#include "libcef/common/net/url_util.h"
|
||||
#include "libcef/common/process_message_impl.h"
|
||||
#include "libcef/common/process_message_smr_impl.h"
|
||||
#include "libcef/common/request_impl.h"
|
||||
#include "libcef/common/string_util.h"
|
||||
#include "libcef/common/task_runner_impl.h"
|
||||
@ -238,18 +239,31 @@ void CefFrameHostImpl::SendProcessMessage(
|
||||
if (!message || !message->IsValid())
|
||||
return;
|
||||
|
||||
// Invalidate the message object immediately by taking the argument list.
|
||||
auto argument_list =
|
||||
static_cast<CefProcessMessageImpl*>(message.get())->TakeArgumentList();
|
||||
if (message->GetArgumentList() != nullptr) {
|
||||
// Invalidate the message object immediately by taking the argument list.
|
||||
auto argument_list =
|
||||
static_cast<CefProcessMessageImpl*>(message.get())->TakeArgumentList();
|
||||
|
||||
SendToRenderFrame(__FUNCTION__,
|
||||
base::BindOnce(
|
||||
[](const CefString& name, base::ListValue argument_list,
|
||||
const RenderFrameType& render_frame) {
|
||||
render_frame->SendMessage(name,
|
||||
std::move(argument_list));
|
||||
},
|
||||
message->GetName(), std::move(argument_list)));
|
||||
SendToRenderFrame(
|
||||
__FUNCTION__,
|
||||
base::BindOnce(
|
||||
[](const CefString& name, base::ListValue argument_list,
|
||||
const RenderFrameType& render_frame) {
|
||||
render_frame->SendMessage(name, std::move(argument_list));
|
||||
},
|
||||
message->GetName(), std::move(argument_list)));
|
||||
} else {
|
||||
auto region =
|
||||
static_cast<CefProcessMessageSMRImpl*>(message.get())->TakeRegion();
|
||||
SendToRenderFrame(
|
||||
__FUNCTION__,
|
||||
base::BindOnce(
|
||||
[](const CefString& name, base::ReadOnlySharedMemoryRegion region,
|
||||
const RenderFrameType& render_frame) {
|
||||
render_frame->SendSharedMemoryRegion(name, std::move(region));
|
||||
},
|
||||
message->GetName(), std::move(region)));
|
||||
}
|
||||
}
|
||||
|
||||
void CefFrameHostImpl::SetFocused(bool focused) {
|
||||
@ -564,6 +578,19 @@ void CefFrameHostImpl::SendMessage(const std::string& name,
|
||||
}
|
||||
}
|
||||
|
||||
void CefFrameHostImpl::SendSharedMemoryRegion(
|
||||
const std::string& name,
|
||||
base::ReadOnlySharedMemoryRegion region) {
|
||||
if (auto browser = GetBrowserHostBase()) {
|
||||
if (auto client = browser->GetClient()) {
|
||||
CefRefPtr<CefProcessMessage> message(
|
||||
new CefProcessMessageSMRImpl(name, std::move(region)));
|
||||
browser->GetClient()->OnProcessMessageReceived(browser.get(), this,
|
||||
PID_RENDERER, message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CefFrameHostImpl::FrameAttached(
|
||||
mojo::PendingRemote<cef::mojom::RenderFrame> render_frame_remote,
|
||||
bool reattached) {
|
||||
|
@ -126,6 +126,8 @@ class CefFrameHostImpl : public CefFrame, public cef::mojom::BrowserFrame {
|
||||
|
||||
// cef::mojom::BrowserFrame methods forwarded from CefBrowserFrame.
|
||||
void SendMessage(const std::string& name, base::Value arguments) override;
|
||||
void SendSharedMemoryRegion(const std::string& name,
|
||||
base::ReadOnlySharedMemoryRegion region) override;
|
||||
void FrameAttached(mojo::PendingRemote<cef::mojom::RenderFrame> render_frame,
|
||||
bool reattached) override;
|
||||
void DidFinishFrameLoad(const GURL& validated_url,
|
||||
|
@ -55,6 +55,9 @@ interface RenderFrame {
|
||||
// Send a message to the render process.
|
||||
SendMessage(string name, mojo_base.mojom.Value arguments);
|
||||
|
||||
// Send a shared memory region to the render process.
|
||||
SendSharedMemoryRegion(string name, mojo_base.mojom.ReadOnlySharedMemoryRegion region);
|
||||
|
||||
// Send a command.
|
||||
SendCommand(string command);
|
||||
|
||||
@ -80,6 +83,9 @@ interface BrowserFrame {
|
||||
// Send a message to the browser process.
|
||||
SendMessage(string name, mojo_base.mojom.Value arguments);
|
||||
|
||||
// Send a shared memory region to the browser process.
|
||||
SendSharedMemoryRegion(string name, mojo_base.mojom.ReadOnlySharedMemoryRegion region);
|
||||
|
||||
// The render frame is ready to begin handling actions.
|
||||
FrameAttached(pending_remote<RenderFrame> render_frame,
|
||||
bool reattached);
|
||||
|
@ -42,6 +42,9 @@ class CefProcessMessageImpl : public CefProcessMessage {
|
||||
CefRefPtr<CefProcessMessage> Copy() override;
|
||||
CefString GetName() override;
|
||||
CefRefPtr<CefListValue> GetArgumentList() override;
|
||||
CefRefPtr<CefSharedMemoryRegion> GetSharedMemoryRegion() override {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
private:
|
||||
const CefString name_;
|
||||
|
90
libcef/common/process_message_smr_impl.cc
Normal file
90
libcef/common/process_message_smr_impl.cc
Normal file
@ -0,0 +1,90 @@
|
||||
// Copyright (c) 2022 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/common/process_message_smr_impl.h"
|
||||
|
||||
#include "base/logging.h"
|
||||
#include "base/memory/ptr_util.h"
|
||||
#include "base/memory/shared_memory_mapping.h"
|
||||
|
||||
namespace {
|
||||
|
||||
class CefSharedMemoryRegionImpl final : public CefSharedMemoryRegion {
|
||||
public:
|
||||
CefSharedMemoryRegionImpl(base::ReadOnlySharedMemoryMapping&& mapping)
|
||||
: mapping_(std::move(mapping)) {}
|
||||
CefSharedMemoryRegionImpl(const CefSharedMemoryRegionImpl&) = delete;
|
||||
CefSharedMemoryRegionImpl& operator=(const CefSharedMemoryRegionImpl&) =
|
||||
delete;
|
||||
|
||||
// CefSharedMemoryRegion methods
|
||||
bool IsValid() override { return mapping_.IsValid(); }
|
||||
size_t Size() override { return IsValid() ? mapping_.size() : 0; }
|
||||
const void* Memory() override { return mapping_.memory(); }
|
||||
|
||||
private:
|
||||
base::ReadOnlySharedMemoryMapping mapping_;
|
||||
IMPLEMENT_REFCOUNTING(CefSharedMemoryRegionImpl);
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
CefProcessMessageSMRImpl::CefProcessMessageSMRImpl(
|
||||
const CefString& name,
|
||||
base::ReadOnlySharedMemoryRegion&& region)
|
||||
: name_(name), region_(std::move(region)) {
|
||||
DCHECK(!name_.empty());
|
||||
DCHECK(region_.IsValid());
|
||||
}
|
||||
|
||||
CefProcessMessageSMRImpl::~CefProcessMessageSMRImpl() = default;
|
||||
|
||||
bool CefProcessMessageSMRImpl::IsValid() {
|
||||
return region_.IsValid();
|
||||
}
|
||||
|
||||
CefString CefProcessMessageSMRImpl::GetName() {
|
||||
return name_;
|
||||
}
|
||||
|
||||
CefRefPtr<CefSharedMemoryRegion>
|
||||
CefProcessMessageSMRImpl::GetSharedMemoryRegion() {
|
||||
return new CefSharedMemoryRegionImpl(region_.Map());
|
||||
}
|
||||
|
||||
base::ReadOnlySharedMemoryRegion CefProcessMessageSMRImpl::TakeRegion() {
|
||||
return std::move(region_);
|
||||
};
|
||||
|
||||
// static
|
||||
CefRefPtr<CefSharedProcessMessageBuilder>
|
||||
CefSharedProcessMessageBuilder::Create(const CefString& name,
|
||||
size_t byte_size) {
|
||||
return new CefSharedProcessMessageBuilderImpl(name, byte_size);
|
||||
}
|
||||
|
||||
CefSharedProcessMessageBuilderImpl::CefSharedProcessMessageBuilderImpl(
|
||||
const CefString& name,
|
||||
size_t byte_size)
|
||||
: name_(name),
|
||||
region_(base::ReadOnlySharedMemoryRegion::Create(byte_size)) {}
|
||||
|
||||
bool CefSharedProcessMessageBuilderImpl::IsValid() {
|
||||
return region_.region.IsValid() && region_.mapping.IsValid();
|
||||
}
|
||||
|
||||
size_t CefSharedProcessMessageBuilderImpl::Size() {
|
||||
return !IsValid() ? 0 : region_.mapping.size();
|
||||
}
|
||||
|
||||
void* CefSharedProcessMessageBuilderImpl::Memory() {
|
||||
return !IsValid() ? nullptr : region_.mapping.memory();
|
||||
}
|
||||
|
||||
CefRefPtr<CefProcessMessage> CefSharedProcessMessageBuilderImpl::Build() {
|
||||
if (!IsValid()) {
|
||||
return nullptr;
|
||||
}
|
||||
return new CefProcessMessageSMRImpl(name_, std::move(region_.region));
|
||||
}
|
58
libcef/common/process_message_smr_impl.h
Normal file
58
libcef/common/process_message_smr_impl.h
Normal file
@ -0,0 +1,58 @@
|
||||
// Copyright (c) 2022 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_COMMON_PROCESS_MESSAGE_SMR_IMPL_H_
|
||||
#define CEF_LIBCEF_COMMON_PROCESS_MESSAGE_SMR_IMPL_H_
|
||||
#pragma once
|
||||
|
||||
#include "include/cef_process_message.h"
|
||||
#include "include/cef_shared_process_message_builder.h"
|
||||
|
||||
#include "base/memory/read_only_shared_memory_region.h"
|
||||
|
||||
class CefProcessMessageSMRImpl final : public CefProcessMessage {
|
||||
public:
|
||||
CefProcessMessageSMRImpl(const CefString& name,
|
||||
base::ReadOnlySharedMemoryRegion&& region);
|
||||
CefProcessMessageSMRImpl(const CefProcessMessageSMRImpl&) = delete;
|
||||
CefProcessMessageSMRImpl& operator=(const CefProcessMessageSMRImpl&) = delete;
|
||||
~CefProcessMessageSMRImpl() override;
|
||||
|
||||
// CefProcessMessage methods.
|
||||
bool IsValid() override;
|
||||
bool IsReadOnly() override { return true; }
|
||||
CefRefPtr<CefProcessMessage> Copy() override { return nullptr; }
|
||||
CefString GetName() override;
|
||||
CefRefPtr<CefListValue> GetArgumentList() override { return nullptr; };
|
||||
CefRefPtr<CefSharedMemoryRegion> GetSharedMemoryRegion() override;
|
||||
[[nodiscard]] base::ReadOnlySharedMemoryRegion TakeRegion();
|
||||
|
||||
private:
|
||||
const CefString name_;
|
||||
base::ReadOnlySharedMemoryRegion region_;
|
||||
|
||||
IMPLEMENT_REFCOUNTING(CefProcessMessageSMRImpl);
|
||||
};
|
||||
|
||||
class CefSharedProcessMessageBuilderImpl final
|
||||
: public CefSharedProcessMessageBuilder {
|
||||
public:
|
||||
CefSharedProcessMessageBuilderImpl(const CefString& name, size_t byte_size);
|
||||
CefSharedProcessMessageBuilderImpl(const CefProcessMessageSMRImpl&) = delete;
|
||||
CefSharedProcessMessageBuilderImpl& operator=(
|
||||
const CefSharedProcessMessageBuilderImpl&) = delete;
|
||||
|
||||
bool IsValid() override;
|
||||
size_t Size() override;
|
||||
void* Memory() override;
|
||||
CefRefPtr<CefProcessMessage> Build() override;
|
||||
|
||||
private:
|
||||
const CefString name_;
|
||||
base::MappedReadOnlyRegion region_;
|
||||
|
||||
IMPLEMENT_REFCOUNTING(CefSharedProcessMessageBuilderImpl);
|
||||
};
|
||||
|
||||
#endif // CEF_LIBCEF_COMMON_PROCESS_MESSAGE_SMR_IMPL_H_
|
@ -21,6 +21,7 @@
|
||||
#include "libcef/common/frame_util.h"
|
||||
#include "libcef/common/net/http_header_utils.h"
|
||||
#include "libcef/common/process_message_impl.h"
|
||||
#include "libcef/common/process_message_smr_impl.h"
|
||||
#include "libcef/common/request_impl.h"
|
||||
#include "libcef/common/string_util.h"
|
||||
#include "libcef/renderer/blink_glue.h"
|
||||
@ -270,16 +271,30 @@ void CefFrameImpl::SendProcessMessage(CefProcessId target_process,
|
||||
if (!message || !message->IsValid())
|
||||
return;
|
||||
|
||||
SendToBrowserFrame(
|
||||
__FUNCTION__,
|
||||
base::BindOnce(
|
||||
[](CefRefPtr<CefProcessMessage> message,
|
||||
const BrowserFrameType& browser_frame) {
|
||||
auto impl = static_cast<CefProcessMessageImpl*>(message.get());
|
||||
browser_frame->SendMessage(impl->GetName(),
|
||||
impl->TakeArgumentList());
|
||||
},
|
||||
message));
|
||||
if (message->GetArgumentList() != nullptr) {
|
||||
// Invalidate the message object immediately by taking the argument list.
|
||||
auto argument_list =
|
||||
static_cast<CefProcessMessageImpl*>(message.get())->TakeArgumentList();
|
||||
SendToBrowserFrame(
|
||||
__FUNCTION__,
|
||||
base::BindOnce(
|
||||
[](const CefString& name, base::ListValue argument_list,
|
||||
const BrowserFrameType& render_frame) {
|
||||
render_frame->SendMessage(name, std::move(argument_list));
|
||||
},
|
||||
message->GetName(), std::move(argument_list)));
|
||||
} else {
|
||||
auto region =
|
||||
static_cast<CefProcessMessageSMRImpl*>(message.get())->TakeRegion();
|
||||
SendToBrowserFrame(
|
||||
__FUNCTION__,
|
||||
base::BindOnce(
|
||||
[](const CefString& name, base::ReadOnlySharedMemoryRegion region,
|
||||
const BrowserFrameType& render_frame) {
|
||||
render_frame->SendSharedMemoryRegion(name, std::move(region));
|
||||
},
|
||||
message->GetName(), std::move(region)));
|
||||
}
|
||||
}
|
||||
|
||||
std::unique_ptr<blink::WebURLLoader> CefFrameImpl::CreateURLLoader() {
|
||||
@ -654,6 +669,18 @@ void CefFrameImpl::SendMessage(const std::string& name, base::Value arguments) {
|
||||
}
|
||||
}
|
||||
|
||||
void CefFrameImpl::SendSharedMemoryRegion(
|
||||
const std::string& name,
|
||||
base::ReadOnlySharedMemoryRegion region) {
|
||||
if (auto app = CefAppManager::Get()->GetApplication()) {
|
||||
if (auto handler = app->GetRenderProcessHandler()) {
|
||||
CefRefPtr<CefProcessMessage> message(
|
||||
new CefProcessMessageSMRImpl(name, std::move(region)));
|
||||
handler->OnProcessMessageReceived(browser_, this, PID_BROWSER, message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CefFrameImpl::SendCommand(const std::string& command) {
|
||||
ExecuteOnLocalFrame(
|
||||
__FUNCTION__,
|
||||
|
@ -135,6 +135,8 @@ class CefFrameImpl
|
||||
// cef::mojom::RenderFrame methods:
|
||||
void FrameAttachedAck() override;
|
||||
void SendMessage(const std::string& name, base::Value arguments) override;
|
||||
void SendSharedMemoryRegion(const std::string& name,
|
||||
base::ReadOnlySharedMemoryRegion region) override;
|
||||
void SendCommand(const std::string& command) override;
|
||||
void SendCommandWithResponse(
|
||||
const std::string& command,
|
||||
|
@ -9,11 +9,12 @@
|
||||
// implementations. See the translator.README.txt file in the tools directory
|
||||
// for more information.
|
||||
//
|
||||
// $hash=b63f665e68e4dc6269c3e88b81068190ea90abb3$
|
||||
// $hash=5d331596c0425f145a19d8de6a866841d9ed8a87$
|
||||
//
|
||||
|
||||
#include "libcef_dll/cpptoc/process_message_cpptoc.h"
|
||||
#include "libcef_dll/cpptoc/list_value_cpptoc.h"
|
||||
#include "libcef_dll/cpptoc/shared_memory_region_cpptoc.h"
|
||||
#include "libcef_dll/shutdown_checker.h"
|
||||
|
||||
// GLOBAL FUNCTIONS - Body may be edited by hand.
|
||||
@ -127,6 +128,24 @@ process_message_get_argument_list(struct _cef_process_message_t* self) {
|
||||
return CefListValueCppToC::Wrap(_retval);
|
||||
}
|
||||
|
||||
struct _cef_shared_memory_region_t* CEF_CALLBACK
|
||||
process_message_get_shared_memory_region(struct _cef_process_message_t* self) {
|
||||
shutdown_checker::AssertNotShutdown();
|
||||
|
||||
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
|
||||
|
||||
DCHECK(self);
|
||||
if (!self)
|
||||
return NULL;
|
||||
|
||||
// Execute
|
||||
CefRefPtr<CefSharedMemoryRegion> _retval =
|
||||
CefProcessMessageCppToC::Get(self)->GetSharedMemoryRegion();
|
||||
|
||||
// Return type: refptr_same
|
||||
return CefSharedMemoryRegionCppToC::Wrap(_retval);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
// CONSTRUCTOR - Do not edit by hand.
|
||||
@ -137,6 +156,8 @@ CefProcessMessageCppToC::CefProcessMessageCppToC() {
|
||||
GetStruct()->copy = process_message_copy;
|
||||
GetStruct()->get_name = process_message_get_name;
|
||||
GetStruct()->get_argument_list = process_message_get_argument_list;
|
||||
GetStruct()->get_shared_memory_region =
|
||||
process_message_get_shared_memory_region;
|
||||
}
|
||||
|
||||
// DESTRUCTOR - Do not edit by hand.
|
||||
|
105
libcef_dll/cpptoc/shared_memory_region_cpptoc.cc
Normal file
105
libcef_dll/cpptoc/shared_memory_region_cpptoc.cc
Normal file
@ -0,0 +1,105 @@
|
||||
// Copyright (c) 2022 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.
|
||||
//
|
||||
// ---------------------------------------------------------------------------
|
||||
//
|
||||
// This file was generated by the CEF translator tool. If making changes by
|
||||
// hand only do so within the body of existing method and function
|
||||
// implementations. See the translator.README.txt file in the tools directory
|
||||
// for more information.
|
||||
//
|
||||
// $hash=b8c6bf91bf16cb696121e7d304c21fbcdc927ffd$
|
||||
//
|
||||
|
||||
#include "libcef_dll/cpptoc/shared_memory_region_cpptoc.h"
|
||||
#include "libcef_dll/shutdown_checker.h"
|
||||
|
||||
namespace {
|
||||
|
||||
// MEMBER FUNCTIONS - Body may be edited by hand.
|
||||
|
||||
int CEF_CALLBACK
|
||||
shared_memory_region_is_valid(struct _cef_shared_memory_region_t* self) {
|
||||
shutdown_checker::AssertNotShutdown();
|
||||
|
||||
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
|
||||
|
||||
DCHECK(self);
|
||||
if (!self)
|
||||
return 0;
|
||||
|
||||
// Execute
|
||||
bool _retval = CefSharedMemoryRegionCppToC::Get(self)->IsValid();
|
||||
|
||||
// Return type: bool
|
||||
return _retval;
|
||||
}
|
||||
|
||||
size_t CEF_CALLBACK
|
||||
shared_memory_region_size(struct _cef_shared_memory_region_t* self) {
|
||||
shutdown_checker::AssertNotShutdown();
|
||||
|
||||
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
|
||||
|
||||
DCHECK(self);
|
||||
if (!self)
|
||||
return 0;
|
||||
|
||||
// Execute
|
||||
size_t _retval = CefSharedMemoryRegionCppToC::Get(self)->Size();
|
||||
|
||||
// Return type: simple
|
||||
return _retval;
|
||||
}
|
||||
|
||||
const void* CEF_CALLBACK
|
||||
shared_memory_region_memory(struct _cef_shared_memory_region_t* self) {
|
||||
shutdown_checker::AssertNotShutdown();
|
||||
|
||||
shutdown_checker::AssertNotShutdown();
|
||||
|
||||
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
|
||||
|
||||
DCHECK(self);
|
||||
if (!self)
|
||||
return 0;
|
||||
|
||||
// Execute
|
||||
const void* _retval = CefSharedMemoryRegionCppToC::Get(self)->Memory();
|
||||
|
||||
// Return type: simple
|
||||
return _retval;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
// CONSTRUCTOR - Do not edit by hand.
|
||||
|
||||
CefSharedMemoryRegionCppToC::CefSharedMemoryRegionCppToC() {
|
||||
GetStruct()->is_valid = shared_memory_region_is_valid;
|
||||
GetStruct()->size = shared_memory_region_size;
|
||||
GetStruct()->memory = shared_memory_region_memory;
|
||||
}
|
||||
|
||||
// DESTRUCTOR - Do not edit by hand.
|
||||
|
||||
CefSharedMemoryRegionCppToC::~CefSharedMemoryRegionCppToC() {
|
||||
shutdown_checker::AssertNotShutdown();
|
||||
}
|
||||
|
||||
template <>
|
||||
CefRefPtr<CefSharedMemoryRegion> CefCppToCRefCounted<
|
||||
CefSharedMemoryRegionCppToC,
|
||||
CefSharedMemoryRegion,
|
||||
cef_shared_memory_region_t>::UnwrapDerived(CefWrapperType type,
|
||||
cef_shared_memory_region_t* s) {
|
||||
NOTREACHED() << "Unexpected class type: " << type;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
template <>
|
||||
CefWrapperType CefCppToCRefCounted<CefSharedMemoryRegionCppToC,
|
||||
CefSharedMemoryRegion,
|
||||
cef_shared_memory_region_t>::kWrapperType =
|
||||
WT_SHARED_MEMORY_REGION;
|
38
libcef_dll/cpptoc/shared_memory_region_cpptoc.h
Normal file
38
libcef_dll/cpptoc/shared_memory_region_cpptoc.h
Normal file
@ -0,0 +1,38 @@
|
||||
// Copyright (c) 2022 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.
|
||||
//
|
||||
// ---------------------------------------------------------------------------
|
||||
//
|
||||
// This file was generated by the CEF translator tool. If making changes by
|
||||
// hand only do so within the body of existing method and function
|
||||
// implementations. See the translator.README.txt file in the tools directory
|
||||
// for more information.
|
||||
//
|
||||
// $hash=77de7d9d9e62fa5075ff6e76e4647639c51a7f05$
|
||||
//
|
||||
|
||||
#ifndef CEF_LIBCEF_DLL_CPPTOC_SHARED_MEMORY_REGION_CPPTOC_H_
|
||||
#define CEF_LIBCEF_DLL_CPPTOC_SHARED_MEMORY_REGION_CPPTOC_H_
|
||||
#pragma once
|
||||
|
||||
#if !defined(BUILDING_CEF_SHARED)
|
||||
#error This file can be included DLL-side only
|
||||
#endif
|
||||
|
||||
#include "include/capi/cef_shared_memory_region_capi.h"
|
||||
#include "include/cef_shared_memory_region.h"
|
||||
#include "libcef_dll/cpptoc/cpptoc_ref_counted.h"
|
||||
|
||||
// Wrap a C++ class with a C structure.
|
||||
// This class may be instantiated and accessed DLL-side only.
|
||||
class CefSharedMemoryRegionCppToC
|
||||
: public CefCppToCRefCounted<CefSharedMemoryRegionCppToC,
|
||||
CefSharedMemoryRegion,
|
||||
cef_shared_memory_region_t> {
|
||||
public:
|
||||
CefSharedMemoryRegionCppToC();
|
||||
virtual ~CefSharedMemoryRegionCppToC();
|
||||
};
|
||||
|
||||
#endif // CEF_LIBCEF_DLL_CPPTOC_SHARED_MEMORY_REGION_CPPTOC_H_
|
145
libcef_dll/cpptoc/shared_process_message_builder_cpptoc.cc
Normal file
145
libcef_dll/cpptoc/shared_process_message_builder_cpptoc.cc
Normal file
@ -0,0 +1,145 @@
|
||||
// Copyright (c) 2022 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.
|
||||
//
|
||||
// ---------------------------------------------------------------------------
|
||||
//
|
||||
// This file was generated by the CEF translator tool. If making changes by
|
||||
// hand only do so within the body of existing method and function
|
||||
// implementations. See the translator.README.txt file in the tools directory
|
||||
// for more information.
|
||||
//
|
||||
// $hash=b3c3551c52baf66ab3cd4ee485313ef41a29313b$
|
||||
//
|
||||
|
||||
#include "libcef_dll/cpptoc/shared_process_message_builder_cpptoc.h"
|
||||
#include "libcef_dll/cpptoc/process_message_cpptoc.h"
|
||||
#include "libcef_dll/shutdown_checker.h"
|
||||
|
||||
// GLOBAL FUNCTIONS - Body may be edited by hand.
|
||||
|
||||
CEF_EXPORT cef_shared_process_message_builder_t*
|
||||
cef_shared_process_message_builder_create(const cef_string_t* name,
|
||||
size_t byte_size) {
|
||||
shutdown_checker::AssertNotShutdown();
|
||||
|
||||
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
|
||||
|
||||
// Verify param: name; type: string_byref_const
|
||||
DCHECK(name);
|
||||
if (!name)
|
||||
return NULL;
|
||||
|
||||
// Execute
|
||||
CefRefPtr<CefSharedProcessMessageBuilder> _retval =
|
||||
CefSharedProcessMessageBuilder::Create(CefString(name), byte_size);
|
||||
|
||||
// Return type: refptr_same
|
||||
return CefSharedProcessMessageBuilderCppToC::Wrap(_retval);
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
// MEMBER FUNCTIONS - Body may be edited by hand.
|
||||
|
||||
int CEF_CALLBACK shared_process_message_builder_is_valid(
|
||||
struct _cef_shared_process_message_builder_t* self) {
|
||||
shutdown_checker::AssertNotShutdown();
|
||||
|
||||
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
|
||||
|
||||
DCHECK(self);
|
||||
if (!self)
|
||||
return 0;
|
||||
|
||||
// Execute
|
||||
bool _retval = CefSharedProcessMessageBuilderCppToC::Get(self)->IsValid();
|
||||
|
||||
// Return type: bool
|
||||
return _retval;
|
||||
}
|
||||
|
||||
size_t CEF_CALLBACK shared_process_message_builder_size(
|
||||
struct _cef_shared_process_message_builder_t* self) {
|
||||
shutdown_checker::AssertNotShutdown();
|
||||
|
||||
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
|
||||
|
||||
DCHECK(self);
|
||||
if (!self)
|
||||
return 0;
|
||||
|
||||
// Execute
|
||||
size_t _retval = CefSharedProcessMessageBuilderCppToC::Get(self)->Size();
|
||||
|
||||
// Return type: simple
|
||||
return _retval;
|
||||
}
|
||||
|
||||
void* CEF_CALLBACK shared_process_message_builder_memory(
|
||||
struct _cef_shared_process_message_builder_t* self) {
|
||||
shutdown_checker::AssertNotShutdown();
|
||||
|
||||
DCHECK(self);
|
||||
if (!self)
|
||||
return 0;
|
||||
|
||||
// Execute
|
||||
void* _retval = CefSharedProcessMessageBuilderCppToC::Get(self)->Memory();
|
||||
|
||||
// Return type: simple
|
||||
return _retval;
|
||||
}
|
||||
|
||||
cef_process_message_t* CEF_CALLBACK shared_process_message_builder_build(
|
||||
struct _cef_shared_process_message_builder_t* self) {
|
||||
shutdown_checker::AssertNotShutdown();
|
||||
|
||||
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
|
||||
|
||||
DCHECK(self);
|
||||
if (!self)
|
||||
return NULL;
|
||||
|
||||
// Execute
|
||||
CefRefPtr<CefProcessMessage> _retval =
|
||||
CefSharedProcessMessageBuilderCppToC::Get(self)->Build();
|
||||
|
||||
// Return type: refptr_same
|
||||
return CefProcessMessageCppToC::Wrap(_retval);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
// CONSTRUCTOR - Do not edit by hand.
|
||||
|
||||
CefSharedProcessMessageBuilderCppToC::CefSharedProcessMessageBuilderCppToC() {
|
||||
GetStruct()->is_valid = shared_process_message_builder_is_valid;
|
||||
GetStruct()->size = shared_process_message_builder_size;
|
||||
GetStruct()->memory = shared_process_message_builder_memory;
|
||||
GetStruct()->build = shared_process_message_builder_build;
|
||||
}
|
||||
|
||||
// DESTRUCTOR - Do not edit by hand.
|
||||
|
||||
CefSharedProcessMessageBuilderCppToC::~CefSharedProcessMessageBuilderCppToC() {
|
||||
shutdown_checker::AssertNotShutdown();
|
||||
}
|
||||
|
||||
template <>
|
||||
CefRefPtr<CefSharedProcessMessageBuilder>
|
||||
CefCppToCRefCounted<CefSharedProcessMessageBuilderCppToC,
|
||||
CefSharedProcessMessageBuilder,
|
||||
cef_shared_process_message_builder_t>::
|
||||
UnwrapDerived(CefWrapperType type,
|
||||
cef_shared_process_message_builder_t* s) {
|
||||
NOTREACHED() << "Unexpected class type: " << type;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
template <>
|
||||
CefWrapperType
|
||||
CefCppToCRefCounted<CefSharedProcessMessageBuilderCppToC,
|
||||
CefSharedProcessMessageBuilder,
|
||||
cef_shared_process_message_builder_t>::kWrapperType =
|
||||
WT_SHARED_PROCESS_MESSAGE_BUILDER;
|
38
libcef_dll/cpptoc/shared_process_message_builder_cpptoc.h
Normal file
38
libcef_dll/cpptoc/shared_process_message_builder_cpptoc.h
Normal file
@ -0,0 +1,38 @@
|
||||
// Copyright (c) 2022 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.
|
||||
//
|
||||
// ---------------------------------------------------------------------------
|
||||
//
|
||||
// This file was generated by the CEF translator tool. If making changes by
|
||||
// hand only do so within the body of existing method and function
|
||||
// implementations. See the translator.README.txt file in the tools directory
|
||||
// for more information.
|
||||
//
|
||||
// $hash=a3ec0a78d1e092d99780b6ec87d345a20c081be6$
|
||||
//
|
||||
|
||||
#ifndef CEF_LIBCEF_DLL_CPPTOC_SHARED_PROCESS_MESSAGE_BUILDER_CPPTOC_H_
|
||||
#define CEF_LIBCEF_DLL_CPPTOC_SHARED_PROCESS_MESSAGE_BUILDER_CPPTOC_H_
|
||||
#pragma once
|
||||
|
||||
#if !defined(BUILDING_CEF_SHARED)
|
||||
#error This file can be included DLL-side only
|
||||
#endif
|
||||
|
||||
#include "include/capi/cef_shared_process_message_builder_capi.h"
|
||||
#include "include/cef_shared_process_message_builder.h"
|
||||
#include "libcef_dll/cpptoc/cpptoc_ref_counted.h"
|
||||
|
||||
// Wrap a C++ class with a C structure.
|
||||
// This class may be instantiated and accessed DLL-side only.
|
||||
class CefSharedProcessMessageBuilderCppToC
|
||||
: public CefCppToCRefCounted<CefSharedProcessMessageBuilderCppToC,
|
||||
CefSharedProcessMessageBuilder,
|
||||
cef_shared_process_message_builder_t> {
|
||||
public:
|
||||
CefSharedProcessMessageBuilderCppToC();
|
||||
virtual ~CefSharedProcessMessageBuilderCppToC();
|
||||
};
|
||||
|
||||
#endif // CEF_LIBCEF_DLL_CPPTOC_SHARED_PROCESS_MESSAGE_BUILDER_CPPTOC_H_
|
@ -9,11 +9,12 @@
|
||||
// implementations. See the translator.README.txt file in the tools directory
|
||||
// for more information.
|
||||
//
|
||||
// $hash=7ab779c6c98a1bd2385f14d514304a28ef58717f$
|
||||
// $hash=0f16a0f4711caf0b3761bf6480622de2e75b72ef$
|
||||
//
|
||||
|
||||
#include "libcef_dll/ctocpp/process_message_ctocpp.h"
|
||||
#include "libcef_dll/ctocpp/list_value_ctocpp.h"
|
||||
#include "libcef_dll/ctocpp/shared_memory_region_ctocpp.h"
|
||||
#include "libcef_dll/shutdown_checker.h"
|
||||
|
||||
// STATIC METHODS - Body may be edited by hand.
|
||||
@ -122,6 +123,25 @@ CefRefPtr<CefListValue> CefProcessMessageCToCpp::GetArgumentList() {
|
||||
return CefListValueCToCpp::Wrap(_retval);
|
||||
}
|
||||
|
||||
NO_SANITIZE("cfi-icall")
|
||||
CefRefPtr<CefSharedMemoryRegion>
|
||||
CefProcessMessageCToCpp::GetSharedMemoryRegion() {
|
||||
shutdown_checker::AssertNotShutdown();
|
||||
|
||||
cef_process_message_t* _struct = GetStruct();
|
||||
if (CEF_MEMBER_MISSING(_struct, get_shared_memory_region))
|
||||
return nullptr;
|
||||
|
||||
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
|
||||
|
||||
// Execute
|
||||
cef_shared_memory_region_t* _retval =
|
||||
_struct->get_shared_memory_region(_struct);
|
||||
|
||||
// Return type: refptr_same
|
||||
return CefSharedMemoryRegionCToCpp::Wrap(_retval);
|
||||
}
|
||||
|
||||
// CONSTRUCTOR - Do not edit by hand.
|
||||
|
||||
CefProcessMessageCToCpp::CefProcessMessageCToCpp() {}
|
||||
|
@ -9,7 +9,7 @@
|
||||
// implementations. See the translator.README.txt file in the tools directory
|
||||
// for more information.
|
||||
//
|
||||
// $hash=39bf2321370b32cf02bf502529568e935b303550$
|
||||
// $hash=f52b0dfcee0d432a334166fce348234d0d239b85$
|
||||
//
|
||||
|
||||
#ifndef CEF_LIBCEF_DLL_CTOCPP_PROCESS_MESSAGE_CTOCPP_H_
|
||||
@ -40,6 +40,7 @@ class CefProcessMessageCToCpp
|
||||
CefRefPtr<CefProcessMessage> Copy() override;
|
||||
CefString GetName() override;
|
||||
CefRefPtr<CefListValue> GetArgumentList() override;
|
||||
CefRefPtr<CefSharedMemoryRegion> GetSharedMemoryRegion() override;
|
||||
};
|
||||
|
||||
#endif // CEF_LIBCEF_DLL_CTOCPP_PROCESS_MESSAGE_CTOCPP_H_
|
||||
|
90
libcef_dll/ctocpp/shared_memory_region_ctocpp.cc
Normal file
90
libcef_dll/ctocpp/shared_memory_region_ctocpp.cc
Normal file
@ -0,0 +1,90 @@
|
||||
// Copyright (c) 2022 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.
|
||||
//
|
||||
// ---------------------------------------------------------------------------
|
||||
//
|
||||
// This file was generated by the CEF translator tool. If making changes by
|
||||
// hand only do so within the body of existing method and function
|
||||
// implementations. See the translator.README.txt file in the tools directory
|
||||
// for more information.
|
||||
//
|
||||
// $hash=fd0a4c1bd80a53778d6e40e4ebcd9d4484f91269$
|
||||
//
|
||||
|
||||
#include "libcef_dll/ctocpp/shared_memory_region_ctocpp.h"
|
||||
#include "libcef_dll/shutdown_checker.h"
|
||||
|
||||
// VIRTUAL METHODS - Body may be edited by hand.
|
||||
|
||||
NO_SANITIZE("cfi-icall") bool CefSharedMemoryRegionCToCpp::IsValid() {
|
||||
shutdown_checker::AssertNotShutdown();
|
||||
|
||||
cef_shared_memory_region_t* _struct = GetStruct();
|
||||
if (CEF_MEMBER_MISSING(_struct, is_valid))
|
||||
return false;
|
||||
|
||||
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
|
||||
|
||||
// Execute
|
||||
int _retval = _struct->is_valid(_struct);
|
||||
|
||||
// Return type: bool
|
||||
return _retval ? true : false;
|
||||
}
|
||||
|
||||
NO_SANITIZE("cfi-icall") size_t CefSharedMemoryRegionCToCpp::Size() {
|
||||
shutdown_checker::AssertNotShutdown();
|
||||
|
||||
cef_shared_memory_region_t* _struct = GetStruct();
|
||||
if (CEF_MEMBER_MISSING(_struct, size))
|
||||
return 0;
|
||||
|
||||
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
|
||||
|
||||
// Execute
|
||||
size_t _retval = _struct->size(_struct);
|
||||
|
||||
// Return type: simple
|
||||
return _retval;
|
||||
}
|
||||
|
||||
NO_SANITIZE("cfi-icall") const void* CefSharedMemoryRegionCToCpp::Memory() {
|
||||
shutdown_checker::AssertNotShutdown();
|
||||
|
||||
cef_shared_memory_region_t* _struct = GetStruct();
|
||||
if (CEF_MEMBER_MISSING(_struct, memory))
|
||||
return nullptr;
|
||||
|
||||
// Execute
|
||||
const void* _retval = _struct->memory(_struct);
|
||||
|
||||
// Return type: simple
|
||||
return _retval;
|
||||
}
|
||||
|
||||
// CONSTRUCTOR - Do not edit by hand.
|
||||
|
||||
CefSharedMemoryRegionCToCpp::CefSharedMemoryRegionCToCpp() {}
|
||||
|
||||
// DESTRUCTOR - Do not edit by hand.
|
||||
|
||||
CefSharedMemoryRegionCToCpp::~CefSharedMemoryRegionCToCpp() {
|
||||
shutdown_checker::AssertNotShutdown();
|
||||
}
|
||||
|
||||
template <>
|
||||
cef_shared_memory_region_t* CefCToCppRefCounted<
|
||||
CefSharedMemoryRegionCToCpp,
|
||||
CefSharedMemoryRegion,
|
||||
cef_shared_memory_region_t>::UnwrapDerived(CefWrapperType type,
|
||||
CefSharedMemoryRegion* c) {
|
||||
NOTREACHED() << "Unexpected class type: " << type;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
template <>
|
||||
CefWrapperType CefCToCppRefCounted<CefSharedMemoryRegionCToCpp,
|
||||
CefSharedMemoryRegion,
|
||||
cef_shared_memory_region_t>::kWrapperType =
|
||||
WT_SHARED_MEMORY_REGION;
|
43
libcef_dll/ctocpp/shared_memory_region_ctocpp.h
Normal file
43
libcef_dll/ctocpp/shared_memory_region_ctocpp.h
Normal file
@ -0,0 +1,43 @@
|
||||
// Copyright (c) 2022 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.
|
||||
//
|
||||
// ---------------------------------------------------------------------------
|
||||
//
|
||||
// This file was generated by the CEF translator tool. If making changes by
|
||||
// hand only do so within the body of existing method and function
|
||||
// implementations. See the translator.README.txt file in the tools directory
|
||||
// for more information.
|
||||
//
|
||||
// $hash=d477b2660e271bbdc4d6e8f866f006b84f13e50d$
|
||||
//
|
||||
|
||||
#ifndef CEF_LIBCEF_DLL_CTOCPP_SHARED_MEMORY_REGION_CTOCPP_H_
|
||||
#define CEF_LIBCEF_DLL_CTOCPP_SHARED_MEMORY_REGION_CTOCPP_H_
|
||||
#pragma once
|
||||
|
||||
#if !defined(WRAPPING_CEF_SHARED)
|
||||
#error This file can be included wrapper-side only
|
||||
#endif
|
||||
|
||||
#include "include/capi/cef_shared_memory_region_capi.h"
|
||||
#include "include/cef_shared_memory_region.h"
|
||||
#include "libcef_dll/ctocpp/ctocpp_ref_counted.h"
|
||||
|
||||
// Wrap a C structure with a C++ class.
|
||||
// This class may be instantiated and accessed wrapper-side only.
|
||||
class CefSharedMemoryRegionCToCpp
|
||||
: public CefCToCppRefCounted<CefSharedMemoryRegionCToCpp,
|
||||
CefSharedMemoryRegion,
|
||||
cef_shared_memory_region_t> {
|
||||
public:
|
||||
CefSharedMemoryRegionCToCpp();
|
||||
virtual ~CefSharedMemoryRegionCToCpp();
|
||||
|
||||
// CefSharedMemoryRegion methods.
|
||||
bool IsValid() override;
|
||||
size_t Size() override;
|
||||
const void* Memory() override;
|
||||
};
|
||||
|
||||
#endif // CEF_LIBCEF_DLL_CTOCPP_SHARED_MEMORY_REGION_CTOCPP_H_
|
132
libcef_dll/ctocpp/shared_process_message_builder_ctocpp.cc
Normal file
132
libcef_dll/ctocpp/shared_process_message_builder_ctocpp.cc
Normal file
@ -0,0 +1,132 @@
|
||||
// Copyright (c) 2022 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.
|
||||
//
|
||||
// ---------------------------------------------------------------------------
|
||||
//
|
||||
// This file was generated by the CEF translator tool. If making changes by
|
||||
// hand only do so within the body of existing method and function
|
||||
// implementations. See the translator.README.txt file in the tools directory
|
||||
// for more information.
|
||||
//
|
||||
// $hash=a20e093efb07503fe9e64c97c14091e3921544cd$
|
||||
//
|
||||
|
||||
#include "libcef_dll/ctocpp/shared_process_message_builder_ctocpp.h"
|
||||
#include "libcef_dll/ctocpp/process_message_ctocpp.h"
|
||||
#include "libcef_dll/shutdown_checker.h"
|
||||
|
||||
// STATIC METHODS - Body may be edited by hand.
|
||||
|
||||
NO_SANITIZE("cfi-icall")
|
||||
CefRefPtr<CefSharedProcessMessageBuilder>
|
||||
CefSharedProcessMessageBuilder::Create(const CefString& name,
|
||||
size_t byte_size) {
|
||||
shutdown_checker::AssertNotShutdown();
|
||||
|
||||
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
|
||||
|
||||
// Verify param: name; type: string_byref_const
|
||||
DCHECK(!name.empty());
|
||||
if (name.empty())
|
||||
return nullptr;
|
||||
|
||||
// Execute
|
||||
cef_shared_process_message_builder_t* _retval =
|
||||
cef_shared_process_message_builder_create(name.GetStruct(), byte_size);
|
||||
|
||||
// Return type: refptr_same
|
||||
return CefSharedProcessMessageBuilderCToCpp::Wrap(_retval);
|
||||
}
|
||||
|
||||
// VIRTUAL METHODS - Body may be edited by hand.
|
||||
|
||||
NO_SANITIZE("cfi-icall") bool CefSharedProcessMessageBuilderCToCpp::IsValid() {
|
||||
shutdown_checker::AssertNotShutdown();
|
||||
|
||||
cef_shared_process_message_builder_t* _struct = GetStruct();
|
||||
if (CEF_MEMBER_MISSING(_struct, is_valid))
|
||||
return false;
|
||||
|
||||
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
|
||||
|
||||
// Execute
|
||||
int _retval = _struct->is_valid(_struct);
|
||||
|
||||
// Return type: bool
|
||||
return _retval ? true : false;
|
||||
}
|
||||
|
||||
NO_SANITIZE("cfi-icall") size_t CefSharedProcessMessageBuilderCToCpp::Size() {
|
||||
shutdown_checker::AssertNotShutdown();
|
||||
|
||||
cef_shared_process_message_builder_t* _struct = GetStruct();
|
||||
if (CEF_MEMBER_MISSING(_struct, size))
|
||||
return 0;
|
||||
|
||||
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
|
||||
|
||||
// Execute
|
||||
size_t _retval = _struct->size(_struct);
|
||||
|
||||
// Return type: simple
|
||||
return _retval;
|
||||
}
|
||||
|
||||
NO_SANITIZE("cfi-icall") void* CefSharedProcessMessageBuilderCToCpp::Memory() {
|
||||
shutdown_checker::AssertNotShutdown();
|
||||
|
||||
cef_shared_process_message_builder_t* _struct = GetStruct();
|
||||
if (CEF_MEMBER_MISSING(_struct, memory))
|
||||
return nullptr;
|
||||
|
||||
// Execute
|
||||
void* _retval = _struct->memory(_struct);
|
||||
|
||||
// Return type: simple
|
||||
return _retval;
|
||||
}
|
||||
|
||||
NO_SANITIZE("cfi-icall")
|
||||
CefRefPtr<CefProcessMessage> CefSharedProcessMessageBuilderCToCpp::Build() {
|
||||
shutdown_checker::AssertNotShutdown();
|
||||
|
||||
cef_shared_process_message_builder_t* _struct = GetStruct();
|
||||
if (CEF_MEMBER_MISSING(_struct, build))
|
||||
return nullptr;
|
||||
|
||||
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
|
||||
|
||||
// Execute
|
||||
cef_process_message_t* _retval = _struct->build(_struct);
|
||||
|
||||
// Return type: refptr_same
|
||||
return CefProcessMessageCToCpp::Wrap(_retval);
|
||||
}
|
||||
|
||||
// CONSTRUCTOR - Do not edit by hand.
|
||||
|
||||
CefSharedProcessMessageBuilderCToCpp::CefSharedProcessMessageBuilderCToCpp() {}
|
||||
|
||||
// DESTRUCTOR - Do not edit by hand.
|
||||
|
||||
CefSharedProcessMessageBuilderCToCpp::~CefSharedProcessMessageBuilderCToCpp() {
|
||||
shutdown_checker::AssertNotShutdown();
|
||||
}
|
||||
|
||||
template <>
|
||||
cef_shared_process_message_builder_t*
|
||||
CefCToCppRefCounted<CefSharedProcessMessageBuilderCToCpp,
|
||||
CefSharedProcessMessageBuilder,
|
||||
cef_shared_process_message_builder_t>::
|
||||
UnwrapDerived(CefWrapperType type, CefSharedProcessMessageBuilder* c) {
|
||||
NOTREACHED() << "Unexpected class type: " << type;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
template <>
|
||||
CefWrapperType
|
||||
CefCToCppRefCounted<CefSharedProcessMessageBuilderCToCpp,
|
||||
CefSharedProcessMessageBuilder,
|
||||
cef_shared_process_message_builder_t>::kWrapperType =
|
||||
WT_SHARED_PROCESS_MESSAGE_BUILDER;
|
44
libcef_dll/ctocpp/shared_process_message_builder_ctocpp.h
Normal file
44
libcef_dll/ctocpp/shared_process_message_builder_ctocpp.h
Normal file
@ -0,0 +1,44 @@
|
||||
// Copyright (c) 2022 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.
|
||||
//
|
||||
// ---------------------------------------------------------------------------
|
||||
//
|
||||
// This file was generated by the CEF translator tool. If making changes by
|
||||
// hand only do so within the body of existing method and function
|
||||
// implementations. See the translator.README.txt file in the tools directory
|
||||
// for more information.
|
||||
//
|
||||
// $hash=0a8bf76a2347d7afc98e1cbeb61b88be4bc7e789$
|
||||
//
|
||||
|
||||
#ifndef CEF_LIBCEF_DLL_CTOCPP_SHARED_PROCESS_MESSAGE_BUILDER_CTOCPP_H_
|
||||
#define CEF_LIBCEF_DLL_CTOCPP_SHARED_PROCESS_MESSAGE_BUILDER_CTOCPP_H_
|
||||
#pragma once
|
||||
|
||||
#if !defined(WRAPPING_CEF_SHARED)
|
||||
#error This file can be included wrapper-side only
|
||||
#endif
|
||||
|
||||
#include "include/capi/cef_shared_process_message_builder_capi.h"
|
||||
#include "include/cef_shared_process_message_builder.h"
|
||||
#include "libcef_dll/ctocpp/ctocpp_ref_counted.h"
|
||||
|
||||
// Wrap a C structure with a C++ class.
|
||||
// This class may be instantiated and accessed wrapper-side only.
|
||||
class CefSharedProcessMessageBuilderCToCpp
|
||||
: public CefCToCppRefCounted<CefSharedProcessMessageBuilderCToCpp,
|
||||
CefSharedProcessMessageBuilder,
|
||||
cef_shared_process_message_builder_t> {
|
||||
public:
|
||||
CefSharedProcessMessageBuilderCToCpp();
|
||||
virtual ~CefSharedProcessMessageBuilderCToCpp();
|
||||
|
||||
// CefSharedProcessMessageBuilder methods.
|
||||
bool IsValid() override;
|
||||
size_t Size() override;
|
||||
void* Memory() override;
|
||||
CefRefPtr<CefProcessMessage> Build() override;
|
||||
};
|
||||
|
||||
#endif // CEF_LIBCEF_DLL_CTOCPP_SHARED_PROCESS_MESSAGE_BUILDER_CTOCPP_H_
|
@ -8,6 +8,7 @@
|
||||
#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"
|
||||
@ -31,6 +32,10 @@ const char kMemberPersistent[] = "persistent";
|
||||
const int kCanceledErrorCode = -1;
|
||||
const char kCanceledErrorMessage[] = "The query has been canceled";
|
||||
|
||||
// Value of 16KB is chosen as a result of performance tests available at
|
||||
// http://tests/ipc_performance
|
||||
constexpr size_t kResponseSizeThreshold = 16384;
|
||||
|
||||
// Validate configuration settings.
|
||||
bool ValidateConfig(CefMessageRouterConfig& config) {
|
||||
// Must specify function names.
|
||||
@ -41,6 +46,124 @@ 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 GetMessageSize(const CefString& response) {
|
||||
return sizeof(MessageHeader) +
|
||||
(response.size() * sizeof(CefString::char_type));
|
||||
}
|
||||
|
||||
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 (response.size() <= 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{};
|
||||
}
|
||||
|
||||
// Helper template for generated ID values.
|
||||
template <typename T>
|
||||
class IdGenerator {
|
||||
@ -428,14 +551,11 @@ class CefMessageRouterBrowserSideImpl : public CefMessageRouterBrowserSide {
|
||||
int context_id,
|
||||
int request_id,
|
||||
const CefString& response) {
|
||||
CefRefPtr<CefProcessMessage> message =
|
||||
CefProcessMessage::Create(query_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);
|
||||
frame->SendProcessMessage(PID_RENDERER, message);
|
||||
if (auto message =
|
||||
BuildMessage(config_.message_size_threshold, query_message_name_,
|
||||
context_id, request_id, response)) {
|
||||
frame->SendProcessMessage(PID_RENDERER, message);
|
||||
}
|
||||
}
|
||||
|
||||
void SendQueryFailure(QueryInfo* info,
|
||||
@ -817,31 +937,21 @@ class CefMessageRouterRendererSideImpl : public CefMessageRouterRendererSide {
|
||||
|
||||
const std::string& message_name = message->GetName();
|
||||
if (message_name == query_message_name_) {
|
||||
CefRefPtr<CefListValue> args = message->GetArgumentList();
|
||||
DCHECK_GT(args->GetSize(), 3U);
|
||||
|
||||
const int context_id = args->GetInt(0);
|
||||
const int request_id = args->GetInt(1);
|
||||
bool is_success = args->GetBool(2);
|
||||
|
||||
if (is_success) {
|
||||
DCHECK_EQ(args->GetSize(), 4U);
|
||||
const CefString& response = args->GetString(3);
|
||||
auto content = ParseMessage(message);
|
||||
if (content.success) {
|
||||
CefPostTask(
|
||||
TID_RENDERER,
|
||||
base::BindOnce(
|
||||
&CefMessageRouterRendererSideImpl::ExecuteSuccessCallback, this,
|
||||
browser->GetIdentifier(), context_id, request_id, response));
|
||||
browser->GetIdentifier(), content.context_id,
|
||||
content.request_id, content.message));
|
||||
} else {
|
||||
DCHECK_EQ(args->GetSize(), 5U);
|
||||
int error_code = args->GetInt(3);
|
||||
const CefString& error_message = args->GetString(4);
|
||||
CefPostTask(
|
||||
TID_RENDERER,
|
||||
base::BindOnce(
|
||||
&CefMessageRouterRendererSideImpl::ExecuteFailureCallback, this,
|
||||
browser->GetIdentifier(), context_id, request_id, error_code,
|
||||
error_message));
|
||||
browser->GetIdentifier(), content.context_id,
|
||||
content.request_id, content.error_code, content.message));
|
||||
}
|
||||
|
||||
return true;
|
||||
@ -913,10 +1023,9 @@ class CefMessageRouterRendererSideImpl : public CefMessageRouterRendererSide {
|
||||
|
||||
const int request_id = request_id_generator_.GetNextId();
|
||||
|
||||
RequestInfo* info = new RequestInfo;
|
||||
info->persistent = persistent;
|
||||
info->success_callback = success_callback;
|
||||
info->failure_callback = failure_callback;
|
||||
auto* info =
|
||||
new RequestInfo{persistent, success_callback, failure_callback};
|
||||
|
||||
browser_request_info_map_.Add(browser->GetIdentifier(),
|
||||
std::make_pair(context_id, request_id), info);
|
||||
|
||||
@ -1117,7 +1226,9 @@ class CefMessageRouterRendererSideImpl : public CefMessageRouterRendererSide {
|
||||
} // namespace
|
||||
|
||||
CefMessageRouterConfig::CefMessageRouterConfig()
|
||||
: js_query_function("cefQuery"), js_cancel_function("cefQueryCancel") {}
|
||||
: js_query_function("cefQuery"),
|
||||
js_cancel_function("cefQueryCancel"),
|
||||
message_size_threshold(kResponseSizeThreshold) {}
|
||||
|
||||
// static
|
||||
CefRefPtr<CefMessageRouterBrowserSide> CefMessageRouterBrowserSide::Create(
|
||||
|
@ -9,7 +9,7 @@
|
||||
// implementations. See the translator.README.txt file in the tools directory
|
||||
// for more information.
|
||||
//
|
||||
// $hash=5bf495a6015a7c0937225685bfbe8e0163e67583$
|
||||
// $hash=9c3fcd2a053f20a9a09b9938996f5df9eb2053ef$
|
||||
//
|
||||
|
||||
#include <dlfcn.h>
|
||||
@ -39,6 +39,7 @@
|
||||
#include "include/capi/cef_response_capi.h"
|
||||
#include "include/capi/cef_scheme_capi.h"
|
||||
#include "include/capi/cef_server_capi.h"
|
||||
#include "include/capi/cef_shared_process_message_builder_capi.h"
|
||||
#include "include/capi/cef_ssl_info_capi.h"
|
||||
#include "include/capi/cef_stream_capi.h"
|
||||
#include "include/capi/cef_task_capi.h"
|
||||
@ -219,6 +220,9 @@ typedef void (*cef_server_create_ptr)(const cef_string_t*,
|
||||
uint16,
|
||||
int,
|
||||
struct _cef_server_handler_t*);
|
||||
typedef struct _cef_shared_process_message_builder_t* (
|
||||
*cef_shared_process_message_builder_create_ptr)(const cef_string_t*,
|
||||
size_t);
|
||||
typedef struct _cef_stream_reader_t* (*cef_stream_reader_create_for_file_ptr)(
|
||||
const cef_string_t*);
|
||||
typedef struct _cef_stream_reader_t* (
|
||||
@ -580,6 +584,8 @@ struct libcef_pointers {
|
||||
cef_resource_bundle_get_global_ptr cef_resource_bundle_get_global;
|
||||
cef_response_create_ptr cef_response_create;
|
||||
cef_server_create_ptr cef_server_create;
|
||||
cef_shared_process_message_builder_create_ptr
|
||||
cef_shared_process_message_builder_create;
|
||||
cef_stream_reader_create_for_file_ptr cef_stream_reader_create_for_file;
|
||||
cef_stream_reader_create_for_data_ptr cef_stream_reader_create_for_data;
|
||||
cef_stream_reader_create_for_handler_ptr cef_stream_reader_create_for_handler;
|
||||
@ -789,6 +795,7 @@ int libcef_init_pointers(const char* path) {
|
||||
INIT_ENTRY(cef_resource_bundle_get_global);
|
||||
INIT_ENTRY(cef_response_create);
|
||||
INIT_ENTRY(cef_server_create);
|
||||
INIT_ENTRY(cef_shared_process_message_builder_create);
|
||||
INIT_ENTRY(cef_stream_reader_create_for_file);
|
||||
INIT_ENTRY(cef_stream_reader_create_for_data);
|
||||
INIT_ENTRY(cef_stream_reader_create_for_handler);
|
||||
@ -1341,6 +1348,14 @@ void cef_server_create(const cef_string_t* address,
|
||||
g_libcef_pointers.cef_server_create(address, port, backlog, handler);
|
||||
}
|
||||
|
||||
NO_SANITIZE("cfi-icall")
|
||||
struct _cef_shared_process_message_builder_t*
|
||||
cef_shared_process_message_builder_create(const cef_string_t* name,
|
||||
size_t byte_size) {
|
||||
return g_libcef_pointers.cef_shared_process_message_builder_create(name,
|
||||
byte_size);
|
||||
}
|
||||
|
||||
NO_SANITIZE("cfi-icall")
|
||||
struct _cef_stream_reader_t* cef_stream_reader_create_for_file(
|
||||
const cef_string_t* fileName) {
|
||||
|
@ -9,7 +9,7 @@
|
||||
// implementations. See the translator.README.txt file in the tools directory
|
||||
// for more information.
|
||||
//
|
||||
// $hash=54ed016f3b2bbffebc96ac9cadd3c3986d240342$
|
||||
// $hash=27716558f027af36498437317407384392a34b71$
|
||||
//
|
||||
|
||||
#ifndef CEF_LIBCEF_DLL_WRAPPER_TYPES_H_
|
||||
@ -133,6 +133,8 @@ enum CefWrapperType {
|
||||
WT_SERVER,
|
||||
WT_SERVER_HANDLER,
|
||||
WT_SET_COOKIE_CALLBACK,
|
||||
WT_SHARED_MEMORY_REGION,
|
||||
WT_SHARED_PROCESS_MESSAGE_BUILDER,
|
||||
WT_STREAM_READER,
|
||||
WT_STREAM_WRITER,
|
||||
WT_STRING_VISITOR,
|
||||
|
@ -16,6 +16,7 @@
|
||||
#include "include/cef_command_ids.h"
|
||||
#include "include/cef_frame.h"
|
||||
#include "include/cef_parser.h"
|
||||
#include "include/cef_shared_process_message_builder.h"
|
||||
#include "include/cef_ssl_status.h"
|
||||
#include "include/cef_x509_certificate.h"
|
||||
#include "include/wrapper/cef_closure_task.h"
|
||||
@ -24,6 +25,7 @@
|
||||
#include "tests/cefclient/browser/test_runner.h"
|
||||
#include "tests/shared/browser/extension_util.h"
|
||||
#include "tests/shared/browser/resource_util.h"
|
||||
#include "tests/shared/common/binary_value_utils.h"
|
||||
#include "tests/shared/common/client_switches.h"
|
||||
|
||||
namespace client {
|
||||
@ -52,7 +54,7 @@ enum client_menu_ids {
|
||||
CLIENT_ID_TESTMENU_RADIOITEM3,
|
||||
};
|
||||
|
||||
// Musr match the value in client_renderer.cc.
|
||||
// Must match the value in client_renderer.cc.
|
||||
const char kFocusedNodeChangedMessage[] = "ClientRenderer.FocusedNodeChanged";
|
||||
|
||||
std::string GetTimeString(const CefTime& value) {
|
||||
@ -224,6 +226,66 @@ std::string GetCertificateInformation(CefRefPtr<CefX509Certificate> cert,
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
void OnTestProcessMessageReceived(
|
||||
const CefRefPtr<CefFrame>& frame,
|
||||
const CefRefPtr<CefProcessMessage>& process_message,
|
||||
const bv_utils::TimePoint& finish_time) {
|
||||
DCHECK(process_message->IsValid());
|
||||
|
||||
CefRefPtr<CefListValue> input_args = process_message->GetArgumentList();
|
||||
DCHECK_EQ(input_args->GetSize(), 1U);
|
||||
|
||||
const auto renderer_msg =
|
||||
bv_utils::GetRendererMsgFromBinary(input_args->GetBinary(0));
|
||||
|
||||
CefRefPtr<CefProcessMessage> response =
|
||||
CefProcessMessage::Create(bv_utils::kTestSendProcessMessage);
|
||||
CefRefPtr<CefListValue> args = response->GetArgumentList();
|
||||
|
||||
const auto message_size = std::max(input_args->GetBinary(0)->GetSize(),
|
||||
sizeof(bv_utils::BrowserMessage));
|
||||
std::vector<uint8_t> data(message_size);
|
||||
|
||||
const auto browser_msg =
|
||||
reinterpret_cast<bv_utils::BrowserMessage*>(data.data());
|
||||
browser_msg->test_id = renderer_msg.test_id;
|
||||
browser_msg->duration = finish_time - renderer_msg.start_time;
|
||||
browser_msg->start_time = bv_utils::Now();
|
||||
|
||||
args->SetBinary(0, bv_utils::CreateCefBinaryValue(data));
|
||||
frame->SendProcessMessage(PID_RENDERER, response);
|
||||
}
|
||||
|
||||
void OnTestSMRProcessMessageReceived(
|
||||
const CefRefPtr<CefFrame>& frame,
|
||||
const CefRefPtr<CefProcessMessage>& process_message,
|
||||
const bv_utils::TimePoint& finish_time) {
|
||||
DCHECK(process_message->IsValid());
|
||||
|
||||
CefRefPtr<CefSharedMemoryRegion> region =
|
||||
process_message->GetSharedMemoryRegion();
|
||||
DCHECK_GE(region->Size(), sizeof(bv_utils::RendererMessage));
|
||||
|
||||
const auto renderer_msg =
|
||||
static_cast<const bv_utils::RendererMessage*>(region->Memory());
|
||||
const auto message_size =
|
||||
std::max(region->Size(), sizeof(bv_utils::BrowserMessage));
|
||||
const auto renderer_time = renderer_msg->start_time;
|
||||
const auto duration = finish_time - renderer_time;
|
||||
const auto start_time = bv_utils::Now();
|
||||
|
||||
auto builder = CefSharedProcessMessageBuilder::Create(
|
||||
bv_utils::kTestSendSMRProcessMessage, message_size);
|
||||
|
||||
const auto browser_msg =
|
||||
static_cast<bv_utils::BrowserMessage*>(builder->Memory());
|
||||
browser_msg->test_id = renderer_msg->test_id;
|
||||
browser_msg->duration = duration;
|
||||
browser_msg->start_time = start_time;
|
||||
|
||||
frame->SendProcessMessage(PID_RENDERER, builder->Build());
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
class ClientDownloadImageCallback : public CefDownloadImageCallback {
|
||||
@ -332,13 +394,15 @@ bool ClientHandler::OnProcessMessageReceived(
|
||||
CefRefPtr<CefProcessMessage> message) {
|
||||
CEF_REQUIRE_UI_THREAD();
|
||||
|
||||
const auto finish_time = bv_utils::Now();
|
||||
|
||||
if (message_router_->OnProcessMessageReceived(browser, frame, source_process,
|
||||
message)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Check for messages from the client renderer.
|
||||
std::string message_name = message->GetName();
|
||||
const std::string& message_name = message->GetName();
|
||||
if (message_name == kFocusedNodeChangedMessage) {
|
||||
// A message is sent from ClientRenderDelegate to tell us whether the
|
||||
// currently focused DOM node is editable. Use of |focus_on_editable_field_|
|
||||
@ -348,6 +412,16 @@ bool ClientHandler::OnProcessMessageReceived(
|
||||
return true;
|
||||
}
|
||||
|
||||
if (message_name == bv_utils::kTestSendProcessMessage) {
|
||||
OnTestProcessMessageReceived(frame, message, finish_time);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (message_name == bv_utils::kTestSendSMRProcessMessage) {
|
||||
OnTestSMRProcessMessageReceived(frame, message, finish_time);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -46,27 +46,28 @@
|
||||
#define IDS_BINDING_HTML 1000
|
||||
#define IDS_DIALOGS_HTML 1001
|
||||
#define IDS_DRAGGABLE_HTML 1002
|
||||
#define IDS_LOCALSTORAGE_HTML 1003
|
||||
#define IDS_LOGO_PNG 1004
|
||||
#define IDS_MEDIA_ROUTER_HTML 1005
|
||||
#define IDS_MENU_ICON_1X_PNG 1006
|
||||
#define IDS_MENU_ICON_2X_PNG 1007
|
||||
#define IDS_OSRTEST_HTML 1008
|
||||
#define IDS_OTHER_TESTS_HTML 1009
|
||||
#define IDS_PDF_HTML 1010
|
||||
#define IDS_PDF_PDF 1011
|
||||
#define IDS_PERFORMANCE_HTML 1012
|
||||
#define IDS_PERFORMANCE2_HTML 1013
|
||||
#define IDS_PREFERENCES_HTML 1014
|
||||
#define IDS_RESPONSE_FILTER_HTML 1015
|
||||
#define IDS_SERVER_HTML 1016
|
||||
#define IDS_TRANSPARENCY_HTML 1017
|
||||
#define IDS_URLREQUEST_HTML 1018
|
||||
#define IDS_WEBSOCKET_HTML 1019
|
||||
#define IDS_WINDOW_HTML 1020
|
||||
#define IDS_WINDOW_ICON_1X_PNG 1021
|
||||
#define IDS_WINDOW_ICON_2X_PNG 1022
|
||||
#define IDS_XMLHTTPREQUEST_HTML 1023
|
||||
#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_EXTENSIONS_SET_PAGE_COLOR_ICON_PNG 1030
|
||||
#define IDS_EXTENSIONS_SET_PAGE_COLOR_MANIFEST_JSON 1031
|
||||
|
@ -13,40 +13,40 @@ int GetResourceId(const char* resource_name) {
|
||||
static struct _resource_map {
|
||||
const char* name;
|
||||
int id;
|
||||
} resource_map[] = {
|
||||
{"binding.html", IDS_BINDING_HTML},
|
||||
{"dialogs.html", IDS_DIALOGS_HTML},
|
||||
{"draggable.html", IDS_DRAGGABLE_HTML},
|
||||
{"extensions/set_page_color/icon.png",
|
||||
IDS_EXTENSIONS_SET_PAGE_COLOR_ICON_PNG},
|
||||
{"extensions/set_page_color/manifest.json",
|
||||
IDS_EXTENSIONS_SET_PAGE_COLOR_MANIFEST_JSON},
|
||||
{"extensions/set_page_color/popup.html",
|
||||
IDS_EXTENSIONS_SET_PAGE_COLOR_POPUP_HTML},
|
||||
{"extensions/set_page_color/popup.js",
|
||||
IDS_EXTENSIONS_SET_PAGE_COLOR_POPUP_JS},
|
||||
{"localstorage.html", IDS_LOCALSTORAGE_HTML},
|
||||
{"logo.png", IDS_LOGO_PNG},
|
||||
{"media_router.html", IDS_MEDIA_ROUTER_HTML},
|
||||
{"menu_icon.1x.png", IDS_MENU_ICON_1X_PNG},
|
||||
{"menu_icon.2x.png", IDS_MENU_ICON_2X_PNG},
|
||||
{"osr_test.html", IDS_OSRTEST_HTML},
|
||||
{"other_tests.html", IDS_OTHER_TESTS_HTML},
|
||||
{"pdf.html", IDS_PDF_HTML},
|
||||
{"pdf.pdf", IDS_PDF_PDF},
|
||||
{"performance.html", IDS_PERFORMANCE_HTML},
|
||||
{"performance2.html", IDS_PERFORMANCE2_HTML},
|
||||
{"preferences.html", IDS_PREFERENCES_HTML},
|
||||
{"response_filter.html", IDS_RESPONSE_FILTER_HTML},
|
||||
{"server.html", IDS_SERVER_HTML},
|
||||
{"transparency.html", IDS_TRANSPARENCY_HTML},
|
||||
{"urlrequest.html", IDS_URLREQUEST_HTML},
|
||||
{"websocket.html", IDS_WEBSOCKET_HTML},
|
||||
{"window.html", IDS_WINDOW_HTML},
|
||||
{"window_icon.1x.png", IDS_WINDOW_ICON_1X_PNG},
|
||||
{"window_icon.2x.png", IDS_WINDOW_ICON_2X_PNG},
|
||||
{"xmlhttprequest.html", IDS_XMLHTTPREQUEST_HTML},
|
||||
};
|
||||
} resource_map[] = {{"binding.html", IDS_BINDING_HTML},
|
||||
{"dialogs.html", IDS_DIALOGS_HTML},
|
||||
{"draggable.html", IDS_DRAGGABLE_HTML},
|
||||
{"extensions/set_page_color/icon.png",
|
||||
IDS_EXTENSIONS_SET_PAGE_COLOR_ICON_PNG},
|
||||
{"extensions/set_page_color/manifest.json",
|
||||
IDS_EXTENSIONS_SET_PAGE_COLOR_MANIFEST_JSON},
|
||||
{"extensions/set_page_color/popup.html",
|
||||
IDS_EXTENSIONS_SET_PAGE_COLOR_POPUP_HTML},
|
||||
{"extensions/set_page_color/popup.js",
|
||||
IDS_EXTENSIONS_SET_PAGE_COLOR_POPUP_JS},
|
||||
{"ipc_performance.html", IDS_IPC_PERFORMANCE_HTML},
|
||||
{"localstorage.html", IDS_LOCALSTORAGE_HTML},
|
||||
{"logo.png", IDS_LOGO_PNG},
|
||||
{"media_router.html", IDS_MEDIA_ROUTER_HTML},
|
||||
{"menu_icon.1x.png", IDS_MENU_ICON_1X_PNG},
|
||||
{"menu_icon.2x.png", IDS_MENU_ICON_2X_PNG},
|
||||
{"osr_test.html", IDS_OSRTEST_HTML},
|
||||
{"other_tests.html", IDS_OTHER_TESTS_HTML},
|
||||
{"pdf.html", IDS_PDF_HTML},
|
||||
{"pdf.pdf", IDS_PDF_PDF},
|
||||
{"performance.html", IDS_PERFORMANCE_HTML},
|
||||
{"performance2.html", IDS_PERFORMANCE2_HTML},
|
||||
{"preferences.html", IDS_PREFERENCES_HTML},
|
||||
{"response_filter.html", IDS_RESPONSE_FILTER_HTML},
|
||||
{"server.html", IDS_SERVER_HTML},
|
||||
{"transparency.html", IDS_TRANSPARENCY_HTML},
|
||||
{"urlrequest.html", IDS_URLREQUEST_HTML},
|
||||
{"websocket.html", IDS_WEBSOCKET_HTML},
|
||||
{"window.html", IDS_WINDOW_HTML},
|
||||
{"window_icon.1x.png", IDS_WINDOW_ICON_1X_PNG},
|
||||
{"window_icon.2x.png", IDS_WINDOW_ICON_2X_PNG},
|
||||
{"xmlhttprequest.html", IDS_XMLHTTPREQUEST_HTML},
|
||||
{"xmlhttprequest.html", IDS_XMLHTTPREQUEST_HTML}};
|
||||
|
||||
for (size_t i = 0; i < sizeof(resource_map) / sizeof(_resource_map); ++i) {
|
||||
if (!strcmp(resource_map[i].name, resource_name))
|
||||
|
@ -3,6 +3,7 @@
|
||||
// can be found in the LICENSE file.
|
||||
|
||||
#include "tests/cefclient/renderer/client_renderer.h"
|
||||
#include "tests/cefclient/renderer/ipc_performance_test.h"
|
||||
#include "tests/cefclient/renderer/performance_test.h"
|
||||
#include "tests/shared/renderer/client_app_renderer.h"
|
||||
|
||||
@ -12,6 +13,7 @@ namespace client {
|
||||
void ClientAppRenderer::CreateDelegates(DelegateSet& delegates) {
|
||||
renderer::CreateDelegates(delegates);
|
||||
performance_test::CreateDelegates(delegates);
|
||||
ipc_performance_test::CreateDelegates(delegates);
|
||||
}
|
||||
|
||||
} // namespace client
|
||||
|
249
tests/cefclient/renderer/ipc_performance_test.cc
Normal file
249
tests/cefclient/renderer/ipc_performance_test.cc
Normal file
@ -0,0 +1,249 @@
|
||||
// Copyright (c) 2022 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/renderer/ipc_performance_test.h"
|
||||
|
||||
#include "include/cef_shared_process_message_builder.h"
|
||||
#include "include/wrapper/cef_helpers.h"
|
||||
#include "tests/shared/common/binary_value_utils.h"
|
||||
|
||||
namespace {
|
||||
|
||||
// JS object member names.
|
||||
constexpr char kMessageSize[] = "size";
|
||||
constexpr char kTestId[] = "testId";
|
||||
constexpr CefV8Value::PropertyAttribute kAttributes =
|
||||
static_cast<CefV8Value::PropertyAttribute>(
|
||||
V8_PROPERTY_ATTRIBUTE_READONLY | V8_PROPERTY_ATTRIBUTE_DONTENUM |
|
||||
V8_PROPERTY_ATTRIBUTE_DONTDELETE);
|
||||
|
||||
struct TestInfo {
|
||||
size_t message_size = 0;
|
||||
int id = 0;
|
||||
bool is_valid = false;
|
||||
};
|
||||
|
||||
TestInfo GetTest(const CefV8ValueList& arguments, CefString& exception) {
|
||||
TestInfo info{};
|
||||
|
||||
if (arguments.size() != 1 || !arguments[0]->IsObject()) {
|
||||
exception = "Invalid arguments; expecting a single object";
|
||||
return info;
|
||||
}
|
||||
|
||||
CefRefPtr<CefV8Value> arg = arguments[0];
|
||||
CefRefPtr<CefV8Value> message_size = arg->GetValue(kMessageSize);
|
||||
if (!message_size.get() || !message_size->IsInt()) {
|
||||
exception =
|
||||
"Invalid arguments; object member 'size' is required and must have "
|
||||
"integer type";
|
||||
return info;
|
||||
}
|
||||
|
||||
if (message_size->GetIntValue() < 1) {
|
||||
exception =
|
||||
"Invalid arguments; object member 'size' must be "
|
||||
"positive";
|
||||
return info;
|
||||
}
|
||||
|
||||
CefRefPtr<CefV8Value> test_id = arg->GetValue(kTestId);
|
||||
if (!message_size.get() || !message_size->IsInt()) {
|
||||
exception =
|
||||
"Invalid arguments; object member 'testId' is required and must "
|
||||
"have integer type";
|
||||
return info;
|
||||
}
|
||||
|
||||
info.message_size = static_cast<size_t>(message_size->GetIntValue());
|
||||
info.id = test_id->GetIntValue();
|
||||
info.is_valid = true;
|
||||
|
||||
return info;
|
||||
}
|
||||
|
||||
// Handle bindings in the render process.
|
||||
class IpcDelegate final : public client::ClientAppRenderer::Delegate {
|
||||
public:
|
||||
class V8HandlerImpl final : public CefV8Handler {
|
||||
public:
|
||||
explicit V8HandlerImpl(const CefRefPtr<IpcDelegate>& delegate)
|
||||
: delegate_(delegate) {}
|
||||
V8HandlerImpl(const V8HandlerImpl&) = delete;
|
||||
V8HandlerImpl& operator=(const V8HandlerImpl&) = delete;
|
||||
|
||||
bool Execute(const CefString& name,
|
||||
CefRefPtr<CefV8Value> object,
|
||||
const CefV8ValueList& arguments,
|
||||
CefRefPtr<CefV8Value>& retval,
|
||||
CefString& exception) override {
|
||||
if (name == bv_utils::kTestSendProcessMessage) {
|
||||
const auto test = GetTest(arguments, exception);
|
||||
if (test.is_valid) {
|
||||
SendTestProcessMessage(test.message_size, test.id);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
if (name == bv_utils::kTestSendSMRProcessMessage) {
|
||||
const auto test = GetTest(arguments, exception);
|
||||
if (test.is_valid) {
|
||||
SendTestSMRProcessMessage(test.message_size, test.id);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private:
|
||||
void SendTestProcessMessage(int message_size, int test_id) {
|
||||
auto context = CefV8Context::GetCurrentContext();
|
||||
delegate_->SendTestProcessMessage(context->GetFrame(), message_size,
|
||||
test_id);
|
||||
}
|
||||
|
||||
void SendTestSMRProcessMessage(int message_size, int test_id) {
|
||||
auto context = CefV8Context::GetCurrentContext();
|
||||
delegate_->SendTestSMRProcessMessage(context->GetFrame(), message_size,
|
||||
test_id);
|
||||
}
|
||||
|
||||
CefRefPtr<IpcDelegate> delegate_;
|
||||
IMPLEMENT_REFCOUNTING(V8HandlerImpl);
|
||||
};
|
||||
|
||||
IpcDelegate() = default;
|
||||
IpcDelegate(const IpcDelegate&) = delete;
|
||||
IpcDelegate& operator=(const IpcDelegate&) = delete;
|
||||
|
||||
void OnContextCreated(CefRefPtr<client::ClientAppRenderer> app,
|
||||
CefRefPtr<CefBrowser> browser,
|
||||
CefRefPtr<CefFrame> frame,
|
||||
CefRefPtr<CefV8Context> context) override {
|
||||
CEF_REQUIRE_RENDERER_THREAD();
|
||||
|
||||
CefRefPtr<CefV8Handler> handler = new V8HandlerImpl(this);
|
||||
|
||||
// Register function handlers with the 'window' object.
|
||||
auto window = context->GetGlobal();
|
||||
window->SetValue(
|
||||
bv_utils::kTestSendProcessMessage,
|
||||
CefV8Value::CreateFunction(bv_utils::kTestSendProcessMessage, handler),
|
||||
kAttributes);
|
||||
|
||||
window->SetValue(bv_utils::kTestSendSMRProcessMessage,
|
||||
CefV8Value::CreateFunction(
|
||||
bv_utils::kTestSendSMRProcessMessage, handler),
|
||||
kAttributes);
|
||||
}
|
||||
|
||||
bool OnProcessMessageReceived(CefRefPtr<client::ClientAppRenderer> app,
|
||||
CefRefPtr<CefBrowser> browser,
|
||||
CefRefPtr<CefFrame> frame,
|
||||
CefProcessId source_process,
|
||||
CefRefPtr<CefProcessMessage> message) override {
|
||||
CEF_REQUIRE_RENDERER_THREAD();
|
||||
const auto finish_time = bv_utils::Now();
|
||||
|
||||
if (message->GetName() == bv_utils::kTestSendProcessMessage) {
|
||||
auto args = message->GetArgumentList();
|
||||
DCHECK_EQ(args->GetSize(), 1U);
|
||||
|
||||
const auto browser_msg =
|
||||
bv_utils::GetBrowserMsgFromBinary(args->GetBinary(0));
|
||||
PassTestResultToJs(frame, finish_time, browser_msg);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
if (message->GetName() == bv_utils::kTestSendSMRProcessMessage) {
|
||||
const auto region = message->GetSharedMemoryRegion();
|
||||
DCHECK(region->IsValid());
|
||||
DCHECK_GE(region->Size(), sizeof(bv_utils::BrowserMessage));
|
||||
|
||||
const auto browser_msg =
|
||||
static_cast<const bv_utils::BrowserMessage*>(region->Memory());
|
||||
|
||||
PassTestResultToJs(frame, finish_time, *browser_msg);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private:
|
||||
IMPLEMENT_REFCOUNTING(IpcDelegate);
|
||||
|
||||
void SendTestProcessMessage(CefRefPtr<CefFrame> frame,
|
||||
size_t message_size,
|
||||
int test_id) {
|
||||
CEF_REQUIRE_RENDERER_THREAD();
|
||||
|
||||
auto process_message =
|
||||
CefProcessMessage::Create(bv_utils::kTestSendProcessMessage);
|
||||
auto args = process_message->GetArgumentList();
|
||||
|
||||
const auto buffer_size =
|
||||
std::max(message_size, sizeof(bv_utils::RendererMessage));
|
||||
std::vector<uint8_t> buffer(buffer_size);
|
||||
|
||||
const auto renderer_msg =
|
||||
reinterpret_cast<bv_utils::RendererMessage*>(buffer.data());
|
||||
|
||||
renderer_msg->test_id = test_id;
|
||||
renderer_msg->start_time = bv_utils::Now();
|
||||
|
||||
args->SetBinary(0, bv_utils::CreateCefBinaryValue(buffer));
|
||||
frame->SendProcessMessage(PID_BROWSER, process_message);
|
||||
}
|
||||
|
||||
void SendTestSMRProcessMessage(CefRefPtr<CefFrame> frame,
|
||||
size_t message_size,
|
||||
int test_id) {
|
||||
CEF_REQUIRE_RENDERER_THREAD();
|
||||
|
||||
const auto buffer_size =
|
||||
std::max(message_size, sizeof(bv_utils::RendererMessage));
|
||||
const auto start_time = bv_utils::Now();
|
||||
|
||||
auto builder = CefSharedProcessMessageBuilder::Create(
|
||||
bv_utils::kTestSendSMRProcessMessage, buffer_size);
|
||||
|
||||
auto renderer_msg =
|
||||
static_cast<bv_utils::RendererMessage*>(builder->Memory());
|
||||
renderer_msg->test_id = test_id;
|
||||
renderer_msg->start_time = start_time;
|
||||
|
||||
frame->SendProcessMessage(PID_BROWSER, builder->Build());
|
||||
}
|
||||
|
||||
// Execute the onSuccess JavaScript callback.
|
||||
void PassTestResultToJs(CefRefPtr<CefFrame> frame,
|
||||
const bv_utils::TimePoint& finish_time,
|
||||
const bv_utils::BrowserMessage& msg) {
|
||||
const auto rendered_to_browser = msg.duration;
|
||||
const auto browser_to_rendered = finish_time - msg.start_time;
|
||||
|
||||
CefString code = "testSendProcessMessageResult(" +
|
||||
std::to_string(msg.test_id) + ", " +
|
||||
bv_utils::ToMilliString(rendered_to_browser) + ", " +
|
||||
bv_utils::ToMilliString(browser_to_rendered) + ");";
|
||||
|
||||
frame->ExecuteJavaScript(code, frame->GetURL(), 0);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
namespace client {
|
||||
namespace ipc_performance_test {
|
||||
|
||||
void CreateDelegates(ClientAppRenderer::DelegateSet& delegates) {
|
||||
delegates.insert(new IpcDelegate());
|
||||
}
|
||||
|
||||
} // namespace ipc_performance_test
|
||||
} // namespace client
|
19
tests/cefclient/renderer/ipc_performance_test.h
Normal file
19
tests/cefclient/renderer/ipc_performance_test.h
Normal file
@ -0,0 +1,19 @@
|
||||
// Copyright (c) 2022 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_RENDERER_IPC_PERFORMANCE_TEST_H_
|
||||
#define CEF_TESTS_CEFCLIENT_RENDERER_IPC_PERFORMANCE_TEST_H_
|
||||
#pragma once
|
||||
|
||||
#include "tests/shared/renderer/client_app_renderer.h"
|
||||
|
||||
namespace client {
|
||||
namespace ipc_performance_test {
|
||||
|
||||
void CreateDelegates(ClientAppRenderer::DelegateSet& delegates);
|
||||
|
||||
} // namespace ipc_performance_test
|
||||
} // namespace client
|
||||
|
||||
#endif // CEF_TESTS_CEFCLIENT_RENDERER_IPC_PERFORMANCE_TEST_H_
|
448
tests/cefclient/resources/ipc_performance.html
Normal file
448
tests/cefclient/resources/ipc_performance.html
Normal file
@ -0,0 +1,448 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>IPC Performance Tests</title>
|
||||
<script src="https://cdn.plot.ly/plotly-2.12.1.min.js"></script>
|
||||
<style>
|
||||
body {
|
||||
font-family: Tahoma, Serif;
|
||||
font-size: 10pt;
|
||||
}
|
||||
|
||||
.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>IPC Performance Tests</h1>
|
||||
|
||||
<table>
|
||||
<tr>
|
||||
<td>
|
||||
<p>
|
||||
There is no progress indication of the tests because it
|
||||
significantly influences measurements. <br />It usually takes 30
|
||||
seconds (for 100 samples) to complete the tests. <br /><b>AL</b> -
|
||||
ArgumentList-based process messages. <b>SM</b> -
|
||||
SharedMemoryRegion-based process messages.
|
||||
</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
Samples:
|
||||
<input
|
||||
id="sSamples"
|
||||
type="text"
|
||||
value="100"
|
||||
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%">AL Round Trip Avg, ms</td>
|
||||
<td class="center" style="width: 8%">SM Round Trip Avg, ms</td>
|
||||
<td class="center" style="width: 10%">Relative Trip Difference</td>
|
||||
<td class="center" style="width: 8%">AL Speed, MB/s</td>
|
||||
<td class="center" style="width: 8%">SM Speed, MB/s</td>
|
||||
<td class="center" style="width: 10%">Relative Speed Difference</td>
|
||||
<td class="center" style="width: 8%">AL Standard Deviation</td>
|
||||
<td class="center" style="width: 8%">SM 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 nextTest(test) {
|
||||
setTimeout(() => {
|
||||
execNextTest(test.index);
|
||||
}, 0);
|
||||
}
|
||||
|
||||
function testSendProcessMessageResult(
|
||||
testIndex,
|
||||
fromRendererToBrowser,
|
||||
fromBrowserToRenderer
|
||||
) {
|
||||
const test = tests[testIndex];
|
||||
|
||||
const roundTrip = fromRendererToBrowser + fromBrowserToRenderer;
|
||||
test.totalRoundTrip += roundTrip;
|
||||
test.sample++;
|
||||
box_plot_test_data[testIndex].x.push(roundTrip);
|
||||
|
||||
setTimeout(() => {
|
||||
execTest(testIndex);
|
||||
}, 10);
|
||||
}
|
||||
|
||||
function sendRequest(size, testIndex) {
|
||||
window.testSendProcessMessage({
|
||||
size: size,
|
||||
testId: testIndex,
|
||||
});
|
||||
}
|
||||
|
||||
function sendSMRRequest(size, testIndex) {
|
||||
window.testSendSMRProcessMessage({
|
||||
size: size,
|
||||
testId: testIndex,
|
||||
});
|
||||
}
|
||||
|
||||
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 nextTest(test);
|
||||
}
|
||||
|
||||
test.func(test.index);
|
||||
}
|
||||
|
||||
function column(prepared, value) {
|
||||
return (
|
||||
"<td class='right'>" + (!prepared ? "-" : value.toFixed(2)) + "</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.avgRoundTripSMR),
|
||||
relativeDiffColumn(test.prepared, test.relativeTripDiff, false),
|
||||
column(test.prepared, test.speed),
|
||||
column(test.prepared, test.speedSMR),
|
||||
relativeDiffColumn(test.prepared, test.relativeSpeedDiff, true),
|
||||
"<td class='right'>",
|
||||
!test.prepared || test.stdDeviation == null
|
||||
? "-"
|
||||
: test.stdDeviation.toFixed(2),
|
||||
"</td>",
|
||||
"<td class='right'>",
|
||||
!test.prepared || test.stdDeviationSMR == null
|
||||
? "-"
|
||||
: test.stdDeviationSMR.toFixed(2),
|
||||
"</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 buildTestResults(tests) {
|
||||
testResults = [];
|
||||
|
||||
let oldRoundTrip = {
|
||||
x: [],
|
||||
y: [],
|
||||
type: "scatter",
|
||||
name: "ArgumentList",
|
||||
};
|
||||
|
||||
let newRoundTrip = {
|
||||
x: [],
|
||||
y: [],
|
||||
type: "scatter",
|
||||
name: "SharedMemoryRegion",
|
||||
};
|
||||
|
||||
for (let i = 0; i < tests.length / 2; i++) {
|
||||
const index = testResults.length;
|
||||
|
||||
const test = tests[i * 2];
|
||||
const testSMR = tests[i * 2 + 1];
|
||||
|
||||
const avgRoundTrip = test.totalRoundTrip / test.totalSamples;
|
||||
const avgRoundTripSMR = testSMR.totalRoundTrip / testSMR.totalSamples;
|
||||
const relativeTripDiff =
|
||||
((avgRoundTripSMR - avgRoundTrip) / avgRoundTrip) * 100;
|
||||
|
||||
// In MB/s
|
||||
const speed = test.messageSize / (avgRoundTrip * 1000);
|
||||
const speedSMR = testSMR.messageSize / (avgRoundTripSMR * 1000);
|
||||
const relativeSpeedDiff = ((speedSMR - speed) / speed) * 100;
|
||||
|
||||
const stdDeviation = getStandardDeviation(
|
||||
box_plot_test_data[test.index].x,
|
||||
avgRoundTrip
|
||||
);
|
||||
const stdDeviationSMR = getStandardDeviation(
|
||||
box_plot_test_data[testSMR.index].x,
|
||||
avgRoundTripSMR
|
||||
);
|
||||
|
||||
testResults.push({
|
||||
name: humanFileSize(test.messageSize),
|
||||
index: index,
|
||||
prepared: true,
|
||||
avgRoundTrip: avgRoundTrip,
|
||||
avgRoundTripSMR: avgRoundTripSMR,
|
||||
relativeTripDiff: relativeTripDiff,
|
||||
speed: speed,
|
||||
speedSMR: speedSMR,
|
||||
relativeSpeedDiff: relativeSpeedDiff,
|
||||
stdDeviation: stdDeviation,
|
||||
stdDeviationSMR: stdDeviationSMR,
|
||||
});
|
||||
|
||||
oldRoundTrip.x.push(test.messageSize);
|
||||
newRoundTrip.x.push(test.messageSize);
|
||||
oldRoundTrip.y.push(avgRoundTrip);
|
||||
newRoundTrip.y.push(avgRoundTripSMR);
|
||||
}
|
||||
|
||||
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.messageSize),
|
||||
index: index,
|
||||
prepared: false,
|
||||
});
|
||||
}
|
||||
return testResults;
|
||||
}
|
||||
|
||||
function prepareQueuedTests(totalSamples) {
|
||||
if (totalSamples <= 0) totalSamples = 1;
|
||||
|
||||
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, messageSize, testFunc) {
|
||||
const testIndex = tests.length;
|
||||
test = {
|
||||
name: name,
|
||||
messageSize: messageSize,
|
||||
index: testIndex,
|
||||
func: testFunc,
|
||||
};
|
||||
tests.push(test);
|
||||
|
||||
box_plot_test_data.push({
|
||||
x: [],
|
||||
type: "box",
|
||||
boxpoints: "all",
|
||||
name: name,
|
||||
jitter: 0.3,
|
||||
pointpos: -1.8,
|
||||
});
|
||||
}
|
||||
|
||||
function execNextTest(testIndex) {
|
||||
testIndex++;
|
||||
if (tests.length <= testIndex) {
|
||||
return testSuiteFinished();
|
||||
} else {
|
||||
return execTest(testIndex);
|
||||
}
|
||||
}
|
||||
|
||||
function execQueuedTests(totalSamples) {
|
||||
prepareQueuedTests(totalSamples);
|
||||
// Let the updated table render before starting the tests
|
||||
setTimeout(() => execNextTest(-1), 200);
|
||||
}
|
||||
|
||||
function setSettingsState(disabled) {
|
||||
document.getElementById("sSamples").disabled = disabled;
|
||||
document.getElementById("sRun").disabled = disabled;
|
||||
}
|
||||
|
||||
function testSuiteFinished() {
|
||||
testResults = buildTestResults(tests);
|
||||
testResults.forEach((result) => displayResult(result));
|
||||
|
||||
const round_trip_layout = {
|
||||
title: "Average round trip, ms (Smaller Better)",
|
||||
};
|
||||
Plotly.newPlot(
|
||||
"round_trip_avg_chart",
|
||||
round_trip_avg_plot_data,
|
||||
round_trip_layout
|
||||
);
|
||||
|
||||
const box_plot_layout = {
|
||||
title: "Round Trip Time, ms",
|
||||
};
|
||||
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);
|
||||
return false;
|
||||
};
|
||||
|
||||
for (let size = 512; size <= 512 * 1024; size = size * 2) {
|
||||
queueTest(humanFileSize(size) + " AL", size, (testIndex) =>
|
||||
sendRequest(size, testIndex)
|
||||
);
|
||||
|
||||
queueTest(humanFileSize(size) + " SM", size, (testIndex) =>
|
||||
sendSMRRequest(size, testIndex)
|
||||
);
|
||||
}
|
||||
|
||||
const totalSamples = parseInt(document.getElementById("sSamples").value);
|
||||
prepareQueuedTests(totalSamples);
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
@ -17,6 +17,7 @@
|
||||
<li><a href="http://www.html5test.com">HTML5 Feature Test</a></li>
|
||||
<li><a href="http://html5-demos.appspot.com/static/filesystem/filer.js/demos/index.html">HTML5 Filesystem</a> - requires "cache-path" flag</li>
|
||||
<li><a href="http://www.youtube.com/watch?v=siOHh0uzcuY&html5=True">HTML5 Video</a></li>
|
||||
<li><a href="ipc_performance">IPC Performance Tests</a></li>
|
||||
<li><a href="binding">JavaScript Binding</a></li>
|
||||
<li><a href="performance">JavaScript Performance Tests</a></li>
|
||||
<li><a href="performance2">JavaScript Performance (2) Tests</a></li>
|
||||
|
@ -32,6 +32,7 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
|
||||
IDS_BINDING_HTML BINARY "..\\binding.html"
|
||||
IDS_DIALOGS_HTML BINARY "..\\dialogs.html"
|
||||
IDS_DRAGGABLE_HTML BINARY "..\\draggable.html"
|
||||
IDS_IPC_PERFORMANCE_HTML BINARY "..\\ipc_performance.html"
|
||||
IDS_LOCALSTORAGE_HTML BINARY "..\\localstorage.html"
|
||||
IDS_LOGO_PNG BINARY "..\\logo.png"
|
||||
IDS_MEDIA_ROUTER_HTML BINARY "..\\media_router.html"
|
||||
|
@ -59,6 +59,11 @@ void CreateRenderDelegates(ClientAppRenderer::DelegateSet& delegates) {
|
||||
delegates);
|
||||
CreateProcessMessageRendererTests(delegates);
|
||||
|
||||
// Bring in the shared process message tests.
|
||||
extern void CreateSharedProcessMessageTests(ClientAppRenderer::DelegateSet &
|
||||
delegates);
|
||||
CreateSharedProcessMessageTests(delegates);
|
||||
|
||||
// Bring in the RequestHandler tests.
|
||||
extern void CreateRequestHandlerRendererTests(ClientAppRenderer::DelegateSet &
|
||||
delegates);
|
||||
|
81
tests/ceftests/message_router_harness_unittest.cc
Normal file
81
tests/ceftests/message_router_harness_unittest.cc
Normal file
@ -0,0 +1,81 @@
|
||||
// Copyright (c) 2022 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 {
|
||||
|
||||
// Used to verify that the test harness (bound functions) behave correctly.
|
||||
class HarnessTestHandler : public SingleLoadTestHandler {
|
||||
public:
|
||||
HarnessTestHandler(bool test_success) : test_success_(test_success) {}
|
||||
|
||||
std::string GetMainHTML() override {
|
||||
std::string html;
|
||||
if (test_success_) {
|
||||
// All assertions should pass.
|
||||
html =
|
||||
"<html><body><script>\n"
|
||||
"var fail_ct = 0;\n"
|
||||
"try { window.mrtAssertTotalCount(" LINESTR
|
||||
",0); } catch (e) { fail_ct++; }\n"
|
||||
"try { window.mrtAssertBrowserCount(" LINESTR
|
||||
",0); } catch (e) { fail_ct++; }\n"
|
||||
"try { window.mrtAssertContextCount(" LINESTR
|
||||
",0); } catch (e) { fail_ct++; }\n"
|
||||
"window.mrtNotify('' + (fail_ct == 0));"
|
||||
"</script></body></html>";
|
||||
} else {
|
||||
// All assertions should fail.
|
||||
html =
|
||||
"<html><body><script>\n"
|
||||
"var fail_ct = 0;\n"
|
||||
"try { window.mrtAssertTotalCount(" LINESTR
|
||||
",1); } catch (e) { fail_ct++; }\n"
|
||||
"try { window.mrtAssertBrowserCount(" LINESTR
|
||||
",1); } catch (e) { fail_ct++; }\n"
|
||||
"try { window.mrtAssertContextCount(" LINESTR
|
||||
",1); } catch (e) { fail_ct++; }\n"
|
||||
"window.mrtNotify('' + (fail_ct == 3));"
|
||||
"</script></body></html>";
|
||||
}
|
||||
return html;
|
||||
}
|
||||
|
||||
void OnNotify(CefRefPtr<CefBrowser> browser,
|
||||
CefRefPtr<CefFrame> frame,
|
||||
const std::string& message) override {
|
||||
AssertMainBrowser(browser);
|
||||
AssertMainFrame(frame);
|
||||
|
||||
got_done_.yes();
|
||||
EXPECT_STREQ("true", message.c_str());
|
||||
DestroyTest();
|
||||
}
|
||||
|
||||
void DestroyTest() override {
|
||||
EXPECT_TRUE(got_done_);
|
||||
TestHandler::DestroyTest();
|
||||
}
|
||||
|
||||
private:
|
||||
const bool test_success_;
|
||||
TrackCallback got_done_;
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
// Verify that the test harness works with successful assertions.
|
||||
TEST(MessageRouterTest, HarnessSuccess) {
|
||||
CefRefPtr<HarnessTestHandler> handler = new HarnessTestHandler(true);
|
||||
handler->ExecuteTest();
|
||||
ReleaseAndWaitForDestructor(handler);
|
||||
}
|
||||
|
||||
// Verify that the test harness works with failed assertions.
|
||||
TEST(MessageRouterTest, HarnessFailure) {
|
||||
CefRefPtr<HarnessTestHandler> handler = new HarnessTestHandler(false);
|
||||
handler->ExecuteTest();
|
||||
ReleaseAndWaitForDestructor(handler);
|
||||
}
|
File diff suppressed because it is too large
Load Diff
623
tests/ceftests/message_router_single_query_unittest.cc
Normal file
623
tests/ceftests/message_router_single_query_unittest.cc
Normal file
@ -0,0 +1,623 @@
|
||||
// Copyright (c) 2022 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 {
|
||||
|
||||
const char kSingleQueryRequest[] = "request_context";
|
||||
const char kSingleQueryResponse[] = "success_response";
|
||||
const int kSingleQueryErrorCode = 5;
|
||||
const char kSingleQueryErrorMessage[] = "error_message";
|
||||
|
||||
// Test a single query in a single page load.
|
||||
class SingleQueryTestHandler : public SingleLoadTestHandler {
|
||||
public:
|
||||
enum TestType {
|
||||
SUCCESS,
|
||||
FAILURE,
|
||||
CANCEL,
|
||||
};
|
||||
|
||||
SingleQueryTestHandler(TestType type, bool sync_callback)
|
||||
: test_type_(type), sync_callback_(sync_callback), query_id_(0) {}
|
||||
|
||||
std::string GetMainHTML() override {
|
||||
std::string html;
|
||||
|
||||
std::stringstream ss;
|
||||
ss << kSingleQueryErrorCode;
|
||||
const std::string& errorCodeStr = ss.str();
|
||||
|
||||
html =
|
||||
"<html><body><script>\n"
|
||||
// No requests should exist.
|
||||
"window.mrtAssertTotalCount(" LINESTR
|
||||
",0);\n"
|
||||
"window.mrtAssertBrowserCount(" LINESTR
|
||||
",0);\n"
|
||||
"window.mrtAssertContextCount(" LINESTR
|
||||
",0);\n"
|
||||
// Send the query.
|
||||
"var request_id = window.mrtQuery({\n"
|
||||
" request: '" +
|
||||
std::string(kSingleQueryRequest) +
|
||||
"',\n"
|
||||
" persistent: false,\n"
|
||||
" onSuccess: function(response) {\n"
|
||||
// Request should be removed before callback is executed.
|
||||
" window.mrtAssertTotalCount(" LINESTR
|
||||
",0);\n"
|
||||
" window.mrtAssertBrowserCount(" LINESTR
|
||||
",0);\n"
|
||||
" window.mrtAssertContextCount(" LINESTR
|
||||
",0);\n"
|
||||
" if (response == '" +
|
||||
std::string(kSingleQueryResponse) +
|
||||
"')\n"
|
||||
" window.mrtNotify('success');\n"
|
||||
" else\n"
|
||||
" window.mrtNotify('error-onSuccess');\n"
|
||||
" },\n"
|
||||
" onFailure: function(error_code, error_message) {\n"
|
||||
// Request should be removed before callback is executed.
|
||||
" window.mrtAssertTotalCount(" LINESTR
|
||||
",0);\n"
|
||||
" window.mrtAssertBrowserCount(" LINESTR
|
||||
",0);\n"
|
||||
" window.mrtAssertContextCount(" LINESTR
|
||||
",0);\n"
|
||||
" if (error_code == " +
|
||||
errorCodeStr + " && error_message == '" +
|
||||
std::string(kSingleQueryErrorMessage) +
|
||||
"')\n"
|
||||
" window.mrtNotify('failure');\n"
|
||||
" else\n"
|
||||
" window.mrtNotify('error-onFailure');\n"
|
||||
" }\n"
|
||||
"});\n"
|
||||
// Request should exist.
|
||||
"window.mrtAssertTotalCount(" LINESTR
|
||||
",1);\n"
|
||||
"window.mrtAssertBrowserCount(" LINESTR
|
||||
",1);\n"
|
||||
"window.mrtAssertContextCount(" LINESTR ",1);\n";
|
||||
|
||||
if (test_type_ == CANCEL) {
|
||||
html +=
|
||||
"window.mrtQueryCancel(request_id);\n"
|
||||
// Request should be removed immediately.
|
||||
"window.mrtAssertTotalCount(" LINESTR
|
||||
",0);\n"
|
||||
"window.mrtAssertBrowserCount(" LINESTR
|
||||
",0);\n"
|
||||
"window.mrtAssertContextCount(" LINESTR
|
||||
",0);\n"
|
||||
"window.mrtNotify('cancel');\n";
|
||||
}
|
||||
|
||||
html += "</script></body></html>";
|
||||
return 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();
|
||||
|
||||
if (test_type_ == SUCCESS) {
|
||||
EXPECT_STREQ("success", message.c_str());
|
||||
} else if (test_type_ == FAILURE) {
|
||||
EXPECT_STREQ("failure", message.c_str());
|
||||
} else if (test_type_ == CANCEL) {
|
||||
EXPECT_STREQ("cancel", message.c_str());
|
||||
}
|
||||
|
||||
DestroyTestIfDone();
|
||||
}
|
||||
|
||||
void ExecuteCallback() {
|
||||
EXPECT_TRUE(callback_.get());
|
||||
if (test_type_ == SUCCESS) {
|
||||
callback_->Success(kSingleQueryResponse);
|
||||
} else if (test_type_ == FAILURE) {
|
||||
callback_->Failure(kSingleQueryErrorCode, kSingleQueryErrorMessage);
|
||||
} else {
|
||||
ADD_FAILURE(); // Not reached.
|
||||
}
|
||||
callback_ = nullptr;
|
||||
}
|
||||
|
||||
bool OnQuery(CefRefPtr<CefBrowser> browser,
|
||||
CefRefPtr<CefFrame> frame,
|
||||
int64 query_id,
|
||||
const CefString& request,
|
||||
bool persistent,
|
||||
CefRefPtr<Callback> callback) override {
|
||||
AssertMainBrowser(browser);
|
||||
AssertMainFrame(frame);
|
||||
EXPECT_NE(0, query_id);
|
||||
EXPECT_FALSE(persistent);
|
||||
EXPECT_STREQ(kSingleQueryRequest, request.ToString().c_str());
|
||||
|
||||
got_on_query_.yes();
|
||||
|
||||
query_id_ = query_id;
|
||||
callback_ = callback;
|
||||
|
||||
if (test_type_ == SUCCESS || test_type_ == FAILURE) {
|
||||
if (sync_callback_) {
|
||||
ExecuteCallback();
|
||||
} else {
|
||||
CefPostTask(
|
||||
TID_UI,
|
||||
base::BindOnce(&SingleQueryTestHandler::ExecuteCallback, this));
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void OnQueryCanceled(CefRefPtr<CefBrowser> browser,
|
||||
CefRefPtr<CefFrame> frame,
|
||||
int64 query_id) override {
|
||||
AssertMainBrowser(browser);
|
||||
AssertMainFrame(frame);
|
||||
EXPECT_EQ(test_type_, CANCEL);
|
||||
EXPECT_EQ(query_id_, query_id);
|
||||
EXPECT_TRUE(got_on_query_);
|
||||
EXPECT_TRUE(callback_.get());
|
||||
|
||||
got_on_query_canceled_.yes();
|
||||
callback_ = nullptr;
|
||||
|
||||
DestroyTestIfDone();
|
||||
}
|
||||
|
||||
void DestroyTestIfDone() {
|
||||
bool destroy_test = false;
|
||||
if (test_type_ == CANCEL)
|
||||
destroy_test = got_notify_ && got_on_query_canceled_;
|
||||
else
|
||||
destroy_test = got_notify_;
|
||||
if (destroy_test)
|
||||
DestroyTest();
|
||||
}
|
||||
|
||||
void DestroyTest() override {
|
||||
EXPECT_TRUE(got_notify_);
|
||||
EXPECT_TRUE(got_on_query_);
|
||||
EXPECT_FALSE(callback_.get());
|
||||
|
||||
if (test_type_ == CANCEL)
|
||||
EXPECT_TRUE(got_on_query_canceled_);
|
||||
else
|
||||
EXPECT_FALSE(got_on_query_canceled_);
|
||||
|
||||
TestHandler::DestroyTest();
|
||||
}
|
||||
|
||||
private:
|
||||
const TestType test_type_;
|
||||
const bool sync_callback_;
|
||||
|
||||
int64 query_id_;
|
||||
CefRefPtr<Callback> callback_;
|
||||
|
||||
TrackCallback got_on_query_;
|
||||
TrackCallback got_on_query_canceled_;
|
||||
TrackCallback got_notify_;
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
// Test that a single query with successful result delivered synchronously.
|
||||
TEST(MessageRouterTest, SingleQuerySuccessSyncCallback) {
|
||||
CefRefPtr<SingleQueryTestHandler> handler =
|
||||
new SingleQueryTestHandler(SingleQueryTestHandler::SUCCESS, true);
|
||||
handler->ExecuteTest();
|
||||
ReleaseAndWaitForDestructor(handler);
|
||||
}
|
||||
|
||||
// Test that a single query with successful result delivered asynchronously.
|
||||
TEST(MessageRouterTest, SingleQuerySuccessAsyncCallback) {
|
||||
CefRefPtr<SingleQueryTestHandler> handler =
|
||||
new SingleQueryTestHandler(SingleQueryTestHandler::SUCCESS, false);
|
||||
handler->ExecuteTest();
|
||||
ReleaseAndWaitForDestructor(handler);
|
||||
}
|
||||
|
||||
// Test that a single query with failure result delivered synchronously.
|
||||
TEST(MessageRouterTest, SingleQueryFailureSyncCallback) {
|
||||
CefRefPtr<SingleQueryTestHandler> handler =
|
||||
new SingleQueryTestHandler(SingleQueryTestHandler::FAILURE, true);
|
||||
handler->ExecuteTest();
|
||||
ReleaseAndWaitForDestructor(handler);
|
||||
}
|
||||
|
||||
// Test that a single query with failure result delivered asynchronously.
|
||||
TEST(MessageRouterTest, SingleQueryFailureAsyncCallback) {
|
||||
CefRefPtr<SingleQueryTestHandler> handler =
|
||||
new SingleQueryTestHandler(SingleQueryTestHandler::FAILURE, false);
|
||||
handler->ExecuteTest();
|
||||
ReleaseAndWaitForDestructor(handler);
|
||||
}
|
||||
|
||||
// Test that a single query with cancellation.
|
||||
TEST(MessageRouterTest, SingleQueryCancel) {
|
||||
CefRefPtr<SingleQueryTestHandler> handler =
|
||||
new SingleQueryTestHandler(SingleQueryTestHandler::CANCEL, true);
|
||||
handler->ExecuteTest();
|
||||
ReleaseAndWaitForDestructor(handler);
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
const int kSinglePersistentQueryResponseCount = 10;
|
||||
|
||||
// Test a single persistent query in a single page load.
|
||||
class SinglePersistentQueryTestHandler : public SingleLoadTestHandler {
|
||||
public:
|
||||
enum TestType {
|
||||
SUCCESS,
|
||||
FAILURE,
|
||||
};
|
||||
|
||||
SinglePersistentQueryTestHandler(TestType test_type, bool sync_callback)
|
||||
: test_type_(test_type), sync_callback_(sync_callback), query_id_(0) {}
|
||||
|
||||
std::string GetMainHTML() override {
|
||||
std::string html;
|
||||
|
||||
std::stringstream ss;
|
||||
ss << kSinglePersistentQueryResponseCount;
|
||||
const std::string& responseCountStr = ss.str();
|
||||
ss.str("");
|
||||
ss << kSingleQueryErrorCode;
|
||||
const std::string& errorCodeStr = ss.str();
|
||||
|
||||
html =
|
||||
"<html><body><script>\n"
|
||||
// No requests should exist.
|
||||
"window.mrtAssertTotalCount(" LINESTR
|
||||
",0);\n"
|
||||
"window.mrtAssertBrowserCount(" LINESTR
|
||||
",0);\n"
|
||||
"window.mrtAssertContextCount(" LINESTR
|
||||
",0);\n"
|
||||
// Keep track of the number of responses.
|
||||
"var count = 0;\n"
|
||||
// Send the query.
|
||||
"var request_id = window.mrtQuery({\n"
|
||||
" request: '" +
|
||||
std::string(kSingleQueryRequest) +
|
||||
"',\n"
|
||||
" persistent: true,\n"
|
||||
" onSuccess: function(response) {\n"
|
||||
// Request should not be removed.
|
||||
" window.mrtAssertTotalCount(" LINESTR
|
||||
",1);\n"
|
||||
" window.mrtAssertBrowserCount(" LINESTR
|
||||
",1);\n"
|
||||
" window.mrtAssertContextCount(" LINESTR
|
||||
",1);\n"
|
||||
" if (response == '" +
|
||||
std::string(kSingleQueryResponse) +
|
||||
"') {\n"
|
||||
" if (++count == " +
|
||||
responseCountStr +
|
||||
") {\n"
|
||||
" window.mrtNotify('success');\n"
|
||||
" window.mrtQueryCancel(request_id);\n"
|
||||
// Request should be removed immediately.
|
||||
" window.mrtAssertTotalCount(" LINESTR
|
||||
",0);\n"
|
||||
" window.mrtAssertBrowserCount(" LINESTR
|
||||
",0);\n"
|
||||
" window.mrtAssertContextCount(" LINESTR
|
||||
",0);\n"
|
||||
" }\n"
|
||||
" } else {\n"
|
||||
" window.mrtNotify('error-onSuccess');\n"
|
||||
" }\n"
|
||||
" },\n"
|
||||
" onFailure: function(error_code, error_message) {\n"
|
||||
// Request should be removed before callback is executed.
|
||||
" window.mrtAssertTotalCount(" LINESTR
|
||||
",0);\n"
|
||||
" window.mrtAssertBrowserCount(" LINESTR
|
||||
",0);\n"
|
||||
" window.mrtAssertContextCount(" LINESTR
|
||||
",0);\n"
|
||||
" if (error_code == " +
|
||||
errorCodeStr + " && error_message == '" +
|
||||
std::string(kSingleQueryErrorMessage) +
|
||||
"') {\n"
|
||||
" window.mrtNotify('failure');\n"
|
||||
" } else {\n"
|
||||
" window.mrtNotify('error-onFailure');\n"
|
||||
" }\n"
|
||||
" }\n"
|
||||
"});\n"
|
||||
// Request should exist.
|
||||
"window.mrtAssertTotalCount(" LINESTR
|
||||
",1);\n"
|
||||
"window.mrtAssertBrowserCount(" LINESTR
|
||||
",1);\n"
|
||||
"window.mrtAssertContextCount(" LINESTR ",1);\n";
|
||||
|
||||
html += "</script></body></html>";
|
||||
return html;
|
||||
}
|
||||
|
||||
void OnNotify(CefRefPtr<CefBrowser> browser,
|
||||
CefRefPtr<CefFrame> frame,
|
||||
const std::string& message) override {
|
||||
AssertMainBrowser(browser);
|
||||
AssertMainFrame(frame);
|
||||
|
||||
if (test_type_ == SUCCESS) {
|
||||
EXPECT_STREQ("success", message.c_str());
|
||||
} else if (test_type_ == FAILURE) {
|
||||
EXPECT_STREQ("failure", message.c_str());
|
||||
}
|
||||
|
||||
got_notify_.yes();
|
||||
|
||||
DestroyTestIfDone();
|
||||
}
|
||||
|
||||
void ExecuteCallback() {
|
||||
EXPECT_TRUE(callback_.get());
|
||||
if (test_type_ == SUCCESS) {
|
||||
callback_->Success(kSingleQueryResponse);
|
||||
} else {
|
||||
callback_->Failure(kSingleQueryErrorCode, kSingleQueryErrorMessage);
|
||||
callback_ = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
bool OnQuery(CefRefPtr<CefBrowser> browser,
|
||||
CefRefPtr<CefFrame> frame,
|
||||
int64 query_id,
|
||||
const CefString& request,
|
||||
bool persistent,
|
||||
CefRefPtr<Callback> callback) override {
|
||||
AssertMainBrowser(browser);
|
||||
AssertMainFrame(frame);
|
||||
EXPECT_NE(0, query_id);
|
||||
EXPECT_TRUE(persistent);
|
||||
EXPECT_STREQ(kSingleQueryRequest, request.ToString().c_str());
|
||||
|
||||
got_on_query_.yes();
|
||||
|
||||
query_id_ = query_id;
|
||||
callback_ = callback;
|
||||
|
||||
int repeat =
|
||||
(test_type_ == SUCCESS ? kSinglePersistentQueryResponseCount : 1);
|
||||
|
||||
for (int i = 0; i < repeat; ++i) {
|
||||
if (sync_callback_) {
|
||||
ExecuteCallback();
|
||||
} else {
|
||||
CefPostTask(
|
||||
TID_UI,
|
||||
base::BindOnce(&SinglePersistentQueryTestHandler::ExecuteCallback,
|
||||
this));
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void OnQueryCanceled(CefRefPtr<CefBrowser> browser,
|
||||
CefRefPtr<CefFrame> frame,
|
||||
int64 query_id) override {
|
||||
AssertMainBrowser(browser);
|
||||
AssertMainFrame(frame);
|
||||
EXPECT_EQ(query_id_, query_id);
|
||||
EXPECT_TRUE(got_on_query_);
|
||||
EXPECT_TRUE(callback_.get());
|
||||
|
||||
got_on_query_canceled_.yes();
|
||||
callback_ = nullptr;
|
||||
|
||||
DestroyTestIfDone();
|
||||
}
|
||||
|
||||
void DestroyTestIfDone() {
|
||||
bool destroy_test = false;
|
||||
if (test_type_ == SUCCESS) {
|
||||
if (got_on_query_ && got_on_query_canceled_ && got_notify_)
|
||||
destroy_test = true;
|
||||
} else if (got_on_query_ && got_notify_) {
|
||||
destroy_test = true;
|
||||
}
|
||||
|
||||
if (destroy_test)
|
||||
DestroyTest();
|
||||
}
|
||||
|
||||
void DestroyTest() override {
|
||||
EXPECT_TRUE(got_notify_);
|
||||
EXPECT_TRUE(got_on_query_);
|
||||
EXPECT_FALSE(callback_.get());
|
||||
|
||||
if (test_type_ == SUCCESS)
|
||||
EXPECT_TRUE(got_on_query_canceled_);
|
||||
else
|
||||
EXPECT_FALSE(got_on_query_canceled_);
|
||||
|
||||
TestHandler::DestroyTest();
|
||||
}
|
||||
|
||||
private:
|
||||
const TestType test_type_;
|
||||
const bool sync_callback_;
|
||||
|
||||
int64 query_id_;
|
||||
CefRefPtr<Callback> callback_;
|
||||
|
||||
TrackCallback got_on_query_;
|
||||
TrackCallback got_on_query_canceled_;
|
||||
TrackCallback got_notify_;
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
// Test that a single query with successful result delivered synchronously.
|
||||
TEST(MessageRouterTest, SinglePersistentQuerySuccessSyncCallback) {
|
||||
CefRefPtr<SinglePersistentQueryTestHandler> handler =
|
||||
new SinglePersistentQueryTestHandler(
|
||||
SinglePersistentQueryTestHandler::SUCCESS, true);
|
||||
handler->ExecuteTest();
|
||||
ReleaseAndWaitForDestructor(handler);
|
||||
}
|
||||
|
||||
// Test that a single query with successful result delivered asynchronously.
|
||||
TEST(MessageRouterTest, SinglePersistentQuerySuccessAsyncCallback) {
|
||||
CefRefPtr<SinglePersistentQueryTestHandler> handler =
|
||||
new SinglePersistentQueryTestHandler(
|
||||
SinglePersistentQueryTestHandler::SUCCESS, false);
|
||||
handler->ExecuteTest();
|
||||
ReleaseAndWaitForDestructor(handler);
|
||||
}
|
||||
|
||||
// Test that a single query with failure result delivered synchronously.
|
||||
TEST(MessageRouterTest, SinglePersistentQueryFailureSyncCallback) {
|
||||
CefRefPtr<SinglePersistentQueryTestHandler> handler =
|
||||
new SinglePersistentQueryTestHandler(
|
||||
SinglePersistentQueryTestHandler::FAILURE, true);
|
||||
handler->ExecuteTest();
|
||||
ReleaseAndWaitForDestructor(handler);
|
||||
}
|
||||
|
||||
// Test that a single query with failure result delivered asynchronously.
|
||||
TEST(MessageRouterTest, SinglePersistentQueryFailureAsyncCallback) {
|
||||
CefRefPtr<SinglePersistentQueryTestHandler> handler =
|
||||
new SinglePersistentQueryTestHandler(
|
||||
SinglePersistentQueryTestHandler::FAILURE, false);
|
||||
handler->ExecuteTest();
|
||||
ReleaseAndWaitForDestructor(handler);
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
// Test a single unhandled query in a single page load.
|
||||
class SingleUnhandledQueryTestHandler : public SingleLoadTestHandler {
|
||||
public:
|
||||
SingleUnhandledQueryTestHandler() {}
|
||||
|
||||
std::string GetMainHTML() override {
|
||||
std::string html;
|
||||
|
||||
html =
|
||||
"<html><body><script>\n"
|
||||
// No requests should exist.
|
||||
"window.mrtAssertTotalCount(" LINESTR
|
||||
",0);\n"
|
||||
"window.mrtAssertBrowserCount(" LINESTR
|
||||
",0);\n"
|
||||
"window.mrtAssertContextCount(" LINESTR
|
||||
",0);\n"
|
||||
// Keep track of the number of responses.
|
||||
"var count = 0;\n"
|
||||
// Send the query.
|
||||
"var request_id = window.mrtQuery({\n"
|
||||
" request: '" +
|
||||
std::string(kSingleQueryRequest) +
|
||||
"',\n"
|
||||
" persistent: false,\n"
|
||||
" onSuccess: function(response) {\n"
|
||||
" window.mrtNotify('error-onSuccess');\n"
|
||||
" },\n"
|
||||
" onFailure: function(error_code, error_message) {\n"
|
||||
// Request should be removed before callback is executed.
|
||||
" window.mrtAssertTotalCount(" LINESTR
|
||||
",0);\n"
|
||||
" window.mrtAssertBrowserCount(" LINESTR
|
||||
",0);\n"
|
||||
" window.mrtAssertContextCount(" LINESTR
|
||||
",0);\n"
|
||||
" if (error_code == -1 && "
|
||||
"error_message == 'The query has been canceled') {\n"
|
||||
" window.mrtNotify('failure');\n"
|
||||
" } else {\n"
|
||||
" window.mrtNotify('error-onFailure');\n"
|
||||
" }\n"
|
||||
" }\n"
|
||||
"});\n"
|
||||
// Request should exist.
|
||||
"window.mrtAssertTotalCount(" LINESTR
|
||||
",1);\n"
|
||||
"window.mrtAssertBrowserCount(" LINESTR
|
||||
",1);\n"
|
||||
"window.mrtAssertContextCount(" LINESTR ",1);\n";
|
||||
|
||||
html += "</script></body></html>";
|
||||
return html;
|
||||
}
|
||||
|
||||
void OnNotify(CefRefPtr<CefBrowser> browser,
|
||||
CefRefPtr<CefFrame> frame,
|
||||
const std::string& message) override {
|
||||
AssertMainBrowser(browser);
|
||||
AssertMainFrame(frame);
|
||||
EXPECT_STREQ("failure", message.c_str());
|
||||
|
||||
got_notify_.yes();
|
||||
|
||||
DestroyTest();
|
||||
}
|
||||
|
||||
bool OnQuery(CefRefPtr<CefBrowser> browser,
|
||||
CefRefPtr<CefFrame> frame,
|
||||
int64 query_id,
|
||||
const CefString& request,
|
||||
bool persistent,
|
||||
CefRefPtr<Callback> callback) override {
|
||||
AssertMainBrowser(browser);
|
||||
AssertMainFrame(frame);
|
||||
EXPECT_NE(0, query_id);
|
||||
EXPECT_FALSE(persistent);
|
||||
EXPECT_STREQ(kSingleQueryRequest, request.ToString().c_str());
|
||||
|
||||
got_on_query_.yes();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void OnQueryCanceled(CefRefPtr<CefBrowser> browser,
|
||||
CefRefPtr<CefFrame> frame,
|
||||
int64 query_id) override {
|
||||
EXPECT_FALSE(true); // Not reached.
|
||||
}
|
||||
|
||||
void DestroyTest() override {
|
||||
EXPECT_TRUE(got_on_query_);
|
||||
EXPECT_TRUE(got_notify_);
|
||||
|
||||
TestHandler::DestroyTest();
|
||||
}
|
||||
|
||||
private:
|
||||
TrackCallback got_on_query_;
|
||||
TrackCallback got_notify_;
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
// Test that a single unhandled query results in a call to onFailure.
|
||||
TEST(MessageRouterTest, SingleUnhandledQuery) {
|
||||
CefRefPtr<SingleUnhandledQueryTestHandler> handler =
|
||||
new SingleUnhandledQueryTestHandler();
|
||||
handler->ExecuteTest();
|
||||
ReleaseAndWaitForDestructor(handler);
|
||||
}
|
222
tests/ceftests/message_router_threshold_unittest.cc
Normal file
222
tests/ceftests/message_router_threshold_unittest.cc
Normal file
@ -0,0 +1,222 @@
|
||||
// Copyright (c) 2022 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 int kSingleQueryErrorCode = 5;
|
||||
constexpr size_t kMessageSizeThreshold = 16000;
|
||||
|
||||
enum class TestType { SUCCESS, FAILURE };
|
||||
|
||||
CefString GenerateResponse(size_t size, char ch) {
|
||||
return CefString(std::string(size, ch));
|
||||
}
|
||||
|
||||
CefString GenerateResponse(size_t size, wchar_t ch) {
|
||||
return CefString(std::wstring(size, ch));
|
||||
}
|
||||
|
||||
template <class CharType>
|
||||
class ThresholdTestHandler final : public SingleLoadTestHandler {
|
||||
public:
|
||||
ThresholdTestHandler(TestType type, size_t message_size, CharType symbol)
|
||||
: test_type_(type),
|
||||
message_size_(message_size),
|
||||
message_size_str_(std::to_string(message_size)),
|
||||
symbol_(symbol) {}
|
||||
|
||||
std::string GetMainHTML() override {
|
||||
const std::string& errorCodeStr = std::to_string(kSingleQueryErrorCode);
|
||||
|
||||
std::string html =
|
||||
"<html><body><script>\n"
|
||||
// Send the query.
|
||||
"var request_id = window." +
|
||||
std::string(kJSQueryFunc) + "({\n request: '" + message_size_str_ +
|
||||
"',\n persistent: false,\n"
|
||||
" onSuccess: function(response) {\n"
|
||||
" window.mrtNotify(response);\n"
|
||||
" },\n"
|
||||
" onFailure: function(error_code, error_message) {\n"
|
||||
" if (error_code == " +
|
||||
errorCodeStr +
|
||||
")\n"
|
||||
" window.mrtNotify(error_message);\n"
|
||||
" else\n"
|
||||
" window.mrtNotify('error-onFailure');\n"
|
||||
" }\n"
|
||||
"});\n</script></body></html>";
|
||||
|
||||
return 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();
|
||||
|
||||
auto expected = GenerateResponse(message_size_, symbol_);
|
||||
|
||||
switch (test_type_) {
|
||||
case TestType::SUCCESS:
|
||||
EXPECT_EQ(expected, message);
|
||||
break;
|
||||
case TestType::FAILURE:
|
||||
EXPECT_EQ(expected, message);
|
||||
break;
|
||||
default:
|
||||
ADD_FAILURE();
|
||||
break;
|
||||
}
|
||||
|
||||
DestroyTest();
|
||||
}
|
||||
|
||||
void ExecuteCallback(size_t response_size) {
|
||||
auto response = GenerateResponse(response_size, symbol_);
|
||||
|
||||
EXPECT_TRUE(callback_.get());
|
||||
switch (test_type_) {
|
||||
case TestType::SUCCESS:
|
||||
callback_->Success(response);
|
||||
break;
|
||||
case TestType::FAILURE:
|
||||
callback_->Failure(kSingleQueryErrorCode, response);
|
||||
break;
|
||||
default:
|
||||
ADD_FAILURE();
|
||||
break;
|
||||
}
|
||||
callback_ = nullptr;
|
||||
}
|
||||
|
||||
bool OnQuery(CefRefPtr<CefBrowser> browser,
|
||||
CefRefPtr<CefFrame> frame,
|
||||
int64 query_id,
|
||||
const CefString& request,
|
||||
bool persistent,
|
||||
CefRefPtr<Callback> callback) override {
|
||||
AssertMainBrowser(browser);
|
||||
AssertMainFrame(frame);
|
||||
EXPECT_NE(0, query_id);
|
||||
EXPECT_FALSE(persistent);
|
||||
EXPECT_EQ(message_size_str_, request.ToString());
|
||||
|
||||
const size_t message_size =
|
||||
static_cast<size_t>(std::stoi(request.ToString()));
|
||||
got_on_query_.yes();
|
||||
|
||||
callback_ = callback;
|
||||
ExecuteCallback(message_size);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void DestroyTest() override {
|
||||
EXPECT_TRUE(got_notify_);
|
||||
EXPECT_TRUE(got_on_query_);
|
||||
EXPECT_FALSE(callback_.get());
|
||||
|
||||
TestHandler::DestroyTest();
|
||||
}
|
||||
|
||||
private:
|
||||
const TestType test_type_;
|
||||
const size_t message_size_;
|
||||
const std::string message_size_str_;
|
||||
const CharType symbol_;
|
||||
|
||||
CefRefPtr<Callback> callback_;
|
||||
|
||||
TrackCallback got_on_query_;
|
||||
TrackCallback got_notify_;
|
||||
};
|
||||
|
||||
using CharTestHandler = CefRefPtr<ThresholdTestHandler<char>>;
|
||||
using WCharTestHandler = CefRefPtr<ThresholdTestHandler<wchar_t>>;
|
||||
|
||||
} // namespace
|
||||
|
||||
TEST(MessageRouterTest, ThresholdMessageUnderSuccessCallback) {
|
||||
const auto UnderThreshold = kMessageSizeThreshold - 1;
|
||||
CharTestHandler handler =
|
||||
new ThresholdTestHandler(TestType::SUCCESS, UnderThreshold, 'A');
|
||||
handler->SetMessageSizeThreshold(kMessageSizeThreshold);
|
||||
|
||||
handler->ExecuteTest();
|
||||
|
||||
ReleaseAndWaitForDestructor(handler);
|
||||
}
|
||||
|
||||
TEST(MessageRouterTest, ThresholMessageExactdSuccessCallback) {
|
||||
CharTestHandler handler =
|
||||
new ThresholdTestHandler(TestType::SUCCESS, kMessageSizeThreshold, 'A');
|
||||
handler->SetMessageSizeThreshold(kMessageSizeThreshold);
|
||||
|
||||
handler->ExecuteTest();
|
||||
|
||||
ReleaseAndWaitForDestructor(handler);
|
||||
}
|
||||
|
||||
TEST(MessageRouterTest, ThresholdMessageOverSuccessCallback) {
|
||||
const auto OverThreshold = kMessageSizeThreshold + 1;
|
||||
CharTestHandler handler =
|
||||
new ThresholdTestHandler(TestType::SUCCESS, OverThreshold, 'A');
|
||||
handler->SetMessageSizeThreshold(kMessageSizeThreshold);
|
||||
|
||||
handler->ExecuteTest();
|
||||
|
||||
ReleaseAndWaitForDestructor(handler);
|
||||
}
|
||||
|
||||
TEST(MessageRouterTest, ThresholdMessageUnderFailureCallback) {
|
||||
const auto UnderThreshold = kMessageSizeThreshold - 1;
|
||||
CharTestHandler handler =
|
||||
new ThresholdTestHandler(TestType::FAILURE, UnderThreshold, 'A');
|
||||
handler->SetMessageSizeThreshold(kMessageSizeThreshold);
|
||||
|
||||
handler->ExecuteTest();
|
||||
|
||||
ReleaseAndWaitForDestructor(handler);
|
||||
}
|
||||
|
||||
TEST(MessageRouterTest, ThresholMessageOverdFailureCallback) {
|
||||
const auto OverThreshold = kMessageSizeThreshold + 1;
|
||||
CharTestHandler handler =
|
||||
new ThresholdTestHandler(TestType::FAILURE, OverThreshold, 'A');
|
||||
handler->SetMessageSizeThreshold(kMessageSizeThreshold);
|
||||
|
||||
handler->ExecuteTest();
|
||||
|
||||
ReleaseAndWaitForDestructor(handler);
|
||||
}
|
||||
|
||||
TEST(MessageRouterTest, ThresholdUtf8MessageUnderSuccessCallback) {
|
||||
const auto UnderThreshold = kMessageSizeThreshold - 1;
|
||||
WCharTestHandler handler =
|
||||
new ThresholdTestHandler(TestType::SUCCESS, UnderThreshold, L'\u304B');
|
||||
handler->SetMessageSizeThreshold(kMessageSizeThreshold);
|
||||
|
||||
handler->ExecuteTest();
|
||||
|
||||
ReleaseAndWaitForDestructor(handler);
|
||||
}
|
||||
|
||||
TEST(MessageRouterTest, ThresholdUtf8MessageOverSuccessCallback) {
|
||||
const auto OverThreshold = kMessageSizeThreshold + 1;
|
||||
WCharTestHandler handler =
|
||||
new ThresholdTestHandler(TestType::SUCCESS, OverThreshold, L'\u304B');
|
||||
handler->SetMessageSizeThreshold(kMessageSizeThreshold);
|
||||
|
||||
handler->ExecuteTest();
|
||||
|
||||
ReleaseAndWaitForDestructor(handler);
|
||||
}
|
256
tests/ceftests/message_router_unittest_utils.cc
Normal file
256
tests/ceftests/message_router_unittest_utils.cc
Normal file
@ -0,0 +1,256 @@
|
||||
// Copyright (c) 2022 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"
|
||||
|
||||
extern const char kJSQueryFunc[] = "mrtQuery";
|
||||
extern const char kJSQueryCancelFunc[] = "mrtQueryCancel";
|
||||
|
||||
namespace {
|
||||
|
||||
const char kTestDomainRoot[] = "http://tests-mr";
|
||||
const char kDoneMessageName[] = "mrtNotifyMsg";
|
||||
const char kJSNotifyFunc[] = "mrtNotify";
|
||||
const char kJSAssertTotalCountFunc[] = "mrtAssertTotalCount";
|
||||
const char kJSAssertBrowserCountFunc[] = "mrtAssertBrowserCount";
|
||||
const char kJSAssertContextCountFunc[] = "mrtAssertContextCount";
|
||||
|
||||
void SetRouterConfig(CefMessageRouterConfig& config) {
|
||||
config.js_query_function = kJSQueryFunc;
|
||||
config.js_cancel_function = kJSQueryCancelFunc;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
// Entry point for creating the test delegate.
|
||||
// Called from client_app_delegates.cc.
|
||||
void CreateMessageRouterRendererTests(
|
||||
ClientAppRenderer::DelegateSet& delegates) {
|
||||
delegates.insert(new MRRenderDelegate);
|
||||
}
|
||||
|
||||
bool MRRenderDelegate::V8HandlerImpl::Execute(const CefString& name,
|
||||
CefRefPtr<CefV8Value> object,
|
||||
const CefV8ValueList& arguments,
|
||||
CefRefPtr<CefV8Value>& retval,
|
||||
CefString& exception) {
|
||||
const std::string& message_name = name;
|
||||
if (message_name == kJSNotifyFunc) {
|
||||
EXPECT_EQ(1U, arguments.size());
|
||||
EXPECT_TRUE(arguments[0]->IsString());
|
||||
|
||||
const CefString& msg = arguments[0]->GetStringValue();
|
||||
CefRefPtr<CefV8Context> context = CefV8Context::GetCurrentContext();
|
||||
CefRefPtr<CefFrame> frame = context->GetFrame();
|
||||
|
||||
CefRefPtr<CefProcessMessage> message =
|
||||
CefProcessMessage::Create(kDoneMessageName);
|
||||
CefRefPtr<CefListValue> args = message->GetArgumentList();
|
||||
args->SetString(0, msg);
|
||||
frame->SendProcessMessage(PID_BROWSER, message);
|
||||
return true;
|
||||
} else {
|
||||
EXPECT_EQ(2U, arguments.size());
|
||||
EXPECT_TRUE(arguments[0]->IsInt());
|
||||
EXPECT_TRUE(arguments[1]->IsInt());
|
||||
|
||||
const int line_no = arguments[0]->GetIntValue();
|
||||
const int expected_count = arguments[1]->GetIntValue();
|
||||
int actual_count = -1;
|
||||
|
||||
CefRefPtr<CefV8Context> context = CefV8Context::GetCurrentContext();
|
||||
CefRefPtr<CefBrowser> browser = context->GetBrowser();
|
||||
|
||||
if (name == kJSAssertTotalCountFunc) {
|
||||
actual_count =
|
||||
delegate_->message_router_->GetPendingCount(nullptr, nullptr);
|
||||
} else if (name == kJSAssertBrowserCountFunc) {
|
||||
actual_count =
|
||||
delegate_->message_router_->GetPendingCount(browser, nullptr);
|
||||
} else if (name == kJSAssertContextCountFunc) {
|
||||
actual_count =
|
||||
delegate_->message_router_->GetPendingCount(browser, context);
|
||||
}
|
||||
|
||||
if (expected_count != actual_count) {
|
||||
std::stringstream ss;
|
||||
ss << message_name << " failed (line " << line_no << "); expected "
|
||||
<< expected_count << ", got " << actual_count;
|
||||
exception = ss.str();
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void MRRenderDelegate::OnWebKitInitialized(CefRefPtr<ClientAppRenderer> app) {
|
||||
// Create the renderer-side router for query handling.
|
||||
CefMessageRouterConfig config;
|
||||
SetRouterConfig(config);
|
||||
message_router_ = CefMessageRouterRendererSide::Create(config);
|
||||
}
|
||||
|
||||
void MRRenderDelegate::OnContextCreated(CefRefPtr<ClientAppRenderer> app,
|
||||
CefRefPtr<CefBrowser> browser,
|
||||
CefRefPtr<CefFrame> frame,
|
||||
CefRefPtr<CefV8Context> context) {
|
||||
const std::string& url = frame->GetURL();
|
||||
if (url.find(kTestDomainRoot) != 0)
|
||||
return;
|
||||
|
||||
message_router_->OnContextCreated(browser, frame, context);
|
||||
|
||||
// Register function handlers with the 'window' object.
|
||||
CefRefPtr<CefV8Value> window = context->GetGlobal();
|
||||
|
||||
CefRefPtr<V8HandlerImpl> handler = new V8HandlerImpl(this);
|
||||
CefV8Value::PropertyAttribute attributes =
|
||||
static_cast<CefV8Value::PropertyAttribute>(
|
||||
V8_PROPERTY_ATTRIBUTE_READONLY | V8_PROPERTY_ATTRIBUTE_DONTENUM |
|
||||
V8_PROPERTY_ATTRIBUTE_DONTDELETE);
|
||||
|
||||
CefRefPtr<CefV8Value> notify_func =
|
||||
CefV8Value::CreateFunction(kJSNotifyFunc, handler.get());
|
||||
window->SetValue(kJSNotifyFunc, notify_func, attributes);
|
||||
|
||||
CefRefPtr<CefV8Value> total_count_func =
|
||||
CefV8Value::CreateFunction(kJSAssertTotalCountFunc, handler.get());
|
||||
window->SetValue(kJSAssertTotalCountFunc, total_count_func, attributes);
|
||||
|
||||
CefRefPtr<CefV8Value> browser_count_func =
|
||||
CefV8Value::CreateFunction(kJSAssertBrowserCountFunc, handler.get());
|
||||
window->SetValue(kJSAssertBrowserCountFunc, browser_count_func, attributes);
|
||||
|
||||
CefRefPtr<CefV8Value> context_count_func =
|
||||
CefV8Value::CreateFunction(kJSAssertContextCountFunc, handler.get());
|
||||
window->SetValue(kJSAssertContextCountFunc, context_count_func, attributes);
|
||||
}
|
||||
|
||||
void MRRenderDelegate::OnContextReleased(CefRefPtr<ClientAppRenderer> app,
|
||||
CefRefPtr<CefBrowser> browser,
|
||||
CefRefPtr<CefFrame> frame,
|
||||
CefRefPtr<CefV8Context> context) {
|
||||
const std::string& url = frame->GetURL();
|
||||
if (url.find(kTestDomainRoot) != 0)
|
||||
return;
|
||||
|
||||
message_router_->OnContextReleased(browser, frame, context);
|
||||
}
|
||||
|
||||
bool MRRenderDelegate::OnProcessMessageReceived(
|
||||
CefRefPtr<ClientAppRenderer> app,
|
||||
CefRefPtr<CefBrowser> browser,
|
||||
CefRefPtr<CefFrame> frame,
|
||||
CefProcessId source_process,
|
||||
CefRefPtr<CefProcessMessage> message) {
|
||||
const std::string& url = frame->GetURL();
|
||||
if (url.find(kTestDomainRoot) != 0)
|
||||
return false;
|
||||
|
||||
return message_router_->OnProcessMessageReceived(browser, frame,
|
||||
source_process, message);
|
||||
}
|
||||
|
||||
void MRTestHandler::RunTest() {
|
||||
RunMRTest();
|
||||
|
||||
// Time out the test after a reasonable period of time.
|
||||
SetTestTimeout(10000);
|
||||
}
|
||||
|
||||
void MRTestHandler::OnAfterCreated(CefRefPtr<CefBrowser> browser) {
|
||||
if (!message_router_.get()) {
|
||||
// Create the browser-side router for query handling.
|
||||
CefMessageRouterConfig config;
|
||||
|
||||
SetRouterConfig(config);
|
||||
if (message_size_threshold_)
|
||||
config.message_size_threshold = message_size_threshold_;
|
||||
|
||||
message_router_ = CefMessageRouterBrowserSide::Create(config);
|
||||
AddHandlers(message_router_);
|
||||
}
|
||||
TestHandler::OnAfterCreated(browser);
|
||||
}
|
||||
|
||||
void MRTestHandler::OnBeforeClose(CefRefPtr<CefBrowser> browser) {
|
||||
message_router_->OnBeforeClose(browser);
|
||||
TestHandler::OnBeforeClose(browser);
|
||||
}
|
||||
|
||||
void MRTestHandler::OnRenderProcessTerminated(CefRefPtr<CefBrowser> browser,
|
||||
TerminationStatus status) {
|
||||
message_router_->OnRenderProcessTerminated(browser);
|
||||
}
|
||||
|
||||
bool MRTestHandler::OnBeforeBrowse(CefRefPtr<CefBrowser> browser,
|
||||
CefRefPtr<CefFrame> frame,
|
||||
CefRefPtr<CefRequest> request,
|
||||
bool user_gesture,
|
||||
bool is_redirect) {
|
||||
message_router_->OnBeforeBrowse(browser, frame);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Returns true if the router handled the navigation.
|
||||
bool MRTestHandler::OnProcessMessageReceived(
|
||||
CefRefPtr<CefBrowser> browser,
|
||||
CefRefPtr<CefFrame> frame,
|
||||
CefProcessId source_process,
|
||||
CefRefPtr<CefProcessMessage> message) {
|
||||
const std::string& message_name = message->GetName();
|
||||
if (message_name == kDoneMessageName) {
|
||||
CefRefPtr<CefListValue> args = message->GetArgumentList();
|
||||
EXPECT_EQ(1U, args->GetSize());
|
||||
EXPECT_EQ(VTYPE_STRING, args->GetType(0));
|
||||
OnNotify(browser, frame, args->GetString(0));
|
||||
return true;
|
||||
}
|
||||
|
||||
return message_router_->OnProcessMessageReceived(browser, frame,
|
||||
source_process, message);
|
||||
}
|
||||
|
||||
CefRefPtr<CefMessageRouterBrowserSide> MRTestHandler::GetRouter() const {
|
||||
return message_router_;
|
||||
}
|
||||
|
||||
void MRTestHandler::SetMessageSizeThreshold(size_t message_size_threshold) {
|
||||
message_size_threshold_ = message_size_threshold;
|
||||
}
|
||||
|
||||
bool MRTestHandler::AssertQueryCount(
|
||||
CefRefPtr<CefBrowser> browser,
|
||||
CefMessageRouterBrowserSide::Handler* handler,
|
||||
int expected_count) {
|
||||
int actual_count = message_router_->GetPendingCount(browser, handler);
|
||||
EXPECT_EQ(expected_count, actual_count);
|
||||
return (expected_count == actual_count);
|
||||
}
|
||||
|
||||
void MRTestHandler::AssertMainBrowser(CefRefPtr<CefBrowser> browser) {
|
||||
EXPECT_TRUE(browser.get());
|
||||
EXPECT_EQ(GetBrowserId(), browser->GetIdentifier());
|
||||
}
|
||||
|
||||
SingleLoadTestHandler::SingleLoadTestHandler()
|
||||
: main_url_("http://tests-mr.com/main.html") {}
|
||||
|
||||
void SingleLoadTestHandler::RunMRTest() {
|
||||
AddOtherResources();
|
||||
AddResource(main_url_, GetMainHTML(), "text/html");
|
||||
|
||||
CreateBrowser(main_url_, nullptr);
|
||||
}
|
||||
|
||||
void SingleLoadTestHandler::AddHandlers(
|
||||
CefRefPtr<CefMessageRouterBrowserSide> message_router) {
|
||||
message_router->AddHandler(this, false);
|
||||
}
|
||||
|
||||
void SingleLoadTestHandler::AssertMainFrame(CefRefPtr<CefFrame> frame) {
|
||||
EXPECT_TRUE(frame.get());
|
||||
EXPECT_TRUE(frame->IsMain());
|
||||
EXPECT_STREQ(main_url_.c_str(), frame->GetURL().ToString().c_str());
|
||||
}
|
137
tests/ceftests/message_router_unittest_utils.h
Normal file
137
tests/ceftests/message_router_unittest_utils.h
Normal file
@ -0,0 +1,137 @@
|
||||
// Copyright (c) 2022 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_CEFTESTS_MESSAGE_ROUTER_UNITTEST_UTILS_H_
|
||||
#define CEF_TESTS_CEFTESTS_MESSAGE_ROUTER_UNITTEST_UTILS_H_
|
||||
#pragma once
|
||||
|
||||
#include <cstdlib>
|
||||
|
||||
#include "include/base/cef_callback.h"
|
||||
#include "include/base/cef_weak_ptr.h"
|
||||
#include "include/cef_v8.h"
|
||||
#include "include/wrapper/cef_closure_task.h"
|
||||
#include "tests/ceftests/routing_test_handler.h"
|
||||
#include "tests/ceftests/test_util.h"
|
||||
#include "tests/gtest/include/gtest/gtest.h"
|
||||
#include "tests/shared/renderer/client_app_renderer.h"
|
||||
|
||||
using client::ClientAppRenderer;
|
||||
|
||||
extern const char kJSQueryFunc[];
|
||||
extern const char kJSQueryCancelFunc[];
|
||||
|
||||
#define S1(N) #N
|
||||
#define S2(N) S1(N)
|
||||
#define LINESTR S2(__LINE__)
|
||||
|
||||
// Handle the renderer side of the routing implementation.
|
||||
class MRRenderDelegate : public ClientAppRenderer::Delegate {
|
||||
public:
|
||||
class V8HandlerImpl : public CefV8Handler {
|
||||
public:
|
||||
explicit V8HandlerImpl(CefRefPtr<MRRenderDelegate> delegate)
|
||||
: delegate_(delegate) {}
|
||||
|
||||
bool Execute(const CefString& name,
|
||||
CefRefPtr<CefV8Value> object,
|
||||
const CefV8ValueList& arguments,
|
||||
CefRefPtr<CefV8Value>& retval,
|
||||
CefString& exception) override;
|
||||
|
||||
private:
|
||||
CefRefPtr<MRRenderDelegate> delegate_;
|
||||
|
||||
IMPLEMENT_REFCOUNTING(V8HandlerImpl);
|
||||
};
|
||||
|
||||
void OnWebKitInitialized(CefRefPtr<ClientAppRenderer> app) override;
|
||||
|
||||
void OnContextCreated(CefRefPtr<ClientAppRenderer> app,
|
||||
CefRefPtr<CefBrowser> browser,
|
||||
CefRefPtr<CefFrame> frame,
|
||||
CefRefPtr<CefV8Context> context) override;
|
||||
|
||||
void OnContextReleased(CefRefPtr<ClientAppRenderer> app,
|
||||
CefRefPtr<CefBrowser> browser,
|
||||
CefRefPtr<CefFrame> frame,
|
||||
CefRefPtr<CefV8Context> context) override;
|
||||
|
||||
bool OnProcessMessageReceived(CefRefPtr<ClientAppRenderer> app,
|
||||
CefRefPtr<CefBrowser> browser,
|
||||
CefRefPtr<CefFrame> frame,
|
||||
CefProcessId source_process,
|
||||
CefRefPtr<CefProcessMessage> message) override;
|
||||
|
||||
private:
|
||||
CefRefPtr<CefMessageRouterRendererSide> message_router_;
|
||||
|
||||
IMPLEMENT_REFCOUNTING(MRRenderDelegate);
|
||||
};
|
||||
|
||||
class MRTestHandler : public TestHandler {
|
||||
public:
|
||||
void RunTest() override;
|
||||
void OnAfterCreated(CefRefPtr<CefBrowser> browser) override;
|
||||
void OnBeforeClose(CefRefPtr<CefBrowser> browser) override;
|
||||
void OnRenderProcessTerminated(CefRefPtr<CefBrowser> browser,
|
||||
TerminationStatus status) override;
|
||||
|
||||
// Only call this method if the navigation isn't canceled.
|
||||
bool OnBeforeBrowse(CefRefPtr<CefBrowser> browser,
|
||||
CefRefPtr<CefFrame> frame,
|
||||
CefRefPtr<CefRequest> request,
|
||||
bool user_gesture,
|
||||
bool is_redirect) override;
|
||||
// Returns true if the router handled the navigation.
|
||||
bool OnProcessMessageReceived(CefRefPtr<CefBrowser> browser,
|
||||
CefRefPtr<CefFrame> frame,
|
||||
CefProcessId source_process,
|
||||
CefRefPtr<CefProcessMessage> message) override;
|
||||
|
||||
CefRefPtr<CefMessageRouterBrowserSide> GetRouter() const;
|
||||
void SetMessageSizeThreshold(size_t message_size_treshold);
|
||||
|
||||
protected:
|
||||
virtual void RunMRTest() = 0;
|
||||
|
||||
virtual void AddHandlers(
|
||||
CefRefPtr<CefMessageRouterBrowserSide> message_router) = 0;
|
||||
|
||||
virtual void OnNotify(CefRefPtr<CefBrowser> browser,
|
||||
CefRefPtr<CefFrame> frame,
|
||||
const std::string& message) = 0;
|
||||
|
||||
bool AssertQueryCount(CefRefPtr<CefBrowser> browser,
|
||||
CefMessageRouterBrowserSide::Handler* handler,
|
||||
int expected_count);
|
||||
void AssertMainBrowser(CefRefPtr<CefBrowser> browser);
|
||||
|
||||
private:
|
||||
CefRefPtr<CefMessageRouterBrowserSide> message_router_;
|
||||
size_t message_size_threshold_ = 0;
|
||||
|
||||
IMPLEMENT_REFCOUNTING(MRTestHandler);
|
||||
};
|
||||
|
||||
// Implementation of MRTestHandler that loads a single page.
|
||||
class SingleLoadTestHandler : public MRTestHandler,
|
||||
public CefMessageRouterBrowserSide::Handler {
|
||||
public:
|
||||
SingleLoadTestHandler();
|
||||
const std::string& GetMainURL() { return main_url_; }
|
||||
|
||||
protected:
|
||||
void RunMRTest() override;
|
||||
void AddHandlers(
|
||||
CefRefPtr<CefMessageRouterBrowserSide> message_router) override;
|
||||
virtual void AddOtherResources() {}
|
||||
virtual std::string GetMainHTML() = 0;
|
||||
void AssertMainFrame(CefRefPtr<CefFrame> frame);
|
||||
|
||||
private:
|
||||
const std::string main_url_;
|
||||
};
|
||||
|
||||
#endif // CEF_TESTS_CEFTESTS_MESSAGE_ROUTER_UNITTEST_UTILS_H_
|
172
tests/ceftests/send_shared_process_message_unittest.cc
Normal file
172
tests/ceftests/send_shared_process_message_unittest.cc
Normal file
@ -0,0 +1,172 @@
|
||||
// Copyright (c) 2022 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 "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 "tests/ceftests/test_handler.h"
|
||||
#include "tests/gtest/include/gtest/gtest.h"
|
||||
#include "tests/shared/renderer/client_app_renderer.h"
|
||||
|
||||
#include <array>
|
||||
|
||||
using client::ClientAppRenderer;
|
||||
|
||||
namespace {
|
||||
|
||||
struct TestData {
|
||||
bool flag = true;
|
||||
int value = 1;
|
||||
double d_value = 77.77;
|
||||
std::array<size_t, 50> buffer{};
|
||||
};
|
||||
|
||||
const char kSharedMessageUrl[] = "http://tests/SendSharedProcessMessageTest";
|
||||
const char kSharedMessageName[] = "SendSharedProcessMessageTest";
|
||||
|
||||
CefRefPtr<CefProcessMessage> CreateTestMessage(const TestData& data) {
|
||||
auto builder = CefSharedProcessMessageBuilder::Create(kSharedMessageName, sizeof(data));
|
||||
std::memcpy(builder->Memory(), reinterpret_cast<const void*>(&data), sizeof(data));
|
||||
return builder->Build();
|
||||
}
|
||||
|
||||
// Renderer side.
|
||||
class SharedMessageRendererTest final : public ClientAppRenderer::Delegate {
|
||||
public:
|
||||
bool OnProcessMessageReceived(CefRefPtr<ClientAppRenderer> app,
|
||||
CefRefPtr<CefBrowser> browser,
|
||||
CefRefPtr<CefFrame> frame,
|
||||
CefProcessId source_process,
|
||||
CefRefPtr<CefProcessMessage> message) override {
|
||||
if (message->GetName() == kSharedMessageName) {
|
||||
EXPECT_TRUE(browser.get());
|
||||
EXPECT_TRUE(frame.get());
|
||||
EXPECT_EQ(PID_BROWSER, source_process);
|
||||
EXPECT_TRUE(message.get());
|
||||
EXPECT_TRUE(message->IsValid());
|
||||
EXPECT_TRUE(message->IsReadOnly());
|
||||
EXPECT_EQ(message->GetArgumentList(), nullptr);
|
||||
|
||||
const std::string& url = frame->GetURL();
|
||||
if (url == kSharedMessageUrl) {
|
||||
// Echo the message back to the sender natively.
|
||||
frame->SendProcessMessage(PID_BROWSER, message);
|
||||
EXPECT_FALSE(message->IsValid());
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
IMPLEMENT_REFCOUNTING(SharedMessageRendererTest);
|
||||
};
|
||||
|
||||
// Browser side.
|
||||
class SharedMessageTestHandler final : public TestHandler {
|
||||
public:
|
||||
explicit SharedMessageTestHandler(cef_thread_id_t send_thread)
|
||||
: send_thread_(send_thread) {}
|
||||
|
||||
void RunTest() override {
|
||||
AddResource(kSharedMessageUrl, "<html><body>TEST</body></html>",
|
||||
"text/html");
|
||||
CreateBrowser(kSharedMessageUrl);
|
||||
|
||||
// Time out the test after a reasonable period of time.
|
||||
SetTestTimeout();
|
||||
}
|
||||
|
||||
void OnLoadEnd(CefRefPtr<CefBrowser> browser,
|
||||
CefRefPtr<CefFrame> frame,
|
||||
int httpStatusCode) override {
|
||||
EXPECT_TRUE(CefCurrentlyOn(TID_UI));
|
||||
|
||||
// Send the message to the renderer process.
|
||||
if (!CefCurrentlyOn(send_thread_)) {
|
||||
CefPostTask(send_thread_,
|
||||
base::BindOnce(&SharedMessageTestHandler::SendProcessMessage,
|
||||
this, browser, frame));
|
||||
} else {
|
||||
SendProcessMessage(browser, frame);
|
||||
}
|
||||
}
|
||||
|
||||
bool OnProcessMessageReceived(CefRefPtr<CefBrowser> browser,
|
||||
CefRefPtr<CefFrame> frame,
|
||||
CefProcessId source_process,
|
||||
CefRefPtr<CefProcessMessage> message) override {
|
||||
EXPECT_TRUE(CefCurrentlyOn(TID_UI));
|
||||
EXPECT_TRUE(browser.get());
|
||||
EXPECT_TRUE(frame.get());
|
||||
EXPECT_EQ(PID_RENDERER, source_process);
|
||||
EXPECT_TRUE(message.get());
|
||||
EXPECT_TRUE(message->IsValid());
|
||||
EXPECT_TRUE(message->IsReadOnly());
|
||||
EXPECT_EQ(message->GetArgumentList(), nullptr);
|
||||
|
||||
// Verify that the recieved message is the same as the sent message.
|
||||
auto region = message->GetSharedMemoryRegion();
|
||||
const TestData* received = static_cast<const TestData*>(region->Memory());
|
||||
EXPECT_EQ(data_.flag, received->flag);
|
||||
EXPECT_EQ(data_.value, received->value);
|
||||
EXPECT_EQ(data_.d_value, received->d_value);
|
||||
|
||||
got_message_.yes();
|
||||
|
||||
// Test is complete.
|
||||
DestroyTest();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
protected:
|
||||
void DestroyTest() override {
|
||||
EXPECT_TRUE(got_message_);
|
||||
TestHandler::DestroyTest();
|
||||
}
|
||||
|
||||
private:
|
||||
void SendProcessMessage(const CefRefPtr<CefBrowser>& browser,
|
||||
const CefRefPtr<CefFrame>& frame) {
|
||||
EXPECT_TRUE(CefCurrentlyOn(send_thread_));
|
||||
|
||||
auto message = CreateTestMessage(data_);
|
||||
frame->SendProcessMessage(PID_RENDERER, message);
|
||||
|
||||
// The message is invalidated immediately
|
||||
EXPECT_FALSE(message->IsValid());
|
||||
}
|
||||
|
||||
cef_thread_id_t send_thread_;
|
||||
TrackCallback got_message_;
|
||||
const TestData data_;
|
||||
|
||||
IMPLEMENT_REFCOUNTING(SharedMessageTestHandler);
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
TEST(SendSharedProcessMessageTest, CanSendAndReceiveFromUiThread) {
|
||||
CefRefPtr<SharedMessageTestHandler> handler =
|
||||
new SharedMessageTestHandler(TID_UI);
|
||||
handler->ExecuteTest();
|
||||
ReleaseAndWaitForDestructor(handler);
|
||||
}
|
||||
|
||||
TEST(SendSharedProcessMessageTest, CanSendAndReceiveFromIoThread) {
|
||||
CefRefPtr<SharedMessageTestHandler> handler =
|
||||
new SharedMessageTestHandler(TID_IO);
|
||||
handler->ExecuteTest();
|
||||
ReleaseAndWaitForDestructor(handler);
|
||||
}
|
||||
|
||||
|
||||
// Entry point for creating shared process message renderer test objects.
|
||||
// Called from client_app_delegates.cc.
|
||||
void CreateSharedProcessMessageTests(
|
||||
ClientAppRenderer::DelegateSet& delegates) {
|
||||
delegates.insert(new SharedMessageRendererTest());
|
||||
}
|
94
tests/ceftests/shared_process_message_unittest.cc
Normal file
94
tests/ceftests/shared_process_message_unittest.cc
Normal file
@ -0,0 +1,94 @@
|
||||
// Copyright (c) 2022 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 "include/cef_shared_process_message_builder.h"
|
||||
|
||||
#include "testing/gtest/include/gtest/gtest.h"
|
||||
|
||||
#include <array>
|
||||
|
||||
namespace {
|
||||
|
||||
constexpr bool kTestFlag = true;
|
||||
constexpr int kTestValue = 42;
|
||||
constexpr double kTestDoubleValue = 123.456;
|
||||
|
||||
struct TestData {
|
||||
bool flag = kTestFlag;
|
||||
int value = kTestValue;
|
||||
double doubleValue = kTestDoubleValue;
|
||||
std::array<size_t, 50> buffer{};
|
||||
};
|
||||
|
||||
const char kSharedMessageName[] = "SharedProcessMessageTest";
|
||||
|
||||
CefRefPtr<CefSharedProcessMessageBuilder> CreateTestBuilder() {
|
||||
auto builder = CefSharedProcessMessageBuilder::Create(kSharedMessageName,
|
||||
sizeof(TestData));
|
||||
EXPECT_NE(builder, nullptr);
|
||||
EXPECT_TRUE(builder->IsValid());
|
||||
|
||||
auto data = static_cast<TestData*>(builder->Memory());
|
||||
EXPECT_NE(data, nullptr);
|
||||
|
||||
data->value = kTestValue;
|
||||
data->doubleValue = kTestDoubleValue;
|
||||
data->flag = kTestFlag;
|
||||
for (size_t i = 0; i < data->buffer.size(); ++i) {
|
||||
data->buffer[i] = i;
|
||||
}
|
||||
|
||||
return builder;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
TEST(SharedProcessMessageTest, CanBuildSharedMessageUsingBuilder) {
|
||||
auto builder = CreateTestBuilder();
|
||||
|
||||
auto message = builder->Build();
|
||||
EXPECT_FALSE(builder->IsValid());
|
||||
EXPECT_NE(message, nullptr);
|
||||
EXPECT_TRUE(message->IsValid());
|
||||
EXPECT_TRUE(message->IsReadOnly());
|
||||
|
||||
auto region = message->GetSharedMemoryRegion();
|
||||
EXPECT_TRUE(region->IsValid());
|
||||
auto read_data = static_cast<const TestData*>(region->Memory());
|
||||
|
||||
EXPECT_EQ(read_data->flag, kTestFlag);
|
||||
EXPECT_EQ(read_data->value, kTestValue);
|
||||
EXPECT_EQ(read_data->doubleValue, kTestDoubleValue);
|
||||
for (size_t i = 0; i < read_data->buffer.size(); ++i) {
|
||||
EXPECT_EQ(read_data->buffer[i], i);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(SharedProcessMessageTest, CopyingIsNotSupportedBySharedMessage) {
|
||||
auto builder = CefSharedProcessMessageBuilder::Create(kSharedMessageName,
|
||||
sizeof(TestData));
|
||||
CefRefPtr<CefProcessMessage> message = builder->Build();
|
||||
CefRefPtr<CefProcessMessage> message_copy = message->Copy();
|
||||
EXPECT_EQ(message_copy, nullptr);
|
||||
}
|
||||
|
||||
TEST(SharedProcessMessageTest,
|
||||
RegionRemainsValidAfterSharedMessageDestruction) {
|
||||
CefRefPtr<CefSharedMemoryRegion> region;
|
||||
{
|
||||
auto builder = CreateTestBuilder();
|
||||
auto message = builder->Build();
|
||||
region = message->GetSharedMemoryRegion();
|
||||
}
|
||||
|
||||
EXPECT_TRUE(region->IsValid());
|
||||
auto read_data = static_cast<const TestData*>(region->Memory());
|
||||
|
||||
EXPECT_EQ(read_data->flag, kTestFlag);
|
||||
EXPECT_EQ(read_data->value, kTestValue);
|
||||
EXPECT_EQ(read_data->doubleValue, kTestDoubleValue);
|
||||
for (size_t i = 0; i < read_data->buffer.size(); ++i) {
|
||||
EXPECT_EQ(read_data->buffer[i], i);
|
||||
}
|
||||
}
|
44
tests/shared/common/binary_value_utils.cc
Normal file
44
tests/shared/common/binary_value_utils.cc
Normal file
@ -0,0 +1,44 @@
|
||||
// Copyright (c) 2022 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/shared/common/binary_value_utils.h"
|
||||
|
||||
namespace bv_utils {
|
||||
|
||||
const char kTestSendProcessMessage[] = "testSendProcessMessage";
|
||||
const char kTestSendSMRProcessMessage[] = "testSendSMRProcessMessage";
|
||||
|
||||
TimePoint Now() {
|
||||
return std::chrono::high_resolution_clock::now();
|
||||
}
|
||||
|
||||
CefRefPtr<CefBinaryValue> CreateCefBinaryValue(
|
||||
const std::vector<uint8_t>& data) {
|
||||
return CefBinaryValue::Create(data.data(), data.size());
|
||||
}
|
||||
|
||||
RendererMessage GetRendererMsgFromBinary(
|
||||
const CefRefPtr<CefBinaryValue>& value) {
|
||||
DCHECK_GE(value->GetSize(), sizeof(RendererMessage));
|
||||
std::vector<uint8_t> data(value->GetSize());
|
||||
value->GetData(data.data(), data.size(), 0);
|
||||
return *reinterpret_cast<const RendererMessage*>(data.data());
|
||||
}
|
||||
|
||||
BrowserMessage GetBrowserMsgFromBinary(const CefRefPtr<CefBinaryValue>& value) {
|
||||
DCHECK_GE(value->GetSize(), sizeof(BrowserMessage));
|
||||
std::vector<uint8_t> data(value->GetSize());
|
||||
value->GetData(data.data(), data.size(), 0);
|
||||
return *reinterpret_cast<const BrowserMessage*>(data.data());
|
||||
}
|
||||
|
||||
std::string ToMilliString(const Duration& duration) {
|
||||
const auto ms =
|
||||
std::chrono::duration_cast<std::chrono::duration<double, std::milli>>(
|
||||
duration);
|
||||
|
||||
return std::to_string(ms.count());
|
||||
}
|
||||
|
||||
} // namespace bv_utils
|
47
tests/shared/common/binary_value_utils.h
Normal file
47
tests/shared/common/binary_value_utils.h
Normal file
@ -0,0 +1,47 @@
|
||||
// Copyright (c) 2022 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_SHARED_COMMON_BINARY_VALUE_UTILS
|
||||
#define CEF_TESTS_SHARED_COMMON_BINARY_VALUE_UTILS
|
||||
#pragma once
|
||||
|
||||
#include <chrono>
|
||||
#include <cstdint>
|
||||
#include <vector>
|
||||
#include "include/cef_values.h"
|
||||
|
||||
namespace bv_utils {
|
||||
|
||||
extern const char kTestSendProcessMessage[];
|
||||
extern const char kTestSendSMRProcessMessage[];
|
||||
|
||||
using TimePoint = std::chrono::high_resolution_clock::time_point;
|
||||
using Duration = std::chrono::high_resolution_clock::duration;
|
||||
|
||||
struct RendererMessage {
|
||||
int test_id;
|
||||
TimePoint start_time;
|
||||
};
|
||||
|
||||
struct BrowserMessage {
|
||||
int test_id;
|
||||
Duration duration;
|
||||
TimePoint start_time;
|
||||
};
|
||||
|
||||
TimePoint Now();
|
||||
|
||||
CefRefPtr<CefBinaryValue> CreateCefBinaryValue(
|
||||
const std::vector<uint8_t>& data);
|
||||
|
||||
RendererMessage GetRendererMsgFromBinary(
|
||||
const CefRefPtr<CefBinaryValue>& value);
|
||||
|
||||
BrowserMessage GetBrowserMsgFromBinary(const CefRefPtr<CefBinaryValue>& value);
|
||||
|
||||
std::string ToMilliString(const Duration& duration);
|
||||
|
||||
} // namespace bv_utils
|
||||
|
||||
#endif // CEF_TESTS_SHARED_COMMON_BINARY_VALUE_UTILS
|
Loading…
x
Reference in New Issue
Block a user