Add callbacks for unresponsive render process (fixes #3661)

The client can optionally wait or terminate the render process.

Expose process exit codes via OnRenderProcessTerminated and
CefGetExitCode (fixes #2126).

cefclient: Add a new https://tests/hang page for testing hang behavior.

cefclient: Move message and resource handling to a new BaseClientHandler
class to support loading of test pages in default Chrome UI windows.
This commit is contained in:
Marshall Greenblatt 2024-03-12 15:47:10 -04:00
parent 5e616b2df0
commit b8f91c5431
73 changed files with 1957 additions and 368 deletions

View File

@ -620,6 +620,8 @@ source_set("libcef_static") {
"libcef/browser/frame_service_base.h",
"libcef/browser/global_preference_manager_impl.cc",
"libcef/browser/global_preference_manager_impl.h",
"libcef/browser/hang_monitor.cc",
"libcef/browser/hang_monitor.h",
"libcef/browser/image_impl.cc",
"libcef/browser/image_impl.h",
"libcef/browser/iothread_state.cc",

View File

@ -8,7 +8,7 @@
# by hand. See the translator.README.txt file in the tools directory for
# more information.
#
# $hash=25599539f43226aac01bfcb74f19ac74217aee9a$
# $hash=3b28f3236c16d2b776a44674ae3bae0a070e9f27$
#
{
@ -85,6 +85,7 @@
'include/cef_task.h',
'include/cef_thread.h',
'include/cef_trace.h',
'include/cef_unresponsive_process_callback.h',
'include/cef_urlrequest.h',
'include/cef_v8.h',
'include/cef_values.h',
@ -189,6 +190,7 @@
'include/capi/cef_task_capi.h',
'include/capi/cef_thread_capi.h',
'include/capi/cef_trace_capi.h',
'include/capi/cef_unresponsive_process_callback_capi.h',
'include/capi/cef_urlrequest_capi.h',
'include/capi/cef_v8_capi.h',
'include/capi/cef_values_capi.h',
@ -508,6 +510,8 @@
'libcef_dll/cpptoc/urlrequest_cpptoc.h',
'libcef_dll/ctocpp/urlrequest_client_ctocpp.cc',
'libcef_dll/ctocpp/urlrequest_client_ctocpp.h',
'libcef_dll/cpptoc/unresponsive_process_callback_cpptoc.cc',
'libcef_dll/cpptoc/unresponsive_process_callback_cpptoc.h',
'libcef_dll/ctocpp/v8accessor_ctocpp.cc',
'libcef_dll/ctocpp/v8accessor_ctocpp.h',
'libcef_dll/ctocpp/v8array_buffer_release_callback_ctocpp.cc',
@ -836,6 +840,8 @@
'libcef_dll/ctocpp/urlrequest_ctocpp.h',
'libcef_dll/cpptoc/urlrequest_client_cpptoc.cc',
'libcef_dll/cpptoc/urlrequest_client_cpptoc.h',
'libcef_dll/ctocpp/unresponsive_process_callback_ctocpp.cc',
'libcef_dll/ctocpp/unresponsive_process_callback_ctocpp.h',
'libcef_dll/cpptoc/v8accessor_cpptoc.cc',
'libcef_dll/cpptoc/v8accessor_cpptoc.h',
'libcef_dll/cpptoc/v8array_buffer_release_callback_cpptoc.cc',

View File

@ -220,6 +220,8 @@
'tests/shared/browser/util_win.h',
],
'cefclient_sources_browser': [
'tests/cefclient/browser/base_client_handler.cc',
'tests/cefclient/browser/base_client_handler.h',
'tests/cefclient/browser/binary_transfer_test.cc',
'tests/cefclient/browser/binary_transfer_test.h',
'tests/cefclient/browser/binding_test.cc',
@ -240,10 +242,11 @@
'tests/cefclient/browser/client_prefs.cc',
'tests/cefclient/browser/client_prefs.h',
'tests/cefclient/browser/client_types.h',
'tests/cefclient/browser/default_client_handler.cc',
'tests/cefclient/browser/default_client_handler.h',
'tests/cefclient/browser/dialog_test.cc',
'tests/cefclient/browser/dialog_test.h',
'tests/cefclient/browser/hang_test.cc',
'tests/cefclient/browser/hang_test.h',
'tests/cefclient/browser/image_cache.cc',
'tests/cefclient/browser/image_cache.h',
'tests/cefclient/browser/main_context.cc',
@ -309,11 +312,11 @@
'tests/cefclient/renderer/performance_test_tests.cc',
],
'cefclient_sources_resources': [
'tests/cefclient/resources/binary_transfer.html',
'tests/cefclient/resources/binding.html',
'tests/cefclient/resources/dialogs.html',
'tests/cefclient/resources/draggable.html',
'tests/cefclient/resources/hang.html',
'tests/cefclient/resources/ipc_performance.html',
'tests/cefclient/resources/binary_transfer.html',
'tests/cefclient/resources/localstorage.html',
'tests/cefclient/resources/logo.png',
'tests/cefclient/resources/media_router.html',

View File

@ -33,7 +33,7 @@
// by hand. See the translator.README.txt file in the tools directory for
// more information.
//
// $hash=b9a2bad4a30bcb99384197c9f7409116dc5b376e$
// $hash=dfa0d4d2da319b2fd5e92324fd14301b500ceb5c$
//
#ifndef CEF_INCLUDE_CAPI_CEF_APP_CAPI_H_
@ -137,15 +137,26 @@ CEF_EXPORT int cef_execute_process(const cef_main_args_t* args,
/// true (1) if initialization succeeds. Returns false (0) if initialization
/// fails or if early exit is desired (for example, due to process singleton
/// relaunch behavior). If this function returns false (0) then the application
/// should exit immediately without calling any other CEF functions. The
/// |windows_sandbox_info| parameter is only used on Windows and may be NULL
/// (see cef_sandbox_win.h for details).
/// should exit immediately without calling any other CEF functions except,
/// optionally, CefGetErrorCode. The |windows_sandbox_info| parameter is only
/// used on Windows and may be NULL (see cef_sandbox_win.h for details).
///
CEF_EXPORT int cef_initialize(const cef_main_args_t* args,
const struct _cef_settings_t* settings,
cef_app_t* application,
void* windows_sandbox_info);
///
/// This function can optionally be called on the main application thread after
/// CefInitialize to retrieve the initialization exit code. When CefInitialize
/// returns true (1) the exit code will be 0 (CEF_RESULT_CODE_NORMAL_EXIT).
/// Otherwise, see cef_resultcode_t for possible exit code values including
/// browser process initialization errors and normal early exit conditions (such
/// as CEF_RESULT_CODE_NORMAL_EXIT_PROCESS_NOTIFIED for process singleton
/// relaunch behavior).
///
CEF_EXPORT int cef_get_exit_code(void);
///
/// This function should be called on the main application thread to shut down
/// the CEF browser process before the application exits. Do not call any other

View File

@ -33,7 +33,7 @@
// by hand. See the translator.README.txt file in the tools directory for
// more information.
//
// $hash=e7f9480661f77931890085d6c5bf23d9842212e2$
// $hash=abcb584dbf5965834f415a0f2daeda3e361696b2$
//
#ifndef CEF_INCLUDE_CAPI_CEF_BROWSER_CAPI_H_
@ -974,6 +974,17 @@ typedef struct _cef_browser_host_t {
struct _cef_browser_host_t* self,
int command_id,
cef_window_open_disposition_t disposition);
///
/// Returns true (1) if the render process associated with this browser is
/// currently unresponsive as indicated by a lack of input event processing
/// for at least 15 seconds. To receive associated state change notifications
/// and optionally handle an unresponsive render process implement
/// cef_request_handler_t::OnRenderProcessUnresponsive. This function can only
/// be called on the UI thread.
///
int(CEF_CALLBACK* is_render_process_unresponsive)(
struct _cef_browser_host_t* self);
} cef_browser_host_t;
///

View File

@ -33,7 +33,7 @@
// by hand. See the translator.README.txt file in the tools directory for
// more information.
//
// $hash=3b59c0bc014d773dedc24649071141ee2dd2125c$
// $hash=2e8b5c5107f61e3d4c333dc02c76a9f30cd0cf83$
//
#ifndef CEF_INCLUDE_CAPI_CEF_REQUEST_HANDLER_CAPI_H_
@ -48,6 +48,7 @@
#include "include/capi/cef_request_capi.h"
#include "include/capi/cef_resource_request_handler_capi.h"
#include "include/capi/cef_ssl_info_capi.h"
#include "include/capi/cef_unresponsive_process_callback_capi.h"
#include "include/capi/cef_x509_certificate_capi.h"
#ifdef __cplusplus
@ -222,14 +223,53 @@ typedef struct _cef_request_handler_t {
void(CEF_CALLBACK* on_render_view_ready)(struct _cef_request_handler_t* self,
struct _cef_browser_t* browser);
///
/// Called on the browser process UI thread when the render process is
/// unresponsive as indicated by a lack of input event processing for at least
/// 15 seconds. Return false (0) for the default behavior which is an
/// indefinite wait with the Alloy runtime or display of the "Page
/// unresponsive" dialog with the Chrome runtime. Return true (1) and don't
/// execute the callback for an indefinite wait without display of the Chrome
/// runtime dialog. Return true (1) and call
/// cef_unresponsive_process_callback_t::Wait either in this function or at a
/// later time to reset the wait timer, potentially triggering another call to
/// this function if the process remains unresponsive. Return true (1) and
/// call cef_unresponsive_process_callback_t:: Terminate either in this
/// function or at a later time to terminate the unresponsive process,
/// resulting in a call to OnRenderProcessTerminated.
/// OnRenderProcessResponsive will be called if the process becomes responsive
/// after this function is called. This functionality depends on the hang
/// monitor which can be disabled by passing the `--disable-hang-monitor`
/// command-line flag.
///
int(CEF_CALLBACK* on_render_process_unresponsive)(
struct _cef_request_handler_t* self,
struct _cef_browser_t* browser,
struct _cef_unresponsive_process_callback_t* callback);
///
/// Called on the browser process UI thread when the render process becomes
/// responsive after previously being unresponsive. See documentation on
/// OnRenderProcessUnresponsive.
///
void(CEF_CALLBACK* on_render_process_responsive)(
struct _cef_request_handler_t* self,
struct _cef_browser_t* browser);
///
/// Called on the browser process UI thread when the render process terminates
/// unexpectedly. |status| indicates how the process terminated.
/// unexpectedly. |status| indicates how the process terminated. |error_code|
/// and |error_string| represent the error that would be displayed in Chrome's
/// "Aw, Snap!" view. Possible |error_code| values include cef_resultcode_t
/// non-normal exit values and platform-specific crash values (for example, a
/// Posix signal or Windows hardware exception).
///
void(CEF_CALLBACK* on_render_process_terminated)(
struct _cef_request_handler_t* self,
struct _cef_browser_t* browser,
cef_termination_status_t status);
cef_termination_status_t status,
int error_code,
const cef_string_t* error_string);
///
/// Called on the browser process UI thread when the window.document object of

View File

@ -0,0 +1,74 @@
// Copyright (c) 2024 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=9ad38f2709d9e3b1bd0e99c279b0497b8aa4c82a$
//
#ifndef CEF_INCLUDE_CAPI_CEF_UNRESPONSIVE_PROCESS_CALLBACK_CAPI_H_
#define CEF_INCLUDE_CAPI_CEF_UNRESPONSIVE_PROCESS_CALLBACK_CAPI_H_
#pragma once
#include "include/capi/cef_base_capi.h"
#ifdef __cplusplus
extern "C" {
#endif
///
/// Callback structure for asynchronous handling of an unresponsive process.
///
typedef struct _cef_unresponsive_process_callback_t {
///
/// Base structure.
///
cef_base_ref_counted_t base;
///
/// Reset the timeout for the unresponsive process.
///
void(CEF_CALLBACK* wait)(struct _cef_unresponsive_process_callback_t* self);
///
/// Terminate the unresponsive process.
///
void(CEF_CALLBACK* terminate)(
struct _cef_unresponsive_process_callback_t* self);
} cef_unresponsive_process_callback_t;
#ifdef __cplusplus
}
#endif
#endif // CEF_INCLUDE_CAPI_CEF_UNRESPONSIVE_PROCESS_CALLBACK_CAPI_H_

View File

@ -42,13 +42,13 @@
// way that may cause binary incompatibility with other builds. The universal
// hash value will change if any platform is affected whereas the platform hash
// values will change only if that particular platform is affected.
#define CEF_API_HASH_UNIVERSAL "93050a5111ee3131f5589bd7d3be5376539a64c2"
#define CEF_API_HASH_UNIVERSAL "6c5009ba08bb760e60f7e17845c532b30f19fbae"
#if defined(OS_WIN)
#define CEF_API_HASH_PLATFORM "ebcca93f53d935802a4cd02606864ff1eb1a1baa"
#define CEF_API_HASH_PLATFORM "09f5a8a3088d2a8384c648be2047e0cb25b1221e"
#elif defined(OS_MAC)
#define CEF_API_HASH_PLATFORM "a2c1ee5ae59a181773019412084903e4824aa300"
#define CEF_API_HASH_PLATFORM "ddee29d0c0de65874ff50f3ff7bc5de51089b9eb"
#elif defined(OS_LINUX)
#define CEF_API_HASH_PLATFORM "915ea22829d9814cb6481891de4619f0aafda72f"
#define CEF_API_HASH_PLATFORM "a27764fa2599737204faad84b00c31bb32dba54f"
#endif
#ifdef __cplusplus

View File

@ -71,9 +71,9 @@ int CefExecuteProcess(const CefMainArgs& args,
/// true if initialization succeeds. Returns false if initialization fails or if
/// early exit is desired (for example, due to process singleton relaunch
/// behavior). If this function returns false then the application should exit
/// immediately without calling any other CEF functions. The
/// |windows_sandbox_info| parameter is only used on Windows and may be NULL
/// (see cef_sandbox_win.h for details).
/// immediately without calling any other CEF functions except, optionally,
/// CefGetErrorCode. The |windows_sandbox_info| parameter is only used on
/// Windows and may be NULL (see cef_sandbox_win.h for details).
///
/*--cef(api_hash_check,optional_param=application,
optional_param=windows_sandbox_info)--*/
@ -82,6 +82,18 @@ bool CefInitialize(const CefMainArgs& args,
CefRefPtr<CefApp> application,
void* windows_sandbox_info);
///
/// This function can optionally be called on the main application thread after
/// CefInitialize to retrieve the initialization exit code. When CefInitialize
/// returns true the exit code will be 0 (CEF_RESULT_CODE_NORMAL_EXIT).
/// Otherwise, see cef_resultcode_t for possible exit code values including
/// browser process initialization errors and normal early exit conditions (such
/// as CEF_RESULT_CODE_NORMAL_EXIT_PROCESS_NOTIFIED for process singleton
/// relaunch behavior).
///
/*--cef()--*/
int CefGetExitCode();
///
/// This function should be called on the main application thread to shut down
/// the CEF browser process before the application exits. Do not call any

View File

@ -1007,6 +1007,17 @@ class CefBrowserHost : public virtual CefBaseRefCounted {
virtual void ExecuteChromeCommand(
int command_id,
cef_window_open_disposition_t disposition) = 0;
///
/// Returns true if the render process associated with this browser is
/// currently unresponsive as indicated by a lack of input event processing
/// for at least 15 seconds. To receive associated state change notifications
/// and optionally handle an unresponsive render process implement
/// CefRequestHandler::OnRenderProcessUnresponsive. This method can only be
/// called on the UI thread.
///
/*--cef()--*/
virtual bool IsRenderProcessUnresponsive() = 0;
};
#endif // CEF_INCLUDE_CEF_BROWSER_H_

View File

@ -48,6 +48,7 @@
#include "include/cef_request.h"
#include "include/cef_resource_request_handler.h"
#include "include/cef_ssl_info.h"
#include "include/cef_unresponsive_process_callback.h"
#include "include/cef_x509_certificate.h"
///
@ -221,14 +222,52 @@ class CefRequestHandler : public virtual CefBaseRefCounted {
/*--cef()--*/
virtual void OnRenderViewReady(CefRefPtr<CefBrowser> browser) {}
///
/// Called on the browser process UI thread when the render process is
/// unresponsive as indicated by a lack of input event processing for at
/// least 15 seconds. Return false for the default behavior which is an
/// indefinite wait with the Alloy runtime or display of the "Page
/// unresponsive" dialog with the Chrome runtime. Return true and don't
/// execute the callback for an indefinite wait without display of the Chrome
/// runtime dialog. Return true and call CefUnresponsiveProcessCallback::Wait
/// either in this method or at a later time to reset the wait timer,
/// potentially triggering another call to this method if the process remains
/// unresponsive. Return true and call CefUnresponsiveProcessCallback::
/// Terminate either in this method or at a later time to terminate the
/// unresponsive process, resulting in a call to OnRenderProcessTerminated.
/// OnRenderProcessResponsive will be called if the process becomes responsive
/// after this method is called. This functionality depends on the hang
/// monitor which can be disabled by passing the `--disable-hang-monitor`
/// command-line flag.
///
/*--cef()--*/
virtual bool OnRenderProcessUnresponsive(
CefRefPtr<CefBrowser> browser,
CefRefPtr<CefUnresponsiveProcessCallback> callback) {
return false;
}
///
/// Called on the browser process UI thread when the render process becomes
/// responsive after previously being unresponsive. See documentation on
/// OnRenderProcessUnresponsive.
///
/*--cef()--*/
virtual void OnRenderProcessResponsive(CefRefPtr<CefBrowser> browser) {}
///
/// Called on the browser process UI thread when the render process
/// terminates unexpectedly. |status| indicates how the process
/// terminated.
/// terminates unexpectedly. |status| indicates how the process terminated.
/// |error_code| and |error_string| represent the error that would be
/// displayed in Chrome's "Aw, Snap!" view. Possible |error_code| values
/// include cef_resultcode_t non-normal exit values and platform-specific
/// crash values (for example, a Posix signal or Windows hardware exception).
///
/*--cef()--*/
virtual void OnRenderProcessTerminated(CefRefPtr<CefBrowser> browser,
TerminationStatus status) {}
TerminationStatus status,
int error_code,
const CefString& error_string) {}
///
/// Called on the browser process UI thread when the window.document object of

View File

@ -0,0 +1,62 @@
// Copyright (c) 2024 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_UNRESPONSIVE_PROCESS_CALLBACK_H_
#define CEF_INCLUDE_CEF_UNRESPONSIVE_PROCESS_CALLBACK_H_
#pragma once
#include "include/cef_base.h"
///
/// Callback interface for asynchronous handling of an unresponsive process.
///
/*--cef(source=library)--*/
class CefUnresponsiveProcessCallback : public virtual CefBaseRefCounted {
public:
///
/// Reset the timeout for the unresponsive process.
///
/*--cef()--*/
virtual void Wait() = 0;
///
/// Terminate the unresponsive process.
///
/*--cef()--*/
virtual void Terminate() = 0;
};
#endif // CEF_INCLUDE_CEF_UNRESPONSIVE_PROCESS_CALLBACK_H_

View File

@ -917,6 +917,16 @@ typedef enum {
/// Out of memory. Some platforms may use TS_PROCESS_CRASHED instead.
///
TS_PROCESS_OOM,
///
/// Child process never launched.
///
TS_LAUNCH_FAILED,
///
/// On Windows, the OS terminated the process due to code integrity failure.
///
TS_INTEGRITY_FAILURE,
} cef_termination_status_t;
///
@ -1027,6 +1037,100 @@ typedef enum {
CERT_STATUS_CT_COMPLIANCE_FAILED = 1 << 20,
} cef_cert_status_t;
///
/// Process result codes. This is not a comprehensive list, as result codes
/// might also include platform-specific crash values (Posix signal or Windows
/// hardware exception), or internal-only implementation values.
///
typedef enum {
// The following values should be kept in sync with Chromium's
// content::ResultCode type.
CEF_RESULT_CODE_NORMAL_EXIT,
/// Process was killed by user or system.
CEF_RESULT_CODE_KILLED,
/// Process hung.
CEF_RESULT_CODE_HUNG,
/// A bad message caused the process termination.
CEF_RESULT_CODE_KILLED_BAD_MESSAGE,
/// The GPU process exited because initialization failed.
CEF_RESULT_CODE_GPU_DEAD_ON_ARRIVAL,
// The following values should be kept in sync with Chromium's
// chrome::ResultCode type. Unused chrome values are excluded.
CEF_RESULT_CODE_CHROME_FIRST,
/// A critical chrome file is missing.
CEF_RESULT_CODE_MISSING_DATA = 7,
/// Command line parameter is not supported.
CEF_RESULT_CODE_UNSUPPORTED_PARAM = 13,
/// The profile was in use on another host.
CEF_RESULT_CODE_PROFILE_IN_USE = 21,
/// Failed to pack an extension via the command line.
CEF_RESULT_CODE_PACK_EXTENSION_ERROR = 22,
/// The browser process exited early by passing the command line to another
/// running browser.
CEF_RESULT_CODE_NORMAL_EXIT_PROCESS_NOTIFIED = 24,
/// A browser process was sandboxed. This should never happen.
CEF_RESULT_CODE_INVALID_SANDBOX_STATE = 31,
/// Cloud policy enrollment failed or was given up by user.
CEF_RESULT_CODE_CLOUD_POLICY_ENROLLMENT_FAILED = 32,
/// The GPU process was terminated due to context lost.
CEF_RESULT_CODE_GPU_EXIT_ON_CONTEXT_LOST = 34,
/// An early startup command was executed and the browser must exit.
CEF_RESULT_CODE_NORMAL_EXIT_PACK_EXTENSION_SUCCESS = 36,
/// The browser process exited because system resources are exhausted. The
/// system state can't be recovered and will be unstable.
CEF_RESULT_CODE_SYSTEM_RESOURCE_EXHAUSTED = 37,
CEF_RESULT_CODE_CHROME_LAST = 39,
// The following values should be kept in sync with Chromium's
// sandbox::TerminationCodes type.
CEF_RESULT_CODE_SANDBOX_FATAL_FIRST = 7006,
/// Windows sandbox could not set the integrity level.
CEF_RESULT_CODE_SANDBOX_FATAL_INTEGRITY = CEF_RESULT_CODE_SANDBOX_FATAL_FIRST,
/// Windows sandbox could not lower the token.
CEF_RESULT_CODE_SANDBOX_FATAL_DROPTOKEN,
/// Windows sandbox failed to flush registry handles.
CEF_RESULT_CODE_SANDBOX_FATAL_FLUSHANDLES,
/// Windows sandbox failed to forbid HCKU caching.
CEF_RESULT_CODE_SANDBOX_FATAL_CACHEDISABLE,
/// Windows sandbox failed to close pending handles.
CEF_RESULT_CODE_SANDBOX_FATAL_CLOSEHANDLES,
/// Windows sandbox could not set the mitigation policy.
CEF_RESULT_CODE_SANDBOX_FATAL_MITIGATION,
/// Windows sandbox exceeded the job memory limit.
CEF_RESULT_CODE_SANDBOX_FATAL_MEMORY_EXCEEDED,
/// Windows sandbox failed to warmup.
CEF_RESULT_CODE_SANDBOX_FATAL_WARMUP,
CEF_RESULT_CODE_SANDBOX_FATAL_LAST,
} cef_resultcode_t;
///
/// The manner in which a link click should be opened. These constants match
/// their equivalents in Chromium's window_open_disposition.h and should not be

View File

@ -18,6 +18,7 @@
#include "libcef/browser/browser_platform_delegate.h"
#include "libcef/browser/context.h"
#include "libcef/browser/devtools/devtools_manager.h"
#include "libcef/browser/hang_monitor.h"
#include "libcef/browser/media_access_query.h"
#include "libcef/browser/osr/osr_util.h"
#include "libcef/browser/request_context_impl.h"
@ -1196,6 +1197,20 @@ void AlloyBrowserHostImpl::WebContentsCreated(
std::move(platform_delegate), /*extension=*/nullptr);
}
void AlloyBrowserHostImpl::RendererUnresponsive(
content::WebContents* source,
content::RenderWidgetHost* render_widget_host,
base::RepeatingClosure hang_monitor_restarter) {
hang_monitor::RendererUnresponsive(this, render_widget_host,
hang_monitor_restarter);
}
void AlloyBrowserHostImpl::RendererResponsive(
content::WebContents* source,
content::RenderWidgetHost* render_widget_host) {
hang_monitor::RendererResponsive(this, render_widget_host);
}
content::JavaScriptDialogManager*
AlloyBrowserHostImpl::GetJavaScriptDialogManager(content::WebContents* source) {
if (!javascript_dialog_manager_) {

View File

@ -233,6 +233,13 @@ class AlloyBrowserHostImpl : public CefBrowserHostBase,
const std::string& frame_name,
const GURL& target_url,
content::WebContents* new_contents) override;
void RendererUnresponsive(
content::WebContents* source,
content::RenderWidgetHost* render_widget_host,
base::RepeatingClosure hang_monitor_restarter) override;
void RendererResponsive(
content::WebContents* source,
content::RenderWidgetHost* render_widget_host) override;
content::JavaScriptDialogManager* GetJavaScriptDialogManager(
content::WebContents* source) override;
void RunFileChooser(content::RenderFrameHost* render_frame_host,

View File

@ -10,6 +10,8 @@
#include "libcef/browser/native/cursor_util.h"
#include "libcef/common/frame_util.h"
#include "chrome/browser/ui/views/sad_tab_view.h"
#include "chrome/common/chrome_result_codes.h"
#include "content/browser/renderer_host/render_widget_host_impl.h"
#include "content/public/browser/focused_node_details.h"
#include "content/public/browser/keyboard_event_processing_result.h"
@ -25,6 +27,10 @@
#include "third_party/blink/public/mojom/input/focus_type.mojom-blink.h"
#include "third_party/blink/public/mojom/widget/platform_widget.mojom-test-utils.h"
#if defined(OS_WIN)
#include "sandbox/win/src/sandbox_types.h"
#endif
using content::KeyboardEventProcessingResult;
namespace {
@ -351,6 +357,22 @@ void CefBrowserContentsDelegate::RenderViewReady() {
void CefBrowserContentsDelegate::PrimaryMainFrameRenderProcessGone(
base::TerminationStatus status) {
static_assert(static_cast<int>(CEF_RESULT_CODE_CHROME_FIRST) ==
static_cast<int>(chrome::RESULT_CODE_CHROME_START),
"enum mismatch");
static_assert(static_cast<int>(CEF_RESULT_CODE_CHROME_LAST) ==
static_cast<int>(chrome::RESULT_CODE_CHROME_LAST_CODE),
"enum mismatch");
#if defined(OS_WIN)
static_assert(static_cast<int>(CEF_RESULT_CODE_SANDBOX_FATAL_FIRST) ==
static_cast<int>(sandbox::SBOX_FATAL_INTEGRITY),
"enum mismatch");
static_assert(static_cast<int>(CEF_RESULT_CODE_SANDBOX_FATAL_LAST) ==
static_cast<int>(sandbox::SBOX_FATAL_LAST),
"enum mismatch");
#endif
cef_termination_status_t ts = TS_ABNORMAL_TERMINATION;
if (status == base::TERMINATION_STATUS_PROCESS_WAS_KILLED) {
ts = TS_PROCESS_WAS_KILLED;
@ -358,14 +380,22 @@ void CefBrowserContentsDelegate::PrimaryMainFrameRenderProcessGone(
ts = TS_PROCESS_CRASHED;
} else if (status == base::TERMINATION_STATUS_OOM) {
ts = TS_PROCESS_OOM;
} else if (status == base::TERMINATION_STATUS_LAUNCH_FAILED) {
ts = TS_LAUNCH_FAILED;
#if BUILDFLAG(IS_WIN)
} else if (status == base::TERMINATION_STATUS_INTEGRITY_FAILURE) {
ts = TS_INTEGRITY_FAILURE;
#endif
} else if (status != base::TERMINATION_STATUS_ABNORMAL_TERMINATION) {
return;
}
if (auto c = client()) {
if (auto handler = c->GetRequestHandler()) {
int error_code = web_contents()->GetCrashedErrorCode();
auto navigation_lock = browser_info_->CreateNavigationLock();
handler->OnRenderProcessTerminated(browser(), ts);
handler->OnRenderProcessTerminated(browser(), ts, error_code,
SadTabView::ErrorToString(error_code));
}
}
}

View File

@ -9,6 +9,7 @@
#include "libcef/browser/browser_info_manager.h"
#include "libcef/browser/browser_platform_delegate.h"
#include "libcef/browser/context.h"
#include "libcef/browser/hang_monitor.h"
#include "libcef/browser/image_impl.h"
#include "libcef/browser/navigation_entry_impl.h"
#include "libcef/browser/printing/print_util.h"
@ -31,6 +32,8 @@
#include "content/public/browser/download_request_utils.h"
#include "content/public/browser/file_select_listener.h"
#include "content/public/browser/navigation_entry.h"
#include "content/public/browser/render_view_host.h"
#include "content/public/browser/render_widget_host.h"
#include "ui/base/resource/resource_scale_factor.h"
#include "ui/gfx/image/image_skia.h"
#include "ui/shell_dialogs/select_file_policy.h"
@ -256,6 +259,11 @@ void CefBrowserHostBase::DestroyBrowser() {
contents_delegate_->RemoveObserver(this);
contents_delegate_->ObserveWebContents(nullptr);
if (unresponsive_process_callback_) {
hang_monitor::Detach(unresponsive_process_callback_);
unresponsive_process_callback_.reset();
}
CefBrowserInfoManager::GetInstance()->RemoveBrowserInfo(browser_info_);
browser_info_->SetBrowser(nullptr);
}
@ -707,6 +715,22 @@ void CefBrowserHostBase::ExitFullscreen(bool will_cause_resize) {
}
}
bool CefBrowserHostBase::IsRenderProcessUnresponsive() {
if (!CEF_CURRENTLY_ON_UIT()) {
DCHECK(false) << "called on invalid thread";
return false;
}
if (auto* web_contents = GetWebContents()) {
if (auto* rvh = web_contents->GetRenderViewHost()) {
if (auto* rwh = rvh->GetWidget()) {
return rwh->IsCurrentlyUnresponsive();
}
}
}
return false;
}
void CefBrowserHostBase::ReplaceMisspelling(const CefString& word) {
if (!CEF_CURRENTLY_ON_UIT()) {
CEF_POST_TASK(

View File

@ -8,6 +8,7 @@
#include "include/cef_browser.h"
#include "include/cef_client.h"
#include "include/cef_unresponsive_process_callback.h"
#include "include/views/cef_browser_view.h"
#include "libcef/browser/browser_contents_delegate.h"
#include "libcef/browser/browser_info.h"
@ -238,6 +239,7 @@ class CefBrowserHostBase : public CefBrowserHost,
void NotifyMoveOrResizeStarted() override;
bool IsFullscreen() override;
void ExitFullscreen(bool will_cause_resize) override;
bool IsRenderProcessUnresponsive() override;
// CefBrowser methods:
bool IsValid() override;
@ -341,6 +343,15 @@ class CefBrowserHostBase : public CefBrowserHost,
}
CefMediaStreamRegistrar* GetMediaStreamRegistrar();
CefRefPtr<CefUnresponsiveProcessCallback> unresponsive_process_callback()
const {
return unresponsive_process_callback_;
}
void set_unresponsive_process_callback(
CefRefPtr<CefUnresponsiveProcessCallback> callback) {
unresponsive_process_callback_ = callback;
}
// Returns the Widget owner for the browser window. Only used with windowed
// browsers.
views::Widget* GetWindowWidget() const;
@ -391,6 +402,7 @@ class CefBrowserHostBase : public CefBrowserHost,
// Only accessed on the UI thread.
std::unique_ptr<CefBrowserContentsDelegate> contents_delegate_;
CefRefPtr<CefUnresponsiveProcessCallback> unresponsive_process_callback_;
// Observers that want to be notified of changes to this object.
// Only accessed on the UI thread.

View File

@ -119,6 +119,21 @@ class BrowserDelegate : public content::WebContentsDelegate {
return callback;
}
// Same as RendererUnresponsive but returning false if unhandled.
virtual bool RendererUnresponsiveEx(
content::WebContents* source,
content::RenderWidgetHost* render_widget_host,
base::RepeatingClosure hang_monitor_restarter) {
return false;
}
// Same as RendererResponsive but returning false if unhandled.
virtual bool RendererResponsiveEx(
content::WebContents* source,
content::RenderWidgetHost* render_widget_host) {
return false;
}
// Optionally override support for the specified window feature of type
// Browser::WindowFeature.
virtual std::optional<bool> SupportsWindowFeature(int feature) const {

View File

@ -14,6 +14,7 @@
#include "libcef/browser/chrome/chrome_browser_host_impl.h"
#include "libcef/browser/chrome/views/chrome_browser_view.h"
#include "libcef/browser/chrome/views/chrome_child_window.h"
#include "libcef/browser/hang_monitor.h"
#include "libcef/browser/media_access_query.h"
#include "libcef/browser/request_context_impl.h"
#include "libcef/browser/views/browser_view_impl.h"
@ -361,6 +362,26 @@ ChromeBrowserDelegate::RequestMediaAccessPermissionEx(
return callback;
}
bool ChromeBrowserDelegate::RendererUnresponsiveEx(
content::WebContents* source,
content::RenderWidgetHost* render_widget_host,
base::RepeatingClosure hang_monitor_restarter) {
if (auto browser = ChromeBrowserHostImpl::GetBrowserForBrowser(browser_)) {
return hang_monitor::RendererUnresponsive(browser.get(), render_widget_host,
hang_monitor_restarter);
}
return false;
}
bool ChromeBrowserDelegate::RendererResponsiveEx(
content::WebContents* source,
content::RenderWidgetHost* render_widget_host) {
if (auto browser = ChromeBrowserHostImpl::GetBrowserForBrowser(browser_)) {
return hang_monitor::RendererResponsive(browser.get(), render_widget_host);
}
return false;
}
bool ChromeBrowserDelegate::SupportsFramelessPictureInPicture() const {
if (!browser_->is_type_picture_in_picture()) {
return false;

View File

@ -76,6 +76,13 @@ class ChromeBrowserDelegate : public cef::BrowserDelegate {
content::WebContents* web_contents,
const content::MediaStreamRequest& request,
content::MediaResponseCallback callback) override;
bool RendererUnresponsiveEx(
content::WebContents* source,
content::RenderWidgetHost* render_widget_host,
base::RepeatingClosure hang_monitor_restarter) override;
bool RendererResponsiveEx(
content::WebContents* source,
content::RenderWidgetHost* render_widget_host) override;
std::optional<bool> SupportsWindowFeature(int feature) const override;
bool SupportsDraggableRegion() const override;
const std::optional<SkRegion> GetDraggableRegion() const override;

View File

@ -34,6 +34,9 @@ namespace {
CefContext* g_context = nullptr;
// Invalid value before CefInitialize is called.
int g_exit_code = -1;
#if DCHECK_IS_ON()
// When the process terminates check if CefShutdown() has been called.
class CefShutdownChecker {
@ -309,8 +312,11 @@ bool CefInitialize(const CefMainArgs& args,
g_context = new CefContext();
// Initialize the global context.
if (!g_context->Initialize(args, settings, application,
windows_sandbox_info)) {
const bool initialized =
g_context->Initialize(args, settings, application, windows_sandbox_info);
g_exit_code = g_context->exit_code();
if (!initialized) {
// Initialization failed. Delete the global context object.
delete g_context;
g_context = nullptr;
@ -320,6 +326,11 @@ bool CefInitialize(const CefMainArgs& args,
return true;
}
int CefGetExitCode() {
DCHECK_NE(g_exit_code, -1) << "invalid call to CefGetExitCode";
return g_exit_code;
}
void CefShutdown() {
// Verify that the context is in a valid state.
if (!CONTEXT_STATE_VALID()) {
@ -477,10 +488,14 @@ bool CefContext::Initialize(const CefMainArgs& args,
main_runner_ = std::make_unique<CefMainRunner>(
settings_.multi_threaded_message_loop, settings_.external_message_pump);
if (!main_runner_->Initialize(
&settings_, application, args, windows_sandbox_info, &initialized_,
base::BindOnce(&CefContext::OnContextInitialized,
base::Unretained(this)))) {
const bool initialized = main_runner_->Initialize(
&settings_, application, args, windows_sandbox_info, &initialized_,
base::BindOnce(&CefContext::OnContextInitialized,
base::Unretained(this)));
exit_code_ = main_runner_->exit_code();
if (!initialized) {
shutting_down_ = true;
FinalizeShutdown();
return false;

View File

@ -52,10 +52,13 @@ class CefContext {
bool OnInitThread();
// Returns true if the context is initialized.
bool initialized() { return initialized_; }
bool initialized() const { return initialized_; }
// Returns true if the context is shutting down.
bool shutting_down() { return shutting_down_; }
bool shutting_down() const { return shutting_down_; }
// Only valid after Initialize is called.
int exit_code() const { return exit_code_; }
const CefSettings& settings() const { return settings_; }
@ -100,6 +103,7 @@ class CefContext {
// Track context state.
bool initialized_ = false;
bool shutting_down_ = false;
int exit_code_ = -1;
// The thread on which the context was initialized.
base::PlatformThreadId init_thread_id_ = 0;

View File

@ -0,0 +1,167 @@
// Copyright 2024 The Chromium Embedded Framework Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be found
// in the LICENSE file.
#include "libcef/browser/hang_monitor.h"
#include "include/cef_client.h"
#include "libcef/browser/browser_host_base.h"
#include "build/build_config.h"
#include "chrome/browser/hang_monitor/hang_crash_dump.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/browser/render_widget_host.h"
#include "content/public/common/result_codes.h"
namespace hang_monitor {
namespace {
// Based on HungRendererDialogView::ForceCrashHungRenderer.
void ForceCrashHungRenderer(content::RenderWidgetHost* render_widget_host) {
content::RenderProcessHost* rph = render_widget_host->GetProcess();
if (rph) {
#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
// A generic |CrashDumpHungChildProcess()| is not implemented for Linux.
// Instead we send an explicit IPC to crash on the renderer's IO thread.
rph->ForceCrash();
#else
// Try to generate a crash report for the hung process.
CrashDumpHungChildProcess(rph->GetProcess().Handle());
rph->Shutdown(content::RESULT_CODE_HUNG);
#endif
}
}
class CefUnresponsiveProcessCallbackImpl
: public CefUnresponsiveProcessCallback {
public:
CefUnresponsiveProcessCallbackImpl(
content::RenderWidgetHost* render_widget_host,
base::RepeatingClosure hang_monitor_restarter)
: render_widget_host_(render_widget_host),
hang_monitor_restarter_(hang_monitor_restarter) {}
CefUnresponsiveProcessCallbackImpl(
const CefUnresponsiveProcessCallbackImpl&) = delete;
CefUnresponsiveProcessCallbackImpl& operator=(
const CefUnresponsiveProcessCallbackImpl&) = delete;
~CefUnresponsiveProcessCallbackImpl() override {
// Do nothing on destruction.
}
void Wait() override { ContinueNow(true); }
void Terminate() override { ContinueNow(false); }
void Detach() {
render_widget_host_ = nullptr;
hang_monitor_restarter_.Reset();
}
bool IsDetached() const { return !render_widget_host_; }
private:
void ContinueNow(bool wait) {
if (CEF_CURRENTLY_ON_UIT()) {
if (!IsDetached()) {
RunNow(render_widget_host_, hang_monitor_restarter_, wait);
Detach();
}
} else {
CEF_POST_TASK(
CEF_UIT,
base::BindOnce(&CefUnresponsiveProcessCallbackImpl::ContinueNow, this,
wait));
}
}
static void RunNow(content::RenderWidgetHost* render_widget_host,
base::RepeatingClosure hang_monitor_restarter,
bool wait) {
CEF_REQUIRE_UIT();
if (wait) {
hang_monitor_restarter.Run();
} else {
ForceCrashHungRenderer(render_widget_host);
}
}
content::RenderWidgetHost* render_widget_host_;
base::RepeatingClosure hang_monitor_restarter_;
IMPLEMENT_REFCOUNTING(CefUnresponsiveProcessCallbackImpl);
};
bool ResetRendererCallback(CefBrowserHostBase* browser) {
CEF_REQUIRE_UIT();
if (auto callback = browser->unresponsive_process_callback()) {
Detach(callback);
browser->set_unresponsive_process_callback(nullptr);
return true;
}
return false;
}
CefRefPtr<CefRequestHandler> GetRequestHandler(CefBrowserHostBase* browser) {
if (auto client = browser->GetClient()) {
return client->GetRequestHandler();
}
return nullptr;
}
} // namespace
bool RendererUnresponsive(CefBrowserHostBase* browser,
content::RenderWidgetHost* render_widget_host,
base::RepeatingClosure hang_monitor_restarter) {
// There should be no callback currently.
DCHECK(!browser->unresponsive_process_callback());
if (auto handler = GetRequestHandler(browser)) {
CefRefPtr<CefUnresponsiveProcessCallbackImpl> callbackImpl(
new CefUnresponsiveProcessCallbackImpl(render_widget_host,
hang_monitor_restarter));
if (!handler->OnRenderProcessUnresponsive(browser, callbackImpl.get())) {
if (!callbackImpl->IsDetached()) {
// Proceed with default handling.
callbackImpl->Detach();
return false;
} else {
LOG(ERROR) << "Should return true from OnRenderProcessUnresponsive "
"when executing the callback";
}
}
// Proceed with client handling. The callback may already be executed, but
// we still want to wait for RendererResponsive.
browser->set_unresponsive_process_callback(callbackImpl.get());
return true;
}
// Proceed with default handling.
return false;
}
bool RendererResponsive(CefBrowserHostBase* browser,
content::RenderWidgetHost* render_widget_host) {
// |handled| will be true if the client handled OnRenderProcessUnresponsive.
bool handled = ResetRendererCallback(browser);
// Always execute the client callback.
if (auto handler = GetRequestHandler(browser)) {
handler->OnRenderProcessResponsive(browser);
}
return handled;
}
void Detach(CefRefPtr<CefUnresponsiveProcessCallback> callback) {
CEF_REQUIRE_UIT();
auto* callback_impl =
static_cast<CefUnresponsiveProcessCallbackImpl*>(callback.get());
callback_impl->Detach();
}
} // namespace hang_monitor

View File

@ -0,0 +1,37 @@
// Copyright 2024 The Chromium Embedded Framework Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be found
// in the LICENSE file.
#ifndef CEF_LIBCEF_BROWSER_HANG_MONITOR_H_
#define CEF_LIBCEF_BROWSER_HANG_MONITOR_H_
#pragma once
#include "include/cef_unresponsive_process_callback.h"
#include "base/functional/callback.h"
namespace content {
class RenderWidgetHost;
}
class CefBrowserHostBase;
namespace hang_monitor {
// Called from WebContentsDelegate::RendererUnresponsive.
// Returns false for default handling.
bool RendererUnresponsive(CefBrowserHostBase* browser,
content::RenderWidgetHost* render_widget_host,
base::RepeatingClosure hang_monitor_restarter);
// Called from WebContentsDelegate::RendererResponsive.
// Returns false for default handling.
bool RendererResponsive(CefBrowserHostBase* browser,
content::RenderWidgetHost* render_widget_host);
// Detach an existing callback object.
void Detach(CefRefPtr<CefUnresponsiveProcessCallback> callback);
} // namespace hang_monitor
#endif // CEF_LIBCEF_BROWSER_HANG_MONITOR_H_

View File

@ -245,20 +245,20 @@ bool CefMainRunner::Initialize(CefSettings* settings,
settings->chrome_runtime ? RuntimeType::CHROME : RuntimeType::ALLOY, this,
settings, application);
int exit_code =
exit_code_ =
ContentMainInitialize(args, windows_sandbox_info, &settings->no_sandbox);
if (exit_code >= 0) {
LOG(ERROR) << "ContentMainInitialize failed with exit code " << exit_code;
if (exit_code_ >= 0) {
LOG(ERROR) << "ContentMainInitialize failed with exit code " << exit_code_;
return false;
}
exit_code = ContentMainRun(initialized, std::move(context_initialized));
if (exit_code != content::RESULT_CODE_NORMAL_EXIT) {
exit_code_ = ContentMainRun(initialized, std::move(context_initialized));
if (exit_code_ != content::RESULT_CODE_NORMAL_EXIT) {
// Some exit codes are used to exit early, but are otherwise a normal
// result. Don't log for those codes.
if (!chrome::IsNormalResultCode(
static_cast<chrome::ResultCode>(exit_code))) {
LOG(ERROR) << "ContentMainRun failed with exit code " << exit_code;
static_cast<chrome::ResultCode>(exit_code_))) {
LOG(ERROR) << "ContentMainRun failed with exit code " << exit_code_;
}
return false;
}

View File

@ -42,6 +42,9 @@ class CefMainRunner : public CefMainRunnerHandler {
bool* initialized,
base::OnceClosure context_initialized);
// Only valid after Initialize is called.
int exit_code() const { return exit_code_; }
// Called from CefContext::Shutdown.
void Shutdown(base::OnceClosure shutdown_on_ui_thread,
base::OnceClosure finalize_shutdown);
@ -90,6 +93,8 @@ class CefMainRunner : public CefMainRunnerHandler {
// Used to quit the current base::RunLoop.
base::OnceClosure quit_callback_;
int exit_code_ = -1;
};
#endif // CEF_LIBCEF_BROWSER_MAIN_RUNNER_H_

View File

@ -9,7 +9,7 @@
// implementations. See the translator.README.txt file in the tools directory
// for more information.
//
// $hash=c1afe37bef47447905f9dc6b6ba56f550e24021f$
// $hash=790f88d9d22bbef9882470f0980f5e7e446d30c5$
//
#include "libcef_dll/cpptoc/browser_host_cpptoc.h"
@ -1506,6 +1506,24 @@ browser_host_execute_chrome_command(struct _cef_browser_host_t* self,
disposition);
}
int CEF_CALLBACK
browser_host_is_render_process_unresponsive(struct _cef_browser_host_t* self) {
shutdown_checker::AssertNotShutdown();
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
DCHECK(self);
if (!self) {
return 0;
}
// Execute
bool _retval = CefBrowserHostCppToC::Get(self)->IsRenderProcessUnresponsive();
// Return type: bool
return _retval;
}
} // namespace
// CONSTRUCTOR - Do not edit by hand.
@ -1588,6 +1606,8 @@ CefBrowserHostCppToC::CefBrowserHostCppToC() {
GetStruct()->can_execute_chrome_command =
browser_host_can_execute_chrome_command;
GetStruct()->execute_chrome_command = browser_host_execute_chrome_command;
GetStruct()->is_render_process_unresponsive =
browser_host_is_render_process_unresponsive;
}
// DESTRUCTOR - Do not edit by hand.

View File

@ -9,7 +9,7 @@
// implementations. See the translator.README.txt file in the tools directory
// for more information.
//
// $hash=4a0c9cb5d77d315e067d07ed633b623a8e12a1fc$
// $hash=436eb7d254d6edc452b8b529758967d274fa2f85$
//
#include "libcef_dll/cpptoc/request_handler_cpptoc.h"
@ -21,6 +21,7 @@
#include "libcef_dll/ctocpp/request_ctocpp.h"
#include "libcef_dll/ctocpp/select_client_certificate_callback_ctocpp.h"
#include "libcef_dll/ctocpp/sslinfo_ctocpp.h"
#include "libcef_dll/ctocpp/unresponsive_process_callback_ctocpp.h"
#include "libcef_dll/ctocpp/x509certificate_ctocpp.h"
#include "libcef_dll/shutdown_checker.h"
@ -345,10 +346,42 @@ request_handler_on_render_view_ready(struct _cef_request_handler_t* self,
CefBrowserCToCpp::Wrap(browser));
}
void CEF_CALLBACK request_handler_on_render_process_terminated(
int CEF_CALLBACK request_handler_on_render_process_unresponsive(
struct _cef_request_handler_t* self,
cef_browser_t* browser,
cef_termination_status_t status) {
struct _cef_unresponsive_process_callback_t* callback) {
shutdown_checker::AssertNotShutdown();
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
DCHECK(self);
if (!self) {
return 0;
}
// Verify param: browser; type: refptr_diff
DCHECK(browser);
if (!browser) {
return 0;
}
// Verify param: callback; type: refptr_diff
DCHECK(callback);
if (!callback) {
return 0;
}
// Execute
bool _retval =
CefRequestHandlerCppToC::Get(self)->OnRenderProcessUnresponsive(
CefBrowserCToCpp::Wrap(browser),
CefUnresponsiveProcessCallbackCToCpp::Wrap(callback));
// Return type: bool
return _retval;
}
void CEF_CALLBACK request_handler_on_render_process_responsive(
struct _cef_request_handler_t* self,
cef_browser_t* browser) {
shutdown_checker::AssertNotShutdown();
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
@ -363,9 +396,40 @@ void CEF_CALLBACK request_handler_on_render_process_terminated(
return;
}
// Execute
CefRequestHandlerCppToC::Get(self)->OnRenderProcessResponsive(
CefBrowserCToCpp::Wrap(browser));
}
void CEF_CALLBACK request_handler_on_render_process_terminated(
struct _cef_request_handler_t* self,
cef_browser_t* browser,
cef_termination_status_t status,
int error_code,
const cef_string_t* error_string) {
shutdown_checker::AssertNotShutdown();
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
DCHECK(self);
if (!self) {
return;
}
// Verify param: browser; type: refptr_diff
DCHECK(browser);
if (!browser) {
return;
}
// Verify param: error_string; type: string_byref_const
DCHECK(error_string);
if (!error_string) {
return;
}
// Execute
CefRequestHandlerCppToC::Get(self)->OnRenderProcessTerminated(
CefBrowserCToCpp::Wrap(browser), status);
CefBrowserCToCpp::Wrap(browser), status, error_code,
CefString(error_string));
}
void CEF_CALLBACK request_handler_on_document_available_in_main_frame(
@ -404,6 +468,10 @@ CefRequestHandlerCppToC::CefRequestHandlerCppToC() {
GetStruct()->on_select_client_certificate =
request_handler_on_select_client_certificate;
GetStruct()->on_render_view_ready = request_handler_on_render_view_ready;
GetStruct()->on_render_process_unresponsive =
request_handler_on_render_process_unresponsive;
GetStruct()->on_render_process_responsive =
request_handler_on_render_process_responsive;
GetStruct()->on_render_process_terminated =
request_handler_on_render_process_terminated;
GetStruct()->on_document_available_in_main_frame =

View File

@ -0,0 +1,82 @@
// Copyright (c) 2024 The Chromium Embedded Framework Authors. All rights
// reserved. Use of this source code is governed by a BSD-style license that
// can be found in the LICENSE file.
//
// ---------------------------------------------------------------------------
//
// 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=d31cea8b172629a308a7d54f8dd6fccff4cc8823$
//
#include "libcef_dll/cpptoc/unresponsive_process_callback_cpptoc.h"
#include "libcef_dll/shutdown_checker.h"
namespace {
// MEMBER FUNCTIONS - Body may be edited by hand.
void CEF_CALLBACK unresponsive_process_callback_wait(
struct _cef_unresponsive_process_callback_t* self) {
shutdown_checker::AssertNotShutdown();
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
DCHECK(self);
if (!self) {
return;
}
// Execute
CefUnresponsiveProcessCallbackCppToC::Get(self)->Wait();
}
void CEF_CALLBACK unresponsive_process_callback_terminate(
struct _cef_unresponsive_process_callback_t* self) {
shutdown_checker::AssertNotShutdown();
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
DCHECK(self);
if (!self) {
return;
}
// Execute
CefUnresponsiveProcessCallbackCppToC::Get(self)->Terminate();
}
} // namespace
// CONSTRUCTOR - Do not edit by hand.
CefUnresponsiveProcessCallbackCppToC::CefUnresponsiveProcessCallbackCppToC() {
GetStruct()->wait = unresponsive_process_callback_wait;
GetStruct()->terminate = unresponsive_process_callback_terminate;
}
// DESTRUCTOR - Do not edit by hand.
CefUnresponsiveProcessCallbackCppToC::~CefUnresponsiveProcessCallbackCppToC() {
shutdown_checker::AssertNotShutdown();
}
template <>
CefRefPtr<CefUnresponsiveProcessCallback>
CefCppToCRefCounted<CefUnresponsiveProcessCallbackCppToC,
CefUnresponsiveProcessCallback,
cef_unresponsive_process_callback_t>::
UnwrapDerived(CefWrapperType type, cef_unresponsive_process_callback_t* s) {
DCHECK(false) << "Unexpected class type: " << type;
return nullptr;
}
template <>
CefWrapperType
CefCppToCRefCounted<CefUnresponsiveProcessCallbackCppToC,
CefUnresponsiveProcessCallback,
cef_unresponsive_process_callback_t>::kWrapperType =
WT_UNRESPONSIVE_PROCESS_CALLBACK;

View File

@ -0,0 +1,38 @@
// Copyright (c) 2024 The Chromium Embedded Framework Authors. All rights
// reserved. Use of this source code is governed by a BSD-style license that
// can be found in the LICENSE file.
//
// ---------------------------------------------------------------------------
//
// 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=1816748407afd5599d8582de51b3289d1ea24a33$
//
#ifndef CEF_LIBCEF_DLL_CPPTOC_UNRESPONSIVE_PROCESS_CALLBACK_CPPTOC_H_
#define CEF_LIBCEF_DLL_CPPTOC_UNRESPONSIVE_PROCESS_CALLBACK_CPPTOC_H_
#pragma once
#if !defined(BUILDING_CEF_SHARED)
#error This file can be included DLL-side only
#endif
#include "include/capi/cef_unresponsive_process_callback_capi.h"
#include "include/cef_unresponsive_process_callback.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 CefUnresponsiveProcessCallbackCppToC
: public CefCppToCRefCounted<CefUnresponsiveProcessCallbackCppToC,
CefUnresponsiveProcessCallback,
cef_unresponsive_process_callback_t> {
public:
CefUnresponsiveProcessCallbackCppToC();
virtual ~CefUnresponsiveProcessCallbackCppToC();
};
#endif // CEF_LIBCEF_DLL_CPPTOC_UNRESPONSIVE_PROCESS_CALLBACK_CPPTOC_H_

View File

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

View File

@ -9,7 +9,7 @@
// implementations. See the translator.README.txt file in the tools directory
// for more information.
//
// $hash=8b1e4268c2b68437b5022e9baf3f1c56bf036fe7$
// $hash=ec03d4b0c8e59ba8f8eb3060e374b4d76e22669b$
//
#ifndef CEF_LIBCEF_DLL_CTOCPP_BROWSER_HOST_CTOCPP_H_
@ -139,6 +139,7 @@ class CefBrowserHostCToCpp : public CefCToCppRefCounted<CefBrowserHostCToCpp,
bool CanExecuteChromeCommand(int command_id) override;
void ExecuteChromeCommand(int command_id,
cef_window_open_disposition_t disposition) override;
bool IsRenderProcessUnresponsive() override;
};
#endif // CEF_LIBCEF_DLL_CTOCPP_BROWSER_HOST_CTOCPP_H_

View File

@ -9,7 +9,7 @@
// implementations. See the translator.README.txt file in the tools directory
// for more information.
//
// $hash=a93a6c9d3656f1c7fd70795abb89d608e996f834$
// $hash=19b44051658f9e6419dc37d33ed9a70239b5f857$
//
#include "libcef_dll/ctocpp/request_handler_ctocpp.h"
@ -20,6 +20,7 @@
#include "libcef_dll/cpptoc/request_cpptoc.h"
#include "libcef_dll/cpptoc/select_client_certificate_callback_cpptoc.h"
#include "libcef_dll/cpptoc/sslinfo_cpptoc.h"
#include "libcef_dll/cpptoc/unresponsive_process_callback_cpptoc.h"
#include "libcef_dll/cpptoc/x509certificate_cpptoc.h"
#include "libcef_dll/ctocpp/resource_request_handler_ctocpp.h"
#include "libcef_dll/shutdown_checker.h"
@ -340,10 +341,68 @@ void CefRequestHandlerCToCpp::OnRenderViewReady(CefRefPtr<CefBrowser> browser) {
_struct->on_render_view_ready(_struct, CefBrowserCppToC::Wrap(browser));
}
NO_SANITIZE("cfi-icall")
bool CefRequestHandlerCToCpp::OnRenderProcessUnresponsive(
CefRefPtr<CefBrowser> browser,
CefRefPtr<CefUnresponsiveProcessCallback> callback) {
shutdown_checker::AssertNotShutdown();
cef_request_handler_t* _struct = GetStruct();
if (CEF_MEMBER_MISSING(_struct, on_render_process_unresponsive)) {
return false;
}
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
// Verify param: browser; type: refptr_diff
DCHECK(browser.get());
if (!browser.get()) {
return false;
}
// Verify param: callback; type: refptr_diff
DCHECK(callback.get());
if (!callback.get()) {
return false;
}
// Execute
int _retval = _struct->on_render_process_unresponsive(
_struct, CefBrowserCppToC::Wrap(browser),
CefUnresponsiveProcessCallbackCppToC::Wrap(callback));
// Return type: bool
return _retval ? true : false;
}
NO_SANITIZE("cfi-icall")
void CefRequestHandlerCToCpp::OnRenderProcessResponsive(
CefRefPtr<CefBrowser> browser) {
shutdown_checker::AssertNotShutdown();
cef_request_handler_t* _struct = GetStruct();
if (CEF_MEMBER_MISSING(_struct, on_render_process_responsive)) {
return;
}
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
// Verify param: browser; type: refptr_diff
DCHECK(browser.get());
if (!browser.get()) {
return;
}
// Execute
_struct->on_render_process_responsive(_struct,
CefBrowserCppToC::Wrap(browser));
}
NO_SANITIZE("cfi-icall")
void CefRequestHandlerCToCpp::OnRenderProcessTerminated(
CefRefPtr<CefBrowser> browser,
TerminationStatus status) {
TerminationStatus status,
int error_code,
const CefString& error_string) {
shutdown_checker::AssertNotShutdown();
cef_request_handler_t* _struct = GetStruct();
@ -358,10 +417,16 @@ void CefRequestHandlerCToCpp::OnRenderProcessTerminated(
if (!browser.get()) {
return;
}
// Verify param: error_string; type: string_byref_const
DCHECK(!error_string.empty());
if (error_string.empty()) {
return;
}
// Execute
_struct->on_render_process_terminated(
_struct, CefBrowserCppToC::Wrap(browser), status);
_struct->on_render_process_terminated(_struct,
CefBrowserCppToC::Wrap(browser), status,
error_code, error_string.GetStruct());
}
NO_SANITIZE("cfi-icall")

View File

@ -9,7 +9,7 @@
// implementations. See the translator.README.txt file in the tools directory
// for more information.
//
// $hash=272831fa944a45a447a333f81c9e5501a3a7db64$
// $hash=af82af05fec824761f5ff735ff6c9831938deb16$
//
#ifndef CEF_LIBCEF_DLL_CTOCPP_REQUEST_HANDLER_CTOCPP_H_
@ -74,8 +74,14 @@ class CefRequestHandlerCToCpp
const X509CertificateList& certificates,
CefRefPtr<CefSelectClientCertificateCallback> callback) override;
void OnRenderViewReady(CefRefPtr<CefBrowser> browser) override;
bool OnRenderProcessUnresponsive(
CefRefPtr<CefBrowser> browser,
CefRefPtr<CefUnresponsiveProcessCallback> callback) override;
void OnRenderProcessResponsive(CefRefPtr<CefBrowser> browser) override;
void OnRenderProcessTerminated(CefRefPtr<CefBrowser> browser,
TerminationStatus status) override;
TerminationStatus status,
int error_code,
const CefString& error_string) override;
void OnDocumentAvailableInMainFrame(CefRefPtr<CefBrowser> browser) override;
};

View File

@ -0,0 +1,74 @@
// Copyright (c) 2024 The Chromium Embedded Framework Authors. All rights
// reserved. Use of this source code is governed by a BSD-style license that
// can be found in the LICENSE file.
//
// ---------------------------------------------------------------------------
//
// 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=c8f9d6f148a367be5eef1b3512ba023da0f9ac84$
//
#include "libcef_dll/ctocpp/unresponsive_process_callback_ctocpp.h"
#include "libcef_dll/shutdown_checker.h"
// VIRTUAL METHODS - Body may be edited by hand.
NO_SANITIZE("cfi-icall") void CefUnresponsiveProcessCallbackCToCpp::Wait() {
shutdown_checker::AssertNotShutdown();
cef_unresponsive_process_callback_t* _struct = GetStruct();
if (CEF_MEMBER_MISSING(_struct, wait)) {
return;
}
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
// Execute
_struct->wait(_struct);
}
NO_SANITIZE("cfi-icall")
void CefUnresponsiveProcessCallbackCToCpp::Terminate() {
shutdown_checker::AssertNotShutdown();
cef_unresponsive_process_callback_t* _struct = GetStruct();
if (CEF_MEMBER_MISSING(_struct, terminate)) {
return;
}
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
// Execute
_struct->terminate(_struct);
}
// CONSTRUCTOR - Do not edit by hand.
CefUnresponsiveProcessCallbackCToCpp::CefUnresponsiveProcessCallbackCToCpp() {}
// DESTRUCTOR - Do not edit by hand.
CefUnresponsiveProcessCallbackCToCpp::~CefUnresponsiveProcessCallbackCToCpp() {
shutdown_checker::AssertNotShutdown();
}
template <>
cef_unresponsive_process_callback_t*
CefCToCppRefCounted<CefUnresponsiveProcessCallbackCToCpp,
CefUnresponsiveProcessCallback,
cef_unresponsive_process_callback_t>::
UnwrapDerived(CefWrapperType type, CefUnresponsiveProcessCallback* c) {
DCHECK(false) << "Unexpected class type: " << type;
return nullptr;
}
template <>
CefWrapperType
CefCToCppRefCounted<CefUnresponsiveProcessCallbackCToCpp,
CefUnresponsiveProcessCallback,
cef_unresponsive_process_callback_t>::kWrapperType =
WT_UNRESPONSIVE_PROCESS_CALLBACK;

View File

@ -0,0 +1,42 @@
// Copyright (c) 2024 The Chromium Embedded Framework Authors. All rights
// reserved. Use of this source code is governed by a BSD-style license that
// can be found in the LICENSE file.
//
// ---------------------------------------------------------------------------
//
// 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=4c04a490cc0609560e711890eeb286431675bf54$
//
#ifndef CEF_LIBCEF_DLL_CTOCPP_UNRESPONSIVE_PROCESS_CALLBACK_CTOCPP_H_
#define CEF_LIBCEF_DLL_CTOCPP_UNRESPONSIVE_PROCESS_CALLBACK_CTOCPP_H_
#pragma once
#if !defined(WRAPPING_CEF_SHARED)
#error This file can be included wrapper-side only
#endif
#include "include/capi/cef_unresponsive_process_callback_capi.h"
#include "include/cef_unresponsive_process_callback.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 CefUnresponsiveProcessCallbackCToCpp
: public CefCToCppRefCounted<CefUnresponsiveProcessCallbackCToCpp,
CefUnresponsiveProcessCallback,
cef_unresponsive_process_callback_t> {
public:
CefUnresponsiveProcessCallbackCToCpp();
virtual ~CefUnresponsiveProcessCallbackCToCpp();
// CefUnresponsiveProcessCallback methods.
void Wait() override;
void Terminate() override;
};
#endif // CEF_LIBCEF_DLL_CTOCPP_UNRESPONSIVE_PROCESS_CALLBACK_CTOCPP_H_

View File

@ -9,7 +9,7 @@
// implementations. See the translator.README.txt file in the tools directory
// for more information.
//
// $hash=215fc5a9025e8b0cd3d1bc7259ad6e6ac53b2125$
// $hash=716d8a4bb86c9ee9ebe8dfe28ec2c37411507830$
//
#include "include/capi/cef_app_capi.h"
@ -118,6 +118,16 @@ CEF_EXPORT int cef_initialize(const cef_main_args_t* args,
return _retval;
}
CEF_EXPORT int cef_get_exit_code() {
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
// Execute
int _retval = CefGetExitCode();
// Return type: simple
return _retval;
}
CEF_EXPORT void cef_shutdown() {
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING

View File

@ -9,7 +9,7 @@
// implementations. See the translator.README.txt file in the tools directory
// for more information.
//
// $hash=f882e920463e6681b19a06c9d897b09b17e27bd3$
// $hash=fd77a51eeea378bb56d43ba2995a0417d905c247$
//
#include <dlfcn.h>
@ -92,6 +92,7 @@ void* libcef_get_ptr(const char* path, const char* name) {
struct libcef_pointers {
decltype(&cef_execute_process) cef_execute_process;
decltype(&cef_initialize) cef_initialize;
decltype(&cef_get_exit_code) cef_get_exit_code;
decltype(&cef_shutdown) cef_shutdown;
decltype(&cef_do_message_loop_work) cef_do_message_loop_work;
decltype(&cef_run_message_loop) cef_run_message_loop;
@ -337,6 +338,7 @@ struct libcef_pointers {
int libcef_init_pointers(const char* path) {
INIT_ENTRY(cef_execute_process);
INIT_ENTRY(cef_initialize);
INIT_ENTRY(cef_get_exit_code);
INIT_ENTRY(cef_shutdown);
INIT_ENTRY(cef_do_message_loop_work);
INIT_ENTRY(cef_run_message_loop);
@ -590,6 +592,10 @@ int cef_initialize(const cef_main_args_t* args,
windows_sandbox_info);
}
NO_SANITIZE("cfi-icall") int cef_get_exit_code() {
return g_libcef_pointers.cef_get_exit_code();
}
NO_SANITIZE("cfi-icall") void cef_shutdown() {
g_libcef_pointers.cef_shutdown();
}

View File

@ -9,7 +9,7 @@
// implementations. See the translator.README.txt file in the tools directory
// for more information.
//
// $hash=f2b284f21cdb59e621ecddbe2f07392d24d48ddd$
// $hash=23f943f8e59a48f29ba3095642bc05d7f987a2f2$
//
#include "include/capi/cef_app_capi.h"
@ -106,6 +106,16 @@ CEF_GLOBAL bool CefInitialize(const CefMainArgs& args,
return _retval ? true : false;
}
NO_SANITIZE("cfi-icall") CEF_GLOBAL int CefGetExitCode() {
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
// Execute
int _retval = cef_get_exit_code();
// Return type: simple
return _retval;
}
NO_SANITIZE("cfi-icall") CEF_GLOBAL void CefShutdown() {
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING

View File

@ -9,7 +9,7 @@
// implementations. See the translator.README.txt file in the tools directory
// for more information.
//
// $hash=613fb0a830ebbd0ad913f60a482b8ba9d6f01ff4$
// $hash=f250db632dc9f127b3aaff303d6105ca235ff462$
//
#ifndef CEF_LIBCEF_DLL_WRAPPER_TYPES_H_
@ -162,6 +162,7 @@ enum CefWrapperType {
WT_TRANSLATOR_TEST_SCOPED_LIBRARY_CHILD_CHILD,
WT_URLREQUEST,
WT_URLREQUEST_CLIENT,
WT_UNRESPONSIVE_PROCESS_CALLBACK,
WT_V8ACCESSOR,
WT_V8ARRAY_BUFFER_RELEASE_CALLBACK,
WT_V8CONTEXT,

View File

@ -340,6 +340,11 @@ patches = [
# Add BrowserPluginGuest::owner_web_contents() method.
'name': 'chrome_plugins',
},
{
# Expose sad tab error strings.
# https://github.com/chromiumembedded/cef/issues/3661
'name': 'chrome_sad_tab_error',
},
{
# Don't create databases, blob_storage or VideoDecodeStats directories when
# cache_path is empty.

View File

@ -132,7 +132,7 @@ index 768e11b9e5648..b4ba1800def14 100644
]
}
diff --git chrome/browser/ui/browser.cc chrome/browser/ui/browser.cc
index 0791cc8f55a92..d94ac23dc878a 100644
index 0791cc8f55a92..df3fb31c5c787 100644
--- chrome/browser/ui/browser.cc
+++ chrome/browser/ui/browser.cc
@@ -264,6 +264,25 @@
@ -301,7 +301,7 @@ index 0791cc8f55a92..d94ac23dc878a 100644
void Browser::BeforeUnloadFired(WebContents* web_contents,
bool proceed,
bool* proceed_to_fire_unload) {
@@ -1975,6 +2060,10 @@ void Browser::WebContentsCreated(WebContents* source_contents,
@@ -1975,12 +2060,24 @@ void Browser::WebContentsCreated(WebContents* source_contents,
// Make the tab show up in the task manager.
task_manager::WebContentsTags::CreateForTabContents(new_contents);
@ -312,7 +312,35 @@ index 0791cc8f55a92..d94ac23dc878a 100644
}
void Browser::RendererUnresponsive(
@@ -2119,11 +2208,15 @@ void Browser::EnterFullscreenModeForTab(
WebContents* source,
content::RenderWidgetHost* render_widget_host,
base::RepeatingClosure hang_monitor_restarter) {
+#if BUILDFLAG(ENABLE_CEF)
+ if (cef_browser_delegate_ &&
+ cef_browser_delegate_->RendererUnresponsiveEx(source, render_widget_host,
+ hang_monitor_restarter)) {
+ return;
+ }
+#endif
+
// Don't show the page hung dialog when a HTML popup hangs because
// the dialog will take the focus and immediately close the popup.
RenderWidgetHostView* view = render_widget_host->GetView();
@@ -1993,6 +2090,13 @@ void Browser::RendererUnresponsive(
void Browser::RendererResponsive(
WebContents* source,
content::RenderWidgetHost* render_widget_host) {
+#if BUILDFLAG(ENABLE_CEF)
+ if (cef_browser_delegate_ &&
+ cef_browser_delegate_->RendererResponsiveEx(source, render_widget_host)) {
+ return;
+ }
+#endif
+
RenderWidgetHostView* view = render_widget_host->GetView();
if (view && !render_widget_host->GetView()->IsHTMLFormPopup()) {
TabDialogs::FromWebContents(source)->HideHungRendererDialog(
@@ -2119,11 +2223,15 @@ void Browser::EnterFullscreenModeForTab(
const blink::mojom::FullscreenOptions& options) {
exclusive_access_manager_->fullscreen_controller()->EnterFullscreenModeForTab(
requesting_frame, options.display_id);
@ -328,7 +356,7 @@ index 0791cc8f55a92..d94ac23dc878a 100644
}
bool Browser::IsFullscreenForTabOrPending(const WebContents* web_contents) {
@@ -2322,6 +2415,15 @@ void Browser::RequestMediaAccessPermission(
@@ -2322,6 +2430,15 @@ void Browser::RequestMediaAccessPermission(
content::WebContents* web_contents,
const content::MediaStreamRequest& request,
content::MediaResponseCallback callback) {
@ -344,7 +372,7 @@ index 0791cc8f55a92..d94ac23dc878a 100644
const extensions::Extension* extension =
GetExtensionForOrigin(profile_, request.security_origin);
MediaCaptureDevicesDispatcher::GetInstance()->ProcessMediaAccessRequest(
@@ -2858,9 +2960,11 @@ void Browser::RemoveScheduledUpdatesFor(WebContents* contents) {
@@ -2858,9 +2975,11 @@ void Browser::RemoveScheduledUpdatesFor(WebContents* contents) {
// Browser, Getters for UI (private):
StatusBubble* Browser::GetStatusBubble() {
@ -357,7 +385,7 @@ index 0791cc8f55a92..d94ac23dc878a 100644
}
// We hide the status bar for web apps windows as this matches native
@@ -2868,6 +2972,12 @@ StatusBubble* Browser::GetStatusBubble() {
@@ -2868,6 +2987,12 @@ StatusBubble* Browser::GetStatusBubble() {
// mode, as the minimal browser UI includes the status bar.
if (web_app::AppBrowserController::IsWebApp(this) &&
!app_controller()->HasMinimalUiButtons()) {
@ -370,7 +398,7 @@ index 0791cc8f55a92..d94ac23dc878a 100644
return nullptr;
}
@@ -3004,6 +3114,8 @@ void Browser::SetAsDelegate(WebContents* web_contents, bool set_delegate) {
@@ -3004,6 +3129,8 @@ void Browser::SetAsDelegate(WebContents* web_contents, bool set_delegate) {
BookmarkTabHelper::FromWebContents(web_contents)->RemoveObserver(this);
web_contents_collection_.StopObserving(web_contents);
}
@ -379,7 +407,7 @@ index 0791cc8f55a92..d94ac23dc878a 100644
}
void Browser::TabDetachedAtImpl(content::WebContents* contents,
@@ -3158,6 +3270,14 @@ bool Browser::PictureInPictureBrowserSupportsWindowFeature(
@@ -3158,6 +3285,14 @@ bool Browser::PictureInPictureBrowserSupportsWindowFeature(
bool Browser::SupportsWindowFeatureImpl(WindowFeature feature,
bool check_can_support) const {

View File

@ -0,0 +1,29 @@
diff --git chrome/browser/ui/views/sad_tab_view.cc chrome/browser/ui/views/sad_tab_view.cc
index 26d1d804f74e7..87f411df5a49c 100644
--- chrome/browser/ui/views/sad_tab_view.cc
+++ chrome/browser/ui/views/sad_tab_view.cc
@@ -680,6 +680,11 @@ void SadTabView::OnBoundsChanged(const gfx::Rect& previous_bounds) {
title_->SizeToFit(max_width);
}
+// static
+std::u16string SadTabView::ErrorToString(int error_code) {
+ return ::ErrorToString(error_code);
+}
+
SadTab* SadTab::Create(content::WebContents* web_contents, SadTabKind kind) {
return new SadTabView(web_contents, kind);
}
diff --git chrome/browser/ui/views/sad_tab_view.h chrome/browser/ui/views/sad_tab_view.h
index d6cb0e1a28eb2..59aca7bbb17c3 100644
--- chrome/browser/ui/views/sad_tab_view.h
+++ chrome/browser/ui/views/sad_tab_view.h
@@ -56,6 +56,8 @@ class SadTabView : public SadTab, public views::View {
// Overridden from views::View:
void OnBoundsChanged(const gfx::Rect& previous_bounds) override;
+ static std::u16string ErrorToString(int error_code);
+
protected:
// Overridden from views::View:
void OnPaint(gfx::Canvas* canvas) override;

View File

@ -0,0 +1,154 @@
// Copyright (c) 2024 The Chromium Embedded Framework Authors. All rights
// reserved. Use of this source code is governed by a BSD-style license that
// can be found in the LICENSE file.
#include "tests/cefclient/browser/base_client_handler.h"
namespace client {
BaseClientHandler::BaseClientHandler() {
resource_manager_ = new CefResourceManager();
test_runner::SetupResourceManager(resource_manager_, &string_resource_map_);
}
// static
CefRefPtr<BaseClientHandler> BaseClientHandler::GetForBrowser(
CefRefPtr<CefBrowser> browser) {
return static_cast<BaseClientHandler*>(browser->GetHost()->GetClient().get());
}
bool BaseClientHandler::OnProcessMessageReceived(
CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
CefProcessId source_process,
CefRefPtr<CefProcessMessage> message) {
CEF_REQUIRE_UI_THREAD();
return message_router_->OnProcessMessageReceived(browser, frame,
source_process, message);
}
void BaseClientHandler::OnAfterCreated(CefRefPtr<CefBrowser> browser) {
CEF_REQUIRE_UI_THREAD();
browser_count_++;
if (!message_router_) {
// Create the browser-side router for query handling.
CefMessageRouterConfig config;
message_router_ = CefMessageRouterBrowserSide::Create(config);
// Register handlers with the router.
test_runner::CreateMessageHandlers(message_handler_set_);
for (auto* message_handler : message_handler_set_) {
message_router_->AddHandler(message_handler, false);
}
}
}
void BaseClientHandler::OnBeforeClose(CefRefPtr<CefBrowser> browser) {
CEF_REQUIRE_UI_THREAD();
if (--browser_count_ == 0) {
// Remove and delete message router handlers.
for (auto* message_handler : message_handler_set_) {
message_router_->RemoveHandler(message_handler);
delete message_handler;
}
message_handler_set_.clear();
message_router_ = nullptr;
}
}
bool BaseClientHandler::OnBeforeBrowse(CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
CefRefPtr<CefRequest> request,
bool user_gesture,
bool is_redirect) {
CEF_REQUIRE_UI_THREAD();
message_router_->OnBeforeBrowse(browser, frame);
return false;
}
bool BaseClientHandler::OnRenderProcessUnresponsive(
CefRefPtr<CefBrowser> browser,
CefRefPtr<CefUnresponsiveProcessCallback> callback) {
switch (hang_action_) {
case HangAction::kDefault:
return false;
case HangAction::kWait:
callback->Wait();
break;
case HangAction::kTerminate:
callback->Terminate();
break;
}
return true;
}
void BaseClientHandler::OnRenderProcessTerminated(
CefRefPtr<CefBrowser> browser,
TerminationStatus status,
int error_code,
const CefString& error_string) {
CEF_REQUIRE_UI_THREAD();
message_router_->OnRenderProcessTerminated(browser);
}
cef_return_value_t BaseClientHandler::OnBeforeResourceLoad(
CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
CefRefPtr<CefRequest> request,
CefRefPtr<CefCallback> callback) {
CEF_REQUIRE_IO_THREAD();
return resource_manager_->OnBeforeResourceLoad(browser, frame, request,
callback);
}
CefRefPtr<CefResourceHandler> BaseClientHandler::GetResourceHandler(
CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
CefRefPtr<CefRequest> request) {
CEF_REQUIRE_IO_THREAD();
return resource_manager_->GetResourceHandler(browser, frame, request);
}
CefRefPtr<CefResponseFilter> BaseClientHandler::GetResourceResponseFilter(
CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
CefRefPtr<CefRequest> request,
CefRefPtr<CefResponse> response) {
CEF_REQUIRE_IO_THREAD();
return test_runner::GetResourceResponseFilter(browser, frame, request,
response);
}
int BaseClientHandler::GetBrowserCount() const {
CEF_REQUIRE_UI_THREAD();
return browser_count_;
}
void BaseClientHandler::SetStringResource(const std::string& page,
const std::string& data) {
if (!CefCurrentlyOn(TID_IO)) {
CefPostTask(TID_IO, base::BindOnce(&BaseClientHandler::SetStringResource,
this, page, data));
return;
}
string_resource_map_[page] = data;
}
void BaseClientHandler::SetHangAction(HangAction action) {
CEF_REQUIRE_UI_THREAD();
hang_action_ = action;
}
BaseClientHandler::HangAction BaseClientHandler::GetHangAction() const {
CEF_REQUIRE_UI_THREAD();
return hang_action_;
}
} // namespace client

View File

@ -0,0 +1,125 @@
// Copyright (c) 2024 The Chromium Embedded Framework Authors. All rights
// reserved. Use of this source code is governed by a BSD-style license that
// can be found in the LICENSE file.
#ifndef CEF_TESTS_CEFCLIENT_BROWSER_BASE_CLIENT_HANDLER_H_
#define CEF_TESTS_CEFCLIENT_BROWSER_BASE_CLIENT_HANDLER_H_
#pragma once
#include "include/cef_client.h"
#include "include/wrapper/cef_message_router.h"
#include "tests/cefclient/browser/test_runner.h"
namespace client {
// Abstract base class for client handlers.
class BaseClientHandler : public CefClient,
public CefLifeSpanHandler,
public CefRequestHandler,
public CefResourceRequestHandler {
public:
BaseClientHandler();
// Returns the BaseClientHandler associated with |browser|.
static CefRefPtr<BaseClientHandler> GetForBrowser(
CefRefPtr<CefBrowser> browser);
// CefClient methods
CefRefPtr<CefLifeSpanHandler> GetLifeSpanHandler() override { return this; }
CefRefPtr<CefRequestHandler> GetRequestHandler() override { return this; }
bool OnProcessMessageReceived(CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
CefProcessId source_process,
CefRefPtr<CefProcessMessage> message) override;
// CefLifeSpanHandler methods
void OnAfterCreated(CefRefPtr<CefBrowser> browser) override;
void OnBeforeClose(CefRefPtr<CefBrowser> browser) override;
// CefRequestHandler methods
bool OnBeforeBrowse(CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
CefRefPtr<CefRequest> request,
bool user_gesture,
bool is_redirect) override;
CefRefPtr<CefResourceRequestHandler> GetResourceRequestHandler(
CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
CefRefPtr<CefRequest> request,
bool is_navigation,
bool is_download,
const CefString& request_initiator,
bool& disable_default_handling) override {
return this;
}
bool OnRenderProcessUnresponsive(
CefRefPtr<CefBrowser> browser,
CefRefPtr<CefUnresponsiveProcessCallback> callback) override;
void OnRenderProcessTerminated(CefRefPtr<CefBrowser> browser,
TerminationStatus status,
int error_code,
const CefString& error_string) override;
// CefResourceRequestHandler methods
cef_return_value_t OnBeforeResourceLoad(
CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
CefRefPtr<CefRequest> request,
CefRefPtr<CefCallback> callback) override;
CefRefPtr<CefResourceHandler> GetResourceHandler(
CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
CefRefPtr<CefRequest> request) override;
CefRefPtr<CefResponseFilter> GetResourceResponseFilter(
CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
CefRefPtr<CefRequest> request,
CefRefPtr<CefResponse> response) override;
// Returns the number of browsers currently using this handler. Can only be
// called on the CEF UI thread.
int GetBrowserCount() const;
// Set a string resource for loading via StringResourceProvider.
void SetStringResource(const std::string& page, const std::string& data);
// Action to be taken when the render process becomes unresponsive.
enum class HangAction {
kDefault,
kWait,
kTerminate,
};
void SetHangAction(HangAction action);
HangAction GetHangAction() const;
protected:
CefRefPtr<CefResourceManager> GetResourceManager() const {
return resource_manager_;
}
private:
// The current number of browsers using this handler.
int browser_count_ = 0;
// Handles the browser side of query routing. The renderer side is handled
// in client_renderer.cc.
CefRefPtr<CefMessageRouterBrowserSide> message_router_;
// Set of Handlers registered with the message router.
test_runner::MessageHandlerSet message_handler_set_;
// Manages the registration and delivery of resources.
CefRefPtr<CefResourceManager> resource_manager_;
// Used to manage string resources in combination with StringResourceProvider.
// Only accessed on the IO thread.
test_runner::StringResourceMap string_resource_map_;
HangAction hang_action_ = HangAction::kDefault;
DISALLOW_COPY_AND_ASSIGN(BaseClientHandler);
};
} // namespace client
#endif // CEF_TESTS_CEFCLIENT_BROWSER_BASE_CLIENT_HANDLER_H_

View File

@ -168,19 +168,22 @@ std::string GetContentStatusString(cef_ssl_content_status_t status) {
// Load a data: URI containing the error message.
void LoadErrorPage(CefRefPtr<CefFrame> frame,
const std::string& title,
const std::string& failed_url,
cef_errorcode_t error_code,
const std::string& error_string,
const std::string& other_info) {
std::stringstream ss;
ss << "<html><head><title>Page failed to load</title></head>"
"<body bgcolor=\"white\">"
"<h3>Page failed to load.</h3>"
"URL: <a href=\""
<< failed_url << "\">" << failed_url
<< "</a><br/>Error: " << test_runner::GetErrorString(error_code) << " ("
<< error_code << ")";
if (MainContext::Get()->UseChromeRuntime()) {
// Use default error pages with Chrome runtime.
return;
}
if (!other_info.empty()) {
std::stringstream ss;
ss << "<html><head><title>" << title
<< "</title></head><body bgcolor=\"white\"><h3>" << title
<< "</h3>URL: <a href=\"" << failed_url << "\">" << failed_url
<< "</a><br/>Error: " << error_string;
if (!other_info.empty() && other_info != error_string) {
ss << "<br/>" << other_info;
}
@ -463,9 +466,6 @@ ClientHandler::ClientHandler(Delegate* delegate,
console_log_file_(MainContext::Get()->GetConsoleLogPath()) {
DCHECK(!console_log_file_.empty());
resource_manager_ = new CefResourceManager();
test_runner::SetupResourceManager(resource_manager_, &string_resource_map_);
// Read command line settings.
CefRefPtr<CefCommandLine> command_line =
CefCommandLine::GetGlobalCommandLine();
@ -538,8 +538,8 @@ bool ClientHandler::OnProcessMessageReceived(
const auto finish_time = bv_utils::Now();
if (message_router_->OnProcessMessageReceived(browser, frame, source_process,
message)) {
if (BaseClientHandler::OnProcessMessageReceived(browser, frame,
source_process, message)) {
return true;
}
@ -973,21 +973,7 @@ void ClientHandler::OnBeforeDevToolsPopup(
void ClientHandler::OnAfterCreated(CefRefPtr<CefBrowser> browser) {
CEF_REQUIRE_UI_THREAD();
browser_count_++;
if (!message_router_) {
// Create the browser-side router for query handling.
CefMessageRouterConfig config;
message_router_ = CefMessageRouterBrowserSide::Create(config);
// Register handlers with the router.
test_runner::CreateMessageHandlers(message_handler_set_);
MessageHandlerSet::const_iterator it = message_handler_set_.begin();
for (; it != message_handler_set_.end(); ++it) {
message_router_->AddHandler(*(it), false);
}
}
BaseClientHandler::OnAfterCreated(browser);
// Set offline mode if requested via the command-line flag.
if (offline_) {
@ -1002,8 +988,8 @@ void ClientHandler::OnAfterCreated(CefRefPtr<CefBrowser> browser) {
CefRefPtr<CefExtension> extension = browser->GetHost()->GetExtension();
if (extension_util::IsInternalExtension(extension->GetPath())) {
// Register the internal handler for extension resources.
extension_util::AddInternalExtensionToResourceManager(extension,
resource_manager_);
extension_util::AddInternalExtensionToResourceManager(
extension, GetResourceManager());
}
}
@ -1022,18 +1008,7 @@ bool ClientHandler::DoClose(CefRefPtr<CefBrowser> browser) {
void ClientHandler::OnBeforeClose(CefRefPtr<CefBrowser> browser) {
CEF_REQUIRE_UI_THREAD();
if (--browser_count_ == 0) {
// Remove and delete message router handlers.
MessageHandlerSet::const_iterator it = message_handler_set_.begin();
for (; it != message_handler_set_.end(); ++it) {
message_router_->RemoveHandler(*(it));
delete *(it);
}
message_handler_set_.clear();
message_router_ = nullptr;
}
BaseClientHandler::OnBeforeClose(browser);
NotifyBrowserClosed(browser);
}
@ -1072,7 +1047,8 @@ void ClientHandler::OnLoadError(CefRefPtr<CefBrowser> browser,
}
// Load the error page.
LoadErrorPage(frame, failedUrl, errorCode, errorText);
LoadErrorPage(frame, "Page failed to load", failedUrl,
test_runner::GetErrorString(errorCode), errorText);
}
bool ClientHandler::OnRequestMediaAccessPermission(
@ -1086,17 +1062,6 @@ bool ClientHandler::OnRequestMediaAccessPermission(
return true;
}
bool ClientHandler::OnBeforeBrowse(CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
CefRefPtr<CefRequest> request,
bool user_gesture,
bool is_redirect) {
CEF_REQUIRE_UI_THREAD();
message_router_->OnBeforeBrowse(browser, frame);
return false;
}
bool ClientHandler::OnOpenURLFromTab(
CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
@ -1176,7 +1141,8 @@ bool ClientHandler::OnCertificateError(CefRefPtr<CefBrowser> browser,
CefRefPtr<CefX509Certificate> cert = ssl_info->GetX509Certificate();
if (cert.get()) {
// Load the error page.
LoadErrorPage(browser->GetMainFrame(), request_url, cert_error,
LoadErrorPage(browser->GetMainFrame(), "SSL certificate error", request_url,
test_runner::GetErrorString(cert_error),
GetCertificateInformation(cert, ssl_info->GetCertStatus()));
}
@ -1220,10 +1186,12 @@ bool ClientHandler::OnSelectClientCertificate(
}
void ClientHandler::OnRenderProcessTerminated(CefRefPtr<CefBrowser> browser,
TerminationStatus status) {
TerminationStatus status,
int error_code,
const CefString& error_string) {
CEF_REQUIRE_UI_THREAD();
message_router_->OnRenderProcessTerminated(browser);
BaseClientHandler::OnRenderProcessTerminated(browser, status, error_code,
error_string);
// Don't reload if there's no start URL, or if the crash URL was specified.
if (startup_url_.empty() || startup_url_ == "chrome://crash") {
@ -1245,6 +1213,10 @@ void ClientHandler::OnRenderProcessTerminated(CefRefPtr<CefBrowser> browser,
// Don't reload the URL that just resulted in termination.
if (url.find(start_url) == 0) {
LoadErrorPage(frame, "Render process terminated", frame->GetURL(),
test_runner::GetErrorString(status) + " (" +
error_string.ToString() + ")",
std::string());
return;
}
@ -1262,37 +1234,6 @@ void ClientHandler::OnDocumentAvailableInMainFrame(
}
}
cef_return_value_t ClientHandler::OnBeforeResourceLoad(
CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
CefRefPtr<CefRequest> request,
CefRefPtr<CefCallback> callback) {
CEF_REQUIRE_IO_THREAD();
return resource_manager_->OnBeforeResourceLoad(browser, frame, request,
callback);
}
CefRefPtr<CefResourceHandler> ClientHandler::GetResourceHandler(
CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
CefRefPtr<CefRequest> request) {
CEF_REQUIRE_IO_THREAD();
return resource_manager_->GetResourceHandler(browser, frame, request);
}
CefRefPtr<CefResponseFilter> ClientHandler::GetResourceResponseFilter(
CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
CefRefPtr<CefRequest> request,
CefRefPtr<CefResponse> response) {
CEF_REQUIRE_IO_THREAD();
return test_runner::GetResourceResponseFilter(browser, frame, request,
response);
}
void ClientHandler::OnProtocolExecution(CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
CefRefPtr<CefRequest> request,
@ -1307,11 +1248,6 @@ void ClientHandler::OnProtocolExecution(CefRefPtr<CefBrowser> browser,
}
}
int ClientHandler::GetBrowserCount() const {
CEF_REQUIRE_UI_THREAD();
return browser_count_;
}
void ClientHandler::ShowDevTools(CefRefPtr<CefBrowser> browser,
const CefPoint& inspect_element_at) {
if (!CefCurrentlyOn(TID_UI)) {
@ -1404,17 +1340,6 @@ void ClientHandler::ShowSSLInformation(CefRefPtr<CefBrowser> browser) {
std::move(config));
}
void ClientHandler::SetStringResource(const std::string& page,
const std::string& data) {
if (!CefCurrentlyOn(TID_IO)) {
CefPostTask(TID_IO, base::BindOnce(&ClientHandler::SetStringResource, this,
page, data));
return;
}
string_resource_map_[page] = data;
}
bool ClientHandler::CreatePopupWindow(CefRefPtr<CefBrowser> browser,
bool is_devtools,
const CefPopupFeatures& popupFeatures,

View File

@ -11,8 +11,7 @@
#include "include/cef_client.h"
#include "include/wrapper/cef_helpers.h"
#include "include/wrapper/cef_message_router.h"
#include "include/wrapper/cef_resource_manager.h"
#include "tests/cefclient/browser/base_client_handler.h"
#include "tests/cefclient/browser/client_types.h"
#include "tests/cefclient/browser/test_runner.h"
@ -27,7 +26,7 @@ class ClientDownloadImageCallback;
// Client handler abstract base class. Provides common functionality shared by
// all concrete client handler implementations.
class ClientHandler : public CefClient,
class ClientHandler : public BaseClientHandler,
public CefCommandHandler,
public CefContextMenuHandler,
public CefDisplayHandler,
@ -35,11 +34,8 @@ class ClientHandler : public CefClient,
public CefDragHandler,
public CefFocusHandler,
public CefKeyboardHandler,
public CefLifeSpanHandler,
public CefLoadHandler,
public CefPermissionHandler,
public CefRequestHandler,
public CefResourceRequestHandler {
public CefPermissionHandler {
public:
// Implement this interface to receive notification of ClientHandler
// events. The methods of this class will be called on the main thread unless
@ -89,8 +85,6 @@ class ClientHandler : public CefClient,
virtual ~Delegate() = default;
};
typedef std::set<CefMessageRouterBrowserSide::Handler*> MessageHandlerSet;
// Constructor may be called on any thread.
// |delegate| must outlive this object or DetachDelegate() must be called.
ClientHandler(Delegate* delegate,
@ -112,9 +106,7 @@ class ClientHandler : public CefClient,
CefRefPtr<CefDragHandler> GetDragHandler() override { return this; }
CefRefPtr<CefFocusHandler> GetFocusHandler() override { return this; }
CefRefPtr<CefKeyboardHandler> GetKeyboardHandler() override { return this; }
CefRefPtr<CefLifeSpanHandler> GetLifeSpanHandler() override { return this; }
CefRefPtr<CefLoadHandler> GetLoadHandler() override { return this; }
CefRefPtr<CefRequestHandler> GetRequestHandler() override { return this; }
CefRefPtr<CefPermissionHandler> GetPermissionHandler() override {
return this;
}
@ -254,11 +246,6 @@ class ClientHandler : public CefClient,
CefRefPtr<CefMediaAccessCallback> callback) override;
// CefRequestHandler methods
bool OnBeforeBrowse(CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
CefRefPtr<CefRequest> request,
bool user_gesture,
bool is_redirect) override;
bool OnOpenURLFromTab(
CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
@ -294,33 +281,17 @@ class ClientHandler : public CefClient,
const X509CertificateList& certificates,
CefRefPtr<CefSelectClientCertificateCallback> callback) override;
void OnRenderProcessTerminated(CefRefPtr<CefBrowser> browser,
TerminationStatus status) override;
TerminationStatus status,
int error_code,
const CefString& error_string) override;
void OnDocumentAvailableInMainFrame(CefRefPtr<CefBrowser> browser) override;
// CefResourceRequestHandler methods
cef_return_value_t OnBeforeResourceLoad(
CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
CefRefPtr<CefRequest> request,
CefRefPtr<CefCallback> callback) override;
CefRefPtr<CefResourceHandler> GetResourceHandler(
CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
CefRefPtr<CefRequest> request) override;
CefRefPtr<CefResponseFilter> GetResourceResponseFilter(
CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
CefRefPtr<CefRequest> request,
CefRefPtr<CefResponse> response) override;
void OnProtocolExecution(CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
CefRefPtr<CefRequest> request,
bool& allow_os_execution) override;
// Returns the number of browsers currently using this handler. Can only be
// called on the CEF UI thread.
int GetBrowserCount() const;
// Show a new DevTools popup window.
void ShowDevTools(CefRefPtr<CefBrowser> browser,
const CefPoint& inspect_element_at);
@ -334,9 +305,6 @@ class ClientHandler : public CefClient,
// Show SSL information for the current site.
void ShowSSLInformation(CefRefPtr<CefBrowser> browser);
// Set a string resource for loading via StringResourceProvider.
void SetStringResource(const std::string& page, const std::string& data);
// Returns the Delegate.
Delegate* delegate() const { return delegate_; }
@ -416,17 +384,6 @@ class ClientHandler : public CefClient,
CefRefPtr<ClientPrintHandlerGtk> print_handler_;
#endif
// Handles the browser side of query routing. The renderer side is handled
// in client_renderer.cc.
CefRefPtr<CefMessageRouterBrowserSide> message_router_;
// Manages the registration and delivery of resources.
CefRefPtr<CefResourceManager> resource_manager_;
// Used to manage string resources in combination with StringResourceProvider.
// Only accessed on the IO thread.
test_runner::StringResourceMap string_resource_map_;
// MAIN THREAD MEMBERS
// The following members will only be accessed on the main thread. This will
// be the same as the CEF UI thread except when using multi-threaded message
@ -444,9 +401,6 @@ class ClientHandler : public CefClient,
int radio_item = 0;
} test_menu_state_;
// The current number of browsers using this handler.
int browser_count_ = 0;
// Console logging state.
const std::string console_log_file_;
@ -456,9 +410,6 @@ class ClientHandler : public CefClient,
// True for the initial navigation after browser creation.
bool initial_navigation_ = true;
// Set of Handlers registered with the message router.
MessageHandlerSet message_handler_set_;
DISALLOW_COPY_AND_ASSIGN(ClientHandler);
};

View File

@ -1,60 +0,0 @@
// Copyright (c) 2023 The Chromium Embedded Framework Authors. All rights
// reserved. Use of this source code is governed by a BSD-style license that
// can be found in the LICENSE file.
#include "tests/cefclient/browser/default_client_handler.h"
#include "tests/cefclient/browser/test_runner.h"
namespace client {
DefaultClientHandler::DefaultClientHandler() {
resource_manager_ = new CefResourceManager();
test_runner::SetupResourceManager(resource_manager_, nullptr);
}
CefRefPtr<CefResourceRequestHandler>
DefaultClientHandler::GetResourceRequestHandler(
CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
CefRefPtr<CefRequest> request,
bool is_navigation,
bool is_download,
const CefString& request_initiator,
bool& disable_default_handling) {
CEF_REQUIRE_IO_THREAD();
return this;
}
cef_return_value_t DefaultClientHandler::OnBeforeResourceLoad(
CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
CefRefPtr<CefRequest> request,
CefRefPtr<CefCallback> callback) {
CEF_REQUIRE_IO_THREAD();
return resource_manager_->OnBeforeResourceLoad(browser, frame, request,
callback);
}
CefRefPtr<CefResourceHandler> DefaultClientHandler::GetResourceHandler(
CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
CefRefPtr<CefRequest> request) {
CEF_REQUIRE_IO_THREAD();
return resource_manager_->GetResourceHandler(browser, frame, request);
}
CefRefPtr<CefResponseFilter> DefaultClientHandler::GetResourceResponseFilter(
CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
CefRefPtr<CefRequest> request,
CefRefPtr<CefResponse> response) {
CEF_REQUIRE_IO_THREAD();
return test_runner::GetResourceResponseFilter(browser, frame, request,
response);
}
} // namespace client

View File

@ -6,52 +6,17 @@
#define CEF_TESTS_CEFCLIENT_BROWSER_DEFAULT_CLIENT_HANDLER_H_
#pragma once
#include "include/cef_client.h"
#include "include/wrapper/cef_resource_manager.h"
#include "tests/cefclient/browser/base_client_handler.h"
namespace client {
// Default client handler for unmanaged browser windows. Used with the Chrome
// runtime only.
class DefaultClientHandler : public CefClient,
public CefRequestHandler,
public CefResourceRequestHandler {
class DefaultClientHandler : public BaseClientHandler {
public:
DefaultClientHandler();
// CefClient methods
CefRefPtr<CefRequestHandler> GetRequestHandler() override { return this; }
// CefRequestHandler methods
CefRefPtr<CefResourceRequestHandler> GetResourceRequestHandler(
CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
CefRefPtr<CefRequest> request,
bool is_navigation,
bool is_download,
const CefString& request_initiator,
bool& disable_default_handling) override;
// CefResourceRequestHandler methods
cef_return_value_t OnBeforeResourceLoad(
CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
CefRefPtr<CefRequest> request,
CefRefPtr<CefCallback> callback) override;
CefRefPtr<CefResourceHandler> GetResourceHandler(
CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
CefRefPtr<CefRequest> request) override;
CefRefPtr<CefResponseFilter> GetResourceResponseFilter(
CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
CefRefPtr<CefRequest> request,
CefRefPtr<CefResponse> response) override;
DefaultClientHandler() = default;
private:
// Manages the registration and delivery of resources.
CefRefPtr<CefResourceManager> resource_manager_;
IMPLEMENT_REFCOUNTING(DefaultClientHandler);
DISALLOW_COPY_AND_ASSIGN(DefaultClientHandler);
};

View File

@ -0,0 +1,81 @@
// Copyright (c) 2024 The Chromium Embedded Framework Authors. All rights
// reserved. Use of this source code is governed by a BSD-style license that
// can be found in the LICENSE file.
#include "tests/cefclient/browser/hang_test.h"
#include <string>
#include "tests/cefclient/browser/base_client_handler.h"
#include "tests/cefclient/browser/test_runner.h"
namespace client::hang_test {
namespace {
const char kTestUrlPath[] = "/hang";
const char kTestMessageName[] = "HangTest";
// Handle messages in the browser process.
class Handler : public CefMessageRouterBrowserSide::Handler {
public:
Handler() = default;
// Called due to cefQuery execution in hang.html.
bool OnQuery(CefRefPtr<CefBrowser> browser,
CefRefPtr<CefFrame> frame,
int64_t query_id,
const CefString& request,
bool persistent,
CefRefPtr<Callback> callback) override {
// Only handle messages from the test URL.
const std::string& url = frame->GetURL();
if (!test_runner::IsTestURL(url, kTestUrlPath)) {
return false;
}
if (auto client_handler = BaseClientHandler::GetForBrowser(browser)) {
using HangAction = BaseClientHandler::HangAction;
const std::string& message_name = request;
if (message_name.find(kTestMessageName) == 0) {
const std::string& command =
message_name.substr(sizeof(kTestMessageName));
if (command == "getcommand") {
std::string current;
switch (client_handler->GetHangAction()) {
case HangAction::kDefault:
current = "default";
break;
case HangAction::kWait:
current = "wait";
break;
case HangAction::kTerminate:
current = "terminate";
break;
}
callback->Success(current);
} else if (command == "setdefault") {
client_handler->SetHangAction(HangAction::kDefault);
} else if (command == "setwait") {
client_handler->SetHangAction(HangAction::kWait);
} else if (command == "setterminate") {
client_handler->SetHangAction(HangAction::kTerminate);
} else {
LOG(ERROR) << "Unrecognized command: " << command;
}
return true;
}
}
return false;
}
};
} // namespace
void CreateMessageHandlers(test_runner::MessageHandlerSet& handlers) {
handlers.insert(new Handler());
}
} // namespace client::hang_test

View File

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

View File

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

View File

@ -25,6 +25,7 @@ int GetResourceId(const char* resource_name) {
IDS_EXTENSIONS_SET_PAGE_COLOR_POPUP_HTML},
{"extensions/set_page_color/popup.js",
IDS_EXTENSIONS_SET_PAGE_COLOR_POPUP_JS},
{"hang.html", IDS_HANG_HTML},
{"ipc_performance.html", IDS_IPC_PERFORMANCE_HTML},
{"localstorage.html", IDS_LOCALSTORAGE_HTML},
{"logo.png", IDS_LOGO_PNG},

View File

@ -8,6 +8,7 @@
#include <map>
#include <set>
#include <sstream>
#include <string>
#include "include/base/cef_callback.h"
#include "include/cef_parser.h"
@ -16,10 +17,11 @@
#include "include/views/cef_browser_view.h"
#include "include/wrapper/cef_closure_task.h"
#include "include/wrapper/cef_stream_resource_handler.h"
#include "tests/cefclient/browser/base_client_handler.h"
#include "tests/cefclient/browser/binary_transfer_test.h"
#include "tests/cefclient/browser/binding_test.h"
#include "tests/cefclient/browser/client_handler.h"
#include "tests/cefclient/browser/dialog_test.h"
#include "tests/cefclient/browser/hang_test.h"
#include "tests/cefclient/browser/main_context.h"
#include "tests/cefclient/browser/media_router_test.h"
#include "tests/cefclient/browser/preferences_test.h"
@ -50,9 +52,7 @@ const char kTestGetTextPage[] = "get_text.html";
void LoadStringResourcePage(CefRefPtr<CefBrowser> browser,
const std::string& page,
const std::string& data) {
CefRefPtr<CefClient> client = browser->GetHost()->GetClient();
ClientHandler* client_handler = static_cast<ClientHandler*>(client.get());
client_handler->SetStringResource(page, data);
BaseClientHandler::GetForBrowser(browser)->SetStringResource(page, data);
browser->GetMainFrame()->LoadURL(kTestOrigin + page);
}
@ -752,10 +752,29 @@ std::string GetErrorString(cef_errorcode_t code) {
CASE(ERR_CACHE_MISS);
CASE(ERR_INSECURE_RESPONSE);
default:
return "UNKNOWN";
return std::to_string(static_cast<int>(code));
}
}
std::string GetErrorString(cef_termination_status_t status) {
switch (status) {
case TS_ABNORMAL_TERMINATION:
return "ABNORMAL_TERMINATION";
case TS_PROCESS_WAS_KILLED:
return "PROCESS_WAS_KILLED";
case TS_PROCESS_CRASHED:
return "PROCESS_CRASHED";
case TS_PROCESS_OOM:
return "PROCESS_OOM";
case TS_LAUNCH_FAILED:
return "LAUNCH_FAILED";
case TS_INTEGRITY_FAILURE:
return "INTEGRITY_FAILURE";
}
NOTREACHED();
return std::string();
}
void SetupResourceManager(CefRefPtr<CefResourceManager> resource_manager,
StringResourceMap* string_resource_map) {
if (!CefCurrentlyOn(TID_IO)) {
@ -851,6 +870,9 @@ void CreateMessageHandlers(MessageHandlerSet& handlers) {
// Create the dialog test handlers.
dialog_test::CreateMessageHandlers(handlers);
// Create the hang test handlers.
hang_test::CreateMessageHandlers(handlers);
// Create the media router test handlers.
media_router_test::CreateMessageHandlers(handlers);

View File

@ -33,8 +33,9 @@ std::string GetDataURI(const std::string& data, const std::string& mime_type);
// Returns the string representation of the specified error code.
std::string GetErrorString(cef_errorcode_t code);
std::string GetErrorString(cef_termination_status_t status);
typedef std::map<std::string, std::string> StringResourceMap;
using StringResourceMap = std::map<std::string, std::string>;
// Set up the resource manager for tests.
void SetupResourceManager(CefRefPtr<CefResourceManager> resource_manager,
@ -52,7 +53,7 @@ bool IsTestURL(const std::string& url, const std::string& path);
// Create all CefMessageRouterBrowserSide::Handler objects. They will be
// deleted when the ClientHandler is destroyed.
typedef std::set<CefMessageRouterBrowserSide::Handler*> MessageHandlerSet;
using MessageHandlerSet = std::set<CefMessageRouterBrowserSide::Handler*>;
void CreateMessageHandlers(MessageHandlerSet& handlers);
// Register scheme handlers for tests.

View File

@ -110,7 +110,7 @@ int RunMain(int argc, char* argv[]) {
// fails or if early exit is desired (for example, due to process singleton
// relaunch behavior).
if (!context->Initialize(main_args, settings, app, nullptr)) {
return 1;
return CefGetExitCode();
}
// Force Gtk to use Xwayland (in case a Wayland compositor is being used).

View File

@ -583,7 +583,7 @@ int RunMain(int argc, char* argv[]) {
// fails or if early exit is desired (for example, due to process singleton
// relaunch behavior).
if (!context->Initialize(main_args, settings, app, nullptr)) {
return 1;
return CefGetExitCode();
}
// Register scheme handlers.

View File

@ -99,7 +99,7 @@ int RunMain(HINSTANCE hInstance, int nCmdShow) {
// fails or if early exit is desired (for example, due to process singleton
// relaunch behavior).
if (!context->Initialize(main_args, settings, app, sandbox_info)) {
return 1;
return CefGetExitCode();
}
// Register scheme handlers.

View File

@ -1,6 +1,25 @@
<html>
<head>
<title>Dialog Test</title>
<style>
#loading {
display: inline-block;
width: 10px;
height: 10px;
border: 3px solid rgba(0,0,0,.3);
border-radius: 50%;
border-top-color: #000;
animation: spin 1s ease-in-out infinite;
-webkit-animation: spin 1s ease-in-out infinite;
}
@keyframes spin {
to { -webkit-transform: rotate(360deg); }
}
@-webkit-keyframes spin {
to { -webkit-transform: rotate(360deg); }
}
</style>
<script>
function show_alert() {
alert("I am an alert box!");
@ -74,7 +93,19 @@ Click a button to show the associated dialog type.
<br/><input type="button" onclick="show_file_dialog('fom', 'FileOpenMultiple');" value="Show File Open (multiple types/files)" disabled="true"> <span id="fom"></span>
<br/><input type="button" onclick="show_file_dialog('fof', 'FileOpenFolder');" value="Show File Open Folder" disabled="true"> <span id="fof"></span>
<br/><input type="button" onclick="show_file_dialog('fs', 'FileSave');" value="Show File Save" disabled="true"> <span id="fs"></span>
<p id="time"></p>
</form>
Observe page responsiveness:
<br/><br/>
<table><tr>
<td valign="top">
CSS:<br/><div id="loading"></div>
</td>
<td>&nbsp;</td>
<td valign="top">
JavaScript:<br/><div id="time"></div>
</td>
</tr></table>
(JavaScript will stop updating while alert/confirm/prompt is displayed)
</body>
</html>

View File

@ -0,0 +1,119 @@
<html>
<head>
<title>Render Process Hang Test</title>
<style>
#loading {
display: inline-block;
width: 10px;
height: 10px;
border: 3px solid rgba(0,0,0,.3);
border-radius: 50%;
border-top-color: #000;
animation: spin 1s ease-in-out infinite;
-webkit-animation: spin 1s ease-in-out infinite;
}
@keyframes spin {
to { -webkit-transform: rotate(360deg); }
}
@-webkit-keyframes spin {
to { -webkit-transform: rotate(360deg); }
}
#hangtime {
width: 40px;
}
</style>
<script language="JavaScript">
function setFormEnabled(enabled) {
var elements = document.getElementById("form").elements;
for (var i = 0, element; element = elements[i++]; ) {
element.disabled = !enabled;
}
}
function updateTime() {
document.getElementById('time').innerText = new Date().toLocaleString();
}
function setupTest() {
// Retrieve the currently configured command.
// Results in a call to the OnQuery method in hang_test.cc
window.cefQuery({
request: 'HangTest:getcommand',
onSuccess: function(response) {
document.getElementById(response).checked = true;
setFormEnabled(true);
},
});
}
function setup() {
// Disable all elements.
setFormEnabled(false);
updateTime();
setInterval(updateTime, 1000);
if (location.hostname == 'tests' || location.hostname == 'localhost') {
setupTest();
return;
}
alert('This page can only be run from tests or localhost.');
}
// Send a query to the browser process.
function sendCommand(command) {
// Set the configured command.
// Results in a call to the OnQuery method in hang_test.cc
window.cefQuery({
request: 'HangTest:' + command
});
}
// Hang the render process for the specified number of seconds.
function triggerHang() {
const delayMs = parseInt(document.getElementById('hangtime').value) * 1000;
const startTime = performance.now();
while(performance.now() - startTime < delayMs) {}
}
</script>
</head>
<form id="form">
<body bgcolor="white" onload="setup()">
<div>Use the below controls to trigger a render process hang.</div>
<br/>
<div>Hang for <input type="number" id="hangtime" min="1" max="99" step="1" value="20"/> seconds.</div>
<br/>
<div>Action after hanging for at least 15 seconds:</div>
<br/>
<div><input type="radio" name="command" id="default" value="default" onclick="sendCommand('setdefault')"/>
<label for="default">Default behavior (Alloy runtime: Wait; Chrome runtime: show "Page unresponsive" dialog [1])</label></div>
<div><input type="radio" name="command" id="wait" value="wait" onclick="sendCommand('setwait')"/>
<label for="wait">Wait</label></div>
<div><input type="radio" name="command" id="terminate" value="terminate" onclick="sendCommand('setterminate')"/>
<label for="terminate">Terminate the render process [2]</label></div>
<br/>
<div>[1] The "Page unresponsive" dialog will be auto-dismissed when the hang ends.</div>
<div>[2] After termination the browser navigates to the startup URL or shows an error page.</div>
<br/>
<div><input type="button" value="Trigger Hang" onclick="triggerHang()"/></div>
</form>
Observe page responsiveness:
<br/><br/>
<table><tr>
<td valign="top">
CSS:<br/><div id="loading"></div>
</td>
<td>&nbsp;</td>
<td valign="top">
JavaScript:<br/><div id="time"></div>
</td>
</tr></table>
(JavaScript will stop updating during the hang)
</body>
</html>

View File

@ -41,6 +41,7 @@
<li><a href="xmlhttprequest">XMLHttpRequest</a></li>
<li><a href="javascript:window.print();">Print this page with &quot;javascript:window.print();&quot;</a></li>
<li><a href="https://patrickhlauke.github.io/touch">Touch Feature Tests</a> - requires "touch-events=enabled" flag (and CAPS LOCK on Mac for Trackpad simulation)</li>
<li><a href="hang">Render process hang test</a></li>
</ul>
</body>
</html>

View File

@ -33,6 +33,7 @@ IDS_BINARY_TRANSFER_HTML BINARY "..\\binary_transfer.html"
IDS_BINDING_HTML BINARY "..\\binding.html"
IDS_DIALOGS_HTML BINARY "..\\dialogs.html"
IDS_DRAGGABLE_HTML BINARY "..\\draggable.html"
IDS_HANG_HTML BINARY "..\\hang.html"
IDS_IPC_PERFORMANCE_HTML BINARY "..\\ipc_performance.html"
IDS_LOCALSTORAGE_HTML BINARY "..\\localstorage.html"
IDS_LOGO_PNG BINARY "..\\logo.png"

View File

@ -82,7 +82,7 @@ int main(int argc, char* argv[]) {
// fails or if early exit is desired (for example, due to process singleton
// relaunch behavior).
if (!CefInitialize(main_args, settings, app.get(), nullptr)) {
return 1;
return CefGetExitCode();
}
// Run the CEF message loop. This will block until CefQuitMessageLoop() is

View File

@ -174,7 +174,7 @@ int main(int argc, char* argv[]) {
// fails or if early exit is desired (for example, due to process singleton
// relaunch behavior).
if (!CefInitialize(main_args, settings, app.get(), nullptr)) {
return 1;
return CefGetExitCode();
}
// Create the application delegate.

View File

@ -95,7 +95,7 @@ int APIENTRY wWinMain(HINSTANCE hInstance,
// fails or if early exit is desired (for example, due to process singleton
// relaunch behavior).
if (!CefInitialize(main_args, settings, app.get(), sandbox_info)) {
return 1;
return CefGetExitCode();
}
// Run the CEF message loop. This will block until CefQuitMessageLoop() is

View File

@ -184,7 +184,9 @@ void MRTestHandler::OnBeforeClose(CefRefPtr<CefBrowser> browser) {
}
void MRTestHandler::OnRenderProcessTerminated(CefRefPtr<CefBrowser> browser,
TerminationStatus status) {
TerminationStatus status,
int error_code,
const CefString& error_string) {
message_router_->OnRenderProcessTerminated(browser);
}

View File

@ -76,7 +76,9 @@ class MRTestHandler : public TestHandler {
void OnAfterCreated(CefRefPtr<CefBrowser> browser) override;
void OnBeforeClose(CefRefPtr<CefBrowser> browser) override;
void OnRenderProcessTerminated(CefRefPtr<CefBrowser> browser,
TerminationStatus status) override;
TerminationStatus status,
int error_code,
const CefString& error_string) override;
// Only call this method if the navigation isn't canceled.
bool OnBeforeBrowse(CefRefPtr<CefBrowser> browser,

View File

@ -259,13 +259,16 @@ class NetNotifyTestHandler : public TestHandler {
}
void OnRenderProcessTerminated(CefRefPtr<CefBrowser> browser,
TerminationStatus status) override {
TerminationStatus status,
int error_code,
const CefString& error_string) override {
got_process_terminated_ct_++;
// Termination is expected for cross-origin requests initiated from the
// renderer process.
if (!(test_type_ == NNTT_DELAYED_RENDERER && !same_origin_)) {
TestHandler::OnRenderProcessTerminated(browser, status);
TestHandler::OnRenderProcessTerminated(browser, status, error_code,
error_string);
}
FinishTest();

View File

@ -78,7 +78,9 @@ void RoutingTestHandler::OnBeforeClose(CefRefPtr<CefBrowser> browser) {
void RoutingTestHandler::OnRenderProcessTerminated(
CefRefPtr<CefBrowser> browser,
TerminationStatus status) {
TerminationStatus status,
int error_code,
const CefString& error_string) {
message_router_->OnRenderProcessTerminated(browser);
}

View File

@ -20,7 +20,9 @@ class RoutingTestHandler : public TestHandler,
void OnAfterCreated(CefRefPtr<CefBrowser> browser) override;
void OnBeforeClose(CefRefPtr<CefBrowser> browser) override;
void OnRenderProcessTerminated(CefRefPtr<CefBrowser> browser,
TerminationStatus status) override;
TerminationStatus status,
int error_code,
const CefString& error_string) override;
// Only call this method if the navigation isn't canceled.
bool OnBeforeBrowse(CefRefPtr<CefBrowser> browser,

View File

@ -437,8 +437,11 @@ CefRefPtr<CefResourceHandler> TestHandler::GetResourceHandler(
}
void TestHandler::OnRenderProcessTerminated(CefRefPtr<CefBrowser> browser,
TerminationStatus status) {
LOG(WARNING) << "OnRenderProcessTerminated: status = " << status << ".";
TerminationStatus status,
int error_code,
const CefString& error_string) {
LOG(WARNING) << "OnRenderProcessTerminated: status = " << status
<< ", error = " << error_string.ToString() << ".";
}
CefRefPtr<CefBrowser> TestHandler::GetBrowser() const {

View File

@ -180,7 +180,9 @@ class TestHandler : public CefClient,
CefRefPtr<CefRequest> request) override;
void OnRenderProcessTerminated(CefRefPtr<CefBrowser> browser,
TerminationStatus status) override;
TerminationStatus status,
int error_code,
const CefString& error_string) override;
// These methods should only be used if at most one non-popup browser exists.
CefRefPtr<CefBrowser> GetBrowser() const;