mirror of
https://bitbucket.org/chromiumembedded/cef
synced 2025-06-05 21:39:12 +02:00
Compare commits
29 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
3b5a9dfb50 | ||
|
7c94248e45 | ||
|
344f01c1a8 | ||
|
5dc6f2f29c | ||
|
fe66d80346 | ||
|
37e6a4002e | ||
|
96006d1193 | ||
|
36934ebbc5 | ||
|
84beb5a7e1 | ||
|
d1c786e7fe | ||
|
615db2f583 | ||
|
4de18f0d4b | ||
|
2830d3a706 | ||
|
8e5da68011 | ||
|
9eac4fa487 | ||
|
059f2446c0 | ||
|
f3023f8ca0 | ||
|
8311b6cfba | ||
|
a5cda9c3dc | ||
|
b36991c674 | ||
|
74f62fd38c | ||
|
071f544b5a | ||
|
2cb5ebb3db | ||
|
3463fdd061 | ||
|
b3fe8ad6d7 | ||
|
0bebcc9e97 | ||
|
9eb3683b09 | ||
|
0c9655dfb7 | ||
|
7b50b32953 |
2
BUILD.gn
2
BUILD.gn
@@ -677,6 +677,8 @@ source_set("libcef_static") {
|
||||
"libcef/browser/scheme_impl.cc",
|
||||
"libcef/browser/server_impl.cc",
|
||||
"libcef/browser/server_impl.h",
|
||||
"libcef/browser/setting_helper.cc",
|
||||
"libcef/browser/setting_helper.h",
|
||||
"libcef/browser/simple_menu_model_impl.cc",
|
||||
"libcef/browser/simple_menu_model_impl.h",
|
||||
"libcef/browser/ssl_info_impl.cc",
|
||||
|
@@ -7,5 +7,6 @@
|
||||
# https://bitbucket.org/chromiumembedded/cef/wiki/BranchesAndBuilding
|
||||
|
||||
{
|
||||
'chromium_checkout': 'refs/tags/134.0.6998.0'
|
||||
'chromium_checkout': 'refs/tags/134.0.6998.178',
|
||||
'depot_tools_checkout': 'f35efa5b85'
|
||||
}
|
||||
|
@@ -1,41 +1,48 @@
|
||||
{
|
||||
"hashes": {
|
||||
"13300": {
|
||||
"comment": "Added February 17, 2025.",
|
||||
"linux": "87d31692cf1ff1f0f2445dd026dcc0aeb02c5786",
|
||||
"mac": "3891d2358697f15e046afc65fefd7019d888817a",
|
||||
"universal": "c1a7d47be6fc130795366a1627573aa8eba1106f",
|
||||
"windows": "0efb201c9e981c4513aeea04f9f2f8041ee9ce1f"
|
||||
"comment": "Added February 21, 2025.",
|
||||
"linux": "2508f3f0b0e5dfa191036fa6c04f8dcfa18c94b9",
|
||||
"mac": "80c0b59ba9dd783aa71fae0aa5f7dad64620e8c9",
|
||||
"windows": "45d39c3669ba75467e3e609f626c31506c0eae22"
|
||||
},
|
||||
"13301": {
|
||||
"comment": "Added February 17, 2025.",
|
||||
"linux": "747f624e5059839e6a7d385de7997d45bbd42184",
|
||||
"mac": "d3ec7d79adbde067590ab1bfff1f30dd8b06546a",
|
||||
"universal": "892e654249acc7360f8aca4ee77da896753b87b8",
|
||||
"windows": "cf9fbb7aa6778fedce78b8557044f219f2b5ba0b"
|
||||
"comment": "Added February 21, 2025.",
|
||||
"linux": "aa073dd1c586812503ca293c718358460d8c2dd6",
|
||||
"mac": "fda40a5df44628cac50a589ff979c0746011591e",
|
||||
"windows": "7109702038d51512d35dd2ed77231f9100e38214"
|
||||
},
|
||||
"13302": {
|
||||
"comment": "Added February 17, 2025.",
|
||||
"linux": "ae4ab1c52ad951d37e6397db9f4e0ab0ce5044cf",
|
||||
"mac": "cfe09351db37aa275613c27145fe622d9c28d4cc",
|
||||
"universal": "acab8df1244923f1f80b18214e73c276a553ded6",
|
||||
"windows": "c4b5a65478bc1a679f4a47ba5ff6899e5c3d8761"
|
||||
"comment": "Added February 21, 2025.",
|
||||
"linux": "d5597ebfa30081953425e897209a8387b9584205",
|
||||
"mac": "4aa24470ba3a4bd9c06bc0e4a201b896394a86b5",
|
||||
"windows": "18799961f4461a9cbae2aed89ac04b73ab7c37f3"
|
||||
},
|
||||
"13303": {
|
||||
"comment": "Added February 17, 2025.",
|
||||
"linux": "2683698b779f11bba19f4051e3760fe327a1c8b2",
|
||||
"mac": "8085a0f62f15946343c63788300e5c2b422b3301",
|
||||
"universal": "128210b71e3f621cb6d2c4b05c6d0408a4547f2f",
|
||||
"windows": "5a22d42c3e6294eb4ee2424053eebdeae3027899"
|
||||
"comment": "Added February 21, 2025.",
|
||||
"linux": "f3a696ee30ce1e00490a58df017393c126c89709",
|
||||
"mac": "f2cdce2b9a4b635c28b5b92c42c35625a937380c",
|
||||
"windows": "20016fd6a9b87ef4c539cd1f42bf1ca09b6903ca"
|
||||
},
|
||||
"13304": {
|
||||
"comment": "Added February 17, 2025.",
|
||||
"linux": "c709233cd071e0d715eb10ceec4c5aea805df997",
|
||||
"mac": "32af7e8f8828b04cf2908de9857940faa54deb8a",
|
||||
"universal": "131b720865dd5c54c72041c0fbfb7c9bbfee8e0b",
|
||||
"windows": "979b48138012378192dac7ee972fa731e9c0dae9"
|
||||
"comment": "Added February 21, 2025.",
|
||||
"linux": "f1ababb4ff51ecbf77c481cee3721ef0eca9c8ca",
|
||||
"mac": "98964c37b8917d83da4b173e22905503d38ad08f",
|
||||
"windows": "19c014af0082aa901398e006381b6980e4f806e9"
|
||||
},
|
||||
"13400": {
|
||||
"comment": "Added February 21, 2025.",
|
||||
"linux": "ea2106b5bc012c25d735521e0c7fb719d433ea4a",
|
||||
"mac": "ba5ab71db4f9447f19eb7b1943024981c88064dd",
|
||||
"windows": "6ab74b90e88b7397aab9911baac5484f12466eef"
|
||||
},
|
||||
"13401": {
|
||||
"comment": "Added March 10, 2025.",
|
||||
"linux": "b14bee2c0fd250da67faea421f620b58e5dea9a2",
|
||||
"mac": "b54732b528bc2669481ec0cf17c7b97b033720b9",
|
||||
"windows": "751255204f006b8b883a8baf552a2da792f8aa44"
|
||||
}
|
||||
},
|
||||
"last": "13304",
|
||||
"last": "13401",
|
||||
"min": "13300"
|
||||
}
|
@@ -247,6 +247,8 @@
|
||||
'tests/cefclient/browser/client_prefs.cc',
|
||||
'tests/cefclient/browser/client_prefs.h',
|
||||
'tests/cefclient/browser/client_types.h',
|
||||
'tests/cefclient/browser/config_test.cc',
|
||||
'tests/cefclient/browser/config_test.h',
|
||||
'tests/cefclient/browser/default_client_handler.cc',
|
||||
'tests/cefclient/browser/default_client_handler.h',
|
||||
'tests/cefclient/browser/dialog_test.cc',
|
||||
@@ -324,6 +326,7 @@
|
||||
'cefclient_sources_resources': [
|
||||
'tests/cefclient/resources/binary_transfer.html',
|
||||
'tests/cefclient/resources/binding.html',
|
||||
'tests/cefclient/resources/config.html',
|
||||
'tests/cefclient/resources/dialogs.html',
|
||||
'tests/cefclient/resources/draggable.html',
|
||||
'tests/cefclient/resources/hang.html',
|
||||
|
@@ -271,6 +271,17 @@ macro(ADD_WINDOWS_MANIFEST manifest_path target extension)
|
||||
)
|
||||
endmacro()
|
||||
|
||||
# Set LPAC ACLs required for Windows sandbox support.
|
||||
# See https://github.com/chromiumembedded/cef/issues/3791#issuecomment-2664128961
|
||||
macro(SET_LPAC_ACLS target)
|
||||
add_custom_command(
|
||||
TARGET ${target}
|
||||
POST_BUILD
|
||||
COMMAND "icacls" "${CEF_TARGET_OUT_DIR}" "/grant" "*S-1-15-2-2:(OI)(CI)(RX)"
|
||||
COMMENT "Setting LPAC ACLs..."
|
||||
)
|
||||
endmacro()
|
||||
|
||||
endif(OS_WINDOWS)
|
||||
|
||||
|
||||
|
@@ -313,6 +313,30 @@
|
||||
#define STACK_UNINITIALIZED
|
||||
#endif
|
||||
|
||||
// Attribute "no_stack_protector" disables -fstack-protector for the specified
|
||||
// function.
|
||||
//
|
||||
// "stack_protector" is enabled on most POSIX builds. The flag adds a canary
|
||||
// to each stack frame, which on function return is checked against a reference
|
||||
// canary. If the canaries do not match, it's likely that a stack buffer
|
||||
// overflow has occurred, so immediately crashing will prevent exploitation in
|
||||
// many cases.
|
||||
//
|
||||
// In some cases it's desirable to remove this, e.g. on hot functions, or if
|
||||
// we have purposely changed the reference canary.
|
||||
//
|
||||
// On Linux systems the reference canary will be purposely changed when forking
|
||||
// sub-processes (see https://crbug.com/40181003). To avoid sub-process shutdown
|
||||
// crashes the NO_STACK_PROTECTOR annotation must be added to all functions in
|
||||
// the call stack leading to CefExecuteProcess(). Applications that cannot add
|
||||
// this annotation must instead pass the `--change-stack-guard-on-fork=disable`
|
||||
// command-line flag.
|
||||
#if defined(COMPILER_GCC) || defined(__clang__)
|
||||
#define NO_STACK_PROTECTOR __attribute__((no_stack_protector))
|
||||
#else
|
||||
#define NO_STACK_PROTECTOR
|
||||
#endif
|
||||
|
||||
// The ANALYZER_ASSUME_TRUE(bool arg) macro adds compiler-specific hints
|
||||
// to Clang which control what code paths are statically analyzed,
|
||||
// and is meant to be used in conjunction with assert & assert-like functions.
|
||||
|
@@ -77,19 +77,15 @@
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#define _CEF_AH_PASTE(a, b, c) a##_##b##_##c
|
||||
#define _CEF_AH_EVAL(a, b, c) _CEF_AH_PASTE(a, b, c)
|
||||
#define _CEF_AH_DECLARE(version, suffix) \
|
||||
_CEF_AH_EVAL(CEF_API_HASH, version, suffix)
|
||||
#define _CEF_AH_PASTE(a, b) a##_##b
|
||||
#define _CEF_AH_EVAL(a, b) _CEF_AH_PASTE(a, b)
|
||||
#define _CEF_AH_DECLARE(version) _CEF_AH_EVAL(CEF_API_HASH, version)
|
||||
|
||||
// API hashes for the selected CEF_API_VERSION. API hashes are created for
|
||||
// each version by analyzing CEF header files for C API type definitions. The
|
||||
// hash value will change when header files are modified in a 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 _CEF_AH_DECLARE(CEF_API_VERSION, UNIVERSAL)
|
||||
#define CEF_API_HASH_PLATFORM _CEF_AH_DECLARE(CEF_API_VERSION, PLATFORM)
|
||||
// cause binary incompatibility with other builds.
|
||||
#define CEF_API_HASH_PLATFORM _CEF_AH_DECLARE(CEF_API_VERSION)
|
||||
|
||||
#if defined(BUILDING_CEF_SHARED)
|
||||
|
||||
@@ -132,7 +128,7 @@ extern "C" {
|
||||
/// parameter describes which hash value will be returned:
|
||||
///
|
||||
/// 0 - CEF_API_HASH_PLATFORM
|
||||
/// 1 - CEF_API_HASH_UNIVERSAL
|
||||
/// 1 - CEF_API_HASH_UNIVERSAL (deprecated, same as CEF_API_HASH_PLATFORM)
|
||||
/// 2 - CEF_COMMIT_HASH (from cef_version.h)
|
||||
///
|
||||
CEF_EXPORT const char* cef_api_hash(int version, int entry);
|
||||
|
@@ -59,7 +59,7 @@ class CefApp;
|
||||
/// |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,
|
||||
/*--cef(api_hash_check,no_stack_protector,optional_param=application,
|
||||
optional_param=windows_sandbox_info)--*/
|
||||
int CefExecuteProcess(const CefMainArgs& args,
|
||||
CefRefPtr<CefApp> application,
|
||||
|
@@ -31,8 +31,11 @@
|
||||
#define CEF_INCLUDE_CEF_BASE_H_
|
||||
#pragma once
|
||||
|
||||
#include "include/base/cef_atomic_ref_count.h"
|
||||
#if !defined(GENERATING_CEF_API_HASH)
|
||||
#include "include/base/cef_build.h"
|
||||
#endif
|
||||
|
||||
#include "include/base/cef_atomic_ref_count.h"
|
||||
#include "include/base/cef_macros.h"
|
||||
|
||||
// Bring in common C++ type definitions used by CEF consumers.
|
||||
|
@@ -249,7 +249,7 @@ class CefPdfPrintCallback : public virtual CefBaseRefCounted {
|
||||
/// is the output path. |ok| will be true if the printing completed
|
||||
/// successfully or false otherwise.
|
||||
///
|
||||
/*--cef()--*/
|
||||
/*--cef(optional_param=path)--*/
|
||||
virtual void OnPdfPrintFinished(const CefString& path, bool ok) = 0;
|
||||
};
|
||||
|
||||
|
@@ -41,6 +41,7 @@
|
||||
#include <vector>
|
||||
|
||||
#include "include/cef_base.h"
|
||||
#include "include/cef_registration.h"
|
||||
#include "include/cef_values.h"
|
||||
|
||||
///
|
||||
@@ -65,6 +66,24 @@ class CefPreferenceRegistrar : public CefBaseScoped {
|
||||
CefRefPtr<CefValue> default_value) = 0;
|
||||
};
|
||||
|
||||
#if CEF_API_ADDED(13401)
|
||||
///
|
||||
/// Implemented by the client to observe preference changes and registered via
|
||||
/// CefPreferenceManager::AddPreferenceObserver. The methods of this class will
|
||||
/// be called on the browser process UI thread.
|
||||
///
|
||||
/*--cef(source=client,added=13401)--*/
|
||||
class CefPreferenceObserver : public virtual CefBaseRefCounted {
|
||||
public:
|
||||
///
|
||||
/// Called when a preference has changed. The new value can be retrieved using
|
||||
/// CefPreferenceManager::GetPreference.
|
||||
///
|
||||
/*--cef()--*/
|
||||
virtual void OnPreferenceChanged(const CefString& name) = 0;
|
||||
};
|
||||
#endif
|
||||
|
||||
///
|
||||
/// Manage access to preferences. Many built-in preferences are registered by
|
||||
/// Chromium. Custom preferences can be registered in
|
||||
@@ -73,6 +92,36 @@ class CefPreferenceRegistrar : public CefBaseScoped {
|
||||
/*--cef(source=library,no_debugct_check)--*/
|
||||
class CefPreferenceManager : public virtual CefBaseRefCounted {
|
||||
public:
|
||||
#if CEF_API_ADDED(13401)
|
||||
///
|
||||
/// Returns the current Chrome Variations configuration (combination of field
|
||||
/// trials and chrome://flags) as equivalent command-line switches
|
||||
/// (`--[enable|disable]-features=XXXX`, etc). These switches can be used to
|
||||
/// apply the same configuration when launching a CEF-based application. See
|
||||
/// https://developer.chrome.com/docs/web-platform/chrome-variations for
|
||||
/// background and details. Note that field trial tests are disabled by
|
||||
/// default in Official CEF builds (via the
|
||||
/// `disable_fieldtrial_testing_config=true` GN flag). This method must be
|
||||
/// called on the browser process UI thread.
|
||||
///
|
||||
/*--cef(added=13401)--*/
|
||||
static void GetChromeVariationsAsSwitches(std::vector<CefString>& switches);
|
||||
|
||||
///
|
||||
/// Returns the current Chrome Variations configuration (combination of field
|
||||
/// trials and chrome://flags) as human-readable strings. This is the
|
||||
/// human-readable equivalent of the "Active Variations" section of
|
||||
/// chrome://version. See
|
||||
/// https://developer.chrome.com/docs/web-platform/chrome-variations for
|
||||
/// background and details. Note that field trial tests are disabled by
|
||||
/// default in Official CEF builds (via the
|
||||
/// `disable_fieldtrial_testing_config=true` GN flag). This method must be
|
||||
/// called on the browser process UI thread.
|
||||
///
|
||||
/*--cef(added=13401)--*/
|
||||
static void GetChromeVariationsAsStrings(std::vector<CefString>& strings);
|
||||
#endif
|
||||
|
||||
///
|
||||
/// Returns the global preference manager object.
|
||||
///
|
||||
@@ -129,6 +178,21 @@ class CefPreferenceManager : public virtual CefBaseRefCounted {
|
||||
virtual bool SetPreference(const CefString& name,
|
||||
CefRefPtr<CefValue> value,
|
||||
CefString& error) = 0;
|
||||
|
||||
#if CEF_API_ADDED(13401)
|
||||
///
|
||||
/// Add an observer for preference changes. |name| is the name of the
|
||||
/// preference to observe. If |name| is empty then all preferences will
|
||||
/// be observed. Observing all preferences has performance consequences and
|
||||
/// is not recommended outside of testing scenarios. The observer will remain
|
||||
/// registered until the returned Registration object is destroyed. This
|
||||
/// method must be called on the browser process UI thread.
|
||||
///
|
||||
/*--cef(optional_param=name,added=13401)--*/
|
||||
virtual CefRefPtr<CefRegistration> AddPreferenceObserver(
|
||||
const CefString& name,
|
||||
CefRefPtr<CefPreferenceObserver> observer) = 0;
|
||||
#endif
|
||||
};
|
||||
|
||||
#endif // CEF_INCLUDE_CEF_PREFERENCE_H_
|
||||
|
@@ -44,6 +44,7 @@
|
||||
#include "include/cef_cookie.h"
|
||||
#include "include/cef_media_router.h"
|
||||
#include "include/cef_preference.h"
|
||||
#include "include/cef_registration.h"
|
||||
#include "include/cef_values.h"
|
||||
|
||||
class CefRequestContextHandler;
|
||||
@@ -66,6 +67,27 @@ class CefResolveCallback : public virtual CefBaseRefCounted {
|
||||
const std::vector<CefString>& resolved_ips) = 0;
|
||||
};
|
||||
|
||||
#if CEF_API_ADDED(13401)
|
||||
///
|
||||
/// Implemented by the client to observe content and website setting changes and
|
||||
/// registered via CefRequestContext::AddSettingObserver. The methods of this
|
||||
/// class will be called on the browser process UI thread.
|
||||
///
|
||||
/*--cef(source=client,added=13401)--*/
|
||||
class CefSettingObserver : public virtual CefBaseRefCounted {
|
||||
public:
|
||||
///
|
||||
/// Called when a content or website setting has changed. The new value can be
|
||||
/// retrieved using CefRequestContext::GetContentSetting or
|
||||
/// CefRequestContext::GetWebsiteSetting.
|
||||
///
|
||||
/*--cef(optional_param=requesting_url,optional_param=top_level_url)--*/
|
||||
virtual void OnSettingChanged(const CefString& requesting_url,
|
||||
const CefString& top_level_url,
|
||||
cef_content_setting_types_t content_type) = 0;
|
||||
};
|
||||
#endif
|
||||
|
||||
///
|
||||
/// A request context provides request handling for a set of related browser
|
||||
/// or URL request objects. A request context can be specified when creating a
|
||||
@@ -292,6 +314,17 @@ class CefRequestContext : public CefPreferenceManager {
|
||||
cef_content_setting_types_t content_type,
|
||||
cef_content_setting_values_t value) = 0;
|
||||
|
||||
#if CEF_API_ADDED(13401)
|
||||
///
|
||||
/// Add an observer for content and website setting changes. The observer will
|
||||
/// remain registered until the returned Registration object is destroyed.
|
||||
/// This method must be called on the browser process UI thread.
|
||||
///
|
||||
/*--cef(added=13401)--*/
|
||||
virtual CefRefPtr<CefRegistration> AddSettingObserver(
|
||||
CefRefPtr<CefSettingObserver> observer) = 0;
|
||||
#endif
|
||||
|
||||
///
|
||||
/// Sets the Chrome color scheme for all browsers that share this request
|
||||
/// context. |variant| values of SYSTEM, LIGHT and DARK change the underlying
|
||||
|
@@ -31,7 +31,10 @@
|
||||
#define CEF_INCLUDE_CEF_SANDBOX_MAC_H_
|
||||
#pragma once
|
||||
|
||||
#if !defined(GENERATING_CEF_API_HASH)
|
||||
#include "include/base/cef_build.h"
|
||||
#endif
|
||||
|
||||
#include "include/internal/cef_export.h"
|
||||
|
||||
#if defined(OS_MAC)
|
||||
|
@@ -31,7 +31,9 @@
|
||||
#define CEF_INCLUDE_CEF_SANDBOX_WIN_H_
|
||||
#pragma once
|
||||
|
||||
#if !defined(GENERATING_CEF_API_HASH)
|
||||
#include "include/base/cef_build.h"
|
||||
#endif
|
||||
|
||||
#if defined(OS_WIN)
|
||||
|
||||
|
@@ -31,7 +31,9 @@
|
||||
#define CEF_INCLUDE_INTERNAL_CEF_APP_WIN_H_
|
||||
#pragma once
|
||||
|
||||
#if !defined(GENERATING_CEF_API_HASH)
|
||||
#include "include/base/cef_build.h"
|
||||
#endif
|
||||
|
||||
#if defined(OS_WIN)
|
||||
|
||||
|
@@ -32,7 +32,9 @@
|
||||
#define CEF_INCLUDE_INTERNAL_CEF_EXPORT_H_
|
||||
#pragma once
|
||||
|
||||
#if !defined(GENERATING_CEF_API_HASH)
|
||||
#include "include/base/cef_build.h"
|
||||
#endif
|
||||
|
||||
#if defined(COMPILER_MSVC)
|
||||
|
||||
|
@@ -31,12 +31,14 @@
|
||||
#define CEF_INCLUDE_INTERNAL_CEF_THREAD_INTERNAL_H_
|
||||
#pragma once
|
||||
|
||||
#if !defined(GENERATING_CEF_API_HASH)
|
||||
#if defined(OS_WIN)
|
||||
#include <windows.h>
|
||||
#elif defined(OS_POSIX)
|
||||
#include <pthread.h>
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include "include/internal/cef_export.h"
|
||||
|
||||
|
@@ -35,8 +35,11 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
#if !defined(GENERATING_CEF_API_HASH)
|
||||
#include <time.h>
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "include/internal/cef_export.h"
|
||||
|
||||
|
@@ -3622,7 +3622,7 @@ typedef enum {
|
||||
#if CEF_API_ADDED(13304)
|
||||
CEF_CPAIT_COLLABORATION_MESSAGING,
|
||||
#endif
|
||||
#if CEF_API_ADDED(CEF_NEXT)
|
||||
#if CEF_API_ADDED(13400)
|
||||
CEF_CPAIT_CHANGE_PASSWORD,
|
||||
#endif
|
||||
CEF_CPAIT_NUM_VALUES,
|
||||
|
@@ -486,7 +486,7 @@ typedef enum {
|
||||
/// or legacy behavior.
|
||||
CEF_CONTENT_SETTING_TYPE_LEGACY_COOKIE_SCOPE,
|
||||
|
||||
#if CEF_API_ADDED(CEF_NEXT)
|
||||
#if CEF_API_ADDED(13400)
|
||||
/// Website setting to indicate whether the user has allowlisted suspicious
|
||||
/// notifications for the origin.
|
||||
CEF_CONTENT_SETTING_TYPE_ARE_SUSPICIOUS_NOTIFICATIONS_ALLOWLISTED_BY_USER,
|
||||
|
@@ -31,15 +31,12 @@
|
||||
#define CEF_INCLUDE_INTERNAL_CEF_TYPES_LINUX_H_
|
||||
#pragma once
|
||||
|
||||
#if !defined(GENERATING_CEF_API_HASH)
|
||||
#include "include/base/cef_build.h"
|
||||
#endif
|
||||
|
||||
#if defined(OS_LINUX)
|
||||
|
||||
#if defined(CEF_X11)
|
||||
typedef union _XEvent XEvent;
|
||||
typedef struct _XDisplay XDisplay;
|
||||
#endif
|
||||
|
||||
#include "include/internal/cef_export.h"
|
||||
#include "include/internal/cef_string.h"
|
||||
#include "include/internal/cef_types_color.h"
|
||||
@@ -47,17 +44,6 @@ typedef struct _XDisplay XDisplay;
|
||||
#include "include/internal/cef_types_osr.h"
|
||||
#include "include/internal/cef_types_runtime.h"
|
||||
|
||||
// Handle types.
|
||||
#if defined(CEF_X11)
|
||||
#define cef_cursor_handle_t unsigned long
|
||||
#define cef_event_handle_t XEvent*
|
||||
#else
|
||||
#define cef_cursor_handle_t void*
|
||||
#define cef_event_handle_t void*
|
||||
#endif
|
||||
|
||||
#define cef_window_handle_t unsigned long
|
||||
|
||||
#define kNullCursorHandle 0
|
||||
#define kNullEventHandle NULL
|
||||
#define kNullWindowHandle 0
|
||||
@@ -66,6 +52,20 @@ typedef struct _XDisplay XDisplay;
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#if defined(CEF_X11)
|
||||
typedef union _XEvent XEvent;
|
||||
typedef struct _XDisplay XDisplay;
|
||||
|
||||
// Handle types.
|
||||
typedef unsigned long cef_cursor_handle_t;
|
||||
typedef XEvent* cef_event_handle_t;
|
||||
#else
|
||||
typedef void* cef_cursor_handle_t;
|
||||
typedef void* cef_event_handle_t;
|
||||
#endif
|
||||
|
||||
typedef unsigned long cef_window_handle_t;
|
||||
|
||||
///
|
||||
/// Return the singleton X11 display shared with Chromium. The display is not
|
||||
/// thread-safe and must only be accessed on the browser process UI thread.
|
||||
|
@@ -31,7 +31,9 @@
|
||||
#define CEF_INCLUDE_INTERNAL_CEF_TYPES_MAC_H_
|
||||
#pragma once
|
||||
|
||||
#if !defined(GENERATING_CEF_API_HASH)
|
||||
#include "include/base/cef_build.h"
|
||||
#endif
|
||||
|
||||
#if defined(OS_MAC)
|
||||
#include "include/internal/cef_string.h"
|
||||
@@ -40,16 +42,6 @@
|
||||
#include "include/internal/cef_types_osr.h"
|
||||
#include "include/internal/cef_types_runtime.h"
|
||||
|
||||
// Handle types.
|
||||
// Actually NSCursor*
|
||||
#define cef_cursor_handle_t void*
|
||||
// Acutally NSEvent*
|
||||
#define cef_event_handle_t void*
|
||||
// Actually NSView*
|
||||
#define cef_window_handle_t void*
|
||||
// Actually IOSurface*
|
||||
#define cef_shared_texture_handle_t void*
|
||||
|
||||
#define kNullCursorHandle NULL
|
||||
#define kNullEventHandle NULL
|
||||
#define kNullWindowHandle NULL
|
||||
@@ -78,6 +70,16 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
// Handle types.
|
||||
// Actually NSCursor*
|
||||
typedef void* cef_cursor_handle_t;
|
||||
// Actually NSEvent*
|
||||
typedef void* cef_event_handle_t;
|
||||
// Actually NSView*
|
||||
typedef void* cef_window_handle_t;
|
||||
// Actually IOSurface*
|
||||
typedef void* cef_shared_texture_handle_t;
|
||||
|
||||
///
|
||||
/// Structure representing CefExecuteProcess arguments.
|
||||
///
|
||||
|
@@ -31,10 +31,15 @@
|
||||
#define CEF_INCLUDE_INTERNAL_CEF_TYPES_WIN_H_
|
||||
#pragma once
|
||||
|
||||
#if !defined(GENERATING_CEF_API_HASH)
|
||||
#include "include/base/cef_build.h"
|
||||
#endif
|
||||
|
||||
#if defined(OS_WIN)
|
||||
|
||||
#if !defined(GENERATING_CEF_API_HASH)
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
#include "include/internal/cef_string.h"
|
||||
#include "include/internal/cef_types_color.h"
|
||||
@@ -42,12 +47,6 @@
|
||||
#include "include/internal/cef_types_osr.h"
|
||||
#include "include/internal/cef_types_runtime.h"
|
||||
|
||||
// Handle types.
|
||||
#define cef_cursor_handle_t HCURSOR
|
||||
#define cef_event_handle_t MSG*
|
||||
#define cef_window_handle_t HWND
|
||||
#define cef_shared_texture_handle_t HANDLE
|
||||
|
||||
#define kNullCursorHandle NULL
|
||||
#define kNullEventHandle NULL
|
||||
#define kNullWindowHandle NULL
|
||||
@@ -56,6 +55,12 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
// Handle types.
|
||||
typedef HCURSOR cef_cursor_handle_t;
|
||||
typedef MSG* cef_event_handle_t;
|
||||
typedef HWND cef_window_handle_t;
|
||||
typedef HANDLE cef_shared_texture_handle_t;
|
||||
|
||||
///
|
||||
/// Structure representing CefExecuteProcess arguments.
|
||||
///
|
||||
|
@@ -12,10 +12,12 @@
|
||||
#include "base/task/current_thread.h"
|
||||
#include "base/threading/thread_restrictions.h"
|
||||
#include "cef/libcef/browser/browser_info_manager.h"
|
||||
#include "cef/libcef/browser/prefs/pref_helper.h"
|
||||
#include "cef/libcef/browser/request_context_impl.h"
|
||||
#include "cef/libcef/browser/thread_util.h"
|
||||
#include "cef/libcef/browser/trace_subscriber.h"
|
||||
#include "cef/libcef/common/cef_switches.h"
|
||||
#include "chrome/browser/browser_process_impl.h"
|
||||
#include "components/network_session_configurator/common/network_switches.h"
|
||||
#include "ui/base/ui_base_switches.h"
|
||||
|
||||
@@ -289,6 +291,7 @@ int RunMainWithPreferredStackSize(FiberState& fiber_state) {
|
||||
|
||||
} // namespace
|
||||
|
||||
NO_STACK_PROTECTOR
|
||||
int CefExecuteProcess(const CefMainArgs& args,
|
||||
CefRefPtr<CefApp> application,
|
||||
void* windows_sandbox_info) {
|
||||
@@ -570,12 +573,24 @@ CefTraceSubscriber* CefContext::GetTraceSubscriber() {
|
||||
if (shutting_down_) {
|
||||
return nullptr;
|
||||
}
|
||||
if (!trace_subscriber_.get()) {
|
||||
if (!trace_subscriber_) {
|
||||
trace_subscriber_ = std::make_unique<CefTraceSubscriber>();
|
||||
}
|
||||
return trace_subscriber_.get();
|
||||
}
|
||||
|
||||
pref_helper::Registrar* CefContext::GetPrefRegistrar() {
|
||||
CEF_REQUIRE_UIT();
|
||||
if (shutting_down_) {
|
||||
return nullptr;
|
||||
}
|
||||
if (!pref_registrar_) {
|
||||
pref_registrar_ = std::make_unique<pref_helper::Registrar>();
|
||||
pref_registrar_->Init(g_browser_process->local_state());
|
||||
}
|
||||
return pref_registrar_.get();
|
||||
}
|
||||
|
||||
void CefContext::PopulateGlobalRequestContextSettings(
|
||||
CefRequestContextSettings* settings) {
|
||||
CefRefPtr<CefCommandLine> command_line =
|
||||
@@ -645,12 +660,15 @@ void CefContext::ShutdownOnUIThread() {
|
||||
observer.OnContextDestroyed();
|
||||
}
|
||||
|
||||
if (trace_subscriber_.get()) {
|
||||
trace_subscriber_.reset(nullptr);
|
||||
if (trace_subscriber_) {
|
||||
trace_subscriber_.reset();
|
||||
}
|
||||
if (pref_registrar_) {
|
||||
pref_registrar_.reset();
|
||||
}
|
||||
}
|
||||
|
||||
void CefContext::FinalizeShutdown() {
|
||||
browser_info_manager_.reset(nullptr);
|
||||
browser_info_manager_.reset();
|
||||
application_ = nullptr;
|
||||
}
|
||||
|
@@ -16,6 +16,10 @@
|
||||
#include "cef/libcef/browser/main_runner.h"
|
||||
#include "third_party/skia/include/core/SkColor.h"
|
||||
|
||||
namespace pref_helper {
|
||||
class Registrar;
|
||||
}
|
||||
|
||||
class CefBrowserInfoManager;
|
||||
class CefTraceSubscriber;
|
||||
|
||||
@@ -73,6 +77,7 @@ class CefContext {
|
||||
cef_state_t windowless_state) const;
|
||||
|
||||
CefTraceSubscriber* GetTraceSubscriber();
|
||||
pref_helper::Registrar* GetPrefRegistrar();
|
||||
|
||||
// Populate request context settings for the global system context based on
|
||||
// CefSettings and command-line flags.
|
||||
@@ -112,6 +117,7 @@ class CefContext {
|
||||
|
||||
std::unique_ptr<CefMainRunner> main_runner_;
|
||||
std::unique_ptr<CefTraceSubscriber> trace_subscriber_;
|
||||
std::unique_ptr<pref_helper::Registrar> pref_registrar_;
|
||||
std::unique_ptr<CefBrowserInfoManager> browser_info_manager_;
|
||||
|
||||
// Observers that want to be notified of changes to this object.
|
||||
|
@@ -4,10 +4,28 @@
|
||||
|
||||
#include "cef/libcef/browser/global_preference_manager_impl.h"
|
||||
|
||||
#include "base/metrics/field_trial_list_including_low_anonymity.h"
|
||||
#include "base/strings/string_util.h"
|
||||
#include "cef/libcef/browser/context.h"
|
||||
#include "cef/libcef/browser/prefs/pref_helper.h"
|
||||
#include "cef/libcef/browser/thread_util.h"
|
||||
#include "cef/libcef/common/api_version_util.h"
|
||||
#include "chrome/browser/about_flags.h"
|
||||
#include "chrome/browser/browser_process.h"
|
||||
#include "components/flags_ui/pref_service_flags_storage.h"
|
||||
#include "components/variations/synthetic_trials_active_group_id_provider.h"
|
||||
|
||||
namespace {
|
||||
|
||||
std::string GetActiveGroupNameAsString(
|
||||
const base::FieldTrial::ActiveGroup& group) {
|
||||
constexpr std::string_view kNonBreakingHyphenUTF8 = "\xE2\x80\x91";
|
||||
std::string result = group.trial_name + ":" + group.group_name;
|
||||
base::ReplaceChars(result, "-", kNonBreakingHyphenUTF8, &result);
|
||||
return result;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
bool CefGlobalPreferenceManagerImpl::HasPreference(const CefString& name) {
|
||||
CEF_REQUIRE_UIT_RETURN(false);
|
||||
@@ -40,6 +58,77 @@ bool CefGlobalPreferenceManagerImpl::SetPreference(const CefString& name,
|
||||
value, error);
|
||||
}
|
||||
|
||||
CefRefPtr<CefRegistration>
|
||||
CefGlobalPreferenceManagerImpl::AddPreferenceObserver(
|
||||
const CefString& name,
|
||||
CefRefPtr<CefPreferenceObserver> observer) {
|
||||
CEF_API_REQUIRE_ADDED(13401);
|
||||
CEF_REQUIRE_UIT_RETURN(nullptr);
|
||||
return CefContext::Get()->GetPrefRegistrar()->AddObserver(name, observer);
|
||||
}
|
||||
|
||||
// static
|
||||
void CefPreferenceManager::GetChromeVariationsAsSwitches(
|
||||
std::vector<CefString>& switches) {
|
||||
CEF_API_REQUIRE_ADDED(13401);
|
||||
|
||||
// Verify that the context is in a valid state.
|
||||
if (!CONTEXT_STATE_VALID()) {
|
||||
DCHECK(false) << "context not valid";
|
||||
return;
|
||||
}
|
||||
|
||||
switches.clear();
|
||||
|
||||
// Based on ChromeFeatureListCreator::ConvertFlagsToSwitches().
|
||||
|
||||
flags_ui::PrefServiceFlagsStorage flags_storage(
|
||||
g_browser_process->local_state());
|
||||
base::CommandLine command_line(base::CommandLine::NO_PROGRAM);
|
||||
about_flags::ConvertFlagsToSwitches(&flags_storage, &command_line,
|
||||
flags_ui::kNoSentinels);
|
||||
|
||||
for (const auto& arg : command_line.argv()) {
|
||||
if (!arg.empty()) {
|
||||
switches.push_back(arg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// static
|
||||
void CefPreferenceManager::GetChromeVariationsAsStrings(
|
||||
std::vector<CefString>& strings) {
|
||||
CEF_API_REQUIRE_ADDED(13401);
|
||||
|
||||
// Verify that the context is in a valid state.
|
||||
if (!CONTEXT_STATE_VALID()) {
|
||||
DCHECK(false) << "context not valid";
|
||||
return;
|
||||
}
|
||||
|
||||
strings.clear();
|
||||
|
||||
// Based on components/webui/version/version_handler_helper.cc
|
||||
// GetVariationsList().
|
||||
|
||||
base::FieldTrial::ActiveGroups active_groups;
|
||||
// Include low anonymity trial groups in the version string, as it is only
|
||||
// displayed locally (and is useful for diagnostics purposes).
|
||||
base::FieldTrialListIncludingLowAnonymity::
|
||||
GetActiveFieldTrialGroupsForTesting(&active_groups);
|
||||
|
||||
for (const auto& group : active_groups) {
|
||||
strings.push_back(GetActiveGroupNameAsString(group));
|
||||
}
|
||||
|
||||
// Synthetic field trials.
|
||||
for (const auto& group :
|
||||
variations::SyntheticTrialsActiveGroupIdProvider::GetInstance()
|
||||
->GetGroups()) {
|
||||
strings.push_back(GetActiveGroupNameAsString(group.active_group()));
|
||||
}
|
||||
}
|
||||
|
||||
// static
|
||||
CefRefPtr<CefPreferenceManager>
|
||||
CefPreferenceManager::GetGlobalPreferenceManager() {
|
||||
|
@@ -27,6 +27,9 @@ class CefGlobalPreferenceManagerImpl : public CefPreferenceManager {
|
||||
bool SetPreference(const CefString& name,
|
||||
CefRefPtr<CefValue> value,
|
||||
CefString& error) override;
|
||||
CefRefPtr<CefRegistration> AddPreferenceObserver(
|
||||
const CefString& name,
|
||||
CefRefPtr<CefPreferenceObserver> observer) override;
|
||||
|
||||
private:
|
||||
IMPLEMENT_REFCOUNTING(CefGlobalPreferenceManagerImpl);
|
||||
|
@@ -207,6 +207,7 @@ void CefMainRunner::QuitMessageLoop() {
|
||||
}
|
||||
|
||||
// static
|
||||
NO_STACK_PROTECTOR
|
||||
int CefMainRunner::RunAsHelperProcess(const CefMainArgs& args,
|
||||
CefRefPtr<CefApp> application,
|
||||
void* windows_sandbox_info) {
|
||||
|
@@ -215,8 +215,10 @@ class CefMediaAccessQuery {
|
||||
content::DesktopMediaID(content::DesktopMediaID::TYPE_SCREEN,
|
||||
-1 /* webrtc::kFullDesktopScreenId */);
|
||||
}
|
||||
video_devices.emplace_back(request_.video_type, media_id.ToString(),
|
||||
"Screen");
|
||||
if (media_id.type != content::DesktopMediaID::TYPE_NONE) {
|
||||
video_devices.emplace_back(request_.video_type, media_id.ToString(),
|
||||
"Screen");
|
||||
}
|
||||
}
|
||||
|
||||
blink::mojom::StreamDevicesSetPtr stream_devices_set =
|
||||
|
@@ -20,6 +20,12 @@
|
||||
#include "content/public/browser/render_widget_host_view.h"
|
||||
#include "third_party/blink/public/mojom/context_menu/context_menu.mojom.h"
|
||||
|
||||
#if BUILDFLAG(IS_WIN)
|
||||
#include "chrome/browser/spellchecker/spellcheck_factory.h"
|
||||
#include "chrome/browser/spellchecker/spellcheck_service.h"
|
||||
#include "components/spellcheck/browser/spellcheck_platform.h"
|
||||
#endif
|
||||
|
||||
namespace {
|
||||
|
||||
CefString GetLabel(int message_id) {
|
||||
@@ -120,8 +126,8 @@ bool CefMenuManager::IsShowingContextMenu() {
|
||||
return web_contents()->IsShowingContextMenu();
|
||||
}
|
||||
|
||||
bool CefMenuManager::CreateContextMenu(
|
||||
const content::ContextMenuParams& params) {
|
||||
bool CefMenuManager::CreateContextMenu(const content::ContextMenuParams& params,
|
||||
bool query_spellcheck) {
|
||||
// The renderer may send the "show context menu" message multiple times, one
|
||||
// for each right click mouse event it receives. Normally, this doesn't happen
|
||||
// because mouse events are not forwarded once the context menu is showing.
|
||||
@@ -134,6 +140,24 @@ bool CefMenuManager::CreateContextMenu(
|
||||
}
|
||||
|
||||
params_ = params;
|
||||
|
||||
#if BUILDFLAG(IS_WIN)
|
||||
// System spellcheck suggestions need to be queried asynchronously.
|
||||
if (query_spellcheck && !params_.misspelled_word.empty() &&
|
||||
params_.dictionary_suggestions.empty()) {
|
||||
SpellcheckService* spellcheck_service =
|
||||
SpellcheckServiceFactory::GetForContext(
|
||||
browser_->web_contents()->GetBrowserContext());
|
||||
if (spellcheck_service) {
|
||||
spellcheck_platform::GetPerLanguageSuggestions(
|
||||
spellcheck_service->platform_spell_checker(), params_.misspelled_word,
|
||||
base::BindOnce(&CefMenuManager::OnGetPlatformSuggestionsComplete,
|
||||
weak_ptr_factory_.GetWeakPtr()));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
model_->Clear();
|
||||
|
||||
// Create the default menu model.
|
||||
@@ -511,3 +535,18 @@ bool CefMenuManager::IsCustomContextMenuCommand(int command_id) {
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
#if BUILDFLAG(IS_WIN)
|
||||
void CefMenuManager::OnGetPlatformSuggestionsComplete(
|
||||
const spellcheck::PerLanguageSuggestions&
|
||||
platform_per_language_suggestions) {
|
||||
std::vector<std::u16string> combined_suggestions;
|
||||
spellcheck::FillSuggestions(platform_per_language_suggestions,
|
||||
&combined_suggestions);
|
||||
|
||||
params_.dictionary_suggestions = combined_suggestions;
|
||||
|
||||
// Now that we have spelling suggestions, call CreateContextMenu again.
|
||||
CreateContextMenu(params_, /*query_spellcheck=*/false);
|
||||
}
|
||||
#endif
|
||||
|
@@ -13,6 +13,10 @@
|
||||
#include "content/public/browser/context_menu_params.h"
|
||||
#include "content/public/browser/web_contents_observer.h"
|
||||
|
||||
#if BUILDFLAG(IS_WIN)
|
||||
#include "components/spellcheck/common/spellcheck_common.h"
|
||||
#endif
|
||||
|
||||
namespace content {
|
||||
class RenderFrameHost;
|
||||
class WebContents;
|
||||
@@ -39,7 +43,8 @@ class CefMenuManager : public CefMenuModelImpl::Delegate,
|
||||
bool IsShowingContextMenu();
|
||||
|
||||
// Create the context menu.
|
||||
bool CreateContextMenu(const content::ContextMenuParams& params);
|
||||
bool CreateContextMenu(const content::ContextMenuParams& params,
|
||||
bool query_spellcheck = true);
|
||||
void CancelContextMenu();
|
||||
|
||||
private:
|
||||
@@ -62,6 +67,12 @@ class CefMenuManager : public CefMenuModelImpl::Delegate,
|
||||
// Returns true if the specified id is a custom context menu command.
|
||||
bool IsCustomContextMenuCommand(int command_id);
|
||||
|
||||
#if BUILDFLAG(IS_WIN)
|
||||
void OnGetPlatformSuggestionsComplete(
|
||||
const spellcheck::PerLanguageSuggestions&
|
||||
platform_per_language_suggestions);
|
||||
#endif
|
||||
|
||||
// AlloyBrowserHostImpl pointer is guaranteed to outlive this object.
|
||||
raw_ptr<AlloyBrowserHostImpl> browser_;
|
||||
|
||||
|
@@ -21,7 +21,8 @@ bool CefMenuRunnerMac::RunContextMenu(
|
||||
// Create a menu controller based on the model.
|
||||
MenuControllerCocoa* menu_controller =
|
||||
[[MenuControllerCocoa alloc] initWithModel:model->model()
|
||||
delegate:nil];
|
||||
delegate:nil
|
||||
useWithPopUpButtonCell:NO];
|
||||
|
||||
menu_controller_ = menu_controller;
|
||||
|
||||
|
@@ -6,6 +6,7 @@
|
||||
|
||||
#include "base/notreached.h"
|
||||
#include "base/strings/stringprintf.h"
|
||||
#include "cef/include/cef_preference.h"
|
||||
#include "cef/libcef/browser/thread_util.h"
|
||||
#include "cef/libcef/common/values_impl.h"
|
||||
#include "components/prefs/pref_service.h"
|
||||
@@ -118,4 +119,145 @@ bool SetPreference(PrefService* pref_service,
|
||||
return true;
|
||||
}
|
||||
|
||||
class RegistrationImpl final : public Registration, public CefRegistration {
|
||||
public:
|
||||
RegistrationImpl(Registrar* registrar,
|
||||
const CefString& name,
|
||||
CefRefPtr<CefPreferenceObserver> observer)
|
||||
: registrar_(registrar), name_(name), observer_(observer) {
|
||||
DCHECK(registrar_);
|
||||
DCHECK(observer_);
|
||||
}
|
||||
|
||||
RegistrationImpl(const RegistrationImpl&) = delete;
|
||||
RegistrationImpl& operator=(const RegistrationImpl&) = delete;
|
||||
|
||||
~RegistrationImpl() override {
|
||||
CEF_REQUIRE_UIT();
|
||||
if (registrar_) {
|
||||
registrar_->RemoveObserver(name_.ToString(), this);
|
||||
}
|
||||
}
|
||||
|
||||
void Detach() override {
|
||||
registrar_ = nullptr;
|
||||
observer_ = nullptr;
|
||||
}
|
||||
|
||||
void RunCallback() const override { RunCallback(name_); }
|
||||
|
||||
void RunCallback(const CefString& name) const override {
|
||||
observer_->OnPreferenceChanged(name);
|
||||
}
|
||||
|
||||
private:
|
||||
raw_ptr<Registrar> registrar_;
|
||||
CefString name_;
|
||||
CefRefPtr<CefPreferenceObserver> observer_;
|
||||
|
||||
IMPLEMENT_REFCOUNTING_DELETE_ON_UIT(RegistrationImpl);
|
||||
};
|
||||
|
||||
Registrar::~Registrar() {
|
||||
RemoveAll();
|
||||
}
|
||||
|
||||
void Registrar::Init(PrefService* service) {
|
||||
DCHECK(service);
|
||||
DCHECK(IsEmpty() || service_ == service);
|
||||
service_ = service;
|
||||
}
|
||||
|
||||
void Registrar::Reset() {
|
||||
RemoveAll();
|
||||
service_ = nullptr;
|
||||
}
|
||||
|
||||
void Registrar::RemoveAll() {
|
||||
if (!name_observers_.empty()) {
|
||||
for (auto& [name, registrations] : name_observers_) {
|
||||
service_->RemovePrefObserver(name, this);
|
||||
for (auto& registration : registrations) {
|
||||
registration.Detach();
|
||||
}
|
||||
}
|
||||
name_observers_.clear();
|
||||
}
|
||||
|
||||
if (!all_observers_.empty()) {
|
||||
service_->RemovePrefObserverAllPrefs(this);
|
||||
for (auto& registration : all_observers_) {
|
||||
registration.Detach();
|
||||
}
|
||||
all_observers_.Clear();
|
||||
}
|
||||
}
|
||||
|
||||
bool Registrar::IsEmpty() const {
|
||||
return name_observers_.empty() && all_observers_.empty();
|
||||
}
|
||||
|
||||
CefRefPtr<CefRegistration> Registrar::AddObserver(
|
||||
const CefString& name,
|
||||
CefRefPtr<CefPreferenceObserver> observer) {
|
||||
CHECK(service_);
|
||||
|
||||
RegistrationImpl* impl = new RegistrationImpl(this, name, observer);
|
||||
|
||||
if (name.empty()) {
|
||||
if (all_observers_.empty()) {
|
||||
service_->AddPrefObserverAllPrefs(this);
|
||||
}
|
||||
all_observers_.AddObserver(impl);
|
||||
} else {
|
||||
const std::string& name_str = name.ToString();
|
||||
if (!name_observers_.contains(name_str)) {
|
||||
service_->AddPrefObserver(name_str, this);
|
||||
}
|
||||
name_observers_[name_str].AddObserver(impl);
|
||||
}
|
||||
|
||||
return impl;
|
||||
}
|
||||
|
||||
void Registrar::RemoveObserver(std::string_view name,
|
||||
Registration* registration) {
|
||||
CHECK(service_);
|
||||
|
||||
if (name.empty()) {
|
||||
all_observers_.RemoveObserver(registration);
|
||||
if (all_observers_.empty()) {
|
||||
service_->RemovePrefObserverAllPrefs(this);
|
||||
}
|
||||
} else {
|
||||
auto it = name_observers_.find(std::string(name));
|
||||
DCHECK(it != name_observers_.end());
|
||||
it->second.RemoveObserver(registration);
|
||||
if (it->second.empty()) {
|
||||
name_observers_.erase(it);
|
||||
service_->RemovePrefObserver(name, this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Registrar::OnPreferenceChanged(PrefService* service,
|
||||
std::string_view pref_name) {
|
||||
std::string pref_name_str(pref_name);
|
||||
if (!name_observers_.empty()) {
|
||||
auto it = name_observers_.find(pref_name_str);
|
||||
if (it != name_observers_.end()) {
|
||||
for (Registration& registration : it->second) {
|
||||
registration.RunCallback();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!all_observers_.empty()) {
|
||||
CefString name_str(pref_name_str);
|
||||
for (Registration& registration : all_observers_) {
|
||||
registration.RunCallback(name_str);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace pref_helper
|
||||
|
@@ -5,8 +5,16 @@
|
||||
#ifndef CEF_LIBCEF_BROWSER_PREFS_PREF_HELPER_H_
|
||||
#define CEF_LIBCEF_BROWSER_PREFS_PREF_HELPER_H_
|
||||
|
||||
#include "cef/include/cef_values.h"
|
||||
#include <unordered_map>
|
||||
|
||||
#include "base/memory/raw_ptr.h"
|
||||
#include "base/observer_list.h"
|
||||
#include "cef/include/cef_registration.h"
|
||||
#include "cef/include/cef_values.h"
|
||||
#include "components/prefs/pref_observer.h"
|
||||
|
||||
class CefPreferenceObserver;
|
||||
class CefRegistration;
|
||||
class PrefService;
|
||||
|
||||
namespace pref_helper {
|
||||
@@ -28,6 +36,69 @@ bool SetPreference(PrefService* pref_service,
|
||||
CefRefPtr<CefValue> value,
|
||||
CefString& error);
|
||||
|
||||
class Registration : public base::CheckedObserver {
|
||||
public:
|
||||
virtual void Detach() = 0;
|
||||
virtual void RunCallback() const = 0;
|
||||
virtual void RunCallback(const CefString& name) const = 0;
|
||||
};
|
||||
|
||||
class RegistrationImpl;
|
||||
|
||||
// Automatically manages the registration of one or more CefPreferenceObserver
|
||||
// objects with a PrefService. When the Registrar is destroyed, all registered
|
||||
// observers are automatically unregistered with the PrefService. Loosely based
|
||||
// on PrefChangeRegistrar.
|
||||
class Registrar final : public PrefObserver {
|
||||
public:
|
||||
Registrar() = default;
|
||||
|
||||
Registrar(const Registrar&) = delete;
|
||||
Registrar& operator=(const Registrar&) = delete;
|
||||
|
||||
~Registrar();
|
||||
|
||||
// Must be called before adding or removing observers. Can be called more
|
||||
// than once as long as the value of |service| doesn't change.
|
||||
void Init(PrefService* service);
|
||||
|
||||
// Removes all observers and clears the reference to the PrefService.
|
||||
// `Init` must be called before adding or removing any observers.
|
||||
void Reset();
|
||||
|
||||
// Removes all observers that have been previously added with a call to Add.
|
||||
void RemoveAll();
|
||||
|
||||
// Returns true if no observers are registered.
|
||||
bool IsEmpty() const;
|
||||
|
||||
// Adds a pref |observer| for the specified pref |name|. All registered
|
||||
// observers will be automatically unregistered and detached when the
|
||||
// Registrar's destructor is called.
|
||||
CefRefPtr<CefRegistration> AddObserver(
|
||||
const CefString& name,
|
||||
CefRefPtr<CefPreferenceObserver> observer);
|
||||
|
||||
private:
|
||||
friend class RegistrationImpl;
|
||||
|
||||
void RemoveObserver(std::string_view name, Registration* registration);
|
||||
|
||||
// PrefObserver:
|
||||
void OnPreferenceChanged(PrefService* service,
|
||||
std::string_view pref_name) override;
|
||||
|
||||
raw_ptr<PrefService, AcrossTasksDanglingUntriaged> service_ = nullptr;
|
||||
|
||||
// Observers registered for a preference by name.
|
||||
using ObserverMap =
|
||||
std::unordered_map<std::string, base::ObserverList<Registration>>;
|
||||
ObserverMap name_observers_;
|
||||
|
||||
// Observers registered for all preferences.
|
||||
base::ObserverList<Registration> all_observers_;
|
||||
};
|
||||
|
||||
} // namespace pref_helper
|
||||
|
||||
#endif // CEF_LIBCEF_BROWSER_PREFS_PREF_HELPER_H_
|
||||
|
@@ -10,7 +10,9 @@
|
||||
#include "cef/libcef/browser/browser_context.h"
|
||||
#include "cef/libcef/browser/context.h"
|
||||
#include "cef/libcef/browser/prefs/pref_helper.h"
|
||||
#include "cef/libcef/browser/setting_helper.h"
|
||||
#include "cef/libcef/browser/thread_util.h"
|
||||
#include "cef/libcef/common/api_version_util.h"
|
||||
#include "cef/libcef/common/app_manager.h"
|
||||
#include "cef/libcef/common/task_runner_impl.h"
|
||||
#include "cef/libcef/common/values_impl.h"
|
||||
@@ -459,6 +461,22 @@ bool CefRequestContextImpl::SetPreference(const CefString& name,
|
||||
return pref_helper::SetPreference(pref_service, name, value, error);
|
||||
}
|
||||
|
||||
CefRefPtr<CefRegistration> CefRequestContextImpl::AddPreferenceObserver(
|
||||
const CefString& name,
|
||||
CefRefPtr<CefPreferenceObserver> observer) {
|
||||
CEF_API_REQUIRE_ADDED(13401);
|
||||
if (!VerifyBrowserContext()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (!pref_registrar_) {
|
||||
pref_registrar_ = std::make_unique<pref_helper::Registrar>();
|
||||
pref_registrar_->Init(browser_context()->AsProfile()->GetPrefs());
|
||||
}
|
||||
|
||||
return pref_registrar_->AddObserver(name, observer);
|
||||
}
|
||||
|
||||
void CefRequestContextImpl::ClearCertificateExceptions(
|
||||
CefRefPtr<CefCompletionCallback> callback) {
|
||||
GetBrowserContext(
|
||||
@@ -588,6 +606,26 @@ void CefRequestContextImpl::SetContentSetting(
|
||||
requesting_url, top_level_url, content_type, value));
|
||||
}
|
||||
|
||||
CefRefPtr<CefRegistration> CefRequestContextImpl::AddSettingObserver(
|
||||
CefRefPtr<CefSettingObserver> observer) {
|
||||
CEF_API_REQUIRE_ADDED(13401);
|
||||
if (!VerifyBrowserContext()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (!setting_registrar_) {
|
||||
auto* settings_map = HostContentSettingsMapFactory::GetForProfile(
|
||||
browser_context()->AsProfile());
|
||||
if (!settings_map) {
|
||||
return nullptr;
|
||||
}
|
||||
setting_registrar_ = std::make_unique<setting_helper::Registrar>();
|
||||
setting_registrar_->Init(settings_map);
|
||||
}
|
||||
|
||||
return setting_registrar_->AddObserver(observer);
|
||||
}
|
||||
|
||||
void CefRequestContextImpl::SetChromeColorScheme(cef_color_variant_t variant,
|
||||
cef_color_t user_color) {
|
||||
GetBrowserContext(
|
||||
|
@@ -17,6 +17,14 @@ namespace content {
|
||||
struct GlobalRenderFrameHostId;
|
||||
}
|
||||
|
||||
namespace pref_helper {
|
||||
class Registrar;
|
||||
}
|
||||
|
||||
namespace setting_helper {
|
||||
class Registrar;
|
||||
}
|
||||
|
||||
class CefBrowserContext;
|
||||
|
||||
// Implementation of the CefRequestContext interface. All methods are thread-
|
||||
@@ -80,6 +88,20 @@ class CefRequestContextImpl : public CefRequestContext {
|
||||
scoped_refptr<base::SingleThreadTaskRunner> task_runner,
|
||||
BrowserContextCallback callback);
|
||||
|
||||
// CefPreferenceManager methods.
|
||||
bool HasPreference(const CefString& name) override;
|
||||
CefRefPtr<CefValue> GetPreference(const CefString& name) override;
|
||||
CefRefPtr<CefDictionaryValue> GetAllPreferences(
|
||||
bool include_defaults) override;
|
||||
bool CanSetPreference(const CefString& name) override;
|
||||
bool SetPreference(const CefString& name,
|
||||
CefRefPtr<CefValue> value,
|
||||
CefString& error) override;
|
||||
CefRefPtr<CefRegistration> AddPreferenceObserver(
|
||||
const CefString& name,
|
||||
CefRefPtr<CefPreferenceObserver> observer) override;
|
||||
|
||||
// CefRequestContext methods.
|
||||
bool IsSame(CefRefPtr<CefRequestContext> other) override;
|
||||
bool IsSharingWith(CefRefPtr<CefRequestContext> other) override;
|
||||
bool IsGlobal() override;
|
||||
@@ -92,14 +114,6 @@ class CefRequestContextImpl : public CefRequestContext {
|
||||
const CefString& domain_name,
|
||||
CefRefPtr<CefSchemeHandlerFactory> factory) override;
|
||||
bool ClearSchemeHandlerFactories() override;
|
||||
bool HasPreference(const CefString& name) override;
|
||||
CefRefPtr<CefValue> GetPreference(const CefString& name) override;
|
||||
CefRefPtr<CefDictionaryValue> GetAllPreferences(
|
||||
bool include_defaults) override;
|
||||
bool CanSetPreference(const CefString& name) override;
|
||||
bool SetPreference(const CefString& name,
|
||||
CefRefPtr<CefValue> value,
|
||||
CefString& error) override;
|
||||
void ClearCertificateExceptions(
|
||||
CefRefPtr<CefCompletionCallback> callback) override;
|
||||
void ClearHttpAuthCredentials(
|
||||
@@ -125,6 +139,8 @@ class CefRequestContextImpl : public CefRequestContext {
|
||||
const CefString& top_level_url,
|
||||
cef_content_setting_types_t content_type,
|
||||
cef_content_setting_values_t value) override;
|
||||
CefRefPtr<CefRegistration> AddSettingObserver(
|
||||
CefRefPtr<CefSettingObserver> observer) override;
|
||||
void SetChromeColorScheme(cef_color_variant_t variant,
|
||||
cef_color_t user_color) override;
|
||||
cef_color_variant_t GetChromeColorSchemeMode() override;
|
||||
@@ -218,6 +234,9 @@ class CefRequestContextImpl : public CefRequestContext {
|
||||
|
||||
Config config_;
|
||||
|
||||
std::unique_ptr<pref_helper::Registrar> pref_registrar_;
|
||||
std::unique_ptr<setting_helper::Registrar> setting_registrar_;
|
||||
|
||||
IMPLEMENT_REFCOUNTING_DELETE_ON_UIT(CefRequestContextImpl);
|
||||
};
|
||||
|
||||
|
118
libcef/browser/setting_helper.cc
Normal file
118
libcef/browser/setting_helper.cc
Normal file
@@ -0,0 +1,118 @@
|
||||
// Copyright (c) 2025 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 "cef/libcef/browser/setting_helper.h"
|
||||
|
||||
#include "cef/include/cef_request_context.h"
|
||||
#include "cef/libcef/browser/thread_util.h"
|
||||
#include "components/content_settings/core/browser/host_content_settings_map.h"
|
||||
#include "url/gurl.h"
|
||||
|
||||
namespace setting_helper {
|
||||
|
||||
class RegistrationImpl final : public Registration, public CefRegistration {
|
||||
public:
|
||||
RegistrationImpl(Registrar* registrar, CefRefPtr<CefSettingObserver> observer)
|
||||
: registrar_(registrar), observer_(observer) {
|
||||
DCHECK(registrar_);
|
||||
DCHECK(observer_);
|
||||
}
|
||||
|
||||
RegistrationImpl(const RegistrationImpl&) = delete;
|
||||
RegistrationImpl& operator=(const RegistrationImpl&) = delete;
|
||||
|
||||
~RegistrationImpl() override {
|
||||
CEF_REQUIRE_UIT();
|
||||
if (registrar_) {
|
||||
registrar_->RemoveObserver(this);
|
||||
}
|
||||
}
|
||||
|
||||
void Detach() override {
|
||||
registrar_ = nullptr;
|
||||
observer_ = nullptr;
|
||||
}
|
||||
|
||||
void RunCallback(const CefString& requesting_url,
|
||||
const CefString& top_level_url,
|
||||
cef_content_setting_types_t content_type) const override {
|
||||
observer_->OnSettingChanged(requesting_url, top_level_url, content_type);
|
||||
}
|
||||
|
||||
private:
|
||||
raw_ptr<Registrar> registrar_;
|
||||
CefRefPtr<CefSettingObserver> observer_;
|
||||
|
||||
IMPLEMENT_REFCOUNTING_DELETE_ON_UIT(RegistrationImpl);
|
||||
};
|
||||
|
||||
Registrar::~Registrar() {
|
||||
RemoveAll();
|
||||
}
|
||||
|
||||
void Registrar::Init(HostContentSettingsMap* settings) {
|
||||
DCHECK(settings);
|
||||
DCHECK(IsEmpty() || settings_ == settings);
|
||||
settings_ = settings;
|
||||
}
|
||||
|
||||
void Registrar::Reset() {
|
||||
RemoveAll();
|
||||
settings_ = nullptr;
|
||||
}
|
||||
|
||||
void Registrar::RemoveAll() {
|
||||
if (!observers_.empty()) {
|
||||
settings_->RemoveObserver(this);
|
||||
for (auto& registration : observers_) {
|
||||
registration.Detach();
|
||||
}
|
||||
observers_.Clear();
|
||||
}
|
||||
}
|
||||
|
||||
bool Registrar::IsEmpty() const {
|
||||
return observers_.empty();
|
||||
}
|
||||
|
||||
CefRefPtr<CefRegistration> Registrar::AddObserver(
|
||||
CefRefPtr<CefSettingObserver> observer) {
|
||||
CHECK(settings_);
|
||||
|
||||
RegistrationImpl* impl = new RegistrationImpl(this, observer);
|
||||
|
||||
if (observers_.empty()) {
|
||||
settings_->AddObserver(this);
|
||||
}
|
||||
observers_.AddObserver(impl);
|
||||
|
||||
return impl;
|
||||
}
|
||||
|
||||
void Registrar::RemoveObserver(Registration* registration) {
|
||||
CHECK(settings_);
|
||||
|
||||
observers_.RemoveObserver(registration);
|
||||
if (observers_.empty()) {
|
||||
settings_->RemoveObserver(this);
|
||||
}
|
||||
}
|
||||
|
||||
void Registrar::OnContentSettingChanged(
|
||||
const ContentSettingsPattern& primary_pattern,
|
||||
const ContentSettingsPattern& secondary_pattern,
|
||||
ContentSettingsTypeSet content_type_set) {
|
||||
DCHECK(!IsEmpty());
|
||||
|
||||
const CefString requesting_url(primary_pattern.ToRepresentativeUrl().spec());
|
||||
const CefString top_level_url(secondary_pattern.ToRepresentativeUrl().spec());
|
||||
const auto content_type =
|
||||
static_cast<cef_content_setting_types_t>(content_type_set.GetType());
|
||||
|
||||
for (Registration& registration : observers_) {
|
||||
registration.RunCallback(requesting_url, top_level_url, content_type);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace setting_helper
|
81
libcef/browser/setting_helper.h
Normal file
81
libcef/browser/setting_helper.h
Normal file
@@ -0,0 +1,81 @@
|
||||
// Copyright (c) 2025 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_SETTING_HELPER_H_
|
||||
#define CEF_LIBCEF_BROWSER_SETTING_HELPER_H_
|
||||
|
||||
#include "base/memory/raw_ptr.h"
|
||||
#include "base/observer_list.h"
|
||||
#include "cef/include/cef_registration.h"
|
||||
#include "components/content_settings/core/browser/content_settings_observer.h"
|
||||
|
||||
class CefSettingObserver;
|
||||
class CefRegistration;
|
||||
class HostContentSettingsMap;
|
||||
|
||||
namespace setting_helper {
|
||||
|
||||
class Registration : public base::CheckedObserver {
|
||||
public:
|
||||
virtual void Detach() = 0;
|
||||
virtual void RunCallback(const CefString& requesting_url,
|
||||
const CefString& top_level_url,
|
||||
cef_content_setting_types_t content_type) const = 0;
|
||||
};
|
||||
|
||||
class RegistrationImpl;
|
||||
|
||||
// Automatically manages the registration of one or more CefSettingObserver
|
||||
// objects with a HostContentSettingsMap. When the Registrar is destroyed, all
|
||||
// registered observers are automatically unregistered with the
|
||||
// HostContentSettingsMap. Loosely based on PrefChangeRegistrar.
|
||||
class Registrar final : public content_settings::Observer {
|
||||
public:
|
||||
Registrar() = default;
|
||||
|
||||
Registrar(const Registrar&) = delete;
|
||||
Registrar& operator=(const Registrar&) = delete;
|
||||
|
||||
~Registrar();
|
||||
|
||||
// Must be called before adding or removing observers. Can be called more
|
||||
// than once as long as the value of |settings| doesn't change.
|
||||
void Init(HostContentSettingsMap* settings);
|
||||
|
||||
// Removes all observers and clears the reference to the
|
||||
// HostContentSettingsMap. `Init` must be called before adding or removing any
|
||||
// observers.
|
||||
void Reset();
|
||||
|
||||
// Removes all observers that have been previously added with a call to Add.
|
||||
void RemoveAll();
|
||||
|
||||
// Returns true if no observers are registered.
|
||||
bool IsEmpty() const;
|
||||
|
||||
// Adds a setting observer. All registered observers will be automatically
|
||||
// unregistered and detached when the Registrar's destructor is called.
|
||||
CefRefPtr<CefRegistration> AddObserver(
|
||||
CefRefPtr<CefSettingObserver> observer);
|
||||
|
||||
private:
|
||||
friend class RegistrationImpl;
|
||||
|
||||
void RemoveObserver(Registration* registration);
|
||||
|
||||
// content_settings::Observer:
|
||||
void OnContentSettingChanged(
|
||||
const ContentSettingsPattern& primary_pattern,
|
||||
const ContentSettingsPattern& secondary_pattern,
|
||||
ContentSettingsTypeSet content_type_set) override;
|
||||
|
||||
raw_ptr<HostContentSettingsMap, AcrossTasksDanglingUntriaged> settings_ =
|
||||
nullptr;
|
||||
|
||||
base::ObserverList<Registration> observers_;
|
||||
};
|
||||
|
||||
} // namespace setting_helper
|
||||
|
||||
#endif // CEF_LIBCEF_BROWSER_SETTING_HELPER_H_
|
@@ -48,23 +48,23 @@ CEF_EXPORT int cef_version_info(int entry) {
|
||||
#include "cef/libcef_dll/cef_api_versions.inc"
|
||||
|
||||
CEF_EXPORT const char* cef_api_hash(int version, int entry) {
|
||||
static const ApiVersionHash* hash = nullptr;
|
||||
static const ApiVersionHash* current_version_hash = nullptr;
|
||||
|
||||
// Initialize on the first successful lookup.
|
||||
if (!hash) {
|
||||
for (size_t i = 0; i < kApiVersionHashesSize; ++i) {
|
||||
if (version == kApiVersionHashes[i].version) {
|
||||
hash = &kApiVersionHashes[i];
|
||||
if (!current_version_hash) {
|
||||
for (const auto& version_hash : kApiVersionHashes) {
|
||||
if (version == version_hash.version) {
|
||||
current_version_hash = &version_hash;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (hash) {
|
||||
if (current_version_hash) {
|
||||
g_version = version;
|
||||
}
|
||||
}
|
||||
|
||||
if (!hash) {
|
||||
if (!current_version_hash) {
|
||||
LOG(ERROR) << "Request for unsupported CEF API version " << version;
|
||||
return nullptr;
|
||||
}
|
||||
@@ -76,9 +76,8 @@ CEF_EXPORT const char* cef_api_hash(int version, int entry) {
|
||||
|
||||
switch (entry) {
|
||||
case 0:
|
||||
return hash->platform;
|
||||
case 1:
|
||||
return hash->universal;
|
||||
return current_version_hash->hash;
|
||||
case 2:
|
||||
return CEF_COMMIT_HASH;
|
||||
default:
|
||||
@@ -97,9 +96,8 @@ CEF_EXPORT int cef_id_for_pack_resource_name(const char* name) {
|
||||
|
||||
// Initialize on the first call.
|
||||
if (string_to_id_map->empty()) {
|
||||
for (size_t i = 0; i < kIdNamesPackResourcesSize; ++i) {
|
||||
(*string_to_id_map)[kIdNamesPackResources[i].name] =
|
||||
kIdNamesPackResources[i].id;
|
||||
for (const auto& pack_resource : kIdNamesPackResources) {
|
||||
(*string_to_id_map)[pack_resource.name] = pack_resource.id;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -119,9 +117,8 @@ CEF_EXPORT int cef_id_for_pack_string_name(const char* name) {
|
||||
|
||||
// Initialize on the first call.
|
||||
if (string_to_id_map->empty()) {
|
||||
for (size_t i = 0; i < kIdNamesPackStringsSize; ++i) {
|
||||
(*string_to_id_map)[kIdNamesPackStrings[i].name] =
|
||||
kIdNamesPackStrings[i].id;
|
||||
for (const auto& pack_string : kIdNamesPackStrings) {
|
||||
(*string_to_id_map)[pack_string.name] = pack_string.id;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -141,9 +138,8 @@ CEF_EXPORT int cef_id_for_command_id_name(const char* name) {
|
||||
|
||||
// Initialize on the first call.
|
||||
if (string_to_id_map->empty()) {
|
||||
for (size_t i = 0; i < kIdNamesCommandIdsSize; ++i) {
|
||||
(*string_to_id_map)[kIdNamesCommandIds[i].name] =
|
||||
kIdNamesCommandIds[i].id;
|
||||
for (const auto& command : kIdNamesCommandIds) {
|
||||
(*string_to_id_map)[command.name] = command.id;
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -764,5 +764,14 @@ patches = [
|
||||
# Expose Mojo Connector error state to Receiver disconnect handlers.
|
||||
# https://github.com/chromiumembedded/cef/issues/3664
|
||||
'name': 'mojo_connect_result_3664'
|
||||
},
|
||||
{
|
||||
# Support for configuration accessors/observers.
|
||||
# - Allow pref_service::Registrar access to
|
||||
# PrefService::[Add|Remove]PrefObserver.
|
||||
# - Enable SyntheticTrialsActiveGroupIdProvider::GetGroups in Release
|
||||
# builds.
|
||||
# https://github.com/chromiumembedded/cef/issues/3892
|
||||
'name': 'config_3892'
|
||||
}
|
||||
]
|
||||
|
@@ -20,7 +20,7 @@ index 53a73d6c75b7a..05290de4c03a0 100644
|
||||
|
||||
// Make an exception to allow most visited tiles to commit in third-party
|
||||
diff --git content/browser/renderer_host/navigation_request.cc content/browser/renderer_host/navigation_request.cc
|
||||
index 84b894ac879b5..07d5b00e53e31 100644
|
||||
index e51bcccd6f63f..a4250481a396e 100644
|
||||
--- content/browser/renderer_host/navigation_request.cc
|
||||
+++ content/browser/renderer_host/navigation_request.cc
|
||||
@@ -8358,10 +8358,22 @@ NavigationRequest::GetOriginForURLLoaderFactoryBeforeResponseWithDebugInfo(
|
||||
|
@@ -1,5 +1,5 @@
|
||||
diff --git chrome/browser/BUILD.gn chrome/browser/BUILD.gn
|
||||
index 9f293f4ddd146..e9b20e7c5f39d 100644
|
||||
index ab4deb1a228f5..c98b27c19a611 100644
|
||||
--- chrome/browser/BUILD.gn
|
||||
+++ chrome/browser/BUILD.gn
|
||||
@@ -11,6 +11,7 @@ import("//build/config/compiler/pgo/pgo.gni")
|
||||
@@ -10,7 +10,7 @@ index 9f293f4ddd146..e9b20e7c5f39d 100644
|
||||
import("//chrome/browser/buildflags.gni")
|
||||
import("//chrome/browser/downgrade/buildflags.gni")
|
||||
import("//chrome/browser/request_header_integrity/buildflags.gni")
|
||||
@@ -1838,6 +1839,7 @@ static_library("browser") {
|
||||
@@ -1844,6 +1845,7 @@ static_library("browser") {
|
||||
"//build/config/compiler:compiler_buildflags",
|
||||
"//build/config/linux/dbus:buildflags",
|
||||
"//cc",
|
||||
@@ -18,7 +18,7 @@ index 9f293f4ddd146..e9b20e7c5f39d 100644
|
||||
"//chrome:extra_resources",
|
||||
"//chrome:resources",
|
||||
"//chrome:strings",
|
||||
@@ -2524,6 +2526,10 @@ static_library("browser") {
|
||||
@@ -2530,6 +2532,10 @@ static_library("browser") {
|
||||
sources += [ "net/net_error_diagnostics_dialog_stub.cc" ]
|
||||
}
|
||||
|
||||
|
@@ -648,3 +648,59 @@ index f12ba73369a65..23c43dcb1dd24 100644
|
||||
NavigateParams params(browser, std::move(new_contents));
|
||||
params.source_contents = source_contents;
|
||||
params.url = target_url;
|
||||
diff --git chrome/browser/ui/browser_window/browser_window_features.cc chrome/browser/ui/browser_window/browser_window_features.cc
|
||||
index e584d77d67bda..a38a8504abd85 100644
|
||||
--- chrome/browser/ui/browser_window/browser_window_features.cc
|
||||
+++ chrome/browser/ui/browser_window/browser_window_features.cc
|
||||
@@ -67,6 +67,14 @@ BrowserWindowFeatures::BrowserWindowFeaturesFactory& GetFactory() {
|
||||
return *factory;
|
||||
}
|
||||
|
||||
+bool IsNormalBrowser(Browser* browser) {
|
||||
+ // CEF normal browsers have TYPE_POPUP.
|
||||
+ if (browser->is_type_popup() && browser->cef_delegate()) {
|
||||
+ return true;
|
||||
+ }
|
||||
+ return browser->is_type_normal();
|
||||
+}
|
||||
+
|
||||
} // namespace
|
||||
|
||||
// static
|
||||
@@ -153,10 +161,12 @@ void BrowserWindowFeatures::Init(BrowserWindowInterface* browser) {
|
||||
}
|
||||
|
||||
void BrowserWindowFeatures::InitPostWindowConstruction(Browser* browser) {
|
||||
+ const bool supports_toolbar = IsNormalBrowser(browser);
|
||||
+
|
||||
// Features that are only enabled for normal browser windows (e.g. a window
|
||||
// with an omnibox and a tab strip). By default most features should be
|
||||
// instantiated in this block.
|
||||
- if (browser->is_type_normal()) {
|
||||
+ if (supports_toolbar) {
|
||||
if (IsChromeLabsEnabled()) {
|
||||
chrome_labs_coordinator_ =
|
||||
std::make_unique<ChromeLabsCoordinator>(browser);
|
||||
@@ -198,7 +208,7 @@ void BrowserWindowFeatures::InitPostWindowConstruction(Browser* browser) {
|
||||
}
|
||||
}
|
||||
|
||||
- if ((browser->is_type_normal() || browser->is_type_app()) &&
|
||||
+ if ((supports_toolbar || browser->is_type_app()) &&
|
||||
base::FeatureList::IsEnabled(toast_features::kToastFramework)) {
|
||||
toast_service_ = std::make_unique<ToastService>(browser);
|
||||
}
|
||||
@@ -231,10 +241,12 @@ void BrowserWindowFeatures::InitPostBrowserViewConstruction(
|
||||
browser_view->browser(),
|
||||
side_panel_coordinator_->GetWindowRegistry());
|
||||
|
||||
+ const bool supports_toolbar = IsNormalBrowser(browser_view->browser());
|
||||
+
|
||||
// Memory Saver mode is default off but is available to turn on.
|
||||
// The controller relies on performance manager which isn't initialized in
|
||||
// some unit tests without browser view.
|
||||
- if (browser_view->GetIsNormalType()) {
|
||||
+ if (supports_toolbar) {
|
||||
memory_saver_opt_in_iph_controller_ =
|
||||
std::make_unique<MemorySaverOptInIPHController>(
|
||||
browser_view->browser());
|
||||
|
@@ -1,5 +1,5 @@
|
||||
diff --git chrome/browser/renderer_context_menu/render_view_context_menu.cc chrome/browser/renderer_context_menu/render_view_context_menu.cc
|
||||
index 58add8ca095aa..9fe7728f8ccad 100644
|
||||
index b14b639735870..0cba06a45f327 100644
|
||||
--- chrome/browser/renderer_context_menu/render_view_context_menu.cc
|
||||
+++ chrome/browser/renderer_context_menu/render_view_context_menu.cc
|
||||
@@ -352,6 +352,18 @@ base::OnceCallback<void(RenderViewContextMenu*)>* GetMenuShownCallback() {
|
||||
@@ -136,7 +136,7 @@ index cb51224f9892c..b5a3946999d8f 100644
|
||||
private:
|
||||
// RenderViewContextMenuViewsMac:
|
||||
diff --git chrome/browser/ui/cocoa/renderer_context_menu/render_view_context_menu_mac_cocoa.mm chrome/browser/ui/cocoa/renderer_context_menu/render_view_context_menu_mac_cocoa.mm
|
||||
index 2e34cf104fbe6..850489d12a458 100644
|
||||
index 5e266a42d3df6..e57211944d6a6 100644
|
||||
--- chrome/browser/ui/cocoa/renderer_context_menu/render_view_context_menu_mac_cocoa.mm
|
||||
+++ chrome/browser/ui/cocoa/renderer_context_menu/render_view_context_menu_mac_cocoa.mm
|
||||
@@ -70,6 +70,10 @@ RenderViewContextMenuMacCocoa::~RenderViewContextMenuMacCocoa() {
|
||||
@@ -150,7 +150,7 @@ index 2e34cf104fbe6..850489d12a458 100644
|
||||
views::Widget* widget = views::Widget::GetTopLevelWidgetForNativeView(
|
||||
source_web_contents_->GetNativeView());
|
||||
|
||||
@@ -94,6 +98,10 @@ void RenderViewContextMenuMacCocoa::Show() {
|
||||
@@ -95,6 +99,10 @@ void RenderViewContextMenuMacCocoa::Show() {
|
||||
views::ElementTrackerViews::GetContextForWidget(widget));
|
||||
}
|
||||
|
||||
|
@@ -34,10 +34,10 @@ index f61ec524109fe..92ca490728855 100644
|
||||
|
||||
WebViewGuestDelegate* ChromeExtensionsAPIClient::CreateWebViewGuestDelegate(
|
||||
diff --git chrome/browser/extensions/api/tabs/tabs_api.cc chrome/browser/extensions/api/tabs/tabs_api.cc
|
||||
index d19671bad0e0d..639a1737a0ef5 100644
|
||||
index b3921038447a8..dd5225f5e7227 100644
|
||||
--- chrome/browser/extensions/api/tabs/tabs_api.cc
|
||||
+++ chrome/browser/extensions/api/tabs/tabs_api.cc
|
||||
@@ -1674,7 +1674,7 @@ ExtensionFunction::ResponseAction TabsUpdateFunction::Run() {
|
||||
@@ -1680,7 +1680,7 @@ ExtensionFunction::ResponseAction TabsUpdateFunction::Run() {
|
||||
return RespondNow(Error(ExtensionTabUtil::kTabStripNotEditableError));
|
||||
}
|
||||
|
||||
@@ -46,7 +46,7 @@ index d19671bad0e0d..639a1737a0ef5 100644
|
||||
tab_strip->ActivateTabAt(tab_index);
|
||||
DCHECK_EQ(contents, tab_strip->GetActiveWebContents());
|
||||
}
|
||||
@@ -1688,7 +1688,7 @@ ExtensionFunction::ResponseAction TabsUpdateFunction::Run() {
|
||||
@@ -1694,7 +1694,7 @@ ExtensionFunction::ResponseAction TabsUpdateFunction::Run() {
|
||||
}
|
||||
|
||||
bool highlighted = *params->update_properties.highlighted;
|
||||
@@ -55,7 +55,7 @@ index d19671bad0e0d..639a1737a0ef5 100644
|
||||
tab_strip->ToggleSelectionAt(tab_index);
|
||||
}
|
||||
}
|
||||
@@ -1700,7 +1700,7 @@ ExtensionFunction::ResponseAction TabsUpdateFunction::Run() {
|
||||
@@ -1706,7 +1706,7 @@ ExtensionFunction::ResponseAction TabsUpdateFunction::Run() {
|
||||
kCannotUpdateMuteCaptured, base::NumberToString(tab_id))));
|
||||
}
|
||||
|
||||
@@ -64,7 +64,7 @@ index d19671bad0e0d..639a1737a0ef5 100644
|
||||
int opener_id = *params->update_properties.opener_tab_id;
|
||||
WebContents* opener_contents = nullptr;
|
||||
if (opener_id == tab_id) {
|
||||
@@ -1735,7 +1735,7 @@ ExtensionFunction::ResponseAction TabsUpdateFunction::Run() {
|
||||
@@ -1741,7 +1741,7 @@ ExtensionFunction::ResponseAction TabsUpdateFunction::Run() {
|
||||
->SetAutoDiscardable(state);
|
||||
}
|
||||
|
||||
@@ -73,7 +73,7 @@ index d19671bad0e0d..639a1737a0ef5 100644
|
||||
// Bug fix for crbug.com/1197888. Don't let the extension update the tab if
|
||||
// the user is dragging tabs.
|
||||
if (!ExtensionTabUtil::IsTabStripEditable()) {
|
||||
@@ -1756,7 +1756,8 @@ ExtensionFunction::ResponseAction TabsUpdateFunction::Run() {
|
||||
@@ -1762,7 +1762,8 @@ ExtensionFunction::ResponseAction TabsUpdateFunction::Run() {
|
||||
// Navigate the tab to a new location if the url is different.
|
||||
if (params->update_properties.url) {
|
||||
std::string updated_url = *params->update_properties.url;
|
||||
@@ -83,7 +83,7 @@ index d19671bad0e0d..639a1737a0ef5 100644
|
||||
!IsURLAllowedInIncognito(GURL(updated_url))) {
|
||||
return RespondNow(Error(ErrorUtils::FormatErrorMessage(
|
||||
tabs_constants::kURLsNotAllowedInIncognitoError, updated_url)));
|
||||
@@ -1771,7 +1772,7 @@ ExtensionFunction::ResponseAction TabsUpdateFunction::Run() {
|
||||
@@ -1777,7 +1778,7 @@ ExtensionFunction::ResponseAction TabsUpdateFunction::Run() {
|
||||
return RespondNow(Error(std::move(error)));
|
||||
}
|
||||
|
||||
|
@@ -17,10 +17,10 @@ index fbce13c16ad10..0512b2f09937e 100644
|
||||
std::unique_ptr<permissions::PermissionPrompt> CreatePermissionPrompt(
|
||||
content::WebContents* web_contents,
|
||||
diff --git chrome/browser/ui/views/permissions/permission_prompt_factory.cc chrome/browser/ui/views/permissions/permission_prompt_factory.cc
|
||||
index 0f19f3eeeea54..20a942f2e4007 100644
|
||||
index ab9701eb9ce8c..7c1dbe9adb0e8 100644
|
||||
--- chrome/browser/ui/views/permissions/permission_prompt_factory.cc
|
||||
+++ chrome/browser/ui/views/permissions/permission_prompt_factory.cc
|
||||
@@ -209,11 +209,28 @@ std::unique_ptr<permissions::PermissionPrompt> CreateQuietPrompt(
|
||||
@@ -210,11 +210,28 @@ std::unique_ptr<permissions::PermissionPrompt> CreateQuietPrompt(
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -1,5 +1,5 @@
|
||||
diff --git chrome/browser/safe_browsing/BUILD.gn chrome/browser/safe_browsing/BUILD.gn
|
||||
index c30c5ab55232d..2380f3595ce71 100644
|
||||
index 31a8d9d259f7b..267ef1c830a69 100644
|
||||
--- chrome/browser/safe_browsing/BUILD.gn
|
||||
+++ chrome/browser/safe_browsing/BUILD.gn
|
||||
@@ -40,6 +40,7 @@ static_library("safe_browsing") {
|
||||
|
@@ -592,7 +592,7 @@ index 388954e9b504a..7fd8d7b36fa04 100644
|
||||
#endif
|
||||
|
||||
diff --git chrome/browser/prefs/browser_prefs.cc chrome/browser/prefs/browser_prefs.cc
|
||||
index dc8800d422a2c..675410378cc6f 100644
|
||||
index 3cc0bb183d1d1..57ea33377a7e4 100644
|
||||
--- chrome/browser/prefs/browser_prefs.cc
|
||||
+++ chrome/browser/prefs/browser_prefs.cc
|
||||
@@ -16,6 +16,7 @@
|
||||
@@ -614,7 +614,7 @@ index dc8800d422a2c..675410378cc6f 100644
|
||||
#if BUILDFLAG(ENABLE_EXTENSIONS)
|
||||
#include "chrome/browser/accessibility/animation_policy_prefs.h"
|
||||
#include "chrome/browser/apps/platform_apps/shortcut_manager.h"
|
||||
@@ -1940,6 +1945,11 @@ void RegisterLocalState(PrefRegistrySimple* registry) {
|
||||
@@ -1937,6 +1942,11 @@ void RegisterLocalState(PrefRegistrySimple* registry) {
|
||||
|
||||
// This is intentionally last.
|
||||
RegisterLocalStatePrefsForMigration(registry);
|
||||
@@ -626,7 +626,7 @@ index dc8800d422a2c..675410378cc6f 100644
|
||||
}
|
||||
|
||||
// Register prefs applicable to all profiles.
|
||||
@@ -2390,6 +2400,10 @@ void RegisterUserProfilePrefs(user_prefs::PrefRegistrySyncable* registry,
|
||||
@@ -2387,6 +2397,10 @@ void RegisterUserProfilePrefs(user_prefs::PrefRegistrySyncable* registry,
|
||||
const std::string& locale) {
|
||||
RegisterProfilePrefs(registry, locale);
|
||||
|
||||
|
@@ -397,10 +397,10 @@ index 3d8a15049d4d2..66c4789581fe1 100644
|
||||
// regenerated.
|
||||
bool RegenerateFrameOnThemeChange(BrowserThemeChangeType theme_change_type);
|
||||
diff --git chrome/browser/ui/views/frame/browser_view.cc chrome/browser/ui/views/frame/browser_view.cc
|
||||
index 127aa3ef3ba70..506cb33978bed 100644
|
||||
index 76c889780c153..80e31b0c2986b 100644
|
||||
--- chrome/browser/ui/views/frame/browser_view.cc
|
||||
+++ chrome/browser/ui/views/frame/browser_view.cc
|
||||
@@ -363,10 +363,6 @@ using web_modal::WebContentsModalDialogHost;
|
||||
@@ -364,10 +364,6 @@ using web_modal::WebContentsModalDialogHost;
|
||||
|
||||
namespace {
|
||||
|
||||
@@ -411,7 +411,7 @@ index 127aa3ef3ba70..506cb33978bed 100644
|
||||
#if BUILDFLAG(IS_CHROMEOS)
|
||||
// UMA histograms that record animation smoothness for tab loading animation.
|
||||
constexpr char kTabLoadingSmoothnessHistogramName[] =
|
||||
@@ -776,6 +772,14 @@ class BrowserViewLayoutDelegateImpl : public BrowserViewLayoutDelegate {
|
||||
@@ -777,6 +773,14 @@ class BrowserViewLayoutDelegateImpl : public BrowserViewLayoutDelegate {
|
||||
return browser_view_->frame()->GetTopInset() - browser_view_->y();
|
||||
}
|
||||
|
||||
@@ -426,7 +426,7 @@ index 127aa3ef3ba70..506cb33978bed 100644
|
||||
bool IsToolbarVisible() const override {
|
||||
return browser_view_->IsToolbarVisible();
|
||||
}
|
||||
@@ -927,11 +931,21 @@ class BrowserView::AccessibilityModeObserver : public ui::AXModeObserver {
|
||||
@@ -928,11 +932,21 @@ class BrowserView::AccessibilityModeObserver : public ui::AXModeObserver {
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// BrowserView, public:
|
||||
|
||||
@@ -449,7 +449,7 @@ index 127aa3ef3ba70..506cb33978bed 100644
|
||||
SetShowIcon(::ShouldShowWindowIcon(
|
||||
browser_.get(), AppUsesWindowControlsOverlay(), AppUsesTabbed()));
|
||||
|
||||
@@ -1071,8 +1085,15 @@ BrowserView::BrowserView(std::unique_ptr<Browser> browser)
|
||||
@@ -1072,8 +1086,15 @@ BrowserView::BrowserView(std::unique_ptr<Browser> browser)
|
||||
watermark_view_));
|
||||
#endif
|
||||
|
||||
@@ -467,7 +467,7 @@ index 127aa3ef3ba70..506cb33978bed 100644
|
||||
|
||||
contents_separator_ =
|
||||
top_container_->AddChildView(std::make_unique<ContentsSeparator>());
|
||||
@@ -1144,7 +1165,9 @@ BrowserView::BrowserView(std::unique_ptr<Browser> browser)
|
||||
@@ -1145,7 +1166,9 @@ BrowserView::BrowserView(std::unique_ptr<Browser> browser)
|
||||
}
|
||||
|
||||
BrowserView::~BrowserView() {
|
||||
@@ -477,7 +477,7 @@ index 127aa3ef3ba70..506cb33978bed 100644
|
||||
|
||||
// Remove the layout manager to avoid dangling. This needs to be earlier than
|
||||
// other cleanups that destroy views referenced in the layout manager.
|
||||
@@ -1156,7 +1179,9 @@ BrowserView::~BrowserView() {
|
||||
@@ -1157,7 +1180,9 @@ BrowserView::~BrowserView() {
|
||||
|
||||
// All the tabs should have been destroyed already. If we were closed by the
|
||||
// OS with some tabs than the NativeBrowserFrame should have destroyed them.
|
||||
@@ -487,7 +487,7 @@ index 127aa3ef3ba70..506cb33978bed 100644
|
||||
|
||||
// Stop the animation timer explicitly here to avoid running it in a nested
|
||||
// message loop, which may run by Browser destructor.
|
||||
@@ -1165,17 +1190,18 @@ BrowserView::~BrowserView() {
|
||||
@@ -1166,17 +1191,18 @@ BrowserView::~BrowserView() {
|
||||
// Immersive mode may need to reparent views before they are removed/deleted.
|
||||
immersive_mode_controller_.reset();
|
||||
|
||||
@@ -510,7 +510,7 @@ index 127aa3ef3ba70..506cb33978bed 100644
|
||||
|
||||
// These are raw pointers to child views, so they need to be set to null
|
||||
// before `RemoveAllChildViews()` is called to avoid dangling.
|
||||
@@ -1800,6 +1826,28 @@ gfx::Point BrowserView::GetThemeOffsetFromBrowserView() const {
|
||||
@@ -1801,6 +1827,28 @@ gfx::Point BrowserView::GetThemeOffsetFromBrowserView() const {
|
||||
ThemeProperties::kFrameHeightAboveTabs - browser_view_origin.y());
|
||||
}
|
||||
|
||||
@@ -539,7 +539,7 @@ index 127aa3ef3ba70..506cb33978bed 100644
|
||||
// static:
|
||||
BrowserView::DevToolsDockedPlacement BrowserView::GetDevToolsDockedPlacement(
|
||||
const gfx::Rect& contents_webview_bounds,
|
||||
@@ -2220,7 +2268,13 @@ void BrowserView::OnExclusiveAccessUserInput() {
|
||||
@@ -2221,7 +2269,13 @@ void BrowserView::OnExclusiveAccessUserInput() {
|
||||
|
||||
bool BrowserView::ShouldHideUIForFullscreen() const {
|
||||
// Immersive mode needs UI for the slide-down top panel.
|
||||
@@ -554,7 +554,7 @@ index 127aa3ef3ba70..506cb33978bed 100644
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -3459,7 +3513,9 @@ DownloadBubbleUIController* BrowserView::GetDownloadBubbleUIController() {
|
||||
@@ -3460,7 +3514,9 @@ DownloadBubbleUIController* BrowserView::GetDownloadBubbleUIController() {
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
@@ -565,7 +565,7 @@ index 127aa3ef3ba70..506cb33978bed 100644
|
||||
if (auto* download_button = toolbar_button_provider_->GetDownloadButton()) {
|
||||
return download_button->bubble_controller();
|
||||
}
|
||||
@@ -4089,7 +4145,8 @@ void BrowserView::ReparentTopContainerForEndOfImmersive() {
|
||||
@@ -4094,7 +4150,8 @@ void BrowserView::ReparentTopContainerForEndOfImmersive() {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -575,7 +575,7 @@ index 127aa3ef3ba70..506cb33978bed 100644
|
||||
top_container()->DestroyLayer();
|
||||
AddChildViewAt(top_container(), 0);
|
||||
EnsureFocusOrder();
|
||||
@@ -4607,11 +4664,38 @@ void BrowserView::GetAccessiblePanes(std::vector<views::View*>* panes) {
|
||||
@@ -4612,11 +4669,38 @@ void BrowserView::GetAccessiblePanes(std::vector<views::View*>* panes) {
|
||||
bool BrowserView::ShouldDescendIntoChildForEventHandling(
|
||||
gfx::NativeView child,
|
||||
const gfx::Point& location) {
|
||||
@@ -616,7 +616,7 @@ index 127aa3ef3ba70..506cb33978bed 100644
|
||||
// Draggable regions are defined relative to the web contents.
|
||||
gfx::Point point_in_contents_web_view_coords(location);
|
||||
views::View::ConvertPointToTarget(GetWidget()->GetRootView(),
|
||||
@@ -4620,7 +4704,7 @@ bool BrowserView::ShouldDescendIntoChildForEventHandling(
|
||||
@@ -4625,7 +4709,7 @@ bool BrowserView::ShouldDescendIntoChildForEventHandling(
|
||||
|
||||
// Draggable regions should be ignored for clicks into any browser view's
|
||||
// owned widgets, for example alerts, permission prompts or find bar.
|
||||
@@ -625,7 +625,7 @@ index 127aa3ef3ba70..506cb33978bed 100644
|
||||
point_in_contents_web_view_coords.x(),
|
||||
point_in_contents_web_view_coords.y()) ||
|
||||
WidgetOwnedByAnchorContainsPoint(point_in_contents_web_view_coords);
|
||||
@@ -4734,8 +4818,10 @@ void BrowserView::Layout(PassKey) {
|
||||
@@ -4739,8 +4823,10 @@ void BrowserView::Layout(PassKey) {
|
||||
|
||||
// TODO(jamescook): Why was this in the middle of layout code?
|
||||
toolbar_->location_bar()->omnibox_view()->SetFocusBehavior(
|
||||
@@ -638,7 +638,7 @@ index 127aa3ef3ba70..506cb33978bed 100644
|
||||
|
||||
// Some of the situations when the BrowserView is laid out are:
|
||||
// - Enter/exit immersive fullscreen mode.
|
||||
@@ -4802,6 +4888,11 @@ void BrowserView::AddedToWidget() {
|
||||
@@ -4807,6 +4893,11 @@ void BrowserView::AddedToWidget() {
|
||||
SetThemeProfileForWindow(GetNativeWindow(), browser_->profile());
|
||||
#endif
|
||||
|
||||
@@ -650,7 +650,7 @@ index 127aa3ef3ba70..506cb33978bed 100644
|
||||
toolbar_->Init();
|
||||
if (download::IsDownloadBubbleEnabled() &&
|
||||
features::IsToolbarPinningEnabled() &&
|
||||
@@ -4849,14 +4940,10 @@ void BrowserView::AddedToWidget() {
|
||||
@@ -4854,14 +4945,10 @@ void BrowserView::AddedToWidget() {
|
||||
|
||||
EnsureFocusOrder();
|
||||
|
||||
@@ -668,7 +668,7 @@ index 127aa3ef3ba70..506cb33978bed 100644
|
||||
using_native_frame_ = frame_->ShouldUseNativeFrame();
|
||||
|
||||
MaybeInitializeWebUITabStrip();
|
||||
@@ -5252,7 +5339,8 @@ void BrowserView::ProcessFullscreen(bool fullscreen, const int64_t display_id) {
|
||||
@@ -5257,7 +5344,8 @@ void BrowserView::ProcessFullscreen(bool fullscreen, const int64_t display_id) {
|
||||
// Undo our anti-jankiness hacks and force a re-layout.
|
||||
in_process_fullscreen_ = false;
|
||||
ToolbarSizeChanged(false);
|
||||
@@ -678,7 +678,7 @@ index 127aa3ef3ba70..506cb33978bed 100644
|
||||
}
|
||||
|
||||
void BrowserView::RequestFullscreen(bool fullscreen, int64_t display_id) {
|
||||
@@ -5748,6 +5836,8 @@ Profile* BrowserView::GetProfile() {
|
||||
@@ -5753,6 +5841,8 @@ Profile* BrowserView::GetProfile() {
|
||||
}
|
||||
|
||||
void BrowserView::UpdateUIForTabFullscreen() {
|
||||
@@ -687,7 +687,7 @@ index 127aa3ef3ba70..506cb33978bed 100644
|
||||
frame()->GetFrameView()->UpdateFullscreenTopUI();
|
||||
}
|
||||
|
||||
@@ -5777,6 +5867,8 @@ bool BrowserView::CanUserEnterFullscreen() const {
|
||||
@@ -5782,6 +5872,8 @@ bool BrowserView::CanUserEnterFullscreen() const {
|
||||
}
|
||||
|
||||
bool BrowserView::CanUserExitFullscreen() const {
|
||||
@@ -738,7 +738,7 @@ index b9986c6e9097d..fc8f781e6ac66 100644
|
||||
// Do not friend BrowserViewLayout. Use the BrowserViewLayoutDelegate
|
||||
// interface to keep these two classes decoupled and testable.
|
||||
diff --git chrome/browser/ui/views/frame/browser_view_layout.cc chrome/browser/ui/views/frame/browser_view_layout.cc
|
||||
index 1376fdf933420..336391e29944c 100644
|
||||
index 46f6be18ac556..be2ce4a9dc6da 100644
|
||||
--- chrome/browser/ui/views/frame/browser_view_layout.cc
|
||||
+++ chrome/browser/ui/views/frame/browser_view_layout.cc
|
||||
@@ -52,6 +52,10 @@
|
||||
|
85
patch/patches/config_3892.patch
Normal file
85
patch/patches/config_3892.patch
Normal file
@@ -0,0 +1,85 @@
|
||||
diff --git components/prefs/pref_service.h components/prefs/pref_service.h
|
||||
index f1856d6ee4419..413b77e80d84d 100644
|
||||
--- components/prefs/pref_service.h
|
||||
+++ components/prefs/pref_service.h
|
||||
@@ -52,6 +52,10 @@ namespace base {
|
||||
class FilePath;
|
||||
}
|
||||
|
||||
+namespace pref_helper {
|
||||
+class Registrar;
|
||||
+}
|
||||
+
|
||||
namespace prefs {
|
||||
class ScopedDictionaryPrefUpdate;
|
||||
}
|
||||
@@ -441,6 +445,8 @@ class COMPONENTS_PREFS_EXPORT PrefService {
|
||||
// declared as a friend, too.
|
||||
friend class PrefChangeRegistrar;
|
||||
friend class subtle::PrefMemberBase;
|
||||
+ // CEF registration manager.
|
||||
+ friend class pref_helper::Registrar;
|
||||
|
||||
// These are protected so they can only be accessed by the friend
|
||||
// classes listed above.
|
||||
diff --git components/variations/synthetic_trials_active_group_id_provider.cc components/variations/synthetic_trials_active_group_id_provider.cc
|
||||
index bd51697297471..3e669cd080457 100644
|
||||
--- components/variations/synthetic_trials_active_group_id_provider.cc
|
||||
+++ components/variations/synthetic_trials_active_group_id_provider.cc
|
||||
@@ -27,7 +27,7 @@ SyntheticTrialsActiveGroupIdProvider::GetActiveGroupIds() {
|
||||
return group_ids_;
|
||||
}
|
||||
|
||||
-#if !defined(NDEBUG)
|
||||
+#if !defined(NDEBUG) || BUILDFLAG(ENABLE_CEF)
|
||||
std::vector<SyntheticTrialGroup>
|
||||
SyntheticTrialsActiveGroupIdProvider::GetGroups() {
|
||||
base::AutoLock scoped_lock(lock_);
|
||||
@@ -38,7 +38,7 @@ SyntheticTrialsActiveGroupIdProvider::GetGroups() {
|
||||
void SyntheticTrialsActiveGroupIdProvider::ResetForTesting() {
|
||||
base::AutoLock scoped_lock(lock_);
|
||||
group_ids_.clear();
|
||||
-#if !defined(NDEBUG)
|
||||
+#if !defined(NDEBUG) || BUILDFLAG(ENABLE_CEF)
|
||||
groups_.clear();
|
||||
#endif // !defined(NDEBUG)
|
||||
}
|
||||
@@ -53,7 +53,7 @@ void SyntheticTrialsActiveGroupIdProvider::OnSyntheticTrialsChanged(
|
||||
for (const auto& group : groups) {
|
||||
group_ids_.push_back(group.id());
|
||||
}
|
||||
-#if !defined(NDEBUG)
|
||||
+#if !defined(NDEBUG) || BUILDFLAG(ENABLE_CEF)
|
||||
groups_ = groups;
|
||||
#endif // !defined(NDEBUG)
|
||||
}
|
||||
diff --git components/variations/synthetic_trials_active_group_id_provider.h components/variations/synthetic_trials_active_group_id_provider.h
|
||||
index b4a999731d996..0bbac173fddf1 100644
|
||||
--- components/variations/synthetic_trials_active_group_id_provider.h
|
||||
+++ components/variations/synthetic_trials_active_group_id_provider.h
|
||||
@@ -10,6 +10,7 @@
|
||||
#include "base/component_export.h"
|
||||
#include "base/synchronization/lock.h"
|
||||
#include "base/thread_annotations.h"
|
||||
+#include "cef/libcef/features/features.h"
|
||||
#include "components/variations/active_field_trials.h"
|
||||
#include "components/variations/synthetic_trials.h"
|
||||
|
||||
@@ -36,7 +37,7 @@ class COMPONENT_EXPORT(VARIATIONS) SyntheticTrialsActiveGroupIdProvider
|
||||
// Returns currently active synthetic trial group IDs.
|
||||
std::vector<ActiveGroupId> GetActiveGroupIds();
|
||||
|
||||
-#if !defined(NDEBUG)
|
||||
+#if !defined(NDEBUG) || BUILDFLAG(ENABLE_CEF)
|
||||
// In debug mode, not only the group IDs are tracked but also the full group
|
||||
// info, to display the names unhashed in chrome://version.
|
||||
std::vector<SyntheticTrialGroup> GetGroups();
|
||||
@@ -60,7 +61,7 @@ class COMPONENT_EXPORT(VARIATIONS) SyntheticTrialsActiveGroupIdProvider
|
||||
|
||||
base::Lock lock_;
|
||||
std::vector<ActiveGroupId> group_ids_; // GUARDED_BY(lock_);
|
||||
-#if !defined(NDEBUG)
|
||||
+#if !defined(NDEBUG) || BUILDFLAG(ENABLE_CEF)
|
||||
// In debug builds, keep the full group information to be able to display it
|
||||
// in chrome://version.
|
||||
std::vector<SyntheticTrialGroup> groups_; // GUARDED_BY(lock_);
|
@@ -1,5 +1,5 @@
|
||||
diff --git content/browser/devtools/devtools_http_handler.cc content/browser/devtools/devtools_http_handler.cc
|
||||
index 8a8a0bdade6fe..59b9b4a7fe9da 100644
|
||||
index 1d0f19760a671..c21a9a23ff281 100644
|
||||
--- content/browser/devtools/devtools_http_handler.cc
|
||||
+++ content/browser/devtools/devtools_http_handler.cc
|
||||
@@ -591,7 +591,7 @@ void DevToolsHttpHandler::OnJsonRequest(
|
||||
@@ -12,7 +12,7 @@ index 8a8a0bdade6fe..59b9b4a7fe9da 100644
|
||||
version.Set("V8-Version", V8_VERSION_STRING);
|
||||
std::string host = info.GetHeaderValue("host");
|
||||
diff --git content/browser/loader/navigation_url_loader_impl.cc content/browser/loader/navigation_url_loader_impl.cc
|
||||
index 3bdbefae96ce6..086b906eccd9a 100644
|
||||
index 7e8951316373a..189f591893c1a 100644
|
||||
--- content/browser/loader/navigation_url_loader_impl.cc
|
||||
+++ content/browser/loader/navigation_url_loader_impl.cc
|
||||
@@ -939,7 +939,7 @@ NavigationURLLoaderImpl::CreateNonNetworkLoaderFactory(
|
||||
|
@@ -12,7 +12,7 @@ index 3f65718281973..66580417cc79e 100644
|
||||
# https://crbug.com/474506.
|
||||
"//clank/java/BUILD.gn",
|
||||
diff --git BUILD.gn BUILD.gn
|
||||
index a05810690041d..cac7f91fc271d 100644
|
||||
index 704ddc0e043d8..b762c1887cd3b 100644
|
||||
--- BUILD.gn
|
||||
+++ BUILD.gn
|
||||
@@ -19,6 +19,7 @@ import("//build/config/sanitizers/sanitizers.gni")
|
||||
|
@@ -1,8 +1,8 @@
|
||||
diff --git tools/gritsettings/resource_ids.spec tools/gritsettings/resource_ids.spec
|
||||
index 60e844376f968..b282af990a75a 100644
|
||||
index 80494b5bb318a..61ed661f2a80a 100644
|
||||
--- tools/gritsettings/resource_ids.spec
|
||||
+++ tools/gritsettings/resource_ids.spec
|
||||
@@ -1461,11 +1461,18 @@
|
||||
@@ -1463,11 +1463,18 @@
|
||||
"<(SHARED_INTERMEDIATE_DIR)/third_party/blink/public/strings/permission_element_generated_strings.grd": {
|
||||
"META": {"sizes": {"messages": [2000],}},
|
||||
"messages": [10080],
|
||||
|
@@ -1,8 +1,8 @@
|
||||
diff --git components/metrics/persistent_system_profile.cc components/metrics/persistent_system_profile.cc
|
||||
index 3cef1f28ccdb0..c91c9927436de 100644
|
||||
index 5ffc5ec97f90a..d322d2a26264a 100644
|
||||
--- components/metrics/persistent_system_profile.cc
|
||||
+++ components/metrics/persistent_system_profile.cc
|
||||
@@ -401,6 +401,10 @@ bool PersistentSystemProfile::GetSystemProfile(
|
||||
@@ -415,6 +415,10 @@ bool PersistentSystemProfile::GetSystemProfile(
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@@ -56,7 +56,7 @@ index f1030a744809c..c222a209949e6 100644
|
||||
return nullptr;
|
||||
}
|
||||
diff --git content/browser/renderer_host/render_widget_host_impl.cc content/browser/renderer_host/render_widget_host_impl.cc
|
||||
index 130fb82767d53..952b34877fa89 100644
|
||||
index 734e717d2cc5c..6690432edf9f6 100644
|
||||
--- content/browser/renderer_host/render_widget_host_impl.cc
|
||||
+++ content/browser/renderer_host/render_widget_host_impl.cc
|
||||
@@ -801,7 +801,7 @@ void RenderWidgetHostImpl::WasHidden() {
|
||||
@@ -68,7 +68,7 @@ index 130fb82767d53..952b34877fa89 100644
|
||||
RejectPointerLockOrUnlockIfNecessary(
|
||||
blink::mojom::PointerLockResult::kWrongDocument);
|
||||
}
|
||||
@@ -3681,6 +3681,11 @@ void RenderWidgetHostImpl::StopFling() {
|
||||
@@ -3685,6 +3685,11 @@ void RenderWidgetHostImpl::StopFling() {
|
||||
GetRenderInputRouter()->StopFling();
|
||||
}
|
||||
|
||||
@@ -81,7 +81,7 @@ index 130fb82767d53..952b34877fa89 100644
|
||||
uint16_t angle,
|
||||
display::mojom::ScreenOrientation type) {
|
||||
diff --git content/browser/renderer_host/render_widget_host_impl.h content/browser/renderer_host/render_widget_host_impl.h
|
||||
index 286e3d89a6c24..1276618de2e56 100644
|
||||
index c3429732757d8..09c7d25c1ba66 100644
|
||||
--- content/browser/renderer_host/render_widget_host_impl.h
|
||||
+++ content/browser/renderer_host/render_widget_host_impl.h
|
||||
@@ -838,6 +838,7 @@ class CONTENT_EXPORT RenderWidgetHostImpl
|
||||
|
@@ -1,8 +1,8 @@
|
||||
diff --git content/browser/renderer_host/render_view_host_impl.cc content/browser/renderer_host/render_view_host_impl.cc
|
||||
index ac0856149902d..1f4dda26e44dd 100644
|
||||
index a387789fe4270..e5d9dc26601e8 100644
|
||||
--- content/browser/renderer_host/render_view_host_impl.cc
|
||||
+++ content/browser/renderer_host/render_view_host_impl.cc
|
||||
@@ -752,6 +752,8 @@ bool RenderViewHostImpl::IsRenderViewLive() const {
|
||||
@@ -762,6 +762,8 @@ bool RenderViewHostImpl::IsRenderViewLive() const {
|
||||
}
|
||||
|
||||
void RenderViewHostImpl::SetBackgroundOpaque(bool opaque) {
|
||||
|
@@ -1,8 +1,8 @@
|
||||
diff --git content/browser/renderer_host/render_frame_host_impl.cc content/browser/renderer_host/render_frame_host_impl.cc
|
||||
index 7fc3f01731e3c..c473da6e8abbf 100644
|
||||
index 6e28debbe692a..8eb96841a5347 100644
|
||||
--- content/browser/renderer_host/render_frame_host_impl.cc
|
||||
+++ content/browser/renderer_host/render_frame_host_impl.cc
|
||||
@@ -9591,6 +9591,16 @@ void RenderFrameHostImpl::CreateNewWindow(
|
||||
@@ -9616,6 +9616,16 @@ void RenderFrameHostImpl::CreateNewWindow(
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@ index 7fc3f01731e3c..c473da6e8abbf 100644
|
||||
// Otherwise, consume user activation before we proceed. In particular, it is
|
||||
// important to do this before we return from the |opener_suppressed| case
|
||||
// below.
|
||||
@@ -11968,6 +11978,7 @@ void RenderFrameHostImpl::CommitNavigation(
|
||||
@@ -11993,6 +12003,7 @@ void RenderFrameHostImpl::CommitNavigation(
|
||||
auto browser_calc_origin_to_commit =
|
||||
navigation_request->GetOriginToCommitWithDebugInfo();
|
||||
if (!process_lock.is_error_page() && !is_mhtml_subframe &&
|
||||
|
@@ -1,5 +1,5 @@
|
||||
diff --git content/browser/renderer_host/render_widget_host_view_aura.cc content/browser/renderer_host/render_widget_host_view_aura.cc
|
||||
index 612d67d06d766..5102758c7f398 100644
|
||||
index 1d08f25b91496..ecac98345a92c 100644
|
||||
--- content/browser/renderer_host/render_widget_host_view_aura.cc
|
||||
+++ content/browser/renderer_host/render_widget_host_view_aura.cc
|
||||
@@ -6,6 +6,7 @@
|
||||
@@ -28,7 +28,7 @@ index 612d67d06d766..5102758c7f398 100644
|
||||
SkColor color = *GetBackgroundColor();
|
||||
window_->layer()->SetColor(color);
|
||||
}
|
||||
@@ -2642,6 +2647,16 @@ void RenderWidgetHostViewAura::CreateAuraWindow(aura::client::WindowType type) {
|
||||
@@ -2649,6 +2654,16 @@ void RenderWidgetHostViewAura::CreateAuraWindow(aura::client::WindowType type) {
|
||||
window_->layer()->SetColor(GetBackgroundColor() ? *GetBackgroundColor()
|
||||
: SK_ColorWHITE);
|
||||
UpdateFrameSinkIdRegistration();
|
||||
|
@@ -58,10 +58,10 @@ index 3f0be99e0e145..0462ebbe9bedc 100644
|
||||
// reset to null.
|
||||
const CookieAccessDelegate* cookie_access_delegate() const {
|
||||
diff --git services/network/cookie_manager.cc services/network/cookie_manager.cc
|
||||
index 963ddd7d0fcce..81f37072b77fa 100644
|
||||
index 95f73bcb9fb40..e17a93f69c089 100644
|
||||
--- services/network/cookie_manager.cc
|
||||
+++ services/network/cookie_manager.cc
|
||||
@@ -347,14 +347,9 @@ void CookieManager::AllowFileSchemeCookies(
|
||||
@@ -355,14 +355,9 @@ void CookieManager::AllowFileSchemeCookies(
|
||||
AllowFileSchemeCookiesCallback callback) {
|
||||
OnSettingsWillChange();
|
||||
|
||||
|
@@ -1,8 +1,8 @@
|
||||
diff --git content/browser/storage_partition_impl.cc content/browser/storage_partition_impl.cc
|
||||
index 5b7298888a896..4d1d7d412179f 100644
|
||||
index 29a3522bffdd0..f5edd823612a4 100644
|
||||
--- content/browser/storage_partition_impl.cc
|
||||
+++ content/browser/storage_partition_impl.cc
|
||||
@@ -3402,9 +3402,12 @@ void StoragePartitionImpl::InitNetworkContext() {
|
||||
@@ -3449,9 +3449,12 @@ void StoragePartitionImpl::InitNetworkContext() {
|
||||
cert_verifier::mojom::CertVerifierCreationParamsPtr
|
||||
cert_verifier_creation_params =
|
||||
cert_verifier::mojom::CertVerifierCreationParams::New();
|
||||
|
@@ -1,5 +1,5 @@
|
||||
diff --git BUILD.gn BUILD.gn
|
||||
index 94147651f9b..c243a8ed9cf 100644
|
||||
index 001b0791603..2ad30b10066 100644
|
||||
--- BUILD.gn
|
||||
+++ BUILD.gn
|
||||
@@ -11,6 +11,7 @@ import("//build/config/mips.gni")
|
||||
|
@@ -164,7 +164,7 @@ index eed04364a8c09..a3c7cf6275838 100644
|
||||
LabelButtonImageContainer* image_container() {
|
||||
return image_container_.get();
|
||||
diff --git ui/views/controls/label.cc ui/views/controls/label.cc
|
||||
index 9ad8685569d46..00cf319a53a10 100644
|
||||
index 02297c5213b62..20fd3defae442 100644
|
||||
--- ui/views/controls/label.cc
|
||||
+++ ui/views/controls/label.cc
|
||||
@@ -52,12 +52,29 @@ enum LabelPropertyKey {
|
||||
@@ -654,7 +654,7 @@ index f5b0936aac647..20f476c9abd93 100644
|
||||
std::optional<std::string> show_menu_host_duration_histogram) override;
|
||||
void Cancel() override;
|
||||
diff --git ui/views/controls/menu/menu_runner_impl_cocoa.mm ui/views/controls/menu/menu_runner_impl_cocoa.mm
|
||||
index 05322e627acab..a866a76c50372 100644
|
||||
index e1e3f0d4c54dd..f8afecca2016b 100644
|
||||
--- ui/views/controls/menu/menu_runner_impl_cocoa.mm
|
||||
+++ ui/views/controls/menu/menu_runner_impl_cocoa.mm
|
||||
@@ -72,6 +72,7 @@ void MenuRunnerImplCocoa::RunMenuAt(
|
||||
|
@@ -61,7 +61,7 @@ index 971e5273f1b05..a5d847f7f9d60 100644
|
||||
case ui::mojom::WindowShowState::kMaximized:
|
||||
return kSerializedShowStateMaximized;
|
||||
diff --git content/browser/renderer_host/render_widget_host_view_base.cc content/browser/renderer_host/render_widget_host_view_base.cc
|
||||
index 51f836176bf92..9171a879fca77 100644
|
||||
index fc70d927f9692..ae66251a93264 100644
|
||||
--- content/browser/renderer_host/render_widget_host_view_base.cc
|
||||
+++ content/browser/renderer_host/render_widget_host_view_base.cc
|
||||
@@ -591,6 +591,14 @@ float RenderWidgetHostViewBase::GetScaleOverrideForCapture() const {
|
||||
@@ -80,7 +80,7 @@ index 51f836176bf92..9171a879fca77 100644
|
||||
if (!GetMouseWheelPhaseHandler())
|
||||
return;
|
||||
diff --git content/browser/renderer_host/render_widget_host_view_base.h content/browser/renderer_host/render_widget_host_view_base.h
|
||||
index 2a2edc6063b49..66860109f4191 100644
|
||||
index deb5325b14ef8..5f5cbf472adf9 100644
|
||||
--- content/browser/renderer_host/render_widget_host_view_base.h
|
||||
+++ content/browser/renderer_host/render_widget_host_view_base.h
|
||||
@@ -70,6 +70,7 @@ namespace content {
|
||||
@@ -91,7 +91,7 @@ index 2a2edc6063b49..66860109f4191 100644
|
||||
class ScopedViewTransitionResources;
|
||||
class TextInputManager;
|
||||
class TouchSelectionControllerClientManager;
|
||||
@@ -151,6 +152,9 @@ class CONTENT_EXPORT RenderWidgetHostViewBase
|
||||
@@ -152,6 +153,9 @@ class CONTENT_EXPORT RenderWidgetHostViewBase
|
||||
float GetDeviceScaleFactor() const final;
|
||||
bool IsPointerLocked() override;
|
||||
|
||||
@@ -101,7 +101,7 @@ index 2a2edc6063b49..66860109f4191 100644
|
||||
// Identical to `CopyFromSurface()`, except that this method issues the
|
||||
// `viz::CopyOutputRequest` against the exact `viz::Surface` currently
|
||||
// embedded by this View, while `CopyFromSurface()` may return a copy of any
|
||||
@@ -212,6 +216,10 @@ class CONTENT_EXPORT RenderWidgetHostViewBase
|
||||
@@ -213,6 +217,10 @@ class CONTENT_EXPORT RenderWidgetHostViewBase
|
||||
// Called when screen information or native widget bounds change.
|
||||
virtual void UpdateScreenInfo();
|
||||
|
||||
@@ -112,7 +112,7 @@ index 2a2edc6063b49..66860109f4191 100644
|
||||
// Called by the TextInputManager to notify the view about being removed from
|
||||
// the list of registered views, i.e., TextInputManager is no longer tracking
|
||||
// TextInputState from this view. The RWHV should reset |text_input_manager_|
|
||||
@@ -339,6 +347,12 @@ class CONTENT_EXPORT RenderWidgetHostViewBase
|
||||
@@ -340,6 +348,12 @@ class CONTENT_EXPORT RenderWidgetHostViewBase
|
||||
const gfx::Rect& bounds,
|
||||
const gfx::Rect& anchor_rect) = 0;
|
||||
|
||||
@@ -125,7 +125,7 @@ index 2a2edc6063b49..66860109f4191 100644
|
||||
// Indicates whether the page has finished loading.
|
||||
virtual void SetIsLoading(bool is_loading) = 0;
|
||||
|
||||
@@ -595,6 +609,10 @@ class CONTENT_EXPORT RenderWidgetHostViewBase
|
||||
@@ -599,6 +613,10 @@ class CONTENT_EXPORT RenderWidgetHostViewBase
|
||||
// to all displays.
|
||||
gfx::Size system_cursor_size_;
|
||||
|
||||
@@ -136,7 +136,7 @@ index 2a2edc6063b49..66860109f4191 100644
|
||||
private:
|
||||
FRIEND_TEST_ALL_PREFIXES(
|
||||
BrowserSideFlingBrowserTest,
|
||||
@@ -616,10 +634,6 @@ class CONTENT_EXPORT RenderWidgetHostViewBase
|
||||
@@ -620,10 +638,6 @@ class CONTENT_EXPORT RenderWidgetHostViewBase
|
||||
|
||||
void SynchronizeVisualProperties();
|
||||
|
||||
@@ -196,10 +196,10 @@ index 41b34a27176a3..bdf5f9d4bb61e 100644
|
||||
if (host_ && set_focus_on_mouse_down_or_key_event_) {
|
||||
set_focus_on_mouse_down_or_key_event_ = false;
|
||||
diff --git content/public/browser/render_widget_host_view.h content/public/browser/render_widget_host_view.h
|
||||
index 7cd4d56bb2ac2..19034a43949b1 100644
|
||||
index 027dd27577fdc..cee885246b3e1 100644
|
||||
--- content/public/browser/render_widget_host_view.h
|
||||
+++ content/public/browser/render_widget_host_view.h
|
||||
@@ -254,6 +254,14 @@ class CONTENT_EXPORT RenderWidgetHostView {
|
||||
@@ -255,6 +255,14 @@ class CONTENT_EXPORT RenderWidgetHostView {
|
||||
// This must always return the same device scale factor as GetScreenInfo.
|
||||
virtual float GetDeviceScaleFactor() const = 0;
|
||||
|
||||
@@ -500,10 +500,10 @@ index 932351e288f37..7897f4b72f605 100644
|
||||
// the implementation of ::ShowCursor() is based on a counter, so making this
|
||||
// member static ensures that ::ShowCursor() is always called exactly once
|
||||
diff --git ui/views/widget/native_widget_mac.mm ui/views/widget/native_widget_mac.mm
|
||||
index 89247a9ed3522..2d997ff8fda51 100644
|
||||
index a616400ddaa71..90d424a854c13 100644
|
||||
--- ui/views/widget/native_widget_mac.mm
|
||||
+++ ui/views/widget/native_widget_mac.mm
|
||||
@@ -699,6 +699,7 @@ void NativeWidgetMac::Show(ui::mojom::WindowShowState show_state,
|
||||
@@ -702,6 +702,7 @@ void NativeWidgetMac::Show(ui::mojom::WindowShowState show_state,
|
||||
break;
|
||||
case ui::mojom::WindowShowState::kMaximized:
|
||||
case ui::mojom::WindowShowState::kFullscreen:
|
||||
@@ -512,7 +512,7 @@ index 89247a9ed3522..2d997ff8fda51 100644
|
||||
break;
|
||||
case ui::mojom::WindowShowState::kEnd:
|
||||
diff --git ui/views/widget/widget.cc ui/views/widget/widget.cc
|
||||
index a4c1dba98b0d2..b8f9b62260637 100644
|
||||
index 6853d63ce96bd..1327b1e3cbaac 100644
|
||||
--- ui/views/widget/widget.cc
|
||||
+++ ui/views/widget/widget.cc
|
||||
@@ -234,8 +234,8 @@ bool Widget::InitParams::ShouldInitAsHeadless() const {
|
||||
@@ -565,7 +565,7 @@ index a4c1dba98b0d2..b8f9b62260637 100644
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1922,10 +1933,16 @@ void Widget::OnNativeWidgetParentChanged(gfx::NativeView parent) {
|
||||
@@ -1923,10 +1934,16 @@ void Widget::OnNativeWidgetParentChanged(gfx::NativeView parent) {
|
||||
}
|
||||
|
||||
gfx::Size Widget::GetMinimumSize() const {
|
||||
@@ -582,7 +582,7 @@ index a4c1dba98b0d2..b8f9b62260637 100644
|
||||
return non_client_view_ ? non_client_view_->GetMaximumSize() : gfx::Size();
|
||||
}
|
||||
|
||||
@@ -2206,7 +2223,8 @@ bool Widget::SetInitialFocus(ui::mojom::WindowShowState show_state) {
|
||||
@@ -2207,7 +2224,8 @@ bool Widget::SetInitialFocus(ui::mojom::WindowShowState show_state) {
|
||||
View* v = widget_delegate_->GetInitiallyFocusedView();
|
||||
if (!focus_on_creation_ ||
|
||||
show_state == ui::mojom::WindowShowState::kInactive ||
|
||||
|
@@ -1,5 +1,5 @@
|
||||
diff --git content/browser/web_contents/web_contents_impl.cc content/browser/web_contents/web_contents_impl.cc
|
||||
index 5ff43afce429c..587130d6d4f2a 100644
|
||||
index 94917dc412682..308bcea0b770d 100644
|
||||
--- content/browser/web_contents/web_contents_impl.cc
|
||||
+++ content/browser/web_contents/web_contents_impl.cc
|
||||
@@ -3830,6 +3830,12 @@ void WebContentsImpl::Init(const WebContents::CreateParams& params,
|
||||
@@ -60,7 +60,7 @@ index 5ff43afce429c..587130d6d4f2a 100644
|
||||
|
||||
FrameTree* WebContentsImpl::GetOwnedPictureInPictureFrameTree() {
|
||||
diff --git content/public/browser/web_contents.h content/public/browser/web_contents.h
|
||||
index 5e89cbf0ed5fd..49a6449c46fad 100644
|
||||
index 24afa41509bec..560f83dea80de 100644
|
||||
--- content/public/browser/web_contents.h
|
||||
+++ content/public/browser/web_contents.h
|
||||
@@ -116,10 +116,12 @@ class BrowserPluginGuestDelegate;
|
||||
|
@@ -317,4 +317,9 @@ if(OS_WINDOWS)
|
||||
# Copy CEF binary and resource files to the target output directory.
|
||||
COPY_FILES("${CEF_TARGET}" "${CEF_BINARY_FILES}" "${CEF_BINARY_DIR}" "${CEF_TARGET_OUT_DIR}")
|
||||
COPY_FILES("${CEF_TARGET}" "${CEF_RESOURCE_FILES}" "${CEF_RESOURCE_DIR}" "${CEF_TARGET_OUT_DIR}")
|
||||
|
||||
if(USE_SANDBOX)
|
||||
# Set LPAC ACLs required for Windows sandbox support.
|
||||
SET_LPAC_ACLS("${CEF_TARGET}")
|
||||
endif()
|
||||
endif()
|
||||
|
334
tests/cefclient/browser/config_test.cc
Normal file
334
tests/cefclient/browser/config_test.cc
Normal file
@@ -0,0 +1,334 @@
|
||||
// Copyright (c) 2025 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/config_test.h"
|
||||
|
||||
#include <map>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "include/base/cef_logging.h"
|
||||
#include "include/cef_parser.h"
|
||||
#include "include/cef_request_context.h"
|
||||
#include "tests/cefclient/browser/test_runner.h"
|
||||
|
||||
namespace client::config_test {
|
||||
|
||||
namespace {
|
||||
|
||||
const char kTestUrlPath[] = "/config";
|
||||
|
||||
// Application-specific error codes.
|
||||
const int kMessageFormatError = 1;
|
||||
const int kRequestFailedError = 2;
|
||||
|
||||
// Common to all messages.
|
||||
const char kNameKey[] = "name";
|
||||
const char kNameGlobalConfig[] = "global_config";
|
||||
const char kNameSubscribe[] = "subscribe";
|
||||
|
||||
// Convert a dictionary value to a JSON string.
|
||||
CefString GetJSON(CefRefPtr<CefDictionaryValue> dictionary) {
|
||||
CefRefPtr<CefValue> value = CefValue::Create();
|
||||
value->SetDictionary(dictionary);
|
||||
return CefWriteJSON(value, JSON_WRITER_DEFAULT);
|
||||
}
|
||||
|
||||
using CallbackType = CefMessageRouterBrowserSide::Callback;
|
||||
|
||||
void SendSuccess(CefRefPtr<CallbackType> callback,
|
||||
CefRefPtr<CefDictionaryValue> result) {
|
||||
callback->Success(GetJSON(result));
|
||||
}
|
||||
|
||||
void SendFailure(CefRefPtr<CallbackType> callback,
|
||||
int error_code,
|
||||
const std::string& error_message) {
|
||||
callback->Failure(error_code, error_message);
|
||||
}
|
||||
|
||||
class PreferenceObserver : public CefPreferenceObserver {
|
||||
public:
|
||||
PreferenceObserver(CefRefPtr<CefPreferenceManager> manager,
|
||||
bool global,
|
||||
CefRefPtr<CallbackType> callback)
|
||||
: manager_(manager), global_(global), callback_(callback) {}
|
||||
|
||||
PreferenceObserver(const PreferenceObserver&) = delete;
|
||||
PreferenceObserver& operator=(const PreferenceObserver&) = delete;
|
||||
|
||||
void OnPreferenceChanged(const CefString& name) override {
|
||||
CEF_REQUIRE_UI_THREAD();
|
||||
auto value = manager_->GetPreference(name);
|
||||
|
||||
auto payload = CefDictionaryValue::Create();
|
||||
payload->SetString("type", "preference");
|
||||
payload->SetBool("global", global_);
|
||||
payload->SetString("name", name);
|
||||
if (value) {
|
||||
payload->SetInt("value_type", value->GetType());
|
||||
payload->SetValue("value", value);
|
||||
} else {
|
||||
payload->SetInt("value_type", VTYPE_NULL);
|
||||
payload->SetNull("value");
|
||||
}
|
||||
|
||||
SendSuccess(callback_, payload);
|
||||
}
|
||||
|
||||
private:
|
||||
const CefRefPtr<CefPreferenceManager> manager_;
|
||||
const bool global_;
|
||||
const CefRefPtr<CallbackType> callback_;
|
||||
|
||||
IMPLEMENT_REFCOUNTING(PreferenceObserver);
|
||||
};
|
||||
|
||||
class SettingObserver : public CefSettingObserver {
|
||||
public:
|
||||
SettingObserver(CefRefPtr<CefRequestContext> context,
|
||||
CefRefPtr<CallbackType> callback)
|
||||
: context_(context), callback_(callback) {}
|
||||
|
||||
SettingObserver(const SettingObserver&) = delete;
|
||||
SettingObserver& operator=(const SettingObserver&) = delete;
|
||||
|
||||
void OnSettingChanged(const CefString& requesting_url,
|
||||
const CefString& top_level_url,
|
||||
cef_content_setting_types_t content_type) override {
|
||||
CEF_REQUIRE_UI_THREAD();
|
||||
auto value = context_->GetWebsiteSetting(requesting_url, top_level_url,
|
||||
content_type);
|
||||
|
||||
auto payload = CefDictionaryValue::Create();
|
||||
payload->SetString("type", "setting");
|
||||
payload->SetString("requesting_url", requesting_url);
|
||||
payload->SetString("top_level_url", top_level_url);
|
||||
payload->SetInt("content_type", static_cast<int>(content_type));
|
||||
if (value) {
|
||||
payload->SetInt("value_type", value->GetType());
|
||||
payload->SetValue("value", value);
|
||||
} else {
|
||||
payload->SetInt("value_type", VTYPE_NULL);
|
||||
payload->SetNull("value");
|
||||
}
|
||||
|
||||
SendSuccess(callback_, payload);
|
||||
}
|
||||
|
||||
private:
|
||||
const CefRefPtr<CefRequestContext> context_;
|
||||
const CefRefPtr<CallbackType> callback_;
|
||||
|
||||
IMPLEMENT_REFCOUNTING(SettingObserver);
|
||||
};
|
||||
|
||||
// Handle messages in the browser process. Only accessed on the UI thread.
|
||||
class Handler : public CefMessageRouterBrowserSide::Handler {
|
||||
public:
|
||||
typedef std::vector<std::string> NameVector;
|
||||
|
||||
Handler() { CEF_REQUIRE_UI_THREAD(); }
|
||||
|
||||
Handler(const Handler&) = delete;
|
||||
Handler& operator=(const Handler&) = delete;
|
||||
|
||||
~Handler() override {
|
||||
for (auto& pair : subscription_state_map_) {
|
||||
delete pair.second;
|
||||
}
|
||||
}
|
||||
|
||||
// Called due to cefQuery execution in config.html.
|
||||
bool OnQuery(CefRefPtr<CefBrowser> browser,
|
||||
CefRefPtr<CefFrame> frame,
|
||||
int64_t query_id,
|
||||
const CefString& request,
|
||||
bool persistent,
|
||||
CefRefPtr<Callback> callback) override {
|
||||
CEF_REQUIRE_UI_THREAD();
|
||||
|
||||
// Only handle messages from the test URL.
|
||||
const std::string& url = frame->GetURL();
|
||||
if (!test_runner::IsTestURL(url, kTestUrlPath)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Parse |request| as a JSON dictionary.
|
||||
CefRefPtr<CefDictionaryValue> request_dict = ParseJSON(request);
|
||||
if (!request_dict) {
|
||||
callback->Failure(kMessageFormatError, "Incorrect message format");
|
||||
return true;
|
||||
}
|
||||
|
||||
// Verify the "name" key.
|
||||
if (!VerifyKey(request_dict, kNameKey, VTYPE_STRING, callback)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
const std::string& message_name = request_dict->GetString(kNameKey);
|
||||
if (message_name == kNameGlobalConfig) {
|
||||
// JavaScript is requesting a JSON representation of the global config.
|
||||
|
||||
SendGlobalConfig(callback);
|
||||
return true;
|
||||
} else if (message_name == kNameSubscribe) {
|
||||
// Subscribe to notifications from observers.
|
||||
|
||||
if (!persistent) {
|
||||
SendFailure(callback, kMessageFormatError,
|
||||
"Subscriptions must be persistent");
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!CreateSubscription(browser, query_id, callback)) {
|
||||
SendFailure(callback, kRequestFailedError,
|
||||
"Browser is already subscribed");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void OnQueryCanceled(CefRefPtr<CefBrowser> browser,
|
||||
CefRefPtr<CefFrame> frame,
|
||||
int64_t query_id) override {
|
||||
CEF_REQUIRE_UI_THREAD();
|
||||
RemoveSubscription(browser->GetIdentifier(), query_id);
|
||||
}
|
||||
|
||||
private:
|
||||
// Convert a JSON string to a dictionary value.
|
||||
static CefRefPtr<CefDictionaryValue> ParseJSON(const CefString& string) {
|
||||
CefRefPtr<CefValue> value = CefParseJSON(string, JSON_PARSER_RFC);
|
||||
if (value.get() && value->GetType() == VTYPE_DICTIONARY) {
|
||||
return value->GetDictionary();
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Verify that |key| exists in |dictionary| and has type |value_type|. Fails
|
||||
// |callback| and returns false on failure.
|
||||
static bool VerifyKey(CefRefPtr<CefDictionaryValue> dictionary,
|
||||
const char* key,
|
||||
cef_value_type_t value_type,
|
||||
CefRefPtr<Callback> callback) {
|
||||
if (!dictionary->HasKey(key) || dictionary->GetType(key) != value_type) {
|
||||
callback->Failure(
|
||||
kMessageFormatError,
|
||||
"Missing or incorrectly formatted message key: " + std::string(key));
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static CefRefPtr<CefListValue> MakeListValue(std::vector<CefString> vec) {
|
||||
if (vec.empty()) {
|
||||
return nullptr;
|
||||
}
|
||||
auto list = CefListValue::Create();
|
||||
list->SetSize(vec.size());
|
||||
size_t idx = 0;
|
||||
for (const auto& val : vec) {
|
||||
list->SetString(idx++, val);
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
void SendGlobalConfig(CefRefPtr<Callback> callback) {
|
||||
std::vector<CefString> switches;
|
||||
CefPreferenceManager::GetChromeVariationsAsSwitches(switches);
|
||||
std::vector<CefString> strings;
|
||||
CefPreferenceManager::GetChromeVariationsAsStrings(strings);
|
||||
|
||||
auto payload = CefDictionaryValue::Create();
|
||||
|
||||
if (auto list = MakeListValue(switches)) {
|
||||
payload->SetList("switches", list);
|
||||
} else {
|
||||
payload->SetNull("switches");
|
||||
}
|
||||
|
||||
if (auto list = MakeListValue(strings)) {
|
||||
payload->SetList("strings", list);
|
||||
} else {
|
||||
payload->SetNull("strings");
|
||||
}
|
||||
|
||||
SendSuccess(callback, payload);
|
||||
}
|
||||
|
||||
// Subscription state associated with a single browser.
|
||||
struct SubscriptionState {
|
||||
int64_t query_id;
|
||||
CefRefPtr<PreferenceObserver> global_pref_observer;
|
||||
CefRefPtr<CefRegistration> global_pref_registration;
|
||||
CefRefPtr<PreferenceObserver> context_pref_observer;
|
||||
CefRefPtr<CefRegistration> context_pref_registration;
|
||||
CefRefPtr<SettingObserver> context_setting_observer;
|
||||
CefRefPtr<CefRegistration> context_setting_registration;
|
||||
};
|
||||
|
||||
bool CreateSubscription(CefRefPtr<CefBrowser> browser,
|
||||
int64_t query_id,
|
||||
CefRefPtr<Callback> callback) {
|
||||
const int browser_id = browser->GetIdentifier();
|
||||
if (subscription_state_map_.find(browser_id) !=
|
||||
subscription_state_map_.end()) {
|
||||
// An subscription already exists for this browser.
|
||||
return false;
|
||||
}
|
||||
|
||||
auto global_pref_manager =
|
||||
CefPreferenceManager::GetGlobalPreferenceManager();
|
||||
auto request_context = browser->GetHost()->GetRequestContext();
|
||||
|
||||
SubscriptionState* state = new SubscriptionState();
|
||||
state->query_id = query_id;
|
||||
|
||||
state->global_pref_observer =
|
||||
new PreferenceObserver(global_pref_manager, /*global=*/true, callback);
|
||||
state->global_pref_registration =
|
||||
global_pref_manager->AddPreferenceObserver(CefString(),
|
||||
state->global_pref_observer);
|
||||
|
||||
state->context_pref_observer =
|
||||
new PreferenceObserver(request_context, /*global=*/false, callback);
|
||||
state->context_pref_registration = request_context->AddPreferenceObserver(
|
||||
CefString(), state->context_pref_observer);
|
||||
|
||||
state->context_setting_observer =
|
||||
new SettingObserver(request_context, callback);
|
||||
state->context_setting_registration =
|
||||
request_context->AddSettingObserver(state->context_setting_observer);
|
||||
|
||||
subscription_state_map_[browser_id] = state;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void RemoveSubscription(int browser_id, int64_t query_id) {
|
||||
SubscriptionStateMap::iterator it =
|
||||
subscription_state_map_.find(browser_id);
|
||||
if (it != subscription_state_map_.end() &&
|
||||
it->second->query_id == query_id) {
|
||||
delete it->second;
|
||||
subscription_state_map_.erase(it);
|
||||
}
|
||||
}
|
||||
|
||||
// Map of browser ID to SubscriptionState object.
|
||||
typedef std::map<int, SubscriptionState*> SubscriptionStateMap;
|
||||
SubscriptionStateMap subscription_state_map_;
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
void CreateMessageHandlers(test_runner::MessageHandlerSet& handlers) {
|
||||
handlers.insert(new Handler());
|
||||
}
|
||||
|
||||
} // namespace client::config_test
|
18
tests/cefclient/browser/config_test.h
Normal file
18
tests/cefclient/browser/config_test.h
Normal file
@@ -0,0 +1,18 @@
|
||||
// Copyright (c) 2025 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_CONFIG_TEST_H_
|
||||
#define CEF_TESTS_CEFCLIENT_BROWSER_CONFIG_TEST_H_
|
||||
#pragma once
|
||||
|
||||
#include "tests/cefclient/browser/test_runner.h"
|
||||
|
||||
namespace client::config_test {
|
||||
|
||||
// Create message handlers. Called from test_runner.cc.
|
||||
void CreateMessageHandlers(test_runner::MessageHandlerSet& handlers);
|
||||
|
||||
} // namespace client::config_test
|
||||
|
||||
#endif // CEF_TESTS_CEFCLIENT_BROWSER_CONFIG_TEST_H_
|
@@ -30,6 +30,7 @@ const char kNameValueSet[] = "preferences_set";
|
||||
const char kNameValueState[] = "preferences_state";
|
||||
|
||||
// Used with "preferences_get" messages.
|
||||
const char kGlobalPrefsKey[] = "global_prefs";
|
||||
const char kIncludeDefaultsKey[] = "include_defaults";
|
||||
|
||||
// Used with "preferences_set" messages.
|
||||
@@ -73,30 +74,34 @@ class Handler : public CefMessageRouterBrowserSide::Handler {
|
||||
if (message_name == kNameValueGet) {
|
||||
// JavaScript is requesting a JSON representation of the preferences tree.
|
||||
|
||||
// Verify the "include_defaults" key.
|
||||
if (!VerifyKey(request_dict, kIncludeDefaultsKey, VTYPE_BOOL, callback)) {
|
||||
// Verify the "global_prefs" and "include_defaults" keys.
|
||||
if (!VerifyKey(request_dict, kGlobalPrefsKey, VTYPE_BOOL, callback) ||
|
||||
!VerifyKey(request_dict, kIncludeDefaultsKey, VTYPE_BOOL, callback)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
const bool global_prefs = request_dict->GetBool(kGlobalPrefsKey);
|
||||
const bool include_defaults = request_dict->GetBool(kIncludeDefaultsKey);
|
||||
|
||||
OnPreferencesGet(browser, include_defaults, callback);
|
||||
OnPreferencesGet(browser, global_prefs, include_defaults, callback);
|
||||
|
||||
return true;
|
||||
} else if (message_name == kNameValueSet) {
|
||||
// JavaScript is requesting that preferences be updated to match the
|
||||
// specified JSON representation.
|
||||
|
||||
// Verify the "preferences" key.
|
||||
if (!VerifyKey(request_dict, kPreferencesKey, VTYPE_DICTIONARY,
|
||||
// Verify the "global_prefs" and "preferences" keys.
|
||||
if (!VerifyKey(request_dict, kGlobalPrefsKey, VTYPE_BOOL, callback) ||
|
||||
!VerifyKey(request_dict, kPreferencesKey, VTYPE_DICTIONARY,
|
||||
callback)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
const bool global_prefs = request_dict->GetBool(kGlobalPrefsKey);
|
||||
CefRefPtr<CefDictionaryValue> preferences =
|
||||
request_dict->GetDictionary(kPreferencesKey);
|
||||
|
||||
OnPreferencesSet(browser, preferences, callback);
|
||||
OnPreferencesSet(browser, global_prefs, preferences, callback);
|
||||
|
||||
return true;
|
||||
} else if (message_name == kNameValueState) {
|
||||
@@ -113,14 +118,19 @@ class Handler : public CefMessageRouterBrowserSide::Handler {
|
||||
private:
|
||||
// Execute |callback| with the preferences dictionary as a JSON string.
|
||||
static void OnPreferencesGet(CefRefPtr<CefBrowser> browser,
|
||||
bool global_prefs,
|
||||
bool include_defaults,
|
||||
CefRefPtr<Callback> callback) {
|
||||
CefRefPtr<CefRequestContext> context =
|
||||
browser->GetHost()->GetRequestContext();
|
||||
CefRefPtr<CefPreferenceManager> pref_manager;
|
||||
if (global_prefs) {
|
||||
pref_manager = CefPreferenceManager::GetGlobalPreferenceManager();
|
||||
} else {
|
||||
pref_manager = browser->GetHost()->GetRequestContext();
|
||||
}
|
||||
|
||||
// Retrieve all preference values.
|
||||
CefRefPtr<CefDictionaryValue> prefs =
|
||||
context->GetAllPreferences(include_defaults);
|
||||
pref_manager->GetAllPreferences(include_defaults);
|
||||
|
||||
// Serialize the preferences to JSON and return to the JavaScript caller.
|
||||
callback->Success(GetJSON(prefs));
|
||||
@@ -129,10 +139,15 @@ class Handler : public CefMessageRouterBrowserSide::Handler {
|
||||
// Set preferences based on the contents of |preferences|. Execute |callback|
|
||||
// with a descriptive result message.
|
||||
static void OnPreferencesSet(CefRefPtr<CefBrowser> browser,
|
||||
bool global_prefs,
|
||||
CefRefPtr<CefDictionaryValue> preferences,
|
||||
CefRefPtr<Callback> callback) {
|
||||
CefRefPtr<CefRequestContext> context =
|
||||
browser->GetHost()->GetRequestContext();
|
||||
CefRefPtr<CefPreferenceManager> pref_manager;
|
||||
if (global_prefs) {
|
||||
pref_manager = CefPreferenceManager::GetGlobalPreferenceManager();
|
||||
} else {
|
||||
pref_manager = browser->GetHost()->GetRequestContext();
|
||||
}
|
||||
|
||||
CefRefPtr<CefValue> value = CefValue::Create();
|
||||
value->SetDictionary(preferences);
|
||||
@@ -142,7 +157,7 @@ class Handler : public CefMessageRouterBrowserSide::Handler {
|
||||
|
||||
// Apply preferences. This may result in errors.
|
||||
const bool success =
|
||||
ApplyPrefs(context, std::string(), value, error, changed_names);
|
||||
ApplyPrefs(pref_manager, std::string(), value, error, changed_names);
|
||||
|
||||
// Create a message that accurately represents the result.
|
||||
std::string message;
|
||||
@@ -245,14 +260,14 @@ class Handler : public CefMessageRouterBrowserSide::Handler {
|
||||
// Apply preferences. Returns true on success. Returns false and sets |error|
|
||||
// to a descriptive error string on failure. |changed_names| is the list of
|
||||
// preferences that were successfully changed.
|
||||
static bool ApplyPrefs(CefRefPtr<CefRequestContext> context,
|
||||
static bool ApplyPrefs(CefRefPtr<CefPreferenceManager> pref_manager,
|
||||
const std::string& name,
|
||||
CefRefPtr<CefValue> value,
|
||||
std::string& error,
|
||||
NameVector& changed_names) {
|
||||
if (!name.empty() && context->HasPreference(name)) {
|
||||
if (!name.empty() && pref_manager->HasPreference(name)) {
|
||||
// The preference exists. Set the value.
|
||||
return SetPref(context, name, value, error, changed_names);
|
||||
return SetPref(pref_manager, name, value, error, changed_names);
|
||||
}
|
||||
|
||||
if (value->GetType() == VTYPE_DICTIONARY) {
|
||||
@@ -265,7 +280,7 @@ class Handler : public CefMessageRouterBrowserSide::Handler {
|
||||
for (const auto& i : keys) {
|
||||
const std::string& key = i;
|
||||
const std::string& current_name = name.empty() ? key : name + "." + key;
|
||||
if (!ApplyPrefs(context, current_name, dict->GetValue(key), error,
|
||||
if (!ApplyPrefs(pref_manager, current_name, dict->GetValue(key), error,
|
||||
changed_names)) {
|
||||
return false;
|
||||
}
|
||||
@@ -282,12 +297,12 @@ class Handler : public CefMessageRouterBrowserSide::Handler {
|
||||
// successfully or has not changed. If the value has changed then |name| will
|
||||
// be added to |changed_names|. Returns false and sets |error| to a
|
||||
// descriptive error string on failure.
|
||||
static bool SetPref(CefRefPtr<CefRequestContext> context,
|
||||
static bool SetPref(CefRefPtr<CefPreferenceManager> pref_manager,
|
||||
const std::string& name,
|
||||
CefRefPtr<CefValue> value,
|
||||
std::string& error,
|
||||
NameVector& changed_names) {
|
||||
CefRefPtr<CefValue> existing_value = context->GetPreference(name);
|
||||
CefRefPtr<CefValue> existing_value = pref_manager->GetPreference(name);
|
||||
DCHECK(existing_value);
|
||||
|
||||
if (value->GetType() == VTYPE_STRING &&
|
||||
@@ -322,7 +337,7 @@ class Handler : public CefMessageRouterBrowserSide::Handler {
|
||||
|
||||
// Attempt to set the preference.
|
||||
CefString error_str;
|
||||
if (!context->SetPreference(name, value, error_str)) {
|
||||
if (!pref_manager->SetPreference(name, value, error_str)) {
|
||||
error = error_str.ToString() + ": " + name;
|
||||
return false;
|
||||
}
|
||||
|
@@ -46,32 +46,33 @@
|
||||
#define IDC_STATIC -1
|
||||
#define IDS_BINARY_TRANSFER_HTML 1000
|
||||
#define IDS_BINDING_HTML 1001
|
||||
#define IDS_DIALOGS_HTML 1002
|
||||
#define IDS_DRAGGABLE_HTML 1003
|
||||
#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_TASK_MANAGER_HTML 1020
|
||||
#define IDS_TRANSPARENCY_HTML 1021
|
||||
#define IDS_URLREQUEST_HTML 1022
|
||||
#define IDS_WEBSOCKET_HTML 1023
|
||||
#define IDS_WINDOW_HTML 1024
|
||||
#define IDS_WINDOW_ICON_1X_PNG 1025
|
||||
#define IDS_WINDOW_ICON_2X_PNG 1026
|
||||
#define IDS_XMLHTTPREQUEST_HTML 1027
|
||||
#define IDS_CONFIG_HTML 1002
|
||||
#define IDS_DIALOGS_HTML 1003
|
||||
#define IDS_DRAGGABLE_HTML 1004
|
||||
#define IDS_HANG_HTML 1005
|
||||
#define IDS_IPC_PERFORMANCE_HTML 1006
|
||||
#define IDS_LOCALSTORAGE_HTML 1007
|
||||
#define IDS_LOGO_PNG 1008
|
||||
#define IDS_MEDIA_ROUTER_HTML 1009
|
||||
#define IDS_MENU_ICON_1X_PNG 1010
|
||||
#define IDS_MENU_ICON_2X_PNG 1011
|
||||
#define IDS_OSRTEST_HTML 1012
|
||||
#define IDS_OTHER_TESTS_HTML 1013
|
||||
#define IDS_PDF_HTML 1014
|
||||
#define IDS_PDF_PDF 1015
|
||||
#define IDS_PERFORMANCE_HTML 1016
|
||||
#define IDS_PERFORMANCE2_HTML 1017
|
||||
#define IDS_PREFERENCES_HTML 1018
|
||||
#define IDS_RESPONSE_FILTER_HTML 1019
|
||||
#define IDS_SERVER_HTML 1020
|
||||
#define IDS_TASK_MANAGER_HTML 1021
|
||||
#define IDS_TRANSPARENCY_HTML 1022
|
||||
#define IDS_URLREQUEST_HTML 1023
|
||||
#define IDS_WEBSOCKET_HTML 1024
|
||||
#define IDS_WINDOW_HTML 1025
|
||||
#define IDS_WINDOW_ICON_1X_PNG 1026
|
||||
#define IDS_WINDOW_ICON_2X_PNG 1027
|
||||
#define IDS_XMLHTTPREQUEST_HTML 1028
|
||||
|
||||
// Next default values for new objects
|
||||
//
|
||||
|
@@ -15,6 +15,7 @@ int GetResourceId(const char* resource_name) {
|
||||
int id;
|
||||
} resource_map[] = {{"binary_transfer.html", IDS_BINARY_TRANSFER_HTML},
|
||||
{"binding.html", IDS_BINDING_HTML},
|
||||
{"config.html", IDS_CONFIG_HTML},
|
||||
{"dialogs.html", IDS_DIALOGS_HTML},
|
||||
{"draggable.html", IDS_DRAGGABLE_HTML},
|
||||
{"hang.html", IDS_HANG_HTML},
|
||||
|
@@ -21,6 +21,7 @@
|
||||
#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/config_test.h"
|
||||
#include "tests/cefclient/browser/dialog_test.h"
|
||||
#include "tests/cefclient/browser/hang_test.h"
|
||||
#include "tests/cefclient/browser/main_context.h"
|
||||
@@ -865,6 +866,9 @@ void CreateMessageHandlers(MessageHandlerSet& handlers) {
|
||||
// Create the binding test handlers.
|
||||
binding_test::CreateMessageHandlers(handlers);
|
||||
|
||||
// Create the config test handlers.
|
||||
config_test::CreateMessageHandlers(handlers);
|
||||
|
||||
// Create the dialog test handlers.
|
||||
dialog_test::CreateMessageHandlers(handlers);
|
||||
|
||||
|
@@ -48,6 +48,7 @@ void TerminationSignalHandler(int signatl) {
|
||||
MainContext::Get()->GetRootWindowManager()->CloseAllWindows(true);
|
||||
}
|
||||
|
||||
NO_STACK_PROTECTOR
|
||||
int RunMain(int argc, char* argv[]) {
|
||||
// Create a copy of |argv| on Linux because Chromium mangles the value
|
||||
// internally (see issue #620).
|
||||
@@ -158,6 +159,7 @@ int RunMain(int argc, char* argv[]) {
|
||||
} // namespace client
|
||||
|
||||
// Program entry point function.
|
||||
NO_STACK_PROTECTOR
|
||||
int main(int argc, char* argv[]) {
|
||||
return client::RunMain(argc, argv);
|
||||
}
|
||||
|
703
tests/cefclient/resources/config.html
Normal file
703
tests/cefclient/resources/config.html
Normal file
@@ -0,0 +1,703 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<title>Configuration Test</title>
|
||||
<meta http-equiv="Content-Type" content="text/html;charset=utf-8">
|
||||
|
||||
<style>
|
||||
body {
|
||||
font-family: Verdana, Arial;
|
||||
font-size: 12px;
|
||||
}
|
||||
#message {
|
||||
color: red;
|
||||
font-weight: bold;
|
||||
font-size: 14px;
|
||||
}
|
||||
.desc {
|
||||
font-size: 14px;
|
||||
}
|
||||
.foot {
|
||||
font-size: 11px;
|
||||
}
|
||||
.mono {
|
||||
font-family: monospace;
|
||||
}
|
||||
.cat_header_0 {
|
||||
font-weight: bold;
|
||||
font-size: 14px;
|
||||
}
|
||||
.cat_header_1 {
|
||||
font-weight: bold;
|
||||
}
|
||||
.cat_header_2 {
|
||||
font-family: Verdana, Arial;
|
||||
}
|
||||
.cat_body {
|
||||
font-family: monospace;
|
||||
white-space: pre;
|
||||
margin-left: 10px;
|
||||
}
|
||||
#temp-message {
|
||||
display: none;
|
||||
background-color: #f0f0f0;
|
||||
border: 1px solid #ccc;
|
||||
padding: 10px;
|
||||
position: fixed;
|
||||
bottom: 20px;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
}
|
||||
.hr-container {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
text-align: center;
|
||||
}
|
||||
.hr-line {
|
||||
border-top: 1px solid black;
|
||||
width: 100%;
|
||||
margin: 0 3px;
|
||||
}
|
||||
.hr-text {
|
||||
padding: 0;
|
||||
white-space: nowrap;
|
||||
}
|
||||
</style>
|
||||
|
||||
<script>
|
||||
function onLoad() {
|
||||
if (location.hostname != 'tests') {
|
||||
onCefError(0, 'This page can only be run from tests.');
|
||||
|
||||
// Disable all form elements.
|
||||
var elements = document.getElementById("form").elements;
|
||||
for (var i = 0, element; element = elements[i++]; ) {
|
||||
element.disabled = true;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
getGlobalConfig();
|
||||
updateFilter();
|
||||
startSubscription();
|
||||
}
|
||||
|
||||
function onUnload() {
|
||||
stopSubscription();
|
||||
}
|
||||
|
||||
function onCefError(code, message) {
|
||||
val = 'ERROR: ' + message;
|
||||
if (code !== 0) {
|
||||
val += ' (' + code + ')';
|
||||
}
|
||||
document.getElementById('message').innerHTML = val + '<br/><br/>';
|
||||
}
|
||||
|
||||
function sendCefQuery(payload, onSuccess, onFailure=onCefError, persistent=false) {
|
||||
// Results in a call to the OnQuery method in config_test.cc
|
||||
return window.cefQuery({
|
||||
request: JSON.stringify(payload),
|
||||
onSuccess: onSuccess,
|
||||
onFailure: onFailure,
|
||||
persistent: persistent
|
||||
});
|
||||
}
|
||||
|
||||
// Request the global configuration.
|
||||
function getGlobalConfig() {
|
||||
sendCefQuery(
|
||||
{name: 'global_config'},
|
||||
(message) => onGlobalConfigMessage(JSON.parse(message)),
|
||||
);
|
||||
}
|
||||
|
||||
// Display the global configuration response.
|
||||
function onGlobalConfigMessage(message) {
|
||||
document.getElementById('global_switches').innerHTML =
|
||||
message.switches !== null ? message.switches.join('<br/>') : '(none)';
|
||||
if (message.strings !== null) {
|
||||
document.getElementById('global_strings').innerHTML = message.strings.join('<br/>');
|
||||
document.getElementById('global_strings_ct').textContent = message.strings.length;
|
||||
}
|
||||
}
|
||||
|
||||
var currentSubscriptionId = null;
|
||||
|
||||
// Subscribe to ongoing message notifications from the native code.
|
||||
function startSubscription() {
|
||||
currentSubscriptionId = sendCefQuery(
|
||||
{name: 'subscribe'},
|
||||
(message) => onSubscriptionMessage(JSON.parse(message)),
|
||||
(code, message) => {
|
||||
onCefError(code, message);
|
||||
currentSubscriptionId = null;
|
||||
},
|
||||
true
|
||||
);
|
||||
}
|
||||
|
||||
// Unsubscribe from message notifications.
|
||||
function stopSubscription() {
|
||||
if (currentSubscriptionId !== null) {
|
||||
// Results in a call to the OnQueryCanceled method in config_test.cc
|
||||
window.cefQueryCancel(currentSubscriptionId);
|
||||
}
|
||||
}
|
||||
|
||||
// Returns a nice timestamp for display purposes.
|
||||
function getNiceTimestamp() {
|
||||
const now = new Date();
|
||||
|
||||
const year = now.getFullYear();
|
||||
const month = String(now.getMonth() + 1).padStart(2, '0'); // Months are 0-indexed
|
||||
const day = String(now.getDate()).padStart(2, '0');
|
||||
const hours = String(now.getHours()).padStart(2, '0');
|
||||
const minutes = String(now.getMinutes()).padStart(2, '0');
|
||||
const seconds = String(now.getSeconds()).padStart(2, '0');
|
||||
|
||||
return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
|
||||
}
|
||||
|
||||
var paused = false;
|
||||
var paused_messages = [];
|
||||
var first_after_pause = false;
|
||||
|
||||
// Toggle whether messages are displayed or queued.
|
||||
function togglePause() {
|
||||
paused = !paused;
|
||||
document.getElementById("pause_button").value = paused ? "Resume" : "Pause";
|
||||
|
||||
if (!paused) {
|
||||
first_after_pause = true;
|
||||
while (paused_messages.length > 0) {
|
||||
onSubscriptionMessage(paused_messages.shift());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function doPause() {
|
||||
if (!paused) {
|
||||
togglePause();
|
||||
showTempMessage('Event processing is paused. Click Resume to continue.');
|
||||
}
|
||||
}
|
||||
|
||||
var filter = {}
|
||||
var filtered_ct = 0;
|
||||
var filter_updating = false;
|
||||
|
||||
// Populate |filter| based on form control state.
|
||||
function updateFilter() {
|
||||
if (filter_updating) {
|
||||
// Ignore changes triggered from individual elements while we're updating multiple.
|
||||
return;
|
||||
}
|
||||
|
||||
filter.text = document.getElementById("filter_text").value.trim().toLowerCase();
|
||||
filter.global_prefs = document.getElementById("filter_global_prefs").checked;
|
||||
filter.context_prefs = document.getElementById("filter_context_prefs").checked;
|
||||
filter.context_settings = document.getElementById("filter_context_settings").checked;
|
||||
}
|
||||
|
||||
function doFilter(type, text, global=false) {
|
||||
filter_updating = true;
|
||||
|
||||
document.getElementById("filter_text").value = text;
|
||||
|
||||
var checked = '';
|
||||
if (type === 'preference') {
|
||||
checked = global ? 'filter_global_prefs' : 'filter_context_prefs';
|
||||
} else if (type === 'setting') {
|
||||
checked = 'filter_context_settings';
|
||||
}
|
||||
|
||||
['filter_global_prefs', 'filter_context_prefs', 'filter_context_settings'].forEach(function(id) {
|
||||
document.getElementById(id).checked = id === checked;
|
||||
});
|
||||
|
||||
filter_updating = false;
|
||||
updateFilter();
|
||||
}
|
||||
|
||||
function doFilterReset() {
|
||||
filter_updating = true;
|
||||
document.getElementById("filtered_ct").textContent = 0;
|
||||
document.getElementById("filter_text").value = '';
|
||||
document.getElementById("filter_global_prefs").checked = true;
|
||||
document.getElementById("filter_context_prefs").checked = true;
|
||||
document.getElementById("filter_context_settings").checked = true;
|
||||
filter_updating = false;
|
||||
updateFilter();
|
||||
}
|
||||
|
||||
// Returns true if the message should be displayed based on the current filter settings.
|
||||
function passesFilter(message) {
|
||||
if (message.type === 'preference') {
|
||||
if (message.global) {
|
||||
if (!filter.global_prefs) {
|
||||
return false;
|
||||
}
|
||||
} else if (!filter.context_prefs) {
|
||||
return false;
|
||||
}
|
||||
} else if (message.type === 'setting' && !filter.context_settings) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (filter.text.length > 0) {
|
||||
var check_text = JSON.stringify(message).toLowerCase();
|
||||
if (message.type === 'setting') {
|
||||
check_text += ' ' + getSettingTypeLabel(message.content_type).toLowerCase();
|
||||
}
|
||||
if (check_text.indexOf(filter.text) < 0) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Match the cef_value_type_t values from include/internal/cef_types.h
|
||||
const value_types = [
|
||||
'INVALID',
|
||||
'NULL',
|
||||
'BOOL',
|
||||
'INT',
|
||||
'DOUBLE',
|
||||
'STRING',
|
||||
'BINARY',
|
||||
'DICTIONARY',
|
||||
'LIST',
|
||||
]
|
||||
|
||||
function getValueType(index) {
|
||||
if (index < 0 || index >= value_types.length) {
|
||||
return 'UNKNOWN';
|
||||
}
|
||||
return value_types[index];
|
||||
}
|
||||
|
||||
// Match the cef_content_setting_types_t values from include/internal/cef_types_content_settings.h
|
||||
const setting_types = [
|
||||
"COOKIES",
|
||||
"IMAGES",
|
||||
"JAVASCRIPT",
|
||||
"POPUPS",
|
||||
"GEOLOCATION",
|
||||
"NOTIFICATIONS",
|
||||
"AUTO_SELECT_CERTIFICATE",
|
||||
"MIXEDSCRIPT",
|
||||
"MEDIASTREAM_MIC",
|
||||
"MEDIASTREAM_CAMERA",
|
||||
"PROTOCOL_HANDLERS",
|
||||
"DEPRECATED_PPAPI_BROKER",
|
||||
"AUTOMATIC_DOWNLOADS",
|
||||
"MIDI_SYSEX",
|
||||
"SSL_CERT_DECISIONS",
|
||||
"PROTECTED_MEDIA_IDENTIFIER",
|
||||
"APP_BANNER",
|
||||
"SITE_ENGAGEMENT",
|
||||
"DURABLE_STORAGE",
|
||||
"USB_CHOOSER_DATA",
|
||||
"BLUETOOTH_GUARD",
|
||||
"BACKGROUND_SYNC",
|
||||
"AUTOPLAY",
|
||||
"IMPORTANT_SITE_INFO",
|
||||
"PERMISSION_AUTOBLOCKER_DATA",
|
||||
"ADS",
|
||||
"ADS_DATA",
|
||||
"MIDI",
|
||||
"PASSWORD_PROTECTION",
|
||||
"MEDIA_ENGAGEMENT",
|
||||
"SOUND",
|
||||
"CLIENT_HINTS",
|
||||
"SENSORS",
|
||||
"DEPRECATED_ACCESSIBILITY_EVENTS",
|
||||
"PAYMENT_HANDLER",
|
||||
"USB_GUARD",
|
||||
"BACKGROUND_FETCH",
|
||||
"INTENT_PICKER_DISPLAY",
|
||||
"IDLE_DETECTION",
|
||||
"SERIAL_GUARD",
|
||||
"SERIAL_CHOOSER_DATA",
|
||||
"PERIODIC_BACKGROUND_SYNC",
|
||||
"BLUETOOTH_SCANNING",
|
||||
"HID_GUARD",
|
||||
"HID_CHOOSER_DATA",
|
||||
"WAKE_LOCK_SCREEN",
|
||||
"WAKE_LOCK_SYSTEM",
|
||||
"LEGACY_COOKIE_ACCESS",
|
||||
"FILE_SYSTEM_WRITE_GUARD",
|
||||
"NFC",
|
||||
"BLUETOOTH_CHOOSER_DATA",
|
||||
"CLIPBOARD_READ_WRITE",
|
||||
"CLIPBOARD_SANITIZED_WRITE",
|
||||
"SAFE_BROWSING_URL_CHECK_DATA",
|
||||
"VR",
|
||||
"AR",
|
||||
"FILE_SYSTEM_READ_GUARD",
|
||||
"STORAGE_ACCESS",
|
||||
"CAMERA_PAN_TILT_ZOOM",
|
||||
"WINDOW_MANAGEMENT",
|
||||
"INSECURE_PRIVATE_NETWORK",
|
||||
"LOCAL_FONTS",
|
||||
"PERMISSION_AUTOREVOCATION_DATA",
|
||||
"FILE_SYSTEM_LAST_PICKED_DIRECTORY",
|
||||
"DISPLAY_CAPTURE",
|
||||
"FILE_SYSTEM_ACCESS_CHOOSER_DATA",
|
||||
"FEDERATED_IDENTITY_SHARING",
|
||||
"JAVASCRIPT_JIT",
|
||||
"HTTP_ALLOWED",
|
||||
"FORMFILL_METADATA",
|
||||
"DEPRECATED_FEDERATED_IDENTITY_ACTIVE_SESSION",
|
||||
"AUTO_DARK_WEB_CONTENT",
|
||||
"REQUEST_DESKTOP_SITE",
|
||||
"FEDERATED_IDENTITY_API",
|
||||
"NOTIFICATION_INTERACTIONS",
|
||||
"REDUCED_ACCEPT_LANGUAGE",
|
||||
"NOTIFICATION_PERMISSION_REVIEW",
|
||||
"PRIVATE_NETWORK_GUARD",
|
||||
"PRIVATE_NETWORK_CHOOSER_DATA",
|
||||
"FEDERATED_IDENTITY_IDENTITY_PROVIDER_SIGNIN_STATUS",
|
||||
"REVOKED_UNUSED_SITE_PERMISSIONS",
|
||||
"TOP_LEVEL_STORAGE_ACCESS",
|
||||
"FEDERATED_IDENTITY_AUTO_REAUTHN_PERMISSION",
|
||||
"FEDERATED_IDENTITY_IDENTITY_PROVIDER_REGISTRATION",
|
||||
"ANTI_ABUSE",
|
||||
"THIRD_PARTY_STORAGE_PARTITIONING",
|
||||
"HTTPS_ENFORCED",
|
||||
"ALL_SCREEN_CAPTURE",
|
||||
"COOKIE_CONTROLS_METADATA",
|
||||
"TPCD_HEURISTICS_GRANTS",
|
||||
"TPCD_METADATA_GRANTS",
|
||||
"TPCD_TRIAL",
|
||||
"TOP_LEVEL_TPCD_TRIAL",
|
||||
"TOP_LEVEL_TPCD_ORIGIN_TRIAL",
|
||||
"AUTO_PICTURE_IN_PICTURE",
|
||||
"FILE_SYSTEM_ACCESS_EXTENDED_PERMISSION",
|
||||
"FILE_SYSTEM_ACCESS_RESTORE_PERMISSION",
|
||||
"CAPTURED_SURFACE_CONTROL",
|
||||
"SMART_CARD_GUARD",
|
||||
"SMART_CARD_DATA",
|
||||
"WEB_PRINTING",
|
||||
"AUTOMATIC_FULLSCREEN",
|
||||
"SUB_APP_INSTALLATION_PROMPTS",
|
||||
"SPEAKER_SELECTION",
|
||||
"DIRECT_SOCKETS",
|
||||
"KEYBOARD_LOCK",
|
||||
"POINTER_LOCK",
|
||||
"REVOKED_ABUSIVE_NOTIFICATION_PERMISSIONS",
|
||||
"TRACKING_PROTECTION",
|
||||
"DISPLAY_MEDIA_SYSTEM_AUDIO",
|
||||
"JAVASCRIPT_OPTIMIZER",
|
||||
"STORAGE_ACCESS_HEADER_ORIGIN_TRIAL",
|
||||
"HAND_TRACKING",
|
||||
"WEB_APP_INSTALLATION",
|
||||
"DIRECT_SOCKETS_PRIVATE_NETWORK_ACCESS",
|
||||
"LEGACY_COOKIE_SCOPE",
|
||||
"ARE_SUSPICIOUS_NOTIFICATIONS_ALLOWLISTED_BY_USER",
|
||||
"CONTROLLED_FRAME",
|
||||
];
|
||||
|
||||
function getSettingType(index) {
|
||||
if (index < 0 || index >= setting_types.length) {
|
||||
return 'UNKNOWN';
|
||||
}
|
||||
return setting_types[index];
|
||||
}
|
||||
|
||||
function getSettingTypeLabel(type) {
|
||||
return getSettingType(type) + ' (' + type + ')'
|
||||
}
|
||||
|
||||
function makeDetails(summaryHTML, summaryClass, contentHTML, contentClass, contentId=null, open=false) {
|
||||
const newDetails = document.createElement('details');
|
||||
if (open) {
|
||||
newDetails.open = true;
|
||||
}
|
||||
|
||||
const newSummary = document.createElement('summary');
|
||||
newSummary.innerHTML = summaryHTML;
|
||||
if (summaryClass !== null) {
|
||||
newSummary.className = summaryClass;
|
||||
}
|
||||
newDetails.append(newSummary);
|
||||
|
||||
const newContent = document.createElement('p');
|
||||
newContent.innerHTML = contentHTML
|
||||
if (contentClass !== null) {
|
||||
newContent.className = contentClass;
|
||||
}
|
||||
if (contentId !== null) {
|
||||
newContent.id = contentId;
|
||||
}
|
||||
newDetails.append(newContent);
|
||||
|
||||
const newP = document.createElement('p');
|
||||
newP.append(newDetails);
|
||||
|
||||
return newP;
|
||||
}
|
||||
|
||||
function makeValueExample(value, value_type) {
|
||||
code = '\n// Create a CefValue object programmatically:\n' +
|
||||
'auto value = CefValue::Create();\n';
|
||||
if (value === null || getValueType(value_type) == 'NULL') {
|
||||
code += 'value->SetNull();\n';
|
||||
} else if (typeof value === 'boolean' || getValueType(value_type) == 'BOOL') {
|
||||
code += 'value->SetBool(' + (value ? 'true' : 'false') + ');\n';
|
||||
} else if (Number.isInteger(value) || getValueType(value_type) == 'INT') {
|
||||
code += 'value->SetInt(' + value + ');\n';
|
||||
} else if (typeof value === 'number' || getValueType(value_type) == 'DOUBLE') {
|
||||
code += 'value->SetDouble(' + value + ');\n';
|
||||
} else if (typeof value === 'string' || getValueType(value_type) == 'STRING') {
|
||||
code += 'value->SetString("' + value + '");\n';
|
||||
} else if (Array.isArray(value) || getValueType(value_type) == 'LIST') {
|
||||
code += 'auto listValue = CefListValue::Create();\n';
|
||||
if (value.length > 0) {
|
||||
code += '\n// TODO: Populate |listValue| using CefListValue::Set* methods.\n\n';
|
||||
}
|
||||
code += 'value->SetList(listValue);\n';
|
||||
if (value.length > 0) {
|
||||
code += '\n// ALTERNATELY: Create a CefValue object by parsing a JSON string:\n' +
|
||||
'auto value = CefParseJSON("[ ... ]", JSON_PARSER_RFC);\n';
|
||||
}
|
||||
} else if (typeof value === 'object' || getValueType(value_type) == 'DICTIONARY') {
|
||||
code += 'auto dictValue = CefDictionaryValue::Create();\n';
|
||||
const has_value = Object.keys(value).length > 0;
|
||||
if (has_value) {
|
||||
code += '\n// TODO: Populate |dictValue| using CefDictionaryValue::Set* methods.\n\n';
|
||||
}
|
||||
code += 'value->SetDictionary(dictValue);\n';
|
||||
if (has_value) {
|
||||
code += '\n// ALTERNATELY: Create a CefValue object by parsing a JSON string:\n' +
|
||||
'auto value = CefParseJSON("{ ... }", JSON_PARSER_RFC);\n';
|
||||
}
|
||||
} else {
|
||||
code += '\n//TODO: Populate |value|.\n\n';
|
||||
}
|
||||
return code;
|
||||
}
|
||||
|
||||
function makeCopyLink(elem_id) {
|
||||
return '<a href="#" onMouseDown="copyToClipboard(\'' + elem_id + '\')" onClick="return false">[copy to clipboard]</a>';
|
||||
}
|
||||
|
||||
function makeContent(elem_id, content) {
|
||||
const content_id = 'cn-' + elem_id;
|
||||
return makeDetails('Content ' + makeCopyLink(content_id), 'cat_header_2', content, 'cat_body', content_id, true);
|
||||
}
|
||||
|
||||
function makeHR(label) {
|
||||
const container = document.createElement('div');
|
||||
container.className = 'hr-container';
|
||||
const line1 = document.createElement('div');
|
||||
line1.className = 'hr-line';
|
||||
container.append(line1);
|
||||
const text = document.createElement('span');
|
||||
text.className = 'hr-text';
|
||||
text.innerHTML = label;
|
||||
container.append(text);
|
||||
const line2 = document.createElement('div');
|
||||
line2.className = 'hr-line';
|
||||
container.append(line2);
|
||||
return container;
|
||||
}
|
||||
|
||||
function makeCodeExample(elem_id, message) {
|
||||
const example_id = 'ex-' + elem_id;
|
||||
var code = '// Code must be executed on the browser process UI thread.\n\n';
|
||||
|
||||
if (message.type === "preference") {
|
||||
if (message.global) {
|
||||
code += 'auto pref_manager = CefPreferenceManager::GetGlobalPreferenceManager();\n';
|
||||
} else {
|
||||
code += '// |browser| is an existing CefBrowser instance.\n' +
|
||||
'auto pref_manager = browser->GetHost()->GetRequestContext();\n';
|
||||
}
|
||||
code += makeValueExample(message.value, message.value_type) + '\n' +
|
||||
'CefString error;\n' +
|
||||
'bool success = pref_manager->SetPreference("' + message.name + '", value, error);\n' +
|
||||
'if (!success) {\n' +
|
||||
' // TODO: Use |error| to diagnose the failure.\n' +
|
||||
'}\n';
|
||||
} else if (message.type === "setting") {
|
||||
const type = getSettingType(message.content_type);
|
||||
const content_type = type !== 'UNKNOWN' ? 'CEF_CONTENT_SETTING_TYPE_' + type : message.content_type;
|
||||
|
||||
code += '// |browser| is an existing CefBrowser instance.\n' +
|
||||
'auto context = browser->GetHost()->GetRequestContext();\n' +
|
||||
makeValueExample(message.value, message.value_type) + '\n' +
|
||||
'context->SetWebsiteSetting("' + message.requesting_url + '", "' + message.top_level_url +
|
||||
'", '+ content_type +', value);\n';
|
||||
}
|
||||
|
||||
return makeDetails('C++ Code Example ' + makeCopyLink(example_id), 'cat_header_2', code, 'cat_body', example_id, false);
|
||||
}
|
||||
|
||||
var message_ct = 0;
|
||||
|
||||
// A new message has arrived. It may be queued, filtered out or displayed.
|
||||
function onSubscriptionMessage(message) {
|
||||
if (paused) {
|
||||
// Queue the message until the user clicks Resume.
|
||||
message.timestamp = getNiceTimestamp();
|
||||
paused_messages.push(message);
|
||||
document.getElementById("pause_button").value = 'Resume (' + paused_messages.length + ')';
|
||||
return;
|
||||
}
|
||||
|
||||
if (!passesFilter(message)) {
|
||||
// Filter out the message.
|
||||
filtered_ct++;
|
||||
document.getElementById("filtered_ct").innerHTML = filtered_ct;
|
||||
return;
|
||||
}
|
||||
|
||||
// Use the arrival timestamp for queued messages.
|
||||
var timestamp;
|
||||
if (message.timestamp) {
|
||||
timestamp = message.timestamp;
|
||||
delete message.timestamp;
|
||||
} else {
|
||||
timestamp = getNiceTimestamp();
|
||||
}
|
||||
|
||||
// Display the message.
|
||||
var label = timestamp + ': ';
|
||||
var content = 'value_type=' + getValueType(message.value_type);
|
||||
var search = '';
|
||||
var filter = '';
|
||||
|
||||
if (message.type === "preference") {
|
||||
label += 'Preference (' + (message.global ? 'Global' : 'Profile') +
|
||||
') <span class="mono">' + message.name + '</span>';
|
||||
search = '%5C%22' + message.name + '%5C%22';
|
||||
filter = "'preference', '" + message.name + "', " + (message.global ? 'true' : 'false');
|
||||
} else if (message.type === "setting") {
|
||||
label += 'Setting <span class="mono">' + getSettingTypeLabel(message.content_type) + '</span>';
|
||||
const setting_type = getSettingType(message.content_type);
|
||||
search = 'ContentSettingsType::' + setting_type;
|
||||
filter = "'setting', '" + setting_type + "'";
|
||||
content = 'requesting_url=' + message.requesting_url +
|
||||
'\ntop_level_url=' + message.top_level_url +
|
||||
'\n' + content;
|
||||
}
|
||||
content += '\nvalue=' + JSON.stringify(message.value, null, 1);
|
||||
label += ' <a href="#" onMouseDown="doFilter(' + filter + ')" onClick="return false">[filter]</a>' +
|
||||
' <a href="https://source.chromium.org/search?q=' + search + '" target="_blank">[search 🔗]</a>';
|
||||
|
||||
const messages = document.getElementById('messages');
|
||||
|
||||
if (first_after_pause) {
|
||||
messages.prepend(makeHR('RESUMED'));
|
||||
first_after_pause = false;
|
||||
}
|
||||
|
||||
const elem_id = message_ct++;
|
||||
const newDetails = makeDetails(label, null, makeContent(elem_id, content).outerHTML +
|
||||
makeCodeExample(elem_id, message).outerHTML, 'cat_body');
|
||||
messages.prepend(newDetails);
|
||||
}
|
||||
|
||||
// Clear filter count and displayed/pending messages.
|
||||
function doClear() {
|
||||
filtered_ct = 0;
|
||||
document.getElementById("filtered_ct").textContent = 0;
|
||||
document.getElementById('messages').innerHTML = '';
|
||||
if (paused) {
|
||||
paused_messages = [];
|
||||
document.getElementById("pause_button").value = 'Resume';
|
||||
}
|
||||
message_ct = 0;
|
||||
}
|
||||
|
||||
function showTempMessage(msg) {
|
||||
const element = document.getElementById("temp-message");
|
||||
element.innerHTML = msg;
|
||||
element.style.display = "block";
|
||||
|
||||
setTimeout(function() {
|
||||
element.style.display = "none";
|
||||
}, 3000);
|
||||
}
|
||||
|
||||
function copyToClipboard(elementId) {
|
||||
const element = document.getElementById(elementId);
|
||||
if (!element) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Make all parent details nodes are open, otherwise nothing will be copied to the clipboard.
|
||||
var parent = element.parentNode;
|
||||
while (parent) {
|
||||
if (parent.nodeName === 'DETAILS') {
|
||||
if (!parent.open) {
|
||||
parent.open = true;
|
||||
}
|
||||
}
|
||||
parent = parent.parentNode;
|
||||
}
|
||||
|
||||
navigator.clipboard.writeText(element.outerText)
|
||||
.then(() => {
|
||||
showTempMessage('Text copied to clipboard.');
|
||||
})
|
||||
.catch(err => {
|
||||
showTempMessage('Failed to copy text to clipboard!');
|
||||
console.error('Failed to copy text: ', err);
|
||||
});
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
<body bgcolor="white" onload="onLoad()" onunload="onUnload()">
|
||||
<div id="message"></div>
|
||||
<details open>
|
||||
<summary class="cat_header_0">Startup configuration</summary>
|
||||
<p class="desc">
|
||||
This section displays the global configuration (Chrome Variations) that was applied at startup.
|
||||
Chrome Variations can be configured via chrome://flags <sup>[*]</sup>, via the below command-line switches, or via field trials (disabled in Official builds).
|
||||
The Active Variations section below is the human-readable equivalent of the "Active Variations" section of chrome://version.
|
||||
See <a href="https://developer.chrome.com/docs/web-platform/chrome-variations" target="_blank">Chrome Variations docs</a> for background.
|
||||
</p>
|
||||
<p class="foot">
|
||||
* Flags are stored in the global <span class="mono">browser.enabled_labs_experiments</span> preference.
|
||||
</p>
|
||||
<p class="cat_header_1">Command-Line Switches:</p>
|
||||
<p class="cat_body" id="global_switches"></p>
|
||||
<details>
|
||||
<summary class="cat_header_1">Active Variations (<span id="global_strings_ct">0</span>)</summary>
|
||||
<p class="cat_body" id="global_strings"></p>
|
||||
</details>
|
||||
</details>
|
||||
<br/>
|
||||
<details open>
|
||||
<summary class="cat_header_0">Runtime configuration</summary>
|
||||
<p class="desc">
|
||||
This section displays preference and site settings changes that occur during runtime.
|
||||
Chromium stores both global and Profile-specific preferences.
|
||||
See <a href="https://www.chromium.org/developers/design-documents/preferences/" target="_blank">Preferences docs</a> for background.
|
||||
To view a snapshot of all preferences go <a href="https://tests/preferences#advanced">here</a> instead.
|
||||
</p>
|
||||
<p id="filter">
|
||||
<form id="form">
|
||||
Text Contains: <input type="text" id="filter_text"/> <input type="button" onclick="updateFilter();" value="Apply"/>
|
||||
<br/>Show: <input type="checkbox" id="filter_global_prefs" onChange="updateFilter()" checked /> Global preferences
|
||||
<input type="checkbox" id="filter_context_prefs" onChange="updateFilter()" checked /> Profile-specific preferences
|
||||
<input type="checkbox" id="filter_context_settings" onChange="updateFilter()" checked /> Site settings <sup>[*]</sup>
|
||||
<br/><input type="button" id="clear_button" onclick="doClear()" value="Clear"/>
|
||||
<input type="button" id="pause_button" onclick="togglePause()" value="Pause"/> <sup>[**]</sup> Filtered out: <span id="filtered_ct">0</span>
|
||||
<input type="button" id="reset_button" onclick="doFilterReset()" value="Reset"/>
|
||||
<p class="foot">
|
||||
* Site settings are stored in the Profile-specific <span class="mono">profile.content_settings</span> preference and can be modified via chrome://settings/content.
|
||||
<br/>** Events will not be displayed or filtered out while processing is paused.
|
||||
</p>
|
||||
</form>
|
||||
</p>
|
||||
<div id="messages" onMouseDown="doPause()"></div>
|
||||
<div id="temp-message"></div>
|
||||
</details>
|
||||
</body>
|
||||
</html>
|
@@ -10,6 +10,7 @@
|
||||
<li><a href="https://jigsaw.w3.org/HTTP/Basic/">Authentication (Basic)</a> - credentials returned via GetAuthCredentials</li>
|
||||
<li><a href="https://jigsaw.w3.org/HTTP/Digest/">Authentication (Digest)</a> - credentials returned via GetAuthCredentials</li>
|
||||
<li><a href="binary_transfer">Binary vs String Transfer Benchmark</a></li>
|
||||
<li><a href="config">Chrome Configuration</a></li>
|
||||
<li><a href="http://html5advent2011.digitpaint.nl/3/index.html">Cursors</a></li>
|
||||
<li><a href="dialogs">Dialogs</a></li>
|
||||
<li><a href="http://html5demos.com/drag">Drag & Drop</a></li>
|
||||
|
@@ -13,8 +13,12 @@
|
||||
|
||||
<script>
|
||||
function setup() {
|
||||
if (location.hostname == 'tests' || location.hostname == 'localhost')
|
||||
if (location.hostname === 'tests' || location.hostname === 'localhost') {
|
||||
if (location.hash === '#advanced') {
|
||||
toggleView();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
alert('This page can only be run from tests or localhost.');
|
||||
|
||||
@@ -96,7 +100,8 @@
|
||||
<tr>
|
||||
<td align="left">
|
||||
<input type="button" value="Refresh" onClick="refreshEditor()"/>
|
||||
<input type="checkbox" id="hide_defaults"/> Show modified preferences only
|
||||
<input type="checkbox" id="global_prefs" onChange="refreshEditor()"/> Show global preferences
|
||||
<input type="checkbox" id="hide_defaults" onChange="refreshEditor()"/> Show modified preferences only
|
||||
</td>
|
||||
<td align="right">
|
||||
<input type="button" value="Apply Changes" onClick="applyEditorChanges()"/>
|
||||
@@ -161,10 +166,11 @@
|
||||
|
||||
// Get the preferences and execute |onSuccessCallback| with the resulting
|
||||
// JSON object.
|
||||
function getPreferences(include_defaults, onSuccessCallback) {
|
||||
function getPreferences(global_prefs, include_defaults, onSuccessCallback) {
|
||||
// Create the request object.
|
||||
var request = {};
|
||||
request.name = "preferences_get";
|
||||
request.global_prefs = global_prefs;
|
||||
request.include_defaults = include_defaults;
|
||||
|
||||
// Send the request to C++.
|
||||
@@ -177,10 +183,11 @@
|
||||
}
|
||||
|
||||
// Set the preferences.
|
||||
function setPreferences(preferences) {
|
||||
function setPreferences(global_prefs, preferences) {
|
||||
// Create the request object.
|
||||
var request = {};
|
||||
request.name = "preferences_set";
|
||||
request.global_prefs = global_prefs;
|
||||
request.preferences = preferences;
|
||||
|
||||
// Send the request to C++.
|
||||
@@ -214,8 +221,9 @@
|
||||
|
||||
// Refresh the editor view contents.
|
||||
function refreshEditor() {
|
||||
global_prefs = document.getElementById("global_prefs").checked;
|
||||
include_defaults = !document.getElementById("hide_defaults").checked;
|
||||
getPreferences(include_defaults, function(response) {
|
||||
getPreferences(global_prefs, include_defaults, function(response) {
|
||||
// Set the JSON in the editor.
|
||||
editor.set(response);
|
||||
});
|
||||
@@ -223,12 +231,13 @@
|
||||
|
||||
// Apply changes from the editor view.
|
||||
function applyEditorChanges() {
|
||||
setPreferences(editor.get());
|
||||
global_prefs = document.getElementById("global_prefs").checked;
|
||||
setPreferences(global_prefs, editor.get());
|
||||
}
|
||||
|
||||
// Refresh the simple view contents.
|
||||
function refreshSimple() {
|
||||
getPreferences(true, function(response) {
|
||||
getPreferences(false, true, function(response) {
|
||||
// Spellcheck settings.
|
||||
if (preferences_state.spellcheck_disabled) {
|
||||
// Cannot enable spell checking when disabled via the command-line.
|
||||
@@ -318,7 +327,7 @@
|
||||
}
|
||||
|
||||
if (has_preferences)
|
||||
setPreferences(preferences);
|
||||
setPreferences(false, preferences);
|
||||
}
|
||||
|
||||
// Called when the proxy type is changed.
|
||||
|
@@ -31,6 +31,7 @@ LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
|
||||
|
||||
IDS_BINARY_TRANSFER_HTML BINARY "tests\\cefclient\\resources\\binary_transfer.html"
|
||||
IDS_BINDING_HTML BINARY "tests\\cefclient\\resources\\binding.html"
|
||||
IDS_CONFIG_HTML BINARY "tests\\cefclient\\resources\\config.html"
|
||||
IDS_DIALOGS_HTML BINARY "tests\\cefclient\\resources\\dialogs.html"
|
||||
IDS_DRAGGABLE_HTML BINARY "tests\\cefclient\\resources\\draggable.html"
|
||||
IDS_HANG_HTML BINARY "tests\\cefclient\\resources\\hang.html"
|
||||
|
@@ -212,4 +212,9 @@ if(OS_WINDOWS)
|
||||
# Copy binary and resource files to the target output directory.
|
||||
COPY_FILES("${CEF_TARGET}" "${CEF_BINARY_FILES}" "${CEF_BINARY_DIR}" "${CEF_TARGET_OUT_DIR}")
|
||||
COPY_FILES("${CEF_TARGET}" "${CEF_RESOURCE_FILES}" "${CEF_RESOURCE_DIR}" "${CEF_TARGET_OUT_DIR}")
|
||||
|
||||
if(USE_SANDBOX)
|
||||
# Set LPAC ACLs required for Windows sandbox support.
|
||||
SET_LPAC_ACLS("${CEF_TARGET}")
|
||||
endif()
|
||||
endif()
|
||||
|
@@ -31,6 +31,7 @@ int XIOErrorHandlerImpl(Display* display) {
|
||||
#endif // defined(CEF_X11)
|
||||
|
||||
// Entry point function for all processes.
|
||||
NO_STACK_PROTECTOR
|
||||
int main(int argc, char* argv[]) {
|
||||
// Provide CEF with command-line arguments.
|
||||
CefMainArgs main_args(argc, argv);
|
||||
|
@@ -260,4 +260,9 @@ if(OS_WINDOWS)
|
||||
"resources/"
|
||||
)
|
||||
COPY_RESOURCES("${CEF_TARGET}" "${UNITTESTS_DATA_RESOURCES_SRCS}" "${PREFIXES}" "${CMAKE_CURRENT_SOURCE_DIR}" "${CEF_TARGET_OUT_DIR}/ceftests_files")
|
||||
|
||||
if(USE_SANDBOX)
|
||||
# Set LPAC ACLs required for Windows sandbox support.
|
||||
SET_LPAC_ACLS("${CEF_TARGET}")
|
||||
endif()
|
||||
endif()
|
||||
|
@@ -1248,11 +1248,7 @@ class CookieAccessSchemeHandlerFactory : public CefSchemeHandlerFactory,
|
||||
}
|
||||
|
||||
void Shutdown(base::OnceClosure complete_callback) {
|
||||
if (!CefCurrentlyOn(TID_IO)) {
|
||||
CefPostTask(TID_IO, base::BindOnce(std::move(complete_callback)));
|
||||
return;
|
||||
}
|
||||
|
||||
EXPECT_IO_THREAD();
|
||||
std::move(complete_callback).Run();
|
||||
}
|
||||
|
||||
@@ -1587,6 +1583,7 @@ class CookieAccessTestHandler : public RoutingTestHandler,
|
||||
CefRefPtr<CefBrowser> browser,
|
||||
CefRefPtr<CefFrame> frame,
|
||||
CefRefPtr<CefRequest> request) override {
|
||||
EXPECT_IO_THREAD();
|
||||
if (test_backend_ == RESOURCE_HANDLER && scheme_factory_) {
|
||||
return scheme_factory_->Create(browser, frame, scheme_, request);
|
||||
}
|
||||
@@ -1810,6 +1807,13 @@ class CookieAccessTestHandler : public RoutingTestHandler,
|
||||
}
|
||||
|
||||
void ShutdownSchemeHandler(base::OnceClosure complete_callback) {
|
||||
if (!CefCurrentlyOn(TID_IO)) {
|
||||
CefPostTask(TID_IO, base::BindOnce(
|
||||
&CookieAccessTestHandler::ShutdownSchemeHandler,
|
||||
this, std::move(complete_callback)));
|
||||
return;
|
||||
}
|
||||
|
||||
EXPECT_TRUE(scheme_factory_);
|
||||
|
||||
if (test_backend_ == SCHEME_HANDLER) {
|
||||
|
@@ -134,6 +134,7 @@ class ScopedPlatformSetup final {
|
||||
|
||||
} // namespace
|
||||
|
||||
NO_STACK_PROTECTOR
|
||||
int main(int argc, char* argv[]) {
|
||||
int exit_code;
|
||||
|
||||
|
@@ -19,6 +19,6 @@ TEST(VersionTest, VersionInfo) {
|
||||
|
||||
TEST(VersionTest, ApiHash) {
|
||||
EXPECT_STREQ(CEF_API_HASH_PLATFORM, cef_api_hash(CEF_API_VERSION, 0));
|
||||
EXPECT_STREQ(CEF_API_HASH_UNIVERSAL, cef_api_hash(CEF_API_VERSION, 1));
|
||||
EXPECT_STREQ(CEF_API_HASH_PLATFORM, cef_api_hash(CEF_API_VERSION, 1));
|
||||
EXPECT_STREQ(CEF_COMMIT_HASH, cef_api_hash(CEF_API_VERSION, 2));
|
||||
}
|
||||
|
@@ -4,343 +4,381 @@
|
||||
|
||||
from __future__ import absolute_import
|
||||
from __future__ import print_function
|
||||
from typing import Dict, List
|
||||
from clang_util import clang_eval
|
||||
from file_util import *
|
||||
import hashlib
|
||||
import itertools
|
||||
import os
|
||||
import re
|
||||
import string
|
||||
import sys
|
||||
import time
|
||||
from version_util import EXP_VERSION
|
||||
|
||||
# Determines string type for python 2 and python 3.
|
||||
if sys.version_info[0] == 3:
|
||||
string_type = str
|
||||
else:
|
||||
string_type = basestring
|
||||
API_TOKEN = '#if CEF_API'
|
||||
OS_TOKEN = '#if defined(OS_'
|
||||
INCLUDE_START_MARKER = 'int begin_includes_tag;\n'
|
||||
INCLUDE_DIRS = [
|
||||
'.', # Includes relative to the 'src/cef' directory.
|
||||
'..', # Includes relative to the 'src' directory.
|
||||
]
|
||||
PLATFORM_DEFINES = {
|
||||
'windows': ['OS_WIN', 'ARCH_CPU_X86_64'],
|
||||
'mac': ['OS_MAC', 'OS_POSIX', 'ARCH_CPU_ARM64'],
|
||||
'linux': ['OS_LINUX', 'OS_POSIX', 'CEF_X11', 'ARCH_CPU_X86_64'],
|
||||
}
|
||||
|
||||
SYSTEM_INCLUDES_PATTERN = re.compile(r'(#include <[^>]+>)')
|
||||
FUNCTION_DECLARATION_PATTERN = re.compile(
|
||||
r'\nCEF_EXPORT\s+?.*?\s+?(\w+)\s*?\(.*?\)\s*?;', re.DOTALL)
|
||||
STRUCT_PATTERN = re.compile(
|
||||
r'\ntypedef\s+?struct\s+?(\w+)\s+?\{.*?\}\s+?(\w+)\s*?;', re.DOTALL)
|
||||
ENUM_PATTERN = re.compile(r'\ntypedef\s+?enum\s+?\{.*?\}\s+?(\w+)\s*?;',
|
||||
re.DOTALL)
|
||||
TYPEDEF_PATTERN = re.compile(r'\ntypedef\s+?.*?\s+(\w+);')
|
||||
WHITESPACE_PATTERN = re.compile(r'\s+')
|
||||
PARENTHESIS_PATTERN = re.compile(r'\(\s+')
|
||||
SINGLE_LINE_COMMENT_PATTERN = re.compile(r'//.*\n')
|
||||
CEF_STRING_TYPE_PATTERN = re.compile(
|
||||
r'\n\s*?#\s*?define\s+?(CEF_STRING_TYPE_\w+)\s+?.*?\n')
|
||||
DEFINE_PATTERN = re.compile(r'#define\s+?.*?')
|
||||
|
||||
|
||||
def _run_clang_eval(filename, content, api_version, added_defines, verbose):
|
||||
# Add a tag so we know where the header-specific output begins.
|
||||
tag = 'int begin_includes_tag;\n'
|
||||
def _prepare_content(content: str) -> str:
|
||||
"""
|
||||
Add a marker to the content to indicate where the header-specific output
|
||||
begins and replace system includes with a placeholder
|
||||
"""
|
||||
find = '#ifdef __cplusplus\nextern "C" {'
|
||||
pos = content.find(find)
|
||||
assert pos > 0, filename
|
||||
content = content[0:pos] + tag + content[pos:]
|
||||
assert pos > 0, f'Cannot find "{find}" in {content}'
|
||||
content = content[0:pos] + INCLUDE_START_MARKER + content[pos:]
|
||||
|
||||
defines = [
|
||||
# Makes sure CEF_EXPORT is defined.
|
||||
'USING_CEF_SHARED',
|
||||
content = DEFINE_PATTERN.sub('//DEFINE_PLACEHOLDER//', content)
|
||||
return SYSTEM_INCLUDES_PATTERN.sub('//INCLUDE_PLACEHOLDER//', content)
|
||||
|
||||
# Avoid include of generated headers.
|
||||
'GENERATING_CEF_API_HASH',
|
||||
]
|
||||
|
||||
if filename.find('test/') >= 0:
|
||||
# Avoids errors parsing test includes.
|
||||
defines.append('UNIT_TEST')
|
||||
|
||||
# Not the experimental version.
|
||||
api_version = int(api_version)
|
||||
if api_version != EXP_VERSION:
|
||||
# Specify the exact version.
|
||||
defines.append('CEF_API_VERSION=%d' % api_version)
|
||||
|
||||
if not added_defines is None:
|
||||
defines.extend(added_defines)
|
||||
|
||||
includes = [
|
||||
# Includes relative to the 'src/cef' directory.
|
||||
'.',
|
||||
# Includes relative to the 'src' directory.
|
||||
'..',
|
||||
]
|
||||
|
||||
result = clang_eval(
|
||||
filename,
|
||||
content,
|
||||
defines=defines,
|
||||
includes=includes,
|
||||
as_cpp=False,
|
||||
verbose=verbose)
|
||||
if result is None:
|
||||
return None
|
||||
|
||||
pos = result.find(tag)
|
||||
assert pos > 0, filename
|
||||
result = result[pos + len(tag):]
|
||||
def _process_result(result: str) -> str:
|
||||
"""
|
||||
Remove the non header-specific output and undo substitutions from cef_export.h
|
||||
"""
|
||||
pos = result.find(INCLUDE_START_MARKER)
|
||||
if pos == -1:
|
||||
return result
|
||||
result = result[pos + len(INCLUDE_START_MARKER):]
|
||||
|
||||
replacements = [
|
||||
# Undo substitutions from cef_export.h
|
||||
['__declspec(dllimport)', 'CEF_EXPORT'],
|
||||
['__attribute__((visibility("default")))', 'CEF_EXPORT'],
|
||||
['__stdcall', ''],
|
||||
]
|
||||
|
||||
for find, replace in replacements:
|
||||
result = result.replace(find, replace)
|
||||
|
||||
return result
|
||||
# Must always start with newline as required by _parse_objects()
|
||||
return '\n' + result
|
||||
|
||||
|
||||
class cef_api_hash:
|
||||
def _get_defines(filename: str, added_defines: list) -> List[str]:
|
||||
defines = [
|
||||
# Makes sure CEF_EXPORT is defined.
|
||||
'USING_CEF_SHARED',
|
||||
# Avoid include of generated headers.
|
||||
'GENERATING_CEF_API_HASH',
|
||||
]
|
||||
|
||||
# Avoids errors parsing test includes.
|
||||
if filename.find('test/') >= 0:
|
||||
defines.append('UNIT_TEST')
|
||||
|
||||
defines.extend(added_defines)
|
||||
return defines
|
||||
|
||||
|
||||
def parse_versioned_content(filename: str,
|
||||
content: str,
|
||||
api_version: str,
|
||||
added_defines: list,
|
||||
debug_dir,
|
||||
verbose) -> list:
|
||||
"""
|
||||
Parse the header file content using clang with the specified API version
|
||||
Used for files that are version-specific but not platform-specific
|
||||
"""
|
||||
content = _prepare_content(content)
|
||||
defines = _get_defines(filename, added_defines)
|
||||
|
||||
if api_version != EXP_VERSION:
|
||||
# Specify the exact version.
|
||||
defines.append(f'CEF_API_VERSION={api_version}')
|
||||
|
||||
result = clang_eval(filename, content, defines, INCLUDE_DIRS, verbose)
|
||||
assert result, f'clang failed to eval {filename} with {api_version=}'
|
||||
|
||||
result = _process_result(result)
|
||||
|
||||
if debug_dir:
|
||||
_write_debug_file(debug_dir, 'clang-' + filename.replace('/', '-'), result)
|
||||
|
||||
return _parse_objects(filename, result, 'universal')
|
||||
|
||||
|
||||
def parse_platformed_content(filename: str,
|
||||
content: str,
|
||||
debug_dir,
|
||||
verbose,
|
||||
api_version,
|
||||
added_defines: list) -> list:
|
||||
"""
|
||||
Parse the header file content using clang for every supported platform
|
||||
with the specified API version. Used for files that are both version-specific
|
||||
and platform-specific.
|
||||
"""
|
||||
content = _prepare_content(content)
|
||||
defines = _get_defines(filename, added_defines)
|
||||
|
||||
if api_version and api_version != EXP_VERSION:
|
||||
# Specify the exact version.
|
||||
defines.append(f'CEF_API_VERSION={api_version}')
|
||||
|
||||
content_objects = []
|
||||
for platform, platform_defines in PLATFORM_DEFINES.items():
|
||||
result = clang_eval(filename, content, defines + platform_defines,
|
||||
INCLUDE_DIRS, verbose)
|
||||
assert result, f'clang failed to eval {filename} on {platform=}'
|
||||
|
||||
result = _process_result(result)
|
||||
if debug_dir:
|
||||
_write_debug_file(
|
||||
debug_dir, f'clang-{platform}-' + filename.replace('/', '-'), result)
|
||||
|
||||
objects = _parse_objects(filename, result, platform)
|
||||
content_objects.extend(objects)
|
||||
|
||||
return content_objects
|
||||
|
||||
|
||||
def _write_debug_file(debug_dir, filename, content) -> None:
|
||||
make_dir(debug_dir)
|
||||
outfile = os.path.join(debug_dir, filename)
|
||||
dir = os.path.dirname(outfile)
|
||||
make_dir(dir)
|
||||
if not isinstance(content, str):
|
||||
content = '\n'.join(content)
|
||||
write_file(outfile, content)
|
||||
|
||||
|
||||
def _parse_objects(filename: str, content: str, platform: str) -> list:
|
||||
objects = []
|
||||
content = SINGLE_LINE_COMMENT_PATTERN.sub('', content)
|
||||
|
||||
for m in FUNCTION_DECLARATION_PATTERN.finditer(content):
|
||||
objects.append({
|
||||
'filename': filename,
|
||||
'name': m.group(1),
|
||||
'platform': platform,
|
||||
'text': _prepare_text(m.group(0))
|
||||
})
|
||||
|
||||
for m in STRUCT_PATTERN.finditer(content):
|
||||
# Remove 'CEF_CALLBACK' to normalize cross-platform clang output
|
||||
objects.append({
|
||||
'filename': filename,
|
||||
'name': m.group(2),
|
||||
'platform': platform,
|
||||
'text': _prepare_text(m.group(0).replace('CEF_CALLBACK', ''))
|
||||
})
|
||||
|
||||
for m in ENUM_PATTERN.finditer(content):
|
||||
objects.append({
|
||||
'filename': filename,
|
||||
'name': m.group(1),
|
||||
'platform': platform,
|
||||
'text': _prepare_text(m.group(0))
|
||||
})
|
||||
|
||||
for m in TYPEDEF_PATTERN.finditer(content):
|
||||
if m.group(1) == 'char16_t':
|
||||
# Skip char16_t typedefs to avoid platform-specific differences.
|
||||
continue
|
||||
|
||||
objects.append({
|
||||
'filename': filename,
|
||||
'name': m.group(1),
|
||||
'platform': platform,
|
||||
'text': _prepare_text(m.group(0))
|
||||
})
|
||||
|
||||
return objects
|
||||
|
||||
|
||||
def _prepare_text(text: str) -> str:
|
||||
""" Normalize text for hashing. """
|
||||
text = WHITESPACE_PATTERN.sub(' ', text.strip())
|
||||
return PARENTHESIS_PATTERN.sub('(', text)
|
||||
|
||||
|
||||
def _parse_string_type(filename: str, content: str) -> list:
|
||||
""" Grab defined CEF_STRING_TYPE_xxx """
|
||||
objects = []
|
||||
for m in CEF_STRING_TYPE_PATTERN.finditer(content):
|
||||
objects.append({
|
||||
'filename': filename,
|
||||
'name': m.group(1),
|
||||
'text': _prepare_text(m.group(0)),
|
||||
'platform': 'universal'
|
||||
})
|
||||
return objects
|
||||
|
||||
|
||||
def _get_final_sig(objects, platform) -> str:
|
||||
return '\n'.join(o['text'] for o in objects
|
||||
if o['platform'] == 'universal' or o['platform'] == platform)
|
||||
|
||||
|
||||
def _get_filenames(header_dir) -> List[str]:
|
||||
""" Return file names to be processed, relative to header_dir """
|
||||
cef_dir = os.path.abspath(os.path.join(header_dir, os.pardir))
|
||||
|
||||
# Read the variables list from the autogenerated cef_paths.gypi file.
|
||||
cef_paths = eval_file(os.path.join(cef_dir, 'cef_paths.gypi'))
|
||||
cef_paths = cef_paths['variables']
|
||||
# Read the variables list from the manually edited cef_paths2.gypi file.
|
||||
cef_paths2 = eval_file(os.path.join(cef_dir, 'cef_paths2.gypi'))
|
||||
cef_paths2 = cef_paths2['variables']
|
||||
|
||||
# List of all C API include/ files.
|
||||
paths = cef_paths2['includes_capi'] + cef_paths2['includes_common_capi'] + \
|
||||
cef_paths2['includes_linux_capi'] + cef_paths2['includes_mac_capi'] + \
|
||||
cef_paths2['includes_win_capi'] + cef_paths['autogen_capi_includes']
|
||||
|
||||
return [
|
||||
os.path.relpath(os.path.join(cef_dir, filename), header_dir).replace(
|
||||
'\\', '/').lower() for filename in paths
|
||||
]
|
||||
|
||||
|
||||
def _save_objects_to_file(debug_dir: str, objects: list) -> None:
|
||||
name_len = max([len(o['name']) for o in objects])
|
||||
filename_len = max([len(o['filename']) for o in objects])
|
||||
platform_len = max([len(o['platform']) for o in objects])
|
||||
dump_sig = [
|
||||
f"{o['name']:<{name_len}}|{o['filename']:<{filename_len}}|{o['platform']:<{platform_len}}|{o['text']}"
|
||||
for o in objects
|
||||
]
|
||||
_write_debug_file(debug_dir, 'objects.txt', dump_sig)
|
||||
|
||||
|
||||
class CefApiHasher:
|
||||
""" CEF API hash calculator """
|
||||
|
||||
def __init__(self, headerdir, verbose=False):
|
||||
if headerdir is None or len(headerdir) == 0:
|
||||
raise AssertionError("headerdir is not specified")
|
||||
def __init__(self, header_dir, debug_dir, verbose=False):
|
||||
if header_dir is None or len(header_dir) == 0:
|
||||
raise AssertionError('header_dir is not specified')
|
||||
|
||||
self.__headerdir = headerdir
|
||||
self.__verbose = verbose
|
||||
|
||||
self.platforms = ["windows", "mac", "linux"]
|
||||
|
||||
cef_dir = os.path.abspath(os.path.join(self.__headerdir, os.pardir))
|
||||
|
||||
# Read the variables list from the autogenerated cef_paths.gypi file.
|
||||
cef_paths = eval_file(os.path.join(cef_dir, 'cef_paths.gypi'))
|
||||
cef_paths = cef_paths['variables']
|
||||
|
||||
# Read the variables list from the manually edited cef_paths2.gypi file.
|
||||
cef_paths2 = eval_file(os.path.join(cef_dir, 'cef_paths2.gypi'))
|
||||
cef_paths2 = cef_paths2['variables']
|
||||
|
||||
# Excluded files (paths relative to the include/ directory).
|
||||
excluded_files = []
|
||||
|
||||
# List of platform-specific C API include/ files.
|
||||
self.platform_files = {
|
||||
"windows":
|
||||
self.__get_filenames(cef_dir, cef_paths2['includes_win_capi'],
|
||||
excluded_files),
|
||||
"mac":
|
||||
self.__get_filenames(cef_dir, cef_paths2['includes_mac_capi'],
|
||||
excluded_files),
|
||||
"linux":
|
||||
self.__get_filenames(cef_dir, cef_paths2['includes_linux_capi'],
|
||||
excluded_files)
|
||||
}
|
||||
|
||||
# List of all C API include/ files.
|
||||
paths = cef_paths2['includes_capi'] + cef_paths2['includes_common_capi'] + \
|
||||
cef_paths2['includes_linux_capi'] + cef_paths2['includes_mac_capi'] + \
|
||||
cef_paths2['includes_win_capi'] + cef_paths['autogen_capi_includes']
|
||||
self.filenames = self.__get_filenames(cef_dir, paths, excluded_files)
|
||||
|
||||
self.filecontents = {}
|
||||
self.filecontentobjs = {}
|
||||
self.filenames = _get_filenames(header_dir)
|
||||
self.debug_dir = debug_dir
|
||||
self.verbose = verbose
|
||||
self.versioned_contents = {}
|
||||
self.platformed_contents = {}
|
||||
self.file_content_objs = {}
|
||||
|
||||
# Cache values that will not change between calls to calculate().
|
||||
for filename in self.filenames:
|
||||
if self.__verbose:
|
||||
print("Processing " + filename + "...")
|
||||
self.print(f'Processing {filename} ...')
|
||||
|
||||
assert not filename in self.filecontents, filename
|
||||
assert not filename in self.filecontentobjs, filename
|
||||
if filename in self.versioned_contents \
|
||||
or filename in self.platformed_contents \
|
||||
or filename in self.file_content_objs:
|
||||
self.print(f'{filename} already processed, skipping...')
|
||||
continue
|
||||
|
||||
content = read_file(os.path.join(self.__headerdir, filename), True)
|
||||
content = read_file(os.path.join(header_dir, filename), normalize=True)
|
||||
content_objects = None
|
||||
|
||||
# Parse cef_string.h happens in special case: grab only defined CEF_STRING_TYPE_xxx declaration
|
||||
if filename == "internal/cef_string.h":
|
||||
content_objects = self.__parse_string_type(content)
|
||||
elif content.find('#if CEF_API') >= 0:
|
||||
# Needs to be passed to clang with version-specific defines.
|
||||
self.filecontents[filename] = content
|
||||
is_platform_specific = OS_TOKEN in content
|
||||
is_version_specific = API_TOKEN in content
|
||||
|
||||
# Special case for parsing cef_string.h:
|
||||
# Only extract declarations of the form #define CEF_STRING_TYPE_xxx
|
||||
if filename == 'internal/cef_string.h':
|
||||
content_objects = _parse_string_type(filename, content)
|
||||
elif is_platform_specific and not is_version_specific:
|
||||
# Parse once and cache for all platforms
|
||||
content_objects = parse_platformed_content(
|
||||
filename,
|
||||
content,
|
||||
debug_dir,
|
||||
verbose,
|
||||
api_version=None,
|
||||
added_defines=[])
|
||||
elif is_platform_specific and is_version_specific:
|
||||
# Needs to be passed to clang with version and platform defines.
|
||||
self.platformed_contents[filename] = content
|
||||
elif is_version_specific:
|
||||
# Needs to be passed to clang with version defines.
|
||||
self.versioned_contents[filename] = content
|
||||
else:
|
||||
content_objects = self.__parse_objects(content)
|
||||
content_objects = _parse_objects(filename, content, 'universal')
|
||||
|
||||
if not content_objects is None:
|
||||
self.__prepare_objects(filename, content_objects)
|
||||
self.filecontentobjs[filename] = content_objects
|
||||
if content_objects is not None:
|
||||
self.file_content_objs[filename] = content_objects
|
||||
|
||||
def calculate(self, api_version, debug_dir=None, added_defines=None):
|
||||
debug_enabled = not (debug_dir is None) and len(debug_dir) > 0
|
||||
def calculate(self, api_version: str, added_defines: list) -> Dict[str, str]:
|
||||
""" Calculate the API hash per platform for the specified API version """
|
||||
debug_dir = os.path.join(self.debug_dir,
|
||||
api_version) if self.debug_dir else None
|
||||
|
||||
objects = []
|
||||
for filename in self.filenames:
|
||||
if self.__verbose:
|
||||
print("Processing " + filename + "...")
|
||||
self.print(f'Processing {filename}...')
|
||||
|
||||
content = self.filecontents.get(filename, None)
|
||||
if not content is None:
|
||||
assert content.find('#if CEF_API') >= 0, filename
|
||||
content = _run_clang_eval(filename, content, api_version, added_defines,
|
||||
self.__verbose)
|
||||
if content is None:
|
||||
sys.stderr.write(
|
||||
'ERROR: Failed to compute API hash for %s\n' % filename)
|
||||
return False
|
||||
if debug_enabled:
|
||||
self.__write_debug_file(
|
||||
debug_dir, 'clang-' + filename.replace('/', '-'), content)
|
||||
|
||||
# content must always start with newline as required by __parse_objects()
|
||||
content_objects = self.__parse_objects('\n' + content)
|
||||
self.__prepare_objects(filename, content_objects)
|
||||
if filename in self.versioned_contents:
|
||||
content = self.versioned_contents.get(filename, None)
|
||||
content_objects = parse_versioned_content(filename, content,
|
||||
api_version, added_defines,
|
||||
debug_dir, self.verbose)
|
||||
elif filename in self.platformed_contents:
|
||||
content = self.platformed_contents.get(filename, None)
|
||||
content_objects = parse_platformed_content(filename, content, debug_dir,
|
||||
self.verbose, api_version,
|
||||
added_defines)
|
||||
else:
|
||||
content_objects = self.filecontentobjs.get(filename, None)
|
||||
content_objects = self.file_content_objs.get(filename, None)
|
||||
|
||||
assert not content_objects is None, filename
|
||||
objects.extend(content_objects)
|
||||
# May be None if the full contents of the file are excluded at certain API versions.
|
||||
if not content_objects is None:
|
||||
objects.extend(content_objects)
|
||||
|
||||
# objects will be sorted including filename, to make stable universal hashes
|
||||
objects = sorted(objects, key=lambda o: o["name"] + "@" + o["filename"])
|
||||
# objects will be sorted including filename to make stable hashes
|
||||
objects = sorted(objects, key=lambda o: f"{o['name']}@{o['filename']}")
|
||||
|
||||
if debug_enabled:
|
||||
namelen = max([len(o["name"]) for o in objects])
|
||||
filenamelen = max([len(o["filename"]) for o in objects])
|
||||
dumpsig = []
|
||||
for o in objects:
|
||||
dumpsig.append(
|
||||
format(o["name"], str(namelen) + "s") + "|" + format(
|
||||
o["filename"], "" + str(filenamelen) + "s") + "|" + o["text"])
|
||||
self.__write_debug_file(debug_dir, "objects.txt", dumpsig)
|
||||
if debug_dir:
|
||||
_save_objects_to_file(debug_dir, objects)
|
||||
|
||||
revisions = {}
|
||||
hashes = {}
|
||||
for platform in PLATFORM_DEFINES.keys():
|
||||
sig = _get_final_sig(objects, platform)
|
||||
if debug_dir:
|
||||
_write_debug_file(debug_dir, f'{platform}.sig', sig)
|
||||
hashes[platform] = hashlib.sha1(sig.encode('utf-8')).hexdigest()
|
||||
|
||||
for platform in itertools.chain(["universal"], self.platforms):
|
||||
sig = self.__get_final_sig(objects, platform)
|
||||
if debug_enabled:
|
||||
self.__write_debug_file(debug_dir, platform + ".sig", sig)
|
||||
revstr = hashlib.sha1(sig.encode('utf-8')).hexdigest()
|
||||
revisions[platform] = revstr
|
||||
return hashes
|
||||
|
||||
return revisions
|
||||
|
||||
def __parse_objects(self, content):
|
||||
""" Returns array of objects in content file. """
|
||||
objects = []
|
||||
content = re.sub(r"//.*\n", "", content)
|
||||
|
||||
# function declarations
|
||||
for m in re.finditer(
|
||||
r"\nCEF_EXPORT\s+?.*?\s+?(\w+)\s*?\(.*?\)\s*?;",
|
||||
content,
|
||||
flags=re.DOTALL):
|
||||
object = {"name": m.group(1), "text": m.group(0).strip()}
|
||||
objects.append(object)
|
||||
|
||||
# structs
|
||||
for m in re.finditer(
|
||||
r"\ntypedef\s+?struct\s+?(\w+)\s+?\{.*?\}\s+?(\w+)\s*?;",
|
||||
content,
|
||||
flags=re.DOTALL):
|
||||
text = m.group(0).strip()
|
||||
# remove 'CEF_CALLBACK' to normalize cross-platform clang output
|
||||
text = text.replace('CEF_CALLBACK', '')
|
||||
object = {"name": m.group(2), "text": text}
|
||||
objects.append(object)
|
||||
|
||||
# enums
|
||||
for m in re.finditer(
|
||||
r"\ntypedef\s+?enum\s+?\{.*?\}\s+?(\w+)\s*?;", content,
|
||||
flags=re.DOTALL):
|
||||
object = {"name": m.group(1), "text": m.group(0).strip()}
|
||||
objects.append(object)
|
||||
|
||||
# typedefs
|
||||
for m in re.finditer(r"\ntypedef\s+?.*?\s+(\w+);", content, flags=0):
|
||||
object = {"name": m.group(1), "text": m.group(0).strip()}
|
||||
objects.append(object)
|
||||
|
||||
return objects
|
||||
|
||||
def __prepare_objects(self, filename, objects):
|
||||
platforms = list(
|
||||
[p for p in self.platforms if self.__is_platform_filename(filename, p)])
|
||||
for o in objects:
|
||||
o["text"] = self.__prepare_text(o["text"])
|
||||
o["platforms"] = platforms
|
||||
o["filename"] = filename
|
||||
|
||||
def __parse_string_type(self, content):
|
||||
""" Grab defined CEF_STRING_TYPE_xxx """
|
||||
objects = []
|
||||
for m in re.finditer(
|
||||
r"\n\s*?#\s*?define\s+?(CEF_STRING_TYPE_\w+)\s+?.*?\n",
|
||||
content,
|
||||
flags=0):
|
||||
object = {
|
||||
"name": m.group(1),
|
||||
"text": m.group(0),
|
||||
}
|
||||
objects.append(object)
|
||||
return objects
|
||||
|
||||
def __prepare_text(self, text):
|
||||
text = text.strip()
|
||||
text = re.sub(r"\s+", " ", text)
|
||||
text = re.sub(r"\(\s+", "(", text)
|
||||
return text
|
||||
|
||||
def __get_final_sig(self, objects, platform):
|
||||
sig = []
|
||||
|
||||
for o in objects:
|
||||
if platform == "universal" or platform in o["platforms"]:
|
||||
sig.append(o["text"])
|
||||
|
||||
return "\n".join(sig)
|
||||
|
||||
def __get_filenames(self, cef_dir, paths, excluded_files):
|
||||
""" Returns file names to be processed, relative to headerdir """
|
||||
filenames = [
|
||||
os.path.relpath(os.path.join(cef_dir, filename),
|
||||
self.__headerdir).replace('\\', '/').lower()
|
||||
for filename in paths
|
||||
]
|
||||
|
||||
if len(excluded_files) == 0:
|
||||
return filenames
|
||||
|
||||
return [
|
||||
filename for filename in filenames if not filename in excluded_files
|
||||
]
|
||||
|
||||
def __is_platform_filename(self, filename, platform):
|
||||
if platform == "universal":
|
||||
return True
|
||||
if not platform in self.platform_files:
|
||||
return False
|
||||
listed = False
|
||||
for p in self.platforms:
|
||||
if filename in self.platform_files[p]:
|
||||
if p == platform:
|
||||
return True
|
||||
else:
|
||||
listed = True
|
||||
return not listed
|
||||
|
||||
def __write_debug_file(self, debug_dir, filename, content):
|
||||
make_dir(debug_dir)
|
||||
outfile = os.path.join(debug_dir, filename)
|
||||
dir = os.path.dirname(outfile)
|
||||
make_dir(dir)
|
||||
if not isinstance(content, string_type):
|
||||
content = "\n".join(content)
|
||||
write_file(outfile, content)
|
||||
def print(self, msg):
|
||||
if self.verbose:
|
||||
print(msg)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
if __name__ == '__main__':
|
||||
from optparse import OptionParser
|
||||
import time
|
||||
|
||||
disc = """
|
||||
This utility calculates CEF API hash.
|
||||
"""
|
||||
|
||||
parser = OptionParser(description=disc)
|
||||
parser = OptionParser(description='This utility calculates CEF API hash')
|
||||
parser.add_option(
|
||||
'--cpp-header-dir',
|
||||
dest='cppheaderdir',
|
||||
dest='cpp_header_dir',
|
||||
metavar='DIR',
|
||||
help='input directory for C++ header files [required]')
|
||||
parser.add_option(
|
||||
'--debug-dir',
|
||||
dest='debugdir',
|
||||
dest='debug_dir',
|
||||
metavar='DIR',
|
||||
help='intermediate directory for easy debugging')
|
||||
parser.add_option(
|
||||
@@ -352,28 +390,16 @@ if __name__ == "__main__":
|
||||
help='output detailed status information')
|
||||
(options, args) = parser.parse_args()
|
||||
|
||||
# the cppheader option is required
|
||||
if options.cppheaderdir is None:
|
||||
# the cpp_header_dir option is required
|
||||
if options.cpp_header_dir is None:
|
||||
parser.print_help(sys.stdout)
|
||||
sys.exit()
|
||||
|
||||
# calculate
|
||||
c_start_time = time.time()
|
||||
calc = CefApiHasher(options.cpp_header_dir, options.debug_dir,
|
||||
options.verbose)
|
||||
revisions = calc.calculate(EXP_VERSION, [])
|
||||
|
||||
calc = cef_api_hash(options.cppheaderdir, options.debugdir, options.verbose)
|
||||
revisions = calc.calculate(api_version=EXP_VERSION)
|
||||
|
||||
c_completed_in = time.time() - c_start_time
|
||||
|
||||
if bool(revisions):
|
||||
print("{")
|
||||
for k in sorted(revisions.keys()):
|
||||
print(format("\"" + k + "\"", ">12s") + ": \"" + revisions[k] + "\"")
|
||||
print("}")
|
||||
|
||||
# print
|
||||
# print 'Completed in: ' + str(c_completed_in)
|
||||
# print
|
||||
|
||||
# print "Press any key to continue...";
|
||||
# sys.stdin.readline();
|
||||
print('{')
|
||||
for k in sorted(revisions.keys()):
|
||||
print(format('"' + k + '"', '>12s') + ': "' + revisions[k] + '"')
|
||||
print('}')
|
||||
|
375
tools/cef_api_hash_test.py
Normal file
375
tools/cef_api_hash_test.py
Normal file
@@ -0,0 +1,375 @@
|
||||
# Copyright (c) 2025 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.
|
||||
|
||||
# Execute the following command to run unit tests:
|
||||
# python3 -m unittest discover -s tools -p *_test.py
|
||||
|
||||
from cef_api_hash import *
|
||||
from collections import Counter
|
||||
import unittest
|
||||
|
||||
# Test constants:
|
||||
FILENAME = 'test.h'
|
||||
NONE_DEBUG_DIR = None
|
||||
VERBOSE = False
|
||||
ADDED_DEFINES = []
|
||||
|
||||
CEF_TYPES_WIN = """#ifndef CEF_INCLUDE_INTERNAL_CEF_TYPES_WIN_H_
|
||||
#define CEF_INCLUDE_INTERNAL_CEF_TYPES_WIN_H_
|
||||
#pragma once
|
||||
|
||||
#if !defined(GENERATING_CEF_API_HASH)
|
||||
#include "include/base/cef_build.h"
|
||||
#endif
|
||||
|
||||
#if defined(OS_WIN)
|
||||
|
||||
#if !defined(GENERATING_CEF_API_HASH)
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
#include "include/cef_api_hash.h"
|
||||
#include "include/internal/cef_types_runtime.h"
|
||||
|
||||
#define kNullCursorHandle NULL
|
||||
#define kNullEventHandle NULL
|
||||
#define kNullWindowHandle NULL
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
// Handle types.
|
||||
typedef HWND cef_window_handle_t;
|
||||
|
||||
typedef struct _cef_window_info_t {
|
||||
size_t size;
|
||||
DWORD ex_style;
|
||||
HMENU menu;
|
||||
cef_window_handle_t parent_window;
|
||||
cef_runtime_style_t runtime_style;
|
||||
#if CEF_API_ADDED(13304)
|
||||
int api_version_test;
|
||||
#endif
|
||||
} cef_window_info_t;
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif // OS_WIN
|
||||
#endif // CEF_INCLUDE_INTERNAL_CEF_TYPES_WIN_H_
|
||||
"""
|
||||
|
||||
CEF_TYPES_MAC = """#ifndef CEF_INCLUDE_INTERNAL_CEF_TYPES_MAC_H_
|
||||
#define CEF_INCLUDE_INTERNAL_CEF_TYPES_MAC_H_
|
||||
#pragma once
|
||||
|
||||
#if !defined(GENERATING_CEF_API_HASH)
|
||||
#include "include/base/cef_build.h"
|
||||
#endif
|
||||
|
||||
#include <this_header_does_not_exist.h>
|
||||
|
||||
#if defined(OS_MAC)
|
||||
#include "include/internal/cef_string.h"
|
||||
#include "include/internal/cef_types_geometry.h"
|
||||
#include "include/internal/cef_types_runtime.h"
|
||||
|
||||
#define kNullCursorHandle NULL
|
||||
|
||||
#ifdef __OBJC__
|
||||
#if __has_feature(objc_arc)
|
||||
#define CAST_CEF_CURSOR_HANDLE_TO_NSCURSOR(handle) ((__bridge NSCursor*)handle)
|
||||
#define CAST_CEF_WINDOW_HANDLE_TO_NSVIEW(handle) ((__bridge NSView*)handle)
|
||||
|
||||
#define CAST_NSCURSOR_TO_CEF_CURSOR_HANDLE(cursor) ((__bridge void*)cursor)
|
||||
#define CAST_NSVIEW_TO_CEF_WINDOW_HANDLE(view) ((__bridge void*)view)
|
||||
#else // __has_feature(objc_arc)
|
||||
#define CAST_CEF_CURSOR_HANDLE_TO_NSCURSOR(handle) ((NSCursor*)handle)
|
||||
#define CAST_CEF_WINDOW_HANDLE_TO_NSVIEW(handle) ((NSView*)handle)
|
||||
|
||||
#define CAST_NSCURSOR_TO_CEF_CURSOR_HANDLE(cursor) ((void*)cursor)
|
||||
#define CAST_NSVIEW_TO_CEF_WINDOW_HANDLE(view) ((void*)view)
|
||||
#endif // __has_feature(objc_arc)
|
||||
#endif // __OBJC__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
// Actually NSView*
|
||||
typedef void* cef_window_handle_t;
|
||||
|
||||
///
|
||||
/// Class representing window information.
|
||||
///
|
||||
typedef struct _cef_window_info_t {
|
||||
size_t size;
|
||||
cef_string_t window_name;
|
||||
cef_rect_t bounds;
|
||||
cef_window_handle_t view;
|
||||
cef_runtime_style_t runtime_style;
|
||||
} cef_window_info_t;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // OS_MAC
|
||||
#endif // CEF_INCLUDE_INTERNAL_CEF_TYPES_MAC_H_
|
||||
"""
|
||||
|
||||
CEF_TYPES_LINUX = """#ifndef CEF_INCLUDE_INTERNAL_CEF_TYPES_LINUX_H_
|
||||
#define CEF_INCLUDE_INTERNAL_CEF_TYPES_LINUX_H_
|
||||
#pragma once
|
||||
|
||||
#if !defined(GENERATING_CEF_API_HASH)
|
||||
#include "include/base/cef_build.h"
|
||||
#endif
|
||||
|
||||
#if defined(OS_LINUX)
|
||||
|
||||
#include "include/internal/cef_export.h"
|
||||
#include "include/internal/cef_string.h"
|
||||
#include "include/internal/cef_types_color.h"
|
||||
#include "include/internal/cef_types_geometry.h"
|
||||
#include "include/internal/cef_types_osr.h"
|
||||
#include "include/internal/cef_types_runtime.h"
|
||||
|
||||
#define kNullCursorHandle 0
|
||||
#define kNullEventHandle NULL
|
||||
#define kNullWindowHandle 0
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#if defined(CEF_X11)
|
||||
typedef union _XEvent XEvent;
|
||||
typedef struct _XDisplay XDisplay;
|
||||
|
||||
// Handle types.
|
||||
typedef XEvent* cef_event_handle_t;
|
||||
#else
|
||||
typedef void* cef_event_handle_t;
|
||||
#endif
|
||||
|
||||
typedef unsigned long cef_window_handle_t;
|
||||
|
||||
///
|
||||
/// Return the singleton X11 display shared with Chromium. The display is not
|
||||
/// thread-safe and must only be accessed on the browser process UI thread.
|
||||
///
|
||||
#if defined(CEF_X11)
|
||||
CEF_EXPORT XDisplay* cef_get_xdisplay(void);
|
||||
#endif
|
||||
|
||||
typedef struct _cef_window_info_t {
|
||||
size_t size;
|
||||
cef_string_t window_name;
|
||||
cef_rect_t bounds;
|
||||
cef_window_handle_t parent_window;
|
||||
cef_window_handle_t window;
|
||||
cef_runtime_style_t runtime_style;
|
||||
} cef_window_info_t;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // OS_LINUX
|
||||
|
||||
#endif // CEF_INCLUDE_INTERNAL_CEF_TYPES_LINUX_H_
|
||||
"""
|
||||
|
||||
CEF_TYPES = """#ifndef CEF_INCLUDE_INTERNAL_CEF_TYPES_H_
|
||||
#define CEF_INCLUDE_INTERNAL_CEF_TYPES_H_
|
||||
#pragma once
|
||||
|
||||
#include "include/cef_api_hash.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef enum {
|
||||
CEF_CPAIT_OPTIMIZATION_GUIDE,
|
||||
#if CEF_API_ADDED(13304)
|
||||
CEF_CPAIT_COLLABORATION_MESSAGING,
|
||||
#endif
|
||||
CEF_CPAIT_NUM_VALUES,
|
||||
} cef_chrome_page_action_icon_type_t;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // CEF_INCLUDE_INTERNAL_CEF_TYPES_H_
|
||||
"""
|
||||
|
||||
|
||||
class TestRunClangEval(unittest.TestCase):
|
||||
|
||||
def test_parse_platformed_content_version_13304(self):
|
||||
expected_objects = [{
|
||||
'filename': FILENAME,
|
||||
'name': 'cef_window_handle_t',
|
||||
'platform': 'windows',
|
||||
'text': 'typedef HWND cef_window_handle_t;'
|
||||
}, {
|
||||
'filename':
|
||||
FILENAME,
|
||||
'name':
|
||||
'cef_window_info_t',
|
||||
'platform':
|
||||
'windows',
|
||||
'text':
|
||||
'typedef struct _cef_window_info_t { size_t size; DWORD ex_style; HMENU menu; cef_window_handle_t parent_window; cef_runtime_style_t runtime_style; int api_version_test; } cef_window_info_t;'
|
||||
}]
|
||||
|
||||
objects = parse_platformed_content(FILENAME, CEF_TYPES_WIN, NONE_DEBUG_DIR,
|
||||
VERBOSE, '13304', ADDED_DEFINES)
|
||||
|
||||
self.__assert_equal_objects(objects, expected_objects)
|
||||
|
||||
def test_parse_platformed_content_version_13300(self):
|
||||
expected_objects = [{
|
||||
'filename': FILENAME,
|
||||
'name': 'cef_window_handle_t',
|
||||
'platform': 'windows',
|
||||
'text': 'typedef HWND cef_window_handle_t;'
|
||||
}, {
|
||||
'filename':
|
||||
FILENAME,
|
||||
'name':
|
||||
'cef_window_info_t',
|
||||
'platform':
|
||||
'windows',
|
||||
'text':
|
||||
'typedef struct _cef_window_info_t { size_t size; DWORD ex_style; HMENU menu; cef_window_handle_t parent_window; cef_runtime_style_t runtime_style; } cef_window_info_t;'
|
||||
}]
|
||||
|
||||
objects = parse_platformed_content(FILENAME, CEF_TYPES_WIN, NONE_DEBUG_DIR,
|
||||
VERBOSE, '13300', ADDED_DEFINES)
|
||||
|
||||
self.__assert_equal_objects(objects, expected_objects)
|
||||
|
||||
def test_parse_platformed_content_mac(self):
|
||||
expected_objects = [{
|
||||
'filename': FILENAME,
|
||||
'name': 'cef_window_handle_t',
|
||||
'platform': 'mac',
|
||||
'text': 'typedef void* cef_window_handle_t;'
|
||||
}, {
|
||||
'filename':
|
||||
FILENAME,
|
||||
'name':
|
||||
'cef_window_info_t',
|
||||
'platform':
|
||||
'mac',
|
||||
'text':
|
||||
'typedef struct _cef_window_info_t { size_t size; cef_string_t window_name; cef_rect_t bounds; cef_window_handle_t view; cef_runtime_style_t runtime_style; } cef_window_info_t;'
|
||||
}]
|
||||
|
||||
objects = parse_platformed_content(
|
||||
FILENAME,
|
||||
CEF_TYPES_MAC,
|
||||
NONE_DEBUG_DIR,
|
||||
VERBOSE,
|
||||
api_version=None,
|
||||
added_defines=[])
|
||||
|
||||
self.__assert_equal_objects(objects, expected_objects)
|
||||
|
||||
def test_parse_platformed_content_linux(self):
|
||||
expected_objects = [{
|
||||
'filename': FILENAME,
|
||||
'name': 'XEvent',
|
||||
'platform': 'linux',
|
||||
'text': 'typedef union _XEvent XEvent;'
|
||||
}, {
|
||||
'filename': FILENAME,
|
||||
'name': 'XDisplay',
|
||||
'platform': 'linux',
|
||||
'text': 'typedef struct _XDisplay XDisplay;'
|
||||
}, {
|
||||
'filename': FILENAME,
|
||||
'name': 'cef_event_handle_t',
|
||||
'platform': 'linux',
|
||||
'text': 'typedef XEvent* cef_event_handle_t;'
|
||||
}, {
|
||||
'filename': FILENAME,
|
||||
'name': 'cef_window_handle_t',
|
||||
'platform': 'linux',
|
||||
'text': 'typedef unsigned long cef_window_handle_t;'
|
||||
}, {
|
||||
'filename': FILENAME,
|
||||
'name': 'cef_get_xdisplay',
|
||||
'platform': 'linux',
|
||||
'text': 'CEF_EXPORT XDisplay* cef_get_xdisplay(void);'
|
||||
}, {
|
||||
'filename':
|
||||
FILENAME,
|
||||
'name':
|
||||
'cef_window_info_t',
|
||||
'platform':
|
||||
'linux',
|
||||
'text':
|
||||
'typedef struct _cef_window_info_t { size_t size; cef_string_t window_name; cef_rect_t bounds; cef_window_handle_t parent_window; cef_window_handle_t window; cef_runtime_style_t runtime_style; } cef_window_info_t;'
|
||||
}]
|
||||
|
||||
objects = parse_platformed_content(
|
||||
FILENAME,
|
||||
CEF_TYPES_LINUX,
|
||||
NONE_DEBUG_DIR,
|
||||
VERBOSE,
|
||||
api_version=None,
|
||||
added_defines=[])
|
||||
|
||||
self.__assert_equal_objects(objects, expected_objects)
|
||||
|
||||
def test_parse_versioned_content_version_13304(self):
|
||||
expected_objects = [{
|
||||
'filename':
|
||||
FILENAME,
|
||||
'name':
|
||||
'cef_chrome_page_action_icon_type_t',
|
||||
'platform':
|
||||
'universal',
|
||||
'text':
|
||||
'typedef enum { CEF_CPAIT_OPTIMIZATION_GUIDE, CEF_CPAIT_COLLABORATION_MESSAGING, CEF_CPAIT_NUM_VALUES, } cef_chrome_page_action_icon_type_t;'
|
||||
}]
|
||||
|
||||
objects = parse_versioned_content(FILENAME, CEF_TYPES, '13304',
|
||||
ADDED_DEFINES, NONE_DEBUG_DIR, VERBOSE)
|
||||
|
||||
self.assertEqual(objects, expected_objects)
|
||||
|
||||
def test_parse_versioned_content_version_13303(self):
|
||||
expected_objects = [{
|
||||
'filename':
|
||||
FILENAME,
|
||||
'name':
|
||||
'cef_chrome_page_action_icon_type_t',
|
||||
'platform':
|
||||
'universal',
|
||||
'text':
|
||||
'typedef enum { CEF_CPAIT_OPTIMIZATION_GUIDE, CEF_CPAIT_NUM_VALUES, } cef_chrome_page_action_icon_type_t;'
|
||||
}]
|
||||
|
||||
objects = parse_versioned_content(FILENAME, CEF_TYPES, '13303',
|
||||
ADDED_DEFINES, NONE_DEBUG_DIR, VERBOSE)
|
||||
|
||||
self.assertEqual(objects, expected_objects)
|
||||
|
||||
def __assert_equal_objects(self, actual, expected):
|
||||
# Compare the objects as sets since the order is not guaranteed
|
||||
expected = Counter(tuple(sorted(d.items())) for d in expected)
|
||||
actual = Counter(tuple(sorted(d.items())) for d in actual)
|
||||
self.assertEqual(expected, actual)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
@@ -522,9 +522,9 @@ def dict_to_str(dict):
|
||||
# Attribute keys allowed in CEF metadata comments.
|
||||
COMMON_ATTRIB_KEYS = ('added', 'removed')
|
||||
CLASS_ATTRIB_KEYS = COMMON_ATTRIB_KEYS + ('no_debugct_check', 'source')
|
||||
FUNCTION_ATTRIB_KEYS = COMMON_ATTRIB_KEYS + ('api_hash_check', 'capi_name',
|
||||
'count_func', 'default_retval',
|
||||
'index_param', 'optional_param')
|
||||
FUNCTION_ATTRIB_KEYS = COMMON_ATTRIB_KEYS + (
|
||||
'api_hash_check', 'capi_name', 'count_func', 'default_retval',
|
||||
'index_param', 'no_stack_protector', 'optional_param')
|
||||
|
||||
# regex for matching comment-formatted attributes
|
||||
_cre_attrib = r'/\*--cef\(([A-Za-z0-9_ ,=:\n]{0,})\)--\*/'
|
||||
@@ -1352,10 +1352,15 @@ class obj_class:
|
||||
|
||||
# Clamp to class versions, if specified.
|
||||
if self.has_version_added():
|
||||
versions = [x for x in versions if x >= self.get_version_added()]
|
||||
version_added = self.get_version_added()
|
||||
versions = [x for x in versions if x >= version_added]
|
||||
if not version_added in versions:
|
||||
versions.append(version_added)
|
||||
if self.has_version_removed():
|
||||
versions = [x for x in versions if x < self.get_version_removed()]
|
||||
|
||||
assert len(versions) > 0, self.get_name()
|
||||
|
||||
self.allversions = sorted(versions)
|
||||
return self.allversions
|
||||
|
||||
|
@@ -161,7 +161,7 @@ class VersionFormatter:
|
||||
# - "X" is the Chromium major version (e.g. 74).
|
||||
# - "Y" is an incremental number that starts at 0 when a release branch is
|
||||
# created and changes only when the CEF C/C++ API changes (similar to how
|
||||
# the CEF_API_HASH_UNIVERSAL value behaves in cef_api_hash.h) (release
|
||||
# the CEF_API_HASH_PLATFORM value behaves in cef_api_hash.h) (release
|
||||
# branch only).
|
||||
# - "Z" is an incremental number that starts at 0 when a release branch is
|
||||
# created and changes on each commit, with reset to 0 when "Y" changes
|
||||
|
@@ -27,7 +27,7 @@ else:
|
||||
def clang_format(file_name, file_contents):
|
||||
# -assume-filename is necessary to find the .clang-format file and determine
|
||||
# the language when specifying contents via stdin.
|
||||
result = exec_cmd("%s -assume-filename=%s" % (clang_format_exe, file_name), \
|
||||
result = exec_cmd("%s -assume-filename=%s" % (clang_format_exe, file_name),
|
||||
cef_dir, file_contents.encode('utf-8'))
|
||||
if result['err'] != '':
|
||||
sys.stderr.write("clang-format error: %s\n" % result['err'])
|
||||
@@ -48,40 +48,28 @@ def clang_format_inplace(file_name):
|
||||
return True
|
||||
|
||||
|
||||
def clang_eval(file_name,
|
||||
file_contents,
|
||||
defines=[],
|
||||
includes=[],
|
||||
as_cpp=True,
|
||||
verbose=False):
|
||||
lang = 'c++' if as_cpp else 'c'
|
||||
def clang_eval(file_name, file_contents, defines, includes, verbose):
|
||||
lang = 'c'
|
||||
if file_name.lower().endswith('.h'):
|
||||
lang += '-header'
|
||||
# The -P option removes unnecessary line markers and whitespace.
|
||||
format = '/EP' if sys.platform == 'win32' else '-E -P'
|
||||
|
||||
sdkroot = ''
|
||||
if sys.platform == 'darwin':
|
||||
result = exec_cmd('xcrun --show-sdk-path', '.')
|
||||
if result['ret'] == 0:
|
||||
sdkroot = " -isysroot %s" % result['out'].strip()
|
||||
|
||||
cmd = "%s -x %s %s %s %s %s -" % (clang_exe, lang, format,
|
||||
' '.join(['-D' + v for v in defines]),
|
||||
' '.join(['-I' + v
|
||||
for v in includes]), sdkroot)
|
||||
cmd = "%s -x %s %s %s %s -" % (clang_exe, lang, format,
|
||||
' '.join(['-D' + v for v in defines]),
|
||||
' '.join(['-I' + v for v in includes]))
|
||||
if verbose:
|
||||
print('--- Running "%s" in "%s"' % (cmd, cef_dir))
|
||||
print(f'--- Running "{cmd}" in "{cef_dir}"')
|
||||
|
||||
result = exec_cmd(cmd, cef_dir, file_contents.encode('utf-8'))
|
||||
if result['err'] != '':
|
||||
err = result['err'].replace('<stdin>', file_name)
|
||||
sys.stderr.write("clang error: %s\n" % err)
|
||||
if result['err'] != '' or result['ret'] != 0:
|
||||
error = result['err'].replace('<stdin>', file_name)
|
||||
return_code = result['ret']
|
||||
sys.stderr.write(f'clang {return_code=} {error=}\n')
|
||||
return None
|
||||
if result['out'] != '':
|
||||
output = result['out']
|
||||
if sys.platform == 'win32':
|
||||
# Convert to Unix line endings.
|
||||
output = output.replace("\r", "")
|
||||
return output
|
||||
return None
|
||||
|
||||
output = result['out']
|
||||
if output and sys.platform == 'win32':
|
||||
# Convert to Unix line endings.
|
||||
output = output.replace("\r", "")
|
||||
return output
|
||||
|
@@ -3,6 +3,6 @@ LICENSING
|
||||
|
||||
The CEF project is BSD licensed. Please read the LICENSE.txt file included with
|
||||
this binary distribution for licensing terms and conditions. Other software
|
||||
included in this distribution is provided under other licenses. Please visit
|
||||
"about:credits" in a CEF-based application for complete Chromium and third-party
|
||||
licensing information.
|
||||
included in this distribution is provided under other licenses. Please see the
|
||||
CREDITS.html file or visit "about:credits" in a CEF-based application for
|
||||
complete Chromium and third-party licensing information.
|
||||
|
@@ -13,29 +13,25 @@ def exec_cmd(cmd, path, input_string=None):
|
||||
err = ''
|
||||
ret = -1
|
||||
parts = cmd.split()
|
||||
try:
|
||||
if input_string is None:
|
||||
process = Popen(
|
||||
parts,
|
||||
cwd=path,
|
||||
stdout=PIPE,
|
||||
stderr=PIPE,
|
||||
shell=(sys.platform == 'win32'))
|
||||
out, err = process.communicate()
|
||||
ret = process.returncode
|
||||
else:
|
||||
process = Popen(
|
||||
parts,
|
||||
cwd=path,
|
||||
stdin=PIPE,
|
||||
stdout=PIPE,
|
||||
stderr=PIPE,
|
||||
shell=(sys.platform == 'win32'))
|
||||
out, err = process.communicate(input=input_string)
|
||||
ret = process.returncode
|
||||
except IOError as e:
|
||||
(errno, strerror) = e.args
|
||||
raise
|
||||
except:
|
||||
raise
|
||||
|
||||
if input_string is None:
|
||||
process = Popen(
|
||||
parts,
|
||||
cwd=path,
|
||||
stdout=PIPE,
|
||||
stderr=PIPE,
|
||||
shell=(sys.platform == 'win32'))
|
||||
out, err = process.communicate()
|
||||
ret = process.returncode
|
||||
else:
|
||||
process = Popen(
|
||||
parts,
|
||||
cwd=path,
|
||||
stdin=PIPE,
|
||||
stdout=PIPE,
|
||||
stderr=PIPE,
|
||||
shell=(sys.platform == 'win32'))
|
||||
out, err = process.communicate(input=input_string)
|
||||
ret = process.returncode
|
||||
|
||||
return {'out': out.decode('utf-8'), 'err': err.decode('utf-8'), 'ret': ret}
|
||||
|
@@ -8,8 +8,8 @@ import os
|
||||
import sys
|
||||
|
||||
if sys.platform == 'win32':
|
||||
# Force use of the git version bundled with depot_tools.
|
||||
git_exe = 'git.bat'
|
||||
# Force use of the system installed Git version.
|
||||
git_exe = 'git.exe'
|
||||
else:
|
||||
git_exe = 'git'
|
||||
|
||||
@@ -30,6 +30,15 @@ def exec_git_cmd(args, path='.'):
|
||||
""" Executes a git command with the specified |args|. """
|
||||
cmd = "%s %s" % (git_exe, args)
|
||||
result = exec_cmd(cmd, path)
|
||||
if result['ret'] != 0:
|
||||
sys.stderr.write('Command \"%s\" exited with retval %d\n' % (cmd,
|
||||
result['ret']))
|
||||
if result['err'] != '':
|
||||
err = result['err'].strip()
|
||||
if sys.platform == 'win32':
|
||||
# Convert to Unix line endings.
|
||||
err = err.replace('\r\n', '\n')
|
||||
sys.stderr.write(err + '\n')
|
||||
if result['out'] != '':
|
||||
out = result['out'].strip()
|
||||
if sys.platform == 'win32':
|
||||
|
@@ -11,8 +11,8 @@ import sys
|
||||
|
||||
|
||||
def make_api_versions_header(json):
|
||||
result = get_copyright(full=True, translator=False) + \
|
||||
"""//
|
||||
result = get_copyright(
|
||||
full=True, translator=False) + """//
|
||||
// ---------------------------------------------------------------------------
|
||||
//
|
||||
// This file was generated by the make_api_versions_header.py tool. Versions
|
||||
@@ -27,42 +27,40 @@ def make_api_versions_header(json):
|
||||
"""
|
||||
|
||||
for version, hashes in json['hashes'].items():
|
||||
version_part = """
|
||||
version_part = f"""
|
||||
// $COMMENT$
|
||||
#define CEF_API_VERSION_$VER$ $VER$
|
||||
#define CEF_API_HASH_$VER$_UNIVERSAL "$UNIVERSAL$"
|
||||
#define CEF_API_VERSION_{version} {version}
|
||||
#if defined(OS_WIN)
|
||||
#define CEF_API_HASH_$VER$_PLATFORM "$WINDOWS$"
|
||||
#define CEF_API_HASH_{version} "$WINDOWS$"
|
||||
#elif defined(OS_MAC)
|
||||
#define CEF_API_HASH_$VER$_PLATFORM "$MAC$"
|
||||
#define CEF_API_HASH_{version} "$MAC$"
|
||||
#elif defined(OS_LINUX)
|
||||
#define CEF_API_HASH_$VER$_PLATFORM "$LINUX$"
|
||||
#define CEF_API_HASH_{version} "$LINUX$"
|
||||
#endif
|
||||
""".replace('$VER$', version)
|
||||
"""
|
||||
|
||||
# Substitute hash values for placeholders.
|
||||
for key, value in hashes.items():
|
||||
version_part = version_part.replace('$%s$' % key.upper(), value)
|
||||
version_part = version_part.replace(f"${key.upper()}$", value)
|
||||
|
||||
result += version_part
|
||||
|
||||
result += \
|
||||
"""
|
||||
result += f"""
|
||||
// Oldest supported CEF version.
|
||||
#define CEF_API_VERSION_MIN CEF_API_VERSION_$MIN$
|
||||
#define CEF_API_VERSION_MIN CEF_API_VERSION_{json['min']}
|
||||
|
||||
// Newest supported CEF version.
|
||||
#define CEF_API_VERSION_LAST CEF_API_VERSION_$LAST$
|
||||
#define CEF_API_VERSION_LAST CEF_API_VERSION_{json['last']}
|
||||
|
||||
#endif // CEF_INCLUDE_CEF_API_VERSIONS_H_
|
||||
""".replace('$LAST$', json['last']).replace('$MIN$', json['min'])
|
||||
"""
|
||||
|
||||
return result
|
||||
|
||||
|
||||
def make_api_versions_inc(json):
|
||||
result = get_copyright(full=False, translator=False) + \
|
||||
"""//
|
||||
result = get_copyright(
|
||||
full=False, translator=False) + """//
|
||||
// ---------------------------------------------------------------------------
|
||||
//
|
||||
// This file was generated by the make_api_versions_header.py tool.
|
||||
@@ -72,56 +70,53 @@ namespace {
|
||||
|
||||
struct ApiVersionHash {
|
||||
int version;
|
||||
const char* const universal;
|
||||
const char* const platform;
|
||||
const char* const hash;
|
||||
};
|
||||
|
||||
const ApiVersionHash kApiVersionHashes[] = {"""
|
||||
|
||||
for version, hashes in json['hashes'].items():
|
||||
result += """
|
||||
{$VER$, CEF_API_HASH_$VER$_UNIVERSAL, CEF_API_HASH_$VER$_PLATFORM},""".replace(
|
||||
'$VER$', version)
|
||||
for version in json['hashes'].keys():
|
||||
result += f"\n{{{version}, CEF_API_HASH_{version}}},"
|
||||
|
||||
result += \
|
||||
"""
|
||||
result += """
|
||||
};
|
||||
|
||||
const size_t kApiVersionHashesSize = std::size(kApiVersionHashes);
|
||||
|
||||
} // namespace
|
||||
"""
|
||||
|
||||
return result
|
||||
|
||||
|
||||
def write_api_versions(out_header_file, out_inc_file, json):
|
||||
def write_api_versions(out_header_file, out_inc_file, json) -> bool:
|
||||
"""
|
||||
Return True if the files were written, False if no changes were made.
|
||||
"""
|
||||
out_file = os.path.abspath(out_header_file)
|
||||
result = make_api_versions_header(json)
|
||||
if not bool(result):
|
||||
sys.stderr.write('Failed to create %s\n' % out_file)
|
||||
if not result:
|
||||
sys.stderr.write(f'Failed to create {out_file}\n')
|
||||
sys.exit(1)
|
||||
retval1 = write_file_if_changed(out_file, result)
|
||||
header_write_result = write_file_if_changed(out_file, result)
|
||||
|
||||
out_file = os.path.abspath(out_inc_file)
|
||||
result = make_api_versions_inc(json)
|
||||
if not bool(result):
|
||||
sys.stderr.write('Failed to create %s\n' % out_file)
|
||||
if not result:
|
||||
sys.stderr.write(f'Failed to create {out_file}\n')
|
||||
sys.exit(1)
|
||||
retval2 = write_file_if_changed(out_file, result)
|
||||
inc_write_result = write_file_if_changed(out_file, result)
|
||||
|
||||
return retval1 or retval2
|
||||
return header_write_result or inc_write_result
|
||||
|
||||
|
||||
def main(argv):
|
||||
if len(argv) < 5:
|
||||
print(
|
||||
"Usage:\n %s <output_header_file> <output_inc_file> <api_versions_file> <api_untracked_file>"
|
||||
% argv[0])
|
||||
f"Usage:\n {argv[0]} <output_header_file> <output_inc_file> <api_versions_file> <api_untracked_file>"
|
||||
)
|
||||
sys.exit(-1)
|
||||
|
||||
json, initialized = \
|
||||
read_version_files(argv[3], argv[4], True, combine=True)
|
||||
json = read_version_files(argv[3], argv[4], initialize=True, combine=True)[0]
|
||||
|
||||
if not write_api_versions(argv[1], argv[2], json):
|
||||
print('Nothing done')
|
||||
|
||||
|
@@ -43,7 +43,7 @@ def make_capi_versions_header(header, filename):
|
||||
translate_map = header.get_capi_translations()
|
||||
|
||||
# header string
|
||||
result = get_copyright(full=True, translator=False) + \
|
||||
result = get_copyright(full=False, translator=False) + \
|
||||
"""//
|
||||
// ---------------------------------------------------------------------------
|
||||
//
|
||||
|
@@ -9,10 +9,13 @@ import functools
|
||||
|
||||
|
||||
def make_cpptoc_impl_proto(name, func, parts):
|
||||
proto = ''
|
||||
if func.has_attrib('no_stack_protector'):
|
||||
proto += 'NO_STACK_PROTECTOR '
|
||||
if isinstance(func, obj_function_virtual):
|
||||
proto = parts['retval'] + ' CEF_CALLBACK'
|
||||
proto += parts['retval'] + ' CEF_CALLBACK'
|
||||
else:
|
||||
proto = 'CEF_EXPORT ' + parts['retval']
|
||||
proto += 'CEF_EXPORT ' + parts['retval']
|
||||
|
||||
proto += ' ' + name + '(' + ', '.join(parts['args']) + ')'
|
||||
return proto
|
||||
|
@@ -11,6 +11,8 @@ def make_ctocpp_impl_proto(clsname, name, func, parts):
|
||||
const = ''
|
||||
|
||||
proto = 'NO_SANITIZE("cfi-icall") '
|
||||
if func.has_attrib('no_stack_protector'):
|
||||
proto += 'NO_STACK_PROTECTOR '
|
||||
if clsname is None:
|
||||
proto += 'CEF_GLOBAL ' + parts['retval'] + ' '
|
||||
else:
|
||||
|
@@ -913,6 +913,16 @@ out_dir = os.path.join(src_dir, 'out')
|
||||
build_dir_debug = os.path.join(out_dir, 'Debug' + build_dir_suffix)
|
||||
build_dir_release = os.path.join(out_dir, 'Release' + build_dir_suffix)
|
||||
|
||||
# Transfer the about_credits.html file.
|
||||
# Debug and Release build should be the same so grab whichever exists.
|
||||
rel_path = os.path.join('gen', 'components', 'resources', 'about_credits.html')
|
||||
src_path = os.path.join(build_dir_release, rel_path)
|
||||
if not os.path.exists(src_path):
|
||||
src_path = os.path.join(build_dir_debug, rel_path)
|
||||
if not os.path.exists(src_path):
|
||||
raise Exception('Missing generated resources file: %s' % rel_path)
|
||||
copy_file(src_path, os.path.join(output_dir, 'CREDITS.html'), options.quiet)
|
||||
|
||||
if mode == 'standard' or mode == 'minimal':
|
||||
# create the include directory
|
||||
include_dir = os.path.join(output_dir, 'include')
|
||||
|
@@ -115,6 +115,8 @@ parser.add_option(
|
||||
(options, args) = parser.parse_args()
|
||||
|
||||
if not options.patchfile is None:
|
||||
apply_patch_file(options.patchfile, options.patchdir)
|
||||
result = apply_patch_file(options.patchfile, options.patchdir)
|
||||
if result == 'fail':
|
||||
sys.exit(1)
|
||||
else:
|
||||
apply_patch_config()
|
||||
|
@@ -4,7 +4,8 @@
|
||||
|
||||
from __future__ import absolute_import
|
||||
from __future__ import print_function
|
||||
from cef_api_hash import cef_api_hash
|
||||
from typing import Dict
|
||||
from cef_api_hash import CefApiHasher
|
||||
from cef_version import VersionFormatter
|
||||
from date_util import get_date
|
||||
from file_util import read_file, read_json_file, write_file, write_json_file
|
||||
@@ -41,49 +42,37 @@ def get_next_api_revision(api_versions_file, major_version):
|
||||
return 0
|
||||
|
||||
|
||||
_CALC = None
|
||||
|
||||
|
||||
def compute_api_hashes(cpp_header_dir, api_version, next_allowed, debug_dir,
|
||||
verbose):
|
||||
""" Computes API hashes for the specified |api_version|.
|
||||
"""
|
||||
if not debug_dir is None:
|
||||
debug_dir = os.path.join(debug_dir, api_version)
|
||||
|
||||
def compute_api_hashes(api_version: str,
|
||||
hasher: CefApiHasher,
|
||||
next_allowed: bool) -> Dict[str, str]:
|
||||
""" Computes API hashes for the specified |api_version|. """
|
||||
if not next_allowed:
|
||||
# Next usage is banned with explicit API versions.
|
||||
assert not api_version in UNTRACKED_VERSIONS, api_version
|
||||
assert api_version not in UNTRACKED_VERSIONS, api_version
|
||||
added_defines = [
|
||||
# Using CEF_API_VERSION_NEXT is an error.
|
||||
'CEF_API_VERSION_NEXT="Please_specify_an_exact_CEF_version"',
|
||||
]
|
||||
else:
|
||||
added_defines = None
|
||||
added_defines = []
|
||||
|
||||
global _CALC
|
||||
if _CALC is None:
|
||||
_CALC = cef_api_hash(cpp_header_dir, verbose=verbose)
|
||||
|
||||
hashes = _CALC.calculate(api_version, debug_dir, added_defines)
|
||||
if bool(hashes):
|
||||
hashes = hasher.calculate(api_version, added_defines)
|
||||
if hashes:
|
||||
if api_version in UNTRACKED_VERSIONS:
|
||||
label = version_label(api_version)
|
||||
label = label[0:1].upper() + label[1:]
|
||||
hashes['comment'] = '%s last updated %s.' % (label, get_date())
|
||||
hashes['comment'] = f'{label} last updated {get_date()}.'
|
||||
else:
|
||||
hashes['comment'] = 'Added %s.' % get_date()
|
||||
hashes['comment'] = f'Added {get_date()}.'
|
||||
return hashes
|
||||
|
||||
|
||||
def same_api_hashes(hashes1, hashes2):
|
||||
for key in ('universal', 'linux', 'mac', 'windows'):
|
||||
if hashes1[key] != hashes2[key]:
|
||||
return False
|
||||
return True
|
||||
return all(hashes1[key] == hashes2[key]
|
||||
for key in ['linux', 'mac', 'windows'])
|
||||
|
||||
|
||||
def compute_next_api_verson(api_versions_file):
|
||||
def compute_next_api_version(api_versions_file):
|
||||
""" Computes the next available API version number.
|
||||
"""
|
||||
major_version = int(VersionFormatter().get_chrome_major_version())
|
||||
@@ -95,7 +84,10 @@ def compute_next_api_verson(api_versions_file):
|
||||
|
||||
|
||||
def git_grep_next(cef_dir):
|
||||
cmd = "grep --no-color -n -E (CEF_NEXT|CEF_NEXT)|=next -- :!include/cef_api_hash.h *.h"
|
||||
cmd = "grep --no-color -n -E (CEF_NEXT|CEF_NEXT)|=next -- :!include/cef_api_hash.h *.h *.cc"
|
||||
if sys.platform == 'win32':
|
||||
# Pass the pipe (|) character as a literal argument.
|
||||
cmd = cmd.replace('|', '^|')
|
||||
return exec_git_cmd(cmd, cef_dir)
|
||||
|
||||
|
||||
@@ -105,7 +97,7 @@ def find_next_usage(cpp_header_dir):
|
||||
if result is None:
|
||||
return False
|
||||
|
||||
sys.stderr.write('ERROR: NEXT usage found in CEF headers:\n\n' + result +
|
||||
sys.stderr.write('ERROR: NEXT usage found in CEF source files:\n\n' + result +
|
||||
'\n\nFix manually or run with --replace-next.\n')
|
||||
return True
|
||||
|
||||
@@ -204,8 +196,11 @@ def find_replace_next_usage(cpp_header_dir, next_version):
|
||||
return 0
|
||||
|
||||
|
||||
def exec_apply(cpp_header_dir, api_versions_file, api_untracked_file,
|
||||
next_version, debug_dir, apply_next, verbose):
|
||||
def exec_apply(api_versions_file,
|
||||
api_untracked_file,
|
||||
next_version,
|
||||
apply_next,
|
||||
hasher: CefApiHasher) -> int:
|
||||
""" Updates untracked API hashes if necessary.
|
||||
Saves the hash for the next API version if |apply_next| is true.
|
||||
"""
|
||||
@@ -219,9 +214,8 @@ def exec_apply(cpp_header_dir, api_versions_file, api_untracked_file,
|
||||
untracked_changed = False
|
||||
for version in UNTRACKED_VERSIONS:
|
||||
label = version_label(version)
|
||||
hashes = compute_api_hashes(cpp_header_dir, version, True, debug_dir,
|
||||
verbose)
|
||||
if not bool(hashes):
|
||||
hashes = compute_api_hashes(version, hasher, next_allowed=True)
|
||||
if not hashes:
|
||||
sys.stderr.write('ERROR: Failed to process %s\n' % label)
|
||||
return 1
|
||||
|
||||
@@ -237,9 +231,8 @@ def exec_apply(cpp_header_dir, api_versions_file, api_untracked_file,
|
||||
if apply_next:
|
||||
next_label = version_label(next_version)
|
||||
|
||||
hashes = compute_api_hashes(cpp_header_dir, next_version, False, debug_dir,
|
||||
verbose)
|
||||
if not bool(hashes):
|
||||
hashes = compute_api_hashes(next_version, hasher, next_allowed=False)
|
||||
if not hashes:
|
||||
sys.stderr.write('ERROR: Failed to process %s\n' % next_label)
|
||||
return 1
|
||||
|
||||
@@ -275,29 +268,33 @@ def exec_apply(cpp_header_dir, api_versions_file, api_untracked_file,
|
||||
return 0
|
||||
|
||||
|
||||
def exec_check(cpp_header_dir, api_versions_file, api_untracked_file, debug_dir,
|
||||
fast_check, force_update, skip_untracked, verbose):
|
||||
def exec_check(api_versions_file,
|
||||
api_untracked_file,
|
||||
fast_check,
|
||||
force_update,
|
||||
skip_untracked,
|
||||
hasher: CefApiHasher) -> int:
|
||||
""" Checks existing API version hashes.
|
||||
Resaves all API hashes if |force_update| is true. Otherwise, hash
|
||||
changes are considered an error.
|
||||
"""
|
||||
assert not (fast_check and force_update)
|
||||
|
||||
json_versions, json_untracked, initialized = \
|
||||
read_version_files(api_versions_file, api_untracked_file, False)
|
||||
json_versions, json_untracked, initialized = read_version_files(
|
||||
api_versions_file, api_untracked_file, initialize=False)
|
||||
assert not initialized
|
||||
|
||||
versions = []
|
||||
len_versioned_existing = len_versioned_checked = len_versioned_failed = 0
|
||||
len_untracked_existing = len_untracked_checked = len_untracked_failed = 0
|
||||
|
||||
if not json_versions is None:
|
||||
if json_versions is not None:
|
||||
keys = json_versions['hashes'].keys()
|
||||
len_versioned_existing = len(keys)
|
||||
if len_versioned_existing > 0:
|
||||
if fast_check:
|
||||
# Only checking a subset of versions.
|
||||
for key in ('last', 'min'):
|
||||
for key in ['last', 'min']:
|
||||
if key in json_versions:
|
||||
version = json_versions[key]
|
||||
assert version in json_versions['hashes'], version
|
||||
@@ -307,14 +304,14 @@ def exec_check(cpp_header_dir, api_versions_file, api_untracked_file, debug_dir,
|
||||
versions.extend(keys)
|
||||
len_versioned_checked = len_versioned_existing
|
||||
|
||||
if not json_untracked is None:
|
||||
if json_untracked is not None:
|
||||
keys = json_untracked['hashes'].keys()
|
||||
len_untracked_existing = len(keys)
|
||||
if len_untracked_existing > 0 and not skip_untracked:
|
||||
versions.extend(keys)
|
||||
len_untracked_checked = len_untracked_existing
|
||||
|
||||
if len(versions) == 0:
|
||||
if not versions:
|
||||
print('No hashes to check.')
|
||||
return 0
|
||||
|
||||
@@ -328,8 +325,7 @@ def exec_check(cpp_header_dir, api_versions_file, api_untracked_file, debug_dir,
|
||||
else:
|
||||
stored_hashes = json_versions['hashes'][version]
|
||||
label = version_label(version)
|
||||
computed_hashes = compute_api_hashes(cpp_header_dir, version, True,
|
||||
debug_dir, verbose)
|
||||
computed_hashes = compute_api_hashes(version, hasher, next_allowed=True)
|
||||
if not bool(computed_hashes):
|
||||
sys.stderr.write('ERROR: Failed to process %s\n' % label)
|
||||
return 1
|
||||
@@ -362,8 +358,10 @@ def exec_check(cpp_header_dir, api_versions_file, api_untracked_file, debug_dir,
|
||||
print('WARNING: This change can break back/forward binary compatibility.')
|
||||
else:
|
||||
sys.stderr.write('ERROR: %d hashes checked and failed\n' % len_failed)
|
||||
sys.stderr.write('\nFor debugging tips/tricks see\n' +
|
||||
'https://github.com/chromiumembedded/cef/issues/3836#issuecomment-2587767028\n\n')
|
||||
sys.stderr.write(
|
||||
'\nFor debugging tips/tricks see\n' +
|
||||
'https://github.com/chromiumembedded/cef/issues/3836#issuecomment-2587767028\n\n'
|
||||
)
|
||||
|
||||
print('%d hashes checked and match (%d/%d versioned, %d/%d untracked).' %
|
||||
(len(versions) - len_failed,
|
||||
@@ -412,7 +410,7 @@ https://bitbucket.org/chromiumembedded/cef/wiki/ApiVersioning.md
|
||||
parser = CustomParser(description=desc, epilog=epilog)
|
||||
parser.add_option(
|
||||
'--debug-dir',
|
||||
dest='debugdir',
|
||||
dest='debug_dir',
|
||||
metavar='DIR',
|
||||
help='intermediate directory for easy debugging')
|
||||
parser.add_option(
|
||||
@@ -472,7 +470,7 @@ https://bitbucket.org/chromiumembedded/cef/wiki/ApiVersioning.md
|
||||
parser.add_option(
|
||||
'--force-update',
|
||||
action='store_true',
|
||||
dest='forceupdate',
|
||||
dest='force_update',
|
||||
default=False,
|
||||
help='force update all API hashes (use with -c)')
|
||||
(options, args) = parser.parse_args()
|
||||
@@ -496,7 +494,7 @@ https://bitbucket.org/chromiumembedded/cef/wiki/ApiVersioning.md
|
||||
parser.print_help(sys.stdout)
|
||||
sys.exit(1)
|
||||
|
||||
next_version = compute_next_api_verson(api_versions_file)
|
||||
next_version = compute_next_api_version(api_versions_file)
|
||||
if next_version is None:
|
||||
sys.exit(1)
|
||||
|
||||
@@ -522,17 +520,13 @@ https://bitbucket.org/chromiumembedded/cef/wiki/ApiVersioning.md
|
||||
changed = translate(cef_dir, verbose=options.verbose) > 0
|
||||
skip_untracked = False
|
||||
|
||||
hasher = CefApiHasher(cpp_header_dir, options.debug_dir, options.verbose)
|
||||
|
||||
if options.update or will_apply_next or changed or not os.path.isfile(
|
||||
api_untracked_file):
|
||||
skip_untracked = True
|
||||
if exec_apply(
|
||||
cpp_header_dir,
|
||||
api_versions_file,
|
||||
api_untracked_file,
|
||||
next_version,
|
||||
options.debugdir,
|
||||
apply_next=options.apply,
|
||||
verbose=options.verbose) > 0:
|
||||
if exec_apply(api_versions_file, api_untracked_file, next_version,
|
||||
options.apply, hasher) > 0:
|
||||
# Apply failed.
|
||||
sys.exit(1)
|
||||
elif not options.check:
|
||||
@@ -540,12 +534,6 @@ https://bitbucket.org/chromiumembedded/cef/wiki/ApiVersioning.md
|
||||
sys.exit(0)
|
||||
|
||||
sys.exit(
|
||||
exec_check(
|
||||
cpp_header_dir,
|
||||
api_versions_file,
|
||||
api_untracked_file,
|
||||
options.debugdir,
|
||||
options.fastcheck and not options.forceupdate,
|
||||
options.check and options.forceupdate,
|
||||
skip_untracked,
|
||||
verbose=options.verbose))
|
||||
exec_check(api_versions_file, api_untracked_file, options.fastcheck and
|
||||
not options.force_update, options.check and
|
||||
options.force_update, skip_untracked, hasher))
|
||||
|
@@ -92,7 +92,7 @@ def read_version_files(api_versions_file,
|
||||
}
|
||||
initialized = True
|
||||
else:
|
||||
json_version = None
|
||||
json_versions = None
|
||||
else:
|
||||
assert 'hashes' in json_versions, api_versions_file
|
||||
assert 'last' in json_versions, api_versions_file
|
||||
|
Reference in New Issue
Block a user