diff --git a/README.md b/README.md index 9e2cc4fa..8e6259bc 100644 --- a/README.md +++ b/README.md @@ -607,10 +607,10 @@ Additional information for v31.2 release: * [OnPreKeyEvent](api/KeyboardHandler.md#onprekeyevent) * [OnKeyEvent](api/KeyboardHandler.md#onkeyevent) * [LifespanHandler (interface)](api/LifespanHandler.md#lifespanhandler-interface) - * [OnBeforePopup](api/LifespanHandler.md#onbeforepopup) - * [_OnAfterCreated](api/LifespanHandler.md#_onaftercreated) * [DoClose](api/LifespanHandler.md#doclose) + * [_OnAfterCreated](api/LifespanHandler.md#_onaftercreated) * [OnBeforeClose](api/LifespanHandler.md#onbeforeclose) + * [OnBeforePopup](api/LifespanHandler.md#onbeforepopup) * [LoadHandler (interface)](api/LoadHandler.md#loadhandler-interface) * [OnLoadingStateChange](api/LoadHandler.md#onloadingstatechange) * [OnLoadStart](api/LoadHandler.md#onloadstart) @@ -703,19 +703,21 @@ Additional information for v31.2 release: * [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) * [OnBeforeResourceLoad](api/RequestHandler.md#onbeforeresourceload) - * [GetResourceHandler](api/RequestHandler.md#getresourcehandler) + * [_OnCertificateError](api/RequestHandler.md#_oncertificateerror) + * [OnQuotaRequest](api/RequestHandler.md#onquotarequest) * [OnResourceRedirect](api/RequestHandler.md#onresourceredirect) * [OnResourceResponse](api/RequestHandler.md#onresourceresponse) - * [GetAuthCredentials](api/RequestHandler.md#getauthcredentials) - * [OnQuotaRequest](api/RequestHandler.md#onquotarequest) - * [GetCookieManager](api/RequestHandler.md#getcookiemanager) + * [OnPluginCrashed](api/RequestHandler.md#onplugincrashed) * [OnProtocolExecution](api/RequestHandler.md#onprotocolexecution) - * [_OnBeforePluginLoad](api/RequestHandler.md#_onbeforepluginload) - * [_OnCertificateError](api/RequestHandler.md#_oncertificateerror) * [OnRendererProcessTerminated](api/RequestHandler.md#onrendererprocessterminated) - * [OnPluginCrashed](api/RequestHandler.md#onplugincrashed) * [ResourceHandler (interface)](api/ResourceHandler.md#resourcehandler-interface) * [ProcessRequest](api/ResourceHandler.md#processrequest) * [GetResponseHeaders](api/ResourceHandler.md#getresponseheaders) diff --git a/api/API-index.md b/api/API-index.md index 9946b5b5..d5e3efcb 100644 --- a/api/API-index.md +++ b/api/API-index.md @@ -295,10 +295,10 @@ * [OnPreKeyEvent](KeyboardHandler.md#onprekeyevent) * [OnKeyEvent](KeyboardHandler.md#onkeyevent) * [LifespanHandler (interface)](LifespanHandler.md#lifespanhandler-interface) - * [OnBeforePopup](LifespanHandler.md#onbeforepopup) - * [_OnAfterCreated](LifespanHandler.md#_onaftercreated) * [DoClose](LifespanHandler.md#doclose) + * [_OnAfterCreated](LifespanHandler.md#_onaftercreated) * [OnBeforeClose](LifespanHandler.md#onbeforeclose) + * [OnBeforePopup](LifespanHandler.md#onbeforepopup) * [LoadHandler (interface)](LoadHandler.md#loadhandler-interface) * [OnLoadingStateChange](LoadHandler.md#onloadingstatechange) * [OnLoadStart](LoadHandler.md#onloadstart) @@ -391,19 +391,21 @@ * [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) - * [GetResourceHandler](RequestHandler.md#getresourcehandler) + * [_OnCertificateError](RequestHandler.md#_oncertificateerror) + * [OnQuotaRequest](RequestHandler.md#onquotarequest) * [OnResourceRedirect](RequestHandler.md#onresourceredirect) * [OnResourceResponse](RequestHandler.md#onresourceresponse) - * [GetAuthCredentials](RequestHandler.md#getauthcredentials) - * [OnQuotaRequest](RequestHandler.md#onquotarequest) - * [GetCookieManager](RequestHandler.md#getcookiemanager) + * [OnPluginCrashed](RequestHandler.md#onplugincrashed) * [OnProtocolExecution](RequestHandler.md#onprotocolexecution) - * [_OnBeforePluginLoad](RequestHandler.md#_onbeforepluginload) - * [_OnCertificateError](RequestHandler.md#_oncertificateerror) * [OnRendererProcessTerminated](RequestHandler.md#onrendererprocessterminated) - * [OnPluginCrashed](RequestHandler.md#onplugincrashed) * [ResourceHandler (interface)](ResourceHandler.md#resourcehandler-interface) * [ProcessRequest](ResourceHandler.md#processrequest) * [GetResponseHeaders](ResourceHandler.md#getresponseheaders) diff --git a/api/LifespanHandler.md b/api/LifespanHandler.md index d3bad5c3..2b929512 100644 --- a/api/LifespanHandler.md +++ b/api/LifespanHandler.md @@ -3,22 +3,71 @@ # LifespanHandler (interface) -Implement this interface to handle events related to browser life span. The methods of this class will be called on the UI thread. +Implement this interface to handle events related to browser life span. +The methods of this class will be called on the UI thread. -For an example of how to implement a handler see [cefpython](cefpython.md).CreateBrowser(). For a list of all handler interfaces see [API > Client handlers](API#Client_handlers). +Related code snippets: +- [onbeforeclose.py](../examples/snippets/onbeforeclose.py) Table of contents: * [Callbacks](#callbacks) - * [OnBeforePopup](#onbeforepopup) - * [_OnAfterCreated](#_onaftercreated) * [DoClose](#doclose) + * [_OnAfterCreated](#_onaftercreated) * [OnBeforeClose](#onbeforeclose) + * [OnBeforePopup](#onbeforepopup) ## Callbacks +### DoClose + +| Parameter | Type | +| --- | --- | +| browser | [Browser](Browser.md) | +| __Return__ | bool | + +Called when a browser has recieved a request to close. This may result +directly from a call to [Browser](Browser.md).`CloseBrowser` or indirectly +if the +browser is a top-level OS window created by CEF and the user attempts to +close the window. This method will be called after the Javascript +'onunload' event has been fired. It will not be called for browsers after +the associated OS window has been destroyed (for those browsers it is no +longer possible to cancel the close). + +See complete description of this callback in [cef_life_span_handler.h] +(..|src|include|cef_life_span_handler.h). + + +### _OnAfterCreated + +| Parameter | Type | +| --- | --- | +| browser | [Browser](Browser.md) | +| __Return__ | void | + +Called after a new browser is created. This callback will be the first +notification that references |browser|. + +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. + + +### OnBeforeClose + +| Parameter | Type | +| --- | --- | +| browser | [Browser](Browser.md) | +| __Return__ | void | + +Called just before a browser is destroyed. Release all references to the +browser object and do not attempt to execute any methods on the browser +object after this callback returns. This callback will be the last +notification that references |browser|. See DoClose() documentation for +additional usage information. + + ### OnBeforePopup | Parameter | Type | @@ -73,50 +122,3 @@ There will be no "window.opener" property available in the popup window. * WOD_SAVE_TO_DISK, * WOD_OFF_THE_RECORD, * WOD_IGNORE_ACTION - - -### _OnAfterCreated - -| Parameter | Type | -| --- | --- | -| browser | [Browser](Browser.md) | -| __Return__ | void | - -Called after a new browser is created. This callback will be the first -notification that references |browser|. - -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. - - -### DoClose - -| Parameter | Type | -| --- | --- | -| browser | [Browser](Browser.md) | -| __Return__ | bool | - -Called when a browser has recieved a request to close. This may result -directly from a call to [Browser](Browser.md).`CloseBrowser` or indirectly -if the -browser is a top-level OS window created by CEF and the user attempts to -close the window. This method will be called after the Javascript -'onunload' event has been fired. It will not be called for browsers after -the associated OS window has been destroyed (for those browsers it is no -longer possible to cancel the close). - -See complete description of this callback in [cef_life_span_handler.h] -(..|src|include|cef_life_span_handler.h). - - -### OnBeforeClose - -| Parameter | Type | -| --- | --- | -| browser | [Browser](Browser.md) | -| __Return__ | void | - -Called just before a browser is destroyed. Release all references to the -browser object and do not attempt to execute any methods on the browser -object after this callback returns. This callback will be the last -notification that references |browser|. See DoClose() documentation for -additional usage information. diff --git a/api/RequestHandler.md b/api/RequestHandler.md index e7f48224..f1ef8bf7 100644 --- a/api/RequestHandler.md +++ b/api/RequestHandler.md @@ -4,134 +4,69 @@ # RequestHandler (interface) Implement this interface to handle events related to browser requests. +The methods of this class will be called on the thread indicated. -For an example of how to implement handler see -[cefpython](cefpython.md).CreateBrowserSync(). For a list of all handler -interfaces see [API > Client handlers](API#Client_handlers). - -The `RequestHandler` tests can be found in the old wxpython.py script (v31). - -Not yet exposed in CEF Python: -* OnOpenURLFromTab -* OnSelectClientCertificate +Related code snippets: +- [network_cookies.py](../examples/snippets/network_cookies.py) +Available in upstream CEF, but not yet exposed to CEF Python: +- OnOpenURLFromTab +- OnSelectClientCertificate Table of contents: * [Callbacks](#callbacks) + * [CanGetCookies](#cangetcookies) + * [CanSetCookie](#cansetcookie) + * [GetAuthCredentials](#getauthcredentials) + * [GetCookieManager](#getcookiemanager) + * [GetResourceHandler](#getresourcehandler) * [OnBeforeBrowse](#onbeforebrowse) + * [_OnBeforePluginLoad](#_onbeforepluginload) * [OnBeforeResourceLoad](#onbeforeresourceload) - * [GetResourceHandler](#getresourcehandler) + * [_OnCertificateError](#_oncertificateerror) + * [OnQuotaRequest](#onquotarequest) * [OnResourceRedirect](#onresourceredirect) * [OnResourceResponse](#onresourceresponse) - * [GetAuthCredentials](#getauthcredentials) - * [OnQuotaRequest](#onquotarequest) - * [GetCookieManager](#getcookiemanager) + * [OnPluginCrashed](#onplugincrashed) * [OnProtocolExecution](#onprotocolexecution) - * [_OnBeforePluginLoad](#_onbeforepluginload) - * [_OnCertificateError](#_oncertificateerror) * [OnRendererProcessTerminated](#onrendererprocessterminated) - * [OnPluginCrashed](#onplugincrashed) ## Callbacks -### OnBeforeBrowse +### CanGetCookies | Parameter | Type | | --- | --- | | browser | [Browser](Browser.md) | | frame | [Frame](Frame.md) | | request | [Request](Request.md) | -| user_gesture | bool | -| is_redirect | bool | | __Return__ | bool | Description from upstream CEF: -> Called on the UI thread before browser navigation. Return true to cancel -> the navigation or false to allow the navigation to proceed. The |request| -> object cannot be modified in this callback. -> CefLoadHandler::OnLoadingStateChange will be called twice in all cases. -> If the navigation is allowed CefLoadHandler::OnLoadStart and -> CefLoadHandler::OnLoadEnd will be called. If the navigation is canceled -> CefLoadHandler::OnLoadError will be called with an |errorCode| value of -> ERR_ABORTED. The |user_gesture| value will be true if the browser -> navigated via explicit user gesture (e.g. clicking a link) or false if it -> navigated automatically (e.g. via the DomContentLoaded event). +> 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. -### OnBeforeResourceLoad +### CanSetCookie | 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 request is loaded. The |request| -object may be modified. To cancel the request return true otherwise return -false. - - -### GetResourceHandler - -| Parameter | Type | -| --- | --- | -| browser | [Browser](Browser.md) | -| frame | [Frame](Frame.md) | -| request | [Request](Request.md) | -| __Return__ | [ResourceHandler](ResourceHandler.md) | - -Called on the IO thread before a resource is loaded. To allow the resource -to load normally return None. To specify a handler for the resource return -a [ResourceHandler](ResourceHandler.md) object. The |request| object should -not be modified in this callback. - -The [ResourceHandler](ResourceHandler.md) object is a python class that -implements the `ResourceHandler` callbacks. Remember to keep a strong -reference to this object while resource is being loaded. - -The `GetResourceHandler` example can be found in the old v31 -"wxpython-response.py" script on Linux. - - -### OnResourceRedirect - -| Parameter | Type | -| --- | --- | -| browser | [Browser](Browser.md) | -| frame | [Frame](Frame.md) | -| old_url | string | -| new_url_out | list[string] | -| request | [Request](Request.md) | -| response | [Response](Response.md) | -| __Return__ | void | - Description from upstream CEF: -> Called on the IO thread when a resource load is redirected. The |request| -> parameter will contain the old URL and other request-related information. -> The |response| parameter will contain the response that resulted in the -> redirect. The |new_url| parameter will contain the new URL and can be -> changed if desired. The |request| object cannot be modified in this -> callback. - - -### OnResourceResponse - -| | | -| --- | --- | -| __Return__ | void | - -Available in upstream CEF, but not yet exposed to CEF Python. -See Issue #229. - -You can implement this functionality by using -[ResourceHandler](ResourceHandler.md) and [WebRequest](WebRequest.md) -/ [WebRequestClient](WebRequestClient.md). For an example see the -_OnResourceResponse() method in the old v31 [wxpython-response.py] -example. +> 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 @@ -171,28 +106,6 @@ Example implementations: [[3]](https://github.com/cztomczak/cefpython/blob/cefpython31/cefpython/http_authentication_win.pyx). -### OnQuotaRequest - -| Parameter | Type | -| --- | --- | -| browser | [Browser](Browser.md) | -| origin_url | string | -| new_size | long | -| callback | RequestCallback | -| __Return__ | bool | - -Called on the IO thread when javascript requests a specific storage quota -size via the `webkitStorageInfo.requestQuota` function. |origin_url| is the -origin of the page making the request. |new_size| is the requested quota -size in bytes. Return true to continue the request and call -CefRequestCallback::Continue() either in this method or at a later time to -grant or deny the request. Return false to cancel the request immediately. - -The `RequestCallback` object methods: -* void Continue(bool allow) -* void Cancel() - - ### GetCookieManager | Parameter | Type | @@ -231,27 +144,50 @@ The `CreateAnotherBrowser` function from the old v31 wxpython example does that. - -### OnProtocolExecution +### GetResourceHandler | Parameter | Type | | --- | --- | | browser | [Browser](Browser.md) | -| url | string | -| allow_execution_out | list[bool] | -| __Return__ | void | +| frame | [Frame](Frame.md) | +| request | [Request](Request.md) | +| __Return__ | [ResourceHandler](ResourceHandler.md) | -Called on the UI thread to handle requests for URLs with an unknown -protocol component. Set |allow_execution_out[0]| to True to attempt -execution via the registered OS protocol handler, if any. +Called on the IO thread before a resource is loaded. To allow the resource +to load normally return None. To specify a handler for the resource return +a [ResourceHandler](ResourceHandler.md) object. The |request| object should +not be modified in this callback. -__SECURITY NOTE__: You should use this callback to enforce restrictions -based on scheme, host or other url analysis before allowing OS execution. +The [ResourceHandler](ResourceHandler.md) object is a python class that +implements the `ResourceHandler` callbacks. Remember to keep a strong +reference to this object while resource is being loaded. -There's no default implementation for OnProtocolExecution on Linux, -you have to make OS system call on your own. You probably also need -to use [LoadHandler](LoadHandler.md)::OnLoadError() when implementing -this on Linux. +The `GetResourceHandler` example can be found in the old v31 +"wxpython-response.py" script on Linux. + + +### OnBeforeBrowse + +| Parameter | Type | +| --- | --- | +| browser | [Browser](Browser.md) | +| frame | [Frame](Frame.md) | +| request | [Request](Request.md) | +| user_gesture | bool | +| is_redirect | bool | +| __Return__ | bool | + +Description from upstream CEF: +> Called on the UI thread before browser navigation. Return true to cancel +> the navigation or false to allow the navigation to proceed. The |request| +> object cannot be modified in this callback. +> CefLoadHandler::OnLoadingStateChange will be called twice in all cases. +> If the navigation is allowed CefLoadHandler::OnLoadStart and +> CefLoadHandler::OnLoadEnd will be called. If the navigation is canceled +> CefLoadHandler::OnLoadError will be called with an |errorCode| value of +> ERR_ABORTED. The |user_gesture| value will be true if the browser +> navigated via explicit user gesture (e.g. clicking a link) or false if it +> navigated automatically (e.g. via the DomContentLoaded event). ### _OnBeforePluginLoad @@ -284,7 +220,6 @@ Description from upstream CEF: > 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 @@ -297,6 +232,20 @@ This callback is called every time the page tries to load a plugin (perhaps even multiple times per plugin). +### OnBeforeResourceLoad + +| Parameter | Type | +| --- | --- | +| browser | [Browser](Browser.md) | +| frame | [Frame](Frame.md) | +| request | [Request](Request.md) | +| __Return__ | bool | + +Called on the IO thread before a resource request is loaded. The |request| +object may be modified. To cancel the request return true otherwise return +false. + + ### _OnCertificateError | Parameter | Type | @@ -323,21 +272,63 @@ The `RequestCallback` object methods: * void Cancel() -### OnRendererProcessTerminated +### OnQuotaRequest | Parameter | Type | | --- | --- | | browser | [Browser](Browser.md) | -| status | TerminationStatus | +| origin_url | string | +| new_size | long | +| callback | RequestCallback | +| __Return__ | bool | + +Called on the IO thread when javascript requests a specific storage quota +size via the `webkitStorageInfo.requestQuota` function. |origin_url| is the +origin of the page making the request. |new_size| is the requested quota +size in bytes. Return true to continue the request and call +CefRequestCallback::Continue() either in this method or at a later time to +grant or deny the request. Return false to cancel the request immediately. + +The `RequestCallback` object methods: +* void Continue(bool allow) +* void Cancel() + + +### OnResourceRedirect + +| Parameter | Type | +| --- | --- | +| browser | [Browser](Browser.md) | +| frame | [Frame](Frame.md) | +| old_url | string | +| new_url_out | list[string] | +| request | [Request](Request.md) | +| response | [Response](Response.md) | | __Return__ | void | -Called when the render process terminates unexpectedly. |status| indicates -how the process terminated. +Description from upstream CEF: +> Called on the IO thread when a resource load is redirected. The |request| +> parameter will contain the old URL and other request-related information. +> The |response| parameter will contain the response that resulted in the +> redirect. The |new_url| parameter will contain the new URL and can be +> changed if desired. The |request| object cannot be modified in this +> callback. -`TerminationStatus` constants in the cefpython module: - * TS_ABNORMAL_TERMINATION - Non-zero exit status. - * TS_PROCESS_WAS_KILLED - SIGKILL or task manager kill. - * TS_PROCESS_CRASHED - Segmentation fault. + +### OnResourceResponse + +| | | +| --- | --- | +| __Return__ | void | + +Available in upstream CEF, but not yet exposed to CEF Python. +See Issue #229. + +You can implement this functionality by using +[ResourceHandler](ResourceHandler.md) and [WebRequest](WebRequest.md) +/ [WebRequestClient](WebRequestClient.md). For an example see the +_OnResourceResponse() method in the old v31 [wxpython-response.py] +example. ### OnPluginCrashed @@ -350,3 +341,42 @@ how the process terminated. Called when a plugin has crashed. |plugin_path| is the path of the plugin that crashed. + + +### OnProtocolExecution + +| Parameter | Type | +| --- | --- | +| browser | [Browser](Browser.md) | +| url | string | +| allow_execution_out | list[bool] | +| __Return__ | void | + +Called on the UI thread to handle requests for URLs with an unknown +protocol component. Set |allow_execution_out[0]| to True to attempt +execution via the registered OS protocol handler, if any. + +__SECURITY NOTE__: You should use this callback to enforce restrictions +based on scheme, host or other url analysis before allowing OS execution. + +There's no default implementation for OnProtocolExecution on Linux, +you have to make OS system call on your own. You probably also need +to use [LoadHandler](LoadHandler.md)::OnLoadError() when implementing +this on Linux. + + +### OnRendererProcessTerminated + +| Parameter | Type | +| --- | --- | +| browser | [Browser](Browser.md) | +| status | TerminationStatus | +| __Return__ | void | + +Called when the render process terminates unexpectedly. |status| indicates +how the process terminated. + +`TerminationStatus` constants in the cefpython module: + * TS_ABNORMAL_TERMINATION - Non-zero exit status. + * TS_PROCESS_WAS_KILLED - SIGKILL or task manager kill. + * TS_PROCESS_CRASHED - Segmentation fault. diff --git a/examples/README-examples.md b/examples/README-examples.md index eb64b0d4..c4e98961 100644 --- a/examples/README-examples.md +++ b/examples/README-examples.md @@ -3,6 +3,11 @@ Table of contents: * [Hello World!](#hello-world) * [Supported examples](#supported-examples) + * [Featured](#featured) + * [GUI frameworks](#gui-frameworks) + * [Snippets](#snippets) + * [Build executable with PyInstaller](#build-executable-with-pyinstaller) + * [Unit tests](#unit-tests) * [Other examples](#other-examples) * [More examples to come](#more-examples-to-come) @@ -27,7 +32,7 @@ in sources to see whether this is a known issue with available workarounds. -**Featured** +### Featured - [hello_world.py](hello_world.py) - Basic example, doesn't require any third party GUI framework to run @@ -37,7 +42,7 @@ workarounds. discussed in great details in Tutorial in the [Off-screen rendering](../docs/Tutorial.md#off-screen-rendering) section. -**Embedding using various GUI frameworks** +### GUI frameworks - [gtk2.py](gtk2.py): example for [PyGTK](http://www.pygtk.org/) library (GTK 2) @@ -59,17 +64,25 @@ workarounds. toolkit. This example implements High DPI support on Windows. -**Build executable using Python packagers** +### Snippets + +See small code snippets that test various features in the +[examples/snippets/](snippets/) directory. + + +### Build executable with PyInstaller - [PyInstaller example](pyinstaller/README-pyinstaller.md): example of packaging app using [PyInstaller](http://www.pyinstaller.org/) - packager (currently example supports only Windows platform) + packager. Currently this example supports only Windows platform. -**Unit tests** +### Unit tests There are also available unit tests and its usage of the API can -be of some use. See [main_test.py](../unittests/main_test.py). +be of some use. See: +- [main_test.py](../unittests/main_test.py) - windowed rendering general tests +- [osr_test.py](../unittests/osr_test.py) - off-screen rendering tests ## Other examples diff --git a/examples/snippets/network_cookies.py b/examples/snippets/network_cookies.py new file mode 100644 index 00000000..ec5e474e --- /dev/null +++ b/examples/snippets/network_cookies.py @@ -0,0 +1,47 @@ +# Implement RequestHandler.CanGetCookies and CanSetCookie +# to block or allow cookies over network requests. + +from cefpython3 import cefpython as cef + + +def main(): + cef.Initialize() + browser = cef.CreateBrowserSync( + url="http://www.html-kit.com/tools/cookietester/", + window_title="Network cookies") + browser.SetClientHandler(RequestHandler()) + cef.MessageLoop() + del browser + cef.Shutdown() + + +class RequestHandler(object): + def __init__(self): + self.getcount = 0 + self.setcount = 0 + + def CanGetCookies(self, frame, request, **_): + # 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("url="+request.GetUrl()[0:80]) + print("") + return True + + def CanSetCookie(self, frame, request, 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("url="+request.GetUrl()[0:80]) + print("Name="+cookie.GetName()) + print("Value="+cookie.GetValue()) + print("") + return True + + +if __name__ == '__main__': + main() diff --git a/src/browser.pyx b/src/browser.pyx index c6060d44..34f5e4df 100644 --- a/src/browser.pyx +++ b/src/browser.pyx @@ -248,7 +248,7 @@ cdef class PyBrowser: "OnQuotaRequest", "OnProtocolExecution", "GetResourceHandler", "OnBeforeBrowse", "OnRendererProcessTerminated", - "OnPluginCrashed"] + "OnPluginCrashed", "CanGetCookies", "CanSetCookie"] # RequestContextHandler self.allowedClientCallbacks += ["GetCookieManager"] # LoadHandler diff --git a/src/cef_v59..v66_changes.txt b/src/cef_v59..v66_changes.txt index e6dbfb2c..f1e3c287 100644 --- a/src/cef_v59..v66_changes.txt +++ b/src/cef_v59..v66_changes.txt @@ -78,6 +78,9 @@ NEW FEATURES + Browser.GetSetting + cefpython.GetBrowserByIdentifier + Browser.HasDevTools ++ examples/snippets/ + + onbeforeclose.py + + network_cookies.py internal/cef_types.h + cef_log_severity_t: new key LOGSEVERITY_DEBUG (no need to expose, @@ -137,8 +140,8 @@ cef_file_util.h + CefLoadCRLSetsFile cef_request_handler.h -- CanGetCookies -- CanSetCookie ++ CanGetCookies ++ CanSetCookie cef_response.h - GetURL diff --git a/src/client_handler/request_handler.cpp b/src/client_handler/request_handler.cpp index ea681559..5227b892 100644 --- a/src/client_handler/request_handler.cpp +++ b/src/client_handler/request_handler.cpp @@ -117,3 +117,18 @@ void RequestHandler::OnPluginCrashed(CefRefPtr browser, 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 a56760b2..7e5e0e6c 100644 --- a/src/client_handler/request_handler.h +++ b/src/client_handler/request_handler.h @@ -67,6 +67,15 @@ class RequestHandler : public CefRequestHandler 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/handlers/request_handler.pyx b/src/handlers/request_handler.pyx index d89c5a1b..866942bf 100644 --- a/src/handlers/request_handler.pyx +++ b/src/handlers/request_handler.pyx @@ -4,6 +4,7 @@ include "../cefpython.pyx" include "../browser.pyx" +include "../cookie.pyx" # cef_termination_status_t cimport cef_types @@ -512,3 +513,75 @@ cdef public void RequestHandler_OnPluginCrashed( 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)