From 570788955558f7bd43790d173187fc25e2a27bd3 Mon Sep 17 00:00:00 2001 From: Marshall Greenblatt Date: Thu, 25 May 2023 11:15:06 +0000 Subject: [PATCH] Add methods for configuring website/content settings (fixes #3490) This approach is now used to allow popups on a case-by-case basis in tests instead of globally disabling the popup blocker with the Chrome runtime. --- cef_paths2.gypi | 1 + include/capi/cef_request_context_capi.h | 69 +++- include/cef_api_hash.h | 8 +- include/cef_request_context.h | 67 ++++ include/internal/cef_types.h | 1 + include/internal/cef_types_content_settings.h | 367 ++++++++++++++++++ libcef/browser/request_context_impl.cc | 167 ++++++++ libcef/browser/request_context_impl.h | 28 ++ libcef_dll/cpptoc/request_context_cpptoc.cc | 89 ++++- libcef_dll/ctocpp/request_context_ctocpp.cc | 89 ++++- libcef_dll/ctocpp/request_context_ctocpp.h | 18 +- .../cefclient/browser/root_window_manager.cc | 8 + tests/ceftests/frame_handler_unittest.cc | 2 + tests/ceftests/navigation_unittest.cc | 57 ++- tests/ceftests/request_context_unittest.cc | 9 + tests/ceftests/test_util.cc | 24 ++ tests/ceftests/test_util.h | 25 ++ tests/shared/browser/client_app_browser.cc | 3 - 18 files changed, 1005 insertions(+), 27 deletions(-) create mode 100644 include/internal/cef_types_content_settings.h diff --git a/cef_paths2.gypi b/cef_paths2.gypi index 38718e4b0..f7414be05 100644 --- a/cef_paths2.gypi +++ b/cef_paths2.gypi @@ -55,6 +55,7 @@ 'include/internal/cef_time.h', 'include/internal/cef_trace_event_internal.h', 'include/internal/cef_types.h', + 'include/internal/cef_types_content_settings.h', 'include/internal/cef_types_geometry.h', ], 'includes_capi': [ diff --git a/include/capi/cef_request_context_capi.h b/include/capi/cef_request_context_capi.h index 58f3ef2d1..22226664a 100644 --- a/include/capi/cef_request_context_capi.h +++ b/include/capi/cef_request_context_capi.h @@ -33,7 +33,7 @@ // by hand. See the translator.README.txt file in the tools directory for // more information. // -// $hash=c2a6265e8e9acce475a8b5755a8c58b97b495207$ +// $hash=1c3c3dfb4bde6cd45278c6a80fbc53f624017c44$ // #ifndef CEF_INCLUDE_CAPI_CEF_REQUEST_CONTEXT_CAPI_H_ @@ -46,6 +46,7 @@ #include "include/capi/cef_extension_handler_capi.h" #include "include/capi/cef_media_router_capi.h" #include "include/capi/cef_preference_capi.h" +#include "include/capi/cef_values_capi.h" #ifdef __cplusplus extern "C" { @@ -301,6 +302,72 @@ typedef struct _cef_request_context_t { struct _cef_media_router_t*(CEF_CALLBACK* get_media_router)( struct _cef_request_context_t* self, struct _cef_completion_callback_t* callback); + + /// + /// Returns the current value for |content_type| that applies for the + /// specified URLs. If both URLs are NULL the default value will be returned. + /// Returns nullptr if no value is configured. Must be called on the browser + /// process UI thread. + /// + struct _cef_value_t*(CEF_CALLBACK* get_website_setting)( + struct _cef_request_context_t* self, + const cef_string_t* requesting_url, + const cef_string_t* top_level_url, + cef_content_setting_types_t content_type); + + /// + /// Sets the current value for |content_type| for the specified URLs in the + /// default scope. If both URLs are NULL, and the context is not incognito, + /// the default value will be set. Pass nullptr for |value| to remove the + /// default value for this content type. + /// + /// WARNING: Incorrect usage of this function may cause instability or + /// security issues in Chromium. Make sure that you first understand the + /// potential impact of any changes to |content_type| by reviewing the related + /// source code in Chromium. For example, if you plan to modify + /// CEF_CONTENT_SETTING_TYPE_POPUPS, first review and understand the usage of + /// ContentSettingsType::POPUPS in Chromium: + /// https://source.chromium.org/search?q=ContentSettingsType::POPUPS + /// + void(CEF_CALLBACK* set_website_setting)( + struct _cef_request_context_t* self, + const cef_string_t* requesting_url, + const cef_string_t* top_level_url, + cef_content_setting_types_t content_type, + struct _cef_value_t* value); + + /// + /// Returns the current value for |content_type| that applies for the + /// specified URLs. If both URLs are NULL the default value will be returned. + /// Returns CEF_CONTENT_SETTING_VALUE_DEFAULT if no value is configured. Must + /// be called on the browser process UI thread. + /// + cef_content_setting_values_t(CEF_CALLBACK* get_content_setting)( + struct _cef_request_context_t* self, + const cef_string_t* requesting_url, + const cef_string_t* top_level_url, + cef_content_setting_types_t content_type); + + /// + /// Sets the current value for |content_type| for the specified URLs in the + /// default scope. If both URLs are NULL, and the context is not incognito, + /// the default value will be set. Pass CEF_CONTENT_SETTING_VALUE_DEFAULT for + /// |value| to use the default value for this content type. + /// + /// WARNING: Incorrect usage of this function may cause instability or + /// security issues in Chromium. Make sure that you first understand the + /// potential impact of any changes to |content_type| by reviewing the related + /// source code in Chromium. For example, if you plan to modify + /// CEF_CONTENT_SETTING_TYPE_POPUPS, first review and understand the usage of + /// ContentSettingsType::POPUPS in Chromium: + /// https://source.chromium.org/search?q=ContentSettingsType::POPUPS + /// + void(CEF_CALLBACK* set_content_setting)( + struct _cef_request_context_t* self, + const cef_string_t* requesting_url, + const cef_string_t* top_level_url, + cef_content_setting_types_t content_type, + cef_content_setting_values_t value); } cef_request_context_t; /// diff --git a/include/cef_api_hash.h b/include/cef_api_hash.h index 77a0dbcdd..4ac85e3df 100644 --- a/include/cef_api_hash.h +++ b/include/cef_api_hash.h @@ -42,13 +42,13 @@ // way that may cause binary incompatibility with other builds. The universal // hash value will change if any platform is affected whereas the platform hash // values will change only if that particular platform is affected. -#define CEF_API_HASH_UNIVERSAL "a3f241333b0d0bdcb3b3ea7c2b003ff146019b54" +#define CEF_API_HASH_UNIVERSAL "ffa07abf4b1f2e4bb228a0ec6b8959b6923236ba" #if defined(OS_WIN) -#define CEF_API_HASH_PLATFORM "22809c1dd1e83a467160065822e4c5a2aa1a6f74" +#define CEF_API_HASH_PLATFORM "25327dfd50f3fd5aefd523622c42297ff5a02382" #elif defined(OS_MAC) -#define CEF_API_HASH_PLATFORM "4366603b6ce969025e27b7d1834028df8e6ffbe4" +#define CEF_API_HASH_PLATFORM "f021e371a8edb71ca9158cffa8c3ada1db2d9955" #elif defined(OS_LINUX) -#define CEF_API_HASH_PLATFORM "d1f8e80f361ae3d013add51dcb1449341be9eff1" +#define CEF_API_HASH_PLATFORM "f8a8b9758a53e7ba8b259151176b54edefea5471" #endif #ifdef __cplusplus diff --git a/include/cef_request_context.h b/include/cef_request_context.h index f65fcd832..1ecaf44f9 100644 --- a/include/cef_request_context.h +++ b/include/cef_request_context.h @@ -46,6 +46,7 @@ #include "include/cef_extension_handler.h" #include "include/cef_media_router.h" #include "include/cef_preference.h" +#include "include/cef_values.h" class CefRequestContextHandler; class CefSchemeHandlerFactory; @@ -314,6 +315,72 @@ class CefRequestContext : public CefPreferenceManager { /*--cef(optional_param=callback)--*/ virtual CefRefPtr GetMediaRouter( CefRefPtr callback) = 0; + + /// + /// Returns the current value for |content_type| that applies for the + /// specified URLs. If both URLs are empty the default value will be returned. + /// Returns nullptr if no value is configured. Must be called on the browser + /// process UI thread. + /// + /*--cef(optional_param=requesting_url,optional_param=top_level_url)--*/ + virtual CefRefPtr GetWebsiteSetting( + const CefString& requesting_url, + const CefString& top_level_url, + cef_content_setting_types_t content_type) = 0; + + /// + /// Sets the current value for |content_type| for the specified URLs in the + /// default scope. If both URLs are empty, and the context is not incognito, + /// the default value will be set. Pass nullptr for |value| to remove the + /// default value for this content type. + /// + /// WARNING: Incorrect usage of this method may cause instability or security + /// issues in Chromium. Make sure that you first understand the potential + /// impact of any changes to |content_type| by reviewing the related source + /// code in Chromium. For example, if you plan to modify + /// CEF_CONTENT_SETTING_TYPE_POPUPS, first review and understand the usage of + /// ContentSettingsType::POPUPS in Chromium: + /// https://source.chromium.org/search?q=ContentSettingsType::POPUPS + /// + /*--cef(optional_param=requesting_url,optional_param=top_level_url, + optional_param=value)--*/ + virtual void SetWebsiteSetting(const CefString& requesting_url, + const CefString& top_level_url, + cef_content_setting_types_t content_type, + CefRefPtr value) = 0; + + /// + /// Returns the current value for |content_type| that applies for the + /// specified URLs. If both URLs are empty the default value will be returned. + /// Returns CEF_CONTENT_SETTING_VALUE_DEFAULT if no value is configured. Must + /// be called on the browser process UI thread. + /// + /*--cef(optional_param=requesting_url,optional_param=top_level_url, + default_retval=CEF_CONTENT_SETTING_VALUE_DEFAULT)--*/ + virtual cef_content_setting_values_t GetContentSetting( + const CefString& requesting_url, + const CefString& top_level_url, + cef_content_setting_types_t content_type) = 0; + + /// + /// Sets the current value for |content_type| for the specified URLs in the + /// default scope. If both URLs are empty, and the context is not incognito, + /// the default value will be set. Pass CEF_CONTENT_SETTING_VALUE_DEFAULT for + /// |value| to use the default value for this content type. + /// + /// WARNING: Incorrect usage of this method may cause instability or security + /// issues in Chromium. Make sure that you first understand the potential + /// impact of any changes to |content_type| by reviewing the related source + /// code in Chromium. For example, if you plan to modify + /// CEF_CONTENT_SETTING_TYPE_POPUPS, first review and understand the usage of + /// ContentSettingsType::POPUPS in Chromium: + /// https://source.chromium.org/search?q=ContentSettingsType::POPUPS + /// + /*--cef(optional_param=requesting_url,optional_param=top_level_url)--*/ + virtual void SetContentSetting(const CefString& requesting_url, + const CefString& top_level_url, + cef_content_setting_types_t content_type, + cef_content_setting_values_t value) = 0; }; #endif // CEF_INCLUDE_CEF_REQUEST_CONTEXT_H_ diff --git a/include/internal/cef_types.h b/include/internal/cef_types.h index 73ad9ccad..77a0c53c2 100644 --- a/include/internal/cef_types.h +++ b/include/internal/cef_types.h @@ -35,6 +35,7 @@ #include "include/internal/cef_string.h" #include "include/internal/cef_string_list.h" #include "include/internal/cef_time.h" +#include "include/internal/cef_types_content_settings.h" #include "include/internal/cef_types_geometry.h" // Bring in platform-specific definitions. diff --git a/include/internal/cef_types_content_settings.h b/include/internal/cef_types_content_settings.h new file mode 100644 index 000000000..e444a1790 --- /dev/null +++ b/include/internal/cef_types_content_settings.h @@ -0,0 +1,367 @@ +// Copyright (c) 2023 Marshall A. Greenblatt. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the name Chromium Embedded +// Framework nor the names of its contributors may be used to endorse +// or promote products derived from this software without specific prior +// written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +#ifndef CEF_INCLUDE_INTERNAL_CEF_TYPES_CONTENT_SETTINGS_H_ +#define CEF_INCLUDE_INTERNAL_CEF_TYPES_CONTENT_SETTINGS_H_ +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +/// +/// Supported content setting types. Some types are platform-specific or only +/// supported with the Chrome runtime. Should be kept in sync with Chromium's +/// ContentSettingsType type. +/// +typedef enum { + CEF_CONTENT_SETTING_TYPE_COOKIES = 0, + CEF_CONTENT_SETTING_TYPE_IMAGES, + CEF_CONTENT_SETTING_TYPE_JAVASCRIPT, + + /// This setting governs both popups and unwanted redirects like tab-unders + /// and framebusting. + CEF_CONTENT_SETTING_TYPE_POPUPS, + + CEF_CONTENT_SETTING_TYPE_GEOLOCATION, + CEF_CONTENT_SETTING_TYPE_NOTIFICATIONS, + CEF_CONTENT_SETTING_TYPE_AUTO_SELECT_CERTIFICATE, + CEF_CONTENT_SETTING_TYPE_MIXEDSCRIPT, + CEF_CONTENT_SETTING_TYPE_MEDIASTREAM_MIC, + CEF_CONTENT_SETTING_TYPE_MEDIASTREAM_CAMERA, + CEF_CONTENT_SETTING_TYPE_PROTOCOL_HANDLERS, + CEF_CONTENT_SETTING_TYPE_AUTOMATIC_DOWNLOADS, + CEF_CONTENT_SETTING_TYPE_MIDI_SYSEX, + CEF_CONTENT_SETTING_TYPE_SSL_CERT_DECISIONS, + CEF_CONTENT_SETTING_TYPE_PROTECTED_MEDIA_IDENTIFIER, + CEF_CONTENT_SETTING_TYPE_APP_BANNER, + CEF_CONTENT_SETTING_TYPE_SITE_ENGAGEMENT, + CEF_CONTENT_SETTING_TYPE_DURABLE_STORAGE, + CEF_CONTENT_SETTING_TYPE_USB_CHOOSER_DATA, + CEF_CONTENT_SETTING_TYPE_BLUETOOTH_GUARD, + CEF_CONTENT_SETTING_TYPE_BACKGROUND_SYNC, + CEF_CONTENT_SETTING_TYPE_AUTOPLAY, + CEF_CONTENT_SETTING_TYPE_IMPORTANT_SITE_INFO, + CEF_CONTENT_SETTING_TYPE_PERMISSION_AUTOBLOCKER_DATA, + CEF_CONTENT_SETTING_TYPE_ADS, + + /// Website setting which stores metadata for the subresource filter to aid in + /// decisions for whether or not to show the UI. + CEF_CONTENT_SETTING_TYPE_ADS_DATA, + + /// This is special-cased in the permissions layer to always allow, and as + /// such doesn't have associated prefs data. + CEF_CONTENT_SETTING_TYPE_MIDI, + + /// This content setting type is for caching password protection service's + /// verdicts of each origin. + CEF_CONTENT_SETTING_TYPE_PASSWORD_PROTECTION, + + /// Website setting which stores engagement data for media related to a + /// specific origin. + CEF_CONTENT_SETTING_TYPE_MEDIA_ENGAGEMENT, + + /// Content setting which stores whether or not the site can play audible + /// sound. This will not block playback but instead the user will not hear it. + CEF_CONTENT_SETTING_TYPE_SOUND, + + /// Website setting which stores the list of client hints that the origin + /// requested the browser to remember. The browser is expected to send all + /// client hints in the HTTP request headers for every resource requested + /// from that origin. + CEF_CONTENT_SETTING_TYPE_CLIENT_HINTS, + + /// Generic Sensor API covering ambient-light-sensor, accelerometer, gyroscope + /// and magnetometer are all mapped to a single content_settings_type. + /// Setting for the Generic Sensor API covering ambient-light-sensor, + /// accelerometer, gyroscope and magnetometer. These are all mapped to a + /// single ContentSettingsType. + CEF_CONTENT_SETTING_TYPE_SENSORS, + + /// Content setting which stores whether or not the user has granted the site + /// permission to respond to accessibility events, which can be used to + /// provide a custom accessibility experience. Requires explicit user consent + /// because some users may not want sites to know they're using assistive + /// technology. + CEF_CONTENT_SETTING_TYPE_ACCESSIBILITY_EVENTS, + + /// Used to store whether to allow a website to install a payment handler. + CEF_CONTENT_SETTING_TYPE_PAYMENT_HANDLER, + + /// Content setting which stores whether to allow sites to ask for permission + /// to access USB devices. If this is allowed specific device permissions are + /// stored under USB_CHOOSER_DATA. + CEF_CONTENT_SETTING_TYPE_USB_GUARD, + + /// Nothing is stored in this setting at present. Please refer to + /// BackgroundFetchPermissionContext for details on how this permission + /// is ascertained. + CEF_CONTENT_SETTING_TYPE_BACKGROUND_FETCH, + + /// Website setting which stores the amount of times the user has dismissed + /// intent picker UI without explicitly choosing an option. + CEF_CONTENT_SETTING_TYPE_INTENT_PICKER_DISPLAY, + + /// Used to store whether to allow a website to detect user active/idle state. + CEF_CONTENT_SETTING_TYPE_IDLE_DETECTION, + + /// Setting for enabling auto-select of all screens for getDisplayMediaSet. + CEF_CONTENT_SETTING_TYPE_GET_DISPLAY_MEDIA_SET_SELECT_ALL_SCREENS, + + /// Content settings for access to serial ports. The "guard" content setting + /// stores whether to allow sites to ask for permission to access a port. The + /// permissions granted to access particular ports are stored in the "chooser + /// data" website setting. + CEF_CONTENT_SETTING_TYPE_SERIAL_GUARD, + CEF_CONTENT_SETTING_TYPE_SERIAL_CHOOSER_DATA, + + /// Nothing is stored in this setting at present. Please refer to + /// PeriodicBackgroundSyncPermissionContext for details on how this permission + /// is ascertained. + /// This content setting is not registered because it does not require access + /// to any existing providers. + CEF_CONTENT_SETTING_TYPE_PERIODIC_BACKGROUND_SYNC, + + /// Content setting which stores whether to allow sites to ask for permission + /// to do Bluetooth scanning. + CEF_CONTENT_SETTING_TYPE_BLUETOOTH_SCANNING, + + /// Content settings for access to HID devices. The "guard" content setting + /// stores whether to allow sites to ask for permission to access a device. + /// The permissions granted to access particular devices are stored in the + /// "chooser data" website setting. + CEF_CONTENT_SETTING_TYPE_HID_GUARD, + CEF_CONTENT_SETTING_TYPE_HID_CHOOSER_DATA, + + /// Wake Lock API, which has two lock types: screen and system locks. + /// Currently, screen locks do not need any additional permission, and system + /// locks are always denied while the right UI is worked out. + CEF_CONTENT_SETTING_TYPE_WAKE_LOCK_SCREEN, + CEF_CONTENT_SETTING_TYPE_WAKE_LOCK_SYSTEM, + + /// Legacy SameSite cookie behavior. This disables SameSite=Lax-by-default, + /// SameSite=None requires Secure, and Schemeful Same-Site, forcing the + /// legacy behavior wherein 1) cookies that don't specify SameSite are treated + /// as SameSite=None, 2) SameSite=None cookies are not required to be Secure, + /// and 3) schemeful same-site is not active. + /// + /// This will also be used to revert to legacy behavior when future changes + /// in cookie handling are introduced. + CEF_CONTENT_SETTING_TYPE_LEGACY_COOKIE_ACCESS, + + /// Content settings which stores whether to allow sites to ask for permission + /// to save changes to an original file selected by the user through the + /// File System Access API. + CEF_CONTENT_SETTING_TYPE_FILE_SYSTEM_WRITE_GUARD, + + /// Used to store whether to allow a website to exchange data with NFC + /// devices. + CEF_CONTENT_SETTING_TYPE_NFC, + + /// Website setting to store permissions granted to access particular + /// Bluetooth devices. + CEF_CONTENT_SETTING_TYPE_BLUETOOTH_CHOOSER_DATA, + + /// Full access to the system clipboard (sanitized read without user gesture, + /// and unsanitized read and write with user gesture). + CEF_CONTENT_SETTING_TYPE_CLIPBOARD_READ_WRITE, + + /// This is special-cased in the permissions layer to always allow, and as + /// such doesn't have associated prefs data. + CEF_CONTENT_SETTING_TYPE_CLIPBOARD_SANITIZED_WRITE, + + /// This content setting type is for caching safe browsing real time url + /// check's verdicts of each origin. + CEF_CONTENT_SETTING_TYPE_SAFE_BROWSING_URL_CHECK_DATA, + + /// Used to store whether a site is allowed to request AR or VR sessions with + /// the WebXr Device API. + CEF_CONTENT_SETTING_TYPE_VR, + CEF_CONTENT_SETTING_TYPE_AR, + + /// Content setting which stores whether to allow site to open and read files + /// and directories selected through the File System Access API. + CEF_CONTENT_SETTING_TYPE_FILE_SYSTEM_READ_GUARD, + + /// Access to first party storage in a third-party context. Exceptions are + /// scoped to the combination of requesting/top-level origin, and are managed + /// through the Storage Access API. For the time being, this content setting + /// exists in parallel to third-party cookie rules stored in COOKIES. + CEF_CONTENT_SETTING_TYPE_STORAGE_ACCESS, + + /// Content setting which stores whether to allow a site to control camera + /// movements. It does not give access to camera. + CEF_CONTENT_SETTING_TYPE_CAMERA_PAN_TILT_ZOOM, + + /// Content setting for Screen Enumeration and Screen Detail functionality. + /// Permits access to detailed multi-screen information, like size and + /// position. Permits placing fullscreen and windowed content on specific + /// screens. See also: https://w3c.github.io/window-placement + CEF_CONTENT_SETTING_TYPE_WINDOW_MANAGEMENT, + + /// Stores whether to allow insecure websites to make local network requests. + /// See also: https://wicg.github.io/local-network-access + /// Set through enterprise policies only. + CEF_CONTENT_SETTING_TYPE_INSECURE_LOCAL_NETWORK, + + /// Content setting which stores whether or not a site can access low-level + /// locally installed font data using the Local Fonts Access API. + CEF_CONTENT_SETTING_TYPE_LOCAL_FONTS, + + /// Stores per-origin state for permission auto-revocation (for all permission + /// types). + CEF_CONTENT_SETTING_TYPE_PERMISSION_AUTOREVOCATION_DATA, + + /// Stores per-origin state of the most recently selected directory for the + /// use by the File System Access API. + CEF_CONTENT_SETTING_TYPE_FILE_SYSTEM_LAST_PICKED_DIRECTORY, + + /// Controls access to the getDisplayMedia API when {preferCurrentTab: true} + /// is specified. + CEF_CONTENT_SETTING_TYPE_DISPLAY_CAPTURE, + + /// Website setting to store permissions metadata granted to paths on the + /// local file system via the File System Access API. + /// |FILE_SYSTEM_WRITE_GUARD| is the corresponding "guard" setting. + CEF_CONTENT_SETTING_TYPE_FILE_SYSTEM_ACCESS_CHOOSER_DATA, + + /// Stores a grant that allows a relying party to send a request for identity + /// information to specified identity providers, potentially through any + /// anti-tracking measures that would otherwise prevent it. This setting is + /// associated with the relying party's origin. + CEF_CONTENT_SETTING_TYPE_FEDERATED_IDENTITY_SHARING, + + /// Whether to use the v8 optimized JIT for running JavaScript on the page. + CEF_CONTENT_SETTING_TYPE_JAVASCRIPT_JIT, + + /// Content setting which stores user decisions to allow loading a site over + /// HTTP. Entries are added by hostname when a user bypasses the HTTPS-First + /// Mode interstitial warning when a site does not support HTTPS. Allowed + /// hosts are exact hostname matches -- subdomains of a host on the allowlist + /// must be separately allowlisted. + CEF_CONTENT_SETTING_TYPE_HTTP_ALLOWED, + + /// Stores metadata related to form fill, such as e.g. whether user data was + /// autofilled on a specific website. + CEF_CONTENT_SETTING_TYPE_FORMFILL_METADATA, + + /// Setting to indicate that there is an active federated sign-in session + /// between a specified relying party and a specified identity provider for + /// a specified account. When this is present it allows access to session + /// management capabilities between the sites. This setting is associated + /// with the relying party's origin. + CEF_CONTENT_SETTING_TYPE_FEDERATED_IDENTITY_ACTIVE_SESSION, + + /// Setting to indicate whether Chrome should automatically apply darkening to + /// web content. + CEF_CONTENT_SETTING_TYPE_AUTO_DARK_WEB_CONTENT, + + /// Setting to indicate whether Chrome should request the desktop view of a + /// site instead of the mobile one. + CEF_CONTENT_SETTING_TYPE_REQUEST_DESKTOP_SITE, + + /// Setting to indicate whether browser should allow signing into a website + /// via the browser FedCM API. + CEF_CONTENT_SETTING_TYPE_FEDERATED_IDENTITY_API, + + /// Stores notification interactions per origin for the past 90 days. + /// Interactions per origin are pre-aggregated over seven-day windows: A + /// notification interaction or display is assigned to the last Monday + /// midnight in local time. + CEF_CONTENT_SETTING_TYPE_NOTIFICATION_INTERACTIONS, + + /// Website setting which stores the last reduced accept language negotiated + /// for a given origin, to be used on future visits to the origin. + CEF_CONTENT_SETTING_TYPE_REDUCED_ACCEPT_LANGUAGE, + + /// Website setting which is used for NotificationPermissionReviewService to + /// store origin blocklist from review notification permissions feature. + CEF_CONTENT_SETTING_TYPE_NOTIFICATION_PERMISSION_REVIEW, + + /// Website setting to store permissions granted to access particular devices + /// in private network. + CEF_CONTENT_SETTING_TYPE_PRIVATE_NETWORK_GUARD, + CEF_CONTENT_SETTING_TYPE_PRIVATE_NETWORK_CHOOSER_DATA, + + /// Website setting which stores whether the browser has observed the user + /// signing into an identity-provider based on observing the IdP-SignIn-Status + /// HTTP header. + CEF_CONTENT_SETTING_TYPE_FEDERATED_IDENTITY_IDENTITY_PROVIDER_SIGNIN_STATUS, + + /// Website setting which is used for UnusedSitePermissionsService to + /// store revoked permissions of unused sites from unused site permissions + /// feature. + CEF_CONTENT_SETTING_TYPE_REVOKED_UNUSED_SITE_PERMISSIONS, + + /// Similar to STORAGE_ACCESS, but applicable at the page-level rather than + /// being specific to a frame. + CEF_CONTENT_SETTING_TYPE_TOP_LEVEL_STORAGE_ACCESS, + + /// Setting to indicate whether user has opted in to allowing auto re-authn + /// via the FedCM API. + CEF_CONTENT_SETTING_TYPE_FEDERATED_IDENTITY_AUTO_REAUTHN_PERMISSION, + + /// Website setting which stores whether the user has explicitly registered + /// a website as an identity-provider. + CEF_CONTENT_SETTING_TYPE_FEDERATED_IDENTITY_IDENTITY_PROVIDER_REGISTRATION, + + /// Content setting which is used to indicate whether anti-abuse functionality + /// should be enabled. + CEF_CONTENT_SETTING_TYPE_ANTI_ABUSE, + + /// Content setting used to indicate whether third-party storage partitioning + /// should be enabled. + CEF_CONTENT_SETTING_TYPE_THIRD_PARTY_STORAGE_PARTITIONING, + + /// Used to indicate whether HTTPS-First Mode is enabled on the hostname. + CEF_CONTENT_SETTING_TYPE_HTTPS_ENFORCED, + + CEF_CONTENT_SETTING_TYPE_NUM_TYPES, +} cef_content_setting_types_t; + +/// +/// Supported content setting values. Should be kept in sync with Chromium's +/// ContentSetting type. +/// +typedef enum { + CEF_CONTENT_SETTING_VALUE_DEFAULT = 0, + CEF_CONTENT_SETTING_VALUE_ALLOW, + CEF_CONTENT_SETTING_VALUE_BLOCK, + CEF_CONTENT_SETTING_VALUE_ASK, + CEF_CONTENT_SETTING_VALUE_SESSION_ONLY, + CEF_CONTENT_SETTING_VALUE_DETECT_IMPORTANT_CONTENT, + + CEF_CONTENT_SETTING_VALUE_NUM_VALUES +} cef_content_setting_values_t; + +#ifdef __cplusplus +} +#endif + +#endif // CEF_INCLUDE_INTERNAL_CEF_TYPES_CONTENT_SETTINGS_H_ diff --git a/libcef/browser/request_context_impl.cc b/libcef/browser/request_context_impl.cc index e3540ab27..244eec670 100644 --- a/libcef/browser/request_context_impl.cc +++ b/libcef/browser/request_context_impl.cc @@ -9,11 +9,14 @@ #include "libcef/browser/thread_util.h" #include "libcef/common/app_manager.h" #include "libcef/common/task_runner_impl.h" +#include "libcef/common/values_impl.h" #include "base/atomic_sequence_num.h" #include "base/logging.h" #include "base/strings/stringprintf.h" +#include "chrome/browser/content_settings/host_content_settings_map_factory.h" #include "chrome/browser/profiles/profile.h" +#include "components/content_settings/core/browser/host_content_settings_map.h" #include "components/prefs/pref_service.h" #include "content/public/browser/browser_task_traits.h" #include "content/public/browser/child_process_host.h" @@ -497,6 +500,99 @@ CefRefPtr CefRequestContextImpl::GetMediaRouter( return media_router.get(); } +CefRefPtr CefRequestContextImpl::GetWebsiteSetting( + const CefString& requesting_url, + const CefString& top_level_url, + cef_content_setting_types_t content_type) { + if (!VerifyBrowserContext()) { + return nullptr; + } + + auto* settings_map = HostContentSettingsMapFactory::GetForProfile( + browser_context()->AsProfile()); + if (!settings_map) { + return nullptr; + } + + // Either or both URLs may be invalid. + GURL requesting_gurl(requesting_url.ToString()); + GURL top_level_gurl(top_level_url.ToString()); + + content_settings::SettingInfo info; + base::Value value = settings_map->GetWebsiteSetting( + requesting_gurl, top_level_gurl, + static_cast(content_type), &info); + if (value.is_none()) { + return nullptr; + } + + return new CefValueImpl(std::move(value)); +} + +void CefRequestContextImpl::SetWebsiteSetting( + const CefString& requesting_url, + const CefString& top_level_url, + cef_content_setting_types_t content_type, + CefRefPtr value) { + GetBrowserContext( + content::GetUIThreadTaskRunner({}), + base::BindOnce(&CefRequestContextImpl::SetWebsiteSettingInternal, this, + requesting_url, top_level_url, content_type, value)); +} + +cef_content_setting_values_t CefRequestContextImpl::GetContentSetting( + const CefString& requesting_url, + const CefString& top_level_url, + cef_content_setting_types_t content_type) { + // Verify that our enums match Chromium's values. + static_assert(static_cast(CEF_CONTENT_SETTING_TYPE_NUM_TYPES) == + static_cast(ContentSettingsType::NUM_TYPES), + "Mismatched enum found for CEF_CONTENT_SETTING_TYPE_NUM_TYPES"); + static_assert( + static_cast(CEF_CONTENT_SETTING_VALUE_NUM_VALUES) == + static_cast(CONTENT_SETTING_NUM_SETTINGS), + "Mismatched enum found for CEF_CONTENT_SETTING_VALUE_NUM_VALUES"); + + if (!VerifyBrowserContext()) { + return CEF_CONTENT_SETTING_VALUE_DEFAULT; + } + + auto* settings_map = HostContentSettingsMapFactory::GetForProfile( + browser_context()->AsProfile()); + if (!settings_map) { + return CEF_CONTENT_SETTING_VALUE_DEFAULT; + } + + ContentSetting value = ContentSetting::CONTENT_SETTING_DEFAULT; + + if (requesting_url.empty() && top_level_url.empty()) { + value = settings_map->GetDefaultContentSetting( + static_cast(content_type), + /*provider_id=*/nullptr); + } else { + GURL requesting_gurl(requesting_url.ToString()); + GURL top_level_gurl(top_level_url.ToString()); + if (requesting_gurl.is_valid() || top_level_gurl.is_valid()) { + value = settings_map->GetContentSetting( + requesting_gurl, top_level_gurl, + static_cast(content_type)); + } + } + + return static_cast(value); +} + +void CefRequestContextImpl::SetContentSetting( + const CefString& requesting_url, + const CefString& top_level_url, + cef_content_setting_types_t content_type, + cef_content_setting_values_t value) { + GetBrowserContext( + content::GetUIThreadTaskRunner({}), + base::BindOnce(&CefRequestContextImpl::SetContentSettingInternal, this, + requesting_url, top_level_url, content_type, value)); +} + void CefRequestContextImpl::OnRenderFrameCreated( const content::GlobalRenderFrameHostId& global_id, bool is_main_frame, @@ -671,6 +767,77 @@ void CefRequestContextImpl::ResolveHostInternal( helper->Start(browser_context, origin); } +void CefRequestContextImpl::SetWebsiteSettingInternal( + const CefString& requesting_url, + const CefString& top_level_url, + cef_content_setting_types_t content_type, + CefRefPtr value, + CefBrowserContext::Getter browser_context_getter) { + auto browser_context = browser_context_getter.Run(); + if (!browser_context) { + return; + } + + auto* settings_map = HostContentSettingsMapFactory::GetForProfile( + browser_context->AsProfile()); + if (!settings_map) { + return; + } + + // Starts as a NONE value. + base::Value new_value; + if (value && value->IsValid()) { + new_value = static_cast(value.get())->CopyValue(); + } + + if (requesting_url.empty() && top_level_url.empty()) { + settings_map->SetWebsiteSettingCustomScope( + ContentSettingsPattern::Wildcard(), ContentSettingsPattern::Wildcard(), + static_cast(content_type), std::move(new_value)); + } else { + GURL requesting_gurl(requesting_url.ToString()); + GURL top_level_gurl(top_level_url.ToString()); + if (requesting_gurl.is_valid() || top_level_gurl.is_valid()) { + settings_map->SetWebsiteSettingDefaultScope( + requesting_gurl, top_level_gurl, + static_cast(content_type), std::move(new_value)); + } + } +} + +void CefRequestContextImpl::SetContentSettingInternal( + const CefString& requesting_url, + const CefString& top_level_url, + cef_content_setting_types_t content_type, + cef_content_setting_values_t value, + CefBrowserContext::Getter browser_context_getter) { + auto browser_context = browser_context_getter.Run(); + if (!browser_context) { + return; + } + + auto* settings_map = HostContentSettingsMapFactory::GetForProfile( + browser_context->AsProfile()); + if (!settings_map) { + return; + } + + if (requesting_url.empty() && top_level_url.empty()) { + settings_map->SetDefaultContentSetting( + static_cast(content_type), + static_cast(value)); + } else { + GURL requesting_gurl(requesting_url.ToString()); + GURL top_level_gurl(top_level_url.ToString()); + if (requesting_gurl.is_valid() || top_level_gurl.is_valid()) { + settings_map->SetContentSettingDefaultScope( + requesting_gurl, top_level_gurl, + static_cast(content_type), + static_cast(value)); + } + } +} + void CefRequestContextImpl::InitializeCookieManagerInternal( CefRefPtr cookie_manager, CefRefPtr callback) { diff --git a/libcef/browser/request_context_impl.h b/libcef/browser/request_context_impl.h index 9cf34d3f0..d2668a9aa 100644 --- a/libcef/browser/request_context_impl.h +++ b/libcef/browser/request_context_impl.h @@ -96,6 +96,22 @@ class CefRequestContextImpl : public CefRequestContext { CefRefPtr GetExtension(const CefString& extension_id) override; CefRefPtr GetMediaRouter( CefRefPtr callback) override; + CefRefPtr GetWebsiteSetting( + const CefString& requesting_url, + const CefString& top_level_url, + cef_content_setting_types_t content_type) override; + void SetWebsiteSetting(const CefString& requesting_url, + const CefString& top_level_url, + cef_content_setting_types_t content_type, + CefRefPtr value) override; + cef_content_setting_values_t GetContentSetting( + const CefString& requesting_url, + const CefString& top_level_url, + cef_content_setting_types_t content_type) override; + void SetContentSetting(const CefString& requesting_url, + const CefString& top_level_url, + cef_content_setting_types_t content_type, + cef_content_setting_values_t value) override; const CefRequestContextSettings& settings() const { return config_.settings; } @@ -159,6 +175,18 @@ class CefRequestContextImpl : public CefRequestContext { void ResolveHostInternal(const CefString& origin, CefRefPtr callback, CefBrowserContext::Getter browser_context_getter); + void SetWebsiteSettingInternal( + const CefString& requesting_url, + const CefString& top_level_url, + cef_content_setting_types_t content_type, + CefRefPtr value, + CefBrowserContext::Getter browser_context_getter); + void SetContentSettingInternal( + const CefString& requesting_url, + const CefString& top_level_url, + cef_content_setting_types_t content_type, + cef_content_setting_values_t value, + CefBrowserContext::Getter browser_context_getter); void InitializeCookieManagerInternal( CefRefPtr cookie_manager, diff --git a/libcef_dll/cpptoc/request_context_cpptoc.cc b/libcef_dll/cpptoc/request_context_cpptoc.cc index 475d89f63..453898d82 100644 --- a/libcef_dll/cpptoc/request_context_cpptoc.cc +++ b/libcef_dll/cpptoc/request_context_cpptoc.cc @@ -9,7 +9,7 @@ // implementations. See the translator.README.txt file in the tools directory // for more information. // -// $hash=11e75abce1b3d294f13b65739bd95fff8f790a3e$ +// $hash=19ec3227b1676b8a359d6ea1264dea80ed717049$ // #include "libcef_dll/cpptoc/request_context_cpptoc.h" @@ -470,6 +470,89 @@ request_context_get_media_router(struct _cef_request_context_t* self, return CefMediaRouterCppToC::Wrap(_retval); } +struct _cef_value_t* CEF_CALLBACK +request_context_get_website_setting(struct _cef_request_context_t* self, + const cef_string_t* requesting_url, + const cef_string_t* top_level_url, + cef_content_setting_types_t content_type) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) { + return NULL; + } + // Unverified params: requesting_url, top_level_url + + // Execute + CefRefPtr _retval = + CefRequestContextCppToC::Get(self)->GetWebsiteSetting( + CefString(requesting_url), CefString(top_level_url), content_type); + + // Return type: refptr_same + return CefValueCppToC::Wrap(_retval); +} + +void CEF_CALLBACK +request_context_set_website_setting(struct _cef_request_context_t* self, + const cef_string_t* requesting_url, + const cef_string_t* top_level_url, + cef_content_setting_types_t content_type, + struct _cef_value_t* value) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) { + return; + } + // Unverified params: requesting_url, top_level_url, value + + // Execute + CefRequestContextCppToC::Get(self)->SetWebsiteSetting( + CefString(requesting_url), CefString(top_level_url), content_type, + CefValueCppToC::Unwrap(value)); +} + +cef_content_setting_values_t CEF_CALLBACK +request_context_get_content_setting(struct _cef_request_context_t* self, + const cef_string_t* requesting_url, + const cef_string_t* top_level_url, + cef_content_setting_types_t content_type) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) { + return CEF_CONTENT_SETTING_VALUE_DEFAULT; + } + // Unverified params: requesting_url, top_level_url + + // Execute + cef_content_setting_values_t _retval = + CefRequestContextCppToC::Get(self)->GetContentSetting( + CefString(requesting_url), CefString(top_level_url), content_type); + + // Return type: simple + return _retval; +} + +void CEF_CALLBACK +request_context_set_content_setting(struct _cef_request_context_t* self, + const cef_string_t* requesting_url, + const cef_string_t* top_level_url, + cef_content_setting_types_t content_type, + cef_content_setting_values_t value) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) { + return; + } + // Unverified params: requesting_url, top_level_url + + // Execute + CefRequestContextCppToC::Get(self)->SetContentSetting( + CefString(requesting_url), CefString(top_level_url), content_type, value); +} + int CEF_CALLBACK request_context_has_preference(struct _cef_preference_manager_t* self, const cef_string_t* name) { @@ -626,6 +709,10 @@ CefRequestContextCppToC::CefRequestContextCppToC() { GetStruct()->get_extensions = request_context_get_extensions; GetStruct()->get_extension = request_context_get_extension; GetStruct()->get_media_router = request_context_get_media_router; + GetStruct()->get_website_setting = request_context_get_website_setting; + GetStruct()->set_website_setting = request_context_set_website_setting; + GetStruct()->get_content_setting = request_context_get_content_setting; + GetStruct()->set_content_setting = request_context_set_content_setting; GetStruct()->base.has_preference = request_context_has_preference; GetStruct()->base.get_preference = request_context_get_preference; GetStruct()->base.get_all_preferences = request_context_get_all_preferences; diff --git a/libcef_dll/ctocpp/request_context_ctocpp.cc b/libcef_dll/ctocpp/request_context_ctocpp.cc index 13dec2cac..d1a68a1ac 100644 --- a/libcef_dll/ctocpp/request_context_ctocpp.cc +++ b/libcef_dll/ctocpp/request_context_ctocpp.cc @@ -9,7 +9,7 @@ // implementations. See the translator.README.txt file in the tools directory // for more information. // -// $hash=9c0cf12774084952a4497e83741a2f9988923109$ +// $hash=17602248a48e405470bdf7b6a34866cdf67a5780$ // #include "libcef_dll/ctocpp/request_context_ctocpp.h" @@ -459,6 +459,93 @@ CefRefPtr CefRequestContextCToCpp::GetMediaRouter( return CefMediaRouterCToCpp::Wrap(_retval); } +NO_SANITIZE("cfi-icall") +CefRefPtr CefRequestContextCToCpp::GetWebsiteSetting( + const CefString& requesting_url, + const CefString& top_level_url, + cef_content_setting_types_t content_type) { + cef_request_context_t* _struct = GetStruct(); + if (CEF_MEMBER_MISSING(_struct, get_website_setting)) { + return nullptr; + } + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Unverified params: requesting_url, top_level_url + + // Execute + cef_value_t* _retval = + _struct->get_website_setting(_struct, requesting_url.GetStruct(), + top_level_url.GetStruct(), content_type); + + // Return type: refptr_same + return CefValueCToCpp::Wrap(_retval); +} + +NO_SANITIZE("cfi-icall") +void CefRequestContextCToCpp::SetWebsiteSetting( + const CefString& requesting_url, + const CefString& top_level_url, + cef_content_setting_types_t content_type, + CefRefPtr value) { + cef_request_context_t* _struct = GetStruct(); + if (CEF_MEMBER_MISSING(_struct, set_website_setting)) { + return; + } + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Unverified params: requesting_url, top_level_url, value + + // Execute + _struct->set_website_setting(_struct, requesting_url.GetStruct(), + top_level_url.GetStruct(), content_type, + CefValueCToCpp::Unwrap(value)); +} + +NO_SANITIZE("cfi-icall") +cef_content_setting_values_t CefRequestContextCToCpp::GetContentSetting( + const CefString& requesting_url, + const CefString& top_level_url, + cef_content_setting_types_t content_type) { + cef_request_context_t* _struct = GetStruct(); + if (CEF_MEMBER_MISSING(_struct, get_content_setting)) { + return CEF_CONTENT_SETTING_VALUE_DEFAULT; + } + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Unverified params: requesting_url, top_level_url + + // Execute + cef_content_setting_values_t _retval = + _struct->get_content_setting(_struct, requesting_url.GetStruct(), + top_level_url.GetStruct(), content_type); + + // Return type: simple + return _retval; +} + +NO_SANITIZE("cfi-icall") +void CefRequestContextCToCpp::SetContentSetting( + const CefString& requesting_url, + const CefString& top_level_url, + cef_content_setting_types_t content_type, + cef_content_setting_values_t value) { + cef_request_context_t* _struct = GetStruct(); + if (CEF_MEMBER_MISSING(_struct, set_content_setting)) { + return; + } + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Unverified params: requesting_url, top_level_url + + // Execute + _struct->set_content_setting(_struct, requesting_url.GetStruct(), + top_level_url.GetStruct(), content_type, value); +} + NO_SANITIZE("cfi-icall") bool CefRequestContextCToCpp::HasPreference(const CefString& name) { cef_preference_manager_t* _struct = diff --git a/libcef_dll/ctocpp/request_context_ctocpp.h b/libcef_dll/ctocpp/request_context_ctocpp.h index ac5422bd1..b123581bb 100644 --- a/libcef_dll/ctocpp/request_context_ctocpp.h +++ b/libcef_dll/ctocpp/request_context_ctocpp.h @@ -9,7 +9,7 @@ // implementations. See the translator.README.txt file in the tools directory // for more information. // -// $hash=4a05f4583cacc076519f6505f8f8952c5e471a49$ +// $hash=b55016db9d45bab1e3716e790257f5bed768c66e$ // #ifndef CEF_LIBCEF_DLL_CTOCPP_REQUEST_CONTEXT_CTOCPP_H_ @@ -68,6 +68,22 @@ class CefRequestContextCToCpp CefRefPtr GetExtension(const CefString& extension_id) override; CefRefPtr GetMediaRouter( CefRefPtr callback) override; + CefRefPtr GetWebsiteSetting( + const CefString& requesting_url, + const CefString& top_level_url, + cef_content_setting_types_t content_type) override; + void SetWebsiteSetting(const CefString& requesting_url, + const CefString& top_level_url, + cef_content_setting_types_t content_type, + CefRefPtr value) override; + cef_content_setting_values_t GetContentSetting( + const CefString& requesting_url, + const CefString& top_level_url, + cef_content_setting_types_t content_type) override; + void SetContentSetting(const CefString& requesting_url, + const CefString& top_level_url, + cef_content_setting_types_t content_type, + cef_content_setting_values_t value) override; // CefPreferenceManager methods. bool HasPreference(const CefString& name) override; diff --git a/tests/cefclient/browser/root_window_manager.cc b/tests/cefclient/browser/root_window_manager.cc index 303ca3724..dba3da815 100644 --- a/tests/cefclient/browser/root_window_manager.cc +++ b/tests/cefclient/browser/root_window_manager.cc @@ -58,6 +58,14 @@ class ClientRequestContextHandler : public CefRequestContextHandler, } } } + + // Allow the startup URL to create popups that bypass the popup blocker. + // For example, via Tests > New Popup from the top menu. This applies for + // for the Chrome runtime only. + const auto& startup_url = MainContext::Get()->GetMainURL(); + request_context->SetContentSetting(startup_url, startup_url, + CEF_CONTENT_SETTING_TYPE_POPUPS, + CEF_CONTENT_SETTING_VALUE_ALLOW); } // CefExtensionHandler methods: diff --git a/tests/ceftests/frame_handler_unittest.cc b/tests/ceftests/frame_handler_unittest.cc index 7acd5196b..198703a5f 100644 --- a/tests/ceftests/frame_handler_unittest.cc +++ b/tests/ceftests/frame_handler_unittest.cc @@ -1667,6 +1667,8 @@ class ParentOrderMainTestHandler : public OrderMainTestHandler { void OnAfterCreated(CefRefPtr browser) override { OrderMainTestHandler::OnAfterCreated(browser); + GrantPopupPermission(browser->GetHost()->GetRequestContext(), GetMainURL()); + // Create the popup ASAP. browser->GetMainFrame()->ExecuteJavaScript( "window.open('" + popup_handler_->GetMainURL() + "');", CefString(), 0); diff --git a/tests/ceftests/navigation_unittest.cc b/tests/ceftests/navigation_unittest.cc index 957089f8c..a6646207f 100644 --- a/tests/ceftests/navigation_unittest.cc +++ b/tests/ceftests/navigation_unittest.cc @@ -7,8 +7,11 @@ #include "include/base/cef_callback.h" #include "include/cef_callback.h" +#include "include/cef_request_context.h" +#include "include/cef_request_context_handler.h" #include "include/cef_scheme.h" #include "include/wrapper/cef_closure_task.h" +#include "include/wrapper/cef_scoped_temp_dir.h" #include "tests/ceftests/test_handler.h" #include "tests/ceftests/test_util.h" #include "tests/gtest/include/gtest/gtest.h" @@ -1476,6 +1479,9 @@ class OrderNavTestHandler : public TestHandler { got_message_ = false; if (!browser->IsPopup()) { + GrantPopupPermission(browser->GetHost()->GetRequestContext(), + browser->GetMainFrame()->GetURL()); + // Create the popup window. browser->GetMainFrame()->ExecuteJavaScript( "window.open('" + std::string(KONav2) + "');", CefString(), 0); @@ -2309,6 +2315,9 @@ class PopupSimultaneousTestHandler : public TestHandler { EXPECT_LT(after_created_ct_, kSimultPopupCount); browser_id_[after_created_ct_] = browser->GetIdentifier(); after_created_ct_++; + } else { + GrantPopupPermission(browser->GetHost()->GetRequestContext(), + kSimultPopupMainUrl); } } @@ -2410,18 +2419,22 @@ const char kPopupJSOpenPopupUrl[] = "https://www.tests-pjso.com/popup.html"; // Test a popup where the URL is a JavaScript URI that opens another popup. class PopupJSWindowOpenTestHandler : public TestHandler { public: - PopupJSWindowOpenTestHandler() - : before_popup_ct_(0U), - after_created_ct_(0U), - load_end_ct_(0U), - before_close_ct_(0U) {} + PopupJSWindowOpenTestHandler(TestRequestContextMode mode, + const std::string& cache_path) + : mode_(mode), cache_path_(cache_path) {} void RunTest() override { AddResource(kPopupJSOpenMainUrl, "Main", "text/html"); AddResource(kPopupJSOpenPopupUrl, "Popup", "text/html"); + // Create a new disk-based request context so that we can grant default + // popup permission (used for the popup without a valid URL) without + // impacting the global context. + auto request_context = CreateTestRequestContext(mode_, cache_path_); + GrantPopupPermission(request_context, CefString()); + // Create the browser. - CreateBrowser(kPopupJSOpenMainUrl); + CreateBrowser(kPopupJSOpenMainUrl, request_context); // Time out the test after a reasonable period of time. SetTestTimeout(); @@ -2487,6 +2500,10 @@ class PopupJSWindowOpenTestHandler : public TestHandler { load_end_ct_++; CloseBrowser(browser, true); } else if (browser->GetMainFrame()->GetURL() == kPopupJSOpenMainUrl) { + // For the popup that has a valid URL. + GrantPopupPermission(browser->GetHost()->GetRequestContext(), + kPopupJSOpenMainUrl); + // Load the problematic JS URI. // This will result in 2 popups being created: // - An empty popup @@ -2528,13 +2545,16 @@ class PopupJSWindowOpenTestHandler : public TestHandler { TestHandler::DestroyTest(); } + const TestRequestContextMode mode_; + const std::string cache_path_; + CefRefPtr popup1_; CefRefPtr popup2_; - size_t before_popup_ct_; - size_t after_created_ct_; - size_t load_end_ct_; - size_t before_close_ct_; + size_t before_popup_ct_ = 0U; + size_t after_created_ct_ = 0U; + size_t load_end_ct_ = 0U; + size_t before_close_ct_ = 0U; IMPLEMENT_REFCOUNTING(PopupJSWindowOpenTestHandler); }; @@ -2542,12 +2562,11 @@ class PopupJSWindowOpenTestHandler : public TestHandler { } // namespace // Test a popup where the URL is a JavaScript URI that opens another popup. -TEST(NavigationTest, PopupJSWindowOpen) { - CefRefPtr handler = - new PopupJSWindowOpenTestHandler(); - handler->ExecuteTest(); - ReleaseAndWaitForDestructor(handler); -} +RC_TEST_SINGLE(NavigationTest, + PopupJSWindowOpen, + PopupJSWindowOpenTestHandler, + TEST_RC_MODE_CUSTOM, + /*with_cache_path*/ true) namespace { @@ -2604,6 +2623,9 @@ class PopupJSWindowEmptyTestHandler : public TestHandler { got_load_end_popup_.yes(); CloseBrowser(browser, true); } else { + GrantPopupPermission(browser->GetHost()->GetRequestContext(), + browser->GetMainFrame()->GetURL()); + browser->GetMainFrame()->LoadURL("javascript:window.open('')"); } } @@ -3582,6 +3604,9 @@ class ExtraInfoNavTestHandler : public TestHandler { if (popup_opened_) { DestroyTest(); } else { + GrantPopupPermission(browser->GetHost()->GetRequestContext(), + browser->GetMainFrame()->GetURL()); + browser->GetMainFrame()->ExecuteJavaScript( "window.open('" + std::string(kExtraInfoPopupUrl) + "');", CefString(), 0); diff --git a/tests/ceftests/request_context_unittest.cc b/tests/ceftests/request_context_unittest.cc index d5845623b..2159437bc 100644 --- a/tests/ceftests/request_context_unittest.cc +++ b/tests/ceftests/request_context_unittest.cc @@ -249,6 +249,8 @@ class PopupTestHandler : public TestHandler { context_ = CefRequestContext::CreateContext(settings, nullptr); cookie_manager_ = context_->GetCookieManager(nullptr); + GrantPopupPermission(context_, url_); + // Create browser that loads the 1st URL. CreateBrowser(url_, context_); @@ -487,6 +489,13 @@ class PopupNavTestHandler : public TestHandler { CefRefPtr request_context = CreateTestRequestContext(rc_mode_, rc_cache_path_); + if (request_context) { + GrantPopupPermission(request_context, kPopupNavPageUrl); + } else { + GrantPopupPermission(CefRequestContext::GetGlobalContext(), + kPopupNavPageUrl); + } + // Create the browser. CreateBrowser(kPopupNavPageUrl, request_context); diff --git a/tests/ceftests/test_util.cc b/tests/ceftests/test_util.cc index 4ec7c58d8..34c10ab15 100644 --- a/tests/ceftests/test_util.cc +++ b/tests/ceftests/test_util.cc @@ -362,6 +362,30 @@ void SendMouseClickEvent(CefRefPtr browser, 100); } +void GrantPopupPermission(CefRefPtr request_context, + const std::string& parent_url) { + if (IsChromeRuntimeEnabled()) { + static bool test_website_setting = []() { + return CefCommandLine::GetGlobalCommandLine()->HasSwitch( + "test-website-setting"); + }(); + + // The below calls are equivalent. + // NOTE: If the popup allow functionality stops working, debug the code in + // components/blocked_content/popup_blocker.cc + if (test_website_setting) { + auto value = CefValue::Create(); + value->SetInt(CEF_CONTENT_SETTING_VALUE_ALLOW); + request_context->SetWebsiteSetting( + parent_url, parent_url, CEF_CONTENT_SETTING_TYPE_POPUPS, value); + } else { + request_context->SetContentSetting(parent_url, parent_url, + CEF_CONTENT_SETTING_TYPE_POPUPS, + CEF_CONTENT_SETTING_VALUE_ALLOW); + } + } +} + CefRefPtr CreateTestRequestContext( TestRequestContextMode mode, const std::string& cache_path) { diff --git a/tests/ceftests/test_util.h b/tests/ceftests/test_util.h index 7b7684e76..359d7ca20 100644 --- a/tests/ceftests/test_util.h +++ b/tests/ceftests/test_util.h @@ -108,6 +108,12 @@ void SendMouseClickEvent(CefRefPtr browser, const CefMouseEvent& mouse_event, cef_mouse_button_type_t mouse_button_type = MBT_LEFT); +// Allow |parent_url| to create popups that bypass the popup blocker. If +// |parent_url| is empty the default value will be configured. This method only +// applies for the Chrome runtime. +void GrantPopupPermission(CefRefPtr request_context, + const std::string& parent_url); + // Return a RequestContext object matching the specified |mode|. // |cache_path| may be specified for CUSTOM modes. // Use the RC_TEST_GROUP_BASE macro to test all valid combinations. @@ -115,6 +121,25 @@ CefRefPtr CreateTestRequestContext( TestRequestContextMode mode, const std::string& cache_path); +// Run a single test without additional test modes. +#define RC_TEST_SINGLE(test_case_name, test_name, test_class, rc_mode, \ + with_cache_path) \ + TEST(test_case_name, test_name) { \ + CefScopedTempDir scoped_temp_dir; \ + std::string cache_path; \ + if (with_cache_path) { \ + EXPECT_TRUE(scoped_temp_dir.CreateUniqueTempDirUnderPath( \ + CefTestSuite::GetInstance()->root_cache_path())); \ + cache_path = scoped_temp_dir.GetPath(); \ + } \ + CefRefPtr handler = new test_class(rc_mode, cache_path); \ + handler->ExecuteTest(); \ + ReleaseAndWaitForDestructor(handler); \ + if (!scoped_temp_dir.IsEmpty()) { \ + scoped_temp_dir.Take(); \ + } \ + } + // Helper macro for testing a single RequestContextMode value. // See RC_TEST_GROUP_ALL documentation for example usage. #define RC_TEST_BASE(test_case_name, test_name, test_class, test_mode, \ diff --git a/tests/shared/browser/client_app_browser.cc b/tests/shared/browser/client_app_browser.cc index a904a9ad4..f0a5dd48f 100644 --- a/tests/shared/browser/client_app_browser.cc +++ b/tests/shared/browser/client_app_browser.cc @@ -74,9 +74,6 @@ void ClientAppBrowser::OnBeforeCommandLineProcessing( command_line->AppendSwitch("disable-gpu-shader-disk-cache"); } - // Disable popup blocking for the chrome runtime. - command_line->AppendSwitch("disable-popup-blocking"); - #if defined(OS_MAC) // Disable the toolchain prompt on macOS. command_line->AppendSwitch("use-mock-keychain");