diff --git a/.gitignore b/.gitignore index b786188bc..928c0a70f 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,7 @@ .idea/ build/ dist/ +venv/ *.log __pycache__/ *.pyc @@ -16,3 +17,5 @@ unittests/GPUCache/ unittests/blob_storage/ unittests/webrtc_event_logs/ .DS_Store +MediaDeviceSalts +MediaDeviceSalts-journal diff --git a/Authors b/Authors index b44b24e68..181289824 100644 --- a/Authors +++ b/Authors @@ -20,3 +20,4 @@ Contributors: nobodyguy Elliot Woods Bryan Koroleski + Ted Lin diff --git a/README.md b/README.md index 4ff688b09..eee95cffe 100644 --- a/README.md +++ b/README.md @@ -44,7 +44,7 @@ PyGame, PyOpenGL, PyWin32, PySide and PySDL2. Command to install with pip: ``` -pip install cefpython3==66.1 +pip install cefpython3==123.0 ``` Hosted at [pypi/cefpython3](https://pypi.python.org/pypi/cefpython3). On Linux pip 8.1+ is required. @@ -55,7 +55,7 @@ Below is a table with supported platforms, python versions and architectures. OS | Py2 | Py3 | 32bit | 64bit | Requirements --- | --- | --- | --- | --- | --- -Windows | 2.7 | 3.4 / 3.5 / 3.6 / 3.7 / 3.8 / 3.9 | Yes | Yes | Windows 7+ (Note that Python 3.9 supports Windows 8.1+) +Windows | 2.7 | 3.4 / 3.5 / 3.6 / 3.7 / 3.8 / 3.9 / 3.10 / 3.11 | Yes | Yes | Windows 7+ (Note that Python 3.9 supports Windows 8.1+) Linux | 2.7 | 3.4 / 3.5 / 3.6 / 3.7 | Yes | Yes | Debian 8+, Ubuntu 14.04+,
Fedora 24+, openSUSE 13.3+ Mac | 2.7 | 3.4 / 3.5 / 3.6 / 3.7 | No | Yes | MacOS 10.9+ @@ -87,7 +87,7 @@ Mac | 2.7 | 3.4 / 3.5 / 3.6 / 3.7 | No | Yes | MacOS 10.9+ [Issues labelled Knowledge Base](../../issues?q=is%3Aissue+is%3Aopen+label%3A%22Knowledge+Base%22) - To search documentation use GitHub "This repository" search at the top. To narrow results to documentation only select - "Markdown" in the side pane. + "Markdown" in the right pane. ## Support development @@ -195,7 +195,6 @@ at this moment. * [PaintBuffer](api/PaintBuffer.md#paintbuffer-object) object * [Request](api/Request.md#request-class) class * [Response](api/Response.md#response-object) object - * [WebPluginInfo](api/WebPluginInfo.md#webplugininfo-object) object * [WebRequest](api/WebRequest.md#webrequest-class) class * [WindowInfo](api/WindowInfo.md#windowinfo-class) class * [WindowUtils](api/WindowUtils.md#windowutils-class) class @@ -204,6 +203,7 @@ at this moment. #### Client handlers (interfaces) * [AccessibilityHandler](api/AccessibilityHandler.md#accessibilityhandler-interface) + * [CookieAccessFilter](api/CookieAccessFilter.md#cookieaccessfilter-interface) * [DisplayHandler](api/DisplayHandler.md#displayhandler-interface) * [DownloadHandler](api/DownloadHandler.md#downloadhandler) * [FocusHandler](api/FocusHandler.md#focushandler-interface) @@ -230,7 +230,6 @@ at this moment. * [_OnAccessibilityTreeChange](api/AccessibilityHandler.md#_onaccessibilitytreechange) * [_OnAccessibilityLocationChange](api/AccessibilityHandler.md#_onaccessibilitylocationchange) * [Application settings](api/ApplicationSettings.md#application-settings) - * [accept_language_list](api/ApplicationSettings.md#accept_language_list) * [app_user_model_id](api/ApplicationSettings.md#app_user_model_id) * [auto_zooming](api/ApplicationSettings.md#auto_zooming) * [background_color](api/ApplicationSettings.md#background_color) @@ -241,7 +240,6 @@ at this moment. * [downloads_enabled](api/ApplicationSettings.md#downloads_enabled) * [external_message_pump](api/ApplicationSettings.md#external_message_pump) * [framework_dir_path](api/ApplicationSettings.md#framework_dir_path) - * [ignore_certificate_errors](api/ApplicationSettings.md#ignore_certificate_errors) * [javascript_flags](api/ApplicationSettings.md#javascript_flags) * [locale](api/ApplicationSettings.md#locale) * [locales_dir_path](api/ApplicationSettings.md#locales_dir_path) @@ -249,19 +247,15 @@ at this moment. * [log_file](api/ApplicationSettings.md#log_file) * [log_severity](api/ApplicationSettings.md#log_severity) * [multi_threaded_message_loop](api/ApplicationSettings.md#multi_threaded_message_loop) - * [net_security_expiration_enabled](api/ApplicationSettings.md#net_security_expiration_enabled) * [pack_loading_disabled](api/ApplicationSettings.md#pack_loading_disabled) * [persist_session_cookies](api/ApplicationSettings.md#persist_session_cookies) * [persist_user_preferences](api/ApplicationSettings.md#persist_user_preferences) - * [product_version](api/ApplicationSettings.md#product_version) * [remote_debugging_port](api/ApplicationSettings.md#remote_debugging_port) * [resources_dir_path](api/ApplicationSettings.md#resources_dir_path) - * [single_process](api/ApplicationSettings.md#single_process) * [string_encoding](api/ApplicationSettings.md#string_encoding) * [uncaught_exception_stack_size](api/ApplicationSettings.md#uncaught_exception_stack_size) * [unique_request_context_per_browser](api/ApplicationSettings.md#unique_request_context_per_browser) * [user_agent](api/ApplicationSettings.md#user_agent) - * [user_data_path](api/ApplicationSettings.md#user_data_path) * [windowless_rendering_enabled](api/ApplicationSettings.md#windowless_rendering_enabled) * [Browser (object)](api/Browser.md#browser-object) * [AddWordToDictionary](api/Browser.md#addwordtodictionary) @@ -308,7 +302,6 @@ at this moment. * [Invalidate](api/Browser.md#invalidate) * [IsFullscreen](api/Browser.md#isfullscreen) * [IsLoading](api/Browser.md#isloading) - * [IsMouseCursorChangeDisabled](api/Browser.md#ismousecursorchangedisabled) * [IsPopup](api/Browser.md#ispopup) * [IsWindowRenderingDisabled](api/Browser.md#iswindowrenderingdisabled) * [LoadUrl](api/Browser.md#loadurl) @@ -326,13 +319,11 @@ at this moment. * [SendMouseClickEvent](api/Browser.md#sendmouseclickevent) * [SendMouseMoveEvent](api/Browser.md#sendmousemoveevent) * [SendMouseWheelEvent](api/Browser.md#sendmousewheelevent) - * [SendFocusEvent](api/Browser.md#sendfocusevent) * [SendCaptureLostEvent](api/Browser.md#sendcapturelostevent) * [SetAccessibilityState](api/Browser.md#setaccessibilitystate) * [SetClientCallback](api/Browser.md#setclientcallback) * [SetClientHandler](api/Browser.md#setclienthandler) * [SetFocus](api/Browser.md#setfocus) - * [SetMouseCursorChangeDisabled](api/Browser.md#setmousecursorchangedisabled) * [SetJavascriptBindings](api/Browser.md#setjavascriptbindings) * [SetUserData](api/Browser.md#setuserdata) * [SetZoomLevel](api/Browser.md#setzoomlevel) @@ -346,27 +337,21 @@ at this moment. * [WasHidden](api/Browser.md#washidden) * [Browser settings](api/BrowserSettings.md#browser-settings) * [Font settings](api/BrowserSettings.md#font-settings) - * [accept_language_list](api/BrowserSettings.md#accept_language_list) - * [application_cache_disabled](api/BrowserSettings.md#application_cache_disabled) * [background_color](api/BrowserSettings.md#background_color) * [databases_disabled](api/BrowserSettings.md#databases_disabled) * [default_encoding](api/BrowserSettings.md#default_encoding) * [dom_paste_disabled](api/BrowserSettings.md#dom_paste_disabled) - * [file_access_from_file_urls_allowed](api/BrowserSettings.md#file_access_from_file_urls_allowed) * [inherit_client_handlers_for_popups](api/BrowserSettings.md#inherit_client_handlers_for_popups) * [image_load_disabled](api/BrowserSettings.md#image_load_disabled) * [javascript_disabled](api/BrowserSettings.md#javascript_disabled) * [javascript_close_windows_disallowed](api/BrowserSettings.md#javascript_close_windows_disallowed) * [javascript_access_clipboard_disallowed](api/BrowserSettings.md#javascript_access_clipboard_disallowed) * [local_storage_disabled](api/BrowserSettings.md#local_storage_disabled) - * [plugins_disabled](api/BrowserSettings.md#plugins_disabled) * [remote_fonts](api/BrowserSettings.md#remote_fonts) * [shrink_standalone_images_to_fit](api/BrowserSettings.md#shrink_standalone_images_to_fit) * [tab_to_links_disabled](api/BrowserSettings.md#tab_to_links_disabled) * [text_area_resize_disabled](api/BrowserSettings.md#text_area_resize_disabled) - * [universal_access_from_file_urls_allowed](api/BrowserSettings.md#universal_access_from_file_urls_allowed) * [user_style_sheet_location](api/BrowserSettings.md#user_style_sheet_location) - * [web_security_disabled](api/BrowserSettings.md#web_security_disabled) * [webgl_disabled](api/BrowserSettings.md#webgl_disabled) * [windowless_frame_rate](api/BrowserSettings.md#windowless_frame_rate) * [Callback (object)](api/Callback.md#callback-object) @@ -427,9 +412,6 @@ at this moment. * [GetExpires](api/Cookie.md#getexpires) * [CookieManager (class)](api/CookieManager.md#cookiemanager-class) * [GetGlobalManager](api/CookieManager.md#getglobalmanager) - * [GetBlockingManager](api/CookieManager.md#getblockingmanager) - * [CreateManager](api/CookieManager.md#createmanager) - * [SetSupportedSchemes](api/CookieManager.md#setsupportedschemes) * [VisitAllCookies](api/CookieManager.md#visitallcookies) * [VisitUrlCookies](api/CookieManager.md#visiturlcookies) * [SetCookie](api/CookieManager.md#setcookie) @@ -449,7 +431,6 @@ at this moment. * [DownloadHandler](api/DownloadHandler.md#downloadhandler) * [DpiAware (class)](api/DpiAware.md#dpiaware-class) * [CalculateWindowSize](api/DpiAware.md#calculatewindowsize) - * [EnableHighDpiSupport](api/DpiAware.md#enablehighdpisupport) * [GetSystemDpi](api/DpiAware.md#getsystemdpi) * [IsProcessDpiAware](api/DpiAware.md#isprocessdpiaware) * [SetProcessDpiAware](api/DpiAware.md#setprocessdpiaware) @@ -616,10 +597,7 @@ at this moment. * [GetResourceType](api/Request.md#getresourcetype) * [GetTransitionType](api/Request.md#gettransitiontype) * [RequestHandler (interface)](api/RequestHandler.md#requesthandler-interface) - * [CanGetCookies](api/RequestHandler.md#cangetcookies) - * [CanSetCookie](api/RequestHandler.md#cansetcookie) * [GetAuthCredentials](api/RequestHandler.md#getauthcredentials) - * [GetCookieManager](api/RequestHandler.md#getcookiemanager) * [GetResourceHandler](api/RequestHandler.md#getresourcehandler) * [OnBeforeBrowse](api/RequestHandler.md#onbeforebrowse) * [_OnBeforePluginLoad](api/RequestHandler.md#_onbeforepluginload) @@ -657,11 +635,6 @@ at this moment. * [OnContextCreated](api/V8ContextHandler.md#oncontextcreated) * [OnContextReleased](api/V8ContextHandler.md#oncontextreleased) * [Virtual Key codes](api/VirtualKey.md#virtual-key-codes) -* [WebPluginInfo (object)](api/WebPluginInfo.md#webplugininfo-object) - * [GetName](api/WebPluginInfo.md#getname) - * [GetPath](api/WebPluginInfo.md#getpath) - * [GetVersion](api/WebPluginInfo.md#getversion) - * [GetDescription](api/WebPluginInfo.md#getdescription) * [WebRequest (class)](api/WebRequest.md#webrequest-class) * [Create](api/WebRequest.md#create) * [GetRequest](api/WebRequest.md#getrequest) diff --git a/api/API-categories.md b/api/API-categories.md index d1d7320e8..024694cd6 100644 --- a/api/API-categories.md +++ b/api/API-categories.md @@ -30,7 +30,6 @@ * [PaintBuffer](PaintBuffer.md#paintbuffer-object) object * [Request](Request.md#request-class) class * [Response](Response.md#response-object) object - * [WebPluginInfo](WebPluginInfo.md#webplugininfo-object) object * [WebRequest](WebRequest.md#webrequest-class) class * [WindowInfo](WindowInfo.md#windowinfo-class) class * [WindowUtils](WindowUtils.md#windowutils-class) class diff --git a/api/API-index.md b/api/API-index.md index 9535cb5b7..3e5143e07 100644 --- a/api/API-index.md +++ b/api/API-index.md @@ -6,7 +6,6 @@ * [_OnAccessibilityTreeChange](AccessibilityHandler.md#_onaccessibilitytreechange) * [_OnAccessibilityLocationChange](AccessibilityHandler.md#_onaccessibilitylocationchange) * [Application settings](ApplicationSettings.md#application-settings) - * [accept_language_list](ApplicationSettings.md#accept_language_list) * [app_user_model_id](ApplicationSettings.md#app_user_model_id) * [auto_zooming](ApplicationSettings.md#auto_zooming) * [background_color](ApplicationSettings.md#background_color) @@ -17,7 +16,6 @@ * [downloads_enabled](ApplicationSettings.md#downloads_enabled) * [external_message_pump](ApplicationSettings.md#external_message_pump) * [framework_dir_path](ApplicationSettings.md#framework_dir_path) - * [ignore_certificate_errors](ApplicationSettings.md#ignore_certificate_errors) * [javascript_flags](ApplicationSettings.md#javascript_flags) * [locale](ApplicationSettings.md#locale) * [locales_dir_path](ApplicationSettings.md#locales_dir_path) @@ -25,19 +23,15 @@ * [log_file](ApplicationSettings.md#log_file) * [log_severity](ApplicationSettings.md#log_severity) * [multi_threaded_message_loop](ApplicationSettings.md#multi_threaded_message_loop) - * [net_security_expiration_enabled](ApplicationSettings.md#net_security_expiration_enabled) * [pack_loading_disabled](ApplicationSettings.md#pack_loading_disabled) * [persist_session_cookies](ApplicationSettings.md#persist_session_cookies) * [persist_user_preferences](ApplicationSettings.md#persist_user_preferences) - * [product_version](ApplicationSettings.md#product_version) * [remote_debugging_port](ApplicationSettings.md#remote_debugging_port) * [resources_dir_path](ApplicationSettings.md#resources_dir_path) - * [single_process](ApplicationSettings.md#single_process) * [string_encoding](ApplicationSettings.md#string_encoding) * [uncaught_exception_stack_size](ApplicationSettings.md#uncaught_exception_stack_size) * [unique_request_context_per_browser](ApplicationSettings.md#unique_request_context_per_browser) * [user_agent](ApplicationSettings.md#user_agent) - * [user_data_path](ApplicationSettings.md#user_data_path) * [windowless_rendering_enabled](ApplicationSettings.md#windowless_rendering_enabled) * [Browser (object)](Browser.md#browser-object) * [AddWordToDictionary](Browser.md#addwordtodictionary) @@ -84,7 +78,6 @@ * [Invalidate](Browser.md#invalidate) * [IsFullscreen](Browser.md#isfullscreen) * [IsLoading](Browser.md#isloading) - * [IsMouseCursorChangeDisabled](Browser.md#ismousecursorchangedisabled) * [IsPopup](Browser.md#ispopup) * [IsWindowRenderingDisabled](Browser.md#iswindowrenderingdisabled) * [LoadUrl](Browser.md#loadurl) @@ -102,13 +95,11 @@ * [SendMouseClickEvent](Browser.md#sendmouseclickevent) * [SendMouseMoveEvent](Browser.md#sendmousemoveevent) * [SendMouseWheelEvent](Browser.md#sendmousewheelevent) - * [SendFocusEvent](Browser.md#sendfocusevent) * [SendCaptureLostEvent](Browser.md#sendcapturelostevent) * [SetAccessibilityState](Browser.md#setaccessibilitystate) * [SetClientCallback](Browser.md#setclientcallback) * [SetClientHandler](Browser.md#setclienthandler) * [SetFocus](Browser.md#setfocus) - * [SetMouseCursorChangeDisabled](Browser.md#setmousecursorchangedisabled) * [SetJavascriptBindings](Browser.md#setjavascriptbindings) * [SetUserData](Browser.md#setuserdata) * [SetZoomLevel](Browser.md#setzoomlevel) @@ -122,27 +113,21 @@ * [WasHidden](Browser.md#washidden) * [Browser settings](BrowserSettings.md#browser-settings) * [Font settings](BrowserSettings.md#font-settings) - * [accept_language_list](BrowserSettings.md#accept_language_list) - * [application_cache_disabled](BrowserSettings.md#application_cache_disabled) * [background_color](BrowserSettings.md#background_color) * [databases_disabled](BrowserSettings.md#databases_disabled) * [default_encoding](BrowserSettings.md#default_encoding) * [dom_paste_disabled](BrowserSettings.md#dom_paste_disabled) - * [file_access_from_file_urls_allowed](BrowserSettings.md#file_access_from_file_urls_allowed) * [inherit_client_handlers_for_popups](BrowserSettings.md#inherit_client_handlers_for_popups) * [image_load_disabled](BrowserSettings.md#image_load_disabled) * [javascript_disabled](BrowserSettings.md#javascript_disabled) * [javascript_close_windows_disallowed](BrowserSettings.md#javascript_close_windows_disallowed) * [javascript_access_clipboard_disallowed](BrowserSettings.md#javascript_access_clipboard_disallowed) * [local_storage_disabled](BrowserSettings.md#local_storage_disabled) - * [plugins_disabled](BrowserSettings.md#plugins_disabled) * [remote_fonts](BrowserSettings.md#remote_fonts) * [shrink_standalone_images_to_fit](BrowserSettings.md#shrink_standalone_images_to_fit) * [tab_to_links_disabled](BrowserSettings.md#tab_to_links_disabled) * [text_area_resize_disabled](BrowserSettings.md#text_area_resize_disabled) - * [universal_access_from_file_urls_allowed](BrowserSettings.md#universal_access_from_file_urls_allowed) * [user_style_sheet_location](BrowserSettings.md#user_style_sheet_location) - * [web_security_disabled](BrowserSettings.md#web_security_disabled) * [webgl_disabled](BrowserSettings.md#webgl_disabled) * [windowless_frame_rate](BrowserSettings.md#windowless_frame_rate) * [Callback (object)](Callback.md#callback-object) @@ -203,9 +188,6 @@ * [GetExpires](Cookie.md#getexpires) * [CookieManager (class)](CookieManager.md#cookiemanager-class) * [GetGlobalManager](CookieManager.md#getglobalmanager) - * [GetBlockingManager](CookieManager.md#getblockingmanager) - * [CreateManager](CookieManager.md#createmanager) - * [SetSupportedSchemes](CookieManager.md#setsupportedschemes) * [VisitAllCookies](CookieManager.md#visitallcookies) * [VisitUrlCookies](CookieManager.md#visiturlcookies) * [SetCookie](CookieManager.md#setcookie) @@ -225,7 +207,6 @@ * [DownloadHandler](DownloadHandler.md#downloadhandler) * [DpiAware (class)](DpiAware.md#dpiaware-class) * [CalculateWindowSize](DpiAware.md#calculatewindowsize) - * [EnableHighDpiSupport](DpiAware.md#enablehighdpisupport) * [GetSystemDpi](DpiAware.md#getsystemdpi) * [IsProcessDpiAware](DpiAware.md#isprocessdpiaware) * [SetProcessDpiAware](DpiAware.md#setprocessdpiaware) @@ -392,13 +373,9 @@ * [GetResourceType](Request.md#getresourcetype) * [GetTransitionType](Request.md#gettransitiontype) * [RequestHandler (interface)](RequestHandler.md#requesthandler-interface) - * [CanGetCookies](RequestHandler.md#cangetcookies) - * [CanSetCookie](RequestHandler.md#cansetcookie) * [GetAuthCredentials](RequestHandler.md#getauthcredentials) - * [GetCookieManager](RequestHandler.md#getcookiemanager) * [GetResourceHandler](RequestHandler.md#getresourcehandler) * [OnBeforeBrowse](RequestHandler.md#onbeforebrowse) - * [_OnBeforePluginLoad](RequestHandler.md#_onbeforepluginload) * [OnBeforeResourceLoad](RequestHandler.md#onbeforeresourceload) * [_OnCertificateError](RequestHandler.md#_oncertificateerror) * [OnQuotaRequest](RequestHandler.md#onquotarequest) @@ -433,11 +410,6 @@ * [OnContextCreated](V8ContextHandler.md#oncontextcreated) * [OnContextReleased](V8ContextHandler.md#oncontextreleased) * [Virtual Key codes](VirtualKey.md#virtual-key-codes) -* [WebPluginInfo (object)](WebPluginInfo.md#webplugininfo-object) - * [GetName](WebPluginInfo.md#getname) - * [GetPath](WebPluginInfo.md#getpath) - * [GetVersion](WebPluginInfo.md#getversion) - * [GetDescription](WebPluginInfo.md#getdescription) * [WebRequest (class)](WebRequest.md#webrequest-class) * [Create](WebRequest.md#create) * [GetRequest](WebRequest.md#getrequest) diff --git a/api/ApplicationSettings.md b/api/ApplicationSettings.md index a9ad20f1b..3d8daa2b3 100644 --- a/api/ApplicationSettings.md +++ b/api/ApplicationSettings.md @@ -7,7 +7,6 @@ Table of contents: * [Introduction](#introduction) * [Settings](#settings) - * [accept_language_list](#accept_language_list) * [app_user_model_id](#app_user_model_id) * [auto_zooming](#auto_zooming) * [background_color](#background_color) @@ -18,7 +17,6 @@ Table of contents: * [downloads_enabled](#downloads_enabled) * [external_message_pump](#external_message_pump) * [framework_dir_path](#framework_dir_path) - * [ignore_certificate_errors](#ignore_certificate_errors) * [javascript_flags](#javascript_flags) * [locale](#locale) * [locales_dir_path](#locales_dir_path) @@ -26,19 +24,15 @@ Table of contents: * [log_file](#log_file) * [log_severity](#log_severity) * [multi_threaded_message_loop](#multi_threaded_message_loop) - * [net_security_expiration_enabled](#net_security_expiration_enabled) * [pack_loading_disabled](#pack_loading_disabled) * [persist_session_cookies](#persist_session_cookies) * [persist_user_preferences](#persist_user_preferences) - * [product_version](#product_version) * [remote_debugging_port](#remote_debugging_port) * [resources_dir_path](#resources_dir_path) - * [single_process](#single_process) * [string_encoding](#string_encoding) * [uncaught_exception_stack_size](#uncaught_exception_stack_size) * [unique_request_context_per_browser](#unique_request_context_per_browser) * [user_agent](#user_agent) - * [user_data_path](#user_data_path) * [windowless_rendering_enabled](#windowless_rendering_enabled) @@ -57,18 +51,6 @@ to Chromium Preferences. ## Settings -### accept_language_list - -(string) -Comma delimited ordered list of language codes without any -whitespace that -will be used in the "Accept-Language" HTTP header. May be overridden on a -per-browser basis using the CefBrowserSettings.accept_language_list value. -If both values are empty then "en-US,en" will be used. Can be overridden -for individual CefRequestContext instances via the -CefRequestContextSettings.accept_language_list value. - - ### app_user_model_id This is setting is applied only on Windows. @@ -231,40 +213,6 @@ the "framework-dir-path" command-line switch. See also [Issue #304](../../../issues/304). -### ignore_certificate_errors - -(bool) -Set to true (1) to ignore errors related to invalid SSL certificates. -Enabling this setting can lead to potential security vulnerabilities like -"man in the middle" attacks. Applications that load content from the -internet should not enable this setting. Also configurable using the -"ignore-certificate-errors" [command-line switch](CommandLineSwitches.md). -Can be overridden for individual CefRequestContext instances via the -CefRequestContextSettings.ignore_certificate_errors value. - -__IMPORTANT__: This option not only ignores all certificate errors, -but it also enables caching of content due to custom patch being -applied (read more in "NOTE ON CACHING" further down). If you don't -want this caching feature of insecure content then alternatively you -can ignore certificate errors using the -RequestHandler.[_OnCertificateError()](#_oncertificateerror) -callback. Note that disk caching is enabled only when the "cache_path" -option is set. - -__NOTE ON CACHING__: Chromium by default disallows caching of -content when there is certificate error. There is a issue125.patch -in the patches/ directory that can be enabled when doing a custom -CEF build. This patch changes the caching behavior on sites with SSL -certificate errors when used with this setting. This patch can be -applied Chromium sources to allow for caching even when there is -certificate error, but only when the "ignore_certificate_errors" -option is set to True. -When it's set to False then the Chromium's caching behavior does not -change. Enabling caching with certificate errors is useful on local -private networks that use self-signed SSL certificates. See the -referenced CEF topic in [Issue #125](../../../issues/125) for more details. - - ### javascript_flags (string) @@ -424,15 +372,6 @@ the module directory on Windows/Linux or the app bundle Resources directory on Mac OS X. Also configurable using the --resources-dir-path switch. -### single_process - -(bool) -Set to true (1) to use a single process for the browser and renderer. This -run mode is not officially supported by Chromium and is less stable than -the multi-process default. Also configurable using the "single-process" -[command-line switch](CommandLineSwitches.md). - - ### string_encoding (string) @@ -473,8 +412,7 @@ set `unique_request_context_per_browser` to True. In upstream CEF each request context may have separate settings like cache_path, persist_session_cookies, persist_user_preferences, -ignore_certificate_errors, enable_net_security_expiration, -accept_language_list. Such functionality wasn't yet exposed in CEF Python. +enable_net_security_expiration. Such functionality wasn't yet exposed in CEF Python. ### user_agent @@ -485,17 +423,6 @@ default User-Agent string will be used. Also configurable using the "user-agent" [command-line switch](CommandLineSwitches.md). -### user_data_path - -(string) -The location where user data such as spell checking dictionary files will -be stored on disk. If empty then the default platform-specific user data -directory will be used (`"~/.cef_user_data"` directory on Linux, -`"~/Library/Application Support/CEF/User Data"` directory on Mac OS X, -`"Local Settings\Application Data\CEF\User Data"` directory under the user -profile directory on Windows). - - ### windowless_rendering_enabled (bool) diff --git a/api/Browser.md b/api/Browser.md index b34b90e2f..6e7ef9dba 100644 --- a/api/Browser.md +++ b/api/Browser.md @@ -63,7 +63,6 @@ Table of contents: * [Invalidate](#invalidate) * [IsFullscreen](#isfullscreen) * [IsLoading](#isloading) - * [IsMouseCursorChangeDisabled](#ismousecursorchangedisabled) * [IsPopup](#ispopup) * [IsWindowRenderingDisabled](#iswindowrenderingdisabled) * [LoadUrl](#loadurl) @@ -81,13 +80,11 @@ Table of contents: * [SendMouseClickEvent](#sendmouseclickevent) * [SendMouseMoveEvent](#sendmousemoveevent) * [SendMouseWheelEvent](#sendmousewheelevent) - * [SendFocusEvent](#sendfocusevent) * [SendCaptureLostEvent](#sendcapturelostevent) * [SetAccessibilityState](#setaccessibilitystate) * [SetClientCallback](#setclientcallback) * [SetClientHandler](#setclienthandler) * [SetFocus](#setfocus) - * [SetMouseCursorChangeDisabled](#setmousecursorchangedisabled) * [SetJavascriptBindings](#setjavascriptbindings) * [SetUserData](#setuserdata) * [SetZoomLevel](#setzoomlevel) @@ -659,17 +656,6 @@ Available only in CEF 3. Not yet implemented. Returns true if the browser is currently loading. -### IsMouseCursorChangeDisabled - -| | | -| --- | --- | -| __Return__ | bool | - -Available only in CEF 3. - -Returns true if mouse cursor change is disabled. - - ### IsPopup | | | @@ -894,16 +880,6 @@ flags see SendMouseClickEvent(). Send a mouse wheel event to the browser. The |x| and |y| coordinates are relative to the upper-left corner of the view. The |deltaX| and |deltaY| values represent the movement delta in the X and Y directions respectively. In order to scroll inside select popups with window rendering disabled [RenderHandler](RenderHandler.md).GetScreenPoint() should be implemented properly. For a list of modifiers flags see SendMouseClickEvent(). -### SendFocusEvent - -| Parameter | Type | -| --- | --- | -| setFocus | bool | -| __Return__ | void | - -Send a focus event to the browser. - - ### SendCaptureLostEvent | | | @@ -988,16 +964,6 @@ LifespanHandler etc. Set whether the browser is focused. -### SetMouseCursorChangeDisabled - -| Parameter | Type | -| --- | --- | -| disabled | bool | -| __Return__ | void | - -Set whether mouse cursor change is disabled. - - ### SetJavascriptBindings | Parameter | Type | diff --git a/api/BrowserSettings.md b/api/BrowserSettings.md index ed2b2e50d..ae806824d 100644 --- a/api/BrowserSettings.md +++ b/api/BrowserSettings.md @@ -8,27 +8,21 @@ Table of contents: * [Introduction](#introduction) * [Settings](#settings) * [Font settings](#font-settings) - * [accept_language_list](#accept_language_list) - * [application_cache_disabled](#application_cache_disabled) * [background_color](#background_color) * [databases_disabled](#databases_disabled) * [default_encoding](#default_encoding) * [dom_paste_disabled](#dom_paste_disabled) - * [file_access_from_file_urls_allowed](#file_access_from_file_urls_allowed) * [inherit_client_handlers_for_popups](#inherit_client_handlers_for_popups) * [image_load_disabled](#image_load_disabled) * [javascript_disabled](#javascript_disabled) * [javascript_close_windows_disallowed](#javascript_close_windows_disallowed) * [javascript_access_clipboard_disallowed](#javascript_access_clipboard_disallowed) * [local_storage_disabled](#local_storage_disabled) - * [plugins_disabled](#plugins_disabled) * [remote_fonts](#remote_fonts) * [shrink_standalone_images_to_fit](#shrink_standalone_images_to_fit) * [tab_to_links_disabled](#tab_to_links_disabled) * [text_area_resize_disabled](#text_area_resize_disabled) - * [universal_access_from_file_urls_allowed](#universal_access_from_file_urls_allowed) * [user_style_sheet_location](#user_style_sheet_location) - * [web_security_disabled](#web_security_disabled) * [webgl_disabled](#webgl_disabled) * [windowless_frame_rate](#windowless_frame_rate) @@ -60,20 +54,6 @@ In some cases, the default values of settings that are suggested by its name may * minimum_logical_font_size (int) -### accept_language_list - -(string) -Comma delimited ordered list of language codes without any whitespace that -will be used in the "Accept-Language" HTTP header. May be set globally -using the CefBrowserSettings.accept_language_list value. If both values are -empty then "en-US,en" will be used. - - -### application_cache_disabled - -(bool) Controls whether the application cache can be used. Also configurable using the --disable-application-cache switch. - - ### background_color (int) @@ -106,11 +86,6 @@ in a known order. Equivalent to the `SkColor` type in Chromium. (bool) Controls whether DOM pasting is supported in the editor via `execCommand("paste")`. The |javascript_access_clipboard_disallowed| setting must also be set (to true or false). Also configurable using the --disable-javascript-dom-paste switch. -### file_access_from_file_urls_allowed - -(bool) Controls whether file URLs will have access to other file URLs. Also configurable using the --allow-access-from-files switch. Other similar switches are: --allow-file-access and --allow-file-access-from-files. - - ### inherit_client_handlers_for_popups @@ -155,11 +130,6 @@ switch. (bool) Controls whether local storage can be used. Also configurable using the --disable-local-storage switch. -### plugins_disabled - -(bool) Controls whether any plugins will be loaded. Also configurable using the --disable-plugins switch. - - ### remote_fonts (bool) Controls the loading of fonts from remote sources. Also configurable using the --disable-remote-fonts switch. @@ -180,11 +150,6 @@ switch. (bool) Controls whether text areas can be resized. Also configurable using the --disable-text-area-resize switch. -### universal_access_from_file_urls_allowed - -(bool) Controls whether file URLs will have access to all URLs. Also configurable using the --allow-universal-access-from-files switch. Other similar switches are --allow-file-access and --allow-file-access-from-files. - - ### user_style_sheet_location (string) Location of the user style sheet that will be used for all pages. This must be a data URL of the form `data:text/css;charset=utf-8;base64,content` where "content" is the base64 encoded contents of the CSS file. Also configurable using the "user-style-sheet-location" command-line switch. @@ -192,11 +157,6 @@ switch. This setting was removed in Chrome 33. Soon it will be removed from cefpython as well. -### web_security_disabled - -(bool) Controls whether web security restrictions (same-origin policy) will be enforced. Disabling this setting is not recommend as it will allow risky security behavior such as cross-site scripting (XSS). Also configurable using the --disable-web-security switch. - - ### webgl_disabled (bool) Controls whether WebGL can be used. Note that WebGL requires hardware support and may not work on all systems even when enabled. Also configurable using the --disable-webgl switch. diff --git a/api/CookieAccessFilter.md b/api/CookieAccessFilter.md new file mode 100644 index 000000000..d2ac4292c --- /dev/null +++ b/api/CookieAccessFilter.md @@ -0,0 +1,45 @@ +[API categories](API-categories.md) | [API index](API-index.md) + + +# CookieAccessFilter (interface) + + + +Table of contents: +* [Callbacks](#callbacks) + * [CanSendCookie](#cansendcookie) + * [CanSaveCookie](#cansavecookie) + + +## Callbacks + + +### CanSendCookie + +| Parameter | Type | +| --- | --- | +| browser | [Browser](Browser.md) | +| frame | [Frame](Frame.md) | +| request | [Request](Request.md) | +| cookie | [Cookie](Cookie.md) | +| __Return__ | bool | + +Called on the IO thread before a resource is sent. Browser and frame values represent +the source of the request. Return true if the specified cookie can be sent with the +request or false otherwise. + +### CanSaveCookie + +| Parameter | Type | +| --- | --- | +| browser | [Browser](Browser.md) | +| frame | [Frame](Frame.md) | +| request | [Request](Request.md) | +| response | [Response](Response.md) | +| cookie | [Cookie](Cookie.md) | +| __Return__ | bool | + +Called on the IO thread after a resource response is received. Browser and frame values +represent the source of the request. Return true if the specified cookie returned with +the response can be saved or false otherwise. + diff --git a/api/CookieManager.md b/api/CookieManager.md index b0d06a911..c947a3f47 100644 --- a/api/CookieManager.md +++ b/api/CookieManager.md @@ -18,9 +18,6 @@ also have an OnComplete callback. Table of contents: * [Methods](#methods) * [GetGlobalManager](#getglobalmanager) - * [GetBlockingManager](#getblockingmanager) - * [CreateManager](#createmanager) - * [SetSupportedSchemes](#setsupportedschemes) * [VisitAllCookies](#visitallcookies) * [VisitUrlCookies](#visiturlcookies) * [SetCookie](#setcookie) @@ -49,52 +46,6 @@ Description from upstream CEF: > calling CefRequestContext::GetGlobalContext()->GetDefaultCookieManager() -### GetBlockingManager - -| | | -| --- | --- | -| __Return__ | [CookieManager](CookieManager.md) | - -Description from upstream CEF: -> Returns a cookie manager that neither stores nor retrieves cookies. All -> usage of cookies will be blocked including cookies accessed via the network -> (request/response headers), via JavaScript (document.cookie), and via -> CefCookieManager methods. No cookies will be displayed in DevTools. If you -> wish to only block cookies sent via the network use the CefRequestHandler -> CanGetCookies and CanSetCookie methods instead. - - -### CreateManager - -| Parameter | Type | -| --- | --- | -| path | string | -| persistSessionCookies=False | bool | -| __Return__ | [CookieManager](CookieManager.md) | - -Creates a new cookie manager. Otherwise, data will be stored at the -specified |path|. To persist session cookies (cookies without an expiry -date or validity interval) set |persistSessionCookies| -to true. If using global manager then see the [ApplicationSettings](ApplicationSettings.md).`persist_session_cookies` -option. Session cookies are generally intended to be transient and most -Web browsers do not persist them. Returns None if creation fails. - -You can have a separate cookie manager for each browser, -see [RequestHandler](RequestHandler.md).GetCookieManager(). - - -### SetSupportedSchemes - -| Parameter | Type | -| --- | --- | -| schemes | list | -| __Return__ | void | - -Set the schemes supported by this manager. The default schemes ("http", -"https", "ws" and "wss") will always be supported. Must be called before -any cookies are accessed. - - ### VisitAllCookies | Parameter | Type | diff --git a/api/DpiAware.md b/api/DpiAware.md index 5a335b216..77bb91b73 100644 --- a/api/DpiAware.md +++ b/api/DpiAware.md @@ -12,19 +12,14 @@ Table of contents: * [Introduction](#introduction) * [Static methods](#static-methods) * [CalculateWindowSize](#calculatewindowsize) - * [EnableHighDpiSupport](#enablehighdpisupport) * [GetSystemDpi](#getsystemdpi) * [IsProcessDpiAware](#isprocessdpiaware) - * [SetProcessDpiAware](#setprocessdpiaware) * [Scale](#scale) ## Introduction -By default if DPI awareness is not enabled in application, then OS performs display scaling. That causes text to look blurry on high DPI displays. To resolve this you have to - call `cef.DpiAware.EnableHighDpiSupport` method. High DPI support is available only on Windows. - Enabling High DPI support in app can be done by embedding a DPI awareness xml manifest in both main executable and subprocess executable (see [Issue #112](../issues/112) comment #2), or by calling the `cef.DpiAware.EnableHighDpiSupport` method. ## Static methods @@ -46,21 +41,6 @@ OS DPI settings. For 800/600 with Win7 DPI settings being set to "Larger 150%" will return 1200/900. -### EnableHighDpiSupport - -| | | -| --- | --- | -| __Return__ | void | - -Calling this function will set current process and subprocesses -to be DPI aware. - -Description from upstream CEF: -> Call during process startup to enable High-DPI support on Windows 7 or newer. -> Older versions of Windows should be left DPI-unaware because they do not -> support DirectWrite and GDI fonts are kerned very badly. - - ### GetSystemDpi | | | @@ -105,19 +85,6 @@ To check whether OS display scaling on high DPI settings was disabled. DPI aware On Win8 this will return True if DPI awareness is set to either "System DPI aware" or "Per monitor DPI aware". -### SetProcessDpiAware - -| | | -| --- | --- | -| __Return__ | void | - -Calling this method is deprecated, call instead `EnableHighDpiSupport()`. -See [Issue #358](../../../issues/358) for how the behavior changed in -latest CEF. This method now internally calls `EnableHighDpiSupport()`. - -Enables DPI awareness for the running process. Embedding a DPI manifest in .exe is the prefered way, as it gives more reliable results, otherwise some display bugs may appear (discussed in the "Introduction" section on this page). - - ### Scale | Parameter | Type | diff --git a/api/LifespanHandler.md b/api/LifespanHandler.md index 1794d62d7..3edd4e677 100644 --- a/api/LifespanHandler.md +++ b/api/LifespanHandler.md @@ -82,42 +82,48 @@ additional usage information. | window_info_out | list[[WindowInfo](WindowInfo.md)] | | client | None | | browser_settings_out | list[[BrowserSettings](BrowserSettings.md)] | +| extra_info_out | dict | | no_javascript_access_out | list[bool] | | __Return__ | bool | Description from upstream CEF: > Called on the UI thread before a new popup browser is created. The -> |browser| and |frame| values represent the source of the popup request. The -> |target_url| and |target_frame_name| values indicate where the popup -> browser should navigate and may be empty if not specified with the request. -> The |target_disposition| value indicates where the user intended to open -> the popup (e.g. current tab, new tab, etc). The |user_gesture| value will -> be true if the popup was opened via explicit user gesture (e.g. clicking a -> link) or false if the popup opened automatically (e.g. via the -> DomContentLoaded event). The |popup_features| structure contains additional +> |browser| and |frame| values represent the source of the popup request. +> The |target_url| and |target_frame_name| values indicate where the popup +> browser should navigate and may be empty if not specified with the +> request. The |target_disposition| value indicates where the user intended +> to open the popup (e.g. current tab, new tab, etc). The |user_gesture| +> value will be true if the popup was opened via explicit user gesture (e.g. +> clicking a link) or false if the popup opened automatically (e.g. via the +> DomContentLoaded event). The |popupFeatures| structure contains additional > information about the requested popup window. To allow creation of the -> popup browser optionally modify |windowInfo|, |client|, |browserSettings| and +> popup browser optionally modify |windowInfo|, |client|, |settings| and > |no_javascript_access| and return false. To cancel creation of the popup -> browser return true. The |client| and |settings| values will default to the -> source browser's values. If the |no_javascript_access| value is set to +> browser return true. The |client| and |settings| values will default to +> the source browser's values. If the |no_javascript_access| value is set to > false the new browser will not be scriptable and may not be hosted in the > same renderer process as the source browser. Any modifications to -> |window_info| will be ignored if the parent browser is wrapped in a +> |windowInfo| will be ignored if the parent browser is wrapped in a > CefBrowserView. Popup browser creation will be canceled if the parent -> browser is destroyed before the popup browser creation completes (indicated -> by a call to OnAfterCreated for the popup browser). +> browser is destroyed before the popup browser creation completes +> (indicated by a call to OnAfterCreated for the popup browser). The +> |extra_info| parameter provides an opportunity to specify extra +> information specific to the created popup browser that will be passed to +> CefRenderProcessHandler::OnBrowserCreated() in the render process. `WindowOpenDisposition` constants in the cefpython module: -* WOD_UNKNOWN, -* WOD_CURRENT_TAB, -* WOD_SINGLETON_TAB, -* WOD_NEW_FOREGROUND_TAB, -* WOD_NEW_BACKGROUND_TAB, -* WOD_NEW_POPUP, -* WOD_NEW_WINDOW, -* WOD_SAVE_TO_DISK, -* WOD_OFF_THE_RECORD, -* WOD_IGNORE_ACTION +* CEF_WOD_UNKNOWN, +* CEF_WOD_CURRENT_TAB, +* CEF_WOD_SINGLETON_TAB, +* CEF_WOD_NEW_FOREGROUND_TAB, +* CEF_WOD_NEW_BACKGROUND_TAB, +* CEF_WOD_NEW_POPUP, +* CEF_WOD_NEW_WINDOW, +* CEF_WOD_SAVE_TO_DISK, +* CEF_WOD_OFF_THE_RECORD, +* CEF_WOD_IGNORE_ACTION, +* CEF_WOD_SWITCH_TO_TAB, +* CEF_WOD_NEW_PICTURE_IN_PICTURE Note that if you return True and create the popup window yourself, then the popup window and parent window will not be able to script each other. diff --git a/api/RequestHandler.md b/api/RequestHandler.md index f1ef8bf72..28c2dc22b 100644 --- a/api/RequestHandler.md +++ b/api/RequestHandler.md @@ -16,13 +16,9 @@ Available in upstream CEF, but not yet exposed to CEF Python: Table of contents: * [Callbacks](#callbacks) - * [CanGetCookies](#cangetcookies) - * [CanSetCookie](#cansetcookie) * [GetAuthCredentials](#getauthcredentials) - * [GetCookieManager](#getcookiemanager) * [GetResourceHandler](#getresourcehandler) * [OnBeforeBrowse](#onbeforebrowse) - * [_OnBeforePluginLoad](#_onbeforepluginload) * [OnBeforeResourceLoad](#onbeforeresourceload) * [_OnCertificateError](#_oncertificateerror) * [OnQuotaRequest](#onquotarequest) @@ -36,39 +32,6 @@ Table of contents: ## Callbacks -### CanGetCookies - -| Parameter | Type | -| --- | --- | -| browser | [Browser](Browser.md) | -| frame | [Frame](Frame.md) | -| request | [Request](Request.md) | -| __Return__ | bool | - -Description from upstream CEF: -> Called on the IO thread before sending a network request with a "Cookie" -> request header. Return true to allow cookies to be included in the network -> request or false to block cookies. The |request| object should not be -> modified in this callback. - - -### CanSetCookie - -| Parameter | Type | -| --- | --- | -| browser | [Browser](Browser.md) | -| frame | [Frame](Frame.md) | -| request | [Request](Request.md) | -| cookie | [Cookie](Cookie.md) | -| __Return__ | bool | - -Description from upstream CEF: -> Called on the IO thread when receiving a network request with a -> "Set-Cookie" response header value represented by |cookie|. Return true to -> allow the cookie to be stored or false to block the cookie. The |request| -> object should not be modified in this callback. - - ### GetAuthCredentials | Parameter | Type | @@ -106,44 +69,6 @@ Example implementations: [[3]](https://github.com/cztomczak/cefpython/blob/cefpython31/cefpython/http_authentication_win.pyx). -### GetCookieManager - -| Parameter | Type | -| --- | --- | -| browser | None or [Browser](Browser.md) | -| main_url | string | -| __Return__ | [CookieManager](CookieManager.md) | - -Called on the IO thread to retrieve the cookie manager. |main_url| -is the URL of the top-level frame. Cookies managers can be unique -per browser or shared across multiple browsers. The global cookie -manager will be used if this method returns None. - -**IMPORTANT**: In some cases this callback is not called due to a -race condition. See Issue [#429](../../../issues/429) for details. - -To successfully implement separate cookie manager per browser session, -you have to set ApplicationSettings.`unique_request_context_per_browser` -to True. Otherwise the browser param passed to this callback will -always be the same first browser that was created using -[cefpython](cefpython.md).`CreateBrowserSync`. - -**NOTE**: If implementing custom cookie managers you will encounter -problems similar to [Issue #365](../../../issues/365) ("Cookies not -flushed to disk when closing app immediately"). To resolve -it you have to call CookieManager.[FlushStore](CookieManager.md#flushstore) -method when closing associated browser. - -Popup browsers created javascript's window.open share the same -renderer process and request context. If you want to have separate -cookie managers for popups created using window.open then you have -to implement the LifespanHandler.`OnBeforePopup` callback. Return -True in that callback to cancel popup creation and instead create -the window on your own and embed browser in it. -The `CreateAnotherBrowser` function from the old v31 wxpython -example does that. - - ### GetResourceHandler | Parameter | Type | @@ -190,48 +115,6 @@ Description from upstream CEF: > navigated automatically (e.g. via the DomContentLoaded event). -### _OnBeforePluginLoad - -| Parameter | Type | -| --- | --- | -| browser | [Browser](Browser.md) | -| mime_type | string | -| plugin_url | string | -| is_main_frame | bool | -| top_origin_url | string | -| plugin_info | [WebPluginInfo](WebPluginInfo.md) | -| __Return__ | bool | - -Description from upstream CEF: -> Called on multiple browser process threads before a plugin instance is -> loaded. |mime_type| is the mime type of the plugin that will be loaded. -> |plugin_url| is the content URL that the plugin will load and may be empty. -> |is_main_frame| will be true if the plugin is being loaded in the main -> (top-level) frame, |top_origin_url| is the URL for the top-level frame that -> contains the plugin when loading a specific plugin instance or empty when -> building the initial list of enabled plugins for 'navigator.plugins' -> JavaScript state. |plugin_info| includes additional information about the -> plugin that will be loaded. |plugin_policy| is the recommended policy. -> Modify |plugin_policy| and return true to change the policy. Return false -> to use the recommended policy. The default plugin policy can be set at -> runtime using the `--plugin-policy=[allow|detect|block]` command-line flag. -> Decisions to mark a plugin as disabled by setting |plugin_policy| to -> PLUGIN_POLICY_DISABLED may be cached when |top_origin_url| is empty. To -> purge the plugin list cache and potentially trigger new calls to this -> method call CefRequestContext::PurgePluginListCache. - -Return True to block loading of the plugin. - -This callback will be executed during browser creation, thus you must -call [cefpython](cefpython.md).SetGlobalClientCallback() to use it. -The callback name was prefixed with "`_`" to distinguish this special -behavior. - -Plugins are loaded on demand, only when website requires it. -This callback is called every time the page tries to load a plugin -(perhaps even multiple times per plugin). - - ### OnBeforeResourceLoad | Parameter | Type | diff --git a/api/WebPluginInfo.md b/api/WebPluginInfo.md deleted file mode 100644 index ad4396d35..000000000 --- a/api/WebPluginInfo.md +++ /dev/null @@ -1,63 +0,0 @@ -[API categories](API-categories.md) | [API index](API-index.md) - - -# WebPluginInfo (object) - -See also [RequestHandler](RequestHandler.md)._OnBeforePluginLoad(). - -Web Plugin API available in upstream CEF, but not yet exposed in CEF Python -(see src/include/cef_web_plugin.h): - -* CefRegisterCdmCallback -* CefRegisterWidevineCdm -* CefIsWebPluginUnstable -* CefRegisterWebPluginCrash -* CefUnregisterInternalWebPlugin -* CefRefreshWebPlugins -* CefVisitWebPluginInfo - - -Table of contents: -* [Methods](#methods) - * [GetName](#getname) - * [GetPath](#getpath) - * [GetVersion](#getversion) - * [GetDescription](#getdescription) - -## Methods - - -### GetName - -| | | -| --- | --- | -| __Return__ | string | - -Returns the plugin name (i.e. Flash). - - -### GetPath - -| | | -| --- | --- | -| __Return__ | string | - -Returns the plugin file path (DLL/bundle/library). - - -### GetVersion - -| | | -| --- | --- | -| __Return__ | string | - -Returns the version of the plugin (may be OS-specific). - - -### GetDescription - -| | | -| --- | --- | -| __Return__ | string | - -Returns a description of the plugin from the version information. diff --git a/docs/Build-instructions.md b/docs/Build-instructions.md index 9ca4d6e99..6ff602f80 100644 --- a/docs/Build-instructions.md +++ b/docs/Build-instructions.md @@ -9,13 +9,12 @@ Table of contents: * [Linux](#linux) * [Mac](#mac) * [All platforms](#all-platforms) -* [Build using prebuilt CEF binaries and libraries](#build-using-prebuilt-cef-binaries-and-libraries) * [Build using CEF binaries from Spotify Automated Builds](#build-using-cef-binaries-from-spotify-automated-builds) * [Build upstream CEF from sources](#build-upstream-cef-from-sources) * [Building old unsupported version of Chromium](#building-old-unsupported-version-of-chromium) * [Possible errors](#possible-errors) * [Build CEF manually](#build-cef-manually) -* [CEF Automated Builds (Spotify and Adobe)](#cef-automated-builds-spotify-and-adobe) +* [CEF Automated Builds (Spotify)](#cef-automated-builds-spotify) * [Notes](#notes) * [How to patch mini tutorial](#how-to-patch-mini-tutorial) @@ -48,13 +47,13 @@ Before you can build CEF Python or CEF you must satisfy ## Quick build instructions for Windows -Complete steps for building CEF Python v50+ with Python 2.7 using +Complete steps for building CEF Python v123+ with Python 3 using prebuilt binaries and libraries from GitHub Releases. When cloning repository you should checkout a stable branch which are named "cefpythonXX" where XX is Chromium version number. -1) Tested and works fine on Windows 7 64-bit +1) Tested and works fine on Windows 11 64-bit 2) Download [ninja](https://github.com/ninja-build/ninja) 1.7.2 or later and add it to PATH. @@ -235,37 +234,6 @@ requirements common for all platforms. cefpython version to avoid issues. -## Build using prebuilt CEF binaries and libraries - -When cloning repository you should checkout a stable branch which -are named "cefpythonXX" where XX is Chromium version number. - -1) Clone cefpython, checkout for example "cefpython57" branch - that includes Chromium v57, then create a build/ directory and enter it: -``` -git clone https://github.com/cztomczak/cefpython.git -cd cefpython/ -git checkout cefpython57 -mkdir build/ -cd build/ -``` - -2) Download binaries and libraries from - [GH releases](https://github.com/cztomczak/cefpython/tags) - tagged eg. 'v57-upstream' when building v57. The version - of the binaries must match exactly the CEF version from - the "cefpython/src/version/" directory (look for CEF_VERSION - constant in .h file). - -3) Extract the downloaded archive eg. "cef55_3.2883.1553.g80bd606_win32.zip" - in the "build/" directory (using "extract here" option) - -4) Run the build.py tool (xx.x is version number): -``` -python ../tools/build.py xx.x -``` - - ## Build using CEF binaries from Spotify Automated Builds When cloning repository you should checkout a stable branch which @@ -281,7 +249,7 @@ mkdir build/ cd build/ ``` -2) Download CEF binaries from [Spotify Automated Builds](http://opensource.spotify.com/cefbuilds/index.html). +2) Download CEF binaries from [Spotify Automated Builds](https://cef-builds.spotifycdn.com/index.html). The version of the binaries must match exactly the CEF version from the "cefpython/src/version/" directory (look for CEF_VERSION constant in .h file). @@ -421,17 +389,14 @@ Note that CEF patches must be applied in the "download_dir/chromium/src/cef/" directory, not in the "download_dir/cef/" directory. -## CEF Automated Builds (Spotify and Adobe) +## CEF Automated Builds (Spotify) There are two sites that provide automated CEF builds: -* Spotify - http://opensource.spotify.com/cefbuilds/index.html +* Spotify - https://cef-builds.spotifycdn.com/index.html * This is the new build system * Since June 2016 all builds are without tcmalloc, see [cefpython/#73](https://github.com/cztomczak/cefpython/issues/73) and [cef/#1827](https://bitbucket.org/chromiumembedded/cef/issues/1827) -* Adobe - https://cefbuilds.com/ - * This is the old build system. Not tested whether it builds without - tcmalloc. ## Notes diff --git a/docs/Migration-guide.md b/docs/Migration-guide.md index 5ad3d4384..8f63a4529 100644 --- a/docs/Migration-guide.md +++ b/docs/Migration-guide.md @@ -52,6 +52,14 @@ Table of contents: * [v66+ Changes to Mac apps that integrate into existing message loop (Qt, wxPython)](#v66-changes-to-mac-apps-that-integrate-into-existing-message-loop-qt-wxpython) * [v66.1+ Navigation urls passed to CreateBrowserSync or LoadUrl methods need to be encoded by app code](#v661-navigation-urls-passed-to-createbrowsersync-or-loadurl-methods-need-to-be-encoded-by-app-code) * [v67+ Do not call the 'WindowUtils.OnSize' function](#v67-do-not-call-the-windowutilsonsize-function) +* [v123+ cef_types changed](#v123-cef_types-changed) +* [v123+ Windows dpiaware change](#v123-windows-dpiaware-change) +* [v123+ plugin support is removed](#v123-plugin-support-is-removed) +* [v123+ cookie related code is changed](#v123-cookie-related-code-is-changed) +* [v123+ LifeSpan Handler callback](#v123-lifespan-handler-callback) +* [v123+ BrowserSettings options removed](#v123-browsersettings-options-removed) +* [v123+ Browser's function `SendProcessMessage` is removed](#v123-browsers-function-sendprocessmessage-is-removed) +* [v123+ Response's function `GetHeader` is renamed to `GetHeaderByName`](#v123-responses-function-getheader-is-renamed-to-getheaderbyname) ## v49+ Distribution packages @@ -505,4 +513,74 @@ This function can sometimes cause app hanging during window resize. Call instead the new `WindowUtils`.[UpdateBrowserSize](../api/WindowUtils.md#updatebrowsersize) function. Except when you use the `pywin32.py` example, in such case `WindowUtils.OnSize` must be called. -See [Issue #464](../../../issues/464) for more details. \ No newline at end of file +See [Issue #464](../../../issues/464) for more details. + +## v123+ cef_types changed + +cef_types removed: +- WOD_UNKNOWN, +- WOD_CURRENT_TAB, +- WOD_SINGLETON_TAB, +- WOD_NEW_FOREGROUND_TAB, +- WOD_NEW_BACKGROUND_TAB, +- WOD_NEW_POPUP, +- WOD_NEW_WINDOW, +- WOD_SAVE_TO_DISK, +- WOD_OFF_THE_RECORD, +- WOD_IGNORE_ACTION +- TID_FILE + +cef_types added: +- CEF_WOD_UNKNOWN, +- CEF_WOD_CURRENT_TAB, +- CEF_WOD_SINGLETON_TAB, +- CEF_WOD_NEW_FOREGROUND_TAB, +- CEF_WOD_NEW_BACKGROUND_TAB, +- CEF_WOD_NEW_POPUP, +- CEF_WOD_NEW_WINDOW, +- CEF_WOD_SAVE_TO_DISK, +- CEF_WOD_OFF_THE_RECORD, +- CEF_WOD_IGNORE_ACTION + +## v123+ Windows dpiaware change + +Per https://github.com/chromiumembedded/cef/issues/3452 windows high-dpi support is now enabled +You shouldn't normally need to use DpiAware class + +## v123+ plugin support is removed + +As cef has removed plugin support https://github.com/chromiumembedded/cef/commit/28c7f040016a0271ec2612cc5021599fb55a1054 +previous popular plugin such as flash, pdf would no longer work +`OnBeforePluginLoad` handler is removed + +## v123+ cookie related code is changed + +- removed `CanGetCookies` +- removed `CanSetCookie` +- added `CanSendCookie` +- added `CanSaveCookie` + +## v123+ LifeSpan Handler callback +`OnBeforePopup` callback function params adds extra `extra_info` + +## v123+ BrowserSettings options removed + +The following options were removed from BrowserSettings: +- accept_language_list +- product_version +- net_security_expiration_enabled +- single_process +- author_and_user_styles_disabled +- ignore_certificate_errors +- user_data_path +- application_cache_disabled +- plugins_disabled +- universal_access_from_file_urls_allowed +- file_access_from_file_urls_allowed +- web_security_disabled + +## v123+ Browser's function `SendProcessMessage` is removed + +## v123+ Response's function `GetHeader` is renamed to `GetHeaderByName` + +## v123+ CookieManager's `GetBlockingManager`, `CreateManager` and `SetSupportedSchemes` functions are removed \ No newline at end of file diff --git a/examples/hello_world.py b/examples/hello_world.py index 789f4666e..5968c6542 100644 --- a/examples/hello_world.py +++ b/examples/hello_world.py @@ -11,6 +11,7 @@ from cefpython3 import cefpython as cef import platform import sys +from pkg_resources import parse_version def main(): @@ -31,7 +32,7 @@ def check_versions(): print("[hello_world.py] Python {ver} {arch}".format( ver=platform.python_version(), arch=platform.architecture()[0])) - assert cef.__version__ >= "57.0", "CEF Python v57.0+ required to run this" + assert parse_version(cef.__version__) >= parse_version("57.0"), "CEF Python v57.0+ required to run this" if __name__ == '__main__': diff --git a/examples/pysdl2.py b/examples/pysdl2.py index 97f9293dc..dfce311d2 100644 --- a/examples/pysdl2.py +++ b/examples/pysdl2.py @@ -127,6 +127,11 @@ def main(): dest='renderer', choices=['software', 'hardware'] ) + parser.add_argument( + '--debug', + help='debug app', + action='store_true' + ) args = parser.parse_args() logLevel = logging.INFO if args.verbose: @@ -135,7 +140,7 @@ def main(): format='[%(filename)s %(levelname)s]: %(message)s', level=logLevel ) - logging.info("Using PySDL2 %s" % sdl2.__version__) + logging.info("Using PySDL2 %s", sdl2.__version__) version = sdl2.SDL_version() sdl2.SDL_GetVersion(version) logging.info( @@ -224,7 +229,7 @@ def main(): browser.SetClientHandler(renderHandler) # Must call WasResized at least once to let know CEF that # viewport size is available and that OnPaint may be called. - browser.SendFocusEvent(True) + browser.SetFocus(True) browser.WasResized() # Begin the main rendering loop diff --git a/examples/pywin32.py b/examples/pywin32.py index bf8d2b9be..0ca8f7482 100644 --- a/examples/pywin32.py +++ b/examples/pywin32.py @@ -16,6 +16,7 @@ from cefpython3 import cefpython as cef import distutils.sysconfig +from pkg_resources import parse_version import math import os import platform @@ -108,7 +109,7 @@ def check_versions(): pywin32_version = fp.read().strip() print("[pywin32.py] pywin32 {ver}".format(ver=pywin32_version)) - assert cef.__version__ >= "57.0", "CEF Python v57.0+ required to run this" + assert parse_version(cef.__version__) >= parse_version("57.0"), "CEF Python v57.0+ required to run this" def create_browser(window_info, settings, url): diff --git a/examples/qt.py b/examples/qt.py index efb1b381f..d359dcd81 100644 --- a/examples/qt.py +++ b/examples/qt.py @@ -18,10 +18,12 @@ import os import platform import sys +from pkg_resources import parse_version # GLOBALS PYQT4 = False PYQT5 = False +PYQT6 = False PYSIDE = False PYSIDE2 = False @@ -39,6 +41,14 @@ from PyQt5.QtCore import * # noinspection PyUnresolvedReferences from PyQt5.QtWidgets import * +elif "pyqt6" in sys.argv: + PYQT6 = True + # noinspection PyUnresolvedReferences + from PyQt6.QtGui import * + # noinspection PyUnresolvedReferences + from PyQt6.QtCore import * + # noinspection PyUnresolvedReferences + from PyQt6.QtWidgets import * elif "pyside" in sys.argv: PYSIDE = True # noinspection PyUnresolvedReferences @@ -65,6 +75,7 @@ print("USAGE:") print(" qt.py pyqt4") print(" qt.py pyqt5") + print(" qt.py pyqt6") print(" qt.py pyside") print(" qt.py pyside2") sys.exit(1) @@ -104,7 +115,10 @@ def main(): main_window.show() main_window.activateWindow() main_window.raise_() - app.exec_() + if PYQT6: + app.exec() + else: + app.exec_() if not cef.GetAppSetting("external_message_pump"): app.stopTimer() del main_window # Just to be safe, similarly to "del app" @@ -116,7 +130,7 @@ def check_versions(): print("[qt.py] CEF Python {ver}".format(ver=cef.__version__)) print("[qt.py] Python {ver} {arch}".format( ver=platform.python_version(), arch=platform.architecture()[0])) - if PYQT4 or PYQT5: + if PYQT4 or PYQT5 or PYQT6: print("[qt.py] PyQt {v1} (qt {v2})".format( v1=PYQT_VERSION_STR, v2=qVersion())) elif PYSIDE: @@ -126,7 +140,7 @@ def check_versions(): print("[qt.py] PySide2 {v1} (qt {v2})".format( v1=PySide2.__version__, v2=QtCore.__version__)) # CEF Python version requirement - assert cef.__version__ >= "55.4", "CEF Python v55.4+ required to run this" + assert parse_version(cef.__version__) >= parse_version("55.4"), "CEF Python v55.4+ required to run this" class MainWindow(QMainWindow): @@ -142,11 +156,16 @@ def __init__(self): self.setWindowTitle("PyQt4 example") elif PYQT5: self.setWindowTitle("PyQt5 example") + elif PYQT6: + self.setWindowTitle("PyQt6 example") elif PYSIDE: self.setWindowTitle("PySide example") elif PYSIDE2: self.setWindowTitle("PySide2 example") - self.setFocusPolicy(Qt.StrongFocus) + if PYQT6: + self.setFocusPolicy(Qt.FocusPolicy.StrongFocus) + else: + self.setFocusPolicy(Qt.StrongFocus) self.setupLayout() def setupLayout(self): @@ -167,7 +186,7 @@ def setupLayout(self): frame.setLayout(layout) self.setCentralWidget(frame) - if (PYSIDE2 or PYQT5) and WINDOWS: + if (PYSIDE2 or PYQT5 or PYQT6) and WINDOWS: # On Windows with PyQt5 main window must be shown first # before CEF browser is embedded, otherwise window is # not resized and application hangs during resize. diff --git a/examples/screenshot.py b/examples/screenshot.py index 5ca8d4913..f494c0013 100644 --- a/examples/screenshot.py +++ b/examples/screenshot.py @@ -36,6 +36,7 @@ """ from cefpython3 import cefpython as cef +from pkg_resources import parse_version import os import platform import subprocess @@ -99,7 +100,7 @@ def check_versions(): ver=platform.python_version(), arch=platform.architecture()[0])) print("[screenshot.py] Pillow {ver}".format(ver=PILLOW_VERSION)) - assert cef.__version__ >= "57.0", "CEF Python v57.0+ required to run this" + assert parse_version(cef.__version__) >= parse_version("57.0"), "CEF Python v57.0+ required to run this" def command_line_arguments(): @@ -139,9 +140,10 @@ def create_browser(settings): browser = cef.CreateBrowserSync(window_info=window_info, settings=settings, url=URL) + print('created browser ', browser) browser.SetClientHandler(LoadHandler()) browser.SetClientHandler(RenderHandler()) - browser.SendFocusEvent(True) + browser.SetFocus(True) # You must call WasResized at least once to let know CEF that # viewport size is available and that OnPaint may be called. browser.WasResized() diff --git a/examples/snippets/network_cookies.py b/examples/snippets/network_cookies.py index c3631cff5..a4504be25 100644 --- a/examples/snippets/network_cookies.py +++ b/examples/snippets/network_cookies.py @@ -1,5 +1,5 @@ """ -Implement RequestHandler.CanGetCookies and CanSetCookie +Implement RequestHandler.CanSendCookie and CanSaveCookie to block or allow cookies over network requests. """ @@ -22,23 +22,23 @@ def __init__(self): self.getcount = 0 self.setcount = 0 - def CanGetCookies(self, frame, request, **_): + def CanSendCookie(self, browser, frame, request, cookie): # There are multiple iframes on that website, let's log # cookies only for the main frame. if frame.IsMain(): self.getcount += 1 - print("-- CanGetCookies #"+str(self.getcount)) + print("-- CanSendCookie #"+str(self.getcount)) print("url="+request.GetUrl()[0:80]) print("") # Return True to allow reading cookies or False to block return True - def CanSetCookie(self, frame, request, cookie, **_): + def CanSaveCookie(self, browser, frame, request, response, cookie): # There are multiple iframes on that website, let's log # cookies only for the main frame. if frame.IsMain(): self.setcount += 1 - print("-- CanSetCookie @"+str(self.setcount)) + print("-- CanSaveCookie @"+str(self.setcount)) print("url="+request.GetUrl()[0:80]) print("Name="+cookie.GetName()) print("Value="+cookie.GetValue()) @@ -48,4 +48,4 @@ def CanSetCookie(self, frame, request, cookie, **_): if __name__ == '__main__': - main() + main() \ No newline at end of file diff --git a/examples/snippets/ondomready.py b/examples/snippets/ondomready.py index 8775129c7..1ca1fcf0b 100644 --- a/examples/snippets/ondomready.py +++ b/examples/snippets/ondomready.py @@ -8,7 +8,7 @@ def main(): cef.Initialize() - browser = cef.CreateBrowserSync(url="https://www.google.com/", + browser = cef.CreateBrowserSync(url="https://example.com/", window_title="_OnDomReady event") load_handler = LoadHandler(browser) browser.SetClientHandler(load_handler) diff --git a/examples/tkinter_.py b/examples/tkinter_.py index 327f171fb..63b75bbbb 100644 --- a/examples/tkinter_.py +++ b/examples/tkinter_.py @@ -26,6 +26,7 @@ import os import platform import logging as _logging +from pkg_resources import parse_version # Fix for PyCharm hints warnings WindowUtils = cef.WindowUtils() @@ -53,7 +54,7 @@ def main(): logger.info("Python {ver} {arch}".format( ver=platform.python_version(), arch=platform.architecture()[0])) logger.info("Tk {ver}".format(ver=tk.Tcl().eval('info patchlevel'))) - assert cef.__version__ >= "55.3", "CEF Python v55.3+ required to run this" + assert parse_version(cef.__version__) >= parse_version("55.3"), "CEF Python v55.3+ required to run this" sys.excepthook = cef.ExceptHook # To shutdown all CEF processes on error # Tk must be initialized before CEF otherwise fatal error (Issue #306) root = tk.Tk() diff --git a/examples/tutorial.py b/examples/tutorial.py index 860bbe12c..d02059d43 100644 --- a/examples/tutorial.py +++ b/examples/tutorial.py @@ -6,6 +6,7 @@ import platform import sys import threading +from pkg_resources import parse_version # HTML code. Browser will navigate to a Data uri created # from this html code. @@ -85,7 +86,7 @@ def check_versions(): print("[tutorial.py] Python {ver} {arch}".format( ver=platform.python_version(), arch=platform.architecture()[0])) - assert cef.__version__ >= "57.0", "CEF Python v57.0+ required to run this" + assert parse_version(cef.__version__) >= parse_version("57.0"), "CEF Python v57.0+ required to run this" def html_to_data_uri(html, js_callback=None): @@ -188,6 +189,7 @@ def __init__(self, browser): def test_multiple_callbacks(self, js_callback): """Test both javascript and python callbacks.""" + print('in test_multiple_callbacks') js_print(self.browser, "Python", "test_multiple_callbacks", "Called from Javascript. Will call Javascript callback now.") diff --git a/examples/wxpython.py b/examples/wxpython.py index 92dd7d834..df1391ed7 100644 --- a/examples/wxpython.py +++ b/examples/wxpython.py @@ -12,6 +12,7 @@ import platform import sys import os +from pkg_resources import parse_version # Platforms WINDOWS = (platform.system() == "Windows") @@ -47,9 +48,6 @@ def main(): # the same time. This is an incorrect approach # and only a temporary fix. settings["external_message_pump"] = True - if WINDOWS: - # noinspection PyUnresolvedReferences, PyArgumentList - cef.DpiAware.EnableHighDpiSupport() cef.Initialize(settings=settings) app = CefApp(False) app.MainLoop() @@ -65,7 +63,7 @@ def check_versions(): ver=platform.python_version(), arch=platform.architecture()[0])) print("[wxpython.py] wxPython {ver}".format(ver=wx.version())) # CEF Python version requirement - assert cef.__version__ >= "66.0", "CEF Python v66.0+ required to run this" + assert parse_version(cef.__version__) >= parse_version("66.0"), "CEF Python v66.0+ required to run this" def scale_window_size_for_high_dpi(width, height): diff --git a/src/browser.pyx b/src/browser.pyx index c8cba03ad..e734e5995 100644 --- a/src/browser.pyx +++ b/src/browser.pyx @@ -5,6 +5,8 @@ include "cefpython.pyx" cimport cef_types +from libc.stdint cimport uint32_t, int64_t +from libcpp cimport nullptr from cef_types cimport cef_state_t IF UNAME_SYSNAME == "Linux": cimport x11 @@ -59,7 +61,7 @@ cdef PyBrowser GetPyBrowser(CefRefPtr[CefBrowser] cefBrowser, global g_pyBrowsers - if cefBrowser == NULL or not cefBrowser.get(): + if not cefBrowser or not cefBrowser.get(): raise Exception("{caller}: CefBrowser reference is NULL" .format(caller=callerIdStr)) @@ -148,7 +150,7 @@ cdef void RemovePyBrowser(int browserId) except *: # noinspection PyUnresolvedReferences Debug("del g_pyBrowsers[%s]" % browserId) pyBrowser = g_pyBrowsers[browserId] - pyBrowser.cefBrowser.Assign(NULL) + pyBrowser.cefBrowser.Assign(nullptr) del pyBrowser del g_pyBrowsers[browserId] g_unreferenced_browsers.append(browserId) @@ -207,7 +209,7 @@ cdef class PyBrowser: cdef void* imageBuffer cdef CefRefPtr[CefBrowser] GetCefBrowser(self) except *: - if self.cefBrowser != NULL and self.cefBrowser.get(): + if self.cefBrowser and self.cefBrowser.get(): return self.cefBrowser raise Exception("PyBrowser.GetCefBrowser() failed: CefBrowser " "was destroyed") @@ -215,7 +217,7 @@ cdef class PyBrowser: cdef CefRefPtr[CefBrowserHost] GetCefBrowserHost(self) except *: cdef CefRefPtr[CefBrowserHost] cefBrowserHost = ( self.GetCefBrowser().get().GetHost()) - if cefBrowserHost != NULL and cefBrowserHost.get(): + if cefBrowserHost and cefBrowserHost.get(): return cefBrowserHost raise Exception("PyBrowser.GetCefBrowserHost() failed: this " "method can only be called in the browser " @@ -246,9 +248,9 @@ cdef class PyBrowser: self.allowedClientCallbacks += ["OnBeforeResourceLoad", "OnResourceRedirect", "GetAuthCredentials", "OnQuotaRequest", "OnProtocolExecution", - "GetResourceHandler", - "OnBeforeBrowse", "OnRendererProcessTerminated", - "OnPluginCrashed", "CanGetCookies", "CanSetCookie"] + "GetResourceHandler", "OnBeforeBrowse", + "OnRendererProcessTerminated", + "CanSendCookie", "CanSaveCookie"] # RequestContextHandler self.allowedClientCallbacks += ["GetCookieManager"] # LoadHandler @@ -394,9 +396,9 @@ cdef class PyBrowser: # If using GetCookieManager to implement custom cookie managers # then flushing of cookies would need to be handled manually. self.GetCefBrowserHost().get().GetRequestContext().get() \ - .GetDefaultCookieManager( - NULL) \ - .get().FlushStore(NULL) + .GetCookieManager( + nullptr) \ + .get().FlushStore(nullptr) cdef int browserId = self.GetCefBrowser().get().GetIdentifier() self.GetCefBrowserHost().get().CloseBrowser(bool(forceClose)) @@ -413,12 +415,12 @@ cdef class PyBrowser: py_string scriptUrl="", int startLine=1): self.GetMainFrame().ExecuteJavascript(jsCode, scriptUrl, startLine) - cpdef py_void Find(self, int searchId, py_string searchText, + cpdef py_void Find(self, py_string searchText, py_bool forward, py_bool matchCase, py_bool findNext): cdef CefString cefSearchText PyToCefString(searchText, cefSearchText) - self.GetCefBrowserHost().get().Find(searchId, cefSearchText, + self.GetCefBrowserHost().get().Find(cefSearchText, bool(forward), bool(matchCase), bool(findNext)) cpdef PyFrame GetFocusedFrame(self): @@ -426,16 +428,18 @@ cdef class PyBrowser: "Browser.GetFocusedFrame() may only be called on UI thread") return GetPyFrame(self.GetCefBrowser().get().GetFocusedFrame()) - cpdef PyFrame GetFrame(self, py_string name): + cpdef PyFrame GetFrameByName(self, py_string name): assert IsThread(TID_UI), ( - "Browser.GetFrame() may only be called on the UI thread") + "Browser.GetFrameByName() may only be called on the UI thread") cdef CefString cefName PyToCefString(name, cefName) - return GetPyFrame(self.GetCefBrowser().get().GetFrame(cefName)) + return GetPyFrame(self.GetCefBrowser().get().GetFrameByName(cefName)) - cpdef object GetFrameByIdentifier(self, object identifier): - return GetPyFrame(self.GetCefBrowser().get().GetFrame( - identifier)) + cpdef object GetFrameByIdentifier(self, py_string identifier): + cdef CefString cefIdentifier + PyToCefString(identifier, cefIdentifier) + return GetPyFrame(self.GetCefBrowser().get().GetFrameByIdentifier( + cefIdentifier)) cpdef list GetFrameNames(self): assert IsThread(TID_UI), ( @@ -456,7 +460,7 @@ cdef class PyBrowser: cdef PyFrame frame cdef list frames = [] for name in names: - frame = self.GetFrame(name) + frame = self.GetFrameByName(name) frames.append(frame) return frames @@ -581,7 +585,7 @@ cdef class PyBrowser: cdef CefBrowserSettings settings cdef CefPoint inspect_element_at self.GetCefBrowserHost().get().ShowDevTools( - window_info, NULL, settings, + window_info, nullptr, settings, inspect_element_at) cpdef py_void StopLoad(self): @@ -654,7 +658,7 @@ cdef class PyBrowser: right = monitorInfo.rcMonitor.right bottom = monitorInfo.rcMonitor.bottom # noinspection PyUnresolvedReferences - SetWindowPos(hwnd, NULL, + SetWindowPos(hwnd, nullptr, left, top, right-left, bottom-top, SWP_NOZORDER | SWP_NOACTIVATE | SWP_FRAMECHANGED) else: @@ -664,7 +668,7 @@ cdef class PyBrowser: if not for_metro: (left, top, right, bottom) = self.windowRect # noinspection PyUnresolvedReferences - SetWindowPos(hwnd, NULL, + SetWindowPos(hwnd, nullptr, int(left), int(top), int(right-left), int(bottom-top), SWP_NOZORDER | SWP_NOACTIVATE | SWP_FRAMECHANGED) @@ -679,7 +683,7 @@ cdef class PyBrowser: if "type" in pyEvent: cefEvent.type = int(pyEvent["type"]) if "modifiers" in pyEvent: - cefEvent.modifiers = pyEvent["modifiers"] + cefEvent.modifiers = pyEvent["modifiers"] # Always set CefKeyEvent.windows_key_code in SendKeyEvent, even on # Linux. When sending key event for 'backspace' on Linux and setting # "native_key_code", "character", "unmodified_character" it doesn't @@ -728,8 +732,9 @@ cdef class PyBrowser: self.GetCefBrowserHost().get().SendMouseWheelEvent(mouseEvent, deltaX, deltaY) + # for backward compatibility cpdef py_void SendFocusEvent(self, py_bool setFocus): - self.GetCefBrowserHost().get().SendFocusEvent(bool(setFocus)) + self.GetCefBrowserHost().get().SetFocus(setFocus) cpdef py_void SendCaptureLostEvent(self): self.GetCefBrowserHost().get().SendCaptureLostEvent() @@ -738,13 +743,6 @@ cdef class PyBrowser: self.GetCefBrowserHost().get().StartDownload(PyToCefStringValue( url)) - cpdef py_void SetMouseCursorChangeDisabled(self, py_bool disabled): - self.GetCefBrowserHost().get().SetMouseCursorChangeDisabled( - bool(disabled)) - - cpdef py_bool IsMouseCursorChangeDisabled(self): - return self.GetCefBrowserHost().get().IsMouseCursorChangeDisabled() - cpdef py_bool TryCloseBrowser(self): return self.GetCefBrowserHost().get().TryCloseBrowser() @@ -757,35 +755,12 @@ cdef class PyBrowser: cpdef py_void NotifyScreenInfoChanged(self): self.GetCefBrowserHost().get().NotifyScreenInfoChanged() - cdef void SendProcessMessage(self, cef_process_id_t targetProcess, - object frameId, py_string messageName, list pyArguments - ) except *: - cdef CefRefPtr[CefProcessMessage] message = \ - CefProcessMessage_Create(PyToCefStringValue(messageName)) - # This does not work, no idea why, the CEF implementation - # seems not to allow it, both Assign() and swap() do not work: - # | message.get().GetArgumentList().Assign(arguments.get()) - # | message.get().GetArgumentList().swap(arguments) - cdef CefRefPtr[CefListValue] messageArguments = \ - message.get().GetArgumentList() - PyListToExistingCefListValue(self.GetIdentifier(), frameId, - pyArguments, messageArguments) - Debug("SendProcessMessage(): message=%s, arguments size=%d" % ( - messageName, - message.get().GetArgumentList().get().GetSize())) - cdef cpp_bool success = \ - self.GetCefBrowser().get().SendProcessMessage( - targetProcess, message) - if not success: - raise Exception("Browser.SendProcessMessage() failed: "\ - "messageName=%s" % messageName) - # ------------------------------------------------------------------------- # OSR drag & drop # ------------------------------------------------------------------------- cpdef py_void DragTargetDragEnter(self, DragData drag_data, int x, int y, - uint32 allowed_ops): + uint32_t allowed_ops): cdef CefMouseEvent mouse_event mouse_event.x = x mouse_event.y = y @@ -793,7 +768,7 @@ cdef class PyBrowser: drag_data.cef_drag_data, mouse_event, allowed_ops) - cpdef py_void DragTargetDragOver(self, int x, int y, uint32 allowed_ops): + cpdef py_void DragTargetDragOver(self, int x, int y, uint32_t allowed_ops): cdef CefMouseEvent mouse_event mouse_event.x = x mouse_event.y = y @@ -809,7 +784,7 @@ cdef class PyBrowser: mouse_event.y = y self.GetCefBrowserHost().get().DragTargetDrop(mouse_event) - cpdef py_void DragSourceEndedAt(self, int x, int y, uint32 operation): + cpdef py_void DragSourceEndedAt(self, int x, int y, uint32_t operation): self.GetCefBrowserHost().get().DragSourceEndedAt( x, y, operation) diff --git a/src/cefpython.pyx b/src/cefpython.pyx index c3b1e1a13..27502f973 100644 --- a/src/cefpython.pyx +++ b/src/cefpython.pyx @@ -193,6 +193,8 @@ from libcpp.string cimport string as cpp_string # noinspection PyUnresolvedReferences from wstring cimport wstring as cpp_wstring # noinspection PyUnresolvedReferences +from libcpp.memory cimport unique_ptr +# noinspection PyUnresolvedReferences from libc.string cimport strlen # noinspection PyUnresolvedReferences from libc.string cimport memcpy @@ -250,16 +252,12 @@ from cef_types cimport ( CefSettings, CefBrowserSettings, CefRect, CefSize, CefPoint, CefKeyEvent, CefMouseEvent, CefScreenInfo, PathKey, PK_DIR_EXE, PK_DIR_MODULE, - int32, uint32, int64, uint64, cef_log_severity_t, ) # noinspection PyUnresolvedReferences from cef_ptr cimport CefRefPtr -# noinspection PyUnresolvedReferences -from cef_scoped_ptr cimport scoped_ptr - from cef_task cimport * from cef_platform cimport * from cef_app cimport * @@ -273,7 +271,6 @@ from cef_time cimport * from cef_values cimport * from cefpython_app cimport * from cef_process_message cimport * -from cef_web_plugin cimport * from cef_request_handler cimport * from cef_request cimport * from cef_cookie cimport * @@ -321,7 +318,7 @@ g_browser_settings = {} # noinspection PyUnresolvedReferences cdef CefRefPtr[CefRequestContext] g_shared_request_context -cdef scoped_ptr[MainMessageLoopExternalPump] g_external_message_pump +cdef unique_ptr[MainMessageLoopExternalPump] g_external_message_pump cdef py_bool g_MessageLoop_called = False cdef py_bool g_MessageLoopWork_called = False @@ -358,7 +355,6 @@ include "window_info.pyx" include "process_message_utils.pyx" include "javascript_callback.pyx" include "python_callback.pyx" -include "web_plugin_info.pyx" include "request.pyx" include "cookie.pyx" include "string_visitor.pyx" @@ -376,6 +372,7 @@ include "image.pyx" # Handlers include "handlers/accessibility_handler.pyx" include "handlers/browser_process_handler.pyx" +include "handlers/cookie_access_filter.pyx" include "handlers/display_handler.pyx" include "handlers/focus_handler.pyx" include "handlers/javascript_dialog_handler.pyx" @@ -581,8 +578,6 @@ def Initialize(applicationSettings=None, commandLineSwitches=None, **kwargs): # ------------------------------------------------------------------------ if not "multi_threaded_message_loop" in application_settings: application_settings["multi_threaded_message_loop"] = False - if not "single_process" in application_settings: - application_settings["single_process"] = False # ------------------------------------------------------------------------ # ------------------------------------------------------------------------ @@ -593,7 +588,6 @@ def Initialize(applicationSettings=None, commandLineSwitches=None, **kwargs): if not application_settings["cache_path"]: g_commandLineSwitches["disable-gpu-shader-disk-cache"] = "" - cdef CefRefPtr[CefApp] cefApp = new CefPythonApp() IF UNAME_SYSNAME == "Windows": @@ -625,10 +619,10 @@ def Initialize(applicationSettings=None, commandLineSwitches=None, **kwargs): if GetAppSetting("external_message_pump")\ and not g_external_message_pump.get(): Debug("Create external message pump") + global g_external_message_pump # Using .reset() here to assign new instance was causing # MainMessageLoopExternalPump destructor to be called. Strange. - g_external_message_pump.Assign( - MainMessageLoopExternalPump.Create()) + g_external_message_pump = MainMessageLoopExternalPump.Create() Debug("CefInitialize()") cdef cpp_bool ret @@ -761,14 +755,16 @@ def CreateBrowserSync(windowInfo=None, else: cefRequestContext.Assign(g_shared_request_context.get()) + cdef CefRefPtr[CefDictionaryValue] extra_info + # CEF browser creation. with nogil: cefBrowser = cef_browser_static.CreateBrowserSync( cefWindowInfo, clientHandler, - cefNavigateUrl, cefBrowserSettings, + cefNavigateUrl, cefBrowserSettings, extra_info, cefRequestContext) - if cefBrowser == NULL or not cefBrowser.get(): + if not cefBrowser or not cefBrowser.get(): Debug("CefBrowser::CreateBrowserSync() failed") return None else: @@ -971,7 +967,7 @@ cpdef py_void SetGlobalClientCallback(py_string name, object callback): # Accept both with and without a prefix. if name.startswith("_"): name = name[1:] - if name in ["OnCertificateError", "OnBeforePluginLoad", "OnAfterCreated", + if name in ["OnCertificateError", "OnAfterCreated", "OnAccessibilityTreeChange", "OnAccessibilityLocationChange"]: g_globalClientCallbacks[name] = callback else: diff --git a/src/cefpython3.wx/chromectrl.py b/src/cefpython3.wx/chromectrl.py index cf06f82a2..0c0129d31 100644 --- a/src/cefpython3.wx/chromectrl.py +++ b/src/cefpython3.wx/chromectrl.py @@ -160,9 +160,6 @@ def __init__(self, parent, url="", useTimer=True, if not browserSettings: browserSettings = {} - # Disable plugins: - # | browserSettings["plugins_disabled"] = True - self.browser = cefpython.CreateBrowserSync(windowInfo, browserSettings=browserSettings, navigateUrl=url) diff --git a/src/client_handler/Makefile b/src/client_handler/Makefile index 25e645ff7..84472c744 100644 --- a/src/client_handler/Makefile +++ b/src/client_handler/Makefile @@ -23,7 +23,7 @@ SRC = client_handler.cpp cookie_visitor.cpp resource_handler.cpp \ download_handler.cpp focus_handler.cpp js_dialog_handler.cpp \ keyboard_handler.cpp lifespan_handler.cpp load_handler.cpp \ render_handler.cpp request_handler.cpp dialog_handler.cpp \ - cef_log.cpp accessibility_handler.cpp \ + cef_log.cpp accessibility_handler.cpp cookie_access_filter.cpp \ $(SRC_MORE) OBJ = $(filter %.o, $(SRC:.cpp=.o) $(SRC:.mm=.o)) diff --git a/src/client_handler/client_handler.cpp b/src/client_handler/client_handler.cpp index daf9a4e59..02190eaa1 100644 --- a/src/client_handler/client_handler.cpp +++ b/src/client_handler/client_handler.cpp @@ -27,6 +27,7 @@ bool ClientHandler::OnProcessMessageReceived( CefRefPtr browser, + CefRefPtr frame, CefProcessId source_process, CefRefPtr message) { @@ -34,16 +35,14 @@ bool ClientHandler::OnProcessMessageReceived( if (source_process != PID_RENDERER) { return false; } - std::string messageName = message->GetName().ToString(); + const std::string& messageName = message->GetName(); std::string logMessage = "[Browser process] OnProcessMessageReceived(): "; logMessage.append(messageName.c_str()); LOG(INFO) << logMessage.c_str(); if (messageName == "OnContextCreated") { CefRefPtr arguments = message->GetArgumentList(); - if (arguments->GetSize() == 1 && arguments->GetType(0) == VTYPE_INT) { - int64 frameId = arguments->GetInt(0); - CefRefPtr frame = browser->GetFrame(frameId); - if (!frame.get()) { + if (arguments->GetSize() == 1 && arguments->GetType(0) == VTYPE_STRING) { + if (!frame.get()) { // Frame was already destroyed while IPC messaging was // executing. Issue #431. User callback will not be // executed in such case. @@ -60,9 +59,9 @@ bool ClientHandler::OnProcessMessageReceived( CefRefPtr arguments = message->GetArgumentList(); if (arguments->GetSize() == 2 \ && arguments->GetType(0) == VTYPE_INT \ - && arguments->GetType(1) == VTYPE_INT) { + && arguments->GetType(1) == VTYPE_STRING) { int browserId = arguments->GetInt(0); - int64 frameId = arguments->GetInt(1); + CefString frameId = arguments->GetString(1); // Even if frame was alrady destroyed (Issue #431) you still // want to call V8ContextHandler_OnContextReleased as it releases // some resources. Thus passing IDs instead of actual @@ -79,12 +78,12 @@ bool ClientHandler::OnProcessMessageReceived( CefRefPtr arguments = message->GetArgumentList(); if (arguments->GetSize() == 3 // frameId - && arguments->GetType(0) == VTYPE_INT + && arguments->GetType(0) == VTYPE_STRING // functionName && arguments->GetType(1) == VTYPE_STRING // functionArguments && arguments->GetType(2) == VTYPE_LIST) { - int64 frameId = arguments->GetInt(0); + CefString frameId = arguments->GetString(0); CefString functionName = arguments->GetString(1); CefRefPtr functionArguments = arguments->GetList(2); // Even if frame was already destroyed (Issue #431) you still diff --git a/src/client_handler/client_handler.h b/src/client_handler/client_handler.h index 3e9e3917b..e52d0b50c 100644 --- a/src/client_handler/client_handler.h +++ b/src/client_handler/client_handler.h @@ -87,6 +87,7 @@ class ClientHandler : public CefClient, } bool OnProcessMessageReceived(CefRefPtr browser, + CefRefPtr frame, CefProcessId source_process, CefRefPtr message ) override; diff --git a/src/client_handler/cookie_access_filter.cpp b/src/client_handler/cookie_access_filter.cpp new file mode 100644 index 000000000..6eaeb70bf --- /dev/null +++ b/src/client_handler/cookie_access_filter.cpp @@ -0,0 +1,24 @@ +// Copyright (c) 2018 CEF Python, see the Authors file. +// All rights reserved. Licensed under BSD 3-clause license. +// Project website: https://github.com/cztomczak/cefpython + +#include "cookie_access_filter.h" +#include "common/cefpython_public_api.h" + + +bool CookieAccessFilter::CanSendCookie(CefRefPtr browser, + CefRefPtr frame, + CefRefPtr request, + const CefCookie& cookie) { + REQUIRE_IO_THREAD(); + return CookieAccessFilter_CanSendCookie(browser, frame, request, cookie); +} + +bool CookieAccessFilter::CanSaveCookie(CefRefPtr browser, + CefRefPtr frame, + CefRefPtr request, + CefRefPtr response, + const CefCookie& cookie) { + REQUIRE_IO_THREAD(); + return CookieAccessFilter_CanSaveCookie(browser, frame, request, response, cookie); +} diff --git a/src/client_handler/cookie_access_filter.h b/src/client_handler/cookie_access_filter.h new file mode 100644 index 000000000..4d0c57c9c --- /dev/null +++ b/src/client_handler/cookie_access_filter.h @@ -0,0 +1,27 @@ +// Copyright (c) 2018 CEF Python, see the Authors file. +// All rights reserved. Licensed under BSD 3-clause license. +// Project website: https://github.com/cztomczak/cefpython + +#include "common/cefpython_public_api.h" +#include "include/cef_resource_request_handler.h" + + +class CookieAccessFilter : public CefCookieAccessFilter +{ +public: + CookieAccessFilter(){} + virtual ~CookieAccessFilter(){} + + virtual bool CanSendCookie(CefRefPtr browser, + CefRefPtr frame, + CefRefPtr request, + const CefCookie& cookie) override; + virtual bool CanSaveCookie(CefRefPtr browser, + CefRefPtr frame, + CefRefPtr request, + CefRefPtr response, + const CefCookie& cookie) override; + +private: + IMPLEMENT_REFCOUNTING(CookieAccessFilter); +}; diff --git a/src/client_handler/cookie_visitor.h b/src/client_handler/cookie_visitor.h index 54c2b53fd..0b990baca 100644 --- a/src/client_handler/cookie_visitor.h +++ b/src/client_handler/cookie_visitor.h @@ -24,7 +24,7 @@ class CookieVisitor : public CefCookieVisitor int count, int total, bool& deleteCookie - ) OVERRIDE; + ) override; protected: IMPLEMENT_REFCOUNTING(CookieVisitor); diff --git a/src/client_handler/dialog_handler.cpp b/src/client_handler/dialog_handler.cpp index ab90de9b6..6946e4f65 100644 --- a/src/client_handler/dialog_handler.cpp +++ b/src/client_handler/dialog_handler.cpp @@ -19,7 +19,6 @@ bool DialogHandler::OnFileDialog(CefRefPtr browser, const CefString& title, const CefString& default_file_path, const std::vector& accept_filters, - int selected_accept_filter, CefRefPtr callback) { #if defined(OS_LINUX) @@ -28,7 +27,6 @@ bool DialogHandler::OnFileDialog(CefRefPtr browser, title, default_file_path, accept_filters, - selected_accept_filter, callback); #else return false; diff --git a/src/client_handler/dialog_handler.h b/src/client_handler/dialog_handler.h index 21d79a60d..2cea565f6 100644 --- a/src/client_handler/dialog_handler.h +++ b/src/client_handler/dialog_handler.h @@ -23,7 +23,6 @@ class DialogHandler : public CefDialogHandler const CefString& title, const CefString& default_file_path, const std::vector& accept_filters, - int selected_accept_filter, CefRefPtr callback) override; diff --git a/src/client_handler/display_handler.cpp b/src/client_handler/display_handler.cpp index b00bf6a51..573549e26 100644 --- a/src/client_handler/display_handler.cpp +++ b/src/client_handler/display_handler.cpp @@ -59,4 +59,13 @@ void DisplayHandler::OnLoadingProgressChange(CefRefPtr browser, double progress) { REQUIRE_UI_THREAD(); return DisplayHandler_OnLoadingProgressChange(browser, progress); +} + +bool DisplayHandler::OnCursorChange(CefRefPtr browser, + CefCursorHandle cursor, + cef_cursor_type_t type, + const CefCursorInfo& custom_cursor_info) +{ + REQUIRE_UI_THREAD(); + return DisplayHandler_OnCursorChange(browser, cursor); } \ No newline at end of file diff --git a/src/client_handler/display_handler.h b/src/client_handler/display_handler.h index a281713d9..382bceeaa 100644 --- a/src/client_handler/display_handler.h +++ b/src/client_handler/display_handler.h @@ -38,6 +38,12 @@ class DisplayHandler : public CefDisplayHandler void OnLoadingProgressChange(CefRefPtr browser, double progress) override; + + bool OnCursorChange(CefRefPtr browser, + CefCursorHandle cursor, + cef_cursor_type_t type, + const CefCursorInfo& custom_cursor_info + ) override; private: IMPLEMENT_REFCOUNTING(DisplayHandler); diff --git a/src/client_handler/dpi_aware.cpp b/src/client_handler/dpi_aware.cpp index 48e2a13f7..9ee258d65 100644 --- a/src/client_handler/dpi_aware.cpp +++ b/src/client_handler/dpi_aware.cpp @@ -11,6 +11,7 @@ #include "include/wrapper/cef_closure_task.h" #include "include/base/cef_bind.h" #include "include/base/cef_logging.h" +#include "include/base/cef_callback.h" const int DEFAULT_DPIX = 96; @@ -219,7 +220,7 @@ void SetBrowserDpiSettings(CefRefPtr cefBrowser, CefPostDelayedTask( TID_UI, CefCreateClosureTask( - base::Bind(&SetBrowserDpiSettings, + base::BindOnce(&SetBrowserDpiSettings, cefBrowser, autoZooming) ), 50 diff --git a/src/client_handler/lifespan_handler.cpp b/src/client_handler/lifespan_handler.cpp index b4d7d52f6..d9d6010d6 100644 --- a/src/client_handler/lifespan_handler.cpp +++ b/src/client_handler/lifespan_handler.cpp @@ -19,6 +19,7 @@ bool LifespanHandler::OnBeforePopup(CefRefPtr browser, CefWindowInfo& windowInfo, CefRefPtr& client, CefBrowserSettings& settings, + CefRefPtr& extra_info, bool* no_javascript_access) { REQUIRE_UI_THREAD(); @@ -27,7 +28,7 @@ bool LifespanHandler::OnBeforePopup(CefRefPtr browser, return LifespanHandler_OnBeforePopup(browser, frame, target_url, target_frame_name, target_disposition, user_gesture, popupFeaturesNotImpl, windowInfo, client, settings, - no_javascript_access); + extra_info, no_javascript_access); } diff --git a/src/client_handler/lifespan_handler.h b/src/client_handler/lifespan_handler.h index 91244eff9..6b38d7dda 100644 --- a/src/client_handler/lifespan_handler.h +++ b/src/client_handler/lifespan_handler.h @@ -24,6 +24,7 @@ class LifespanHandler : public CefLifeSpanHandler CefWindowInfo& windowInfo, CefRefPtr& client, CefBrowserSettings& settings, + CefRefPtr& extra_info, bool* no_javascript_access) override; void OnAfterCreated(CefRefPtr browser) override; bool DoClose(CefRefPtr browser) override; diff --git a/src/client_handler/render_handler.cpp b/src/client_handler/render_handler.cpp index cf45d15ee..1935a3baf 100644 --- a/src/client_handler/render_handler.cpp +++ b/src/client_handler/render_handler.cpp @@ -13,11 +13,11 @@ bool RenderHandler::GetRootScreenRect(CefRefPtr browser, } -bool RenderHandler::GetViewRect(CefRefPtr browser, +void RenderHandler::GetViewRect(CefRefPtr browser, CefRect& rect) { REQUIRE_UI_THREAD(); - return RenderHandler_GetViewRect(browser, rect); + RenderHandler_GetViewRect(browser, rect); } @@ -69,16 +69,6 @@ void RenderHandler::OnPaint(CefRefPtr browser, } -void RenderHandler::OnCursorChange(CefRefPtr browser, - CefCursorHandle cursor, - CursorType type, - const CefCursorInfo& custom_cursor_info) -{ - REQUIRE_UI_THREAD(); - RenderHandler_OnCursorChange(browser, cursor); -} - - void RenderHandler::OnScrollOffsetChanged(CefRefPtr browser, double x, double y) diff --git a/src/client_handler/render_handler.h b/src/client_handler/render_handler.h index 75eee86c5..c87c52354 100644 --- a/src/client_handler/render_handler.h +++ b/src/client_handler/render_handler.h @@ -22,7 +22,7 @@ class RenderHandler : public CefRenderHandler, bool GetRootScreenRect(CefRefPtr browser, CefRect& rect) override; - bool GetViewRect(CefRefPtr browser, + void GetViewRect(CefRefPtr browser, CefRect& rect) override; bool GetScreenPoint(CefRefPtr browser, @@ -46,12 +46,6 @@ class RenderHandler : public CefRenderHandler, const void* buffer, int width, int height) override; - void OnCursorChange(CefRefPtr browser, - CefCursorHandle cursor, - CursorType type, - const CefCursorInfo& custom_cursor_info - ) override; - void OnScrollOffsetChanged(CefRefPtr browser, double x, double y) override; diff --git a/src/client_handler/request_context_handler.cpp b/src/client_handler/request_context_handler.cpp deleted file mode 100644 index bf816cf51..000000000 --- a/src/client_handler/request_context_handler.cpp +++ /dev/null @@ -1,39 +0,0 @@ -// Copyright (c) 2013 CEF Python, see the Authors file. -// All rights reserved. Licensed under BSD 3-clause license. -// Project website: https://github.com/cztomczak/cefpython - -#include "request_context_handler.h" -#include "common/cefpython_public_api.h" - -// -------------------------------------------------------------------------- -// CefRequestContextHandler -// -------------------------------------------------------------------------- - -CefRefPtr RequestContextHandler::GetCookieManager() { - REQUIRE_IO_THREAD(); - if (browser_.get()) { - return RequestHandler_GetCookieManager(browser_, - browser_->GetMainFrame()->GetURL()); - } else { - CefString mainUrl; - return RequestHandler_GetCookieManager(browser_, mainUrl); - } - // Default: return NULL. -} - -bool RequestContextHandler::OnBeforePluginLoad( - const CefString& mime_type, - const CefString& plugin_url, - bool is_main_frame, - const CefString& top_origin_url, - CefRefPtr plugin_info, - PluginPolicy* plugin_policy) { - // Called on multiple threads - return RequestHandler_OnBeforePluginLoad(browser_, - mime_type, - plugin_url, - is_main_frame, - top_origin_url, - plugin_info, - plugin_policy); -} diff --git a/src/client_handler/request_context_handler.h b/src/client_handler/request_context_handler.h index b8bf25f3a..6c4e3218d 100644 --- a/src/client_handler/request_context_handler.h +++ b/src/client_handler/request_context_handler.h @@ -10,12 +10,14 @@ #include "common/cefpython_public_api.h" +#include "include/cef_request_context_handler.h" +#include "include/base/cef_callback.h" + class RequestContextHandler : public CefRequestContextHandler { private: CefRefPtr browser_; - typedef cef_plugin_policy_t PluginPolicy; public: // Browser may be NULL when instantiated from cefpython.CreateBrowserSync. @@ -29,14 +31,6 @@ class RequestContextHandler : browser_ = browser; } - virtual CefRefPtr GetCookieManager() OVERRIDE; - virtual bool OnBeforePluginLoad(const CefString& mime_type, - const CefString& plugin_url, - bool is_main_frame, - const CefString& top_origin_url, - CefRefPtr plugin_info, - PluginPolicy* plugin_policy) OVERRIDE; - private: IMPLEMENT_REFCOUNTING(RequestContextHandler); }; diff --git a/src/client_handler/request_handler.cpp b/src/client_handler/request_handler.cpp index 5227b8921..a070a9b72 100644 --- a/src/client_handler/request_handler.cpp +++ b/src/client_handler/request_handler.cpp @@ -4,6 +4,7 @@ #include "request_handler.h" #include "include/base/cef_logging.h" +#include "include/base/cef_callback.h" bool RequestHandler::OnBeforeBrowse(CefRefPtr browser, @@ -22,7 +23,7 @@ ReturnValue RequestHandler::OnBeforeResourceLoad( CefRefPtr browser, CefRefPtr frame, CefRefPtr request, - CefRefPtr callback) + CefRefPtr callback) { REQUIRE_IO_THREAD(); bool retval = RequestHandler_OnBeforeResourceLoad(browser, frame, request); @@ -73,8 +74,8 @@ bool RequestHandler::GetAuthCredentials(CefRefPtr browser, bool RequestHandler::OnQuotaRequest(CefRefPtr browser, const CefString& origin_url, - int64 new_size, - CefRefPtr callback) { + int64_t new_size, + CefRefPtr callback) { REQUIRE_IO_THREAD(); return RequestHandler_OnQuotaRequest(browser, origin_url, new_size, callback); @@ -94,7 +95,7 @@ bool RequestHandler::OnCertificateError( cef_errorcode_t cert_error, const CefString& request_url, CefRefPtr ssl_info, // not used - CefRefPtr callback) + CefRefPtr callback) { REQUIRE_UI_THREAD(); return RequestHandler_OnCertificateError(cert_error, request_url, @@ -109,26 +110,3 @@ void RequestHandler::OnRenderProcessTerminated(CefRefPtr browser, LOG(ERROR) << "[Browser process] OnRenderProcessTerminated()"; RequestHandler_OnRendererProcessTerminated(browser, status); } - - -void RequestHandler::OnPluginCrashed(CefRefPtr browser, - const CefString& plugin_path) -{ - REQUIRE_UI_THREAD(); - RequestHandler_OnPluginCrashed(browser, plugin_path); -} - -bool RequestHandler::CanGetCookies(CefRefPtr browser, - CefRefPtr frame, - CefRefPtr request) { - REQUIRE_IO_THREAD(); - return RequestHandler_CanGetCookies(browser, frame, request); -} - -bool RequestHandler::CanSetCookie(CefRefPtr browser, - CefRefPtr frame, - CefRefPtr request, - const CefCookie& cookie) { - REQUIRE_IO_THREAD(); - return RequestHandler_CanSetCookie(browser, frame, request, cookie); -} diff --git a/src/client_handler/request_handler.h b/src/client_handler/request_handler.h index 7e5e0e6c3..6ce8cde66 100644 --- a/src/client_handler/request_handler.h +++ b/src/client_handler/request_handler.h @@ -4,11 +4,14 @@ #include "common/cefpython_public_api.h" #include "include/cef_request_handler.h" +#include "include/base/cef_callback.h" +#include "cookie_access_filter.h" typedef cef_return_value_t ReturnValue; -class RequestHandler : public CefRequestHandler +class RequestHandler : public CefRequestHandler, + public CookieAccessFilter { public: RequestHandler(){} @@ -23,19 +26,19 @@ class RequestHandler : public CefRequestHandler ReturnValue OnBeforeResourceLoad(CefRefPtr browser, CefRefPtr frame, CefRefPtr request, - CefRefPtr callback - ) override; + CefRefPtr callback + ) ; CefRefPtr GetResourceHandler( CefRefPtr browser, CefRefPtr frame, - CefRefPtr request) override; + CefRefPtr request) ; void OnResourceRedirect(CefRefPtr browser, CefRefPtr frame, CefRefPtr request, CefRefPtr response, - CefString& new_url) override; + CefString& new_url) ; bool GetAuthCredentials(CefRefPtr browser, CefRefPtr frame, @@ -44,38 +47,26 @@ class RequestHandler : public CefRequestHandler int port, const CefString& realm, const CefString& scheme, - CefRefPtr callback) override; + CefRefPtr callback) ; bool OnQuotaRequest(CefRefPtr browser, const CefString& origin_url, - int64 new_size, - CefRefPtr callback) override; + int64_t new_size, + CefRefPtr callback) ; void OnProtocolExecution(CefRefPtr browser, const CefString& url, - bool& allow_os_execution) override; + bool& allow_os_execution) ; bool OnCertificateError(CefRefPtr browser, cef_errorcode_t cert_error, const CefString& request_url, CefRefPtr ssl_info, - CefRefPtr callback) override; + CefRefPtr callback) override; void OnRenderProcessTerminated(CefRefPtr browser, cef_termination_status_t status) override; - void OnPluginCrashed(CefRefPtr browser, - const CefString& plugin_path) override; - - bool CanGetCookies(CefRefPtr browser, - CefRefPtr frame, - CefRefPtr request) override; - - bool CanSetCookie(CefRefPtr browser, - CefRefPtr frame, - CefRefPtr request, - const CefCookie& cookie) override; - private: IMPLEMENT_REFCOUNTING(RequestHandler); }; diff --git a/src/client_handler/resource_handler.cpp b/src/client_handler/resource_handler.cpp index 963575928..08d2565a0 100644 --- a/src/client_handler/resource_handler.cpp +++ b/src/client_handler/resource_handler.cpp @@ -12,7 +12,7 @@ bool ResourceHandler::ProcessRequest(CefRefPtr request, } void ResourceHandler::GetResponseHeaders(CefRefPtr response, - int64& response_length, + int64_t& response_length, CefString& redirectUrl) { REQUIRE_IO_THREAD(); ResourceHandler_GetResponseHeaders(resourceHandlerId_, response, @@ -28,16 +28,6 @@ bool ResourceHandler::ReadResponse(void* data_out, bytes_to_read, bytes_read, callback); } -bool ResourceHandler::CanGetCookie(const CefCookie& cookie) { - REQUIRE_IO_THREAD(); - return ResourceHandler_CanGetCookie(resourceHandlerId_, cookie); -} - -bool ResourceHandler::CanSetCookie(const CefCookie& cookie) { - REQUIRE_IO_THREAD(); - return ResourceHandler_CanSetCookie(resourceHandlerId_, cookie); -} - void ResourceHandler::Cancel() { REQUIRE_IO_THREAD(); return ResourceHandler_Cancel(resourceHandlerId_); diff --git a/src/client_handler/resource_handler.h b/src/client_handler/resource_handler.h index 3bf5e41f6..fc81264ad 100644 --- a/src/client_handler/resource_handler.h +++ b/src/client_handler/resource_handler.h @@ -23,7 +23,7 @@ class ResourceHandler : public CefResourceHandler CefRefPtr callback) override; virtual void GetResponseHeaders(CefRefPtr response, - int64& response_length, + int64_t& response_length, CefString& redirectUrl) override; virtual bool ReadResponse(void* data_out, @@ -31,11 +31,7 @@ class ResourceHandler : public CefResourceHandler int& bytes_read, CefRefPtr callback) override; - virtual bool CanGetCookie(const CefCookie& cookie) override; - - virtual bool CanSetCookie(const CefCookie& cookie) override; - - virtual void Cancel() OVERRIDE; + virtual void Cancel() override; private: IMPLEMENT_REFCOUNTING(ResourceHandler); diff --git a/src/client_handler/string_visitor.h b/src/client_handler/string_visitor.h index 3765442c5..c36cf40f6 100644 --- a/src/client_handler/string_visitor.h +++ b/src/client_handler/string_visitor.h @@ -21,7 +21,7 @@ class StringVisitor : public CefStringVisitor virtual void Visit( const CefString& string - ) OVERRIDE; + ) override; protected: IMPLEMENT_REFCOUNTING(StringVisitor); diff --git a/src/client_handler/task.cpp b/src/client_handler/task.cpp index ec032a2d6..62a9fcbff 100644 --- a/src/client_handler/task.cpp +++ b/src/client_handler/task.cpp @@ -5,21 +5,22 @@ #include "task.h" #include "include/wrapper/cef_closure_task.h" #include "include/base/cef_bind.h" +#include "include/base/cef_callback.h" void PostTaskWrapper(int threadId, int taskId) { CefPostTask( static_cast(threadId), - CefCreateClosureTask(base::Bind( + CefCreateClosureTask(base::BindOnce( &PyTaskRunnable, taskId )) ); } -void PostDelayedTaskWrapper(int threadId, int64 delay_ms, int taskId) { +void PostDelayedTaskWrapper(int threadId, int64_t delay_ms, int taskId) { CefPostDelayedTask( static_cast(threadId), - CefCreateClosureTask(base::Bind( + CefCreateClosureTask(base::BindOnce( &PyTaskRunnable, taskId )), @@ -33,7 +34,7 @@ CefRefPtr CreateTask_SetCookie( const CefCookie& cookie, CefRefPtr callback) { - return CefCreateClosureTask(base::Bind( + return CefCreateClosureTask(base::BindOnce( base::IgnoreResult(&CefCookieManager::SetCookie), obj, url, cookie, @@ -47,7 +48,7 @@ CefRefPtr CreateTask_DeleteCookies( const CefString& cookie_name, CefRefPtr callback) { - return CefCreateClosureTask(base::Bind( + return CefCreateClosureTask(base::BindOnce( base::IgnoreResult(&CefCookieManager::DeleteCookies), obj, url, cookie_name, diff --git a/src/client_handler/task.h b/src/client_handler/task.h index 1839d9e32..a7d8c5b38 100644 --- a/src/client_handler/task.h +++ b/src/client_handler/task.h @@ -9,7 +9,7 @@ #include "include/cef_task.h" void PostTaskWrapper(int threadId, int taskId); -void PostDelayedTaskWrapper(int threadId, int64 delay_ms, int taskId); +void PostDelayedTaskWrapper(int threadId, int64_t delay_ms, int taskId); CefRefPtr CreateTask_SetCookie( CefCookieManager* obj, diff --git a/src/client_handler/web_request_client.cpp b/src/client_handler/web_request_client.cpp index 965de919b..509a72eda 100644 --- a/src/client_handler/web_request_client.cpp +++ b/src/client_handler/web_request_client.cpp @@ -9,14 +9,14 @@ void WebRequestClient::OnRequestComplete(CefRefPtr request) { } void WebRequestClient::OnUploadProgress(CefRefPtr request, - int64 current, - int64 total) { + int64_t current, + int64_t total) { WebRequestClient_OnUploadProgress(webRequestId_, request, current, total); } void WebRequestClient::OnDownloadProgress(CefRefPtr request, - int64 current, - int64 total) { + int64_t current, + int64_t total) { WebRequestClient_OnDownloadProgress(webRequestId_, request, current, total); } diff --git a/src/client_handler/web_request_client.h b/src/client_handler/web_request_client.h index 8b815a968..8f5bce96a 100644 --- a/src/client_handler/web_request_client.h +++ b/src/client_handler/web_request_client.h @@ -20,26 +20,26 @@ class WebRequestClient : public CefURLRequestClient } virtual ~WebRequestClient(){} - virtual void OnRequestComplete(CefRefPtr request) OVERRIDE; + virtual void OnRequestComplete(CefRefPtr request) override; virtual void OnUploadProgress(CefRefPtr request, - int64 current, - int64 total) OVERRIDE; + int64_t current, + int64_t total) override; virtual void OnDownloadProgress(CefRefPtr request, - int64 current, - int64 total) OVERRIDE; + int64_t current, + int64_t total) override; virtual void OnDownloadData(CefRefPtr request, const void* data, - size_t data_length) OVERRIDE; + size_t data_length) override; virtual bool GetAuthCredentials(bool isProxy, const CefString& host, int port, const CefString& realm, const CefString& scheme, - CefRefPtr callback) OVERRIDE; + CefRefPtr callback) override; protected: IMPLEMENT_REFCOUNTING(WebRequestClient); diff --git a/src/common/cefpython_public_api.h b/src/common/cefpython_public_api.h index c796388e6..84552489c 100644 --- a/src/common/cefpython_public_api.h +++ b/src/common/cefpython_public_api.h @@ -50,6 +50,10 @@ #include "../../build/build_cefpython/cefpython_py38_fixed.h" #elif PY_MINOR_VERSION == 9 #include "../../build/build_cefpython/cefpython_py39_fixed.h" +#elif PY_MINOR_VERSION == 10 +#include "../../build/build_cefpython/cefpython_py310_fixed.h" +#elif PY_MINOR_VERSION == 11 +#include "../../build/build_cefpython/cefpython_py311_fixed.h" #endif // PY_MINOR_VERSION #endif // PY_MAJOR_VERSION diff --git a/src/cookie.pyx b/src/cookie.pyx index 6d90144b0..d776923ef 100644 --- a/src/cookie.pyx +++ b/src/cookie.pyx @@ -167,16 +167,16 @@ cdef class Cookie: return self.cefCookie.httponly cpdef py_void SetCreation(self, object creation): - DatetimeToCefTimeT(creation, self.cefCookie.creation) + DatetimeToCefBasetimeT(creation, self.cefCookie.creation) cpdef object GetCreation(self): - return CefTimeTToDatetime(self.cefCookie.creation) + return CefBasetimeTToDatetime(self.cefCookie.creation) cpdef py_void SetLastAccess(self, object lastAccess): - DatetimeToCefTimeT(lastAccess, self.cefCookie.last_access) + DatetimeToCefBasetimeT(lastAccess, self.cefCookie.last_access) cpdef object GetLastAccess(self): - return CefTimeTToDatetime(self.cefCookie.last_access) + return CefBasetimeTToDatetime(self.cefCookie.last_access) cpdef py_void SetHasExpires(self, py_bool hasExpires): self.cefCookie.has_expires = bool(hasExpires) @@ -185,10 +185,10 @@ cdef class Cookie: return self.cefCookie.has_expires cpdef py_void SetExpires(self, object expires): - DatetimeToCefTimeT(expires, self.cefCookie.expires) + DatetimeToCefBasetimeT(expires, self.cefCookie.expires) cpdef object GetExpires(self): - return CefTimeTToDatetime(self.cefCookie.expires) + return CefBasetimeTToDatetime(self.cefCookie.expires) # ------------------------------------------------------------------------------ # CookieManager @@ -204,37 +204,10 @@ class CookieManager(object): cdef CefRefPtr[CefCookieManager] cefCookieManager if not g_globalCookieManager: cefCookieManager = CefCookieManager_GetGlobalManager( - NULL) + nullptr) g_globalCookieManager = CreatePyCookieManager(cefCookieManager) return g_globalCookieManager - @classmethod - def GetBlockingManager(cls): - return CreatePyCookieManager(CefCookieManager_GetBlockingManager()) - - @classmethod - def CreateManager(cls, py_string path, - py_bool persist_session_cookies=False): - """ - Create a new cookie manager. - :param path: - :type path: str - :param persist_session_cookies: - :type path: bool - :return: CookieManager object - :rtype: CookieManager - """ - # When PyCharm generates a stub for the cefpython module - # it doesn't use the above docstring for code inspections. - # No idea why. - cdef CefRefPtr[CefCookieManager] cefCookieManager - cefCookieManager = CefCookieManager_CreateManager( - PyToCefStringValue(path), bool(persist_session_cookies), - NULL) - if cefCookieManager != NULL and cefCookieManager.get(): - return CreatePyCookieManager(cefCookieManager) - return None - # ------------------------------------------------------------------------------ # PyCookieManager # ------------------------------------------------------------------------------ @@ -248,13 +221,6 @@ cdef PyCookieManager CreatePyCookieManager( cdef class PyCookieManager: cdef CefRefPtr[CefCookieManager] cefCookieManager - cpdef py_void SetSupportedSchemes(self, list schemes): - cdef cpp_vector[CefString] schemesVector - for scheme in schemes: - schemesVector.push_back(PyToCefStringValue(scheme)) - self.cefCookieManager.get().SetSupportedSchemes(schemesVector, - NULL) - cdef py_void ValidateUserCookieVisitor(self, object userCookieVisitor): if userCookieVisitor and hasattr(userCookieVisitor, "Visit") and ( callable(getattr(userCookieVisitor, "Visit"))): @@ -287,23 +253,17 @@ cdef class PyCookieManager: CefPostTask(TID_IO, CreateTask_SetCookie( self.cefCookieManager.get(), PyToCefStringValue(url), cookie.cefCookie, - NULL)) + nullptr)) cpdef py_void DeleteCookies(self, py_string url, py_string cookie_name): CefPostTask(TID_IO, CreateTask_DeleteCookies( self.cefCookieManager.get(), PyToCefStringValue(url), PyToCefStringValue(cookie_name), - NULL)) - - cpdef py_bool SetStoragePath(self, py_string path, - py_bool persistSessionCookies=False): - return self.cefCookieManager.get().SetStoragePath( - PyToCefStringValue(path), bool(persistSessionCookies), - NULL) + nullptr)) cpdef py_bool FlushStore(self, callback=None): return self.cefCookieManager.get().FlushStore( - NULL) + nullptr) # ------------------------------------------------------------------------------ diff --git a/src/dpi_aware_win.pyx b/src/dpi_aware_win.pyx index a7fc345fa..98e7702c8 100644 --- a/src/dpi_aware_win.pyx +++ b/src/dpi_aware_win.pyx @@ -61,10 +61,5 @@ class DpiAware: @classmethod def SetProcessDpiAware(cls): """Deprecated.""" - DpiAware.EnableHighDpiSupport() + pass - @classmethod - def EnableHighDpiSupport(cls): - # This CEF function sets process to be DPI aware. This - # CEF func is also called in subprocesses. - CefEnableHighDPISupport() diff --git a/src/extern/cef/cef_app.pxd b/src/extern/cef/cef_app.pxd index ef270f1fc..1715c0cfd 100644 --- a/src/extern/cef/cef_app.pxd +++ b/src/extern/cef/cef_app.pxd @@ -23,8 +23,6 @@ cdef extern from "include/cef_app.h": cdef cppclass CefApp: pass - cdef void CefEnableHighDPISupport() nogil - cdef int CefExecuteProcess(CefMainArgs& args, CefRefPtr[CefApp] application, void* windows_sandbox_info diff --git a/src/extern/cef/cef_browser.pxd b/src/extern/cef/cef_browser.pxd index da209d5c3..a34259e5e 100644 --- a/src/extern/cef/cef_browser.pxd +++ b/src/extern/cef/cef_browser.pxd @@ -9,9 +9,10 @@ from cef_string cimport CefString from cef_client cimport CefClient from libcpp cimport bool as cpp_bool from libcpp.vector cimport vector as cpp_vector +from libc.stdint cimport int64_t from cef_frame cimport CefFrame cimport cef_types -from cef_types cimport int64, cef_state_t, CefSize +from cef_types cimport cef_state_t, CefSize from cef_types cimport CefBrowserSettings, CefPoint from cef_drag_data cimport CefDragData from cef_types cimport CefMouseEvent @@ -38,8 +39,6 @@ cdef extern from "include/cef_browser.h": double GetZoomLevel() void SetZoomLevel(double zoomLevel) void StartDownload(const CefString& url) - void SetMouseCursorChangeDisabled(cpp_bool disabled) - cpp_bool IsMouseCursorChangeDisabled() cpp_bool IsWindowRenderingDisabled() void WasResized() void WasHidden(cpp_bool hidden) @@ -54,7 +53,6 @@ cdef extern from "include/cef_browser.h": cpp_bool mouseLeave) void SendMouseWheelEvent(cef_types.CefMouseEvent, int deltaX, int deltaY) - void SendFocusEvent(cpp_bool setFocus) void SendCaptureLostEvent() void ShowDevTools(const CefWindowInfo& windowInfo, @@ -66,7 +64,7 @@ cdef extern from "include/cef_browser.h": CefRefPtr[CefRequestContext] GetRequestContext() - void Find(int identifier, const CefString& searchText, cpp_bool forward, + void Find(const CefString& searchText, cpp_bool forward, cpp_bool matchCase, cpp_bool findNext) void StopFinding(cpp_bool clearSelection) void Print() @@ -100,8 +98,8 @@ cdef extern from "include/cef_browser.h": cpp_bool CanGoBack() cpp_bool CanGoForward() CefRefPtr[CefFrame] GetFocusedFrame() - CefRefPtr[CefFrame] GetFrame(CefString& name) - CefRefPtr[CefFrame] GetFrame(int64 identifier) + CefRefPtr[CefFrame] GetFrameByName(CefString& name) + CefRefPtr[CefFrame] GetFrameByIdentifier(CefString& identifier) void GetFrameNames(cpp_vector[CefString]& names) CefRefPtr[CefFrame] GetMainFrame() void GoBack() @@ -113,5 +111,3 @@ cdef extern from "include/cef_browser.h": void StopLoad() cpp_bool IsLoading() int GetIdentifier() - cpp_bool SendProcessMessage(CefProcessId target_process, - CefRefPtr[CefProcessMessage] message) diff --git a/src/extern/cef/cef_browser_static.pxd b/src/extern/cef/cef_browser_static.pxd index 17b1a283d..fafa76aac 100644 --- a/src/extern/cef/cef_browser_static.pxd +++ b/src/extern/cef/cef_browser_static.pxd @@ -14,6 +14,7 @@ ELIF UNAME_SYSNAME == "Darwin": # noinspection PyUnresolvedReferences from cef_client cimport CefClient from cef_types cimport CefBrowserSettings +from cef_values cimport CefDictionaryValue # noinspection PyUnresolvedReferences from cef_request_context cimport CefRequestContext # noinspection PyUnresolvedReferences @@ -28,4 +29,5 @@ cdef extern from "include/cef_browser.h" namespace "CefBrowserHost": CefRefPtr[CefClient], CefString&, CefBrowserSettings&, + CefRefPtr[CefDictionaryValue], CefRefPtr[CefRequestContext]) nogil diff --git a/src/extern/cef/cef_cookie.pxd b/src/extern/cef/cef_cookie.pxd index c113aea9a..4cc20a238 100644 --- a/src/extern/cef/cef_cookie.pxd +++ b/src/extern/cef/cef_cookie.pxd @@ -10,8 +10,9 @@ from cef_string cimport CefString from cef_ptr cimport CefRefPtr # noinspection PyUnresolvedReferences from cef_callback cimport CefCompletionCallback +from cef_time cimport cef_basetime_t -cdef extern from "include/cef_cookie.h": +cdef extern from "include/internal/cef_types.h": ctypedef struct CefCookie: cef_string_t name cef_string_t value @@ -19,28 +20,18 @@ cdef extern from "include/cef_cookie.h": cef_string_t path cpp_bool secure cpp_bool httponly - cef_time_t creation - cef_time_t last_access + cef_basetime_t creation + cef_basetime_t last_access cpp_bool has_expires - cef_time_t expires + cef_basetime_t expires + +cdef extern from "include/cef_cookie.h": cdef CefRefPtr[CefCookieManager] CefCookieManager_GetGlobalManager \ "CefCookieManager::GetGlobalManager"( CefRefPtr[CefCompletionCallback] callback) - cdef CefRefPtr[CefCookieManager] CefCookieManager_GetBlockingManager \ - "CefCookieManager::GetBlockingManager"() - - - cdef CefRefPtr[CefCookieManager] CefCookieManager_CreateManager \ - "CefCookieManager::CreateManager"( - const CefString& path, - cpp_bool persist_session_cookies, - CefRefPtr[CefCompletionCallback] callback) - cdef cppclass CefCookieManager: - void SetSupportedSchemes(const cpp_vector[CefString]& schemes, - CefRefPtr[CefCompletionCallback] callback) cpp_bool VisitAllCookies(CefRefPtr[CefCookieVisitor] visitor) cpp_bool VisitUrlCookies(const CefString& url, cpp_bool includeHttpOnly, @@ -50,9 +41,6 @@ cdef extern from "include/cef_cookie.h": cpp_bool DeleteCookies(const CefString& url, const CefString& cookie_name, CefRefPtr[CefDeleteCookiesCallback] callback) - cpp_bool SetStoragePath(const CefString& path, - cpp_bool persist_session_cookies, - CefRefPtr[CefCompletionCallback] callback) cpp_bool FlushStore(CefRefPtr[CefCompletionCallback] callback) cdef cppclass CefCookieVisitor: diff --git a/src/extern/cef/cef_frame.pxd b/src/extern/cef/cef_frame.pxd index 28cdceee2..54efdd373 100644 --- a/src/extern/cef/cef_frame.pxd +++ b/src/extern/cef/cef_frame.pxd @@ -4,12 +4,12 @@ include "compile_time_constants.pxi" -from cef_types cimport int64 from cef_string cimport CefString from libcpp cimport bool as cpp_bool from cef_ptr cimport CefRefPtr from cef_browser cimport CefBrowser from cef_string_visitor cimport CefStringVisitor +from cef_process_message cimport CefProcessMessage, CefProcessId cdef extern from "include/cef_frame.h": @@ -17,7 +17,7 @@ cdef extern from "include/cef_frame.h": cpp_bool IsValid() void ExecuteJavaScript(CefString& jsCode, CefString& scriptUrl, int startLine) CefString GetURL() - int64 GetIdentifier() + CefString GetIdentifier() cpp_bool IsMain() void LoadURL(CefString& url) void Undo() @@ -35,3 +35,5 @@ cdef extern from "include/cef_frame.h": CefString GetName() CefRefPtr[CefFrame] GetParent() CefRefPtr[CefBrowser] GetBrowser() + cpp_bool SendProcessMessage(CefProcessId target_process, + CefRefPtr[CefProcessMessage] message) diff --git a/src/extern/cef/cef_ptr.pxd b/src/extern/cef/cef_ptr.pxd index c5d9877cf..31bf22e44 100644 --- a/src/extern/cef/cef_ptr.pxd +++ b/src/extern/cef/cef_ptr.pxd @@ -1,6 +1,7 @@ # Copyright (c) 2012 CEF Python, see the Authors file. # All rights reserved. Licensed under BSD 3-clause license. # Project website: https://github.com/cztomczak/cefpython +from libcpp cimport nullptr_t, bool cdef extern from "include/internal/cef_ptr.h": cdef cppclass CefRefPtr[T]: @@ -14,4 +15,7 @@ cdef extern from "include/internal/cef_ptr.h": # noinspection PyUnresolvedReferences void swap(CefRefPtr[T]& r) # noinspection PyUnresolvedReferences + CefRefPtr[T]& Assign "operator="(nullptr_t) CefRefPtr[T]& Assign "operator="(T* p) + bool operator bool() + bool operator!() diff --git a/src/extern/cef/cef_request.pxd b/src/extern/cef/cef_request.pxd index e7bd336d0..0ec425ae3 100644 --- a/src/extern/cef/cef_request.pxd +++ b/src/extern/cef/cef_request.pxd @@ -53,6 +53,7 @@ cdef extern from "include/cef_request.h": # noinspection PyUnresolvedReferences ctypedef cef_postdataelement_type_t ElementType + @staticmethod cdef CefRefPtr[CefPostDataElement] CefPostDataElement_Create \ "CefPostDataElement::Create"() cdef cppclass CefPostDataElement: diff --git a/src/extern/cef/cef_request_context.pxd b/src/extern/cef/cef_request_context.pxd index 116741749..1107cb6fc 100644 --- a/src/extern/cef/cef_request_context.pxd +++ b/src/extern/cef/cef_request_context.pxd @@ -16,5 +16,5 @@ cdef extern from "include/cef_request_context.h": CefRefPtr[CefRequestContext] CreateContext( CefRefPtr[CefRequestContext] other, CefRefPtr[CefRequestContextHandler] handler) - CefRefPtr[CefCookieManager] GetDefaultCookieManager( + CefRefPtr[CefCookieManager] GetCookieManager( CefRefPtr[CefCompletionCallback] callback) diff --git a/src/extern/cef/cef_request_handler.pxd b/src/extern/cef/cef_request_handler.pxd index 96a7d88c6..a6e320488 100644 --- a/src/extern/cef/cef_request_handler.pxd +++ b/src/extern/cef/cef_request_handler.pxd @@ -11,7 +11,3 @@ cdef extern from "include/cef_auth_callback.h": const CefString& password) void Cancel() -cdef extern from "include/cef_request_handler.h": - cdef cppclass CefRequestCallback: - void Continue(cpp_bool allow) - void Cancel() diff --git a/src/extern/cef/cef_resource_request_handler.pxd b/src/extern/cef/cef_resource_request_handler.pxd new file mode 100644 index 000000000..1087d55bf --- /dev/null +++ b/src/extern/cef/cef_resource_request_handler.pxd @@ -0,0 +1,9 @@ +# Copyright (c) 2013 CEF Python, see the Authors file. +# All rights reserved. Licensed under BSD 3-clause license. +# Project website: https://github.com/cztomczak/cefpython + +cdef extern from "include/cef_resource_request_handler.h": + cdef cppclass CefResourceRequestHandler: + pass + cdef cppclass CefCookieAccessFilter: + pass \ No newline at end of file diff --git a/src/extern/cef/cef_response.pxd b/src/extern/cef/cef_response.pxd index ef6729f12..9c08a0ec1 100644 --- a/src/extern/cef/cef_response.pxd +++ b/src/extern/cef/cef_response.pxd @@ -21,6 +21,6 @@ cdef extern from "include/cef_response.h": void SetStatusText(CefString& statusText) CefString GetMimeType() void SetMimeType(CefString& mimeType) - CefString GetHeader(CefString& name) + CefString GetHeaderByName(CefString& name) void GetHeaderMap(CefResponseHeaderMap& headerMap) void SetHeaderMap(CefResponseHeaderMap& headerMap) diff --git a/src/extern/cef/cef_scoped_ptr.pxd b/src/extern/cef/cef_scoped_ptr.pxd deleted file mode 100644 index 2e770a5b9..000000000 --- a/src/extern/cef/cef_scoped_ptr.pxd +++ /dev/null @@ -1,17 +0,0 @@ -# Copyright (c) 2016 CEF Python, see the Authors file. -# All rights reserved. Licensed under BSD 3-clause license. -# Project website: https://github.com/cztomczak/cefpython - -cdef extern from "include/base/cef_scoped_ptr.h": - cdef cppclass scoped_ptr[T]: - scoped_ptr() - # noinspection PyUnresolvedReferences - scoped_ptr(T* p) - # noinspection PyUnresolvedReferences - void reset() - # noinspection PyUnresolvedReferences - void reset(T* p) - # noinspection PyUnresolvedReferences - T* get() - # noinspection PyUnresolvedReferences - scoped_ptr[T]& Assign "operator="(scoped_ptr[T] p) diff --git a/src/extern/cef/cef_task.pxd b/src/extern/cef/cef_task.pxd index fbc0181e0..c7dfcdf02 100644 --- a/src/extern/cef/cef_task.pxd +++ b/src/extern/cef/cef_task.pxd @@ -3,9 +3,9 @@ # Project website: https://github.com/cztomczak/cefpython from libcpp cimport bool as cpp_bool +from libc.stdint cimport int64_t # noinspection PyUnresolvedReferences cimport cef_types -from cef_types cimport int64 from cef_ptr cimport CefRefPtr cdef extern from "include/cef_task.h": @@ -16,7 +16,7 @@ cdef extern from "include/cef_task.h": CefRefPtr[CefTask] task) cdef cpp_bool CefPostDelayedTask(CefThreadId threadId, CefRefPtr[CefTask] task, - int64 delay_ms) + int64_t delay_ms) cdef cppclass CefTask: pass diff --git a/src/extern/cef/cef_time.pxd b/src/extern/cef/cef_time.pxd index cdbdc639f..55efa42da 100644 --- a/src/extern/cef/cef_time.pxd +++ b/src/extern/cef/cef_time.pxd @@ -3,6 +3,7 @@ # Project website: https://github.com/cztomczak/cefpython from ctime cimport time_t +from libc.stdint cimport int64_t cdef extern from "include/internal/cef_time.h": ctypedef struct cef_time_t: @@ -15,6 +16,9 @@ cdef extern from "include/internal/cef_time.h": int second int millisecond + ctypedef struct cef_basetime_t: + int64_t val + cdef extern from "include/internal/cef_types.h": cdef cppclass CefTime: CefTime() diff --git a/src/extern/cef/cef_types.pxd b/src/extern/cef/cef_types.pxd index 6bd21ba46..d17248b9a 100644 --- a/src/extern/cef/cef_types.pxd +++ b/src/extern/cef/cef_types.pxd @@ -15,26 +15,15 @@ from libc.limits cimport UINT_MAX cdef extern from "include/internal/cef_types.h": - # noinspection PyUnresolvedReferences - ctypedef int32_t int32 - # noinspection PyUnresolvedReferences - ctypedef uint32_t uint32 - # noinspection PyUnresolvedReferences - ctypedef int64_t int64 - # noinspection PyUnresolvedReferences - ctypedef uint64_t uint64 - IF UNAME_SYSNAME == "Windows": # noinspection PyUnresolvedReferences - ctypedef wchar_t char16 + ctypedef wchar_t char16_t ELSE: - ctypedef unsigned short char16 + ctypedef unsigned short char16_t - ctypedef uint32 cef_color_t + ctypedef uint32_t cef_color_t ctypedef struct CefSettings: - cef_string_t accept_language_list - int single_process cef_string_t browser_subprocess_path int command_line_args_disabled cef_string_t cache_path @@ -53,17 +42,14 @@ cdef extern from "include/internal/cef_types.h": int remote_debugging_port int uncaught_exception_stack_size int context_safety_implementation # Not exposed. - int ignore_certificate_errors cef_color_t background_color int persist_user_preferences - cef_string_t user_data_path int windowless_rendering_enabled int no_sandbox int external_message_pump cef_string_t framework_dir_path ctypedef struct CefBrowserSettings: - cef_string_t accept_language_list cef_color_t background_color cef_string_t standard_font_family cef_string_t fixed_font_family @@ -191,12 +177,12 @@ cdef extern from "include/internal/cef_types.h": KEYEVENT_CHAR ctypedef struct _cef_key_event_t: cef_key_event_type_t type - uint32 modifiers + uint32_t modifiers int windows_key_code int native_key_code int is_system_key - char16 character - char16 unmodified_character + char16_t character + char16_t unmodified_character cpp_bool focus_on_editable_field ctypedef _cef_key_event_t CefKeyEvent ctypedef enum cef_event_flags_t: @@ -287,7 +273,7 @@ cdef extern from "include/internal/cef_types.h": ctypedef struct cef_mouse_event_t: int x int y - uint32 modifiers + uint32_t modifiers ctypedef cef_mouse_event_t CefMouseEvent # RenderHandler > GetScreenInfo(): @@ -323,16 +309,18 @@ cdef extern from "include/internal/cef_types.h": # LifespanHandler and RequestHandler ctypedef enum cef_window_open_disposition_t: - WOD_UNKNOWN, - WOD_CURRENT_TAB, - WOD_SINGLETON_TAB, - WOD_NEW_FOREGROUND_TAB, - WOD_NEW_BACKGROUND_TAB, - WOD_NEW_POPUP, - WOD_NEW_WINDOW, - WOD_SAVE_TO_DISK, - WOD_OFF_THE_RECORD, - WOD_IGNORE_ACTION + CEF_WOD_UNKNOWN, + CEF_WOD_CURRENT_TAB, + CEF_WOD_SINGLETON_TAB, + CEF_WOD_NEW_FOREGROUND_TAB, + CEF_WOD_NEW_BACKGROUND_TAB, + CEF_WOD_NEW_POPUP, + CEF_WOD_NEW_WINDOW, + CEF_WOD_SAVE_TO_DISK, + CEF_WOD_OFF_THE_RECORD, + CEF_WOD_IGNORE_ACTION, + CEF_WOD_SWITCH_TO_TAB, + CEF_WOD_NEW_PICTURE_IN_PICTURE ctypedef cef_window_open_disposition_t WindowOpenDisposition ctypedef enum cef_path_key_t: @@ -347,12 +335,6 @@ cdef extern from "include/internal/cef_types.h": PK_DIR_RESOURCES, ctypedef cef_path_key_t PathKey - ctypedef enum cef_plugin_policy_t: - PLUGIN_POLICY_ALLOW, - PLUGIN_POLICY_DETECT_IMPORTANT, - PLUGIN_POLICY_BLOCK, - PLUGIN_POLICY_DISABLE, - # Drag & drop ctypedef enum cef_drag_operations_mask_t: diff --git a/src/extern/cef/cef_values.pxd b/src/extern/cef/cef_values.pxd index 3210432b4..249c2ae53 100644 --- a/src/extern/cef/cef_values.pxd +++ b/src/extern/cef/cef_values.pxd @@ -9,6 +9,7 @@ from libcpp.vector cimport vector from cef_types cimport cef_value_type_t cdef extern from "include/cef_values.h": + @staticmethod cdef CefRefPtr[CefBinaryValue] CefBinaryValue_Create \ "CefBinaryValue::Create"(const void* data, size_t data_size) @@ -31,7 +32,8 @@ cdef extern from "include/cef_values.h": CefRefPtr[CefBinaryValue] Copy() size_t GetSize() size_t GetData(void* buffer_, size_t buffer_size, size_t data_offset) - + + @staticmethod cdef CefRefPtr[CefDictionaryValue] CefDictionaryValue_Create \ "CefDictionaryValue::Create"() diff --git a/src/extern/cef/cef_web_plugin.pxd b/src/extern/cef/cef_web_plugin.pxd deleted file mode 100644 index 25d33fa9d..000000000 --- a/src/extern/cef/cef_web_plugin.pxd +++ /dev/null @@ -1,14 +0,0 @@ -# Copyright (c) 2013 CEF Python, see the Authors file. -# All rights reserved. Licensed under BSD 3-clause license. -# Project website: https://github.com/cztomczak/cefpython - -from cef_string cimport CefString - -# CEF 3 only. - -cdef extern from "include/cef_web_plugin.h": - cdef cppclass CefWebPluginInfo: - CefString GetName() - CefString GetPath() - CefString GetVersion() - CefString GetDescription() diff --git a/src/extern/cef/cef_win.pxd b/src/extern/cef/cef_win.pxd index 5e341b75b..e6844e58c 100644 --- a/src/extern/cef/cef_win.pxd +++ b/src/extern/cef/cef_win.pxd @@ -5,9 +5,10 @@ include "compile_time_constants.pxi" # noinspection PyUnresolvedReferences -from windows cimport HWND, RECT, HINSTANCE, HCURSOR +from windows cimport HWND, HINSTANCE, HCURSOR from cef_string cimport CefString from libcpp cimport bool as cpp_bool +from cef_types cimport CefRect cdef extern from "include/internal/cef_win.h": @@ -18,7 +19,7 @@ cdef extern from "include/internal/cef_win.h": cdef cppclass CefWindowInfo: void SetAsChild(CefWindowHandle parent, - RECT windowRect) + const CefRect windowRect) void SetAsPopup(CefWindowHandle parent, const CefString& windowName) void SetAsWindowless(CefWindowHandle parent) diff --git a/src/extern/main_message_loop.pxd b/src/extern/main_message_loop.pxd index 486f309af..af05e1100 100644 --- a/src/extern/main_message_loop.pxd +++ b/src/extern/main_message_loop.pxd @@ -2,11 +2,11 @@ # All rights reserved. Licensed under BSD 3-clause license. # Project website: https://github.com/cztomczak/cefpython -from cef_scoped_ptr cimport scoped_ptr +from libcpp.memory cimport unique_ptr cdef extern from \ "subprocess/main_message_loop/main_message_loop_external_pump.h": cdef cppclass MainMessageLoopExternalPump: @staticmethod - scoped_ptr[MainMessageLoopExternalPump] Create() + unique_ptr[MainMessageLoopExternalPump] Create() diff --git a/src/extern/task.pxd b/src/extern/task.pxd index 14f2777b4..3c883ad95 100644 --- a/src/extern/task.pxd +++ b/src/extern/task.pxd @@ -11,13 +11,13 @@ from cef_cookie cimport CefCookie, CefCookieManager from cef_cookie cimport CefSetCookieCallback, CefDeleteCookiesCallback # noinspection PyUnresolvedReferences from libcpp cimport bool as cpp_bool -from cef_types cimport int64 +from libc.stdint cimport int64_t cdef extern from "client_handler/task.h": void PostTaskWrapper(int threadId, int taskId) nogil - void PostDelayedTaskWrapper(int threadId, int64 delay_ms, int taskId) nogil + void PostDelayedTaskWrapper(int threadId, int64_t delay_ms, int taskId) nogil cdef CefRefPtr[CefTask] CreateTask_SetCookie( CefCookieManager* obj, diff --git a/src/frame.pyx b/src/frame.pyx index 812e4b3c9..493d30948 100644 --- a/src/frame.pyx +++ b/src/frame.pyx @@ -11,11 +11,11 @@ cdef dict g_pyFrames = {} # it shouldn't be kept global anymore. cdef list g_unreferenced_frames = [] # [str unique identifier, ..] -cdef object GetUniqueFrameId(int browserId, object frameId): - return str(browserId) +"#"+ str(frameId) +cdef str GetUniqueFrameId(int browserId, py_string frameId): + return str(browserId) +"#"+ frameId -cdef PyFrame GetPyFrameById(int browserId, object frameId): - cdef object uniqueFrameId = GetUniqueFrameId(browserId, frameId) +cdef PyFrame GetPyFrameById(int browserId, py_string frameId): + cdef str uniqueFrameId = GetUniqueFrameId(browserId, frameId) if uniqueFrameId in g_pyFrames: return g_pyFrames[uniqueFrameId] return None @@ -23,23 +23,23 @@ cdef PyFrame GetPyFrameById(int browserId, object frameId): cdef PyFrame GetPyFrame(CefRefPtr[CefFrame] cefFrame): global g_pyFrames - if cefFrame == NULL or not cefFrame.get(): + if not cefFrame or not cefFrame.get(): raise Exception("GetPyFrame(): CefFrame reference is NULL") cdef PyFrame pyFrame - cdef object frameId = cefFrame.get().GetIdentifier() # int64 + cdef CefString frameId = cefFrame.get().GetIdentifier() cdef int browserId = cefFrame.get().GetBrowser().get().GetIdentifier() - assert (frameId and browserId), "frameId or browserId empty" - cdef object uniqueFrameId = GetUniqueFrameId(browserId, frameId) + assert (not frameId.empty() and browserId), "frameId or browserId empty" + cdef str uniqueFrameId = GetUniqueFrameId(browserId, CefToPyString(frameId)) - if frameId < 0: + if frameId.empty(): # Underlying frame does not yet exist. In such case PyFrame # is not stored in g_pyFrames since frameId is invalid. # However even though frame is not supposed to exist, you # can still call CefFrame.ExecuteFunction and it works fine # in tutorial.py example. Debug("GetPyFrame(): underlying frame does not yet exist:" - " browserId = {0}, frameId = {1}".format(browserId, frameId)) + " browserId = {0}, frameId = {1}".format(browserId, CefToPyString(frameId))) else: if uniqueFrameId in g_pyFrames: return g_pyFrames[uniqueFrameId] @@ -56,11 +56,11 @@ cdef PyFrame GetPyFrame(CefRefPtr[CefFrame] cefFrame): del g_pyFrames[uFid] # ---- - pyFrame = PyFrame(browserId, frameId) + pyFrame = PyFrame(browserId, CefToPyString(frameId)) pyFrame.cefFrame = cefFrame if uniqueFrameId in g_unreferenced_frames \ - or frameId < 0 \ + or frameId.empty() \ or browserId in g_unreferenced_browsers \ or browserId in g_closed_browsers: # Browser was already globally unreferenced in OnBeforeClose, @@ -77,19 +77,19 @@ cdef PyFrame GetPyFrame(CefRefPtr[CefFrame] cefFrame): # SIDE EFFECT: two calls to GetPyFrame for the same frame object # may return two different PyFrame objects. Compare # frame objects always using GetIdentifier(). - Debug("GetPyFrame(): create new PyFrame, frameId=%s" % frameId) + Debug("GetPyFrame(): create new PyFrame, frameId=%s" % CefToPyString(frameId)) g_pyFrames[uniqueFrameId] = pyFrame return pyFrame -cdef void RemovePyFrame(int browserId, object frameId) except *: +cdef void RemovePyFrame(int browserId, str frameId) except *: # Called from V8ContextHandler_OnContextReleased(). global g_pyFrames cdef PyFrame pyFrame - cdef object uniqueFrameId = GetUniqueFrameId(browserId, frameId) + cdef str uniqueFrameId = GetUniqueFrameId(browserId, frameId) if uniqueFrameId in g_pyFrames: Debug("del g_pyFrames[%s]" % uniqueFrameId) pyFrame = g_pyFrames[uniqueFrameId] - pyFrame.cefFrame.Assign(NULL) + pyFrame.cefFrame.Assign(nullptr) del pyFrame del g_pyFrames[uniqueFrameId] g_unreferenced_frames.append(uniqueFrameId) @@ -109,7 +109,7 @@ cdef void RemovePyFramesForBrowser(int browserId) except *: for uniqueFrameId in toRemove: Debug("del g_pyFrames[%s]" % uniqueFrameId) pyFrame = g_pyFrames[uniqueFrameId] - pyFrame.cefFrame.Assign(NULL) + pyFrame.cefFrame.Assign(nullptr) del pyFrame del g_pyFrames[uniqueFrameId] g_unreferenced_frames.append(uniqueFrameId) @@ -119,22 +119,22 @@ cdef void RemovePyFramesForBrowser(int browserId) except *: cdef class PyFrame: cdef CefRefPtr[CefFrame] cefFrame cdef int browserId - cdef object frameId + cdef str frameId cdef CefRefPtr[CefFrame] GetCefFrame(self) except *: # Do not call IsValid() here, if the frame does not exist # then no big deal, no reason to crash the application. # The CEF calls will fail, but they also won't cause crash. - if self.cefFrame != NULL and self.cefFrame.get(): + if self.cefFrame and self.cefFrame.get(): return self.cefFrame raise Exception("PyFrame.GetCefFrame() failed: CefFrame was destroyed") - def __init__(self, int browserId, int frameId): + def __init__(self, int browserId, py_string frameId): self.browserId = browserId self.frameId = frameId cpdef py_bool IsValid(self): - if self.cefFrame != NULL and self.cefFrame.get() \ + if self.cefFrame and self.cefFrame.get() \ and self.cefFrame.get().IsValid(): return True return False @@ -168,7 +168,7 @@ cdef class PyFrame: self.GetCefFrame().get().ExecuteJavaScript(PyToCefStringValue(jsCode), PyToCefStringValue(scriptUrl), startLine) - cpdef object GetIdentifier(self): + cpdef str GetIdentifier(self): # It is better to save browser and frame identifiers during # browser instantiation. When freeing PyBrowser and PyFrame # we need these identifiers. CefFrame and CefBrowser may already @@ -203,13 +203,6 @@ cdef class PyFrame: cpdef py_bool IsMain(self): return self.GetCefFrame().get().IsMain() - cpdef py_void LoadString(self, py_string value, py_string url): - cdef CefString cefValue - cdef CefString cefUrl - PyToCefString(value, cefValue) - PyToCefString(url, cefUrl) - self.GetCefFrame().get().LoadString(cefValue, cefUrl) - cpdef py_void LoadUrl(self, py_string url): cdef CefString cefUrl PyToCefString(url, cefUrl) @@ -229,3 +222,25 @@ cdef class PyFrame: cpdef py_void ViewSource(self): self.GetCefFrame().get().ViewSource() + + cpdef py_void SendProcessMessage(self, cef_process_id_t targetProcess, + py_string frameId, py_string messageName, list pyArguments + ) : + cdef CefRefPtr[CefProcessMessage] message = \ + CefProcessMessage_Create(PyToCefStringValue(messageName)) + # This does not work, no idea why, the CEF implementation + # seems not to allow it, both Assign() and swap() do not work: + # | message.get().GetArgumentList().Assign(arguments.get()) + # | message.get().GetArgumentList().swap(arguments) + cdef CefRefPtr[CefListValue] messageArguments = \ + message.get().GetArgumentList() + PyListToExistingCefListValue(self.GetBrowserIdentifier(), + frameId, + pyArguments, messageArguments) + Debug("SendProcessMessage(): message=%s, arguments size=%d" % ( + messageName, + message.get().GetArgumentList().get().GetSize())) + + self.GetCefFrame().get().SendProcessMessage(targetProcess, message) + + diff --git a/src/handlers/cookie_access_filter.pyx b/src/handlers/cookie_access_filter.pyx new file mode 100644 index 000000000..55c4918f6 --- /dev/null +++ b/src/handlers/cookie_access_filter.pyx @@ -0,0 +1,87 @@ +# Copyright (c) 2018 CEF Python, see the Authors file. +# All rights reserved. Licensed under BSD 3-clause license. +# Project website: https://github.com/cztomczak/cefpython + +include "../cefpython.pyx" +include "../browser.pyx" +include "../frame.pyx" +include "../process_message_utils.pyx" + +cdef public cpp_bool CookieAccessFilter_CanSendCookie( + CefRefPtr[CefBrowser] cef_browser, + CefRefPtr[CefFrame] cef_frame, + CefRefPtr[CefRequest] cef_request, + const CefCookie& cef_cookie + ) except * with gil: + cdef PyBrowser browser + cdef PyFrame frame + cdef PyRequest request + cdef PyCookie cookie + cdef object callback + cdef py_bool retval + try: + Debug("CookieAccessFilter_CanSendCookie") + # Issue #455: CefRequestHandler callbacks still executed after + # browser was closed. + if IsBrowserClosed(cef_browser): + return False + + browser = GetPyBrowser(cef_browser, "CanSendCookie") + frame = GetPyFrame(cef_frame) + request = CreatePyRequest(cef_request) + cookie = CreatePyCookie(cef_cookie) + callback = browser.GetClientCallback("CanSendCookie") + if callback: + retval = callback( + browser=browser, + frame=frame, + request=request, + cookie=cookie) + return bool(retval) + else: + # Return True by default + return True + except: + (exc_type, exc_value, exc_trace) = sys.exc_info() + sys.excepthook(exc_type, exc_value, exc_trace) + +cdef public cpp_bool CookieAccessFilter_CanSaveCookie( + CefRefPtr[CefBrowser] cef_browser, + CefRefPtr[CefFrame] cef_frame, + CefRefPtr[CefRequest] cef_request, + CefRefPtr[CefResponse] cef_response, + const CefCookie& cef_cookie + ) except * with gil: + cdef PyBrowser browser + cdef PyFrame frame + cdef PyRequest request + cdef PyResponse response + cdef PyCookie cookie + cdef object callback + cdef py_bool retval + try: + # Issue #455: CefRequestHandler callbacks still executed after + # browser was closed. + if IsBrowserClosed(cef_browser): + return False + + browser = GetPyBrowser(cef_browser, "CanSaveCookie") + frame = GetPyFrame(cef_frame) + request = CreatePyRequest(cef_request) + response = CreatePyResponse(cef_response) + cookie = CreatePyCookie(cef_cookie) + callback = browser.GetClientCallback("CanSaveCookie") + if callback: + retval = callback( + browser=browser, + frame=frame, + request=request, + response=response, + cookie=cookie) + return bool(retval) + else: + # Return True by default + return True + except: + (exc_type, exc_value, exc_trace) = sys.exc_info() + sys.excepthook(exc_type, exc_value, exc_trace) diff --git a/src/handlers/display_handler.pyx b/src/handlers/display_handler.pyx index 7d66d00f7..f729a7dee 100644 --- a/src/handlers/display_handler.pyx +++ b/src/handlers/display_handler.pyx @@ -143,3 +143,23 @@ cdef public void DisplayHandler_OnLoadingProgressChange( except: (exc_type, exc_value, exc_trace) = sys.exc_info() sys.excepthook(exc_type, exc_value, exc_trace) + +cdef public cpp_bool DisplayHandler_OnCursorChange( + CefRefPtr[CefBrowser] cefBrowser, + CefCursorHandle cursor + ) except * with gil: + cdef PyBrowser pyBrowser + try: + pyBrowser = GetPyBrowser(cefBrowser, "OnCursorChange") + callback = pyBrowser.GetClientCallback("OnCursorChange") + if callback: + ret = callback(browser=pyBrowser, cursor=cursor) + if ret: + return True + else: + return False + else: + return False + except: + (exc_type, exc_value, exc_trace) = sys.exc_info() + sys.excepthook(exc_type, exc_value, exc_trace) diff --git a/src/handlers/lifespan_handler.pyx b/src/handlers/lifespan_handler.pyx index bfe22bd11..7c354881b 100644 --- a/src/handlers/lifespan_handler.pyx +++ b/src/handlers/lifespan_handler.pyx @@ -11,16 +11,16 @@ from cef_types cimport WindowOpenDisposition cimport cef_types # WindowOpenDisposition -WOD_UNKNOWN = cef_types.WOD_UNKNOWN -WOD_CURRENT_TAB = cef_types.WOD_CURRENT_TAB -WOD_SINGLETON_TAB = cef_types.WOD_SINGLETON_TAB -WOD_NEW_FOREGROUND_TAB = cef_types.WOD_NEW_FOREGROUND_TAB -WOD_NEW_BACKGROUND_TAB = cef_types.WOD_NEW_BACKGROUND_TAB -WOD_NEW_POPUP = cef_types.WOD_NEW_POPUP -WOD_NEW_WINDOW = cef_types.WOD_NEW_WINDOW -WOD_SAVE_TO_DISK = cef_types.WOD_SAVE_TO_DISK -WOD_OFF_THE_RECORD = cef_types.WOD_OFF_THE_RECORD -WOD_IGNORE_ACTION = cef_types.WOD_IGNORE_ACTION +CEF_WOD_UNKNOWN = cef_types.CEF_WOD_UNKNOWN +CEF_WOD_CURRENT_TAB = cef_types.CEF_WOD_CURRENT_TAB +CEF_WOD_SINGLETON_TAB = cef_types.CEF_WOD_SINGLETON_TAB +CEF_WOD_NEW_FOREGROUND_TAB = cef_types.CEF_WOD_NEW_FOREGROUND_TAB +CEF_WOD_NEW_BACKGROUND_TAB = cef_types.CEF_WOD_NEW_BACKGROUND_TAB +CEF_WOD_NEW_POPUP = cef_types.CEF_WOD_NEW_POPUP +CEF_WOD_NEW_WINDOW = cef_types.CEF_WOD_NEW_WINDOW +CEF_WOD_SAVE_TO_DISK = cef_types.CEF_WOD_SAVE_TO_DISK +CEF_WOD_OFF_THE_RECORD = cef_types.CEF_WOD_OFF_THE_RECORD +CEF_WOD_IGNORE_ACTION = cef_types.CEF_WOD_IGNORE_ACTION cdef public cpp_bool LifespanHandler_OnBeforePopup( @@ -34,6 +34,7 @@ cdef public cpp_bool LifespanHandler_OnBeforePopup( CefWindowInfo& windowInfo, CefRefPtr[CefClient]& client, CefBrowserSettings& settings, + CefRefPtr[CefDictionaryValue]& extra_info, cpp_bool* noJavascriptAccess ) except * with gil: # Empty place-holders: popupFeatures, client. @@ -133,13 +134,13 @@ cdef public void LifespanHandler_OnBeforeClose( # GetCookieManager to implement custom cookie managers then # flushing of cookies would need to be handled manually. cefBrowser.get().GetHost().get().GetRequestContext().get() \ - .GetDefaultCookieManager( - NULL) \ - .get().FlushStore(NULL) + .GetCookieManager( + nullptr) \ + .get().FlushStore(nullptr) browserId = pyBrowser.GetIdentifier() - pyBrowser.cefBrowser.Assign(NULL) - cefBrowser.Assign(NULL) + pyBrowser.cefBrowser.Assign(nullptr) + cefBrowser.Assign(nullptr) del pyBrowser RemovePythonCallbacksForBrowser(browserId) diff --git a/src/handlers/render_handler.pyx b/src/handlers/render_handler.pyx index a8ad49124..a282c8893 100644 --- a/src/handlers/render_handler.pyx +++ b/src/handlers/render_handler.pyx @@ -7,6 +7,7 @@ include "../browser.pyx" include "../string_utils.pyx" cimport cef_types +from libc.stdint cimport uint32_t from cef_types cimport CefRange # cef_paint_element_type_t, PaintElementType @@ -73,7 +74,13 @@ cdef public cpp_bool RenderHandler_GetViewRect( else: return False else: - return False + # without a default cefRect, pysdl2 example will fail + # the value is inspired by https://github.com/obsproject/obs-browser/blob/master/browser-client.cpp#L280 + cefRect.x = 0 + cefRect.y = 0 + cefRect.width = 16 + cefRect.height = 16 + return True except: (exc_type, exc_value, exc_trace) = sys.exc_info() sys.excepthook(exc_type, exc_value, exc_trace) @@ -219,20 +226,6 @@ cdef public void RenderHandler_OnPaint( (exc_type, exc_value, exc_trace) = sys.exc_info() sys.excepthook(exc_type, exc_value, exc_trace) -cdef public void RenderHandler_OnCursorChange( - CefRefPtr[CefBrowser] cefBrowser, - CefCursorHandle cursor - ) except * with gil: - cdef PyBrowser pyBrowser - try: - pyBrowser = GetPyBrowser(cefBrowser, "OnCursorChange") - callback = pyBrowser.GetClientCallback("OnCursorChange") - if callback: - callback(browser=pyBrowser, cursor=cursor) - except: - (exc_type, exc_value, exc_trace) = sys.exc_info() - sys.excepthook(exc_type, exc_value, exc_trace) - cdef public void RenderHandler_OnScrollOffsetChanged( CefRefPtr[CefBrowser] cefBrowser ) except * with gil: @@ -249,7 +242,7 @@ cdef public void RenderHandler_OnScrollOffsetChanged( cdef public cpp_bool RenderHandler_StartDragging( CefRefPtr[CefBrowser] cef_browser, CefRefPtr[CefDragData] cef_drag_data, - uint32 allowed_ops, + uint32_t allowed_ops, int x, int y ) except * with gil: cdef PyBrowser browser @@ -278,7 +271,7 @@ cdef public cpp_bool RenderHandler_StartDragging( cdef public void RenderHandler_UpdateDragCursor( CefRefPtr[CefBrowser] cef_browser, - uint32 operation, + uint32_t operation, ) except * with gil: cdef PyBrowser browser try: diff --git a/src/handlers/request_handler.pyx b/src/handlers/request_handler.pyx index 866942bfd..17f52acd7 100644 --- a/src/handlers/request_handler.pyx +++ b/src/handlers/request_handler.pyx @@ -8,6 +8,7 @@ include "../cookie.pyx" # cef_termination_status_t cimport cef_types +from libc.stdint cimport int64_t TS_ABNORMAL_TERMINATION = cef_types.TS_ABNORMAL_TERMINATION TS_PROCESS_WAS_KILLED = cef_types.TS_PROCESS_WAS_KILLED TS_PROCESS_CRASHED = cef_types.TS_PROCESS_CRASHED @@ -37,16 +38,16 @@ cdef class PyAuthCallback: # ----------------------------------------------------------------------------- cdef PyRequestCallback CreatePyRequestCallback( - CefRefPtr[CefRequestCallback] cefCallback): + CefRefPtr[CefCallback] cefCallback): cdef PyRequestCallback pyCallback = PyRequestCallback() pyCallback.cefCallback = cefCallback return pyCallback cdef class PyRequestCallback: - cdef CefRefPtr[CefRequestCallback] cefCallback + cdef CefRefPtr[CefCallback] cefCallback - cpdef py_void Continue(self, py_bool allow): - self.cefCallback.get().Continue(bool(allow)) + cpdef py_void Continue(self): + self.cefCallback.get().Continue() cpdef py_void Cancel(self): self.cefCallback.get().Cancel() @@ -140,7 +141,7 @@ cdef public CefRefPtr[CefResourceHandler] RequestHandler_GetResourceHandler( # Issue #455: CefRequestHandler callbacks still executed after # browser was closed. if IsBrowserClosed(cefBrowser): - return NULL + return nullptr pyBrowser = GetPyBrowser(cefBrowser, "GetResourceHandler") pyFrame = GetPyFrame(cefFrame) @@ -154,9 +155,9 @@ cdef public CefRefPtr[CefResourceHandler] RequestHandler_GetResourceHandler( if returnValue: return CreateResourceHandler(returnValue) else: - return NULL + return nullptr else: - return NULL + return nullptr except: (exc_type, exc_value, exc_trace) = sys.exc_info() sys.excepthook(exc_type, exc_value, exc_trace) @@ -279,8 +280,8 @@ cdef public cpp_bool RequestHandler_GetAuthCredentials( cdef public cpp_bool RequestHandler_OnQuotaRequest( CefRefPtr[CefBrowser] cefBrowser, const CefString& cefOriginUrl, - int64 newSize, - CefRefPtr[CefRequestCallback] cefRequestCallback + int64_t newSize, + CefRefPtr[CefCallback] cefCallback ) except * with gil: cdef PyBrowser pyBrowser cdef py_string pyOriginUrl @@ -300,7 +301,7 @@ cdef public cpp_bool RequestHandler_OnQuotaRequest( browser=pyBrowser, origin_url=pyOriginUrl, new_size=newSize, - callback=CreatePyRequestCallback(cefRequestCallback)) + callback=CreatePyRequestCallback(cefCallback)) return bool(returnValue) else: return False @@ -309,49 +310,6 @@ cdef public cpp_bool RequestHandler_OnQuotaRequest( sys.excepthook(exc_type, exc_value, exc_trace) -cdef public CefRefPtr[CefCookieManager] RequestHandler_GetCookieManager( - CefRefPtr[CefBrowser] cefBrowser, - const CefString& cefMainUrl - ) except * with gil: - # In CEF the GetCookieManager callback belongs to - # CefRequestContextHandler. - # In an exceptional case the browser parameter may be None - # due to limitation in CEF API. No workaround as of now. - cdef PyBrowser pyBrowser - cdef str pyMainUrl - cdef object clientCallback - cdef PyCookieManager returnValue - try: - # Issue #429: in some cases due to a race condition the browser - # may be NULL. - if not cefBrowser.get(): - return NULL - - # Issue #455: CefRequestHandler callbacks still executed after - # browser was closed. - if IsBrowserClosed(cefBrowser): - return NULL - - pyBrowser = GetPyBrowser(cefBrowser, "GetCookieManager") - pyMainUrl = CefToPyString(cefMainUrl) - clientCallback = pyBrowser.GetClientCallback("GetCookieManager") - if clientCallback: - returnValue = clientCallback( - browser=pyBrowser, - main_url=pyMainUrl) - if returnValue: - if isinstance(returnValue, PyCookieManager): - return returnValue.cefCookieManager - else: - raise Exception("Expected a CookieManager object") - return NULL - else: - return NULL - except: - (exc_type, exc_value, exc_trace) = sys.exc_info() - sys.excepthook(exc_type, exc_value, exc_trace) - - cdef public void RequestHandler_OnProtocolExecution( CefRefPtr[CefBrowser] cefBrowser, const CefString& cefUrl, @@ -388,60 +346,10 @@ cdef public void RequestHandler_OnProtocolExecution( sys.excepthook(exc_type, exc_value, exc_trace) -cdef public cpp_bool RequestHandler_OnBeforePluginLoad( - CefRefPtr[CefBrowser] browser, - const CefString& mime_type, - const CefString& plugin_url, - cpp_bool is_main_frame, - const CefString& top_origin_url, - CefRefPtr[CefWebPluginInfo] plugin_info, - cef_types.cef_plugin_policy_t* plugin_policy - ) except * with gil: - cdef PyBrowser pyBrowser - cdef PyWebPluginInfo pyInfo - cdef py_bool returnValue - cdef object clientCallback - try: - # OnBeforePluginLoad is called from RequestContexthandler. - # The Browser object might not be available, because it is - # being set synchronously during CreateBrowserSync, after - # Browser is created. From testing it always works, however - # better be safe. - if not browser.get(): - Debug("WARNING: RequestHandler_OnBeforePluginLoad() failed," - " Browser object is not available") - return False - - # Issue #455: CefRequestHandler callbacks still executed after - # browser was closed. - if IsBrowserClosed(browser): - return False - - py_browser = GetPyBrowser(browser, "OnBeforePluginLoad") - py_plugin_info = CreatePyWebPluginInfo(plugin_info) - clientCallback = GetGlobalClientCallback("OnBeforePluginLoad") - if clientCallback: - returnValue = clientCallback( - browser=py_browser, - mime_type=CefToPyString(mime_type), - plugin_url=CefToPyString(plugin_url), - is_main_frame=bool(is_main_frame), - top_origin_url=CefToPyString(top_origin_url), - plugin_info=py_plugin_info) - if returnValue: - plugin_policy[0] = cef_types.PLUGIN_POLICY_DISABLE - return bool(returnValue) - else: - return False - except: - (exc_type, exc_value, exc_trace) = sys.exc_info() - sys.excepthook(exc_type, exc_value, exc_trace) - - cdef public cpp_bool RequestHandler_OnCertificateError( int certError, const CefString& cefRequestUrl, - CefRefPtr[CefRequestCallback] cefCertCallback + CefRefPtr[CefCallback] cefCertCallback ) except * with gil: cdef py_bool returnValue cdef object clientCallback @@ -485,103 +393,3 @@ cdef public void RequestHandler_OnRendererProcessTerminated( except: (exc_type, exc_value, exc_trace) = sys.exc_info() sys.excepthook(exc_type, exc_value, exc_trace) - - -cdef public void RequestHandler_OnPluginCrashed( - CefRefPtr[CefBrowser] cefBrowser, - const CefString& cefPluginPath - ) except * with gil: - # TODO: plugin may crash during browser creation. Let this callback - # to be set either through cefpython.SetGlobalClientCallback() - # or PyBrowser.SetClientCallback(). Modify the - # PyBrowser.GetClientCallback() implementation to return a global - # callback first if set. - cdef PyBrowser pyBrowser - cdef object clientCallback - try: - # Issue #455: CefRequestHandler callbacks still executed after - # browser was closed. - if IsBrowserClosed(cefBrowser): - return - - pyBrowser = GetPyBrowser(cefBrowser, "OnPluginCrashed") - clientCallback = pyBrowser.GetClientCallback("OnPluginCrashed") - if clientCallback: - clientCallback( - browser=pyBrowser, - plugin_path=CefToPyString(cefPluginPath)) - except: - (exc_type, exc_value, exc_trace) = sys.exc_info() - sys.excepthook(exc_type, exc_value, exc_trace) - - -cdef public cpp_bool RequestHandler_CanGetCookies( - CefRefPtr[CefBrowser] cef_browser, - CefRefPtr[CefFrame] cef_frame, - CefRefPtr[CefRequest] cef_request - ) except * with gil: - cdef PyBrowser browser - cdef PyFrame frame - cdef PyRequest request - cdef object callback - cdef py_bool retval - try: - # Issue #455: CefRequestHandler callbacks still executed after - # browser was closed. - if IsBrowserClosed(cef_browser): - return False - - browser = GetPyBrowser(cef_browser, "CanGetCookies") - frame = GetPyFrame(cef_frame) - request = CreatePyRequest(cef_request) - callback = browser.GetClientCallback("CanGetCookies") - if callback: - retval = callback( - browser=browser, - frame=frame, - request=request) - return bool(retval) - else: - # Return True by default - return True - except: - (exc_type, exc_value, exc_trace) = sys.exc_info() - sys.excepthook(exc_type, exc_value, exc_trace) - - -cdef public cpp_bool RequestHandler_CanSetCookie( - CefRefPtr[CefBrowser] cef_browser, - CefRefPtr[CefFrame] cef_frame, - CefRefPtr[CefRequest] cef_request, - const CefCookie& cef_cookie - ) except * with gil: - cdef PyBrowser browser - cdef PyFrame frame - cdef PyRequest request - cdef PyCookie cookie - cdef object callback - cdef py_bool retval - try: - # Issue #455: CefRequestHandler callbacks still executed after - # browser was closed. - if IsBrowserClosed(cef_browser): - return False - - browser = GetPyBrowser(cef_browser, "CanSetCookie") - frame = GetPyFrame(cef_frame) - request = CreatePyRequest(cef_request) - cookie = CreatePyCookie(cef_cookie) - callback = browser.GetClientCallback("CanSetCookie") - if callback: - retval = callback( - browser=browser, - frame=frame, - request=request, - cookie=cookie) - return bool(retval) - else: - # Return True by default - return True - except: - (exc_type, exc_value, exc_trace) = sys.exc_info() - sys.excepthook(exc_type, exc_value, exc_trace) diff --git a/src/handlers/resource_handler.pyx b/src/handlers/resource_handler.pyx index 1c379f192..695c57e63 100644 --- a/src/handlers/resource_handler.pyx +++ b/src/handlers/resource_handler.pyx @@ -3,7 +3,7 @@ # Project website: https://github.com/cztomczak/cefpython include "../cefpython.pyx" - +from libc.stdint cimport int64_t import weakref # ----------------------------------------------------------------------------- @@ -21,7 +21,7 @@ cdef int g_userResourceHandlerMaxId = 0 cdef py_void ValidateUserResourceHandler(object userResourceHandler): cdef list methods = ["ProcessRequest", "GetResponseHeaders", - "ReadResponse", "CanGetCookie", "CanSetCookie", "Cancel"] + "ReadResponse", "Cancel"] for method in methods: if userResourceHandler and hasattr(userResourceHandler, method)\ and callable(getattr(userResourceHandler, method)): @@ -102,7 +102,7 @@ cdef public cpp_bool ResourceHandler_ProcessRequest( cdef public void ResourceHandler_GetResponseHeaders( int resourceHandlerId, CefRefPtr[CefResponse] cefResponse, - int64& cefResponseLength, + int64_t& cefResponseLength, CefString& cefRedirectUrl ) except * with gil: cdef PyResourceHandler pyResourceHandler @@ -122,7 +122,7 @@ cdef public void ResourceHandler_GetResponseHeaders( if userCallback: returnValue = userCallback(pyResponse, responseLengthOut, redirectUrlOut) - (&cefResponseLength)[0] = responseLengthOut[0] + (&cefResponseLength)[0] = responseLengthOut[0] if redirectUrlOut[0]: PyToCefString(redirectUrlOut[0], cefRedirectUrl) return @@ -182,50 +182,6 @@ cdef public cpp_bool ResourceHandler_ReadResponse( (exc_type, exc_value, exc_trace) = sys.exc_info() sys.excepthook(exc_type, exc_value, exc_trace) -cdef public cpp_bool ResourceHandler_CanGetCookie( - int resourceHandlerId, - const CefCookie& cefCookie - ) except * with gil: - cdef PyResourceHandler pyResourceHandler - cdef object userCallback - cdef py_bool returnValue - cdef PyCookie pyCookie - try: - assert IsThread(TID_IO), "Must be called on the IO thread" - pyResourceHandler = GetPyResourceHandler(resourceHandlerId) - pyCookie = CreatePyCookie(cefCookie) - if pyResourceHandler: - userCallback = pyResourceHandler.GetCallback("CanGetCookie") - if userCallback: - returnValue = userCallback(cookie=pyCookie) - return bool(returnValue) - return False - except: - (exc_type, exc_value, exc_trace) = sys.exc_info() - sys.excepthook(exc_type, exc_value, exc_trace) - -cdef public cpp_bool ResourceHandler_CanSetCookie( - int resourceHandlerId, - const CefCookie& cefCookie - ) except * with gil: - cdef PyResourceHandler pyResourceHandler - cdef object userCallback - cdef py_bool returnValue - cdef PyCookie pyCookie - try: - assert IsThread(TID_IO), "Must be called on the IO thread" - pyResourceHandler = GetPyResourceHandler(resourceHandlerId) - pyCookie = CreatePyCookie(cefCookie) - if pyResourceHandler: - userCallback = pyResourceHandler.GetCallback("CanSetCookie") - if userCallback: - returnValue = userCallback(cookie=pyCookie) - return bool(returnValue) - return False - except: - (exc_type, exc_value, exc_trace) = sys.exc_info() - sys.excepthook(exc_type, exc_value, exc_trace) - cdef public void ResourceHandler_Cancel( int resourceHandlerId ) except * with gil: diff --git a/src/handlers/v8context_handler.pyx b/src/handlers/v8context_handler.pyx index fccdad562..2766d9a5f 100644 --- a/src/handlers/v8context_handler.pyx +++ b/src/handlers/v8context_handler.pyx @@ -11,6 +11,7 @@ include "../cefpython.pyx" include "../browser.pyx" include "../frame.pyx" +from libc.stdint cimport int64_t cdef public void V8ContextHandler_OnContextCreated( CefRefPtr[CefBrowser] cefBrowser, @@ -20,7 +21,6 @@ cdef public void V8ContextHandler_OnContextCreated( cdef PyFrame pyFrame cdef object clientCallback try: - Debug("V8ContextHandler_OnContextCreated()") pyBrowser = GetPyBrowser(cefBrowser, "OnContextCreated") pyBrowser.SetUserData("__v8ContextCreated", True) pyFrame = GetPyFrame(cefFrame) @@ -34,7 +34,7 @@ cdef public void V8ContextHandler_OnContextCreated( cdef public void V8ContextHandler_OnContextReleased( int browserId, - int64 frameId + CefString frameId ) except * with gil: cdef PyBrowser pyBrowser cdef PyFrame pyFrame @@ -53,16 +53,16 @@ cdef public void V8ContextHandler_OnContextReleased( if not pyBrowser: Debug("OnContextReleased: Browser doesn't exist anymore, id={id}" .format(id=str(browserId))) - RemovePyFrame(browserId, frameId) + RemovePyFrame(browserId, CefToPyString(frameId)) return - pyFrame = GetPyFrameById(browserId, frameId) + pyFrame = GetPyFrameById(browserId, CefToPyString(frameId)) # Frame may already be destroyed while IPC messaging was executing # (Issue #431). if pyFrame: clientCallback = pyBrowser.GetClientCallback("OnContextReleased") if clientCallback: clientCallback(browser=pyBrowser, frame=pyFrame) - RemovePyFrame(browserId, frameId) + RemovePyFrame(browserId, CefToPyString(frameId)) except: (exc_type, exc_value, exc_trace) = sys.exc_info() sys.excepthook(exc_type, exc_value, exc_trace) diff --git a/src/handlers/v8function_handler.pyx b/src/handlers/v8function_handler.pyx index ee73619f8..8121674af 100644 --- a/src/handlers/v8function_handler.pyx +++ b/src/handlers/v8function_handler.pyx @@ -8,7 +8,7 @@ include "../frame.pyx" cdef public void V8FunctionHandler_Execute( CefRefPtr[CefBrowser] cefBrowser, - int64 frameId, + CefString& frameId, CefString& cefFuncName, CefRefPtr[CefListValue] cefFuncArgs ) except * with gil: @@ -22,7 +22,7 @@ cdef public void V8FunctionHandler_Execute( cdef py_string errorMessage try: pyBrowser = GetPyBrowser(cefBrowser, "V8FunctionHandler_Execute") - cefFrame = cefBrowser.get().GetFrame(frameId) + cefFrame = cefBrowser.get().GetFrameByName(frameId) if cefFrame.get(): pyFrame = GetPyFrame(cefFrame) else: diff --git a/src/include/base/cef_atomic_flag.h b/src/include/base/cef_atomic_flag.h new file mode 100644 index 000000000..3a2fdbc1d --- /dev/null +++ b/src/include/base/cef_atomic_flag.h @@ -0,0 +1,97 @@ +// Copyright (c) 2014 Marshall A. Greenblatt. Portions copyright (c) 2011 +// Google Inc. 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_BASE_CEF_ATOMIC_FLAG_H_ +#define CEF_INCLUDE_BASE_CEF_ATOMIC_FLAG_H_ +#pragma once + +#if defined(USING_CHROMIUM_INCLUDES) +// When building CEF include the Chromium header directly. +#include "base/synchronization/atomic_flag.h" + +#else // !USING_CHROMIUM_INCLUDES +// The following is substantially similar to the Chromium implementation. +// If the Chromium implementation diverges the below implementation should be +// updated to match. + +#include + +#include + +#include "include/base/cef_thread_checker.h" + +namespace base { + +/// +/// A flag that can safely be set from one thread and read from other threads. +/// +/// This class IS NOT intended for synchronization between threads. +/// +class AtomicFlag { + public: + AtomicFlag(); + + AtomicFlag(const AtomicFlag&) = delete; + AtomicFlag& operator=(const AtomicFlag&) = delete; + + ~AtomicFlag(); + + /// + /// Set the flag. Must always be called from the same thread. + /// + void Set(); + + /// + /// Returns true iff the flag was set. If this returns true, the current + /// thread is guaranteed to be synchronized with all memory operations on the + /// thread which invoked Set() up until at least the first call to Set() on + /// it. + /// + bool IsSet() const { + // Inline here: this has a measurable performance impact on base::WeakPtr. + return flag_.load(std::memory_order_acquire) != 0; + } + + /// + /// Resets the flag. Be careful when using this: callers might not expect + /// IsSet() to return false after returning true once. + /// + void UnsafeResetForTesting(); + + private: + std::atomic flag_{0}; + base::ThreadChecker set_thread_checker_; +}; + +} // namespace base + +#endif // !USING_CHROMIUM_INCLUDES + +#endif // CEF_INCLUDE_BASE_CEF_ATOMIC_FLAG_H_ diff --git a/src/include/base/cef_atomic_ref_count.h b/src/include/base/cef_atomic_ref_count.h index 4d6777970..38e8f93b7 100644 --- a/src/include/base/cef_atomic_ref_count.h +++ b/src/include/base/cef_atomic_ref_count.h @@ -43,120 +43,78 @@ // When building CEF include the Chromium header directly. #include "base/atomic_ref_count.h" -// Used when declaring a base::AtomicRefCount value. This is an object type with -// Chromium headers. -#define ATOMIC_DECLARATION (0) - -// Maintaining compatibility with AtompicRefCount* functions that were removed -// from Chromium in http://crrev.com/ee96d561. -namespace base { - -// Increment a reference count by 1. -inline void AtomicRefCountInc(volatile AtomicRefCount* ptr) { - const_cast(ptr)->Increment(); -} - -// Decrement a reference count by 1 and return whether the result is non-zero. -// Insert barriers to ensure that state written before the reference count -// became zero will be visible to a thread that has just made the count zero. -inline bool AtomicRefCountDec(volatile AtomicRefCount* ptr) { - return const_cast(ptr)->Decrement(); -} - -// Return whether the reference count is one. If the reference count is used -// in the conventional way, a refrerence count of 1 implies that the current -// thread owns the reference and no other thread shares it. This call performs -// the test for a reference count of one, and performs the memory barrier -// needed for the owning thread to act on the object, knowing that it has -// exclusive access to the object. -inline bool AtomicRefCountIsOne(volatile AtomicRefCount* ptr) { - return const_cast(ptr)->IsOne(); -} - -// Return whether the reference count is zero. With conventional object -// referencing counting, the object will be destroyed, so the reference count -// should never be zero. Hence this is generally used for a debug check. -inline bool AtomicRefCountIsZero(volatile AtomicRefCount* ptr) { - return const_cast(ptr)->IsZero(); -} - -} // namespace base - #else // !USING_CHROMIUM_INCLUDES // The following is substantially similar to the Chromium implementation. // If the Chromium implementation diverges the below implementation should be // updated to match. -#include "include/base/cef_atomicops.h" - -// Annotations are not currently supported. -#define ANNOTATE_HAPPENS_BEFORE(obj) /* empty */ -#define ANNOTATE_HAPPENS_AFTER(obj) /* empty */ - -// Used when declaring a base::AtomicRefCount value. This is an integer/ptr type -// with CEF headers. -#define ATOMIC_DECLARATION = 0 +#include namespace base { -typedef subtle::Atomic32 AtomicRefCount; - -// Increment a reference count by "increment", which must exceed 0. -inline void AtomicRefCountIncN(volatile AtomicRefCount* ptr, - AtomicRefCount increment) { - subtle::NoBarrier_AtomicIncrement(ptr, increment); -} - -// Decrement a reference count by "decrement", which must exceed 0, -// and return whether the result is non-zero. -// Insert barriers to ensure that state written before the reference count -// became zero will be visible to a thread that has just made the count zero. -inline bool AtomicRefCountDecN(volatile AtomicRefCount* ptr, - AtomicRefCount decrement) { - ANNOTATE_HAPPENS_BEFORE(ptr); - bool res = (subtle::Barrier_AtomicIncrement(ptr, -decrement) != 0); - if (!res) { - ANNOTATE_HAPPENS_AFTER(ptr); +class AtomicRefCount { + public: + constexpr AtomicRefCount() : ref_count_(0) {} + explicit constexpr AtomicRefCount(int initial_value) + : ref_count_(initial_value) {} + + /// + /// Increment a reference count. + /// Returns the previous value of the count. + /// + int Increment() { return Increment(1); } + + /// + /// Increment a reference count by "increment", which must exceed 0. + /// Returns the previous value of the count. + /// + int Increment(int increment) { + return ref_count_.fetch_add(increment, std::memory_order_relaxed); + } + + /// + /// Decrement a reference count, and return whether the result is non-zero. + /// Insert barriers to ensure that state written before the reference count + /// became zero will be visible to a thread that has just made the count zero. + /// + bool Decrement() { + // TODO(jbroman): Technically this doesn't need to be an acquire operation + // unless the result is 1 (i.e., the ref count did indeed reach zero). + // However, there are toolchain issues that make that not work as well at + // present (notably TSAN doesn't like it). + return ref_count_.fetch_sub(1, std::memory_order_acq_rel) != 1; } - return res; -} - -// Increment a reference count by 1. -inline void AtomicRefCountInc(volatile AtomicRefCount* ptr) { - base::AtomicRefCountIncN(ptr, 1); -} - -// Decrement a reference count by 1 and return whether the result is non-zero. -// Insert barriers to ensure that state written before the reference count -// became zero will be visible to a thread that has just made the count zero. -inline bool AtomicRefCountDec(volatile AtomicRefCount* ptr) { - return base::AtomicRefCountDecN(ptr, 1); -} - -// Return whether the reference count is one. If the reference count is used -// in the conventional way, a refrerence count of 1 implies that the current -// thread owns the reference and no other thread shares it. This call performs -// the test for a reference count of one, and performs the memory barrier -// needed for the owning thread to act on the object, knowing that it has -// exclusive access to the object. -inline bool AtomicRefCountIsOne(volatile AtomicRefCount* ptr) { - bool res = (subtle::Acquire_Load(ptr) == 1); - if (res) { - ANNOTATE_HAPPENS_AFTER(ptr); + + /// + /// Return whether the reference count is one. If the reference count is used + /// in the conventional way, a refrerence count of 1 implies that the current + /// thread owns the reference and no other thread shares it. This call + /// performs the test for a reference count of one, and performs the memory + /// barrier needed for the owning thread to act on the object, knowing that it + /// has exclusive access to the object. + /// + bool IsOne() const { return ref_count_.load(std::memory_order_acquire) == 1; } + + /// + /// Return whether the reference count is zero. With conventional object + /// referencing counting, the object will be destroyed, so the reference count + /// should never be zero. Hence this is generally used for a debug check. + /// + bool IsZero() const { + return ref_count_.load(std::memory_order_acquire) == 0; } - return res; -} - -// Return whether the reference count is zero. With conventional object -// referencing counting, the object will be destroyed, so the reference count -// should never be zero. Hence this is generally used for a debug check. -inline bool AtomicRefCountIsZero(volatile AtomicRefCount* ptr) { - bool res = (subtle::Acquire_Load(ptr) == 0); - if (res) { - ANNOTATE_HAPPENS_AFTER(ptr); + + /// + /// Returns the current reference count (with no barriers). This is subtle, + /// and should be used only for debugging. + /// + int SubtleRefCountForDebug() const { + return ref_count_.load(std::memory_order_relaxed); } - return res; -} + + private: + std::atomic_int ref_count_; +}; } // namespace base diff --git a/src/include/base/cef_atomicops.h b/src/include/base/cef_atomicops.h deleted file mode 100644 index 96aebabf8..000000000 --- a/src/include/base/cef_atomicops.h +++ /dev/null @@ -1,199 +0,0 @@ -// Copyright (c) 2014 Marshall A. Greenblatt. Portions copyright (c) 2012 -// Google Inc. 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. - -// For atomic operations on reference counts, see cef_atomic_ref_count.h. - -// The routines exported by this module are subtle. If you use them, even if -// you get the code right, it will depend on careful reasoning about atomicity -// and memory ordering; it will be less readable, and harder to maintain. If -// you plan to use these routines, you should have a good reason, such as solid -// evidence that performance would otherwise suffer, or there being no -// alternative. You should assume only properties explicitly guaranteed by the -// specifications in this file. You are almost certainly _not_ writing code -// just for the x86; if you assume x86 semantics, x86 hardware bugs and -// implementations on other archtectures will cause your code to break. If you -// do not know what you are doing, avoid these routines, and use a Mutex. -// -// It is incorrect to make direct assignments to/from an atomic variable. -// You should use one of the Load or Store routines. The NoBarrier -// versions are provided when no barriers are needed: -// NoBarrier_Store() -// NoBarrier_Load() -// Although there are currently no compiler enforcement, you are encouraged -// to use these. -// - -#ifndef CEF_INCLUDE_BASE_CEF_ATOMICOPS_H_ -#define CEF_INCLUDE_BASE_CEF_ATOMICOPS_H_ -#pragma once - -#if defined(BASE_ATOMICOPS_H_) -// Do nothing if the Chromium header has already been included. -// This can happen in cases where Chromium code is used directly by the -// client application. When using Chromium code directly always include -// the Chromium header first to avoid type conflicts. -#elif defined(USING_CHROMIUM_INCLUDES) -// When building CEF include the Chromium header directly. -#include "base/atomicops.h" -#else // !USING_CHROMIUM_INCLUDES -// The following is substantially similar to the Chromium implementation. -// If the Chromium implementation diverges the below implementation should be -// updated to match. - -#include - -#include "include/base/cef_build.h" - -#if defined(OS_WIN) && defined(ARCH_CPU_64_BITS) -// windows.h #defines this (only on x64). This causes problems because the -// public API also uses MemoryBarrier at the public name for this fence. So, on -// X64, undef it, and call its documented -// (http://msdn.microsoft.com/en-us/library/windows/desktop/ms684208.aspx) -// implementation directly. -#undef MemoryBarrier -#endif - -namespace base { -namespace subtle { - -typedef int32_t Atomic32; -#ifdef ARCH_CPU_64_BITS -// We need to be able to go between Atomic64 and AtomicWord implicitly. This -// means Atomic64 and AtomicWord should be the same type on 64-bit. -#if defined(__ILP32__) || defined(OS_NACL) -// NaCl's intptr_t is not actually 64-bits on 64-bit! -// http://code.google.com/p/nativeclient/issues/detail?id=1162 -typedef int64_t Atomic64; -#else -typedef intptr_t Atomic64; -#endif -#endif - -// Use AtomicWord for a machine-sized pointer. It will use the Atomic32 or -// Atomic64 routines below, depending on your architecture. -typedef intptr_t AtomicWord; - -// Atomically execute: -// result = *ptr; -// if (*ptr == old_value) -// *ptr = new_value; -// return result; -// -// I.e., replace "*ptr" with "new_value" if "*ptr" used to be "old_value". -// Always return the old value of "*ptr" -// -// This routine implies no memory barriers. -Atomic32 NoBarrier_CompareAndSwap(volatile Atomic32* ptr, - Atomic32 old_value, - Atomic32 new_value); - -// Atomically store new_value into *ptr, returning the previous value held in -// *ptr. This routine implies no memory barriers. -Atomic32 NoBarrier_AtomicExchange(volatile Atomic32* ptr, Atomic32 new_value); - -// Atomically increment *ptr by "increment". Returns the new value of -// *ptr with the increment applied. This routine implies no memory barriers. -Atomic32 NoBarrier_AtomicIncrement(volatile Atomic32* ptr, Atomic32 increment); - -Atomic32 Barrier_AtomicIncrement(volatile Atomic32* ptr, Atomic32 increment); - -// These following lower-level operations are typically useful only to people -// implementing higher-level synchronization operations like spinlocks, -// mutexes, and condition-variables. They combine CompareAndSwap(), a load, or -// a store with appropriate memory-ordering instructions. "Acquire" operations -// ensure that no later memory access can be reordered ahead of the operation. -// "Release" operations ensure that no previous memory access can be reordered -// after the operation. "Barrier" operations have both "Acquire" and "Release" -// semantics. A MemoryBarrier() has "Barrier" semantics, but does no memory -// access. -Atomic32 Acquire_CompareAndSwap(volatile Atomic32* ptr, - Atomic32 old_value, - Atomic32 new_value); -Atomic32 Release_CompareAndSwap(volatile Atomic32* ptr, - Atomic32 old_value, - Atomic32 new_value); - -void MemoryBarrier(); -void NoBarrier_Store(volatile Atomic32* ptr, Atomic32 value); -void Acquire_Store(volatile Atomic32* ptr, Atomic32 value); -void Release_Store(volatile Atomic32* ptr, Atomic32 value); - -Atomic32 NoBarrier_Load(volatile const Atomic32* ptr); -Atomic32 Acquire_Load(volatile const Atomic32* ptr); -Atomic32 Release_Load(volatile const Atomic32* ptr); - -// 64-bit atomic operations (only available on 64-bit processors). -#ifdef ARCH_CPU_64_BITS -Atomic64 NoBarrier_CompareAndSwap(volatile Atomic64* ptr, - Atomic64 old_value, - Atomic64 new_value); -Atomic64 NoBarrier_AtomicExchange(volatile Atomic64* ptr, Atomic64 new_value); -Atomic64 NoBarrier_AtomicIncrement(volatile Atomic64* ptr, Atomic64 increment); -Atomic64 Barrier_AtomicIncrement(volatile Atomic64* ptr, Atomic64 increment); - -Atomic64 Acquire_CompareAndSwap(volatile Atomic64* ptr, - Atomic64 old_value, - Atomic64 new_value); -Atomic64 Release_CompareAndSwap(volatile Atomic64* ptr, - Atomic64 old_value, - Atomic64 new_value); -void NoBarrier_Store(volatile Atomic64* ptr, Atomic64 value); -void Acquire_Store(volatile Atomic64* ptr, Atomic64 value); -void Release_Store(volatile Atomic64* ptr, Atomic64 value); -Atomic64 NoBarrier_Load(volatile const Atomic64* ptr); -Atomic64 Acquire_Load(volatile const Atomic64* ptr); -Atomic64 Release_Load(volatile const Atomic64* ptr); -#endif // ARCH_CPU_64_BITS - -} // namespace subtle -} // namespace base - -// Include our platform specific implementation. -#if defined(OS_WIN) && defined(COMPILER_MSVC) && defined(ARCH_CPU_X86_FAMILY) -#include "include/base/internal/cef_atomicops_x86_msvc.h" -#elif defined(OS_MACOSX) -#include "include/base/internal/cef_atomicops_mac.h" -#elif defined(COMPILER_GCC) && defined(ARCH_CPU_X86_FAMILY) -#include "include/base/internal/cef_atomicops_x86_gcc.h" -#elif defined(COMPILER_GCC) && defined(__ARM_ARCH) -#include "include/base/internal/cef_atomicops_arm_gcc.h" -#else -#error "Atomic operations are not supported on your platform" -#endif - -// On some platforms we need additional declarations to make -// AtomicWord compatible with our other Atomic* types. -#if defined(OS_MACOSX) || defined(OS_OPENBSD) -#include "include/base/internal/cef_atomicops_atomicword_compat.h" -#endif - -#endif // !USING_CHROMIUM_INCLUDES - -#endif // CEF_INCLUDE_BASE_CEF_ATOMICOPS_H_ diff --git a/src/include/base/cef_auto_reset.h b/src/include/base/cef_auto_reset.h new file mode 100644 index 000000000..be3a05da5 --- /dev/null +++ b/src/include/base/cef_auto_reset.h @@ -0,0 +1,90 @@ +// Copyright (c) 2014 Marshall A. Greenblatt. Portions copyright (c) 2011 +// Google Inc. 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. + +// base::AutoReset<> is useful for setting a variable to a new value only within +// a particular scope. An base::AutoReset<> object resets a variable to its +// original value upon destruction, making it an alternative to writing +// "var = false;" or "var = old_val;" at all of a block's exit points. +// +// This should be obvious, but note that an base::AutoReset<> instance should +// have a shorter lifetime than its scoped_variable, to prevent invalid memory +// writes when the base::AutoReset<> object is destroyed. + +#ifndef CEF_INCLUDE_BASE_CEF_AUTO_RESET_H_ +#define CEF_INCLUDE_BASE_CEF_AUTO_RESET_H_ +#pragma once + +#if defined(USING_CHROMIUM_INCLUDES) +// When building CEF include the Chromium header directly. +#include "base/auto_reset.h" +#else // !USING_CHROMIUM_INCLUDES +// The following is substantially similar to the Chromium implementation. +// If the Chromium implementation diverges the below implementation should be +// updated to match. + +#include + +namespace base { + +template +class AutoReset { + public: + template + AutoReset(T* scoped_variable, U&& new_value) + : scoped_variable_(scoped_variable), + original_value_( + std::exchange(*scoped_variable_, std::forward(new_value))) {} + + AutoReset(AutoReset&& other) + : scoped_variable_(std::exchange(other.scoped_variable_, nullptr)), + original_value_(std::move(other.original_value_)) {} + + AutoReset& operator=(AutoReset&& rhs) { + scoped_variable_ = std::exchange(rhs.scoped_variable_, nullptr); + original_value_ = std::move(rhs.original_value_); + return *this; + } + + ~AutoReset() { + if (scoped_variable_) { + *scoped_variable_ = std::move(original_value_); + } + } + + private: + T* scoped_variable_; + T original_value_; +}; + +} // namespace base + +#endif // !USING_CHROMIUM_INCLUDES + +#endif // CEF_INCLUDE_BASE_CEF_AUTO_RESET_H_ diff --git a/src/include/base/cef_bind.h b/src/include/base/cef_bind.h index 77c9c5573..e879b5694 100644 --- a/src/include/base/cef_bind.h +++ b/src/include/base/cef_bind.h @@ -28,546 +28,361 @@ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +/// +/// \file +/// base::BindOnce() and base::BindRepeating() are helpers for creating +/// base::OnceCallback and base::RepeatingCallback objects respectively. +/// +/// For a runnable object of n-arity, the base::Bind*() family allows partial +/// application of the first m arguments. The remaining n - m arguments must be +/// passed when invoking the callback with Run(). +/// +///
+///   // The first argument is bound at callback creation; the remaining
+///   // two must be passed when calling Run() on the callback object.
+///   base::OnceCallback cb = base::BindOnce(
+///       [](short x, int y, long z) { return x * y * z; }, 42);
+/// 
+/// +/// When binding to a method, the receiver object must also be specified at +/// callback creation time. When Run() is invoked, the method will be invoked on +/// the specified receiver object. +/// +///
+///   class C : public base::RefCounted { void F(); };
+///   auto instance = base::MakeRefCounted();
+///   auto cb = base::BindOnce(&C::F, instance);
+///   std::move(cb).Run();  // Identical to instance->F()
+/// 
+/// +/// See https://chromium.googlesource.com/chromium/src/+/lkgr/docs/callback.md +/// for the full documentation. +/// + +// Implementation notes +// +// If you're reading the implementation, before proceeding further, you should +// read the top comment of base/internal/cef_bind_internal.h for a definition +// of common terms and concepts. + #ifndef CEF_INCLUDE_BASE_CEF_BIND_H_ #define CEF_INCLUDE_BASE_CEF_BIND_H_ #pragma once -#if defined(BASE_BIND_H_) -// Do nothing if the Chromium header has already been included. -// This can happen in cases where Chromium code is used directly by the -// client application. When using Chromium code directly always include -// the Chromium header first to avoid type conflicts. -#elif defined(USING_CHROMIUM_INCLUDES) +#if defined(USING_CHROMIUM_INCLUDES) // When building CEF include the Chromium header directly. -#include "base/bind.h" +#include "base/functional/bind.h" #else // !USING_CHROMIUM_INCLUDES // The following is substantially similar to the Chromium implementation. // If the Chromium implementation diverges the below implementation should be // updated to match. +#include +#include +#include +#include + +#include "include/base/cef_build.h" +#include "include/base/cef_compiler_specific.h" #include "include/base/internal/cef_bind_internal.h" -#include "include/base/internal/cef_callback_internal.h" -// ----------------------------------------------------------------------------- -// Usage documentation -// ----------------------------------------------------------------------------- -// -// See base/cef_callback.h for documentation. -// -// -// ----------------------------------------------------------------------------- -// Implementation notes -// ----------------------------------------------------------------------------- -// -// If you're reading the implementation, before proceeding further, you should -// read the top comment of base/bind_internal.h for a definition of common -// terms and concepts. -// -// RETURN TYPES -// -// Though Bind()'s result is meant to be stored in a Callback<> type, it -// cannot actually return the exact type without requiring a large amount -// of extra template specializations. The problem is that in order to -// discern the correct specialization of Callback<>, Bind would need to -// unwrap the function signature to determine the signature's arity, and -// whether or not it is a method. -// -// Each unique combination of (arity, function_type, num_prebound) where -// function_type is one of {function, method, const_method} would require -// one specialization. We eventually have to do a similar number of -// specializations anyways in the implementation (see the Invoker<>, -// classes). However, it is avoidable in Bind if we return the result -// via an indirection like we do below. -// -// TODO(ajwong): We might be able to avoid this now, but need to test. -// -// It is possible to move most of the COMPILE_ASSERT asserts into BindState<>, -// but it feels a little nicer to have the asserts here so people do not -// need to crack open bind_internal.h. On the other hand, it makes Bind() -// harder to read. +#if defined(OS_APPLE) && !HAS_FEATURE(objc_arc) +#include "include/base/internal/cef_scoped_block_mac.h" +#endif namespace base { -template -base::Callback::RunnableType, - typename cef_internal::FunctorTraits::RunType, - void()>::UnboundRunType> -Bind(Functor functor) { - // Typedefs for how to store and run the functor. - typedef - typename cef_internal::FunctorTraits::RunnableType RunnableType; - typedef typename cef_internal::FunctorTraits::RunType RunType; - - typedef cef_internal::BindState BindState; - - return Callback( - new BindState(cef_internal::MakeRunnable(functor))); +/// +/// Bind as OnceCallback. +/// +template +inline OnceCallback> +BindOnce(Functor&& functor, Args&&... args) { + static_assert(!cef_internal::IsOnceCallback>() || + (std::is_rvalue_reference() && + !std::is_const>()), + "BindOnce requires non-const rvalue for OnceCallback binding." + " I.e.: base::BindOnce(std::move(callback))."); + static_assert( + std::conjunction>...>::value, + "Use std::move() instead of base::Passed() with base::BindOnce()"); + + return cef_internal::BindImpl(std::forward(functor), + std::forward(args)...); } -template -base::Callback::RunnableType, - typename cef_internal::FunctorTraits::RunType, - void(typename cef_internal::CallbackParamTraits::StorageType)>:: - UnboundRunType> -Bind(Functor functor, const P1& p1) { - // Typedefs for how to store and run the functor. - typedef - typename cef_internal::FunctorTraits::RunnableType RunnableType; - typedef typename cef_internal::FunctorTraits::RunType RunType; - - // Use RunnableType::RunType instead of RunType above because our - // checks should below for bound references need to know what the actual - // functor is going to interpret the argument as. - typedef cef_internal::FunctionTraits - BoundFunctorTraits; - - // Do not allow binding a non-const reference parameter. Non-const reference - // parameters are disallowed by the Google style guide. Also, binding a - // non-const reference parameter can make for subtle bugs because the - // invoked function will receive a reference to the stored copy of the - // argument and not the original. - COMPILE_ASSERT( - !(is_non_const_reference::value), - do_not_bind_functions_with_nonconst_ref); - - // For methods, we need to be careful for parameter 1. We do not require - // a scoped_refptr because BindState<> itself takes care of AddRef() for - // methods. We also disallow binding of an array as the method's target - // object. - COMPILE_ASSERT(cef_internal::HasIsMethodTag::value || - !cef_internal::NeedsScopedRefptrButGetsRawPtr::value, - p1_is_refcounted_type_and_needs_scoped_refptr); - COMPILE_ASSERT(!cef_internal::HasIsMethodTag::value || - !is_array::value, - first_bound_argument_to_method_cannot_be_array); - typedef cef_internal::BindState< - RunnableType, RunType, - void(typename cef_internal::CallbackParamTraits::StorageType)> - BindState; - - return Callback( - new BindState(cef_internal::MakeRunnable(functor), p1)); +/// +/// Bind as RepeatingCallback. +/// +template +inline RepeatingCallback> +BindRepeating(Functor&& functor, Args&&... args) { + static_assert( + !cef_internal::IsOnceCallback>(), + "BindRepeating cannot bind OnceCallback. Use BindOnce with std::move()."); + + return cef_internal::BindImpl( + std::forward(functor), std::forward(args)...); } -template -base::Callback::RunnableType, - typename cef_internal::FunctorTraits::RunType, - void(typename cef_internal::CallbackParamTraits::StorageType, - typename cef_internal::CallbackParamTraits::StorageType)>:: - UnboundRunType> -Bind(Functor functor, const P1& p1, const P2& p2) { - // Typedefs for how to store and run the functor. - typedef - typename cef_internal::FunctorTraits::RunnableType RunnableType; - typedef typename cef_internal::FunctorTraits::RunType RunType; - - // Use RunnableType::RunType instead of RunType above because our - // checks should below for bound references need to know what the actual - // functor is going to interpret the argument as. - typedef cef_internal::FunctionTraits - BoundFunctorTraits; - - // Do not allow binding a non-const reference parameter. Non-const reference - // parameters are disallowed by the Google style guide. Also, binding a - // non-const reference parameter can make for subtle bugs because the - // invoked function will receive a reference to the stored copy of the - // argument and not the original. - COMPILE_ASSERT( - !(is_non_const_reference::value || - is_non_const_reference::value), - do_not_bind_functions_with_nonconst_ref); - - // For methods, we need to be careful for parameter 1. We do not require - // a scoped_refptr because BindState<> itself takes care of AddRef() for - // methods. We also disallow binding of an array as the method's target - // object. - COMPILE_ASSERT(cef_internal::HasIsMethodTag::value || - !cef_internal::NeedsScopedRefptrButGetsRawPtr::value, - p1_is_refcounted_type_and_needs_scoped_refptr); - COMPILE_ASSERT(!cef_internal::HasIsMethodTag::value || - !is_array::value, - first_bound_argument_to_method_cannot_be_array); - COMPILE_ASSERT(!cef_internal::NeedsScopedRefptrButGetsRawPtr::value, - p2_is_refcounted_type_and_needs_scoped_refptr); - typedef cef_internal::BindState< - RunnableType, RunType, - void(typename cef_internal::CallbackParamTraits::StorageType, - typename cef_internal::CallbackParamTraits::StorageType)> - BindState; - - return Callback( - new BindState(cef_internal::MakeRunnable(functor), p1, p2)); +/// +/// Special cases for binding to a base::Callback without extra bound arguments. +/// We CHECK() the validity of callback to guard against null pointers +/// accidentally ending up in posted tasks, causing hard-to-debug crashes. +/// +template +OnceCallback BindOnce(OnceCallback callback) { + CHECK(callback); + return callback; } -template -base::Callback::RunnableType, - typename cef_internal::FunctorTraits::RunType, - void(typename cef_internal::CallbackParamTraits::StorageType, - typename cef_internal::CallbackParamTraits::StorageType, - typename cef_internal::CallbackParamTraits::StorageType)>:: - UnboundRunType> -Bind(Functor functor, const P1& p1, const P2& p2, const P3& p3) { - // Typedefs for how to store and run the functor. - typedef - typename cef_internal::FunctorTraits::RunnableType RunnableType; - typedef typename cef_internal::FunctorTraits::RunType RunType; - - // Use RunnableType::RunType instead of RunType above because our - // checks should below for bound references need to know what the actual - // functor is going to interpret the argument as. - typedef cef_internal::FunctionTraits - BoundFunctorTraits; - - // Do not allow binding a non-const reference parameter. Non-const reference - // parameters are disallowed by the Google style guide. Also, binding a - // non-const reference parameter can make for subtle bugs because the - // invoked function will receive a reference to the stored copy of the - // argument and not the original. - COMPILE_ASSERT( - !(is_non_const_reference::value || - is_non_const_reference::value || - is_non_const_reference::value), - do_not_bind_functions_with_nonconst_ref); - - // For methods, we need to be careful for parameter 1. We do not require - // a scoped_refptr because BindState<> itself takes care of AddRef() for - // methods. We also disallow binding of an array as the method's target - // object. - COMPILE_ASSERT(cef_internal::HasIsMethodTag::value || - !cef_internal::NeedsScopedRefptrButGetsRawPtr::value, - p1_is_refcounted_type_and_needs_scoped_refptr); - COMPILE_ASSERT(!cef_internal::HasIsMethodTag::value || - !is_array::value, - first_bound_argument_to_method_cannot_be_array); - COMPILE_ASSERT(!cef_internal::NeedsScopedRefptrButGetsRawPtr::value, - p2_is_refcounted_type_and_needs_scoped_refptr); - COMPILE_ASSERT(!cef_internal::NeedsScopedRefptrButGetsRawPtr::value, - p3_is_refcounted_type_and_needs_scoped_refptr); - typedef cef_internal::BindState< - RunnableType, RunType, - void(typename cef_internal::CallbackParamTraits::StorageType, - typename cef_internal::CallbackParamTraits::StorageType, - typename cef_internal::CallbackParamTraits::StorageType)> - BindState; - - return Callback( - new BindState(cef_internal::MakeRunnable(functor), p1, p2, p3)); +template +OnceCallback BindOnce(RepeatingCallback callback) { + CHECK(callback); + return callback; } -template -base::Callback::RunnableType, - typename cef_internal::FunctorTraits::RunType, - void(typename cef_internal::CallbackParamTraits::StorageType, - typename cef_internal::CallbackParamTraits::StorageType, - typename cef_internal::CallbackParamTraits::StorageType, - typename cef_internal::CallbackParamTraits::StorageType)>:: - UnboundRunType> -Bind(Functor functor, const P1& p1, const P2& p2, const P3& p3, const P4& p4) { - // Typedefs for how to store and run the functor. - typedef - typename cef_internal::FunctorTraits::RunnableType RunnableType; - typedef typename cef_internal::FunctorTraits::RunType RunType; - - // Use RunnableType::RunType instead of RunType above because our - // checks should below for bound references need to know what the actual - // functor is going to interpret the argument as. - typedef cef_internal::FunctionTraits - BoundFunctorTraits; - - // Do not allow binding a non-const reference parameter. Non-const reference - // parameters are disallowed by the Google style guide. Also, binding a - // non-const reference parameter can make for subtle bugs because the - // invoked function will receive a reference to the stored copy of the - // argument and not the original. - COMPILE_ASSERT( - !(is_non_const_reference::value || - is_non_const_reference::value || - is_non_const_reference::value || - is_non_const_reference::value), - do_not_bind_functions_with_nonconst_ref); - - // For methods, we need to be careful for parameter 1. We do not require - // a scoped_refptr because BindState<> itself takes care of AddRef() for - // methods. We also disallow binding of an array as the method's target - // object. - COMPILE_ASSERT(cef_internal::HasIsMethodTag::value || - !cef_internal::NeedsScopedRefptrButGetsRawPtr::value, - p1_is_refcounted_type_and_needs_scoped_refptr); - COMPILE_ASSERT(!cef_internal::HasIsMethodTag::value || - !is_array::value, - first_bound_argument_to_method_cannot_be_array); - COMPILE_ASSERT(!cef_internal::NeedsScopedRefptrButGetsRawPtr::value, - p2_is_refcounted_type_and_needs_scoped_refptr); - COMPILE_ASSERT(!cef_internal::NeedsScopedRefptrButGetsRawPtr::value, - p3_is_refcounted_type_and_needs_scoped_refptr); - COMPILE_ASSERT(!cef_internal::NeedsScopedRefptrButGetsRawPtr::value, - p4_is_refcounted_type_and_needs_scoped_refptr); - typedef cef_internal::BindState< - RunnableType, RunType, - void(typename cef_internal::CallbackParamTraits::StorageType, - typename cef_internal::CallbackParamTraits::StorageType, - typename cef_internal::CallbackParamTraits::StorageType, - typename cef_internal::CallbackParamTraits::StorageType)> - BindState; - - return Callback( - new BindState(cef_internal::MakeRunnable(functor), p1, p2, p3, p4)); +template +RepeatingCallback BindRepeating( + RepeatingCallback callback) { + CHECK(callback); + return callback; } -template -base::Callback::RunnableType, - typename cef_internal::FunctorTraits::RunType, - void(typename cef_internal::CallbackParamTraits::StorageType, - typename cef_internal::CallbackParamTraits::StorageType, - typename cef_internal::CallbackParamTraits::StorageType, - typename cef_internal::CallbackParamTraits::StorageType, - typename cef_internal::CallbackParamTraits::StorageType)>:: - UnboundRunType> -Bind(Functor functor, - const P1& p1, - const P2& p2, - const P3& p3, - const P4& p4, - const P5& p5) { - // Typedefs for how to store and run the functor. - typedef - typename cef_internal::FunctorTraits::RunnableType RunnableType; - typedef typename cef_internal::FunctorTraits::RunType RunType; - - // Use RunnableType::RunType instead of RunType above because our - // checks should below for bound references need to know what the actual - // functor is going to interpret the argument as. - typedef cef_internal::FunctionTraits - BoundFunctorTraits; - - // Do not allow binding a non-const reference parameter. Non-const reference - // parameters are disallowed by the Google style guide. Also, binding a - // non-const reference parameter can make for subtle bugs because the - // invoked function will receive a reference to the stored copy of the - // argument and not the original. - COMPILE_ASSERT( - !(is_non_const_reference::value || - is_non_const_reference::value || - is_non_const_reference::value || - is_non_const_reference::value || - is_non_const_reference::value), - do_not_bind_functions_with_nonconst_ref); - - // For methods, we need to be careful for parameter 1. We do not require - // a scoped_refptr because BindState<> itself takes care of AddRef() for - // methods. We also disallow binding of an array as the method's target - // object. - COMPILE_ASSERT(cef_internal::HasIsMethodTag::value || - !cef_internal::NeedsScopedRefptrButGetsRawPtr::value, - p1_is_refcounted_type_and_needs_scoped_refptr); - COMPILE_ASSERT(!cef_internal::HasIsMethodTag::value || - !is_array::value, - first_bound_argument_to_method_cannot_be_array); - COMPILE_ASSERT(!cef_internal::NeedsScopedRefptrButGetsRawPtr::value, - p2_is_refcounted_type_and_needs_scoped_refptr); - COMPILE_ASSERT(!cef_internal::NeedsScopedRefptrButGetsRawPtr::value, - p3_is_refcounted_type_and_needs_scoped_refptr); - COMPILE_ASSERT(!cef_internal::NeedsScopedRefptrButGetsRawPtr::value, - p4_is_refcounted_type_and_needs_scoped_refptr); - COMPILE_ASSERT(!cef_internal::NeedsScopedRefptrButGetsRawPtr::value, - p5_is_refcounted_type_and_needs_scoped_refptr); - typedef cef_internal::BindState< - RunnableType, RunType, - void(typename cef_internal::CallbackParamTraits::StorageType, - typename cef_internal::CallbackParamTraits::StorageType, - typename cef_internal::CallbackParamTraits::StorageType, - typename cef_internal::CallbackParamTraits::StorageType, - typename cef_internal::CallbackParamTraits::StorageType)> - BindState; - - return Callback( - new BindState(cef_internal::MakeRunnable(functor), p1, p2, p3, p4, p5)); +/// +/// Unretained() allows binding a non-refcounted class, and to disable +/// refcounting on arguments that are refcounted objects. +/// +/// EXAMPLE OF Unretained(): +/// +///
+///   class Foo {
+///    public:
+///     void func() { cout << "Foo:f" << endl; }
+///   };
+///
+///   // In some function somewhere.
+///   Foo foo;
+///   OnceClosure foo_callback =
+///       BindOnce(&Foo::func, Unretained(&foo));
+///   std::move(foo_callback).Run();  // Prints "Foo:f".
+/// 
+/// +/// Without the Unretained() wrapper on |&foo|, the above call would fail +/// to compile because Foo does not support the AddRef() and Release() methods. +/// +template +inline cef_internal::UnretainedWrapper Unretained(T* o) { + return cef_internal::UnretainedWrapper(o); } -template -base::Callback::RunnableType, - typename cef_internal::FunctorTraits::RunType, - void(typename cef_internal::CallbackParamTraits::StorageType, - typename cef_internal::CallbackParamTraits::StorageType, - typename cef_internal::CallbackParamTraits::StorageType, - typename cef_internal::CallbackParamTraits::StorageType, - typename cef_internal::CallbackParamTraits::StorageType, - typename cef_internal::CallbackParamTraits::StorageType)>:: - UnboundRunType> -Bind(Functor functor, - const P1& p1, - const P2& p2, - const P3& p3, - const P4& p4, - const P5& p5, - const P6& p6) { - // Typedefs for how to store and run the functor. - typedef - typename cef_internal::FunctorTraits::RunnableType RunnableType; - typedef typename cef_internal::FunctorTraits::RunType RunType; - - // Use RunnableType::RunType instead of RunType above because our - // checks should below for bound references need to know what the actual - // functor is going to interpret the argument as. - typedef cef_internal::FunctionTraits - BoundFunctorTraits; - - // Do not allow binding a non-const reference parameter. Non-const reference - // parameters are disallowed by the Google style guide. Also, binding a - // non-const reference parameter can make for subtle bugs because the - // invoked function will receive a reference to the stored copy of the - // argument and not the original. - COMPILE_ASSERT( - !(is_non_const_reference::value || - is_non_const_reference::value || - is_non_const_reference::value || - is_non_const_reference::value || - is_non_const_reference::value || - is_non_const_reference::value), - do_not_bind_functions_with_nonconst_ref); - - // For methods, we need to be careful for parameter 1. We do not require - // a scoped_refptr because BindState<> itself takes care of AddRef() for - // methods. We also disallow binding of an array as the method's target - // object. - COMPILE_ASSERT(cef_internal::HasIsMethodTag::value || - !cef_internal::NeedsScopedRefptrButGetsRawPtr::value, - p1_is_refcounted_type_and_needs_scoped_refptr); - COMPILE_ASSERT(!cef_internal::HasIsMethodTag::value || - !is_array::value, - first_bound_argument_to_method_cannot_be_array); - COMPILE_ASSERT(!cef_internal::NeedsScopedRefptrButGetsRawPtr::value, - p2_is_refcounted_type_and_needs_scoped_refptr); - COMPILE_ASSERT(!cef_internal::NeedsScopedRefptrButGetsRawPtr::value, - p3_is_refcounted_type_and_needs_scoped_refptr); - COMPILE_ASSERT(!cef_internal::NeedsScopedRefptrButGetsRawPtr::value, - p4_is_refcounted_type_and_needs_scoped_refptr); - COMPILE_ASSERT(!cef_internal::NeedsScopedRefptrButGetsRawPtr::value, - p5_is_refcounted_type_and_needs_scoped_refptr); - COMPILE_ASSERT(!cef_internal::NeedsScopedRefptrButGetsRawPtr::value, - p6_is_refcounted_type_and_needs_scoped_refptr); - typedef cef_internal::BindState< - RunnableType, RunType, - void(typename cef_internal::CallbackParamTraits::StorageType, - typename cef_internal::CallbackParamTraits::StorageType, - typename cef_internal::CallbackParamTraits::StorageType, - typename cef_internal::CallbackParamTraits::StorageType, - typename cef_internal::CallbackParamTraits::StorageType, - typename cef_internal::CallbackParamTraits::StorageType)> - BindState; +/// +/// RetainedRef() accepts a ref counted object and retains a reference to it. +/// When the callback is called, the object is passed as a raw pointer. +/// +/// EXAMPLE OF RetainedRef(): +/// +///
+///    void foo(RefCountedBytes* bytes) {}
+///
+///    scoped_refptr bytes = ...;
+///    OnceClosure callback = BindOnce(&foo, base::RetainedRef(bytes));
+///    std::move(callback).Run();
+/// 
+/// +/// Without RetainedRef, the scoped_refptr would try to implicitly convert to +/// a raw pointer and fail compilation: +/// +///
+///    OnceClosure callback = BindOnce(&foo, bytes); // ERROR!
+/// 
+/// +template +inline cef_internal::RetainedRefWrapper RetainedRef(T* o) { + return cef_internal::RetainedRefWrapper(o); +} +template +inline cef_internal::RetainedRefWrapper RetainedRef(scoped_refptr o) { + return cef_internal::RetainedRefWrapper(std::move(o)); +} - return Callback(new BindState( - cef_internal::MakeRunnable(functor), p1, p2, p3, p4, p5, p6)); +/// +/// Owned() transfers ownership of an object to the callback resulting from +/// bind; the object will be deleted when the callback is deleted. +/// +/// EXAMPLE OF Owned(): +/// +///
+///   void foo(int* arg) { cout << *arg << endl }
+///
+///   int* pn = new int(1);
+///   RepeatingClosure foo_callback = BindRepeating(&foo, Owned(pn));
+///
+///   foo_callback.Run();  // Prints "1"
+///   foo_callback.Run();  // Prints "1"
+///   *pn = 2;
+///   foo_callback.Run();  // Prints "2"
+///
+///   foo_callback.Reset();  // |pn| is deleted.  Also will happen when
+///                          // |foo_callback| goes out of scope.
+/// 
+/// +/// Without Owned(), someone would have to know to delete |pn| when the last +/// reference to the callback is deleted. +/// +template +inline cef_internal::OwnedWrapper Owned(T* o) { + return cef_internal::OwnedWrapper(o); } -template -base::Callback::RunnableType, - typename cef_internal::FunctorTraits::RunType, - void(typename cef_internal::CallbackParamTraits::StorageType, - typename cef_internal::CallbackParamTraits::StorageType, - typename cef_internal::CallbackParamTraits::StorageType, - typename cef_internal::CallbackParamTraits::StorageType, - typename cef_internal::CallbackParamTraits::StorageType, - typename cef_internal::CallbackParamTraits::StorageType, - typename cef_internal::CallbackParamTraits::StorageType)>:: - UnboundRunType> -Bind(Functor functor, - const P1& p1, - const P2& p2, - const P3& p3, - const P4& p4, - const P5& p5, - const P6& p6, - const P7& p7) { - // Typedefs for how to store and run the functor. - typedef - typename cef_internal::FunctorTraits::RunnableType RunnableType; - typedef typename cef_internal::FunctorTraits::RunType RunType; +template +inline cef_internal::OwnedWrapper Owned( + std::unique_ptr&& ptr) { + return cef_internal::OwnedWrapper(std::move(ptr)); +} - // Use RunnableType::RunType instead of RunType above because our - // checks should below for bound references need to know what the actual - // functor is going to interpret the argument as. - typedef cef_internal::FunctionTraits - BoundFunctorTraits; +/// +/// OwnedRef() stores an object in the callback resulting from +/// bind and passes a reference to the object to the bound function. +/// +/// EXAMPLE OF OwnedRef(): +/// +///
+///   void foo(int& arg) { cout << ++arg << endl }
+///
+///   int counter = 0;
+///   RepeatingClosure foo_callback = BindRepeating(&foo, OwnedRef(counter));
+///
+///   foo_callback.Run();  // Prints "1"
+///   foo_callback.Run();  // Prints "2"
+///   foo_callback.Run();  // Prints "3"
+///
+///   cout << counter;     // Prints "0", OwnedRef creates a copy of counter.
+/// 
+/// +/// Supports OnceCallbacks as well, useful to pass placeholder arguments: +/// +///
+///   void bar(int& ignore, const std::string& s) { cout << s << endl }
+///
+///   OnceClosure bar_callback = BindOnce(&bar, OwnedRef(0), "Hello");
+///
+///   std::move(bar_callback).Run(); // Prints "Hello"
+/// 
+/// +/// Without OwnedRef() it would not be possible to pass a mutable reference to +/// an object owned by the callback. +/// +template +cef_internal::OwnedRefWrapper> OwnedRef(T&& t) { + return cef_internal::OwnedRefWrapper>(std::forward(t)); +} - // Do not allow binding a non-const reference parameter. Non-const reference - // parameters are disallowed by the Google style guide. Also, binding a - // non-const reference parameter can make for subtle bugs because the - // invoked function will receive a reference to the stored copy of the - // argument and not the original. - COMPILE_ASSERT( - !(is_non_const_reference::value || - is_non_const_reference::value || - is_non_const_reference::value || - is_non_const_reference::value || - is_non_const_reference::value || - is_non_const_reference::value || - is_non_const_reference::value), - do_not_bind_functions_with_nonconst_ref); +/// +/// Passed() is for transferring movable-but-not-copyable types (eg. unique_ptr) +/// through a RepeatingCallback. Logically, this signifies a destructive +/// transfer of the state of the argument into the target function. Invoking +/// RepeatingCallback::Run() twice on a callback that was created with a +/// Passed() argument will CHECK() because the first invocation would have +/// already transferred ownership to the target function. +/// +/// Note that Passed() is not necessary with BindOnce(), as std::move() does the +/// same thing. Avoid Passed() in favor of std::move() with BindOnce(). +/// +/// EXAMPLE OF Passed(): +/// +///
+///   void TakesOwnership(std::unique_ptr arg) { }
+///   std::unique_ptr CreateFoo() { return std::make_unique();
+///   }
+///
+///   auto f = std::make_unique();
+///
+///   // |cb| is given ownership of Foo(). |f| is now NULL.
+///   // You can use std::move(f) in place of &f, but it's more verbose.
+///   RepeatingClosure cb = BindRepeating(&TakesOwnership, Passed(&f));
+///
+///   // Run was never called so |cb| still owns Foo() and deletes
+///   // it on Reset().
+///   cb.Reset();
+///
+///   // |cb| is given a new Foo created by CreateFoo().
+///   cb = BindRepeating(&TakesOwnership, Passed(CreateFoo()));
+///
+///   // |arg| in TakesOwnership() is given ownership of Foo(). |cb|
+///   // no longer owns Foo() and, if reset, would not delete Foo().
+///   cb.Run();  // Foo() is now transferred to |arg| and deleted.
+///   cb.Run();  // This CHECK()s since Foo() already been used once.
+/// 
+/// +/// We offer 2 syntaxes for calling Passed(). The first takes an rvalue and is +/// best suited for use with the return value of a function or other temporary +/// rvalues. The second takes a pointer to the scoper and is just syntactic +/// sugar to avoid having to write Passed(std::move(scoper)). +/// +/// Both versions of Passed() prevent T from being an lvalue reference. The +/// first via use of enable_if, and the second takes a T* which will not bind to +/// T&. +/// +template ::value>* = nullptr> +inline cef_internal::PassedWrapper Passed(T&& scoper) { + return cef_internal::PassedWrapper(std::move(scoper)); +} +template +inline cef_internal::PassedWrapper Passed(T* scoper) { + return cef_internal::PassedWrapper(std::move(*scoper)); +} - // For methods, we need to be careful for parameter 1. We do not require - // a scoped_refptr because BindState<> itself takes care of AddRef() for - // methods. We also disallow binding of an array as the method's target - // object. - COMPILE_ASSERT(cef_internal::HasIsMethodTag::value || - !cef_internal::NeedsScopedRefptrButGetsRawPtr::value, - p1_is_refcounted_type_and_needs_scoped_refptr); - COMPILE_ASSERT(!cef_internal::HasIsMethodTag::value || - !is_array::value, - first_bound_argument_to_method_cannot_be_array); - COMPILE_ASSERT(!cef_internal::NeedsScopedRefptrButGetsRawPtr::value, - p2_is_refcounted_type_and_needs_scoped_refptr); - COMPILE_ASSERT(!cef_internal::NeedsScopedRefptrButGetsRawPtr::value, - p3_is_refcounted_type_and_needs_scoped_refptr); - COMPILE_ASSERT(!cef_internal::NeedsScopedRefptrButGetsRawPtr::value, - p4_is_refcounted_type_and_needs_scoped_refptr); - COMPILE_ASSERT(!cef_internal::NeedsScopedRefptrButGetsRawPtr::value, - p5_is_refcounted_type_and_needs_scoped_refptr); - COMPILE_ASSERT(!cef_internal::NeedsScopedRefptrButGetsRawPtr::value, - p6_is_refcounted_type_and_needs_scoped_refptr); - COMPILE_ASSERT(!cef_internal::NeedsScopedRefptrButGetsRawPtr::value, - p7_is_refcounted_type_and_needs_scoped_refptr); - typedef cef_internal::BindState< - RunnableType, RunType, - void(typename cef_internal::CallbackParamTraits::StorageType, - typename cef_internal::CallbackParamTraits::StorageType, - typename cef_internal::CallbackParamTraits::StorageType, - typename cef_internal::CallbackParamTraits::StorageType, - typename cef_internal::CallbackParamTraits::StorageType, - typename cef_internal::CallbackParamTraits::StorageType, - typename cef_internal::CallbackParamTraits::StorageType)> - BindState; +/// +/// IgnoreResult() is used to adapt a function or callback with a return type to +/// one with a void return. This is most useful if you have a function with, +/// say, a pesky ignorable bool return that you want to use with PostTask or +/// something else that expect a callback with a void return. +/// +/// EXAMPLE OF IgnoreResult(): +/// +///
+///   int DoSomething(int arg) { cout << arg << endl; }
+///
+///   // Assign to a callback with a void return type.
+///   OnceCallback cb = BindOnce(IgnoreResult(&DoSomething));
+///   std::move(cb).Run(1);  // Prints "1".
+///
+///   // Prints "2" on |ml|.
+///   ml->PostTask(FROM_HERE, BindOnce(IgnoreResult(&DoSomething), 2);
+/// 
+/// +template +inline cef_internal::IgnoreResultHelper IgnoreResult(T data) { + return cef_internal::IgnoreResultHelper(std::move(data)); +} - return Callback(new BindState( - cef_internal::MakeRunnable(functor), p1, p2, p3, p4, p5, p6, p7)); +#if defined(OS_APPLE) && !HAS_FEATURE(objc_arc) + +/// +/// RetainBlock() is used to adapt an Objective-C block when Automated Reference +/// Counting (ARC) is disabled. This is unnecessary when ARC is enabled, as the +/// BindOnce and BindRepeating already support blocks then. +/// +/// EXAMPLE OF RetainBlock(): +/// +///
+///   // Wrap the block and bind it to a callback.
+///   OnceCallback cb =
+///       BindOnce(RetainBlock(^(int n) { NSLog(@"%d", n); }));
+///   std::move(cb).Run(1);  // Logs "1".
+/// 
+/// +template +base::mac::ScopedBlock RetainBlock(R (^block)(Args...)) { + return base::mac::ScopedBlock(block, + base::scoped_policy::RETAIN); } +#endif // defined(OS_APPLE) && !HAS_FEATURE(objc_arc) + } // namespace base #endif // !USING_CHROMIUM_INCLUDES diff --git a/src/include/base/cef_bind_helpers.h b/src/include/base/cef_bind_helpers.h deleted file mode 100644 index 2b4798b2c..000000000 --- a/src/include/base/cef_bind_helpers.h +++ /dev/null @@ -1,579 +0,0 @@ -// Copyright (c) 2014 Marshall A. Greenblatt. Portions copyright (c) 2011 -// Google Inc. All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the name Chromium Embedded -// Framework nor the names of its contributors may be used to endorse -// or promote products derived from this software without specific prior -// written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// This defines a set of argument wrappers and related factory methods that -// can be used specify the refcounting and reference semantics of arguments -// that are bound by the Bind() function in base/bind.h. -// -// It also defines a set of simple functions and utilities that people want -// when using Callback<> and Bind(). -// -// -// ARGUMENT BINDING WRAPPERS -// -// The wrapper functions are base::Unretained(), base::Owned(), base::Passed(), -// base::ConstRef(), and base::IgnoreResult(). -// -// Unretained() allows Bind() to bind a non-refcounted class, and to disable -// refcounting on arguments that are refcounted objects. -// -// Owned() transfers ownership of an object to the Callback resulting from -// bind; the object will be deleted when the Callback is deleted. -// -// Passed() is for transferring movable-but-not-copyable types (eg. scoped_ptr) -// through a Callback. Logically, this signifies a destructive transfer of -// the state of the argument into the target function. Invoking -// Callback::Run() twice on a Callback that was created with a Passed() -// argument will CHECK() because the first invocation would have already -// transferred ownership to the target function. -// -// ConstRef() allows binding a constant reference to an argument rather -// than a copy. -// -// IgnoreResult() is used to adapt a function or Callback with a return type to -// one with a void return. This is most useful if you have a function with, -// say, a pesky ignorable bool return that you want to use with PostTask or -// something else that expect a Callback with a void return. -// -// EXAMPLE OF Unretained(): -// -// class Foo { -// public: -// void func() { cout << "Foo:f" << endl; } -// }; -// -// // In some function somewhere. -// Foo foo; -// Closure foo_callback = -// Bind(&Foo::func, Unretained(&foo)); -// foo_callback.Run(); // Prints "Foo:f". -// -// Without the Unretained() wrapper on |&foo|, the above call would fail -// to compile because Foo does not support the AddRef() and Release() methods. -// -// -// EXAMPLE OF Owned(): -// -// void foo(int* arg) { cout << *arg << endl } -// -// int* pn = new int(1); -// Closure foo_callback = Bind(&foo, Owned(pn)); -// -// foo_callback.Run(); // Prints "1" -// foo_callback.Run(); // Prints "1" -// *n = 2; -// foo_callback.Run(); // Prints "2" -// -// foo_callback.Reset(); // |pn| is deleted. Also will happen when -// // |foo_callback| goes out of scope. -// -// Without Owned(), someone would have to know to delete |pn| when the last -// reference to the Callback is deleted. -// -// -// EXAMPLE OF ConstRef(): -// -// void foo(int arg) { cout << arg << endl } -// -// int n = 1; -// Closure no_ref = Bind(&foo, n); -// Closure has_ref = Bind(&foo, ConstRef(n)); -// -// no_ref.Run(); // Prints "1" -// has_ref.Run(); // Prints "1" -// -// n = 2; -// no_ref.Run(); // Prints "1" -// has_ref.Run(); // Prints "2" -// -// Note that because ConstRef() takes a reference on |n|, |n| must outlive all -// its bound callbacks. -// -// -// EXAMPLE OF IgnoreResult(): -// -// int DoSomething(int arg) { cout << arg << endl; } -// -// // Assign to a Callback with a void return type. -// Callback cb = Bind(IgnoreResult(&DoSomething)); -// cb->Run(1); // Prints "1". -// -// // Prints "1" on |ml|. -// ml->PostTask(FROM_HERE, Bind(IgnoreResult(&DoSomething), 1); -// -// -// EXAMPLE OF Passed(): -// -// void TakesOwnership(scoped_ptr arg) { } -// scoped_ptr CreateFoo() { return scoped_ptr(new Foo()); } -// -// scoped_ptr f(new Foo()); -// -// // |cb| is given ownership of Foo(). |f| is now NULL. -// // You can use f.Pass() in place of &f, but it's more verbose. -// Closure cb = Bind(&TakesOwnership, Passed(&f)); -// -// // Run was never called so |cb| still owns Foo() and deletes -// // it on Reset(). -// cb.Reset(); -// -// // |cb| is given a new Foo created by CreateFoo(). -// cb = Bind(&TakesOwnership, Passed(CreateFoo())); -// -// // |arg| in TakesOwnership() is given ownership of Foo(). |cb| -// // no longer owns Foo() and, if reset, would not delete Foo(). -// cb.Run(); // Foo() is now transferred to |arg| and deleted. -// cb.Run(); // This CHECK()s since Foo() already been used once. -// -// Passed() is particularly useful with PostTask() when you are transferring -// ownership of an argument into a task, but don't necessarily know if the -// task will always be executed. This can happen if the task is cancellable -// or if it is posted to a MessageLoopProxy. -// -// -// SIMPLE FUNCTIONS AND UTILITIES. -// -// DoNothing() - Useful for creating a Closure that does nothing when called. -// DeletePointer() - Useful for creating a Closure that will delete a -// pointer when invoked. Only use this when necessary. -// In most cases MessageLoop::DeleteSoon() is a better -// fit. - -#ifndef CEF_INCLUDE_BASE_CEF_BIND_HELPERS_H_ -#define CEF_INCLUDE_BASE_CEF_BIND_HELPERS_H_ -#pragma once - -#if defined(BASE_BIND_HELPERS_H_) -// Do nothing if the Chromium header has already been included. -// This can happen in cases where Chromium code is used directly by the -// client application. When using Chromium code directly always include -// the Chromium header first to avoid type conflicts. -#elif defined(USING_CHROMIUM_INCLUDES) -// When building CEF include the Chromium header directly. -#include "base/bind_helpers.h" -#else // !USING_CHROMIUM_INCLUDES -// The following is substantially similar to the Chromium implementation. -// If the Chromium implementation diverges the below implementation should be -// updated to match. - -#include "include/base/cef_basictypes.h" -#include "include/base/cef_callback.h" -#include "include/base/cef_template_util.h" -#include "include/base/cef_weak_ptr.h" - -namespace base { -namespace cef_internal { - -// Use the Substitution Failure Is Not An Error (SFINAE) trick to inspect T -// for the existence of AddRef() and Release() functions of the correct -// signature. -// -// http://en.wikipedia.org/wiki/Substitution_failure_is_not_an_error -// http://stackoverflow.com/questions/257288/is-it-possible-to-write-a-c-template-to-check-for-a-functions-existence -// http://stackoverflow.com/questions/4358584/sfinae-approach-comparison -// http://stackoverflow.com/questions/1966362/sfinae-to-check-for-inherited-member-functions -// -// The last link in particular show the method used below. -// -// For SFINAE to work with inherited methods, we need to pull some extra tricks -// with multiple inheritance. In the more standard formulation, the overloads -// of Check would be: -// -// template -// Yes NotTheCheckWeWant(Helper<&C::TargetFunc>*); -// -// template -// No NotTheCheckWeWant(...); -// -// static const bool value = sizeof(NotTheCheckWeWant(0)) == sizeof(Yes); -// -// The problem here is that template resolution will not match -// C::TargetFunc if TargetFunc does not exist directly in C. That is, if -// TargetFunc in inherited from an ancestor, &C::TargetFunc will not match, -// |value| will be false. This formulation only checks for whether or -// not TargetFunc exist directly in the class being introspected. -// -// To get around this, we play a dirty trick with multiple inheritance. -// First, We create a class BaseMixin that declares each function that we -// want to probe for. Then we create a class Base that inherits from both T -// (the class we wish to probe) and BaseMixin. Note that the function -// signature in BaseMixin does not need to match the signature of the function -// we are probing for; thus it's easiest to just use void(void). -// -// Now, if TargetFunc exists somewhere in T, then &Base::TargetFunc has an -// ambiguous resolution between BaseMixin and T. This lets us write the -// following: -// -// template -// No GoodCheck(Helper<&C::TargetFunc>*); -// -// template -// Yes GoodCheck(...); -// -// static const bool value = sizeof(GoodCheck(0)) == sizeof(Yes); -// -// Notice here that the variadic version of GoodCheck() returns Yes here -// instead of No like the previous one. Also notice that we calculate |value| -// by specializing GoodCheck() on Base instead of T. -// -// We've reversed the roles of the variadic, and Helper overloads. -// GoodCheck(Helper<&C::TargetFunc>*), when C = Base, fails to be a valid -// substitution if T::TargetFunc exists. Thus GoodCheck(0) will resolve -// to the variadic version if T has TargetFunc. If T::TargetFunc does not -// exist, then &C::TargetFunc is not ambiguous, and the overload resolution -// will prefer GoodCheck(Helper<&C::TargetFunc>*). -// -// This method of SFINAE will correctly probe for inherited names, but it cannot -// typecheck those names. It's still a good enough sanity check though. -// -// Works on gcc-4.2, gcc-4.4, and Visual Studio 2008. -// -// TODO(ajwong): Move to ref_counted.h or template_util.h when we've vetted -// this works well. -// -// TODO(ajwong): Make this check for Release() as well. -// See http://crbug.com/82038. -template -class SupportsAddRefAndRelease { - typedef char Yes[1]; - typedef char No[2]; - - struct BaseMixin { - void AddRef(); - }; - -// MSVC warns when you try to use Base if T has a private destructor, the -// common pattern for refcounted types. It does this even though no attempt to -// instantiate Base is made. We disable the warning for this definition. -#if defined(OS_WIN) -#pragma warning(push) -#pragma warning(disable : 4624) -#endif - struct Base : public T, public BaseMixin {}; -#if defined(OS_WIN) -#pragma warning(pop) -#endif - - template - struct Helper {}; - - template - static No& Check(Helper<&C::AddRef>*); - - template - static Yes& Check(...); - - public: - static const bool value = sizeof(Check(0)) == sizeof(Yes); -}; - -// Helpers to assert that arguments of a recounted type are bound with a -// scoped_refptr. -template -struct UnsafeBindtoRefCountedArgHelper : false_type {}; - -template -struct UnsafeBindtoRefCountedArgHelper - : integral_constant::value> {}; - -template -struct UnsafeBindtoRefCountedArg : false_type {}; - -template -struct UnsafeBindtoRefCountedArg - : UnsafeBindtoRefCountedArgHelper::value, T> {}; - -template -class HasIsMethodTag { - typedef char Yes[1]; - typedef char No[2]; - - template - static Yes& Check(typename U::IsMethod*); - - template - static No& Check(...); - - public: - static const bool value = sizeof(Check(0)) == sizeof(Yes); -}; - -template -class UnretainedWrapper { - public: - explicit UnretainedWrapper(T* o) : ptr_(o) {} - T* get() const { return ptr_; } - - private: - T* ptr_; -}; - -template -class ConstRefWrapper { - public: - explicit ConstRefWrapper(const T& o) : ptr_(&o) {} - const T& get() const { return *ptr_; } - - private: - const T* ptr_; -}; - -template -struct IgnoreResultHelper { - explicit IgnoreResultHelper(T functor) : functor_(functor) {} - - T functor_; -}; - -template -struct IgnoreResultHelper> { - explicit IgnoreResultHelper(const Callback& functor) : functor_(functor) {} - - const Callback& functor_; -}; - -// An alternate implementation is to avoid the destructive copy, and instead -// specialize ParamTraits<> for OwnedWrapper<> to change the StorageType to -// a class that is essentially a scoped_ptr<>. -// -// The current implementation has the benefit though of leaving ParamTraits<> -// fully in callback_internal.h as well as avoiding type conversions during -// storage. -template -class OwnedWrapper { - public: - explicit OwnedWrapper(T* o) : ptr_(o) {} - ~OwnedWrapper() { delete ptr_; } - T* get() const { return ptr_; } - OwnedWrapper(const OwnedWrapper& other) { - ptr_ = other.ptr_; - other.ptr_ = NULL; - } - - private: - mutable T* ptr_; -}; - -// PassedWrapper is a copyable adapter for a scoper that ignores const. -// -// It is needed to get around the fact that Bind() takes a const reference to -// all its arguments. Because Bind() takes a const reference to avoid -// unnecessary copies, it is incompatible with movable-but-not-copyable -// types; doing a destructive "move" of the type into Bind() would violate -// the const correctness. -// -// This conundrum cannot be solved without either C++11 rvalue references or -// a O(2^n) blowup of Bind() templates to handle each combination of regular -// types and movable-but-not-copyable types. Thus we introduce a wrapper type -// that is copyable to transmit the correct type information down into -// BindState<>. Ignoring const in this type makes sense because it is only -// created when we are explicitly trying to do a destructive move. -// -// Two notes: -// 1) PassedWrapper supports any type that has a "Pass()" function. -// This is intentional. The whitelisting of which specific types we -// support is maintained by CallbackParamTraits<>. -// 2) is_valid_ is distinct from NULL because it is valid to bind a "NULL" -// scoper to a Callback and allow the Callback to execute once. -template -class PassedWrapper { - public: - explicit PassedWrapper(T scoper) : is_valid_(true), scoper_(scoper.Pass()) {} - PassedWrapper(const PassedWrapper& other) - : is_valid_(other.is_valid_), scoper_(other.scoper_.Pass()) {} - T Pass() const { - CHECK(is_valid_); - is_valid_ = false; - return scoper_.Pass(); - } - - private: - mutable bool is_valid_; - mutable T scoper_; -}; - -// Unwrap the stored parameters for the wrappers above. -template -struct UnwrapTraits { - typedef const T& ForwardType; - static ForwardType Unwrap(const T& o) { return o; } -}; - -template -struct UnwrapTraits> { - typedef T* ForwardType; - static ForwardType Unwrap(UnretainedWrapper unretained) { - return unretained.get(); - } -}; - -template -struct UnwrapTraits> { - typedef const T& ForwardType; - static ForwardType Unwrap(ConstRefWrapper const_ref) { - return const_ref.get(); - } -}; - -template -struct UnwrapTraits> { - typedef T* ForwardType; - static ForwardType Unwrap(const scoped_refptr& o) { return o.get(); } -}; - -template -struct UnwrapTraits> { - typedef const WeakPtr& ForwardType; - static ForwardType Unwrap(const WeakPtr& o) { return o; } -}; - -template -struct UnwrapTraits> { - typedef T* ForwardType; - static ForwardType Unwrap(const OwnedWrapper& o) { return o.get(); } -}; - -template -struct UnwrapTraits> { - typedef T ForwardType; - static T Unwrap(PassedWrapper& o) { return o.Pass(); } -}; - -// Utility for handling different refcounting semantics in the Bind() -// function. -template -struct MaybeRefcount; - -template -struct MaybeRefcount { - static void AddRef(const T&) {} - static void Release(const T&) {} -}; - -template -struct MaybeRefcount { - static void AddRef(const T*) {} - static void Release(const T*) {} -}; - -template -struct MaybeRefcount { - static void AddRef(const T&) {} - static void Release(const T&) {} -}; - -template -struct MaybeRefcount { - static void AddRef(T* o) { o->AddRef(); } - static void Release(T* o) { o->Release(); } -}; - -// No need to additionally AddRef() and Release() since we are storing a -// scoped_refptr<> inside the storage object already. -template -struct MaybeRefcount> { - static void AddRef(const scoped_refptr& o) {} - static void Release(const scoped_refptr& o) {} -}; - -template -struct MaybeRefcount { - static void AddRef(const T* o) { o->AddRef(); } - static void Release(const T* o) { o->Release(); } -}; - -// IsWeakMethod is a helper that determine if we are binding a WeakPtr<> to a -// method. It is used internally by Bind() to select the correct -// InvokeHelper that will no-op itself in the event the WeakPtr<> for -// the target object is invalidated. -// -// P1 should be the type of the object that will be received of the method. -template -struct IsWeakMethod : public false_type {}; - -template -struct IsWeakMethod> : public true_type {}; - -template -struct IsWeakMethod>> : public true_type {}; - -} // namespace cef_internal - -template -static inline cef_internal::UnretainedWrapper Unretained(T* o) { - return cef_internal::UnretainedWrapper(o); -} - -template -static inline cef_internal::ConstRefWrapper ConstRef(const T& o) { - return cef_internal::ConstRefWrapper(o); -} - -template -static inline cef_internal::OwnedWrapper Owned(T* o) { - return cef_internal::OwnedWrapper(o); -} - -// We offer 2 syntaxes for calling Passed(). The first takes a temporary and -// is best suited for use with the return value of a function. The second -// takes a pointer to the scoper and is just syntactic sugar to avoid having -// to write Passed(scoper.Pass()). -template -static inline cef_internal::PassedWrapper Passed(T scoper) { - return cef_internal::PassedWrapper(scoper.Pass()); -} -template -static inline cef_internal::PassedWrapper Passed(T* scoper) { - return cef_internal::PassedWrapper(scoper->Pass()); -} - -template -static inline cef_internal::IgnoreResultHelper IgnoreResult(T data) { - return cef_internal::IgnoreResultHelper(data); -} - -template -static inline cef_internal::IgnoreResultHelper> IgnoreResult( - const Callback& data) { - return cef_internal::IgnoreResultHelper>(data); -} - -void DoNothing(); - -template -void DeletePointer(T* obj) { - delete obj; -} - -} // namespace base - -#endif // !USING_CHROMIUM_INCLUDES - -#endif // CEF_INCLUDE_BASE_CEF_BIND_HELPERS_H_ diff --git a/src/include/base/cef_build.h b/src/include/base/cef_build.h index 1e2065ce3..717f05df1 100644 --- a/src/include/base/cef_build.h +++ b/src/include/base/cef_build.h @@ -27,53 +27,132 @@ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +/// \file +/// This file adds defines about the platform we're currently building on. +/// +///
+///  Operating System:
+///    OS_AIX / OS_ANDROID / OS_ASMJS / OS_FREEBSD / OS_FUCHSIA / OS_IOS /
+///    OS_LINUX / OS_MAC / OS_NACL (SFI or NONSFI) / OS_NETBSD / OS_OPENBSD /
+///    OS_QNX / OS_SOLARIS / OS_WIN
+///  Operating System family:
+///    OS_APPLE: IOS or MAC
+///    OS_BSD: FREEBSD or NETBSD or OPENBSD
+///    OS_POSIX: AIX or ANDROID or ASMJS or CHROMEOS or FREEBSD or IOS or LINUX
+///              or MAC or NACL or NETBSD or OPENBSD or QNX or SOLARIS
+///
+///  /!\ Note: OS_CHROMEOS is set by the build system, not this file
+///
+///  Compiler:
+///    COMPILER_MSVC / COMPILER_GCC
+///
+///  Processor:
+///    ARCH_CPU_ARM64 / ARCH_CPU_ARMEL / ARCH_CPU_MIPS / ARCH_CPU_MIPS64 /
+///    ARCH_CPU_MIPS64EL / ARCH_CPU_MIPSEL / ARCH_CPU_PPC64 / ARCH_CPU_S390 /
+///    ARCH_CPU_S390X / ARCH_CPU_X86 / ARCH_CPU_X86_64
+///  Processor family:
+///    ARCH_CPU_ARM_FAMILY: ARMEL or ARM64
+///    ARCH_CPU_MIPS_FAMILY: MIPS64EL or MIPSEL or MIPS64 or MIPS
+///    ARCH_CPU_PPC64_FAMILY: PPC64
+///    ARCH_CPU_S390_FAMILY: S390 or S390X
+///    ARCH_CPU_X86_FAMILY: X86 or X86_64
+///  Processor features:
+///    ARCH_CPU_31_BITS / ARCH_CPU_32_BITS / ARCH_CPU_64_BITS
+///    ARCH_CPU_BIG_ENDIAN / ARCH_CPU_LITTLE_ENDIAN
+/// 
+/// + #ifndef CEF_INCLUDE_BASE_CEF_BUILD_H_ #define CEF_INCLUDE_BASE_CEF_BUILD_H_ #pragma once #if defined(USING_CHROMIUM_INCLUDES) // When building CEF include the Chromium header directly. -#include "base/compiler_specific.h" +#include "build/build_config.h" #else // !USING_CHROMIUM_INCLUDES // The following is substantially similar to the Chromium implementation. // If the Chromium implementation diverges the below implementation should be // updated to match. -#if defined(_WIN32) -#ifndef OS_WIN -#define OS_WIN 1 -#endif +// A set of macros to use for platform detection. +#if defined(ANDROID) +#define OS_ANDROID 1 #elif defined(__APPLE__) -#ifndef OS_MACOSX +// Only include TargetConditionals after testing ANDROID as some Android builds +// on the Mac have this header available and it's not needed unless the target +// is really an Apple platform. +#include +#if defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE +#define OS_IOS 1 +#else +#define OS_MAC 1 +// For backwards compatibility. #define OS_MACOSX 1 -#endif +#endif // defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE #elif defined(__linux__) -#ifndef OS_LINUX +#if !defined(OS_CHROMEOS) +// Do not define OS_LINUX on Chrome OS build. +// The OS_CHROMEOS macro is defined in GN. #define OS_LINUX 1 +#endif // !defined(OS_CHROMEOS) +// Include a system header to pull in features.h for glibc/uclibc macros. +#include +#if defined(__GLIBC__) && !defined(__UCLIBC__) +// We really are using glibc, not uClibc pretending to be glibc. +#define LIBC_GLIBC 1 #endif +#elif defined(_WIN32) +#define OS_WIN 1 +#elif defined(__Fuchsia__) +#define OS_FUCHSIA 1 +#elif defined(__FreeBSD__) +#define OS_FREEBSD 1 +#elif defined(__NetBSD__) +#define OS_NETBSD 1 +#elif defined(__OpenBSD__) +#define OS_OPENBSD 1 +#elif defined(__sun) +#define OS_SOLARIS 1 +#elif defined(__QNXNTO__) +#define OS_QNX 1 +#elif defined(_AIX) +#define OS_AIX 1 +#elif defined(__asmjs__) || defined(__wasm__) +#define OS_ASMJS 1 #else -#error Please add support for your platform in cef_build.h +#error Please add support for your platform in include/base/cef_build.h +#endif +// NOTE: Adding a new port? Please follow +// https://chromium.googlesource.com/chromium/src/+/master/docs/new_port_policy.md + +#if defined(OS_MAC) || defined(OS_IOS) +#define OS_APPLE 1 +#endif + +// For access to standard BSD features, use OS_BSD instead of a +// more specific macro. +#if defined(OS_FREEBSD) || defined(OS_NETBSD) || defined(OS_OPENBSD) +#define OS_BSD 1 #endif // For access to standard POSIXish features, use OS_POSIX instead of a // more specific macro. -#if defined(OS_MACOSX) || defined(OS_LINUX) -#ifndef OS_POSIX +#if defined(OS_AIX) || defined(OS_ANDROID) || defined(OS_ASMJS) || \ + defined(OS_FREEBSD) || defined(OS_IOS) || defined(OS_LINUX) || \ + defined(OS_CHROMEOS) || defined(OS_MAC) || defined(OS_NACL) || \ + defined(OS_NETBSD) || defined(OS_OPENBSD) || defined(OS_QNX) || \ + defined(OS_SOLARIS) #define OS_POSIX 1 #endif -#endif -// Compiler detection. +// Compiler detection. Note: clang masquerades as GCC on POSIX and as MSVC on +// Windows. #if defined(__GNUC__) -#ifndef COMPILER_GCC #define COMPILER_GCC 1 -#endif #elif defined(_MSC_VER) -#ifndef COMPILER_MSVC #define COMPILER_MSVC 1 -#endif #else -#error Please add support for your compiler in cef_build.h +#error Please add support for your compiler in build/build_config.h #endif // Processor architecture detection. For more info on what's defined, see: @@ -90,108 +169,95 @@ #define ARCH_CPU_X86 1 #define ARCH_CPU_32_BITS 1 #define ARCH_CPU_LITTLE_ENDIAN 1 +#elif defined(__s390x__) +#define ARCH_CPU_S390_FAMILY 1 +#define ARCH_CPU_S390X 1 +#define ARCH_CPU_64_BITS 1 +#define ARCH_CPU_BIG_ENDIAN 1 +#elif defined(__s390__) +#define ARCH_CPU_S390_FAMILY 1 +#define ARCH_CPU_S390 1 +#define ARCH_CPU_31_BITS 1 +#define ARCH_CPU_BIG_ENDIAN 1 +#elif (defined(__PPC64__) || defined(__PPC__)) && defined(__BIG_ENDIAN__) +#define ARCH_CPU_PPC64_FAMILY 1 +#define ARCH_CPU_PPC64 1 +#define ARCH_CPU_64_BITS 1 +#define ARCH_CPU_BIG_ENDIAN 1 +#elif defined(__PPC64__) +#define ARCH_CPU_PPC64_FAMILY 1 +#define ARCH_CPU_PPC64 1 +#define ARCH_CPU_64_BITS 1 +#define ARCH_CPU_LITTLE_ENDIAN 1 #elif defined(__ARMEL__) #define ARCH_CPU_ARM_FAMILY 1 #define ARCH_CPU_ARMEL 1 #define ARCH_CPU_32_BITS 1 #define ARCH_CPU_LITTLE_ENDIAN 1 -#elif defined(__aarch64__) +#elif defined(__aarch64__) || defined(_M_ARM64) #define ARCH_CPU_ARM_FAMILY 1 #define ARCH_CPU_ARM64 1 #define ARCH_CPU_64_BITS 1 #define ARCH_CPU_LITTLE_ENDIAN 1 -#elif defined(__pnacl__) +#elif defined(__pnacl__) || defined(__asmjs__) || defined(__wasm__) #define ARCH_CPU_32_BITS 1 #define ARCH_CPU_LITTLE_ENDIAN 1 #elif defined(__MIPSEL__) +#if defined(__LP64__) +#define ARCH_CPU_MIPS_FAMILY 1 +#define ARCH_CPU_MIPS64EL 1 +#define ARCH_CPU_64_BITS 1 +#define ARCH_CPU_LITTLE_ENDIAN 1 +#else #define ARCH_CPU_MIPS_FAMILY 1 #define ARCH_CPU_MIPSEL 1 #define ARCH_CPU_32_BITS 1 #define ARCH_CPU_LITTLE_ENDIAN 1 +#endif +#elif defined(__MIPSEB__) +#if defined(__LP64__) +#define ARCH_CPU_MIPS_FAMILY 1 +#define ARCH_CPU_MIPS64 1 +#define ARCH_CPU_64_BITS 1 +#define ARCH_CPU_BIG_ENDIAN 1 #else -#error Please add support for your architecture in cef_build.h +#define ARCH_CPU_MIPS_FAMILY 1 +#define ARCH_CPU_MIPS 1 +#define ARCH_CPU_32_BITS 1 +#define ARCH_CPU_BIG_ENDIAN 1 +#endif +#else +#error Please add support for your architecture in include/base/cef_build.h #endif // Type detection for wchar_t. #if defined(OS_WIN) -#define WCHAR_T_IS_UTF16 +#define WCHAR_T_IS_16_BIT +#elif defined(OS_FUCHSIA) +#define WCHAR_T_IS_32_BIT #elif defined(OS_POSIX) && defined(COMPILER_GCC) && defined(__WCHAR_MAX__) && \ (__WCHAR_MAX__ == 0x7fffffff || __WCHAR_MAX__ == 0xffffffff) -#define WCHAR_T_IS_UTF32 +#define WCHAR_T_IS_32_BIT #elif defined(OS_POSIX) && defined(COMPILER_GCC) && defined(__WCHAR_MAX__) && \ (__WCHAR_MAX__ == 0x7fff || __WCHAR_MAX__ == 0xffff) // On Posix, we'll detect short wchar_t, but projects aren't guaranteed to // compile in this mode (in particular, Chrome doesn't). This is intended for // other projects using base who manage their own dependencies and make sure // short wchar works for them. -#define WCHAR_T_IS_UTF16 -#else -#error Please add support for your compiler in cef_build.h -#endif - -// Annotate a function indicating the caller must examine the return value. -// Use like: -// int foo() WARN_UNUSED_RESULT; -// To explicitly ignore a result, see |ignore_result()| in . -#ifndef WARN_UNUSED_RESULT -#if defined(COMPILER_GCC) -#define WARN_UNUSED_RESULT __attribute__((warn_unused_result)) -#else -#define WARN_UNUSED_RESULT -#endif -#endif // WARN_UNUSED_RESULT - -// Annotate a typedef or function indicating it's ok if it's not used. -// Use like: -// typedef Foo Bar ALLOW_UNUSED_TYPE; -#ifndef ALLOW_UNUSED_TYPE -#if defined(COMPILER_GCC) -#define ALLOW_UNUSED_TYPE __attribute__((unused)) +#define WCHAR_T_IS_16_BIT #else -#define ALLOW_UNUSED_TYPE +#error Please add support for your compiler in include/base/cef_build.h #endif -#endif // ALLOW_UNUSED_TYPE -// Annotate a variable indicating it's ok if the variable is not used. -// (Typically used to silence a compiler warning when the assignment -// is important for some other reason.) -// Use like: -// int x = ...; -// ALLOW_UNUSED_LOCAL(x); -#ifndef ALLOW_UNUSED_LOCAL -#define ALLOW_UNUSED_LOCAL(x) false ? (void)x : (void)0 +#if defined(OS_ANDROID) +// The compiler thinks std::string::const_iterator and "const char*" are +// equivalent types. +#define STD_STRING_ITERATOR_IS_CHAR_POINTER +// The compiler thinks std::u16string::const_iterator and "char16_t*" are +// equivalent types. +#define BASE_STRING16_ITERATOR_IS_CHAR16_POINTER #endif #endif // !USING_CHROMIUM_INCLUDES -// Annotate a virtual method indicating it must be overriding a virtual method -// in the parent class. -// Use like: -// void foo() OVERRIDE; -// NOTE: This define should only be used in classes exposed to the client since -// C++11 support may not be enabled in client applications. CEF internal classes -// should use the `override` keyword directly. -#ifndef OVERRIDE -#if defined(__clang__) -#define OVERRIDE override -#elif defined(COMPILER_MSVC) && _MSC_VER >= 1600 -// Visual Studio 2010 and later support override. -#define OVERRIDE override -#elif defined(COMPILER_GCC) && __cplusplus >= 201103 && \ - (__GNUC__ * 10000 + __GNUC_MINOR__ * 100) >= 40700 -// GCC 4.7 supports explicit virtual overrides when C++11 support is enabled. -#define OVERRIDE override -#else -#define OVERRIDE -#endif -#endif // OVERRIDE - -// Check for C++11 template alias support which was added in VS2013 and GCC4.7. -// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2258.pdf -#if __cplusplus > 199711L || (defined(_MSC_VER) && _MSC_VER >= 1800) || \ - (defined(__GNUC__) && \ - (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__ >= 40700)) -#define HAS_CPP11_TEMPLATE_ALIAS_SUPPORT -#endif - #endif // CEF_INCLUDE_BASE_CEF_BUILD_H_ diff --git a/src/include/base/cef_callback.h b/src/include/base/cef_callback.h index 16e238a97..bcfe4992a 100644 --- a/src/include/base/cef_callback.h +++ b/src/include/base/cef_callback.h @@ -28,772 +28,221 @@ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +/// \file +/// A callback is similar in concept to a function pointer: it wraps a runnable +/// object such as a function, method, lambda, or even another callback, +/// allowing the runnable object to be invoked later via the callback object. +/// +/// Unlike function pointers, callbacks are created with base::BindOnce() or +/// base::BindRepeating() and support partial function application. +/// +/// A base::OnceCallback may be Run() at most once; a base::RepeatingCallback +/// may be Run() any number of times. |is_null()| is guaranteed to return true +/// for a moved-from callback. +/// +///
+///   // The lambda takes two arguments, but the first argument |x| is bound at
+///   // callback creation.
+///   base::OnceCallback cb = base::BindOnce([] (int x, int y) {
+///     return x + y;
+///   }, 1);
+///   // Run() only needs the remaining unbound argument |y|.
+///   printf("1 + 2 = %d\n", std::move(cb).Run(2));  // Prints 3
+///   printf("cb is null? %s\n",
+///          cb.is_null() ? "true" : "false");  // Prints true
+///   std::move(cb).Run(2);  // Crashes since |cb| has already run.
+/// 
+/// +/// Callbacks also support cancellation. A common use is binding the receiver +/// object as a WeakPtr. If that weak pointer is invalidated, calling Run() +/// will be a no-op. Note that |IsCancelled()| and |is_null()| are distinct: +/// simply cancelling a callback will not also make it null. +/// +/// See https://chromium.googlesource.com/chromium/src/+/lkgr/docs/callback.md +/// for the full documentation. + #ifndef CEF_INCLUDE_BASE_CEF_CALLBACK_H_ #define CEF_INCLUDE_BASE_CEF_CALLBACK_H_ #pragma once -#if defined(BASE_CALLBACK_H_) -// Do nothing if the Chromium header has already been included. -// This can happen in cases where Chromium code is used directly by the -// client application. When using Chromium code directly always include -// the Chromium header first to avoid type conflicts. -#elif defined(USING_CHROMIUM_INCLUDES) +#if defined(USING_CHROMIUM_INCLUDES) // When building CEF include the Chromium header directly. -#include "base/callback.h" +#include "base/functional/callback.h" #else // !USING_CHROMIUM_INCLUDES // The following is substantially similar to the Chromium implementation. // If the Chromium implementation diverges the below implementation should be // updated to match. +#include + +#include "include/base/cef_bind.h" #include "include/base/cef_callback_forward.h" -#include "include/base/cef_template_util.h" +#include "include/base/cef_logging.h" #include "include/base/internal/cef_callback_internal.h" -// NOTE: Header files that do not require the full definition of Callback or -// Closure should #include "base/cef_callback_forward.h" instead of this file. - -// ----------------------------------------------------------------------------- -// Introduction -// ----------------------------------------------------------------------------- -// -// The templated Callback class is a generalized function object. Together -// with the Bind() function in bind.h, they provide a type-safe method for -// performing partial application of functions. -// -// Partial application (or "currying") is the process of binding a subset of -// a function's arguments to produce another function that takes fewer -// arguments. This can be used to pass around a unit of delayed execution, -// much like lexical closures are used in other languages. For example, it -// is used in Chromium code to schedule tasks on different MessageLoops. -// -// A callback with no unbound input parameters (base::Callback) -// is called a base::Closure. Note that this is NOT the same as what other -// languages refer to as a closure -- it does not retain a reference to its -// enclosing environment. -// -// MEMORY MANAGEMENT AND PASSING -// -// The Callback objects themselves should be passed by const-reference, and -// stored by copy. They internally store their state via a refcounted class -// and thus do not need to be deleted. -// -// The reason to pass via a const-reference is to avoid unnecessary -// AddRef/Release pairs to the internal state. -// -// -// ----------------------------------------------------------------------------- -// Quick reference for basic stuff -// ----------------------------------------------------------------------------- -// -// BINDING A BARE FUNCTION -// -// int Return5() { return 5; } -// base::Callback func_cb = base::Bind(&Return5); -// LOG(INFO) << func_cb.Run(); // Prints 5. -// -// BINDING A CLASS METHOD -// -// The first argument to bind is the member function to call, the second is -// the object on which to call it. -// -// class Ref : public base::RefCountedThreadSafe { -// public: -// int Foo() { return 3; } -// void PrintBye() { LOG(INFO) << "bye."; } -// }; -// scoped_refptr ref = new Ref(); -// base::Callback ref_cb = base::Bind(&Ref::Foo, ref); -// LOG(INFO) << ref_cb.Run(); // Prints out 3. -// -// By default the object must support RefCounted or you will get a compiler -// error. If you're passing between threads, be sure it's -// RefCountedThreadSafe! See "Advanced binding of member functions" below if -// you don't want to use reference counting. -// -// RUNNING A CALLBACK -// -// Callbacks can be run with their "Run" method, which has the same -// signature as the template argument to the callback. -// -// void DoSomething(const base::Callback& callback) { -// callback.Run(5, "hello"); -// } -// -// Callbacks can be run more than once (they don't get deleted or marked when -// run). However, this precludes using base::Passed (see below). -// -// void DoSomething(const base::Callback& callback) { -// double myresult = callback.Run(3.14159); -// myresult += callback.Run(2.71828); -// } -// -// PASSING UNBOUND INPUT PARAMETERS -// -// Unbound parameters are specified at the time a callback is Run(). They are -// specified in the Callback template type: -// -// void MyFunc(int i, const std::string& str) {} -// base::Callback cb = base::Bind(&MyFunc); -// cb.Run(23, "hello, world"); -// -// PASSING BOUND INPUT PARAMETERS -// -// Bound parameters are specified when you create thee callback as arguments -// to Bind(). They will be passed to the function and the Run()ner of the -// callback doesn't see those values or even know that the function it's -// calling. -// -// void MyFunc(int i, const std::string& str) {} -// base::Callback cb = base::Bind(&MyFunc, 23, "hello world"); -// cb.Run(); -// -// A callback with no unbound input parameters (base::Callback) -// is called a base::Closure. So we could have also written: -// -// base::Closure cb = base::Bind(&MyFunc, 23, "hello world"); -// -// When calling member functions, bound parameters just go after the object -// pointer. -// -// base::Closure cb = base::Bind(&MyClass::MyFunc, this, 23, "hello world"); -// -// PARTIAL BINDING OF PARAMETERS -// -// You can specify some parameters when you create the callback, and specify -// the rest when you execute the callback. -// -// void MyFunc(int i, const std::string& str) {} -// base::Callback cb = base::Bind(&MyFunc, 23); -// cb.Run("hello world"); -// -// When calling a function bound parameters are first, followed by unbound -// parameters. -// -// -// ----------------------------------------------------------------------------- -// Quick reference for advanced binding -// ----------------------------------------------------------------------------- -// -// BINDING A CLASS METHOD WITH WEAK POINTERS -// -// base::Bind(&MyClass::Foo, GetWeakPtr()); -// -// The callback will not be run if the object has already been destroyed. -// DANGER: weak pointers are not threadsafe, so don't use this -// when passing between threads! -// -// BINDING A CLASS METHOD WITH MANUAL LIFETIME MANAGEMENT -// -// base::Bind(&MyClass::Foo, base::Unretained(this)); -// -// This disables all lifetime management on the object. You're responsible -// for making sure the object is alive at the time of the call. You break it, -// you own it! -// -// BINDING A CLASS METHOD AND HAVING THE CALLBACK OWN THE CLASS -// -// MyClass* myclass = new MyClass; -// base::Bind(&MyClass::Foo, base::Owned(myclass)); -// -// The object will be deleted when the callback is destroyed, even if it's -// not run (like if you post a task during shutdown). Potentially useful for -// "fire and forget" cases. -// -// IGNORING RETURN VALUES -// -// Sometimes you want to call a function that returns a value in a callback -// that doesn't expect a return value. -// -// int DoSomething(int arg) { cout << arg << endl; } -// base::Callback) cb = -// base::Bind(base::IgnoreResult(&DoSomething)); -// -// -// ----------------------------------------------------------------------------- -// Quick reference for binding parameters to Bind() -// ----------------------------------------------------------------------------- -// -// Bound parameters are specified as arguments to Bind() and are passed to the -// function. A callback with no parameters or no unbound parameters is called a -// Closure (base::Callback and base::Closure are the same thing). -// -// PASSING PARAMETERS OWNED BY THE CALLBACK -// -// void Foo(int* arg) { cout << *arg << endl; } -// int* pn = new int(1); -// base::Closure foo_callback = base::Bind(&foo, base::Owned(pn)); -// -// The parameter will be deleted when the callback is destroyed, even if it's -// not run (like if you post a task during shutdown). -// -// PASSING PARAMETERS AS A scoped_ptr -// -// void TakesOwnership(scoped_ptr arg) {} -// scoped_ptr f(new Foo); -// // f becomes null during the following call. -// base::Closure cb = base::Bind(&TakesOwnership, base::Passed(&f)); -// -// Ownership of the parameter will be with the callback until the it is run, -// when ownership is passed to the callback function. This means the callback -// can only be run once. If the callback is never run, it will delete the -// object when it's destroyed. -// -// PASSING PARAMETERS AS A scoped_refptr -// -// void TakesOneRef(scoped_refptr arg) {} -// scoped_refptr f(new Foo) -// base::Closure cb = base::Bind(&TakesOneRef, f); -// -// This should "just work." The closure will take a reference as long as it -// is alive, and another reference will be taken for the called function. -// -// PASSING PARAMETERS BY REFERENCE -// -// Const references are *copied* unless ConstRef is used. Example: -// -// void foo(const int& arg) { printf("%d %p\n", arg, &arg); } -// int n = 1; -// base::Closure has_copy = base::Bind(&foo, n); -// base::Closure has_ref = base::Bind(&foo, base::ConstRef(n)); -// n = 2; -// foo(n); // Prints "2 0xaaaaaaaaaaaa" -// has_copy.Run(); // Prints "1 0xbbbbbbbbbbbb" -// has_ref.Run(); // Prints "2 0xaaaaaaaaaaaa" -// -// Normally parameters are copied in the closure. DANGER: ConstRef stores a -// const reference instead, referencing the original parameter. This means -// that you must ensure the object outlives the callback! -// -// -// ----------------------------------------------------------------------------- -// Implementation notes -// ----------------------------------------------------------------------------- -// -// WHERE IS THIS DESIGN FROM: -// -// The design Callback and Bind is heavily influenced by C++'s -// tr1::function/tr1::bind, and by the "Google Callback" system used inside -// Google. -// -// -// HOW THE IMPLEMENTATION WORKS: -// -// There are three main components to the system: -// 1) The Callback classes. -// 2) The Bind() functions. -// 3) The arguments wrappers (e.g., Unretained() and ConstRef()). -// -// The Callback classes represent a generic function pointer. Internally, -// it stores a refcounted piece of state that represents the target function -// and all its bound parameters. Each Callback specialization has a templated -// constructor that takes an BindState<>*. In the context of the constructor, -// the static type of this BindState<> pointer uniquely identifies the -// function it is representing, all its bound parameters, and a Run() method -// that is capable of invoking the target. -// -// Callback's constructor takes the BindState<>* that has the full static type -// and erases the target function type as well as the types of the bound -// parameters. It does this by storing a pointer to the specific Run() -// function, and upcasting the state of BindState<>* to a -// BindStateBase*. This is safe as long as this BindStateBase pointer -// is only used with the stored Run() pointer. -// -// To BindState<> objects are created inside the Bind() functions. -// These functions, along with a set of internal templates, are responsible for -// -// - Unwrapping the function signature into return type, and parameters -// - Determining the number of parameters that are bound -// - Creating the BindState storing the bound parameters -// - Performing compile-time asserts to avoid error-prone behavior -// - Returning an Callback<> with an arity matching the number of unbound -// parameters and that knows the correct refcounting semantics for the -// target object if we are binding a method. -// -// The Bind functions do the above using type-inference, and template -// specializations. -// -// By default Bind() will store copies of all bound parameters, and attempt -// to refcount a target object if the function being bound is a class method. -// These copies are created even if the function takes parameters as const -// references. (Binding to non-const references is forbidden, see bind.h.) -// -// To change this behavior, we introduce a set of argument wrappers -// (e.g., Unretained(), and ConstRef()). These are simple container templates -// that are passed by value, and wrap a pointer to argument. See the -// file-level comment in base/bind_helpers.h for more info. -// -// These types are passed to the Unwrap() functions, and the MaybeRefcount() -// functions respectively to modify the behavior of Bind(). The Unwrap() -// and MaybeRefcount() functions change behavior by doing partial -// specialization based on whether or not a parameter is a wrapper type. -// -// ConstRef() is similar to tr1::cref. Unretained() is specific to Chromium. -// -// -// WHY NOT TR1 FUNCTION/BIND? -// -// Direct use of tr1::function and tr1::bind was considered, but ultimately -// rejected because of the number of copy constructors invocations involved -// in the binding of arguments during construction, and the forwarding of -// arguments during invocation. These copies will no longer be an issue in -// C++0x because C++0x will support rvalue reference allowing for the compiler -// to avoid these copies. However, waiting for C++0x is not an option. -// -// Measured with valgrind on gcc version 4.4.3 (Ubuntu 4.4.3-4ubuntu5), the -// tr1::bind call itself will invoke a non-trivial copy constructor three times -// for each bound parameter. Also, each when passing a tr1::function, each -// bound argument will be copied again. -// -// In addition to the copies taken at binding and invocation, copying a -// tr1::function causes a copy to be made of all the bound parameters and -// state. -// -// Furthermore, in Chromium, it is desirable for the Callback to take a -// reference on a target object when representing a class method call. This -// is not supported by tr1. -// -// Lastly, tr1::function and tr1::bind has a more general and flexible API. -// This includes things like argument reordering by use of -// tr1::bind::placeholder, support for non-const reference parameters, and some -// limited amount of subtyping of the tr1::function object (e.g., -// tr1::function is convertible to tr1::function). -// -// These are not features that are required in Chromium. Some of them, such as -// allowing for reference parameters, and subtyping of functions, may actually -// become a source of errors. Removing support for these features actually -// allows for a simpler implementation, and a terser Currying API. -// -// -// WHY NOT GOOGLE CALLBACKS? -// -// The Google callback system also does not support refcounting. Furthermore, -// its implementation has a number of strange edge cases with respect to type -// conversion of its arguments. In particular, the argument's constness must -// at times match exactly the function signature, or the type-inference might -// break. Given the above, writing a custom solution was easier. -// -// -// MISSING FUNCTIONALITY -// - Invoking the return of Bind. Bind(&foo).Run() does not work; -// - Binding arrays to functions that take a non-const pointer. -// Example: -// void Foo(const char* ptr); -// void Bar(char* ptr); -// Bind(&Foo, "test"); -// Bind(&Bar, "test"); // This fails because ptr is not const. - namespace base { -// First, we forward declare the Callback class template. This informs the -// compiler that the template only has 1 type parameter which is the function -// signature that the Callback is representing. -// -// After this, create template specializations for 0-7 parameters. Note that -// even though the template typelist grows, the specialization still -// only has one type: the function signature. -// -// If you are thinking of forward declaring Callback in your own header file, -// please include "base/callback_forward.h" instead. -template -class Callback; - -namespace cef_internal { -template -struct BindState; -} // namespace cef_internal - -template -class Callback : public cef_internal::CallbackBase { +template +class OnceCallback : public cef_internal::CallbackBase { public: - typedef R(RunType)(); - - Callback() : CallbackBase(NULL) {} + using ResultType = R; + using RunType = R(Args...); + using PolymorphicInvoke = R (*)(cef_internal::BindStateBase*, + cef_internal::PassingType...); - // Note that this constructor CANNOT be explicit, and that Bind() CANNOT - // return the exact Callback<> type. See base/bind.h for details. - template - Callback( - cef_internal::BindState* bind_state) - : CallbackBase(bind_state) { - // Force the assignment to a local variable of PolymorphicInvoke - // so the compiler will typecheck that the passed in Run() method has - // the correct type. - PolymorphicInvoke invoke_func = - &cef_internal::BindState::InvokerType::Run; - polymorphic_invoke_ = reinterpret_cast(invoke_func); - } + constexpr OnceCallback() = default; + OnceCallback(std::nullptr_t) = delete; - bool Equals(const Callback& other) const { - return CallbackBase::Equals(other); - } + explicit OnceCallback(cef_internal::BindStateBase* bind_state) + : cef_internal::CallbackBase(bind_state) {} - R Run() const { - PolymorphicInvoke f = - reinterpret_cast(polymorphic_invoke_); + OnceCallback(const OnceCallback&) = delete; + OnceCallback& operator=(const OnceCallback&) = delete; - return f(bind_state_.get()); - } - - private: - typedef R (*PolymorphicInvoke)(cef_internal::BindStateBase*); -}; - -template -class Callback : public cef_internal::CallbackBase { - public: - typedef R(RunType)(A1); + OnceCallback(OnceCallback&&) noexcept = default; + OnceCallback& operator=(OnceCallback&&) noexcept = default; - Callback() : CallbackBase(NULL) {} + OnceCallback(RepeatingCallback other) + : cef_internal::CallbackBase(std::move(other)) {} - // Note that this constructor CANNOT be explicit, and that Bind() CANNOT - // return the exact Callback<> type. See base/bind.h for details. - template - Callback( - cef_internal::BindState* bind_state) - : CallbackBase(bind_state) { - // Force the assignment to a local variable of PolymorphicInvoke - // so the compiler will typecheck that the passed in Run() method has - // the correct type. - PolymorphicInvoke invoke_func = - &cef_internal::BindState::InvokerType::Run; - polymorphic_invoke_ = reinterpret_cast(invoke_func); + OnceCallback& operator=(RepeatingCallback other) { + static_cast(*this) = std::move(other); + return *this; } - bool Equals(const Callback& other) const { - return CallbackBase::Equals(other); + R Run(Args... args) const& { + static_assert(!sizeof(*this), + "OnceCallback::Run() may only be invoked on a non-const " + "rvalue, i.e. std::move(callback).Run()."); + NOTREACHED(); } - R Run(typename cef_internal::CallbackParamTraits::ForwardType a1) const { + R Run(Args... args) && { + // Move the callback instance into a local variable before the invocation, + // that ensures the internal state is cleared after the invocation. + // It's not safe to touch |this| after the invocation, since running the + // bound function may destroy |this|. + OnceCallback cb = std::move(*this); PolymorphicInvoke f = - reinterpret_cast(polymorphic_invoke_); - - return f(bind_state_.get(), cef_internal::CallbackForward(a1)); + reinterpret_cast(cb.polymorphic_invoke()); + return f(cb.bind_state_.get(), std::forward(args)...); + } + + // Then() returns a new OnceCallback that receives the same arguments as + // |this|, and with the return type of |then|. The returned callback will: + // 1) Run the functor currently bound to |this| callback. + // 2) Run the |then| callback with the result from step 1 as its single + // argument. + // 3) Return the value from running the |then| callback. + // + // Since this method generates a callback that is a replacement for `this`, + // `this` will be consumed and reset to a null callback to ensure the + // originally-bound functor can be run at most once. + template + OnceCallback Then(OnceCallback then) && { + CHECK(then); + return BindOnce( + cef_internal::ThenHelper< + OnceCallback, OnceCallback>::CreateTrampoline(), + std::move(*this), std::move(then)); + } + + // This overload is required; even though RepeatingCallback is implicitly + // convertible to OnceCallback, that conversion will not used when matching + // for template argument deduction. + template + OnceCallback Then( + RepeatingCallback then) && { + CHECK(then); + return BindOnce( + cef_internal::ThenHelper< + OnceCallback, + RepeatingCallback>::CreateTrampoline(), + std::move(*this), std::move(then)); } - - private: - typedef R (*PolymorphicInvoke)( - cef_internal::BindStateBase*, - typename cef_internal::CallbackParamTraits::ForwardType); }; -template -class Callback : public cef_internal::CallbackBase { +template +class RepeatingCallback + : public cef_internal::CallbackBaseCopyable { public: - typedef R(RunType)(A1, A2); - - Callback() : CallbackBase(NULL) {} - - // Note that this constructor CANNOT be explicit, and that Bind() CANNOT - // return the exact Callback<> type. See base/bind.h for details. - template - Callback( - cef_internal::BindState* bind_state) - : CallbackBase(bind_state) { - // Force the assignment to a local variable of PolymorphicInvoke - // so the compiler will typecheck that the passed in Run() method has - // the correct type. - PolymorphicInvoke invoke_func = - &cef_internal::BindState::InvokerType::Run; - polymorphic_invoke_ = reinterpret_cast(invoke_func); - } - - bool Equals(const Callback& other) const { - return CallbackBase::Equals(other); - } - - R Run(typename cef_internal::CallbackParamTraits::ForwardType a1, - typename cef_internal::CallbackParamTraits::ForwardType a2) const { - PolymorphicInvoke f = - reinterpret_cast(polymorphic_invoke_); - - return f(bind_state_.get(), cef_internal::CallbackForward(a1), - cef_internal::CallbackForward(a2)); - } + using ResultType = R; + using RunType = R(Args...); + using PolymorphicInvoke = R (*)(cef_internal::BindStateBase*, + cef_internal::PassingType...); - private: - typedef R (*PolymorphicInvoke)( - cef_internal::BindStateBase*, - typename cef_internal::CallbackParamTraits::ForwardType, - typename cef_internal::CallbackParamTraits::ForwardType); -}; + constexpr RepeatingCallback() = default; + RepeatingCallback(std::nullptr_t) = delete; -template -class Callback : public cef_internal::CallbackBase { - public: - typedef R(RunType)(A1, A2, A3); + explicit RepeatingCallback(cef_internal::BindStateBase* bind_state) + : cef_internal::CallbackBaseCopyable(bind_state) {} - Callback() : CallbackBase(NULL) {} + // Copyable and movable. + RepeatingCallback(const RepeatingCallback&) = default; + RepeatingCallback& operator=(const RepeatingCallback&) = default; + RepeatingCallback(RepeatingCallback&&) noexcept = default; + RepeatingCallback& operator=(RepeatingCallback&&) noexcept = default; - // Note that this constructor CANNOT be explicit, and that Bind() CANNOT - // return the exact Callback<> type. See base/bind.h for details. - template - Callback( - cef_internal::BindState* bind_state) - : CallbackBase(bind_state) { - // Force the assignment to a local variable of PolymorphicInvoke - // so the compiler will typecheck that the passed in Run() method has - // the correct type. - PolymorphicInvoke invoke_func = - &cef_internal::BindState::InvokerType::Run; - polymorphic_invoke_ = reinterpret_cast(invoke_func); + bool operator==(const RepeatingCallback& other) const { + return EqualsInternal(other); } - bool Equals(const Callback& other) const { - return CallbackBase::Equals(other); + bool operator!=(const RepeatingCallback& other) const { + return !operator==(other); } - R Run(typename cef_internal::CallbackParamTraits::ForwardType a1, - typename cef_internal::CallbackParamTraits::ForwardType a2, - typename cef_internal::CallbackParamTraits::ForwardType a3) const { + R Run(Args... args) const& { PolymorphicInvoke f = - reinterpret_cast(polymorphic_invoke_); - - return f(bind_state_.get(), cef_internal::CallbackForward(a1), - cef_internal::CallbackForward(a2), - cef_internal::CallbackForward(a3)); + reinterpret_cast(this->polymorphic_invoke()); + return f(this->bind_state_.get(), std::forward(args)...); } - private: - typedef R (*PolymorphicInvoke)( - cef_internal::BindStateBase*, - typename cef_internal::CallbackParamTraits::ForwardType, - typename cef_internal::CallbackParamTraits::ForwardType, - typename cef_internal::CallbackParamTraits::ForwardType); -}; - -template -class Callback : public cef_internal::CallbackBase { - public: - typedef R(RunType)(A1, A2, A3, A4); - - Callback() : CallbackBase(NULL) {} - - // Note that this constructor CANNOT be explicit, and that Bind() CANNOT - // return the exact Callback<> type. See base/bind.h for details. - template - Callback( - cef_internal::BindState* bind_state) - : CallbackBase(bind_state) { - // Force the assignment to a local variable of PolymorphicInvoke - // so the compiler will typecheck that the passed in Run() method has - // the correct type. - PolymorphicInvoke invoke_func = - &cef_internal::BindState::InvokerType::Run; - polymorphic_invoke_ = reinterpret_cast(invoke_func); - } - - bool Equals(const Callback& other) const { - return CallbackBase::Equals(other); - } - - R Run(typename cef_internal::CallbackParamTraits::ForwardType a1, - typename cef_internal::CallbackParamTraits::ForwardType a2, - typename cef_internal::CallbackParamTraits::ForwardType a3, - typename cef_internal::CallbackParamTraits::ForwardType a4) const { - PolymorphicInvoke f = - reinterpret_cast(polymorphic_invoke_); - - return f(bind_state_.get(), cef_internal::CallbackForward(a1), - cef_internal::CallbackForward(a2), - cef_internal::CallbackForward(a3), - cef_internal::CallbackForward(a4)); - } - - private: - typedef R (*PolymorphicInvoke)( - cef_internal::BindStateBase*, - typename cef_internal::CallbackParamTraits::ForwardType, - typename cef_internal::CallbackParamTraits::ForwardType, - typename cef_internal::CallbackParamTraits::ForwardType, - typename cef_internal::CallbackParamTraits::ForwardType); -}; - -template -class Callback : public cef_internal::CallbackBase { - public: - typedef R(RunType)(A1, A2, A3, A4, A5); - - Callback() : CallbackBase(NULL) {} - - // Note that this constructor CANNOT be explicit, and that Bind() CANNOT - // return the exact Callback<> type. See base/bind.h for details. - template - Callback( - cef_internal::BindState* bind_state) - : CallbackBase(bind_state) { - // Force the assignment to a local variable of PolymorphicInvoke - // so the compiler will typecheck that the passed in Run() method has - // the correct type. - PolymorphicInvoke invoke_func = - &cef_internal::BindState::InvokerType::Run; - polymorphic_invoke_ = reinterpret_cast(invoke_func); - } - - bool Equals(const Callback& other) const { - return CallbackBase::Equals(other); - } - - R Run(typename cef_internal::CallbackParamTraits::ForwardType a1, - typename cef_internal::CallbackParamTraits::ForwardType a2, - typename cef_internal::CallbackParamTraits::ForwardType a3, - typename cef_internal::CallbackParamTraits::ForwardType a4, - typename cef_internal::CallbackParamTraits::ForwardType a5) const { + R Run(Args... args) && { + // Move the callback instance into a local variable before the invocation, + // that ensures the internal state is cleared after the invocation. + // It's not safe to touch |this| after the invocation, since running the + // bound function may destroy |this|. + RepeatingCallback cb = std::move(*this); PolymorphicInvoke f = - reinterpret_cast(polymorphic_invoke_); - - return f( - bind_state_.get(), cef_internal::CallbackForward(a1), - cef_internal::CallbackForward(a2), cef_internal::CallbackForward(a3), - cef_internal::CallbackForward(a4), cef_internal::CallbackForward(a5)); + reinterpret_cast(cb.polymorphic_invoke()); + return f(std::move(cb).bind_state_.get(), std::forward(args)...); + } + + // Then() returns a new RepeatingCallback that receives the same arguments as + // |this|, and with the return type of |then|. The + // returned callback will: + // 1) Run the functor currently bound to |this| callback. + // 2) Run the |then| callback with the result from step 1 as its single + // argument. + // 3) Return the value from running the |then| callback. + // + // If called on an rvalue (e.g. std::move(cb).Then(...)), this method + // generates a callback that is a replacement for `this`. Therefore, `this` + // will be consumed and reset to a null callback to ensure the + // originally-bound functor will be run at most once. + template + RepeatingCallback Then( + RepeatingCallback then) const& { + CHECK(then); + return BindRepeating( + cef_internal::ThenHelper< + RepeatingCallback, + RepeatingCallback>::CreateTrampoline(), + *this, std::move(then)); + } + + template + RepeatingCallback Then( + RepeatingCallback then) && { + CHECK(then); + return BindRepeating( + cef_internal::ThenHelper< + RepeatingCallback, + RepeatingCallback>::CreateTrampoline(), + std::move(*this), std::move(then)); } - - private: - typedef R (*PolymorphicInvoke)( - cef_internal::BindStateBase*, - typename cef_internal::CallbackParamTraits::ForwardType, - typename cef_internal::CallbackParamTraits::ForwardType, - typename cef_internal::CallbackParamTraits::ForwardType, - typename cef_internal::CallbackParamTraits::ForwardType, - typename cef_internal::CallbackParamTraits::ForwardType); }; -template -class Callback : public cef_internal::CallbackBase { - public: - typedef R(RunType)(A1, A2, A3, A4, A5, A6); - - Callback() : CallbackBase(NULL) {} - - // Note that this constructor CANNOT be explicit, and that Bind() CANNOT - // return the exact Callback<> type. See base/bind.h for details. - template - Callback( - cef_internal::BindState* bind_state) - : CallbackBase(bind_state) { - // Force the assignment to a local variable of PolymorphicInvoke - // so the compiler will typecheck that the passed in Run() method has - // the correct type. - PolymorphicInvoke invoke_func = - &cef_internal::BindState::InvokerType::Run; - polymorphic_invoke_ = reinterpret_cast(invoke_func); - } - - bool Equals(const Callback& other) const { - return CallbackBase::Equals(other); - } - - R Run(typename cef_internal::CallbackParamTraits::ForwardType a1, - typename cef_internal::CallbackParamTraits::ForwardType a2, - typename cef_internal::CallbackParamTraits::ForwardType a3, - typename cef_internal::CallbackParamTraits::ForwardType a4, - typename cef_internal::CallbackParamTraits::ForwardType a5, - typename cef_internal::CallbackParamTraits::ForwardType a6) const { - PolymorphicInvoke f = - reinterpret_cast(polymorphic_invoke_); - - return f( - bind_state_.get(), cef_internal::CallbackForward(a1), - cef_internal::CallbackForward(a2), cef_internal::CallbackForward(a3), - cef_internal::CallbackForward(a4), cef_internal::CallbackForward(a5), - cef_internal::CallbackForward(a6)); - } - - private: - typedef R (*PolymorphicInvoke)( - cef_internal::BindStateBase*, - typename cef_internal::CallbackParamTraits::ForwardType, - typename cef_internal::CallbackParamTraits::ForwardType, - typename cef_internal::CallbackParamTraits::ForwardType, - typename cef_internal::CallbackParamTraits::ForwardType, - typename cef_internal::CallbackParamTraits::ForwardType, - typename cef_internal::CallbackParamTraits::ForwardType); -}; - -template -class Callback - : public cef_internal::CallbackBase { - public: - typedef R(RunType)(A1, A2, A3, A4, A5, A6, A7); - - Callback() : CallbackBase(NULL) {} - - // Note that this constructor CANNOT be explicit, and that Bind() CANNOT - // return the exact Callback<> type. See base/bind.h for details. - template - Callback( - cef_internal::BindState* bind_state) - : CallbackBase(bind_state) { - // Force the assignment to a local variable of PolymorphicInvoke - // so the compiler will typecheck that the passed in Run() method has - // the correct type. - PolymorphicInvoke invoke_func = - &cef_internal::BindState::InvokerType::Run; - polymorphic_invoke_ = reinterpret_cast(invoke_func); - } - - bool Equals(const Callback& other) const { - return CallbackBase::Equals(other); - } - - R Run(typename cef_internal::CallbackParamTraits::ForwardType a1, - typename cef_internal::CallbackParamTraits::ForwardType a2, - typename cef_internal::CallbackParamTraits::ForwardType a3, - typename cef_internal::CallbackParamTraits::ForwardType a4, - typename cef_internal::CallbackParamTraits::ForwardType a5, - typename cef_internal::CallbackParamTraits::ForwardType a6, - typename cef_internal::CallbackParamTraits::ForwardType a7) const { - PolymorphicInvoke f = - reinterpret_cast(polymorphic_invoke_); - - return f( - bind_state_.get(), cef_internal::CallbackForward(a1), - cef_internal::CallbackForward(a2), cef_internal::CallbackForward(a3), - cef_internal::CallbackForward(a4), cef_internal::CallbackForward(a5), - cef_internal::CallbackForward(a6), cef_internal::CallbackForward(a7)); - } - - private: - typedef R (*PolymorphicInvoke)( - cef_internal::BindStateBase*, - typename cef_internal::CallbackParamTraits::ForwardType, - typename cef_internal::CallbackParamTraits::ForwardType, - typename cef_internal::CallbackParamTraits::ForwardType, - typename cef_internal::CallbackParamTraits::ForwardType, - typename cef_internal::CallbackParamTraits::ForwardType, - typename cef_internal::CallbackParamTraits::ForwardType, - typename cef_internal::CallbackParamTraits::ForwardType); -}; - -// Syntactic sugar to make Callbacks easier to declare since it -// will be used in a lot of APIs with delayed execution. -typedef Callback Closure; - } // namespace base #endif // !USING_CHROMIUM_INCLUDES diff --git a/src/include/base/cef_callback_forward.h b/src/include/base/cef_callback_forward.h index d604d7cfa..2d2277433 100644 --- a/src/include/base/cef_callback_forward.h +++ b/src/include/base/cef_callback_forward.h @@ -32,14 +32,9 @@ #define INCLUDE_BASE_CEF_CALLBACK_FORWARD_H_ #pragma once -#if defined(BASE_CALLBACK_FORWARD_H_) -// Do nothing if the Chromium header has already been included. -// This can happen in cases where Chromium code is used directly by the -// client application. When using Chromium code directly always include -// the Chromium header first to avoid type conflicts. -#elif defined(USING_CHROMIUM_INCLUDES) +#if defined(USING_CHROMIUM_INCLUDES) // When building CEF include the Chromium header directly. -#include "base/callback_forward.h" +#include "base/functional/callback_forward.h" #else // !USING_CHROMIUM_INCLUDES // The following is substantially similar to the Chromium implementation. // If the Chromium implementation diverges the below implementation should be @@ -47,10 +42,19 @@ namespace base { -template -class Callback; +template +class OnceCallback; -typedef Callback Closure; +template +class RepeatingCallback; + +/// +/// Syntactic sugar to make OnceClosure and RepeatingClosure +/// easier to declare since they will be used in a lot of APIs with delayed +/// execution. +/// +using OnceClosure = OnceCallback; +using RepeatingClosure = RepeatingCallback; } // namespace base diff --git a/src/include/base/cef_callback_helpers.h b/src/include/base/cef_callback_helpers.h index ebe074a1f..5e3864405 100644 --- a/src/include/base/cef_callback_helpers.h +++ b/src/include/base/cef_callback_helpers.h @@ -32,60 +32,228 @@ // are implemented using templates, with a class per callback signature, adding // methods to Callback<> itself is unattractive (lots of extra code gets // generated). Instead, consider adding methods here. -// -// ResetAndReturn(&cb) is like cb.Reset() but allows executing a callback (via a -// copy) after the original callback is Reset(). This can be handy if Run() -// reads/writes the variable holding the Callback. #ifndef CEF_INCLUDE_BASE_CEF_CALLBACK_HELPERS_H_ #define CEF_INCLUDE_BASE_CEF_CALLBACK_HELPERS_H_ #pragma once -#if defined(BASE_CALLBACK_HELPERS_H_) -// Do nothing if the Chromium header has already been included. -// This can happen in cases where Chromium code is used directly by the -// client application. When using Chromium code directly always include -// the Chromium header first to avoid type conflicts. -#elif defined(USING_CHROMIUM_INCLUDES) +#if defined(USING_CHROMIUM_INCLUDES) // When building CEF include the Chromium header directly. -#include "base/callback_helpers.h" +#include "base/functional/callback_helpers.h" #else // !USING_CHROMIUM_INCLUDES // The following is substantially similar to the Chromium implementation. // If the Chromium implementation diverges the below implementation should be // updated to match. -#include "include/base/cef_basictypes.h" -#include "include/base/cef_build.h" +#include +#include +#include +#include + +#include "include/base/cef_bind.h" #include "include/base/cef_callback.h" -#include "include/base/cef_macros.h" +#include "include/base/cef_logging.h" namespace base { -template -base::Callback ResetAndReturn(base::Callback* cb) { - base::Callback ret(*cb); - cb->Reset(); - return ret; +namespace internal { + +template +struct IsBaseCallbackImpl : std::false_type {}; + +template +struct IsBaseCallbackImpl> : std::true_type {}; + +template +struct IsBaseCallbackImpl> : std::true_type {}; + +template +struct IsOnceCallbackImpl : std::false_type {}; + +template +struct IsOnceCallbackImpl> : std::true_type {}; + +} // namespace internal + +/// +/// IsBaseCallback::value is true when T is any of the Closure or Callback +/// family of types. +/// +template +using IsBaseCallback = internal::IsBaseCallbackImpl>; + +/// +/// IsOnceCallback::value is true when T is a OnceClosure or OnceCallback +/// type. +/// +template +using IsOnceCallback = internal::IsOnceCallbackImpl>; + +/// +/// SFINAE friendly enabler allowing to overload methods for both Repeating and +/// OnceCallbacks. +/// +/// Usage: +///
+///   template