diff --git a/cef.gyp b/cef.gyp index f070e2255..e24790e97 100644 --- a/cef.gyp +++ b/cef.gyp @@ -994,7 +994,6 @@ 'libcef/browser/scheme_handler.cc', 'libcef/browser/scheme_handler.h', 'libcef/browser/scheme_impl.cc', - 'libcef/browser/scheme_impl.h', 'libcef/browser/software_output_device_osr.cc', 'libcef/browser/software_output_device_osr.h', 'libcef/browser/speech_recognition_manager_delegate.cc', @@ -1021,6 +1020,8 @@ 'libcef/browser/url_request_context_impl.h', 'libcef/browser/url_request_context_proxy.cc', 'libcef/browser/url_request_context_proxy.h', + 'libcef/browser/url_request_manager.cc', + 'libcef/browser/url_request_manager.h', 'libcef/browser/url_request_interceptor.cc', 'libcef/browser/url_request_interceptor.h', 'libcef/browser/url_request_user_data.cc', diff --git a/cef_paths.gypi b/cef_paths.gypi index e3ba4f4a9..8620070e7 100644 --- a/cef_paths.gypi +++ b/cef_paths.gypi @@ -164,6 +164,8 @@ 'libcef_dll/cpptoc/domnode_cpptoc.h', 'libcef_dll/ctocpp/domvisitor_ctocpp.cc', 'libcef_dll/ctocpp/domvisitor_ctocpp.h', + 'libcef_dll/ctocpp/delete_cookies_callback_ctocpp.cc', + 'libcef_dll/ctocpp/delete_cookies_callback_ctocpp.h', 'libcef_dll/ctocpp/dialog_handler_ctocpp.cc', 'libcef_dll/ctocpp/dialog_handler_ctocpp.h', 'libcef_dll/cpptoc/dictionary_value_cpptoc.cc', @@ -260,6 +262,8 @@ 'libcef_dll/ctocpp/scheme_handler_factory_ctocpp.h', 'libcef_dll/cpptoc/scheme_registrar_cpptoc.cc', 'libcef_dll/cpptoc/scheme_registrar_cpptoc.h', + 'libcef_dll/ctocpp/set_cookie_callback_ctocpp.cc', + 'libcef_dll/ctocpp/set_cookie_callback_ctocpp.h', 'libcef_dll/cpptoc/stream_reader_cpptoc.cc', 'libcef_dll/cpptoc/stream_reader_cpptoc.h', 'libcef_dll/cpptoc/stream_writer_cpptoc.cc', @@ -340,6 +344,8 @@ 'libcef_dll/ctocpp/domnode_ctocpp.h', 'libcef_dll/cpptoc/domvisitor_cpptoc.cc', 'libcef_dll/cpptoc/domvisitor_cpptoc.h', + 'libcef_dll/cpptoc/delete_cookies_callback_cpptoc.cc', + 'libcef_dll/cpptoc/delete_cookies_callback_cpptoc.h', 'libcef_dll/cpptoc/dialog_handler_cpptoc.cc', 'libcef_dll/cpptoc/dialog_handler_cpptoc.h', 'libcef_dll/ctocpp/dictionary_value_ctocpp.cc', @@ -436,6 +442,8 @@ 'libcef_dll/cpptoc/scheme_handler_factory_cpptoc.h', 'libcef_dll/ctocpp/scheme_registrar_ctocpp.cc', 'libcef_dll/ctocpp/scheme_registrar_ctocpp.h', + 'libcef_dll/cpptoc/set_cookie_callback_cpptoc.cc', + 'libcef_dll/cpptoc/set_cookie_callback_cpptoc.h', 'libcef_dll/ctocpp/stream_reader_ctocpp.cc', 'libcef_dll/ctocpp/stream_reader_ctocpp.h', 'libcef_dll/ctocpp/stream_writer_ctocpp.cc', diff --git a/include/capi/cef_cookie_capi.h b/include/capi/cef_cookie_capi.h index 82c4dffa2..eb62b1f14 100644 --- a/include/capi/cef_cookie_capi.h +++ b/include/capi/cef_cookie_capi.h @@ -46,6 +46,8 @@ extern "C" { #endif struct _cef_cookie_visitor_t; +struct _cef_delete_cookies_callback_t; +struct _cef_set_cookie_callback_t; /// // Structure used for managing cookies. The functions of this structure may be @@ -59,25 +61,27 @@ typedef struct _cef_cookie_manager_t { /// // Set the schemes supported by this manager. By default only "http" and - // "https" schemes are supported. Must be called before any cookies are - // accessed. + // "https" schemes are supported. If |callback| is non-NULL it will be + // executed asnychronously on the IO thread after the change has been applied. + // Must be called before any cookies are accessed. /// void (CEF_CALLBACK *set_supported_schemes)(struct _cef_cookie_manager_t* self, - cef_string_list_t schemes); + cef_string_list_t schemes, struct _cef_completion_callback_t* callback); /// - // Visit all cookies. The returned cookies are ordered by longest path, then - // by earliest creation date. Returns false (0) if cookies cannot be accessed. + // Visit all cookies on the IO thread. The returned cookies are ordered by + // longest path, then by earliest creation date. Returns false (0) if cookies + // cannot be accessed. /// int (CEF_CALLBACK *visit_all_cookies)(struct _cef_cookie_manager_t* self, struct _cef_cookie_visitor_t* visitor); /// - // Visit a subset of cookies. The results are filtered by the given url - // scheme, host, domain and path. If |includeHttpOnly| is true (1) HTTP-only - // cookies will also be included in the results. The returned cookies are - // ordered by longest path, then by earliest creation date. Returns false (0) - // if cookies cannot be accessed. + // Visit a subset of cookies on the IO thread. The results are filtered by the + // given url scheme, host, domain and path. If |includeHttpOnly| is true (1) + // HTTP-only cookies will also be included in the results. The returned + // cookies are ordered by longest path, then by earliest creation date. + // Returns false (0) if cookies cannot be accessed. /// int (CEF_CALLBACK *visit_url_cookies)(struct _cef_cookie_manager_t* self, const cef_string_t* url, int includeHttpOnly, @@ -87,24 +91,29 @@ typedef struct _cef_cookie_manager_t { // Sets a cookie given a valid URL and explicit user-provided cookie // attributes. This function expects each attribute to be well-formed. It will // check for disallowed characters (e.g. the ';' character is disallowed - // within the cookie value attribute) and will return false (0) without - // setting the cookie if such characters are found. This function must be - // called on the IO thread. + // within the cookie value attribute) and fail without setting the cookie if + // such characters are found. If |callback| is non-NULL it will be executed + // asnychronously on the IO thread after the cookie has been set. Returns + // false (0) if an invalid URL is specified or if cookies cannot be accessed. /// int (CEF_CALLBACK *set_cookie)(struct _cef_cookie_manager_t* self, - const cef_string_t* url, const struct _cef_cookie_t* cookie); + const cef_string_t* url, const struct _cef_cookie_t* cookie, + struct _cef_set_cookie_callback_t* callback); /// // Delete all cookies that match the specified parameters. If both |url| and - // values |cookie_name| are specified all host and domain cookies matching + // |cookie_name| values are specified all host and domain cookies matching // both will be deleted. If only |url| is specified all host cookies (but not // domain cookies) irrespective of path will be deleted. If |url| is NULL all - // cookies for all hosts and domains will be deleted. Returns false (0) if a - // non- NULL invalid URL is specified or if cookies cannot be accessed. This - // function must be called on the IO thread. + // cookies for all hosts and domains will be deleted. If |callback| is non- + // NULL it will be executed asnychronously on the IO thread after the cookies + // have been deleted. Returns false (0) if a non-NULL invalid URL is specified + // or if cookies cannot be accessed. Cookies can alternately be deleted using + // the Visit*Cookies() functions. /// int (CEF_CALLBACK *delete_cookies)(struct _cef_cookie_manager_t* self, - const cef_string_t* url, const cef_string_t* cookie_name); + const cef_string_t* url, const cef_string_t* cookie_name, + struct _cef_delete_cookies_callback_t* callback); /// // Sets the directory path that will be used for storing cookie data. If @@ -112,16 +121,18 @@ typedef struct _cef_cookie_manager_t { // stored at the specified |path|. To persist session cookies (cookies without // an expiry date or validity interval) set |persist_session_cookies| to true // (1). Session cookies are generally intended to be transient and most Web - // browsers do not persist them. Returns false (0) if cookies cannot be - // accessed. + // browsers do not persist them. If |callback| is non-NULL it will be executed + // asnychronously on the IO thread after the manager's storage has been + // initialized. Returns false (0) if cookies cannot be accessed. /// int (CEF_CALLBACK *set_storage_path)(struct _cef_cookie_manager_t* self, - const cef_string_t* path, int persist_session_cookies); + const cef_string_t* path, int persist_session_cookies, + struct _cef_completion_callback_t* callback); /// - // Flush the backing store (if any) to disk and execute the specified - // |callback| on the IO thread when done. Returns false (0) if cookies cannot - // be accessed. + // Flush the backing store (if any) to disk. If |callback| is non-NULL it will + // be executed asnychronously on the IO thread after the flush is complete. + // Returns false (0) if cookies cannot be accessed. /// int (CEF_CALLBACK *flush_store)(struct _cef_cookie_manager_t* self, struct _cef_completion_callback_t* callback); @@ -130,20 +141,27 @@ typedef struct _cef_cookie_manager_t { /// // Returns the global cookie manager. By default data will be stored at -// CefSettings.cache_path if specified or in memory otherwise. +// CefSettings.cache_path if specified or in memory otherwise. If |callback| is +// non-NULL it will be executed asnychronously on the IO thread after the +// manager's storage has been initialized. Using this function is equivalent to +// calling cef_request_tContext::cef_request_context_get_global_context()->get_d +// efault_cookie_manager(). /// -CEF_EXPORT cef_cookie_manager_t* cef_cookie_manager_get_global_manager(); +CEF_EXPORT cef_cookie_manager_t* cef_cookie_manager_get_global_manager( + struct _cef_completion_callback_t* callback); /// // Creates a new cookie manager. If |path| is NULL data will be stored in memory // only. Otherwise, data will be stored at the specified |path|. To persist // session cookies (cookies without an expiry date or validity interval) set // |persist_session_cookies| to true (1). Session cookies are generally intended -// to be transient and most Web browsers do not persist them. Returns NULL if -// creation fails. +// to be transient and most Web browsers do not persist them. If |callback| is +// non-NULL it will be executed asnychronously on the IO thread after the +// manager's storage has been initialized. /// CEF_EXPORT cef_cookie_manager_t* cef_cookie_manager_create_manager( - const cef_string_t* path, int persist_session_cookies); + const cef_string_t* path, int persist_session_cookies, + struct _cef_completion_callback_t* callback); /// @@ -169,6 +187,44 @@ typedef struct _cef_cookie_visitor_t { } cef_cookie_visitor_t; +/// +// Structure to implement to be notified of asynchronous completion via +// cef_cookie_manager_t::set_cookie(). +/// +typedef struct _cef_set_cookie_callback_t { + /// + // Base structure. + /// + cef_base_t base; + + /// + // Method that will be called upon completion. |success| will be true (1) if + // the cookie was set successfully. + /// + void (CEF_CALLBACK *on_complete)(struct _cef_set_cookie_callback_t* self, + int success); +} cef_set_cookie_callback_t; + + +/// +// Structure to implement to be notified of asynchronous completion via +// cef_cookie_manager_t::delete_cookies(). +/// +typedef struct _cef_delete_cookies_callback_t { + /// + // Base structure. + /// + cef_base_t base; + + /// + // Method that will be called upon completion. |num_deleted| will be the + // number of cookies that were deleted or -1 if unknown. + /// + void (CEF_CALLBACK *on_complete)(struct _cef_delete_cookies_callback_t* self, + int num_deleted); +} cef_delete_cookies_callback_t; + + #ifdef __cplusplus } #endif diff --git a/include/capi/cef_request_context_capi.h b/include/capi/cef_request_context_capi.h index 65e9dfe8a..5c8d24d39 100644 --- a/include/capi/cef_request_context_capi.h +++ b/include/capi/cef_request_context_capi.h @@ -38,27 +38,30 @@ #define CEF_INCLUDE_CAPI_CEF_REQUEST_CONTEXT_CAPI_H_ #pragma once +#include "include/capi/cef_cookie_capi.h" #include "include/capi/cef_request_context_handler_capi.h" #ifdef __cplusplus extern "C" { #endif +struct _cef_scheme_handler_factory_t; /// -// A request context provides request handling for a set of related browser -// objects. A request context is specified when creating a new browser object -// via the cef_browser_host_t static factory functions. Browser objects with -// different request contexts will never be hosted in the same render process. -// Browser objects with the same request context may or may not be hosted in the -// same render process depending on the process model. Browser objects created -// indirectly via the JavaScript window.open function or targeted links will -// share the same render process and the same request context as the source -// browser. When running in single-process mode there is only a single render -// process (the main process) and so all browsers created in single-process mode -// will share the same request context. This will be the first request context -// passed into a cef_browser_host_t static factory function and all other -// request context objects will be ignored. +// A request context provides request handling for a set of related browser or +// URL request objects. A request context can be specified when creating a new +// browser via the cef_browser_host_t static factory functions or when creating +// a new URL request via the cef_urlrequest_t static factory functions. Browser +// objects with different request contexts will never be hosted in the same +// render process. Browser objects with the same request context may or may not +// be hosted in the same render process depending on the process model. Browser +// objects created indirectly via the JavaScript window.open function or +// targeted links will share the same render process and the same request +// context as the source browser. When running in single-process mode there is +// only a single render process (the main process) and so all browsers created +// in single-process mode will share the same request context. This will be the +// first request context passed into a cef_browser_host_t static factory +// function and all other request context objects will be ignored. /// typedef struct _cef_request_context_t { /// @@ -74,7 +77,16 @@ typedef struct _cef_request_context_t { struct _cef_request_context_t* other); /// - // Returns true (1) if this object is the global context. + // Returns true (1) if this object is sharing the same storage as |that| + // object. + /// + int (CEF_CALLBACK *is_sharing_with)(struct _cef_request_context_t* self, + struct _cef_request_context_t* other); + + /// + // Returns true (1) if this object is the global context. The global context + // is used by default when creating a browser or URL request with a NULL + // context argument. /// int (CEF_CALLBACK *is_global)(struct _cef_request_context_t* self); @@ -83,6 +95,51 @@ typedef struct _cef_request_context_t { /// struct _cef_request_context_handler_t* (CEF_CALLBACK *get_handler)( struct _cef_request_context_t* self); + + /// + // Returns the cache path for this object. If NULL an "incognito mode" in- + // memory cache is being used. + /// + // The resulting string must be freed by calling cef_string_userfree_free(). + cef_string_userfree_t (CEF_CALLBACK *get_cache_path)( + struct _cef_request_context_t* self); + + /// + // Returns the default cookie manager for this object. This will be the global + // cookie manager if this object is the global request context. Otherwise, + // this will be the default cookie manager used when this request context does + // not receive a value via cef_request_tContextHandler::get_cookie_manager(). + // If |callback| is non-NULL it will be executed asnychronously on the IO + // thread after the manager's storage has been initialized. + /// + struct _cef_cookie_manager_t* (CEF_CALLBACK *get_default_cookie_manager)( + struct _cef_request_context_t* self, + struct _cef_completion_callback_t* callback); + + /// + // Register a scheme handler factory for the specified |scheme_name| and + // optional |domain_name|. An NULL |domain_name| value for a standard scheme + // will cause the factory to match all domain names. The |domain_name| value + // will be ignored for non-standard schemes. If |scheme_name| is a built-in + // scheme and no handler is returned by |factory| then the built-in scheme + // handler factory will be called. If |scheme_name| is a custom scheme then + // you must also implement the cef_app_t::on_register_custom_schemes() + // function in all processes. This function may be called multiple times to + // change or remove the factory that matches the specified |scheme_name| and + // optional |domain_name|. Returns false (0) if an error occurs. This function + // may be called on any thread in the browser process. + /// + int (CEF_CALLBACK *register_scheme_handler_factory)( + struct _cef_request_context_t* self, const cef_string_t* scheme_name, + const cef_string_t* domain_name, + struct _cef_scheme_handler_factory_t* factory); + + /// + // Clear all registered scheme handler factories. Returns false (0) on error. + // This function may be called on any thread in the browser process. + /// + int (CEF_CALLBACK *clear_scheme_handler_factories)( + struct _cef_request_context_t* self); } cef_request_context_t; @@ -92,9 +149,19 @@ typedef struct _cef_request_context_t { CEF_EXPORT cef_request_context_t* cef_request_context_get_global_context(); /// -// Creates a new context object with the specified handler. +// Creates a new context object with the specified |settings| and optional +// |handler|. /// CEF_EXPORT cef_request_context_t* cef_request_context_create_context( + const struct _cef_request_context_settings_t* settings, + struct _cef_request_context_handler_t* handler); + +/// +// Creates a new context object that shares storage with |other| and uses an +// optional |handler|. +/// +CEF_EXPORT cef_request_context_t* create_context_shared( + cef_request_context_t* other, struct _cef_request_context_handler_t* handler); diff --git a/include/capi/cef_request_context_handler_capi.h b/include/capi/cef_request_context_handler_capi.h index 4c6934832..09716402c 100644 --- a/include/capi/cef_request_context_handler_capi.h +++ b/include/capi/cef_request_context_handler_capi.h @@ -47,7 +47,9 @@ extern "C" { /// -// Implement this structure to provide handler implementations. +// Implement this structure to provide handler implementations. The handler +// instance will not be released until all objects related to the context have +// been destroyed. /// typedef struct _cef_request_context_handler_t { /// @@ -56,8 +58,9 @@ typedef struct _cef_request_context_handler_t { cef_base_t base; /// - // Called on the IO thread to retrieve the cookie manager. The global cookie - // manager will be used if this function returns NULL. + // Called on the IO thread to retrieve the cookie manager. If this function + // returns NULL the default cookie manager retrievable via + // cef_request_tContext::get_default_cookie_manager() will be used. /// struct _cef_cookie_manager_t* (CEF_CALLBACK *get_cookie_manager)( struct _cef_request_context_handler_t* self); diff --git a/include/capi/cef_scheme_capi.h b/include/capi/cef_scheme_capi.h index e046aaaba..7fb15da20 100644 --- a/include/capi/cef_scheme_capi.h +++ b/include/capi/cef_scheme_capi.h @@ -139,25 +139,30 @@ typedef struct _cef_scheme_handler_factory_t { /// -// Register a scheme handler factory for the specified |scheme_name| and -// optional |domain_name|. An NULL |domain_name| value for a standard scheme -// will cause the factory to match all domain names. The |domain_name| value -// will be ignored for non-standard schemes. If |scheme_name| is a built-in -// scheme and no handler is returned by |factory| then the built-in scheme -// handler factory will be called. If |scheme_name| is a custom scheme then also -// implement the cef_app_t::on_register_custom_schemes() function in all -// processes. This function may be called multiple times to change or remove the -// factory that matches the specified |scheme_name| and optional |domain_name|. -// Returns false (0) if an error occurs. This function may be called on any -// thread in the browser process. +// Register a scheme handler factory with the global request context. An NULL +// |domain_name| value for a standard scheme will cause the factory to match all +// domain names. The |domain_name| value will be ignored for non-standard +// schemes. If |scheme_name| is a built-in scheme and no handler is returned by +// |factory| then the built-in scheme handler factory will be called. If +// |scheme_name| is a custom scheme then you must also implement the +// cef_app_t::on_register_custom_schemes() function in all processes. This +// function may be called multiple times to change or remove the factory that +// matches the specified |scheme_name| and optional |domain_name|. Returns false +// (0) if an error occurs. This function may be called on any thread in the +// browser process. Using this function is equivalent to calling cef_request_tCo +// ntext::cef_request_context_get_global_context()->register_scheme_handler_fact +// ory(). /// CEF_EXPORT int cef_register_scheme_handler_factory( const cef_string_t* scheme_name, const cef_string_t* domain_name, cef_scheme_handler_factory_t* factory); /// -// Clear all registered scheme handler factories. Returns false (0) on error. -// This function may be called on any thread in the browser process. +// Clear all scheme handler factories registered with the global request +// context. Returns false (0) on error. This function may be called on any +// thread in the browser process. Using this function is equivalent to calling c +// ef_request_tContext::cef_request_context_get_global_context()->clear_scheme_h +// andler_factories(). /// CEF_EXPORT int cef_clear_scheme_handler_factories(); diff --git a/include/capi/cef_urlrequest_capi.h b/include/capi/cef_urlrequest_capi.h index cf95f268b..63edbd18b 100644 --- a/include/capi/cef_urlrequest_capi.h +++ b/include/capi/cef_urlrequest_capi.h @@ -41,6 +41,7 @@ #include "include/capi/cef_auth_callback_capi.h" #include "include/capi/cef_base_capi.h" #include "include/capi/cef_request_capi.h" +#include "include/capi/cef_request_context_capi.h" #include "include/capi/cef_response_capi.h" #ifdef __cplusplus @@ -113,10 +114,14 @@ typedef struct _cef_urlrequest_t { // not normally be rendered then the response may receive special handling // inside the browser (for example, via the file download code path instead of // the URL request code path). The |request| object will be marked as read-only -// after calling this function. +// after calling this function. In the browser process if |request_context| is +// NULL the global request context will be used. In the render process +// |request_context| must be NULL and the context associated with the current +// renderer process' browser will be used. /// CEF_EXPORT cef_urlrequest_t* cef_urlrequest_create( - struct _cef_request_t* request, struct _cef_urlrequest_client_t* client); + struct _cef_request_t* request, struct _cef_urlrequest_client_t* client, + struct _cef_request_context_t* request_context); /// diff --git a/include/cef_cookie.h b/include/cef_cookie.h index 73506dc46..e1eb0e4bf 100644 --- a/include/cef_cookie.h +++ b/include/cef_cookie.h @@ -43,7 +43,8 @@ #include class CefCookieVisitor; - +class CefSetCookieCallback; +class CefDeleteCookiesCallback; /// // Class used for managing cookies. The methods of this class may be called on @@ -54,10 +55,14 @@ class CefCookieManager : public virtual CefBase { public: /// // Returns the global cookie manager. By default data will be stored at - // CefSettings.cache_path if specified or in memory otherwise. + // CefSettings.cache_path if specified or in memory otherwise. If |callback| + // is non-NULL it will be executed asnychronously on the IO thread after the + // manager's storage has been initialized. Using this method is equivalent to + // calling CefRequestContext::GetGlobalContext()->GetDefaultCookieManager(). /// - /*--cef()--*/ - static CefRefPtr GetGlobalManager(); + /*--cef(optional_param=callback)--*/ + static CefRefPtr GetGlobalManager( + CefRefPtr callback); /// // Creates a new cookie manager. If |path| is empty data will be stored in @@ -65,81 +70,98 @@ class CefCookieManager : public virtual CefBase { // persist session cookies (cookies without an expiry date or validity // interval) set |persist_session_cookies| to true. Session cookies are // generally intended to be transient and most Web browsers do not persist - // them. Returns NULL if creation fails. + // them. If |callback| is non-NULL it will be executed asnychronously on the + // IO thread after the manager's storage has been initialized. /// - /*--cef(optional_param=path)--*/ + /*--cef(optional_param=path,optional_param=callback)--*/ static CefRefPtr CreateManager( const CefString& path, - bool persist_session_cookies); + bool persist_session_cookies, + CefRefPtr callback); /// // Set the schemes supported by this manager. By default only "http" and - // "https" schemes are supported. Must be called before any cookies are - // accessed. + // "https" schemes are supported. If |callback| is non-NULL it will be + // executed asnychronously on the IO thread after the change has been applied. + // Must be called before any cookies are accessed. /// - /*--cef()--*/ - virtual void SetSupportedSchemes(const std::vector& schemes) =0; + /*--cef(optional_param=callback)--*/ + virtual void SetSupportedSchemes( + const std::vector& schemes, + CefRefPtr callback) =0; /// - // Visit all cookies. The returned cookies are ordered by longest path, then - // by earliest creation date. Returns false if cookies cannot be accessed. + // Visit all cookies on the IO thread. The returned cookies are ordered by + // longest path, then by earliest creation date. Returns false if cookies + // cannot be accessed. /// /*--cef()--*/ virtual bool VisitAllCookies(CefRefPtr visitor) =0; /// - // Visit a subset of cookies. The results are filtered by the given url - // scheme, host, domain and path. If |includeHttpOnly| is true HTTP-only - // cookies will also be included in the results. The returned cookies are - // ordered by longest path, then by earliest creation date. Returns false if - // cookies cannot be accessed. + // Visit a subset of cookies on the IO thread. The results are filtered by the + // given url scheme, host, domain and path. If |includeHttpOnly| is true + // HTTP-only cookies will also be included in the results. The returned + // cookies are ordered by longest path, then by earliest creation date. + // Returns false if cookies cannot be accessed. /// /*--cef()--*/ - virtual bool VisitUrlCookies(const CefString& url, bool includeHttpOnly, + virtual bool VisitUrlCookies(const CefString& url, + bool includeHttpOnly, CefRefPtr visitor) =0; /// // Sets a cookie given a valid URL and explicit user-provided cookie // attributes. This function expects each attribute to be well-formed. It will // check for disallowed characters (e.g. the ';' character is disallowed - // within the cookie value attribute) and will return false without setting - // the cookie if such characters are found. This method must be called on the - // IO thread. + // within the cookie value attribute) and fail without setting the cookie if + // such characters are found. If |callback| is non-NULL it will be executed + // asnychronously on the IO thread after the cookie has been set. Returns + // false if an invalid URL is specified or if cookies cannot be accessed. /// - /*--cef()--*/ - virtual bool SetCookie(const CefString& url, const CefCookie& cookie) =0; + /*--cef(optional_param=callback)--*/ + virtual bool SetCookie(const CefString& url, + const CefCookie& cookie, + CefRefPtr callback) =0; /// // Delete all cookies that match the specified parameters. If both |url| and - // values |cookie_name| are specified all host and domain cookies matching + // |cookie_name| values are specified all host and domain cookies matching // both will be deleted. If only |url| is specified all host cookies (but not // domain cookies) irrespective of path will be deleted. If |url| is empty all - // cookies for all hosts and domains will be deleted. Returns false if a non- - // empty invalid URL is specified or if cookies cannot be accessed. This - // method must be called on the IO thread. + // cookies for all hosts and domains will be deleted. If |callback| is + // non-NULL it will be executed asnychronously on the IO thread after the + // cookies have been deleted. Returns false if a non-empty invalid URL is + // specified or if cookies cannot be accessed. Cookies can alternately be + // deleted using the Visit*Cookies() methods. /// - /*--cef(optional_param=url,optional_param=cookie_name)--*/ + /*--cef(optional_param=url,optional_param=cookie_name, + optional_param=callback)--*/ virtual bool DeleteCookies(const CefString& url, - const CefString& cookie_name) =0; + const CefString& cookie_name, + CefRefPtr callback) =0; /// // Sets the directory path that will be used for storing cookie data. If // |path| is empty data will be stored in memory only. Otherwise, data will be // stored at the specified |path|. To persist session cookies (cookies without // an expiry date or validity interval) set |persist_session_cookies| to true. - // Session cookies are generally intended to be transient and most Web browsers - // do not persist them. Returns false if cookies cannot be accessed. + // Session cookies are generally intended to be transient and most Web + // browsers do not persist them. If |callback| is non-NULL it will be executed + // asnychronously on the IO thread after the manager's storage has been + // initialized. Returns false if cookies cannot be accessed. /// - /*--cef(optional_param=path)--*/ + /*--cef(optional_param=path,optional_param=callback)--*/ virtual bool SetStoragePath(const CefString& path, - bool persist_session_cookies) =0; + bool persist_session_cookies, + CefRefPtr callback) =0; /// - // Flush the backing store (if any) to disk and execute the specified - // |callback| on the IO thread when done. Returns false if cookies cannot be - // accessed. + // Flush the backing store (if any) to disk. If |callback| is non-NULL it will + // be executed asnychronously on the IO thread after the flush is complete. + // Returns false if cookies cannot be accessed. /// - /*--cef(optional_param=handler)--*/ + /*--cef(optional_param=callback)--*/ virtual bool FlushStore(CefRefPtr callback) =0; }; @@ -163,4 +185,36 @@ class CefCookieVisitor : public virtual CefBase { bool& deleteCookie) =0; }; + +/// +// Interface to implement to be notified of asynchronous completion via +// CefCookieManager::SetCookie(). +/// +/*--cef(source=client)--*/ +class CefSetCookieCallback : public virtual CefBase { + public: + /// + // Method that will be called upon completion. |success| will be true if the + // cookie was set successfully. + /// + /*--cef()--*/ + virtual void OnComplete(bool success) =0; +}; + + +/// +// Interface to implement to be notified of asynchronous completion via +// CefCookieManager::DeleteCookies(). +/// +/*--cef(source=client)--*/ +class CefDeleteCookiesCallback : public virtual CefBase { + public: + /// + // Method that will be called upon completion. |num_deleted| will be the + // number of cookies that were deleted or -1 if unknown. + /// + /*--cef()--*/ + virtual void OnComplete(int num_deleted) =0; +}; + #endif // CEF_INCLUDE_CEF_COOKIE_H_ diff --git a/include/cef_request_context.h b/include/cef_request_context.h index 32495a952..d047c99e1 100644 --- a/include/cef_request_context.h +++ b/include/cef_request_context.h @@ -38,22 +38,26 @@ #define CEF_INCLUDE_CEF_REQUEST_CONTEXT_H_ #pragma once +#include "include/cef_cookie.h" #include "include/cef_request_context_handler.h" +class CefSchemeHandlerFactory; + /// // A request context provides request handling for a set of related browser -// objects. A request context is specified when creating a new browser object -// via the CefBrowserHost static factory methods. Browser objects with different -// request contexts will never be hosted in the same render process. Browser -// objects with the same request context may or may not be hosted in the same -// render process depending on the process model. Browser objects created -// indirectly via the JavaScript window.open function or targeted links will -// share the same render process and the same request context as the source -// browser. When running in single-process mode there is only a single render -// process (the main process) and so all browsers created in single-process mode -// will share the same request context. This will be the first request context -// passed into a CefBrowserHost static factory method and all other request -// context objects will be ignored. +// or URL request objects. A request context can be specified when creating a +// new browser via the CefBrowserHost static factory methods or when creating a +// new URL request via the CefURLRequest static factory methods. Browser objects +// with different request contexts will never be hosted in the same render +// process. Browser objects with the same request context may or may not be +// hosted in the same render process depending on the process model. Browser +// objects created indirectly via the JavaScript window.open function or +// targeted links will share the same render process and the same request +// context as the source browser. When running in single-process mode there is +// only a single render process (the main process) and so all browsers created +// in single-process mode will share the same request context. This will be the +// first request context passed into a CefBrowserHost static factory method and +// all other request context objects will be ignored. /// /*--cef(source=library,no_debugct_check)--*/ class CefRequestContext : public virtual CefBase { @@ -65,10 +69,21 @@ class CefRequestContext : public virtual CefBase { static CefRefPtr GetGlobalContext(); /// - // Creates a new context object with the specified handler. + // Creates a new context object with the specified |settings| and optional + // |handler|. /// /*--cef(optional_param=handler)--*/ static CefRefPtr CreateContext( + const CefRequestContextSettings& settings, + CefRefPtr handler); + + /// + // Creates a new context object that shares storage with |other| and uses an + // optional |handler|. + /// + /*--cef(capi_name=create_context_shared,optional_param=handler)--*/ + static CefRefPtr CreateContext( + CefRefPtr other, CefRefPtr handler); /// @@ -79,7 +94,15 @@ class CefRequestContext : public virtual CefBase { virtual bool IsSame(CefRefPtr other) =0; /// - // Returns true if this object is the global context. + // Returns true if this object is sharing the same storage as |that| object. + /// + /*--cef()--*/ + virtual bool IsSharingWith(CefRefPtr other) =0; + + /// + // Returns true if this object is the global context. The global context is + // used by default when creating a browser or URL request with a NULL context + // argument. /// /*--cef()--*/ virtual bool IsGlobal() =0; @@ -89,6 +112,51 @@ class CefRequestContext : public virtual CefBase { /// /*--cef()--*/ virtual CefRefPtr GetHandler() =0; + + /// + // Returns the cache path for this object. If empty an "incognito mode" + // in-memory cache is being used. + /// + /*--cef()--*/ + virtual CefString GetCachePath() =0; + + /// + // Returns the default cookie manager for this object. This will be the global + // cookie manager if this object is the global request context. Otherwise, + // this will be the default cookie manager used when this request context does + // not receive a value via CefRequestContextHandler::GetCookieManager(). If + // |callback| is non-NULL it will be executed asnychronously on the IO thread + // after the manager's storage has been initialized. + /// + /*--cef(optional_param=callback)--*/ + virtual CefRefPtr GetDefaultCookieManager( + CefRefPtr callback) =0; + + /// + // Register a scheme handler factory for the specified |scheme_name| and + // optional |domain_name|. An empty |domain_name| value for a standard scheme + // will cause the factory to match all domain names. The |domain_name| value + // will be ignored for non-standard schemes. If |scheme_name| is a built-in + // scheme and no handler is returned by |factory| then the built-in scheme + // handler factory will be called. If |scheme_name| is a custom scheme then + // you must also implement the CefApp::OnRegisterCustomSchemes() method in all + // processes. This function may be called multiple times to change or remove + // the factory that matches the specified |scheme_name| and optional + // |domain_name|. Returns false if an error occurs. This function may be + // called on any thread in the browser process. + /// + /*--cef(optional_param=domain_name,optional_param=factory)--*/ + virtual bool RegisterSchemeHandlerFactory( + const CefString& scheme_name, + const CefString& domain_name, + CefRefPtr factory) =0; + + /// + // Clear all registered scheme handler factories. Returns false on error. This + // function may be called on any thread in the browser process. + /// + /*--cef()--*/ + virtual bool ClearSchemeHandlerFactories() =0; }; #endif // CEF_INCLUDE_CEF_REQUEST_CONTEXT_H_ diff --git a/include/cef_request_context_handler.h b/include/cef_request_context_handler.h index f77259efe..c69f119da 100644 --- a/include/cef_request_context_handler.h +++ b/include/cef_request_context_handler.h @@ -42,14 +42,17 @@ #include "include/cef_cookie.h" /// -// Implement this interface to provide handler implementations. +// Implement this interface to provide handler implementations. The handler +// instance will not be released until all objects related to the context have +// been destroyed. /// /*--cef(source=client,no_debugct_check)--*/ class CefRequestContextHandler : public virtual CefBase { public: /// - // Called on the IO thread to retrieve the cookie manager. The global cookie - // manager will be used if this method returns NULL. + // Called on the IO thread to retrieve the cookie manager. If this method + // returns NULL the default cookie manager retrievable via + // CefRequestContext::GetDefaultCookieManager() will be used. /// /*--cef()--*/ virtual CefRefPtr GetCookieManager() { return NULL; } diff --git a/include/cef_scheme.h b/include/cef_scheme.h index cd8415c07..a966a9a79 100644 --- a/include/cef_scheme.h +++ b/include/cef_scheme.h @@ -49,17 +49,18 @@ class CefSchemeHandlerFactory; /// -// Register a scheme handler factory for the specified |scheme_name| and -// optional |domain_name|. An empty |domain_name| value for a standard scheme -// will cause the factory to match all domain names. The |domain_name| value -// will be ignored for non-standard schemes. If |scheme_name| is a built-in -// scheme and no handler is returned by |factory| then the built-in scheme -// handler factory will be called. If |scheme_name| is a custom scheme then -// also implement the CefApp::OnRegisterCustomSchemes() method in all processes. -// This function may be called multiple times to change or remove the factory -// that matches the specified |scheme_name| and optional |domain_name|. -// Returns false if an error occurs. This function may be called on any thread -// in the browser process. +// Register a scheme handler factory with the global request context. An empty +// |domain_name| value for a standard scheme will cause the factory to match all +// domain names. The |domain_name| value will be ignored for non-standard +// schemes. If |scheme_name| is a built-in scheme and no handler is returned by +// |factory| then the built-in scheme handler factory will be called. If +// |scheme_name| is a custom scheme then you must also implement the +// CefApp::OnRegisterCustomSchemes() method in all processes. This function may +// be called multiple times to change or remove the factory that matches the +// specified |scheme_name| and optional |domain_name|. Returns false if an error +// occurs. This function may be called on any thread in the browser process. +// Using this function is equivalent to calling +// CefRequestContext::GetGlobalContext()->RegisterSchemeHandlerFactory(). /// /*--cef(optional_param=domain_name,optional_param=factory)--*/ bool CefRegisterSchemeHandlerFactory( @@ -68,8 +69,10 @@ bool CefRegisterSchemeHandlerFactory( CefRefPtr factory); /// -// Clear all registered scheme handler factories. Returns false on error. This -// function may be called on any thread in the browser process. +// Clear all scheme handler factories registered with the global request +// context. Returns false on error. This function may be called on any thread in +// the browser process. Using this function is equivalent to calling +// CefRequestContext::GetGlobalContext()->ClearSchemeHandlerFactories(). /// /*--cef()--*/ bool CefClearSchemeHandlerFactories(); diff --git a/include/cef_urlrequest.h b/include/cef_urlrequest.h index 1a4e839fe..5b58b6349 100644 --- a/include/cef_urlrequest.h +++ b/include/cef_urlrequest.h @@ -41,6 +41,7 @@ #include "include/cef_auth_callback.h" #include "include/cef_base.h" #include "include/cef_request.h" +#include "include/cef_request_context.h" #include "include/cef_response.h" class CefURLRequestClient; @@ -68,12 +69,16 @@ class CefURLRequest : public virtual CefBase { // would not normally be rendered then the response may receive special // handling inside the browser (for example, via the file download code path // instead of the URL request code path). The |request| object will be marked - // as read-only after calling this method. + // as read-only after calling this method. In the browser process if + // |request_context| is empty the global request context will be used. In the + // render process |request_context| must be empty and the context associated + // with the current renderer process' browser will be used. /// - /*--cef()--*/ + /*--cef(optional_param=request_context)--*/ static CefRefPtr Create( CefRefPtr request, - CefRefPtr client); + CefRefPtr client, + CefRefPtr request_context); /// // Returns the request object used to create this URL request. The returned diff --git a/include/internal/cef_types.h b/include/internal/cef_types.h index dfc04e10b..b7c88d210 100644 --- a/include/internal/cef_types.h +++ b/include/internal/cef_types.h @@ -234,20 +234,34 @@ typedef struct _cef_settings_t { int command_line_args_disabled; /// - // The location where cache data will be stored on disk. If empty an in-memory - // cache will be used for some features and a temporary disk cache for others. - // HTML5 databases such as localStorage will only persist across sessions if a - // cache path is specified. + // The location where cache data will be stored on disk. If empty then + // browsers will be created in "incognito mode" where in-memory caches are + // used for storage and no data is persisted to disk. HTML5 databases such as + // localStorage will only persist across sessions if a cache path is + // specified. Can be overridden for individual CefRequestContext instances via + // the CefRequestContextSettings.cache_path value. /// cef_string_t cache_path; + /// + // 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). + /// + cef_string_t user_data_path; + /// // To persist session cookies (cookies without an expiry date or validity // interval) by default when using the global cookie manager set this value to // true. Session cookies are generally intended to be transient and most Web - // browsers do not persist them. A |cache_path| value must also be specified to - // enable this feature. Also configurable using the "persist-session-cookies" - // command-line switch. + // browsers do not persist them. A |cache_path| value must also be specified + // to enable this feature. Also configurable using the + // "persist-session-cookies" command-line switch. Can be overridden for + // individual CefRequestContext instances via the + // CefRequestContextSettings.persist_session_cookies value. /// int persist_session_cookies; @@ -370,7 +384,9 @@ typedef struct _cef_settings_t { // 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. + // "ignore-certificate-errors" command-line switch. Can be overridden for + // individual CefRequestContext instances via the + // CefRequestContextSettings.ignore_certificate_errors value. /// int ignore_certificate_errors; @@ -386,11 +402,64 @@ typedef struct _cef_settings_t { // 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. + // 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. /// cef_string_t accept_language_list; } cef_settings_t; +/// +// Request context initialization settings. Specify NULL or 0 to get the +// recommended default values. +/// +typedef struct _cef_request_context_settings_t { + /// + // Size of this structure. + /// + size_t size; + + /// + // The location where cache data will be stored on disk. If empty then + // browsers will be created in "incognito mode" where in-memory caches are + // used for storage and no data is persisted to disk. HTML5 databases such as + // localStorage will only persist across sessions if a cache path is + // specified. To share the global browser cache and related configuration set + // this value to match the CefSettings.cache_path value. + /// + cef_string_t cache_path; + + /// + // To persist session cookies (cookies without an expiry date or validity + // interval) by default when using the global cookie manager set this value to + // true. Session cookies are generally intended to be transient and most Web + // browsers do not persist them. Can be set globally using the + // CefSettings.persist_session_cookies value. This value will be ignored if + // |cache_path| is empty or if it matches the CefSettings.cache_path value. + /// + int persist_session_cookies; + + /// + // 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. Can be set globally using the + // CefSettings.ignore_certificate_errors value. This value will be ignored if + // |cache_path| matches the CefSettings.cache_path value. + /// + int ignore_certificate_errors; + + /// + // Comma delimited ordered list of language codes without any whitespace that + // will be used in the "Accept-Language" HTTP header. Can be set globally + // using the CefSettings.accept_language_list value or overridden on a per- + // browser basis using the CefBrowserSettings.accept_language_list value. If + // all values are empty then "en-US,en" will be used. This value will be + // ignored if |cache_path| matches the CefSettings.cache_path value. + /// + cef_string_t accept_language_list; +} cef_request_context_settings_t; + /// // Browser initialization settings. Specify NULL or 0 to get the recommended // default values. The consequences of using custom values may not be well @@ -746,6 +815,18 @@ typedef enum { // module). /// PK_FILE_MODULE, + + /// + // "Local Settings\Application Data" directory under the user profile + // directory on Windows. + /// + PK_LOCAL_APP_DATA, + + /// + // "Application Data" directory under the user profile directory on Windows + // and "~/Library/Application Support" directory on Mac OS X. + /// + PK_USER_DATA, } cef_path_key_t; /// diff --git a/include/internal/cef_types_wrappers.h b/include/internal/cef_types_wrappers.h index b28b76bac..d120463fa 100644 --- a/include/internal/cef_types_wrappers.h +++ b/include/internal/cef_types_wrappers.h @@ -418,6 +418,7 @@ struct CefSettingsTraits { static inline void clear(struct_type* s) { cef_string_clear(&s->browser_subprocess_path); cef_string_clear(&s->cache_path); + cef_string_clear(&s->user_data_path); cef_string_clear(&s->user_agent); cef_string_clear(&s->product_version); cef_string_clear(&s->locale); @@ -441,6 +442,8 @@ struct CefSettingsTraits { cef_string_set(src->cache_path.str, src->cache_path.length, &target->cache_path, copy); + cef_string_set(src->user_data_path.str, src->user_data_path.length, + &target->user_data_path, copy); target->persist_session_cookies = src->persist_session_cookies; cef_string_set(src->user_agent.str, src->user_agent.length, @@ -477,6 +480,36 @@ struct CefSettingsTraits { typedef CefStructBase CefSettings; +struct CefRequestContextSettingsTraits { + typedef cef_request_context_settings_t struct_type; + + static inline void init(struct_type* s) { + s->size = sizeof(struct_type); + } + + static inline void clear(struct_type* s) { + cef_string_clear(&s->cache_path); + cef_string_clear(&s->accept_language_list); + } + + static inline void set(const struct_type* src, struct_type* target, + bool copy) { + cef_string_set(src->cache_path.str, src->cache_path.length, + &target->cache_path, copy); + target->persist_session_cookies = src->persist_session_cookies; + target->ignore_certificate_errors = src->ignore_certificate_errors; + cef_string_set(src->accept_language_list.str, + src->accept_language_list.length, &target->accept_language_list, copy); + } +}; + +/// +// Class representing request context initialization settings. +/// +typedef CefStructBase + CefRequestContextSettings; + + struct CefBrowserSettingsTraits { typedef cef_browser_settings_t struct_type; diff --git a/libcef/browser/browser_context.h b/libcef/browser/browser_context.h index 420ba8378..2270969e5 100644 --- a/libcef/browser/browser_context.h +++ b/libcef/browser/browser_context.h @@ -6,7 +6,9 @@ #define CEF_LIBCEF_BROWSER_BROWSER_CONTEXT_H_ #pragma once +#include "include/cef_request_context_handler.h" #include "libcef/browser/resource_context.h" +#include "libcef/browser/url_request_context_getter_impl.h" #include "content/public/browser/browser_context.h" #include "content/public/browser/browser_thread.h" @@ -26,11 +28,12 @@ // // RCI = CefRequestContextImpl // Implements the CefRequestContext interface which is exposed to clients. -// References the global BCI or creates a new BCP. +// References the isolated BCI or creates a new BCP. // // BCI = CefBrowserContextImpl -// Entry point from WC when using the global RCI. Owns the RC and creates the -// URCGI. Life span controlled by RCI and CefBrowserMainParts. +// Entry point from WC when using an isolated RCI. Owns the RC and creates the +// URCGI. Life span controlled by RCI and (for the global context) +// CefBrowserMainParts. // // BCP = CefBrowserContextProxy // Entry point from WC when using a custom RCI. Owns the RC and creates the @@ -42,14 +45,14 @@ // controlled by BCI/BCP. // // URCGI = CefURLRequestContextGetterImpl -// Creates and owns the URCI. Life span is controlled by RC and -// CefBrowserMainParts. +// Creates and owns the URCI. Life span is controlled by RC and (for the +// global context) CefBrowserMainParts. // // URCGP = CefURLRequestContextGetterProxy // Creates and owns the URCP. Life span is controlled by RC. // // URCI = CefURLRequestContextImpl -// Owns various network-related objects including the global cookie manager. +// Owns various network-related objects including the isolated cookie manager. // Owns URLRequest objects which must be destroyed first. Life span is // controlled by URCGI. // @@ -61,7 +64,7 @@ // CSP = CefCookieStoreProxy // Gives the CefCookieManager instance retrieved via CefRequestContextHandler // an opportunity to handle cookie requests. Otherwise forwards requests via -// URCI to the global cookie manager. Life span is controlled by URCP. +// URCI to the isolated cookie manager. Life span is controlled by URCP. // // // Relationship diagram: @@ -69,7 +72,7 @@ // own = ownership (scoped_ptr) // ptr = raw pointer // -// CefBrowserMainParts global cookie manager, etc... +// CefBrowserMainParts isolated cookie manager, etc... // | | ^ // ref ref ref/own // v v | @@ -103,7 +106,7 @@ // Main entry point for configuring behavior on a per-browser basis. An instance // of this class is passed to WebContents::Create in CefBrowserHostImpl:: -// CreateInternal. Only accessed on the UI thread. +// CreateInternal. Only accessed on the UI thread unless otherwise indicated. class CefBrowserContext : public content::BrowserContext, public base::RefCountedThreadSafe< @@ -114,6 +117,18 @@ class CefBrowserContext // BrowserContext methods. content::ResourceContext* GetResourceContext() override; + // Returns true if this is a CefBrowserContextProxy object. Safe to call from + // any thread. + virtual bool IsProxy() const = 0; + + // Returns the settings associated with this object. Safe to call from any + // thread. + virtual const CefRequestContextSettings& GetSettings() const = 0; + + // Returns the handler associated with this object. Safe to call from any + // thread. + virtual CefRefPtr GetHandler() const = 0; + // Called from CefContentBrowserClient to create the URLRequestContextGetter. virtual net::URLRequestContextGetter* CreateRequestContext( content::ProtocolHandlerMap* protocol_handlers, diff --git a/libcef/browser/browser_context_impl.cc b/libcef/browser/browser_context_impl.cc index 3752b063b..e7d264412 100644 --- a/libcef/browser/browser_context_impl.cc +++ b/libcef/browser/browser_context_impl.cc @@ -6,30 +6,129 @@ #include -#include "libcef/browser/browser_host_impl.h" +#include "libcef/browser/content_browser_client.h" #include "libcef/browser/context.h" #include "libcef/browser/download_manager_delegate.h" #include "libcef/browser/thread_util.h" +#include "base/files/file_util.h" +#include "base/lazy_instance.h" #include "base/logging.h" +#include "base/threading/thread_restrictions.h" +#include "chrome/browser/net/proxy_service_factory.h" #include "content/public/browser/download_manager.h" #include "content/public/browser/browser_thread.h" #include "content/public/browser/storage_partition.h" +#include "net/proxy/proxy_config_service.h" using content::BrowserThread; -CefBrowserContextImpl::CefBrowserContextImpl() { +namespace { + +// Manages the global mapping of cache path to Impl instance. +class ImplManager { + public: + ImplManager() {} + ~ImplManager() { + DCHECK(map_.empty()); + } + + CefBrowserContextImpl* GetImpl(const base::FilePath& path) { + CEF_REQUIRE_UIT(); + DCHECK(!path.empty()); + PathMap::const_iterator it = map_.find(path); + if (it != map_.end()) + return it->second; + return NULL; + } + + void AddImpl(const base::FilePath& path, CefBrowserContextImpl* impl) { + CEF_REQUIRE_UIT(); + DCHECK(!path.empty()); + DCHECK(GetImpl(path) == NULL); + map_.insert(std::make_pair(path, impl)); + } + + void RemoveImpl(const base::FilePath& path) { + CEF_REQUIRE_UIT(); + DCHECK(!path.empty()); + PathMap::iterator it = map_.find(path); + DCHECK(it != map_.end()); + if (it != map_.end()) + map_.erase(it); + } + + private: + typedef std::map PathMap; + PathMap map_; + + DISALLOW_COPY_AND_ASSIGN(ImplManager); +}; + +base::LazyInstance g_manager = LAZY_INSTANCE_INITIALIZER; + +} // namespace + +CefBrowserContextImpl::CefBrowserContextImpl( + const CefRequestContextSettings& settings) + : settings_(settings) { } CefBrowserContextImpl::~CefBrowserContextImpl() { + pref_proxy_config_tracker_->DetachFromPrefService(); + // Delete the download manager delegate here because otherwise we'll crash // when it's accessed from the content::BrowserContext destructor. if (download_manager_delegate_.get()) download_manager_delegate_.reset(NULL); + + if (!cache_path_.empty()) + g_manager.Get().RemoveImpl(cache_path_); +} + +void CefBrowserContextImpl::Initialize() { + cache_path_ = base::FilePath(CefString(&settings_.cache_path)); + if (!cache_path_.empty()) { + base::ThreadRestrictions::ScopedAllowIO allow_io; + if (!base::DirectoryExists(cache_path_) && + !base::CreateDirectory(cache_path_)) { + LOG(ERROR) << "The cache_path directory could not be created: " << + cache_path_.value(); + cache_path_ = base::FilePath(); + CefString(&settings_.cache_path).clear(); + } + } + + if (!cache_path_.empty()) + g_manager.Get().AddImpl(cache_path_, this); + + if (settings_.accept_language_list.length == 0) { + // Use the global language list setting. + CefString(&settings_.accept_language_list) = + CefString(&CefContext::Get()->settings().accept_language_list); + } + + // Initialize proxy configuration tracker. + pref_proxy_config_tracker_.reset( + ProxyServiceFactory::CreatePrefProxyConfigTrackerOfLocalState( + CefContentBrowserClient::Get()->pref_service())); + + // Create the CefURLRequestContextGetterImpl via an indirect call to + // CreateRequestContext. Triggers a call to CefURLRequestContextGetterImpl:: + // GetURLRequestContext() on the IO thread which creates the + // CefURLRequestContextImpl. + GetRequestContext(); + DCHECK(url_request_getter_.get()); +} + +// static +scoped_refptr CefBrowserContextImpl::GetForCachePath( + const base::FilePath& cache_path) { + return g_manager.Get().GetImpl(cache_path); } base::FilePath CefBrowserContextImpl::GetPath() const { - return CefContext::Get()->cache_path(); + return cache_path_; } scoped_ptr @@ -38,7 +137,7 @@ scoped_ptr } bool CefBrowserContextImpl::IsOffTheRecord() const { - return false; + return cache_path_.empty(); } content::DownloadManagerDelegate* @@ -98,14 +197,36 @@ content::SSLHostStateDelegate* return NULL; } +bool CefBrowserContextImpl::IsProxy() const { + return false; +} + +const CefRequestContextSettings& CefBrowserContextImpl::GetSettings() const { + return settings_; +} + +CefRefPtr CefBrowserContextImpl::GetHandler() const { + return NULL; +} + net::URLRequestContextGetter* CefBrowserContextImpl::CreateRequestContext( content::ProtocolHandlerMap* protocol_handlers, content::URLRequestInterceptorScopedVector request_interceptors) { + CEF_REQUIRE_UIT(); DCHECK(!url_request_getter_.get()); + + // Initialize the proxy configuration service. + scoped_ptr proxy_config_service; + proxy_config_service.reset( + ProxyServiceFactory::CreateProxyConfigService( + pref_proxy_config_tracker_.get())); + url_request_getter_ = new CefURLRequestContextGetterImpl( + settings_, BrowserThread::UnsafeGetMessageLoopForThread(BrowserThread::IO), BrowserThread::UnsafeGetMessageLoopForThread(BrowserThread::FILE), protocol_handlers, + proxy_config_service.Pass(), request_interceptors.Pass()); resource_context()->set_url_request_context_getter(url_request_getter_.get()); return url_request_getter_.get(); diff --git a/libcef/browser/browser_context_impl.h b/libcef/browser/browser_context_impl.h index bc7a30269..251e19eb6 100644 --- a/libcef/browser/browser_context_impl.h +++ b/libcef/browser/browser_context_impl.h @@ -13,6 +13,7 @@ #include "base/files/file_path.h" #include "base/memory/ref_counted.h" #include "base/memory/scoped_ptr.h" +#include "chrome/browser/net/pref_proxy_config_tracker.h" namespace content { class DownloadManagerDelegate; @@ -21,12 +22,21 @@ class SpeechRecognitionPreferences; class CefDownloadManagerDelegate; -// Global BrowserContext implementation. Life span is controlled by -// CefRequestContextImpl and CefBrowserMainParts. Only accessed on the UI -// thread. See browser_context.h for an object relationship diagram. +// Isolated BrowserContext implementation. Life span is controlled by +// CefRequestContextImpl and (for the main context) CefBrowserMainParts. Only +// accessed on the UI thread unless otherwise indicated. See browser_context.h +// for an object relationship diagram. class CefBrowserContextImpl : public CefBrowserContext { public: - CefBrowserContextImpl(); + explicit CefBrowserContextImpl(const CefRequestContextSettings& settings); + + // Returns the existing instance, if any, associated with the specified + // |cache_path|. + static scoped_refptr GetForCachePath( + const base::FilePath& cache_path); + + // Must be called immediately after this object is created. + void Initialize(); // BrowserContext methods. base::FilePath GetPath() const override; @@ -50,6 +60,9 @@ class CefBrowserContextImpl : public CefBrowserContext { content::SSLHostStateDelegate* GetSSLHostStateDelegate() override; // CefBrowserContext methods. + bool IsProxy() const override; + const CefRequestContextSettings& GetSettings() const override; + CefRefPtr GetHandler() const override; net::URLRequestContextGetter* CreateRequestContext( content::ProtocolHandlerMap* protocol_handlers, content::URLRequestInterceptorScopedVector request_interceptors) @@ -61,6 +74,11 @@ class CefBrowserContextImpl : public CefBrowserContext { content::URLRequestInterceptorScopedVector request_interceptors) override; + // Guaranteed to exist once this object has been initialized. + scoped_refptr request_context() const { + return url_request_getter_; + } + private: // Only allow deletion via scoped_refptr(). friend struct content::BrowserThread::DeleteOnThread< @@ -69,6 +87,12 @@ class CefBrowserContextImpl : public CefBrowserContext { ~CefBrowserContextImpl() override; + // Members initialized during construction are safe to access from any thread. + CefRequestContextSettings settings_; + base::FilePath cache_path_; + + scoped_ptr pref_proxy_config_tracker_; + scoped_ptr download_manager_delegate_; scoped_refptr url_request_getter_; diff --git a/libcef/browser/browser_context_proxy.cc b/libcef/browser/browser_context_proxy.cc index efe66de65..0c7a970cd 100644 --- a/libcef/browser/browser_context_proxy.cc +++ b/libcef/browser/browser_context_proxy.cc @@ -17,6 +17,8 @@ CefBrowserContextProxy::CefBrowserContextProxy( scoped_refptr parent) : handler_(handler), parent_(parent) { + DCHECK(handler_.get()); + DCHECK(parent_.get()); } CefBrowserContextProxy::~CefBrowserContextProxy() { @@ -93,13 +95,25 @@ content::SSLHostStateDelegate* return parent_->GetSSLHostStateDelegate(); } +bool CefBrowserContextProxy::IsProxy() const { + return true; +} + +const CefRequestContextSettings& CefBrowserContextProxy::GetSettings() const { + return parent_->GetSettings(); +} + +CefRefPtr CefBrowserContextProxy::GetHandler() const { + return handler_; +} + net::URLRequestContextGetter* CefBrowserContextProxy::CreateRequestContext( content::ProtocolHandlerMap* protocol_handlers, content::URLRequestInterceptorScopedVector request_interceptors) { + CEF_REQUIRE_UIT(); DCHECK(!url_request_getter_.get()); url_request_getter_ = - new CefURLRequestContextGetterProxy(handler_, - CefContentBrowserClient::Get()->request_context().get()); + new CefURLRequestContextGetterProxy(handler_, parent_->request_context()); resource_context()->set_url_request_context_getter(url_request_getter_.get()); return url_request_getter_.get(); } diff --git a/libcef/browser/browser_context_proxy.h b/libcef/browser/browser_context_proxy.h index c1e3d8a6b..ea3414c00 100644 --- a/libcef/browser/browser_context_proxy.h +++ b/libcef/browser/browser_context_proxy.h @@ -6,7 +6,6 @@ #define CEF_LIBCEF_BROWSER_BROWSER_CONTEXT_PROXY_H_ #pragma once -#include "include/cef_request_context_handler.h" #include "libcef/browser/browser_context.h" #include "libcef/browser/browser_context_impl.h" @@ -52,6 +51,9 @@ class CefBrowserContextProxy : public CefBrowserContext { content::SSLHostStateDelegate* GetSSLHostStateDelegate() override; // CefBrowserContext methods. + bool IsProxy() const override; + const CefRequestContextSettings& GetSettings() const override; + CefRefPtr GetHandler() const override; net::URLRequestContextGetter* CreateRequestContext( content::ProtocolHandlerMap* protocol_handlers, content::URLRequestInterceptorScopedVector request_interceptors) @@ -63,7 +65,9 @@ class CefBrowserContextProxy : public CefBrowserContext { content::URLRequestInterceptorScopedVector request_interceptors) override; - CefRefPtr handler() const { return handler_; } + scoped_refptr parent() const { + return parent_; + } private: // Only allow deletion via scoped_refptr(). @@ -73,8 +77,10 @@ class CefBrowserContextProxy : public CefBrowserContext { ~CefBrowserContextProxy() override; + // Members initialized during construction are safe to access from any thread. CefRefPtr handler_; scoped_refptr parent_; + scoped_ptr download_manager_delegate_; scoped_refptr url_request_getter_; diff --git a/libcef/browser/browser_host_impl.cc b/libcef/browser/browser_host_impl.cc index c0cb47a81..58dc5db01 100644 --- a/libcef/browser/browser_host_impl.cc +++ b/libcef/browser/browser_host_impl.cc @@ -397,15 +397,16 @@ CefRefPtr CefBrowserHostImpl::CreateInternal( DCHECK(opener == kNullWindowHandle || browser_info->is_popup()); if (!web_contents) { - scoped_refptr browser_context = NULL; - if (request_context.get()) { - CefRequestContextImpl* request_context_impl = - static_cast(request_context.get()); - browser_context = request_context_impl->GetOrCreateBrowserContext(); - } else { - browser_context = CefContentBrowserClient::Get()->browser_context(); - } - DCHECK(browser_context); + // Get or create the request context and browser context. + CefRefPtr request_context_impl = + CefRequestContextImpl::GetForRequestContext(request_context); + DCHECK(request_context_impl.get()); + scoped_refptr browser_context = + request_context_impl->GetBrowserContext(); + DCHECK(browser_context.get()); + + if (!request_context.get()) + request_context = request_context_impl.get(); content::WebContents::CreateParams create_params( browser_context.get()); @@ -424,7 +425,7 @@ CefRefPtr CefBrowserHostImpl::CreateInternal( CefRefPtr browser = new CefBrowserHostImpl(window_info, settings, client, web_contents, - browser_info, opener); + browser_info, opener, request_context); if (!browser->IsWindowless() && !browser->PlatformCreateWindow()) return NULL; @@ -2236,6 +2237,8 @@ void CefBrowserHostImpl::WebContentsCreated( const base::string16& frame_name, const GURL& target_url, content::WebContents* new_contents) { + DCHECK(new_contents); + scoped_ptr pending_popup_info; { base::AutoLock lock_scope(pending_popup_info_lock_); @@ -2261,11 +2264,19 @@ void CefBrowserHostImpl::WebContentsCreated( DCHECK(!info->is_popup()); } + scoped_refptr browser_context = + static_cast(new_contents->GetBrowserContext()); + DCHECK(browser_context.get()); + CefRefPtr request_context = + CefRequestContextImpl::GetForBrowserContext(browser_context).get(); + DCHECK(request_context.get()); + CefRefPtr browser = CefBrowserHostImpl::CreateInternal(pending_popup_info->window_info, pending_popup_info->settings, pending_popup_info->client, - new_contents, info, opener, NULL); + new_contents, info, opener, + request_context); } void CefBrowserHostImpl::DidNavigateMainFramePostCommit( @@ -2725,13 +2736,15 @@ CefBrowserHostImpl::CefBrowserHostImpl( CefRefPtr client, content::WebContents* web_contents, scoped_refptr browser_info, - CefWindowHandle opener) + CefWindowHandle opener, + CefRefPtr request_context) : content::WebContentsObserver(web_contents), window_info_(window_info), settings_(settings), client_(client), browser_info_(browser_info), opener_(opener), + request_context_(request_context), is_loading_(false), can_go_back_(false), can_go_forward_(false), @@ -2753,16 +2766,14 @@ CefBrowserHostImpl::CefBrowserHostImpl( window_x11_ = NULL; #endif + DCHECK(request_context_.get()); + DCHECK(!browser_info_->browser().get()); browser_info_->set_browser(this); web_contents_.reset(web_contents); web_contents->SetDelegate(this); - scoped_refptr browser_context = - static_cast(web_contents->GetBrowserContext()); - request_context_ = new CefRequestContextImpl(browser_context); - registrar_.reset(new content::NotificationRegistrar); registrar_->Add(this, content::NOTIFICATION_WEB_CONTENTS_TITLE_UPDATED, content::Source(web_contents)); diff --git a/libcef/browser/browser_host_impl.h b/libcef/browser/browser_host_impl.h index 15053d135..564de764b 100644 --- a/libcef/browser/browser_host_impl.h +++ b/libcef/browser/browser_host_impl.h @@ -499,7 +499,8 @@ class CefBrowserHostImpl : public CefBrowserHost, CefRefPtr client, content::WebContents* web_contents, scoped_refptr browser_info, - CefWindowHandle opener); + CefWindowHandle opener, + CefRefPtr request_context); // Updates and returns an existing frame or creates a new frame. Pass // CefFrameHostImpl::kUnspecifiedFrameId for |parent_frame_id| if unknown. diff --git a/libcef/browser/browser_main.cc b/libcef/browser/browser_main.cc index 4874a064d..4b8c74e67 100644 --- a/libcef/browser/browser_main.cc +++ b/libcef/browser/browser_main.cc @@ -10,6 +10,7 @@ #include "libcef/browser/browser_context_proxy.h" #include "libcef/browser/browser_message_loop.h" #include "libcef/browser/content_browser_client.h" +#include "libcef/browser/context.h" #include "libcef/browser/devtools_delegate.h" #include "libcef/browser/thread_util.h" #include "libcef/common/net_resource_provider.h" @@ -18,7 +19,6 @@ #include "base/command_line.h" #include "base/message_loop/message_loop.h" #include "base/strings/string_number_conversions.h" -#include "chrome/browser/net/proxy_service_factory.h" #include "content/browser/webui/content_web_ui_controller_factory.h" #include "content/public/browser/gpu_data_manager.h" #include "content/public/browser/web_ui_controller_factory.h" @@ -118,31 +118,16 @@ int CefBrowserMainParts::PreCreateThreads() { // Initialize the V8 proxy integration. net::ProxyResolverV8::EnsureIsolateCreated(); - // Initialize proxy configuration tracker. - pref_proxy_config_tracker_.reset( - ProxyServiceFactory::CreatePrefProxyConfigTrackerOfLocalState( - pref_service_.get())); - return 0; } void CefBrowserMainParts::PreMainMessageLoopRun() { + CefRequestContextSettings settings; + CefContext::Get()->PopulateRequestContextSettings(&settings); + // Create the global BrowserContext. - global_browser_context_ = new CefBrowserContextImpl(); - - // Initialize the proxy configuration service. This needs to occur before - // CefURLRequestContextGetter::GetURLRequestContext() is called for the - // first time. - proxy_config_service_.reset( - ProxyServiceFactory::CreateProxyConfigService( - pref_proxy_config_tracker_.get())); - - // Create the global URLRequestContextGetter via an indirect call to - // CefBrowserContextImpl::CreateRequestContext. Triggers a call to - // CefURLRequestContextGetter::GetURLRequestContext() on the IO thread which - // creates the URLRequestContext. - global_request_context_ = static_cast( - global_browser_context_->GetRequestContext()); + global_browser_context_ = new CefBrowserContextImpl(settings); + global_browser_context_->Initialize(); const base::CommandLine* command_line = base::CommandLine::ForCurrentProcess(); @@ -164,9 +149,7 @@ void CefBrowserMainParts::PostMainMessageLoopRun() { devtools_delegate_->Stop(); devtools_delegate_ = NULL; } - pref_proxy_config_tracker_->DetachFromPrefService(); - global_request_context_ = NULL; global_browser_context_ = NULL; #ifndef NDEBUG @@ -176,8 +159,6 @@ void CefBrowserMainParts::PostMainMessageLoopRun() { } void CefBrowserMainParts::PostDestroyThreads() { - pref_proxy_config_tracker_.reset(NULL); - #if defined(USE_AURA) aura::Env::DeleteInstance(); delete views::ViewsDelegate::views_delegate; diff --git a/libcef/browser/browser_main.h b/libcef/browser/browser_main.h index df8cc0fe4..00e05b8aa 100644 --- a/libcef/browser/browser_main.h +++ b/libcef/browser/browser_main.h @@ -15,9 +15,7 @@ #include "base/memory/scoped_vector.h" #include "base/prefs/pref_service.h" #include "base/strings/string_piece.h" -#include "chrome/browser/net/pref_proxy_config_tracker.h" #include "content/public/browser/browser_main_parts.h" -#include "net/proxy/proxy_config_service.h" #include "net/url_request/url_request_context_getter.h" namespace base { @@ -48,27 +46,18 @@ class CefBrowserMainParts : public content::BrowserMainParts { scoped_refptr browser_context() const { return global_browser_context_; } - scoped_refptr request_context() const { - return global_request_context_; - } CefDevToolsDelegate* devtools_delegate() const { return devtools_delegate_; } PrefService* pref_service() const { return pref_service_.get(); } - scoped_ptr proxy_config_service() { - return proxy_config_service_.Pass(); - } private: void PlatformInitialize(); void PlatformCleanup(); scoped_refptr global_browser_context_; - scoped_refptr global_request_context_; CefDevToolsDelegate* devtools_delegate_; // Deletes itself. scoped_ptr message_loop_; - scoped_ptr pref_proxy_config_tracker_; - scoped_ptr proxy_config_service_; scoped_refptr pref_store_; scoped_ptr pref_service_; diff --git a/libcef/browser/browser_urlrequest_impl.cc b/libcef/browser/browser_urlrequest_impl.cc index 100564674..44bfdf884 100644 --- a/libcef/browser/browser_urlrequest_impl.cc +++ b/libcef/browser/browser_urlrequest_impl.cc @@ -8,6 +8,7 @@ #include "libcef/browser/browser_context.h" #include "libcef/browser/content_browser_client.h" +#include "libcef/browser/request_context_impl.h" #include "libcef/browser/thread_util.h" #include "libcef/browser/url_request_user_data.h" #include "libcef/common/http_header_utils.h" @@ -17,6 +18,7 @@ #include "base/logging.h" #include "base/message_loop/message_loop.h" #include "base/strings/string_util.h" +#include "content/public/browser/browser_thread.h" #include "content/public/common/url_fetcher.h" #include "net/base/io_buffer.h" #include "net/base/load_flags.h" @@ -28,6 +30,7 @@ #include "net/url_request/url_fetcher_response_writer.h" #include "net/url_request/url_request_status.h" +using content::BrowserThread; namespace { @@ -128,10 +131,12 @@ class CefBrowserURLRequest::Context public: Context(CefRefPtr url_request, CefRefPtr request, - CefRefPtr client) + CefRefPtr client, + CefRefPtr request_context) : url_request_(url_request), request_(request), client_(client), + request_context_(request_context), message_loop_proxy_(base::MessageLoop::current()->message_loop_proxy()), status_(UR_IO_PENDING), error_code_(ERR_NONE), @@ -169,13 +174,48 @@ class CefBrowserURLRequest::Context return false; } + BrowserThread::PostTaskAndReply( + BrowserThread::UI, + FROM_HERE, + base::Bind(&CefBrowserURLRequest::Context::GetRequestContextOnUIThread, + this), + base::Bind(&CefBrowserURLRequest::Context::ContinueOnOriginatingThread, + this, url, request_type)); + + return true; + } + + void GetRequestContextOnUIThread() { + CEF_REQUIRE_UIT(); + + // Get or create the request context and browser context. + CefRefPtr request_context_impl = + CefRequestContextImpl::GetForRequestContext(request_context_); + DCHECK(request_context_impl.get()); + scoped_refptr browser_context = + request_context_impl->GetBrowserContext(); + DCHECK(browser_context.get()); + + if (!request_context_.get()) + request_context_ = request_context_impl.get(); + + // The request context is created on the UI thread but accessed and + // destroyed on the IO thread. + url_request_getter_ = browser_context->GetRequestContext(); + } + + void ContinueOnOriginatingThread(const GURL& url, + net::URLFetcher::RequestType request_type) { + DCHECK(CalledOnValidThread()); + fetcher_delegate_.reset( new CefURLFetcherDelegate(this, request_->GetFlags())); fetcher_.reset(net::URLFetcher::Create(url, request_type, fetcher_delegate_.get())); - fetcher_->SetRequestContext( - CefContentBrowserClient::Get()->request_context().get()); + + DCHECK(url_request_getter_.get()); + fetcher_->SetRequestContext(url_request_getter_.get()); CefRequest::HeaderMap headerMap; request_->GetHeaderMap(headerMap); @@ -289,8 +329,6 @@ class CefBrowserURLRequest::Context fetcher_->SaveResponseWithWriter(response_writer.Pass()); fetcher_->Start(); - - return true; } void Cancel() { @@ -424,6 +462,7 @@ class CefBrowserURLRequest::Context CefRefPtr url_request_; CefRefPtr request_; CefRefPtr client_; + CefRefPtr request_context_; scoped_refptr message_loop_proxy_; scoped_ptr fetcher_; scoped_ptr fetcher_delegate_; @@ -432,6 +471,8 @@ class CefBrowserURLRequest::Context CefRefPtr response_; int64 upload_data_size_; bool got_upload_progress_complete_; + + scoped_refptr url_request_getter_; }; @@ -476,8 +517,9 @@ void CefURLFetcherDelegate::OnURLFetchUploadProgress( CefBrowserURLRequest::CefBrowserURLRequest( CefRefPtr request, - CefRefPtr client) { - context_ = new Context(this, request, client); + CefRefPtr client, + CefRefPtr request_context) { + context_ = new Context(this, request, client, request_context); } CefBrowserURLRequest::~CefBrowserURLRequest() { diff --git a/libcef/browser/browser_urlrequest_impl.h b/libcef/browser/browser_urlrequest_impl.h index b0055726e..706cdf706 100644 --- a/libcef/browser/browser_urlrequest_impl.h +++ b/libcef/browser/browser_urlrequest_impl.h @@ -13,7 +13,8 @@ class CefBrowserURLRequest : public CefURLRequest { class Context; CefBrowserURLRequest(CefRefPtr request, - CefRefPtr client); + CefRefPtr client, + CefRefPtr request_context); ~CefBrowserURLRequest() override; bool Start(); diff --git a/libcef/browser/chrome_scheme_handler.cc b/libcef/browser/chrome_scheme_handler.cc index d141f423e..4fd4538c0 100644 --- a/libcef/browser/chrome_scheme_handler.cc +++ b/libcef/browser/chrome_scheme_handler.cc @@ -10,10 +10,9 @@ #include "include/cef_version.h" #include "include/cef_web_plugin.h" -#include "libcef/browser/context.h" #include "libcef/browser/frame_host_impl.h" #include "libcef/browser/internal_scheme_handler.h" -#include "libcef/browser/scheme_impl.h" +#include "libcef/browser/url_request_manager.h" #include "libcef/browser/thread_util.h" #include "libcef/common/content_client.h" @@ -182,7 +181,8 @@ class Delegate : public InternalHandlerDelegate { public: Delegate() {} - bool OnRequest(CefRefPtr request, + bool OnRequest(CefRefPtr browser, + CefRefPtr request, Action* action) override { GURL url = GURL(request->GetURL().ToString()); std::string path = url.path(); @@ -200,7 +200,7 @@ class Delegate : public InternalHandlerDelegate { handled = OnLicense(action); break; case CHROME_VERSION: - handled = OnVersion(action); + handled = OnVersion(browser, action); break; default: break; @@ -245,7 +245,8 @@ class Delegate : public InternalHandlerDelegate { return true; } - bool OnVersion(Action* action) { + bool OnVersion(CefRefPtr browser, + Action* action) { base::StringPiece piece = CefContentClient::Get()->GetDataResource( IDR_CEF_VERSION_HTML, ui::SCALE_FACTOR_NONE); if (piece.empty()) { @@ -276,7 +277,8 @@ class Delegate : public InternalHandlerDelegate { parser.Add("USERAGENT", CefContentClient::Get()->GetUserAgent()); parser.Add("COMMANDLINE", GetCommandLine()); parser.Add("MODULEPATH", GetModulePath()); - parser.Add("CACHEPATH", CefString(CefContext::Get()->cache_path().value())); + parser.Add("CACHEPATH", + browser->GetHost()->GetRequestContext()->GetCachePath()); std::string tmpl = piece.as_string(); parser.Parse(&tmpl); @@ -328,15 +330,20 @@ void DidFinishChromeVersionLoad(CefRefPtr frame) { class ChromeProtocolHandlerWrapper : public net::URLRequestJobFactory::ProtocolHandler { public: - explicit ChromeProtocolHandlerWrapper( - scoped_ptr chrome_protocol_handler) - : chrome_protocol_handler_(chrome_protocol_handler.Pass()) { + ChromeProtocolHandlerWrapper( + CefURLRequestManager* request_manager, + scoped_ptr + chrome_protocol_handler) + : request_manager_(request_manager), + chrome_protocol_handler_(chrome_protocol_handler.Pass()) { + DCHECK(request_manager_); } net::URLRequestJob* MaybeCreateJob( net::URLRequest* request, net::NetworkDelegate* network_delegate) const override { - // Keep synchronized with the checks in ChromeProtocolHandler::MaybeCreateJob. + // Keep synchronized with the checks in + // ChromeProtocolHandler::MaybeCreateJob. if (content::ViewHttpCacheJobFactory::IsSupportedURL(request->url()) || (request->url().SchemeIs(content::kChromeUIScheme) && request->url().host() == content::kChromeUIAppCacheInternalsHost) || @@ -347,21 +354,24 @@ class ChromeProtocolHandlerWrapper : #endif (request->url().SchemeIs(content::kChromeUIScheme) && request->url().host() == content::kChromeUIHistogramHost)) { - return chrome_protocol_handler_->MaybeCreateJob(request, network_delegate); + return chrome_protocol_handler_->MaybeCreateJob(request, + network_delegate); } // Use the protocol handler registered with CEF. - return scheme::GetRequestJob(request, network_delegate); + return request_manager_->GetRequestJob(request, network_delegate); } private: - scoped_ptr chrome_protocol_handler_; + CefURLRequestManager* request_manager_; + scoped_ptr + chrome_protocol_handler_; }; } // namespace -void RegisterChromeHandler() { - CefRegisterSchemeHandlerFactory( +void RegisterChromeHandler(CefURLRequestManager* request_manager) { + request_manager->AddFactory( content::kChromeUIScheme, std::string(), CreateInternalHandlerFactory( @@ -393,10 +403,12 @@ void DidFinishChromeLoad(CefRefPtr frame, scoped_ptr WrapChromeProtocolHandler( + CefURLRequestManager* request_manager, scoped_ptr chrome_protocol_handler) { scoped_ptr ret( - new ChromeProtocolHandlerWrapper(chrome_protocol_handler.Pass())); + new ChromeProtocolHandlerWrapper(request_manager, + chrome_protocol_handler.Pass())); return ret.Pass(); } diff --git a/libcef/browser/chrome_scheme_handler.h b/libcef/browser/chrome_scheme_handler.h index f5b35f40e..3de129ae7 100644 --- a/libcef/browser/chrome_scheme_handler.h +++ b/libcef/browser/chrome_scheme_handler.h @@ -24,12 +24,14 @@ namespace content { class BrowserContext; } +class CefURLRequestManager; + namespace scheme { extern const char kChromeURL[]; // Register the chrome scheme handler. -void RegisterChromeHandler(); +void RegisterChromeHandler(CefURLRequestManager* request_manager); // Used to redirect about: URLs to chrome: URLs. bool WillHandleBrowserAboutURL(GURL* url, @@ -43,6 +45,7 @@ void DidFinishChromeLoad(CefRefPtr frame, // "chrome" protocol handler and forward the rest to CEF's handler. scoped_ptr WrapChromeProtocolHandler( + CefURLRequestManager* request_manager, scoped_ptr chrome_protocol_handler); diff --git a/libcef/browser/content_browser_client.cc b/libcef/browser/content_browser_client.cc index 84c6f7c8a..8f82663fb 100644 --- a/libcef/browser/content_browser_client.cc +++ b/libcef/browser/content_browser_client.cc @@ -64,12 +64,14 @@ namespace { // In-memory store for access tokens used by geolocation. class CefAccessTokenStore : public content::AccessTokenStore { public: - CefAccessTokenStore() {} + // |system_context| is used by NetworkLocationProvider to communicate with a + // remote geolocation service. + explicit CefAccessTokenStore(net::URLRequestContextGetter* system_context) + : system_context_(system_context) {} void LoadAccessTokens( const LoadAccessTokensCallbackType& callback) override { - callback.Run(access_token_set_, - CefContentBrowserClient::Get()->request_context().get()); + callback.Run(access_token_set_, system_context_); } void SaveAccessToken( @@ -78,6 +80,7 @@ class CefAccessTokenStore : public content::AccessTokenStore { } private: + net::URLRequestContextGetter* system_context_; AccessTokenSet access_token_set_; DISALLOW_COPY_AND_ASSIGN(CefAccessTokenStore); @@ -754,7 +757,8 @@ void CefContentBrowserClient::AllowCertificateError( } content::AccessTokenStore* CefContentBrowserClient::CreateAccessTokenStore() { - return new CefAccessTokenStore; + return new CefAccessTokenStore( + browser_main_parts_->browser_context()->request_context().get()); } void CefContentBrowserClient::RequestPermission( @@ -986,7 +990,7 @@ std::string CefContentBrowserClient::GetDefaultDownloadName() { content::DevToolsManagerDelegate* CefContentBrowserClient::GetDevToolsManagerDelegate() { - return new CefDevToolsManagerDelegate(browser_context().get()); + return new CefDevToolsManagerDelegate(); } #if defined(OS_POSIX) && !defined(OS_MACOSX) @@ -1041,11 +1045,6 @@ CefContentBrowserClient::browser_context() const { return browser_main_parts_->browser_context(); } -scoped_refptr -CefContentBrowserClient::request_context() const { - return browser_main_parts_->request_context(); -} - CefDevToolsDelegate* CefContentBrowserClient::devtools_delegate() const { return browser_main_parts_->devtools_delegate(); } @@ -1053,8 +1052,3 @@ CefDevToolsDelegate* CefContentBrowserClient::devtools_delegate() const { PrefService* CefContentBrowserClient::pref_service() const { return browser_main_parts_->pref_service(); } - -scoped_ptr -CefContentBrowserClient::proxy_config_service() const { - return browser_main_parts_->proxy_config_service(); -} diff --git a/libcef/browser/content_browser_client.h b/libcef/browser/content_browser_client.h index fa9ed4121..d68e7d68b 100644 --- a/libcef/browser/content_browser_client.h +++ b/libcef/browser/content_browser_client.h @@ -21,7 +21,6 @@ #include "base/memory/scoped_ptr.h" #include "base/synchronization/lock.h" #include "content/public/browser/content_browser_client.h" -#include "net/proxy/proxy_config_service.h" #include "url/gurl.h" class CefBrowserInfo; @@ -168,13 +167,9 @@ class CefContentBrowserClient : public content::ContentBrowserClient { void set_last_create_window_params(const LastCreateWindowParams& params); scoped_refptr browser_context() const; - scoped_refptr request_context() const; CefDevToolsDelegate* devtools_delegate() const; PrefService* pref_service() const; - // Passes ownership. - scoped_ptr proxy_config_service() const; - private: CefBrowserMainParts* browser_main_parts_; diff --git a/libcef/browser/context.cc b/libcef/browser/context.cc index 4e642972a..7936d397b 100644 --- a/libcef/browser/context.cc +++ b/libcef/browser/context.cc @@ -10,9 +10,9 @@ #include "libcef/browser/browser_message_loop.h" #include "libcef/browser/chrome_browser_process_stub.h" #include "libcef/browser/content_browser_client.h" -#include "libcef/browser/scheme_handler.h" #include "libcef/browser/thread_util.h" #include "libcef/browser/trace_subscriber.h" +#include "libcef/common/cef_switches.h" #include "libcef/common/main_delegate.h" #include "libcef/renderer/content_renderer_client.h" @@ -232,22 +232,6 @@ bool CefContext::Initialize(const CefMainArgs& args, init_thread_id_ = base::PlatformThread::CurrentId(); settings_ = settings; - cache_path_ = base::FilePath(CefString(&settings.cache_path)); - if (!cache_path_.empty() && - !base::DirectoryExists(cache_path_) && - !base::CreateDirectory(cache_path_)) { - NOTREACHED() << "The cache_path directory could not be created"; - cache_path_ = base::FilePath(); - } - if (cache_path_.empty()) { - // Create and use a temporary directory. - if (cache_temp_dir_.CreateUniqueTempDir()) { - cache_path_ = cache_temp_dir_.path(); - } else { - NOTREACHED() << "Failed to create temporary cache_path directory"; - } - } - #if !defined(OS_WIN) if (settings.multi_threaded_message_loop) { NOTIMPLEMENTED() << "multi_threaded_message_loop is not supported."; @@ -346,12 +330,24 @@ CefTraceSubscriber* CefContext::GetTraceSubscriber() { return trace_subscriber_.get(); } +void CefContext::PopulateRequestContextSettings( + CefRequestContextSettings* settings) { + CefRefPtr command_line = + CefCommandLine::GetGlobalCommandLine(); + CefString(&settings->cache_path) = CefString(&settings_.cache_path); + settings->persist_session_cookies = + settings_.persist_session_cookies || + command_line->HasSwitch(switches::kPersistSessionCookies); + settings->ignore_certificate_errors = + settings_.ignore_certificate_errors || + command_line->HasSwitch(switches::kIgnoreCertificateErrors); + CefString(&settings->accept_language_list) = + CefString(&settings_.accept_language_list); +} + void CefContext::OnContextInitialized() { CEF_REQUIRE_UIT(); - // Register internal scheme handlers. - scheme::RegisterInternalHandlers(); - // Must be created after the NotificationService. print_job_manager_.reset(new printing::PrintJobManager()); diff --git a/libcef/browser/context.h b/libcef/browser/context.h index c9d1a82ba..eaab1129e 100644 --- a/libcef/browser/context.h +++ b/libcef/browser/context.h @@ -12,8 +12,6 @@ #include "include/cef_app.h" -#include "base/files/file_path.h" -#include "base/files/scoped_temp_dir.h" #include "base/memory/scoped_ptr.h" #include "base/threading/platform_thread.h" @@ -59,9 +57,6 @@ class CefContext { // Returns true if the context is shutting down. bool shutting_down() { return shutting_down_; } - // Retrieve the path at which cache data will be stored on disk. - const base::FilePath& cache_path() const { return cache_path_; } - const CefSettings& settings() const { return settings_; } printing::PrintJobManager* print_job_manager() const { @@ -70,6 +65,10 @@ class CefContext { CefTraceSubscriber* GetTraceSubscriber(); + // Populate the request context settings based on CefSettings and command- + // line flags. + void PopulateRequestContextSettings(CefRequestContextSettings* settings); + private: void OnContextInitialized(); @@ -88,8 +87,6 @@ class CefContext { base::PlatformThreadId init_thread_id_; CefSettings settings_; - base::FilePath cache_path_; - base::ScopedTempDir cache_temp_dir_; scoped_ptr main_delegate_; scoped_ptr main_runner_; diff --git a/libcef/browser/cookie_manager_impl.cc b/libcef/browser/cookie_manager_impl.cc index 046e7f410..3fdff732c 100644 --- a/libcef/browser/cookie_manager_impl.cc +++ b/libcef/browser/cookie_manager_impl.cc @@ -8,11 +8,9 @@ #include #include -#include "libcef/browser/browser_context.h" #include "libcef/browser/content_browser_client.h" #include "libcef/browser/context.h" #include "libcef/browser/thread_util.h" -#include "libcef/browser/url_request_context_getter.h" #include "libcef/common/time_util.h" #include "base/bind.h" @@ -34,8 +32,9 @@ namespace { // Callback class for visiting cookies. class VisitCookiesCallback : public base::RefCounted { public: - explicit VisitCookiesCallback(net::CookieMonster* cookie_monster, - CefRefPtr visitor) + explicit VisitCookiesCallback( + scoped_refptr cookie_monster, + CefRefPtr visitor) : cookie_monster_(cookie_monster), visitor_(visitor) { } @@ -85,291 +84,276 @@ bool GetCookieDomain(const GURL& url, result); } -void RunCompletionOnIOThread(CefRefPtr callback) { +// Always execute the callback asynchronously. +void RunAsyncCompletionOnIOThread(CefRefPtr callback) { + if (!callback.get()) + return; CEF_POST_TASK(CEF_IOT, base::Bind(&CefCompletionCallback::OnComplete, callback.get())); } +// Always execute the callback asynchronously. +void DeleteCookiesCallbackImpl(CefRefPtr callback, + int num_deleted) { + if (!callback.get()) + return; + CEF_POST_TASK(CEF_IOT, + base::Bind(&CefDeleteCookiesCallback::OnComplete, callback.get(), + num_deleted)); +} + +// Always execute the callback asynchronously. +void SetCookieCallbackImpl(CefRefPtr callback, + bool success) { + if (!callback.get()) + return; + CEF_POST_TASK(CEF_IOT, + base::Bind(&CefSetCookieCallback::OnComplete, callback.get(), success)); +} + } // namespace -CefCookieManagerImpl::CefCookieManagerImpl(bool is_global) - : is_global_(is_global) { +CefCookieManagerImpl::CefCookieManagerImpl() { } CefCookieManagerImpl::~CefCookieManagerImpl() { } void CefCookieManagerImpl::Initialize( + CefRefPtr request_context, const CefString& path, - bool persist_session_cookies) { - if (is_global_) - SetGlobal(); - else - SetStoragePath(path, persist_session_cookies); + bool persist_session_cookies, + CefRefPtr callback) { + if (request_context.get()) { + request_context_ = request_context; + request_context_->GetRequestContextImpl( + BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO), + base::Bind(&CefCookieManagerImpl::InitWithContext, this, callback)); + } else { + SetStoragePath(path, persist_session_cookies, callback); + } +} + +void CefCookieManagerImpl::GetCookieMonster( + scoped_refptr task_runner, + const CookieMonsterCallback& callback) { + if (!task_runner.get()) + task_runner = base::MessageLoop::current()->task_runner(); + + if (!CEF_CURRENTLY_ON_IOT()) { + CEF_POST_TASK(CEF_IOT, + base::Bind(&CefCookieManagerImpl::GetCookieMonster, this, task_runner, + callback)); + return; + } + + if (HasContext()) { + RunMethodWithContext( + base::Bind(&CefCookieManagerImpl::GetCookieMonsterWithContext, this, + task_runner, callback)); + return; + } + + DCHECK(cookie_monster_.get()); + if (cookie_monster_.get()) { + if (task_runner->BelongsToCurrentThread()) { + // Execute the callback immediately. + callback.Run(cookie_monster_); + } else { + // Execute the callback on the target thread. + task_runner->PostTask(FROM_HERE, base::Bind(callback, cookie_monster_)); + } + return; + } +} + +scoped_refptr +CefCookieManagerImpl::GetExistingCookieMonster() { + CEF_REQUIRE_IOT(); + if (cookie_monster_.get()) { + return cookie_monster_; + } else if (request_context_impl_.get()) { + scoped_refptr cookie_monster = + request_context_impl_->GetURLRequestContext()->cookie_store()-> + GetCookieMonster(); + DCHECK(cookie_monster.get()); + return cookie_monster; + } + + LOG(ERROR) << "Cookie manager backing store does not exist yet"; + return NULL; } void CefCookieManagerImpl::SetSupportedSchemes( - const std::vector& schemes) { - if (CEF_CURRENTLY_ON_IOT()) { - if (!cookie_monster_.get()) - return; - - if (is_global_) { - // Global changes are handled by the request context. - scoped_refptr getter = - CefContentBrowserClient::Get()->request_context(); - - std::vector scheme_vec; - std::vector::const_iterator it = schemes.begin(); - for (; it != schemes.end(); ++it) - scheme_vec.push_back(it->ToString()); - - getter->SetCookieSupportedSchemes(scheme_vec); - return; - } - - supported_schemes_ = schemes; - - if (supported_schemes_.empty()) { - supported_schemes_.push_back("http"); - supported_schemes_.push_back("https"); - } - - std::set scheme_set; - std::vector::const_iterator it = supported_schemes_.begin(); - for (; it != supported_schemes_.end(); ++it) - scheme_set.insert(*it); - - const char** arr = new const char*[scheme_set.size()]; - std::set::const_iterator it2 = scheme_set.begin(); - for (int i = 0; it2 != scheme_set.end(); ++it2, ++i) - arr[i] = it2->c_str(); - - cookie_monster_->SetCookieableSchemes(arr, scheme_set.size()); - - delete [] arr; - } else { - // Execute on the IO thread. + const std::vector& schemes, + CefRefPtr callback) { + if (!CEF_CURRENTLY_ON_IOT()) { CEF_POST_TASK(CEF_IOT, - base::Bind(&CefCookieManagerImpl::SetSupportedSchemes, - this, schemes)); + base::Bind(&CefCookieManagerImpl::SetSupportedSchemes, this, schemes, + callback)); + return; } + + if (HasContext()) { + RunMethodWithContext( + base::Bind(&CefCookieManagerImpl::SetSupportedSchemesWithContext, this, + schemes, callback)); + return; + } + + DCHECK(cookie_monster_.get()); + if (!cookie_monster_.get()) + return; + + supported_schemes_ = schemes; + + if (supported_schemes_.empty()) { + supported_schemes_.push_back("http"); + supported_schemes_.push_back("https"); + } + + std::set scheme_set; + std::vector::const_iterator it = supported_schemes_.begin(); + for (; it != supported_schemes_.end(); ++it) + scheme_set.insert(*it); + + const char** arr = new const char*[scheme_set.size()]; + std::set::const_iterator it2 = scheme_set.begin(); + for (int i = 0; it2 != scheme_set.end(); ++it2, ++i) + arr[i] = it2->c_str(); + + cookie_monster_->SetCookieableSchemes(arr, scheme_set.size()); + + delete [] arr; + + RunAsyncCompletionOnIOThread(callback); } bool CefCookieManagerImpl::VisitAllCookies( CefRefPtr visitor) { - if (CEF_CURRENTLY_ON_IOT()) { - if (!cookie_monster_.get()) - return false; - - scoped_refptr callback( - new VisitCookiesCallback(cookie_monster_.get(), visitor)); - - cookie_monster_->GetAllCookiesAsync( - base::Bind(&VisitCookiesCallback::Run, callback.get())); - } else { - // Execute on the IO thread. - CEF_POST_TASK(CEF_IOT, - base::Bind(base::IgnoreResult(&CefCookieManagerImpl::VisitAllCookies), - this, visitor)); - } - + GetCookieMonster( + BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO), + base::Bind(&CefCookieManagerImpl::VisitAllCookiesInternal, this, + visitor)); return true; } bool CefCookieManagerImpl::VisitUrlCookies( - const CefString& url, bool includeHttpOnly, + const CefString& url, + bool includeHttpOnly, CefRefPtr visitor) { - if (CEF_CURRENTLY_ON_IOT()) { - if (!cookie_monster_.get()) - return false; - - net::CookieOptions options; - if (includeHttpOnly) - options.set_include_httponly(); - - scoped_refptr callback( - new VisitCookiesCallback(cookie_monster_.get(), visitor)); - - GURL gurl = GURL(url.ToString()); - cookie_monster_->GetAllCookiesForURLWithOptionsAsync(gurl, options, - base::Bind(&VisitCookiesCallback::Run, callback.get())); - } else { - // Execute on the IO thread. - CEF_POST_TASK(CEF_IOT, - base::Bind(base::IgnoreResult(&CefCookieManagerImpl::VisitUrlCookies), - this, url, includeHttpOnly, visitor)); - } - + GetCookieMonster( + BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO), + base::Bind(&CefCookieManagerImpl::VisitUrlCookiesInternal, this, url, + includeHttpOnly, visitor)); return true; } -bool CefCookieManagerImpl::SetCookie(const CefString& url, - const CefCookie& cookie) { - CEF_REQUIRE_IOT_RETURN(false); - - if (!cookie_monster_.get()) - return false; - +bool CefCookieManagerImpl::SetCookie( + const CefString& url, + const CefCookie& cookie, + CefRefPtr callback) { GURL gurl = GURL(url.ToString()); if (!gurl.is_valid()) return false; - std::string name = CefString(&cookie.name).ToString(); - std::string value = CefString(&cookie.value).ToString(); - std::string domain = CefString(&cookie.domain).ToString(); - std::string path = CefString(&cookie.path).ToString(); - - base::Time expiration_time; - if (cookie.has_expires) - cef_time_to_basetime(cookie.expires, expiration_time); - - cookie_monster_->SetCookieWithDetailsAsync( - gurl, name, value, domain, path, - expiration_time, - cookie.secure ? true : false, - cookie.httponly ? true : false, - net::COOKIE_PRIORITY_DEFAULT, - net::CookieStore::SetCookiesCallback()); + GetCookieMonster( + BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO), + base::Bind(&CefCookieManagerImpl::SetCookieInternal, this, gurl, cookie, + callback)); return true; } -bool CefCookieManagerImpl::DeleteCookies(const CefString& url, - const CefString& cookie_name) { - CEF_REQUIRE_IOT_RETURN(false); - - if (!cookie_monster_.get()) - return false; - - if (url.empty()) { - // Delete all cookies. - cookie_monster_->DeleteAllAsync(net::CookieMonster::DeleteCallback()); - return true; - } - +bool CefCookieManagerImpl::DeleteCookies( + const CefString& url, + const CefString& cookie_name, + CefRefPtr callback) { + // Empty URLs are allowed but not invalid URLs. GURL gurl = GURL(url.ToString()); - if (!gurl.is_valid()) + if (!gurl.is_empty() && !gurl.is_valid()) return false; - if (cookie_name.empty()) { - // Delete all matching host cookies. - cookie_monster_->DeleteAllForHostAsync(gurl, - net::CookieMonster::DeleteCallback()); - } else { - // Delete all matching host and domain cookies. - cookie_monster_->DeleteCookieAsync(gurl, cookie_name, base::Closure()); - } + GetCookieMonster( + BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO), + base::Bind(&CefCookieManagerImpl::DeleteCookiesInternal, this, gurl, + cookie_name, callback)); return true; } bool CefCookieManagerImpl::SetStoragePath( const CefString& path, - bool persist_session_cookies) { - if (CEF_CURRENTLY_ON_IOT()) { - base::FilePath new_path; - if (!path.empty()) - new_path = base::FilePath(path); - - if (is_global_) { - // Global path changes are handled by the request context. - scoped_refptr getter = - CefContentBrowserClient::Get()->request_context(); - getter->SetCookieStoragePath(new_path, persist_session_cookies); - cookie_monster_ = getter->GetURLRequestContext()->cookie_store()-> - GetCookieMonster(); - return true; - } - - if (cookie_monster_.get() && ((storage_path_.empty() && path.empty()) || - storage_path_ == new_path)) { - // The path has not changed so don't do anything. - return true; - } - - scoped_refptr persistent_store; - if (!new_path.empty()) { - // TODO(cef): Move directory creation to the blocking pool instead of - // allowing file IO on this thread. - base::ThreadRestrictions::ScopedAllowIO allow_io; - if (base::DirectoryExists(new_path) || - base::CreateDirectory(new_path)) { - const base::FilePath& cookie_path = new_path.AppendASCII("Cookies"); - persistent_store = - new content::SQLitePersistentCookieStore( - cookie_path, - BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO), - BrowserThread::GetMessageLoopProxyForThread(BrowserThread::DB), - persist_session_cookies, - NULL, - NULL); - } else { - NOTREACHED() << "The cookie storage directory could not be created"; - storage_path_.clear(); - } - } - - // Set the new cookie store that will be used for all new requests. The old - // cookie store, if any, will be automatically flushed and closed when no - // longer referenced. - cookie_monster_ = new net::CookieMonster(persistent_store.get(), NULL); - if (persistent_store.get() && persist_session_cookies) - cookie_monster_->SetPersistSessionCookies(true); - storage_path_ = new_path; - - // Restore the previously supported schemes. - SetSupportedSchemes(supported_schemes_); - } else { - // Execute on the IO thread. + bool persist_session_cookies, + CefRefPtr callback) { + if (!CEF_CURRENTLY_ON_IOT()) { CEF_POST_TASK(CEF_IOT, base::Bind(base::IgnoreResult(&CefCookieManagerImpl::SetStoragePath), - this, path, persist_session_cookies)); + this, path, persist_session_cookies, callback)); + return true; } + if (HasContext()) { + RunMethodWithContext( + base::Bind(&CefCookieManagerImpl::SetStoragePathWithContext, this, path, + persist_session_cookies, callback)); + return true; + } + + base::FilePath new_path; + if (!path.empty()) + new_path = base::FilePath(path); + + if (cookie_monster_.get() && ((storage_path_.empty() && path.empty()) || + storage_path_ == new_path)) { + // The path has not changed so don't do anything. + RunAsyncCompletionOnIOThread(callback); + return true; + } + + scoped_refptr persistent_store; + if (!new_path.empty()) { + // TODO(cef): Move directory creation to the blocking pool instead of + // allowing file IO on this thread. + base::ThreadRestrictions::ScopedAllowIO allow_io; + if (base::DirectoryExists(new_path) || + base::CreateDirectory(new_path)) { + const base::FilePath& cookie_path = new_path.AppendASCII("Cookies"); + persistent_store = + new content::SQLitePersistentCookieStore( + cookie_path, + BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO), + BrowserThread::GetMessageLoopProxyForThread(BrowserThread::DB), + persist_session_cookies, + NULL, + NULL); + } else { + NOTREACHED() << "The cookie storage directory could not be created"; + storage_path_.clear(); + } + } + + // Set the new cookie store that will be used for all new requests. The old + // cookie store, if any, will be automatically flushed and closed when no + // longer referenced. + cookie_monster_ = new net::CookieMonster(persistent_store.get(), NULL); + if (persistent_store.get() && persist_session_cookies) + cookie_monster_->SetPersistSessionCookies(true); + storage_path_ = new_path; + + // Restore the previously supported schemes. + SetSupportedSchemes(supported_schemes_, callback); + return true; } bool CefCookieManagerImpl::FlushStore( CefRefPtr callback) { - if (CEF_CURRENTLY_ON_IOT()) { - if (!cookie_monster_.get()) { - if (callback.get()) - RunCompletionOnIOThread(callback); - return true; - } - - base::Closure flush_callback; - if (callback.get()) - flush_callback = base::Bind(RunCompletionOnIOThread, callback); - else - flush_callback = base::Bind(&base::DoNothing); - - cookie_monster_->FlushStore(flush_callback); - } else { - // Execute on the IO thread. - CEF_POST_TASK(CEF_IOT, - base::Bind(base::IgnoreResult(&CefCookieManagerImpl::FlushStore), - this, callback)); - } - + GetCookieMonster( + BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO), + base::Bind(&CefCookieManagerImpl::FlushStoreInternal, this, callback)); return true; } -void CefCookieManagerImpl::SetGlobal() { - if (CEF_CURRENTLY_ON_IOT()) { - scoped_refptr getter = - CefContentBrowserClient::Get()->request_context(); - if (getter.get()) { - cookie_monster_ = - getter->GetURLRequestContext()->cookie_store()->GetCookieMonster(); - DCHECK(cookie_monster_.get()); - } - } else { - // Execute on the IO thread. - CEF_POST_TASK(CEF_IOT, base::Bind(&CefCookieManagerImpl::SetGlobal, this)); - } -} - // static bool CefCookieManagerImpl::GetCefCookie(const net::CanonicalCookie& cc, CefCookie& cookie) { @@ -421,33 +405,208 @@ bool CefCookieManagerImpl::GetCefCookie(const GURL& url, return true; } +bool CefCookieManagerImpl::HasContext() { + CEF_REQUIRE_IOT(); + return (request_context_impl_.get() || request_context_.get()); +} + +void CefCookieManagerImpl::RunMethodWithContext( + const CefRequestContextImpl::RequestContextCallback& method) { + CEF_REQUIRE_IOT(); + if (request_context_impl_.get()) { + method.Run(request_context_impl_); + } else if (request_context_.get()) { + // Try again after the request context is initialized. + request_context_->GetRequestContextImpl( + BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO), + method); + } else { + NOTREACHED(); + } +} + +void CefCookieManagerImpl::InitWithContext( + CefRefPtr callback, + scoped_refptr request_context) { + CEF_REQUIRE_IOT(); + + DCHECK(!request_context_impl_.get()); + request_context_impl_ = request_context; + + // Clear the CefRequestContextImpl reference here to avoid a potential + // reference loop between CefRequestContextImpl (which has a reference to + // CefRequestContextHandler), CefRequestContextHandler (which may keep a + // reference to this object) and this object. + request_context_ = NULL; + + RunAsyncCompletionOnIOThread(callback); +} + +void CefCookieManagerImpl::SetStoragePathWithContext( + const CefString& path, + bool persist_session_cookies, + CefRefPtr callback, + scoped_refptr request_context) { + CEF_REQUIRE_IOT(); + + base::FilePath new_path; + if (!path.empty()) + new_path = base::FilePath(path); + + request_context->SetCookieStoragePath(new_path, persist_session_cookies); + + RunAsyncCompletionOnIOThread(callback); +} + +void CefCookieManagerImpl::SetSupportedSchemesWithContext( + const std::vector& schemes, + CefRefPtr callback, + scoped_refptr request_context) { + CEF_REQUIRE_IOT(); + + std::vector scheme_vec; + std::vector::const_iterator it = schemes.begin(); + for (; it != schemes.end(); ++it) + scheme_vec.push_back(it->ToString()); + + request_context->SetCookieSupportedSchemes(scheme_vec); + + RunAsyncCompletionOnIOThread(callback); +} + +void CefCookieManagerImpl::GetCookieMonsterWithContext( + scoped_refptr task_runner, + const CookieMonsterCallback& callback, + scoped_refptr request_context) { + CEF_REQUIRE_IOT(); + + scoped_refptr cookie_monster = + request_context->GetURLRequestContext()->cookie_store()-> + GetCookieMonster(); + + if (task_runner->BelongsToCurrentThread()) { + // Execute the callback immediately. + callback.Run(cookie_monster); + } else { + // Execute the callback on the target thread. + task_runner->PostTask(FROM_HERE, base::Bind(callback, cookie_monster)); + } +} + +void CefCookieManagerImpl::VisitAllCookiesInternal( + CefRefPtr visitor, + scoped_refptr cookie_monster) { + CEF_REQUIRE_IOT(); + + scoped_refptr callback( + new VisitCookiesCallback(cookie_monster, visitor)); + + cookie_monster->GetAllCookiesAsync( + base::Bind(&VisitCookiesCallback::Run, callback.get())); +} + +void CefCookieManagerImpl::VisitUrlCookiesInternal( + const CefString& url, + bool includeHttpOnly, + CefRefPtr visitor, + scoped_refptr cookie_monster) { + CEF_REQUIRE_IOT(); + + net::CookieOptions options; + if (includeHttpOnly) + options.set_include_httponly(); + + scoped_refptr callback( + new VisitCookiesCallback(cookie_monster, visitor)); + + GURL gurl = GURL(url.ToString()); + cookie_monster->GetAllCookiesForURLWithOptionsAsync(gurl, options, + base::Bind(&VisitCookiesCallback::Run, callback.get())); +} + +void CefCookieManagerImpl::SetCookieInternal( + const GURL& url, + const CefCookie& cookie, + CefRefPtr callback, + scoped_refptr cookie_monster) { + CEF_REQUIRE_IOT(); + + std::string name = CefString(&cookie.name).ToString(); + std::string value = CefString(&cookie.value).ToString(); + std::string domain = CefString(&cookie.domain).ToString(); + std::string path = CefString(&cookie.path).ToString(); + + base::Time expiration_time; + if (cookie.has_expires) + cef_time_to_basetime(cookie.expires, expiration_time); + + cookie_monster->SetCookieWithDetailsAsync( + url, name, value, domain, path, + expiration_time, + cookie.secure ? true : false, + cookie.httponly ? true : false, + net::COOKIE_PRIORITY_DEFAULT, + base::Bind(SetCookieCallbackImpl, callback)); +} + +void CefCookieManagerImpl::DeleteCookiesInternal( + const GURL& url, + const CefString& cookie_name, + CefRefPtr callback, + scoped_refptr cookie_monster) { + CEF_REQUIRE_IOT(); + + if (url.is_empty()) { + // Delete all cookies. + cookie_monster->DeleteAllAsync( + base::Bind(DeleteCookiesCallbackImpl, callback)); + } else if (cookie_name.empty()) { + // Delete all matching host cookies. + cookie_monster->DeleteAllForHostAsync(url, + base::Bind(DeleteCookiesCallbackImpl, callback)); + } else { + // Delete all matching host and domain cookies. + cookie_monster->DeleteCookieAsync(url, cookie_name, + base::Bind(DeleteCookiesCallbackImpl, callback, -1)); + } +} + +void CefCookieManagerImpl::FlushStoreInternal( + CefRefPtr callback, + scoped_refptr cookie_monster) { + CEF_REQUIRE_IOT(); + + cookie_monster->FlushStore( + base::Bind(RunAsyncCompletionOnIOThread, callback)); +} // CefCookieManager methods ---------------------------------------------------- // static -CefRefPtr CefCookieManager::GetGlobalManager() { +CefRefPtr CefCookieManager::GetGlobalManager( + CefRefPtr callback) { // Verify that the context is in a valid state. if (!CONTEXT_STATE_VALID()) { NOTREACHED() << "context not valid"; return NULL; } - CefRefPtr manager(new CefCookieManagerImpl(true)); - manager->Initialize(CefString(), false); - return manager.get(); + return CefRequestContext::GetGlobalContext()->GetDefaultCookieManager( + callback); } // static CefRefPtr CefCookieManager::CreateManager( const CefString& path, - bool persist_session_cookies) { + bool persist_session_cookies, + CefRefPtr callback) { // Verify that the context is in a valid state. if (!CONTEXT_STATE_VALID()) { NOTREACHED() << "context not valid"; return NULL; } - CefRefPtr manager(new CefCookieManagerImpl(false)); - manager->Initialize(path, persist_session_cookies); - return manager.get(); + CefRefPtr cookie_manager = new CefCookieManagerImpl(); + cookie_manager->Initialize(NULL, path, persist_session_cookies, callback); + return cookie_manager.get(); } diff --git a/libcef/browser/cookie_manager_impl.h b/libcef/browser/cookie_manager_impl.h index 4c9a3d118..09b0ce3ff 100644 --- a/libcef/browser/cookie_manager_impl.h +++ b/libcef/browser/cookie_manager_impl.h @@ -6,45 +6,113 @@ #define CEF_LIBCEF_BROWSER_COOKIE_MANAGER_IMPL_H_ #include "include/cef_cookie.h" +#include "libcef/browser/request_context_impl.h" + #include "base/files/file_path.h" #include "net/cookies/cookie_monster.h" // Implementation of the CefCookieManager interface. class CefCookieManagerImpl : public CefCookieManager { public: - CefCookieManagerImpl(bool is_global); + CefCookieManagerImpl(); ~CefCookieManagerImpl() override; - // Initialize the cookie manager. - void Initialize(const CefString& path, - bool persist_session_cookies); + // Must be called immediately after this object is created. + void Initialize(CefRefPtr request_context, + const CefString& path, + bool persist_session_cookies, + CefRefPtr callback); + + // Executes |callback| either synchronously or asynchronously with the cookie + // monster object when it's available. If |task_runner| is NULL the callback + // will be executed on the originating thread. The resulting cookie monster + // object can only be accessed on the IO thread. + typedef base::Callback)> + CookieMonsterCallback; + void GetCookieMonster( + scoped_refptr task_runner, + const CookieMonsterCallback& callback); + + // Returns the existing cookie monster object. Logs an error if the cookie + // monster does not yet exist. Must be called on the IO thread. + scoped_refptr GetExistingCookieMonster(); // CefCookieManager methods. - void SetSupportedSchemes(const std::vector& schemes) override; + void SetSupportedSchemes(const std::vector& schemes, + CefRefPtr callback) override; bool VisitAllCookies(CefRefPtr visitor) override; bool VisitUrlCookies(const CefString& url, bool includeHttpOnly, CefRefPtr visitor) override; bool SetCookie(const CefString& url, - const CefCookie& cookie) override; + const CefCookie& cookie, + CefRefPtr callback) override; bool DeleteCookies(const CefString& url, - const CefString& cookie_name) override; + const CefString& cookie_name, + CefRefPtr callback) override; bool SetStoragePath(const CefString& path, - bool persist_session_cookies) override; + bool persist_session_cookies, + CefRefPtr callback) override; bool FlushStore(CefRefPtr callback) override; - net::CookieMonster* cookie_monster() { return cookie_monster_.get(); } - static bool GetCefCookie(const net::CanonicalCookie& cc, CefCookie& cookie); static bool GetCefCookie(const GURL& url, const std::string& cookie_line, CefCookie& cookie); private: - void SetGlobal(); + // Returns true if a context is or will be available. + bool HasContext(); - scoped_refptr cookie_monster_; - bool is_global_; + // Execute |method| on the IO thread once the request context is available. + void RunMethodWithContext( + const CefRequestContextImpl::RequestContextCallback& method); + + void InitWithContext( + CefRefPtr callback, + scoped_refptr request_context); + void SetStoragePathWithContext( + const CefString& path, + bool persist_session_cookies, + CefRefPtr callback, + scoped_refptr request_context); + void SetSupportedSchemesWithContext( + const std::vector& schemes, + CefRefPtr callback, + scoped_refptr request_context); + void GetCookieMonsterWithContext( + scoped_refptr task_runner, + const CookieMonsterCallback& callback, + scoped_refptr request_context); + + void VisitAllCookiesInternal( + CefRefPtr visitor, + scoped_refptr cookie_monster); + void VisitUrlCookiesInternal( + const CefString& url, + bool includeHttpOnly, + CefRefPtr visitor, + scoped_refptr cookie_monster); + void SetCookieInternal( + const GURL& url, + const CefCookie& cookie, + CefRefPtr callback, + scoped_refptr cookie_monster); + void DeleteCookiesInternal( + const GURL& url, + const CefString& cookie_name, + CefRefPtr callback, + scoped_refptr cookie_monster); + void FlushStoreInternal( + CefRefPtr callback, + scoped_refptr cookie_monster); + + // Used for cookie monsters owned by the context. + CefRefPtr request_context_; + scoped_refptr request_context_impl_; + + // Used for cookie monsters owned by this object. base::FilePath storage_path_; std::vector supported_schemes_; + scoped_refptr cookie_monster_; IMPLEMENT_REFCOUNTING(CefCookieManagerImpl); }; diff --git a/libcef/browser/cookie_store_proxy.cc b/libcef/browser/cookie_store_proxy.cc index 32fedb5b6..0146c961d 100644 --- a/libcef/browser/cookie_store_proxy.cc +++ b/libcef/browser/cookie_store_proxy.cc @@ -16,6 +16,8 @@ CefCookieStoreProxy::CefCookieStoreProxy( : parent_(parent), handler_(handler) { CEF_REQUIRE_IOT(); + DCHECK(parent_); + DCHECK(handler_.get()); } CefCookieStoreProxy::~CefCookieStoreProxy() { @@ -117,20 +119,18 @@ net::CookieStore* CefCookieStoreProxy::GetCookieStore() { scoped_refptr cookie_store; - if (handler_.get()) { - // Get the manager from the handler. - CefRefPtr manager = handler_->GetCookieManager(); - if (manager.get()) { - cookie_store = reinterpret_cast(manager.get())-> - cookie_monster(); - DCHECK(cookie_store.get()); - return cookie_store.get(); - } + CefRefPtr manager = handler_->GetCookieManager(); + if (manager.get()) { + // Use the cookie store provided by the manager. + cookie_store = reinterpret_cast(manager.get())-> + GetExistingCookieMonster(); + DCHECK(cookie_store.get()); + return cookie_store.get(); } DCHECK(parent_); if (parent_) { - // Use the global cookie store. + // Use the cookie store from the parent. cookie_store = parent_->cookie_store(); DCHECK(cookie_store.get()); } diff --git a/libcef/browser/devtools_delegate.cc b/libcef/browser/devtools_delegate.cc index 9b1456a16..500d5e3b4 100644 --- a/libcef/browser/devtools_delegate.cc +++ b/libcef/browser/devtools_delegate.cc @@ -173,9 +173,7 @@ std::string CefDevToolsDelegate::GetChromeDevToolsURL() { // CefDevToolsManagerDelegate -CefDevToolsManagerDelegate::CefDevToolsManagerDelegate( - content::BrowserContext* browser_context) - : browser_context_(browser_context) { +CefDevToolsManagerDelegate::CefDevToolsManagerDelegate() { } CefDevToolsManagerDelegate::~CefDevToolsManagerDelegate() { diff --git a/libcef/browser/devtools_delegate.h b/libcef/browser/devtools_delegate.h index c8133c2c5..8d0161bb5 100644 --- a/libcef/browser/devtools_delegate.h +++ b/libcef/browser/devtools_delegate.h @@ -45,8 +45,7 @@ class CefDevToolsDelegate : public content::DevToolsHttpHandlerDelegate { class CefDevToolsManagerDelegate : public content::DevToolsManagerDelegate { public: - explicit CefDevToolsManagerDelegate( - content::BrowserContext* browser_context); + CefDevToolsManagerDelegate(); ~CefDevToolsManagerDelegate() override; // DevToolsManagerDelegate implementation. @@ -63,8 +62,6 @@ class CefDevToolsManagerDelegate : public content::DevToolsManagerDelegate { std::string GetPageThumbnailData(const GURL& url) override; private: - content::BrowserContext* browser_context_; - DISALLOW_COPY_AND_ASSIGN(CefDevToolsManagerDelegate); }; diff --git a/libcef/browser/devtools_scheme_handler.cc b/libcef/browser/devtools_scheme_handler.cc index 1573c8985..38f23b80f 100644 --- a/libcef/browser/devtools_scheme_handler.cc +++ b/libcef/browser/devtools_scheme_handler.cc @@ -7,6 +7,7 @@ #include #include "libcef/browser/internal_scheme_handler.h" +#include "libcef/browser/url_request_manager.h" #include "base/strings/string_util.h" #include "content/public/common/url_constants.h" @@ -22,7 +23,8 @@ class Delegate : public InternalHandlerDelegate { public: Delegate() {} - bool OnRequest(CefRefPtr request, + bool OnRequest(CefRefPtr browser, + CefRefPtr request, Action* action) override { GURL url = GURL(request->GetURL().ToString()); std::string path = url.path(); @@ -43,8 +45,8 @@ class Delegate : public InternalHandlerDelegate { } // namespace -void RegisterChromeDevToolsHandler() { - CefRegisterSchemeHandlerFactory( +void RegisterChromeDevToolsHandler(CefURLRequestManager* request_manager) { + request_manager->AddFactory( content::kChromeDevToolsScheme, kChromeDevToolsHost, CreateInternalHandlerFactory( diff --git a/libcef/browser/devtools_scheme_handler.h b/libcef/browser/devtools_scheme_handler.h index 57168b17b..be6c1d6fe 100644 --- a/libcef/browser/devtools_scheme_handler.h +++ b/libcef/browser/devtools_scheme_handler.h @@ -6,12 +6,14 @@ #define CEF_LIBCEF_BROWSER_DEVTOOLS_SCHEME_HANDLER_H_ #pragma once +class CefURLRequestManager; + namespace scheme { extern const char kChromeDevToolsHost[]; // Register the chrome-devtools scheme handler. -void RegisterChromeDevToolsHandler(); +void RegisterChromeDevToolsHandler(CefURLRequestManager* request_manager); } // namespace scheme diff --git a/libcef/browser/internal_scheme_handler.cc b/libcef/browser/internal_scheme_handler.cc index 6a955ffb3..bfc7f4f15 100644 --- a/libcef/browser/internal_scheme_handler.cc +++ b/libcef/browser/internal_scheme_handler.cc @@ -125,7 +125,7 @@ class InternalHandlerFactory : public CefSchemeHandlerFactory { GURL url = GURL(request->GetURL().ToString()); InternalHandlerDelegate::Action action; - if (delegate_->OnRequest(request, &action)) { + if (delegate_->OnRequest(browser, request, &action)) { if (!action.redirect_url.is_empty() && action.redirect_url.is_valid()) return new RedirectHandler(action.redirect_url); diff --git a/libcef/browser/internal_scheme_handler.h b/libcef/browser/internal_scheme_handler.h index f29637374..7b06a8582 100644 --- a/libcef/browser/internal_scheme_handler.h +++ b/libcef/browser/internal_scheme_handler.h @@ -39,7 +39,8 @@ class InternalHandlerDelegate { virtual ~InternalHandlerDelegate() {} // Populate |action| and return true if the request was handled. - virtual bool OnRequest(CefRefPtr request, + virtual bool OnRequest(CefRefPtr browser, + CefRefPtr request, Action* action) = 0; }; diff --git a/libcef/browser/path_util_impl.cc b/libcef/browser/path_util_impl.cc index 9a73d800c..6a759309b 100644 --- a/libcef/browser/path_util_impl.cc +++ b/libcef/browser/path_util_impl.cc @@ -7,6 +7,7 @@ #include "base/files/file_path.h" #include "base/logging.h" #include "base/path_service.h" +#include "chrome/common/chrome_paths.h" bool CefGetPath(PathKey key, CefString& path) { int pref_key = base::PATH_START; @@ -29,6 +30,14 @@ bool CefGetPath(PathKey key, CefString& path) { case PK_FILE_MODULE: pref_key = base::FILE_MODULE; break; +#if defined(OS_WIN) + case PK_LOCAL_APP_DATA: + pref_key = base::DIR_LOCAL_APP_DATA; + break; +#endif + case PK_USER_DATA: + pref_key = chrome::DIR_USER_DATA; + break; default: NOTREACHED() << "invalid argument"; return false; diff --git a/libcef/browser/request_context_impl.cc b/libcef/browser/request_context_impl.cc index 37712b93d..402004f6a 100644 --- a/libcef/browser/request_context_impl.cc +++ b/libcef/browser/request_context_impl.cc @@ -7,18 +7,29 @@ #include "libcef/browser/browser_context_proxy.h" #include "libcef/browser/content_browser_client.h" #include "libcef/browser/context.h" +#include "libcef/browser/cookie_manager_impl.h" #include "libcef/browser/thread_util.h" #include "base/atomic_sequence_num.h" #include "base/logging.h" +using content::BrowserThread; + namespace { base::StaticAtomicSequenceNumber g_next_id; +CefRefPtr GetImpl(CefRefPtr context) { + if (context->IsProxy()) + return static_cast(context.get())->parent(); + return static_cast(context.get()); +} + } // namespace -// Static functions +// CefBrowserContext + +// static CefRefPtr CefRequestContext::GetGlobalContext() { // Verify that the context is in a valid state. if (!CONTEXT_STATE_VALID()) { @@ -26,69 +37,213 @@ CefRefPtr CefRequestContext::GetGlobalContext() { return NULL; } - return new CefRequestContextImpl( - CefContentBrowserClient::Get()->browser_context().get()); + return CefRequestContextImpl::GetForBrowserContext( + CefContentBrowserClient::Get()->browser_context()); } +// static CefRefPtr CefRequestContext::CreateContext( - CefRefPtr handler) { + const CefRequestContextSettings& settings, + CefRefPtr handler) { // Verify that the context is in a valid state. if (!CONTEXT_STATE_VALID()) { NOTREACHED() << "context not valid"; return NULL; } - return new CefRequestContextImpl(handler); + return new CefRequestContextImpl(settings, handler); } +// static +CefRefPtr CefRequestContext::CreateContext( + CefRefPtr other, + CefRefPtr handler) { + // Verify that the context is in a valid state. + if (!CONTEXT_STATE_VALID()) { + NOTREACHED() << "context not valid"; + return NULL; + } + + if (!other.get()) + return NULL; + + return new CefRequestContextImpl( + static_cast(other.get()), handler); +} + + // CefBrowserContextImpl -CefRequestContextImpl::CefRequestContextImpl( - scoped_refptr browser_context) - : browser_context_(browser_context), - unique_id_(0) { - DCHECK(browser_context.get()); - if (!IsGlobal()) { - CEF_REQUIRE_UIT(); - scoped_refptr proxy = - static_cast(browser_context.get()); - handler_ = proxy->handler(); - } -} - -CefRequestContextImpl::CefRequestContextImpl( - CefRefPtr handler) - : handler_(handler), - unique_id_(g_next_id.GetNext()) { -} - CefRequestContextImpl::~CefRequestContextImpl() { } -scoped_refptr -CefRequestContextImpl::GetOrCreateBrowserContext() { - CEF_REQUIRE_UIT(); - if (!browser_context_) { - browser_context_ = new CefBrowserContextProxy( - handler_, CefContentBrowserClient::Get()->browser_context()); +// static +CefRefPtr CefRequestContextImpl::GetForRequestContext( + CefRefPtr request_context) { + if (request_context.get()) { + // Use the context from the provided CefRequestContext. + return static_cast(request_context.get()); } + + // Use the global context. + scoped_refptr browser_context = + CefContentBrowserClient::Get()->browser_context(); + return GetForBrowserContext(browser_context); +} + +// static +CefRefPtr CefRequestContextImpl::GetForBrowserContext( + scoped_refptr browser_context) { + DCHECK(browser_context.get()); + return new CefRequestContextImpl(browser_context); +} + +scoped_refptr CefRequestContextImpl::GetBrowserContext() { + CEF_REQUIRE_UIT(); + + if (!browser_context_) { + scoped_refptr parent; + + if (other_.get()) { + // Share storage with |other_|. + parent = GetImpl(other_->GetBrowserContext()); + } + + if (!parent.get()) { + const base::FilePath& cache_path = + base::FilePath(CefString(&settings_.cache_path)); + if (!cache_path.empty()) { + // Check if a CefBrowserContextImpl is already globally registered for + // the specified cache path. If so then use it. + parent = CefBrowserContextImpl::GetForCachePath(cache_path); + } + } + + if (!parent.get()) { + // Create a new CefBrowserContextImpl instance. If the cache path is non- + // empty then this new instance will become the globally registered + // CefBrowserContextImpl for that path. Otherwise, this new instance will + // be a completely isolated "incongento mode" context. + parent = new CefBrowserContextImpl(settings_); + parent->Initialize(); + } + + // The parent's settings may be different. Force our settings to match the + // parent. + settings_ = parent->GetSettings(); + + if (handler_.get()) { + // Use a proxy that will execute handler callbacks where appropriate and + // otherwise forward all requests to the parent implementation. + browser_context_ = new CefBrowserContextProxy(handler_, parent); + } else { + // Use the parent implementation directly. + browser_context_ = parent; + } + + request_context_impl_ = parent->request_context().get(); + DCHECK(request_context_impl_); + + if (handler_.get()) { + // Keep the handler alive until the associated request context is + // destroyed. + request_context_impl_->AddHandler(handler_); + } + } + + if (!request_context_impl_) { + request_context_impl_ = GetImpl(browser_context_)->request_context().get(); + DCHECK(request_context_impl_); + } + + if (other_.get()) { + // Clear the reference to |other_| after setting |request_context_impl_|. + // This is the reverse order of checks in IsSharedWith(). + other_ = NULL; + } + return browser_context_; } +void CefRequestContextImpl::GetBrowserContext( + scoped_refptr task_runner, + const BrowserContextCallback& callback) { + if (!task_runner.get()) + task_runner = base::MessageLoop::current()->task_runner(); + GetBrowserContextOnUIThread(task_runner, callback); +} + +void CefRequestContextImpl::GetRequestContextImpl( + scoped_refptr task_runner, + const RequestContextCallback& callback) { + if (!task_runner.get()) + task_runner = base::MessageLoop::current()->task_runner(); + if (request_context_impl_) { + // The browser context already exists. + DCHECK(browser_context_.get()); + GetRequestContextImplOnIOThread(task_runner, callback, browser_context_); + } else { + // Need to initialize the browser context first. + GetBrowserContextOnUIThread( + BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO), + base::Bind(&CefRequestContextImpl::GetRequestContextImplOnIOThread, + this, task_runner, callback)); + } +} + bool CefRequestContextImpl::IsSame(CefRefPtr other) { - CefRequestContextImpl* impl = + CefRequestContextImpl* other_impl = static_cast(other.get()); - if (!impl) + if (!other_impl) return false; - // Compare CefBrowserContext points if one has been associated. - if (browser_context_ && impl->browser_context_) - return (browser_context_ == impl->browser_context_); - else if (browser_context_ || impl->browser_context_) + // Compare CefBrowserContext pointers if one has been associated. + if (browser_context_ && other_impl->browser_context_) + return (browser_context_ == other_impl->browser_context_); + else if (browser_context_ || other_impl->browser_context_) return false; // Otherwise compare unique IDs. - return (unique_id_ == impl->unique_id_); + return (unique_id_ == other_impl->unique_id_); +} + +bool CefRequestContextImpl::IsSharingWith(CefRefPtr other) { + CefRequestContextImpl* other_impl = + static_cast(other.get()); + if (!other_impl) + return false; + + if (IsSame(other)) + return true; + + CefRefPtr pending_other = other_; + if (pending_other.get()) { + // This object is not initialized but we know what context this object will + // share with. Compare to that other context instead. + return pending_other->IsSharingWith(other); + } + + pending_other = other_impl->other_; + if (pending_other.get()) { + // The other object is not initialized but we know what context that object + // will share with. Compare to that other context instead. + return pending_other->IsSharingWith(this); + } + + if (request_context_impl_ && other_impl->request_context_impl_) { + // Both objects are initialized. Compare the request context objects. + return (request_context_impl_ == other_impl->request_context_impl_); + } + + // This or the other object is not initialized. Compare the cache path values. + // If both are non-empty and the same then they'll share the same storage. + if (settings_.cache_path.length > 0 && + other_impl->settings_.cache_path.length > 0) { + return (base::FilePath(CefString(&settings_.cache_path)) == + base::FilePath(CefString(&other_impl->settings_.cache_path))); + } + + return false; } bool CefRequestContextImpl::IsGlobal() { @@ -99,3 +254,126 @@ bool CefRequestContextImpl::IsGlobal() { CefRefPtr CefRequestContextImpl::GetHandler() { return handler_; } + +CefString CefRequestContextImpl::GetCachePath() { + return CefString(&settings_.cache_path); +} + +CefRefPtr CefRequestContextImpl::GetDefaultCookieManager( + CefRefPtr callback) { + CefRefPtr cookie_manager = new CefCookieManagerImpl(); + cookie_manager->Initialize(this, CefString(), false, callback); + return cookie_manager.get(); +} + +bool CefRequestContextImpl::RegisterSchemeHandlerFactory( + const CefString& scheme_name, + const CefString& domain_name, + CefRefPtr factory) { + GetRequestContextImpl( + BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO), + base::Bind(&CefRequestContextImpl::RegisterSchemeHandlerFactoryInternal, + this, scheme_name, domain_name, factory)); + return true; +} + +bool CefRequestContextImpl::ClearSchemeHandlerFactories() { + GetRequestContextImpl( + BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO), + base::Bind(&CefRequestContextImpl::ClearSchemeHandlerFactoriesInternal, + this)); + return true; +} + +CefRequestContextImpl::CefRequestContextImpl( + scoped_refptr browser_context) + : browser_context_(browser_context), + settings_(browser_context->GetSettings()), + handler_(browser_context->GetHandler()), + unique_id_(0), + request_context_impl_(NULL) { +} + +CefRequestContextImpl::CefRequestContextImpl( + const CefRequestContextSettings& settings, + CefRefPtr handler) + : settings_(settings), + handler_(handler), + unique_id_(g_next_id.GetNext()), + request_context_impl_(NULL) { +} + +CefRequestContextImpl::CefRequestContextImpl( + CefRefPtr other, + CefRefPtr handler) + : other_(other), + handler_(handler), + unique_id_(g_next_id.GetNext()), + request_context_impl_(NULL) { +} + +void CefRequestContextImpl::GetBrowserContextOnUIThread( + scoped_refptr task_runner, + const BrowserContextCallback& callback) { + if (!CEF_CURRENTLY_ON_UIT()) { + CEF_POST_TASK(CEF_UIT, + base::Bind(&CefRequestContextImpl::GetBrowserContextOnUIThread, + this, task_runner, callback)); + return; + } + + // Make sure the browser context exists. + GetBrowserContext(); + DCHECK(browser_context_.get()); + DCHECK(request_context_impl_); + + if (task_runner->BelongsToCurrentThread()) { + // Execute the callback immediately. + callback.Run(browser_context_); + } else { + // Execute the callback on the target thread. + task_runner->PostTask(FROM_HERE, base::Bind(callback, browser_context_)); + } +} + +void CefRequestContextImpl::GetRequestContextImplOnIOThread( + scoped_refptr task_runner, + const RequestContextCallback& callback, + scoped_refptr browser_context) { + if (!CEF_CURRENTLY_ON_IOT()) { + CEF_POST_TASK(CEF_IOT, + base::Bind(&CefRequestContextImpl::GetRequestContextImplOnIOThread, + this, task_runner, callback, browser_context)); + return; + } + + DCHECK(request_context_impl_); + + // Make sure the request context exists. + request_context_impl_->GetURLRequestContext(); + + if (task_runner->BelongsToCurrentThread()) { + // Execute the callback immediately. + callback.Run(request_context_impl_); + } else { + // Execute the callback on the target thread. + task_runner->PostTask(FROM_HERE, + base::Bind(callback, make_scoped_refptr(request_context_impl_))); + } +} + +void CefRequestContextImpl::RegisterSchemeHandlerFactoryInternal( + const CefString& scheme_name, + const CefString& domain_name, + CefRefPtr factory, + scoped_refptr request_context) { + CEF_REQUIRE_IOT(); + request_context->request_manager()->AddFactory(scheme_name, domain_name, + factory); +} + +void CefRequestContextImpl::ClearSchemeHandlerFactoriesInternal( + scoped_refptr request_context) { + CEF_REQUIRE_IOT(); + request_context->request_manager()->ClearFactories(); +} diff --git a/libcef/browser/request_context_impl.h b/libcef/browser/request_context_impl.h index 863a23992..b3a5513ae 100644 --- a/libcef/browser/request_context_impl.h +++ b/libcef/browser/request_context_impl.h @@ -9,27 +9,98 @@ #include "include/cef_request_context.h" #include "libcef/browser/browser_context.h" +// Implementation of the CefRequestContext interface. All methods are thread- +// safe unless otherwise indicated. class CefRequestContextImpl : public CefRequestContext { public: - explicit CefRequestContextImpl( - scoped_refptr browser_context); - explicit CefRequestContextImpl(CefRefPtr handler); ~CefRequestContextImpl() override; - scoped_refptr GetOrCreateBrowserContext(); + // Returns a CefRequestContextImpl for the specified |request_context|. + // Will return the global context if |request_context| is NULL. + static CefRefPtr GetForRequestContext( + CefRefPtr request_context); + + // Returns a CefRequestContextImpl for the specified |browser_context|. + // |browser_context| must be non-NULL. + static CefRefPtr GetForBrowserContext( + scoped_refptr browser_context); + + // Returns the browser context object. Can only be called on the UI thread. + scoped_refptr GetBrowserContext(); + + // Executes |callback| either synchronously or asynchronously with the browser + // context object when it's available. If |task_runner| is NULL the callback + // will be executed on the originating thread. The resulting context object + // can only be accessed on the UI thread. + typedef base::Callback)> + BrowserContextCallback; + void GetBrowserContext( + scoped_refptr task_runner, + const BrowserContextCallback& callback); + + // Executes |callback| either synchronously or asynchronously with the request + // context object when it's available. If |task_runner| is NULL the callback + // will be executed on the originating thread. The resulting context object + // can only be accessed on the IO thread. + typedef base::Callback)> + RequestContextCallback; + void GetRequestContextImpl( + scoped_refptr task_runner, + const RequestContextCallback& callback); bool IsSame(CefRefPtr other) override; + bool IsSharingWith(CefRefPtr other) override; bool IsGlobal() override; CefRefPtr GetHandler() override; + CefString GetCachePath() override; + CefRefPtr GetDefaultCookieManager( + CefRefPtr callback) override; + bool RegisterSchemeHandlerFactory( + const CefString& scheme_name, + const CefString& domain_name, + CefRefPtr factory) override; + bool ClearSchemeHandlerFactories() override; + + const CefRequestContextSettings& settings() const { return settings_; } + + private: + friend class CefRequestContext; + + explicit CefRequestContextImpl( + scoped_refptr browser_context); + CefRequestContextImpl(const CefRequestContextSettings& settings, + CefRefPtr handler); + CefRequestContextImpl(CefRefPtr other, + CefRefPtr handler); + + void GetBrowserContextOnUIThread( + scoped_refptr task_runner, + const BrowserContextCallback& callback); + void GetRequestContextImplOnIOThread( + scoped_refptr task_runner, + const RequestContextCallback& callback, + scoped_refptr browser_context); + + void RegisterSchemeHandlerFactoryInternal( + const CefString& scheme_name, + const CefString& domain_name, + CefRefPtr factory, + scoped_refptr request_context); + void ClearSchemeHandlerFactoriesInternal( + scoped_refptr request_context); - protected: scoped_refptr browser_context_; + CefRequestContextSettings settings_; + CefRefPtr other_; CefRefPtr handler_; // Used to uniquely identify CefRequestContext objects before an associated // CefBrowserContext has been created. int unique_id_; + // Owned by the CefBrowserContext. + CefURLRequestContextGetterImpl* request_context_impl_; + IMPLEMENT_REFCOUNTING(CefRequestContextImpl); DISALLOW_COPY_AND_ASSIGN(CefRequestContextImpl); }; diff --git a/libcef/browser/scheme_handler.cc b/libcef/browser/scheme_handler.cc index 342d12517..ae40afa1f 100644 --- a/libcef/browser/scheme_handler.cc +++ b/libcef/browser/scheme_handler.cc @@ -23,6 +23,7 @@ namespace scheme { void InstallInternalProtectedHandlers( net::URLRequestJobFactoryImpl* job_factory, + CefURLRequestManager* request_manager, content::ProtocolHandlerMap* protocol_handlers, net::FtpTransactionFactory* ftp_transaction_factory) { protocol_handlers->insert( @@ -58,6 +59,7 @@ void InstallInternalProtectedHandlers( // not to interfere with CEF's "chrome" handler. protocol_handler.reset( scheme::WrapChromeProtocolHandler( + request_manager, make_scoped_ptr(it->second.release())).release()); } else { protocol_handler.reset(it->second.release()); @@ -73,9 +75,9 @@ void InstallInternalProtectedHandlers( } } -void RegisterInternalHandlers() { - scheme::RegisterChromeHandler(); - scheme::RegisterChromeDevToolsHandler(); +void RegisterInternalHandlers(CefURLRequestManager* request_manager) { + scheme::RegisterChromeHandler(request_manager); + scheme::RegisterChromeDevToolsHandler(request_manager); } void DidFinishLoad(CefRefPtr frame, const GURL& validated_url) { diff --git a/libcef/browser/scheme_handler.h b/libcef/browser/scheme_handler.h index 062c5a24f..80d430d19 100644 --- a/libcef/browser/scheme_handler.h +++ b/libcef/browser/scheme_handler.h @@ -16,17 +16,20 @@ class FtpTransactionFactory; class URLRequestJobFactoryImpl; } +class CefURLRequestManager; + namespace scheme { // Install the internal scheme handlers provided by Chromium that cannot be // overridden. void InstallInternalProtectedHandlers( net::URLRequestJobFactoryImpl* job_factory, + CefURLRequestManager* request_manager, content::ProtocolHandlerMap* protocol_handlers, net::FtpTransactionFactory* ftp_transaction_factory); // Register the internal scheme handlers that can be overridden. -void RegisterInternalHandlers(); +void RegisterInternalHandlers(CefURLRequestManager* request_manager); // Used to fire any asynchronous content updates. void DidFinishLoad(CefRefPtr frame, const GURL& validated_url); diff --git a/libcef/browser/scheme_impl.cc b/libcef/browser/scheme_impl.cc index 6864efd6b..b63769f01 100644 --- a/libcef/browser/scheme_impl.cc +++ b/libcef/browser/scheme_impl.cc @@ -1,361 +1,33 @@ -// Copyright (c) 2012 The Chromium Embedded Framework Authors. -// Portions copyright (c) 2006-2009 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. +// Copyright (c) 2015 The Chromium Embedded Framework Authors. All rights +// reserved. Use of this source code is governed by a BSD-style license that can +// be found in the LICENSE file. -#include - -#include "include/cef_browser.h" #include "include/cef_scheme.h" -#include "libcef/browser/browser_context.h" -#include "libcef/browser/browser_host_impl.h" -#include "libcef/browser/content_browser_client.h" #include "libcef/browser/context.h" -#include "libcef/browser/resource_request_job.h" -#include "libcef/browser/scheme_handler.h" -#include "libcef/browser/thread_util.h" -#include "libcef/browser/url_request_context_getter.h" -#include "libcef/common/request_impl.h" -#include "libcef/common/response_impl.h" -#include "libcef/common/scheme_registration.h" -#include "libcef/common/upload_data.h" -#include "base/bind.h" -#include "base/lazy_instance.h" #include "base/logging.h" -#include "base/message_loop/message_loop.h" -#include "base/strings/string_util.h" -#include "base/synchronization/lock.h" -#include "net/base/completion_callback.h" -#include "net/base/io_buffer.h" -#include "net/http/http_response_headers.h" -#include "net/http/http_util.h" -#include "net/url_request/url_request.h" -#include "net/url_request/url_request_context.h" -#include "net/url_request/url_request_filter.h" -#include "net/url_request/url_request_http_job.h" -#include "net/url_request/url_request_job.h" -#include "net/url_request/url_request_job_factory_impl.h" -#include "url/third_party/mozilla/url_parse.h" -#include "url/url_util.h" - -using net::URLRequestStatus; - -namespace { - -bool IsStandardScheme(const std::string& scheme) { - url::Component scheme_comp(0, scheme.length()); - return url::IsStandard(scheme.c_str(), scheme_comp); -} - -// Copied from net/url_request/url_request_job_manager.cc. -struct SchemeToFactory { - const char* scheme; - net::URLRequest::ProtocolFactory* factory; -}; -static const SchemeToFactory kBuiltinFactories[] = { - { "http", net::URLRequestHttpJob::Factory }, - { "https", net::URLRequestHttpJob::Factory }, -}; - -bool IsBuiltinScheme(const std::string& scheme) { - for (size_t i = 0; i < arraysize(kBuiltinFactories); ++i) - if (LowerCaseEqualsASCII(scheme, kBuiltinFactories[i].scheme)) - return true; - return false; -} - -net::URLRequestJob* GetBuiltinSchemeRequestJob( - net::URLRequest* request, - net::NetworkDelegate* network_delegate, - const std::string& scheme) { - // See if the request should be handled by a built-in protocol factory. - for (size_t i = 0; i < arraysize(kBuiltinFactories); ++i) { - if (scheme == kBuiltinFactories[i].scheme) { - net::URLRequestJob* job = - (kBuiltinFactories[i].factory)(request, network_delegate, scheme); - DCHECK(job); // The built-in factories are not expected to fail! - return job; - } - } - - return NULL; -} - -std::string ToLower(const std::string& str) { - std::string str_lower = str; - std::transform(str_lower.begin(), str_lower.end(), str_lower.begin(), - towlower); - return str; -} - -// Class that manages the CefSchemeHandlerFactory instances. -class CefUrlRequestManager { - protected: - // Class used for creating URLRequestJob instances. The lifespan of this - // object is managed by URLRequestJobFactory. - class ProtocolHandler : public net::URLRequestJobFactory::ProtocolHandler { - public: - explicit ProtocolHandler(const std::string& scheme) - : scheme_(scheme) {} - - // From net::URLRequestJobFactory::ProtocolHandler - net::URLRequestJob* MaybeCreateJob( - net::URLRequest* request, - net::NetworkDelegate* network_delegate) const override { - CEF_REQUIRE_IOT(); - return CefUrlRequestManager::GetInstance()->GetRequestJob( - request, network_delegate, scheme_); - } - - private: - std::string scheme_; - }; - - public: - CefUrlRequestManager() {} - - // Retrieve the singleton instance. - static CefUrlRequestManager* GetInstance(); - - bool AddFactory(const std::string& scheme, - const std::string& domain, - CefRefPtr factory) { - if (!factory.get()) { - RemoveFactory(scheme, domain); - return true; - } - - CEF_REQUIRE_IOT(); - - std::string scheme_lower = ToLower(scheme); - std::string domain_lower = ToLower(domain); - - // Hostname is only supported for standard schemes. - if (!IsStandardScheme(scheme_lower)) - domain_lower.clear(); - - SetProtocolHandlerIfNecessary(scheme_lower, true); - - handler_map_[make_pair(scheme_lower, domain_lower)] = factory; - - return true; - } - - void RemoveFactory(const std::string& scheme, - const std::string& domain) { - CEF_REQUIRE_IOT(); - - std::string scheme_lower = ToLower(scheme); - std::string domain_lower = ToLower(domain); - - // Hostname is only supported for standard schemes. - if (!IsStandardScheme(scheme_lower)) - domain_lower.clear(); - - HandlerMap::iterator iter = - handler_map_.find(make_pair(scheme_lower, domain_lower)); - if (iter != handler_map_.end()) { - handler_map_.erase(iter); - - SetProtocolHandlerIfNecessary(scheme_lower, false); - } - } - - // Clear all the existing URL handlers and unregister the ProtocolFactory. - void ClearFactories() { - CEF_REQUIRE_IOT(); - - net::URLRequestJobFactoryImpl* job_factory = GetJobFactoryImpl(); - - // Create a unique set of scheme names. - std::set schemes; - for (HandlerMap::const_iterator i = handler_map_.begin(); - i != handler_map_.end(); ++i) { - schemes.insert(i->first.first); - } - - for (std::set::const_iterator scheme = schemes.begin(); - scheme != schemes.end(); ++scheme) { - const std::string& scheme_name = *scheme; - if (!scheme::IsInternalProtectedScheme(scheme_name)) { - bool set_protocol = job_factory->SetProtocolHandler(scheme_name, NULL); - DCHECK(set_protocol); - } - } - - handler_map_.clear(); - } - - // Helper for chaining ProtocolHandler implementations. - net::URLRequestJob* GetRequestJob(net::URLRequest* request, - net::NetworkDelegate* network_delegate) { - CEF_REQUIRE_IOT(); - return GetRequestJob(request, network_delegate, request->url().scheme()); - } - - private: - net::URLRequestJobFactoryImpl* GetJobFactoryImpl() { - return CefContentBrowserClient::Get()->request_context()-> - job_factory_impl(); - } - - // Add or remove the protocol handler if necessary. |scheme| will already be - // in lower case. - void SetProtocolHandlerIfNecessary(const std::string& scheme, bool add) { - // Don't modify a protocol handler for internal protected schemes or if the - // protocol handler is still needed by other registered factories. - if (scheme::IsInternalProtectedScheme(scheme) || HasFactory(scheme)) - return; - - net::URLRequestJobFactoryImpl* job_factory = GetJobFactoryImpl(); - bool set_protocol = job_factory->SetProtocolHandler( - scheme, - (add ? new ProtocolHandler(scheme) : NULL)); - DCHECK(set_protocol); - } - - // Returns true if any factory currently exists for |scheme|. |scheme| will - // already be in lower case. - bool HasFactory(const std::string& scheme) { - if (handler_map_.empty()) - return false; - - for (HandlerMap::const_iterator i = handler_map_.begin(); - i != handler_map_.end(); ++i) { - if (scheme == i->first.first) - return true; - } - - return false; - } - - // Retrieve the matching handler factory, if any. |scheme| will already be in - // lower case. - CefRefPtr GetHandlerFactory( - net::URLRequest* request, const std::string& scheme) { - CefRefPtr factory; - - if (request->url().is_valid() && IsStandardScheme(scheme)) { - // Check for a match with a domain first. - const std::string& domain = request->url().host(); - - HandlerMap::iterator i = handler_map_.find(make_pair(scheme, domain)); - if (i != handler_map_.end()) - factory = i->second; - } - - if (!factory.get()) { - // Check for a match with no specified domain. - HandlerMap::iterator i = - handler_map_.find(make_pair(scheme, std::string())); - if (i != handler_map_.end()) - factory = i->second; - } - - return factory; - } - - // Create the job that will handle the request. |scheme| will already be in - // lower case. - net::URLRequestJob* GetRequestJob(net::URLRequest* request, - net::NetworkDelegate* network_delegate, - const std::string& scheme) { - net::URLRequestJob* job = NULL; - CefRefPtr factory = - GetHandlerFactory(request, scheme); - if (factory.get()) { - CefRefPtr browser = - CefBrowserHostImpl::GetBrowserForRequest(request); - CefRefPtr frame; - if (browser.get()) - frame = browser->GetFrameForRequest(request); - - // Populate the request data. - CefRefPtr requestPtr(new CefRequestImpl()); - requestPtr->Set(request); - - // Call the handler factory to create the handler for the request. - CefRefPtr handler = - factory->Create(browser.get(), frame, scheme, requestPtr.get()); - if (handler.get()) - job = new CefResourceRequestJob(request, network_delegate, handler); - } - - if (!job && IsBuiltinScheme(scheme)) { - // Give the built-in scheme handler a chance to handle the request. - job = GetBuiltinSchemeRequestJob(request, network_delegate, scheme); - } - -#ifndef NDEBUG - if (job) - DLOG(INFO) << "CefUrlRequestManager hit for " << request->url().spec(); -#endif - - return job; - } - - // Map (scheme, domain) to factories. Will only be accessed on the IO thread. - typedef std::map, - CefRefPtr > HandlerMap; - HandlerMap handler_map_; - - DISALLOW_EVIL_CONSTRUCTORS(CefUrlRequestManager); -}; - -base::LazyInstance g_manager = LAZY_INSTANCE_INITIALIZER; - -CefUrlRequestManager* CefUrlRequestManager::GetInstance() { - return g_manager.Pointer(); -} - -} // namespace - bool CefRegisterSchemeHandlerFactory( const CefString& scheme_name, const CefString& domain_name, CefRefPtr factory) { // Verify that the context is in a valid state. - if (!CONTEXT_STATE_VALID()) + if (!CONTEXT_STATE_VALID()) { + NOTREACHED() << "context not valid"; return false; - - if (CEF_CURRENTLY_ON(CEF_IOT)) { - return CefUrlRequestManager::GetInstance()->AddFactory(scheme_name, - domain_name, - factory); - } else { - CEF_POST_TASK(CEF_IOT, - base::Bind(base::IgnoreResult(&CefRegisterSchemeHandlerFactory), - scheme_name, domain_name, factory)); - return true; } + + return CefRequestContext::GetGlobalContext()-> + RegisterSchemeHandlerFactory(scheme_name, domain_name, factory); } bool CefClearSchemeHandlerFactories() { // Verify that the context is in a valid state. - if (!CONTEXT_STATE_VALID()) + if (!CONTEXT_STATE_VALID()) { + NOTREACHED() << "context not valid"; return false; - - if (CEF_CURRENTLY_ON(CEF_IOT)) { - CefUrlRequestManager::GetInstance()->ClearFactories(); - - // Register internal scheme handlers. - scheme::RegisterInternalHandlers(); - } else { - CEF_POST_TASK(CEF_IOT, - base::Bind(base::IgnoreResult(&CefClearSchemeHandlerFactories))); } - return true; + return CefRequestContext::GetGlobalContext()-> + ClearSchemeHandlerFactories(); } - -namespace scheme { - -net::URLRequestJob* GetRequestJob(net::URLRequest* request, - net::NetworkDelegate* network_delegate) { - return CefUrlRequestManager::GetInstance()->GetRequestJob( - request, network_delegate); -} - -} // namespace scheme diff --git a/libcef/browser/scheme_impl.h b/libcef/browser/scheme_impl.h deleted file mode 100644 index 5b66ef9a1..000000000 --- a/libcef/browser/scheme_impl.h +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright (c) 2013 The Chromium Embedded Framework Authors. All rights -// reserved. Use of this source code is governed by a BSD-style license that -// can be found in the LICENSE file. - -#ifndef CEF_LIBCEF_BROWSER_SCHEME_IMPL_H_ -#define CEF_LIBCEF_BROWSER_SCHEME_IMPL_H_ -#pragma once - -namespace net { -class NetworkDelegate; -class URLRequest; -class URLRequestJob; -} - -namespace scheme { - -// Helper for chaining net::URLRequestJobFactory::ProtocolHandler -// implementations. -net::URLRequestJob* GetRequestJob(net::URLRequest* request, - net::NetworkDelegate* network_delegate); - -} // namespace scheme - -#endif // CEF_LIBCEF_BROWSER_SCHEME_IMPL_H_ diff --git a/libcef/browser/url_request_context_getter_impl.cc b/libcef/browser/url_request_context_getter_impl.cc index 90984323c..01c2bdca4 100644 --- a/libcef/browser/url_request_context_getter_impl.cc +++ b/libcef/browser/url_request_context_getter_impl.cc @@ -10,8 +10,6 @@ #include #include -#include "libcef/browser/content_browser_client.h" -#include "libcef/browser/context.h" #include "libcef/browser/scheme_handler.h" #include "libcef/browser/thread_util.h" #include "libcef/browser/url_network_delegate.h" @@ -98,12 +96,16 @@ class CefHttpUserAgentSettings : public net::HttpUserAgentSettings { } // namespace CefURLRequestContextGetterImpl::CefURLRequestContextGetterImpl( + const CefRequestContextSettings& settings, base::MessageLoop* io_loop, base::MessageLoop* file_loop, content::ProtocolHandlerMap* protocol_handlers, + scoped_ptr proxy_config_service, content::URLRequestInterceptorScopedVector request_interceptors) - : io_loop_(io_loop), + : settings_(settings), + io_loop_(io_loop), file_loop_(file_loop), + proxy_config_service_(proxy_config_service.Pass()), request_interceptors_(request_interceptors.Pass()) { // Must first be created on the UI thread. CEF_REQUIRE_UIT(); @@ -124,19 +126,19 @@ net::URLRequestContext* CefURLRequestContextGetterImpl::GetURLRequestContext() { CEF_REQUIRE_IOT(); if (!url_request_context_.get()) { - const base::FilePath& cache_path = CefContext::Get()->cache_path(); const base::CommandLine* command_line = base::CommandLine::ForCurrentProcess(); - const CefSettings& settings = CefContext::Get()->settings(); + + base::FilePath cache_path; + if (settings_.cache_path.length > 0) + cache_path = base::FilePath(CefString(&settings_.cache_path)); url_request_context_.reset(new CefURLRequestContextImpl()); storage_.reset( new net::URLRequestContextStorage(url_request_context_.get())); - bool persist_session_cookies = - (settings.persist_session_cookies || - command_line->HasSwitch(switches::kPersistSessionCookies)); - SetCookieStoragePath(cache_path, persist_session_cookies); + SetCookieStoragePath(cache_path, + settings_.persist_session_cookies ? true : false); storage_->set_network_delegate(new CefNetworkDelegate); @@ -146,8 +148,8 @@ net::URLRequestContext* CefURLRequestContextGetterImpl::GetURLRequestContext() { base::WorkerPool::GetTaskRunner(true)))); const std::string& accept_language = - settings.accept_language_list.length > 0 ? - CefString(&settings.accept_language_list): "en-US,en"; + settings_.accept_language_list.length > 0 ? + CefString(&settings_.accept_language_list): "en-US,en"; storage_->set_http_user_agent_settings( new CefHttpUserAgentSettings(accept_language)); @@ -161,7 +163,7 @@ net::URLRequestContext* CefURLRequestContextGetterImpl::GetURLRequestContext() { NULL, url_request_context_.get(), url_request_context_->network_delegate(), - CefContentBrowserClient::Get()->proxy_config_service().release(), + proxy_config_service_.release(), *command_line, true)); storage_->set_proxy_service(system_proxy_service.release()); @@ -218,8 +220,7 @@ net::URLRequestContext* CefURLRequestContextGetterImpl::GetURLRequestContext() { network_session_params.http_server_properties = url_request_context_->http_server_properties(); network_session_params.ignore_certificate_errors = - (settings.ignore_certificate_errors || - command_line->HasSwitch(switches::kIgnoreCertificateErrors)); + settings_.ignore_certificate_errors ? true : false; net::HttpCache* main_cache = new net::HttpCache(network_session_params, main_backend); @@ -232,13 +233,18 @@ net::URLRequestContext* CefURLRequestContextGetterImpl::GetURLRequestContext() { scoped_ptr job_factory( new net::URLRequestJobFactoryImpl()); - job_factory_impl_ = job_factory.get(); + url_request_manager_.reset(new CefURLRequestManager(job_factory.get())); + // Install internal scheme handlers that cannot be overridden. scheme::InstallInternalProtectedHandlers(job_factory.get(), + url_request_manager_.get(), &protocol_handlers_, ftp_transaction_factory_.get()); protocol_handlers_.clear(); + // Register internal scheme handlers that can be overridden. + scheme::RegisterInternalHandlers(url_request_manager_.get()); + request_interceptors_.push_back(new CefRequestInterceptor()); // Set up interceptors in the reverse order. @@ -256,7 +262,12 @@ net::URLRequestContext* CefURLRequestContextGetterImpl::GetURLRequestContext() { storage_->set_job_factory(top_job_factory.release()); #if defined(USE_NSS) - net::SetURLRequestContextForNSSHttpIO(url_request_context_.get()); + // Only do this for the first (global) request context. + static bool request_context_for_nss_set = false; + if (!request_context_for_nss_set) { + net::SetURLRequestContextForNSSHttpIO(url_request_context_.get()); + request_context_for_nss_set = true; + } #endif } @@ -347,6 +358,16 @@ void CefURLRequestContextGetterImpl::SetCookieSupportedSchemes( delete [] arr; } +void CefURLRequestContextGetterImpl::AddHandler( + CefRefPtr handler) { + if (!CEF_CURRENTLY_ON_IOT()) { + CEF_POST_TASK(CEF_IOT, + base::Bind(&CefURLRequestContextGetterImpl::AddHandler, this, handler)); + return; + } + handler_list_.push_back(handler); +} + void CefURLRequestContextGetterImpl::CreateProxyConfigService() { if (proxy_config_service_.get()) return; diff --git a/libcef/browser/url_request_context_getter_impl.h b/libcef/browser/url_request_context_getter_impl.h index 23c3933a3..3c1466130 100644 --- a/libcef/browser/url_request_context_getter_impl.h +++ b/libcef/browser/url_request_context_getter_impl.h @@ -9,8 +9,10 @@ #include #include +#include "include/internal/cef_types_wrappers.h" #include "libcef/browser/url_request_context_getter.h" #include "libcef/browser/url_request_context_impl.h" +#include "libcef/browser/url_request_manager.h" #include "base/compiler_specific.h" #include "base/files/file_path.h" @@ -32,16 +34,18 @@ class URLRequestJobFactoryImpl; class URLSecurityManager; } -// Global URLRequestContextGetter implementation. Life span is primarily -// controlled by CefResourceContext and CefBrowserMainParts. Created on the UI -// thread but accessed and destroyed on the IO thread. See browser_context.h -// for an object relationship diagram. +// Isolated URLRequestContextGetter implementation. Life span is primarily +// controlled by CefResourceContext and (for the global context) +// CefBrowserMainParts. Created on the UI thread but accessed and destroyed on +// the IO thread. See browser_context.h for an object relationship diagram. class CefURLRequestContextGetterImpl : public CefURLRequestContextGetter { public: CefURLRequestContextGetterImpl( + const CefRequestContextSettings& settings, base::MessageLoop* io_loop, base::MessageLoop* file_loop, content::ProtocolHandlerMap* protocol_handlers, + scoped_ptr proxy_config_service, content::URLRequestInterceptorScopedVector request_interceptors); ~CefURLRequestContextGetterImpl() override; @@ -53,32 +57,40 @@ class CefURLRequestContextGetterImpl : public CefURLRequestContextGetter { // CefURLRequestContextGetter implementation. net::HostResolver* GetHostResolver() const override; - net::URLRequestJobFactoryImpl* job_factory_impl() const { - return job_factory_impl_; - } - void SetCookieStoragePath(const base::FilePath& path, bool persist_session_cookies); void SetCookieSupportedSchemes(const std::vector& schemes); + // Keep a reference to all handlers sharing this context so that they'll be + // kept alive until the context is destroyed. + void AddHandler(CefRefPtr handler); + + CefURLRequestManager* request_manager() const { + return url_request_manager_.get(); + } + private: void CreateProxyConfigService(); + const CefRequestContextSettings settings_; + base::MessageLoop* io_loop_; base::MessageLoop* file_loop_; scoped_ptr proxy_config_service_; scoped_ptr storage_; scoped_ptr url_request_context_; + scoped_ptr url_request_manager_; scoped_ptr url_security_manager_; scoped_ptr ftp_transaction_factory_; content::ProtocolHandlerMap protocol_handlers_; content::URLRequestInterceptorScopedVector request_interceptors_; - net::URLRequestJobFactoryImpl* job_factory_impl_; base::FilePath cookie_store_path_; std::vector cookie_supported_schemes_; + std::vector > handler_list_; + DISALLOW_COPY_AND_ASSIGN(CefURLRequestContextGetterImpl); }; diff --git a/libcef/browser/url_request_context_getter_proxy.cc b/libcef/browser/url_request_context_getter_proxy.cc index ffa01b9ac..64c33d737 100644 --- a/libcef/browser/url_request_context_getter_proxy.cc +++ b/libcef/browser/url_request_context_getter_proxy.cc @@ -12,7 +12,8 @@ CefURLRequestContextGetterProxy::CefURLRequestContextGetterProxy( scoped_refptr parent) : handler_(handler), parent_(parent) { - DCHECK(parent); + DCHECK(handler_.get()); + DCHECK(parent_.get()); } CefURLRequestContextGetterProxy::~CefURLRequestContextGetterProxy() { diff --git a/libcef/browser/url_request_context_getter_proxy.h b/libcef/browser/url_request_context_getter_proxy.h index 882e62a4e..ba0647a45 100644 --- a/libcef/browser/url_request_context_getter_proxy.h +++ b/libcef/browser/url_request_context_getter_proxy.h @@ -15,8 +15,9 @@ class CefURLRequestContextProxy; // URLRequestContextGetter implementation for a particular CefRequestContext. -// Life span is primarily controlled by CefResourceContext. Only accessed on the -// IO thread. See browser_context.h for an object relationship diagram. +// Life span is primarily controlled by CefResourceContext. Created on the UI +// thread but accessed and destroyed on the IO thread. See browser_context.h for +// an object relationship diagram. class CefURLRequestContextGetterProxy : public CefURLRequestContextGetter { public: CefURLRequestContextGetterProxy( diff --git a/libcef/browser/url_request_context_impl.h b/libcef/browser/url_request_context_impl.h index c38046d80..dd9096c17 100644 --- a/libcef/browser/url_request_context_impl.h +++ b/libcef/browser/url_request_context_impl.h @@ -8,7 +8,7 @@ #include "libcef/browser/url_request_context.h" -// Global URLRequestContext implementation. Life span is controlled by +// Isolated URLRequestContext implementation. Life span is controlled by // CefURLRequestContextGetterImpl. Only accessed on the IO thread. See // browser_context.h for an object relationship diagram. class CefURLRequestContextImpl : public CefURLRequestContext { diff --git a/libcef/browser/url_request_context_proxy.cc b/libcef/browser/url_request_context_proxy.cc index de17634ef..f050a17f6 100644 --- a/libcef/browser/url_request_context_proxy.cc +++ b/libcef/browser/url_request_context_proxy.cc @@ -12,6 +12,8 @@ CefURLRequestContextProxy::CefURLRequestContextProxy( CefURLRequestContextImpl* parent, CefRefPtr handler) { CEF_REQUIRE_IOT(); + DCHECK(parent); + DCHECK(handler.get()); // Cookie store that proxies to the browser implementation. cookie_store_proxy_ = new CefCookieStoreProxy(parent, handler); diff --git a/libcef/browser/url_request_manager.cc b/libcef/browser/url_request_manager.cc new file mode 100644 index 000000000..f0ce7e621 --- /dev/null +++ b/libcef/browser/url_request_manager.cc @@ -0,0 +1,282 @@ +// Copyright (c) 2015 The Chromium Embedded Framework Authors. +// Portions copyright (c) 2006-2009 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "libcef/browser/url_request_manager.h" + +#include "include/cef_browser.h" +#include "include/cef_scheme.h" +#include "libcef/browser/browser_context.h" +#include "libcef/browser/browser_host_impl.h" +#include "libcef/browser/resource_request_job.h" +#include "libcef/browser/scheme_handler.h" +#include "libcef/browser/thread_util.h" +#include "libcef/common/request_impl.h" +#include "libcef/common/scheme_registration.h" + +#include "base/logging.h" +#include "base/strings/string_util.h" +#include "net/url_request/url_request.h" +#include "net/url_request/url_request_context.h" +#include "net/url_request/url_request_filter.h" +#include "net/url_request/url_request_http_job.h" +#include "net/url_request/url_request_job.h" +#include "net/url_request/url_request_job_factory_impl.h" +#include "url/third_party/mozilla/url_parse.h" +#include "url/url_util.h" + +using net::URLRequestStatus; + +namespace { + +bool IsStandardScheme(const std::string& scheme) { + url::Component scheme_comp(0, scheme.length()); + return url::IsStandard(scheme.c_str(), scheme_comp); +} + +// Copied from net/url_request/url_request_job_manager.cc. +struct SchemeToFactory { + const char* scheme; + net::URLRequest::ProtocolFactory* factory; +}; +static const SchemeToFactory kBuiltinFactories[] = { + { "http", net::URLRequestHttpJob::Factory }, + { "https", net::URLRequestHttpJob::Factory }, +}; + +bool IsBuiltinScheme(const std::string& scheme) { + for (size_t i = 0; i < arraysize(kBuiltinFactories); ++i) + if (LowerCaseEqualsASCII(scheme, kBuiltinFactories[i].scheme)) + return true; + return false; +} + +net::URLRequestJob* GetBuiltinSchemeRequestJob( + net::URLRequest* request, + net::NetworkDelegate* network_delegate, + const std::string& scheme) { + // See if the request should be handled by a built-in protocol factory. + for (size_t i = 0; i < arraysize(kBuiltinFactories); ++i) { + if (scheme == kBuiltinFactories[i].scheme) { + net::URLRequestJob* job = + (kBuiltinFactories[i].factory)(request, network_delegate, scheme); + DCHECK(job); // The built-in factories are not expected to fail! + return job; + } + } + + return NULL; +} + +std::string ToLower(const std::string& str) { + std::string str_lower = str; + std::transform(str_lower.begin(), str_lower.end(), str_lower.begin(), + towlower); + return str; +} + +} // namespace + +// Class used for creating URLRequestJob instances. The lifespan of this object +// is managed by URLRequestJobFactory. +class CefProtocolHandler : public net::URLRequestJobFactory::ProtocolHandler { + public: + CefProtocolHandler(CefURLRequestManager* request_manager, + const std::string& scheme) + : request_manager_(request_manager), + scheme_(scheme) {} + + // From net::URLRequestJobFactory::ProtocolHandler + net::URLRequestJob* MaybeCreateJob( + net::URLRequest* request, + net::NetworkDelegate* network_delegate) const override { + CEF_REQUIRE_IOT(); + return request_manager_->GetRequestJob(request, network_delegate, scheme_); + } + + private: + CefURLRequestManager* request_manager_; + std::string scheme_; +}; + + +CefURLRequestManager::CefURLRequestManager( + net::URLRequestJobFactoryImpl* job_factory) + : job_factory_(job_factory) { + CEF_REQUIRE_IOT(); + DCHECK(job_factory_); +} + +CefURLRequestManager::~CefURLRequestManager() { + CEF_REQUIRE_IOT(); +} + +bool CefURLRequestManager::AddFactory( + const std::string& scheme, + const std::string& domain, + CefRefPtr factory) { + if (!factory.get()) { + RemoveFactory(scheme, domain); + return true; + } + + CEF_REQUIRE_IOT(); + + std::string scheme_lower = ToLower(scheme); + std::string domain_lower = ToLower(domain); + + // Hostname is only supported for standard schemes. + if (!IsStandardScheme(scheme_lower)) + domain_lower.clear(); + + SetProtocolHandlerIfNecessary(scheme_lower, true); + + handler_map_[make_pair(scheme_lower, domain_lower)] = factory; + + return true; +} + +void CefURLRequestManager::RemoveFactory(const std::string& scheme, + const std::string& domain) { + CEF_REQUIRE_IOT(); + + std::string scheme_lower = ToLower(scheme); + std::string domain_lower = ToLower(domain); + + // Hostname is only supported for standard schemes. + if (!IsStandardScheme(scheme_lower)) + domain_lower.clear(); + + HandlerMap::iterator iter = + handler_map_.find(make_pair(scheme_lower, domain_lower)); + if (iter != handler_map_.end()) { + handler_map_.erase(iter); + + SetProtocolHandlerIfNecessary(scheme_lower, false); + } +} + +// Clear all the existing URL handlers and unregister the ProtocolFactory. +void CefURLRequestManager::ClearFactories() { + CEF_REQUIRE_IOT(); + + // Create a unique set of scheme names. + std::set schemes; + for (HandlerMap::const_iterator i = handler_map_.begin(); + i != handler_map_.end(); ++i) { + schemes.insert(i->first.first); + } + + for (std::set::const_iterator scheme = schemes.begin(); + scheme != schemes.end(); ++scheme) { + const std::string& scheme_name = *scheme; + if (!scheme::IsInternalProtectedScheme(scheme_name)) { + bool set_protocol = job_factory_->SetProtocolHandler(scheme_name, NULL); + DCHECK(set_protocol); + } + } + + handler_map_.clear(); + + // Re-register internal scheme handlers that can be overridden. + scheme::RegisterInternalHandlers(this); +} + +// Helper for chaining ProtocolHandler implementations. +net::URLRequestJob* CefURLRequestManager::GetRequestJob( + net::URLRequest* request, + net::NetworkDelegate* network_delegate) { + CEF_REQUIRE_IOT(); + return GetRequestJob(request, network_delegate, request->url().scheme()); +} + +void CefURLRequestManager::SetProtocolHandlerIfNecessary( + const std::string& scheme, + bool add) { + // Don't modify a protocol handler for internal protected schemes or if the + // protocol handler is still needed by other registered factories. + if (scheme::IsInternalProtectedScheme(scheme) || HasFactory(scheme)) + return; + + bool set_protocol = job_factory_->SetProtocolHandler( + scheme, + (add ? new CefProtocolHandler(this, scheme) : NULL)); + DCHECK(set_protocol); +} + +bool CefURLRequestManager::HasFactory(const std::string& scheme) { + if (handler_map_.empty()) + return false; + + for (HandlerMap::const_iterator i = handler_map_.begin(); + i != handler_map_.end(); ++i) { + if (scheme == i->first.first) + return true; + } + + return false; +} + +CefRefPtr CefURLRequestManager::GetHandlerFactory( + net::URLRequest* request, + const std::string& scheme) { + CefRefPtr factory; + + if (request->url().is_valid() && IsStandardScheme(scheme)) { + // Check for a match with a domain first. + const std::string& domain = request->url().host(); + + HandlerMap::iterator i = handler_map_.find(make_pair(scheme, domain)); + if (i != handler_map_.end()) + factory = i->second; + } + + if (!factory.get()) { + // Check for a match with no specified domain. + HandlerMap::iterator i = + handler_map_.find(make_pair(scheme, std::string())); + if (i != handler_map_.end()) + factory = i->second; + } + + return factory; +} + +net::URLRequestJob* CefURLRequestManager::GetRequestJob( + net::URLRequest* request, + net::NetworkDelegate* network_delegate, + const std::string& scheme) { + net::URLRequestJob* job = NULL; + CefRefPtr factory = + GetHandlerFactory(request, scheme); + if (factory.get()) { + CefRefPtr browser = + CefBrowserHostImpl::GetBrowserForRequest(request); + CefRefPtr frame; + if (browser.get()) + frame = browser->GetFrameForRequest(request); + + // Populate the request data. + CefRefPtr requestPtr(new CefRequestImpl()); + requestPtr->Set(request); + + // Call the handler factory to create the handler for the request. + CefRefPtr handler = + factory->Create(browser.get(), frame, scheme, requestPtr.get()); + if (handler.get()) + job = new CefResourceRequestJob(request, network_delegate, handler); + } + + if (!job && IsBuiltinScheme(scheme)) { + // Give the built-in scheme handler a chance to handle the request. + job = GetBuiltinSchemeRequestJob(request, network_delegate, scheme); + } + +#ifndef NDEBUG + if (job) + DLOG(INFO) << "CefURLRequestManager hit for " << request->url().spec(); +#endif + + return job; +} diff --git a/libcef/browser/url_request_manager.h b/libcef/browser/url_request_manager.h new file mode 100644 index 000000000..61166ba5d --- /dev/null +++ b/libcef/browser/url_request_manager.h @@ -0,0 +1,80 @@ +// Copyright (c) 2015 The Chromium Embedded Framework Authors. All rights +// reserved. Use of this source code is governed by a BSD-style license that can +// be found in the LICENSE file. + +#ifndef CEF_LIBCEF_BROWSER_URL_REQUEST_MANAGER_H_ +#define CEF_LIBCEF_BROWSER_URL_REQUEST_MANAGER_H_ +#pragma once + +#include + +#include "include/cef_scheme.h" + +namespace net { +class NetworkDelegate; +class URLRequest; +class URLRequestJob; +class URLRequestJobFactoryImpl; +} + +class CefProtocolHandler; + +// Class that manages CefSchemeHandlerFactory instances. Only accessed on the IO +// thread. +class CefURLRequestManager { + public: + explicit CefURLRequestManager(net::URLRequestJobFactoryImpl* job_factory); + ~CefURLRequestManager(); + + // Add |factory| for the specified |scheme| and |domain|. See documentation on + // CefRequestContext::RegisterSchemeHandlerFactory() for usage. + bool AddFactory(const std::string& scheme, + const std::string& domain, + CefRefPtr factory); + + // Remove all factories associated with the specified |scheme| and |domain|. + void RemoveFactory(const std::string& scheme, + const std::string& domain); + + // Clear all the existing URL handlers and unregister the ProtocolFactory. + void ClearFactories(); + + // Helper for chaining ProtocolHandler implementations. + net::URLRequestJob* GetRequestJob(net::URLRequest* request, + net::NetworkDelegate* network_delegate); + + private: + friend class CefProtocolHandler; + + // Add or remove the protocol handler if necessary. |scheme| will already be + // in lower case. + void SetProtocolHandlerIfNecessary(const std::string& scheme, bool add); + + // Returns true if any factory currently exists for |scheme|. |scheme| will + // already be in lower case. + bool HasFactory(const std::string& scheme); + + // Retrieve the matching handler factory, if any. |scheme| will already be in + // lower case. + CefRefPtr GetHandlerFactory( + net::URLRequest* request, const std::string& scheme); + + // Create the job that will handle the request. |scheme| will already be in + // lower case. + net::URLRequestJob* GetRequestJob(net::URLRequest* request, + net::NetworkDelegate* network_delegate, + const std::string& scheme); + + // Life span of |job_factory_| is guaranteed by + // CefURLRequestContextGetterImpl which also owns this object. + net::URLRequestJobFactoryImpl* job_factory_; + + // Map (scheme, domain) to factories. + typedef std::map, + CefRefPtr > HandlerMap; + HandlerMap handler_map_; + + DISALLOW_COPY_AND_ASSIGN(CefURLRequestManager); +}; + +#endif // CEF_LIBCEF_BROWSER_URL_REQUEST_MANAGER_H_ diff --git a/libcef/common/main_delegate.cc b/libcef/common/main_delegate.cc index dcc651659..8ee8c41c9 100644 --- a/libcef/common/main_delegate.cc +++ b/libcef/common/main_delegate.cc @@ -49,6 +49,11 @@ #include "components/crash/app/breakpad_linux.h" #endif +#if defined(OS_LINUX) +#include "base/environment.h" +#include "base/nix/xdg_util.h" +#endif + namespace { base::LazyInstance::Leaky g_crash_reporter_client = @@ -117,6 +122,64 @@ base::FilePath GetLibrariesFilePath() { #endif // !defined(OS_MACOSX) +#if defined(OS_LINUX) + +// Based on chrome/common/chrome_paths_linux.cc. +// See http://standards.freedesktop.org/basedir-spec/basedir-spec-latest.html +// for a spec on where config files go. The net effect for most +// systems is we use ~/.config/chromium/ for Chromium and +// ~/.config/google-chrome/ for official builds. +// (This also helps us sidestep issues with other apps grabbing ~/.chromium .) +bool GetDefaultUserDataDirectory(base::FilePath* result) { + scoped_ptr env(base::Environment::Create()); + base::FilePath config_dir( + base::nix::GetXDGDirectory(env.get(), + base::nix::kXdgConfigHomeEnvVar, + base::nix::kDotConfigDir)); + *result = config_dir.Append(FILE_PATH_LITERAL("cef_user_data")); + return true; +} + +#elif defined(OS_MACOSX) + +// Based on chrome/common/chrome_paths_mac.mm. +bool GetDefaultUserDataDirectory(base::FilePath* result) { + if (!PathService::Get(base::DIR_APP_DATA, result)) + return false; + *result = result->Append(FILE_PATH_LITERAL("CEF")); + *result = result->Append(FILE_PATH_LITERAL("User Data")); + return true; +} + +#elif defined(OS_WIN) + +// Based on chrome/common/chrome_paths_win.cc. +bool GetDefaultUserDataDirectory(base::FilePath* result) { + if (!PathService::Get(base::DIR_LOCAL_APP_DATA, result)) + return false; + *result = result->Append(FILE_PATH_LITERAL("CEF")); + *result = result->Append(FILE_PATH_LITERAL("User Data")); + return true; +} + +#endif + +base::FilePath GetUserDataPath() { + const CefSettings& settings = CefContext::Get()->settings(); + if (settings.user_data_path.length > 0) + return base::FilePath(CefString(&settings.user_data_path)); + + base::FilePath result; + if (GetDefaultUserDataDirectory(&result)) + return result; + + if (PathService::Get(base::DIR_TEMP, &result)) + return result; + + NOTREACHED(); + return result; +} + // File name of the internal PDF plugin on different platforms. const base::FilePath::CharType kInternalPDFPluginFileName[] = #if defined(OS_WIN) @@ -417,14 +480,11 @@ void CefMainDelegate::PreSandboxStartup() { #endif // Paths used to locate spell checking dictionary files. - // TODO(cef): It may be better to use a persistent location for - // DIR_USER_DATA. See the implementation of GetDefaultUserDataDirectory in - // chrome/common/chrome_paths_*. - const base::FilePath& cache_path = CefContext::Get()->cache_path(); - PathService::Override(chrome::DIR_USER_DATA, cache_path); + const base::FilePath& user_data_path = GetUserDataPath(); + PathService::Override(chrome::DIR_USER_DATA, user_data_path); PathService::OverrideAndCreateIfNeeded( chrome::DIR_APP_DICTIONARIES, - cache_path.AppendASCII("Dictionaries"), + user_data_path.AppendASCII("Dictionaries"), false, // May not be an absolute path. true); // Create if necessary. } diff --git a/libcef/common/urlrequest_impl.cc b/libcef/common/urlrequest_impl.cc index 958722fd4..3fa59cd9c 100644 --- a/libcef/common/urlrequest_impl.cc +++ b/libcef/common/urlrequest_impl.cc @@ -14,7 +14,8 @@ // static CefRefPtr CefURLRequest::Create( CefRefPtr request, - CefRefPtr client) { + CefRefPtr client, + CefRefPtr request_context) { if (!request.get() || !client.get()) { NOTREACHED() << "called with invalid parameters"; return NULL; @@ -28,7 +29,7 @@ CefRefPtr CefURLRequest::Create( if (CefContentClient::Get()->browser()) { // In the browser process. CefRefPtr impl = - new CefBrowserURLRequest(request, client); + new CefBrowserURLRequest(request, client, request_context); if (impl->Start()) return impl.get(); return NULL; diff --git a/libcef_dll/cpptoc/cookie_manager_cpptoc.cc b/libcef_dll/cpptoc/cookie_manager_cpptoc.cc index 38e0be3c4..2575b805a 100644 --- a/libcef_dll/cpptoc/cookie_manager_cpptoc.cc +++ b/libcef_dll/cpptoc/cookie_manager_cpptoc.cc @@ -13,31 +13,39 @@ #include "libcef_dll/cpptoc/cookie_manager_cpptoc.h" #include "libcef_dll/ctocpp/completion_callback_ctocpp.h" #include "libcef_dll/ctocpp/cookie_visitor_ctocpp.h" +#include "libcef_dll/ctocpp/delete_cookies_callback_ctocpp.h" +#include "libcef_dll/ctocpp/set_cookie_callback_ctocpp.h" #include "libcef_dll/transfer_util.h" // GLOBAL FUNCTIONS - Body may be edited by hand. -CEF_EXPORT cef_cookie_manager_t* cef_cookie_manager_get_global_manager() { +CEF_EXPORT cef_cookie_manager_t* cef_cookie_manager_get_global_manager( + cef_completion_callback_t* callback) { // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + // Unverified params: callback + // Execute - CefRefPtr _retval = CefCookieManager::GetGlobalManager(); + CefRefPtr _retval = CefCookieManager::GetGlobalManager( + CefCompletionCallbackCToCpp::Wrap(callback)); // Return type: refptr_same return CefCookieManagerCppToC::Wrap(_retval); } CEF_EXPORT cef_cookie_manager_t* cef_cookie_manager_create_manager( - const cef_string_t* path, int persist_session_cookies) { + const cef_string_t* path, int persist_session_cookies, + cef_completion_callback_t* callback) { // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING - // Unverified params: path + // Unverified params: path, callback // Execute CefRefPtr _retval = CefCookieManager::CreateManager( CefString(path), - persist_session_cookies?true:false); + persist_session_cookies?true:false, + CefCompletionCallbackCToCpp::Wrap(callback)); // Return type: refptr_same return CefCookieManagerCppToC::Wrap(_retval); @@ -47,7 +55,8 @@ CEF_EXPORT cef_cookie_manager_t* cef_cookie_manager_create_manager( // MEMBER FUNCTIONS - Body may be edited by hand. void CEF_CALLBACK cookie_manager_set_supported_schemes( - struct _cef_cookie_manager_t* self, cef_string_list_t schemes) { + struct _cef_cookie_manager_t* self, cef_string_list_t schemes, + cef_completion_callback_t* callback) { // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING DCHECK(self); @@ -57,6 +66,7 @@ void CEF_CALLBACK cookie_manager_set_supported_schemes( DCHECK(schemes); if (!schemes) return; + // Unverified params: callback // Translate param: schemes; type: string_vec_byref_const std::vector schemesList; @@ -64,7 +74,8 @@ void CEF_CALLBACK cookie_manager_set_supported_schemes( // Execute CefCookieManagerCppToC::Get(self)->SetSupportedSchemes( - schemesList); + schemesList, + CefCompletionCallbackCToCpp::Wrap(callback)); } int CEF_CALLBACK cookie_manager_visit_all_cookies( @@ -116,7 +127,8 @@ int CEF_CALLBACK cookie_manager_visit_url_cookies( } int CEF_CALLBACK cookie_manager_set_cookie(struct _cef_cookie_manager_t* self, - const cef_string_t* url, const struct _cef_cookie_t* cookie) { + const cef_string_t* url, const struct _cef_cookie_t* cookie, + struct _cef_set_cookie_callback_t* callback) { // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING DCHECK(self); @@ -130,6 +142,7 @@ int CEF_CALLBACK cookie_manager_set_cookie(struct _cef_cookie_manager_t* self, DCHECK(cookie); if (!cookie) return 0; + // Unverified params: callback // Translate param: cookie; type: struct_byref_const CefCookie cookieObj; @@ -139,7 +152,8 @@ int CEF_CALLBACK cookie_manager_set_cookie(struct _cef_cookie_manager_t* self, // Execute bool _retval = CefCookieManagerCppToC::Get(self)->SetCookie( CefString(url), - cookieObj); + cookieObj, + CefSetCookieCallbackCToCpp::Wrap(callback)); // Return type: bool return _retval; @@ -147,18 +161,20 @@ int CEF_CALLBACK cookie_manager_set_cookie(struct _cef_cookie_manager_t* self, int CEF_CALLBACK cookie_manager_delete_cookies( struct _cef_cookie_manager_t* self, const cef_string_t* url, - const cef_string_t* cookie_name) { + const cef_string_t* cookie_name, + struct _cef_delete_cookies_callback_t* callback) { // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING DCHECK(self); if (!self) return 0; - // Unverified params: url, cookie_name + // Unverified params: url, cookie_name, callback // Execute bool _retval = CefCookieManagerCppToC::Get(self)->DeleteCookies( CefString(url), - CefString(cookie_name)); + CefString(cookie_name), + CefDeleteCookiesCallbackCToCpp::Wrap(callback)); // Return type: bool return _retval; @@ -166,18 +182,19 @@ int CEF_CALLBACK cookie_manager_delete_cookies( int CEF_CALLBACK cookie_manager_set_storage_path( struct _cef_cookie_manager_t* self, const cef_string_t* path, - int persist_session_cookies) { + int persist_session_cookies, cef_completion_callback_t* callback) { // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING DCHECK(self); if (!self) return 0; - // Unverified params: path + // Unverified params: path, callback // Execute bool _retval = CefCookieManagerCppToC::Get(self)->SetStoragePath( CefString(path), - persist_session_cookies?true:false); + persist_session_cookies?true:false, + CefCompletionCallbackCToCpp::Wrap(callback)); // Return type: bool return _retval; @@ -190,10 +207,7 @@ int CEF_CALLBACK cookie_manager_flush_store(struct _cef_cookie_manager_t* self, DCHECK(self); if (!self) return 0; - // Verify param: callback; type: refptr_diff - DCHECK(callback); - if (!callback) - return 0; + // Unverified params: callback // Execute bool _retval = CefCookieManagerCppToC::Get(self)->FlushStore( diff --git a/libcef_dll/cpptoc/delete_cookies_callback_cpptoc.cc b/libcef_dll/cpptoc/delete_cookies_callback_cpptoc.cc new file mode 100644 index 000000000..e3c24a685 --- /dev/null +++ b/libcef_dll/cpptoc/delete_cookies_callback_cpptoc.cc @@ -0,0 +1,45 @@ +// Copyright (c) 2015 The Chromium Embedded Framework Authors. All rights +// reserved. Use of this source code is governed by a BSD-style license that +// can be found in the LICENSE file. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#include "libcef_dll/cpptoc/delete_cookies_callback_cpptoc.h" + + +// MEMBER FUNCTIONS - Body may be edited by hand. + +void CEF_CALLBACK delete_cookies_callback_on_complete( + struct _cef_delete_cookies_callback_t* self, int num_deleted) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return; + + // Execute + CefDeleteCookiesCallbackCppToC::Get(self)->OnComplete( + num_deleted); +} + + +// CONSTRUCTOR - Do not edit by hand. + +CefDeleteCookiesCallbackCppToC::CefDeleteCookiesCallbackCppToC( + CefDeleteCookiesCallback* cls) + : CefCppToC(cls) { + struct_.struct_.on_complete = delete_cookies_callback_on_complete; +} + +#ifndef NDEBUG +template<> base::AtomicRefCount CefCppToC::DebugObjCt = 0; +#endif + diff --git a/libcef_dll/cpptoc/delete_cookies_callback_cpptoc.h b/libcef_dll/cpptoc/delete_cookies_callback_cpptoc.h new file mode 100644 index 000000000..9217083a5 --- /dev/null +++ b/libcef_dll/cpptoc/delete_cookies_callback_cpptoc.h @@ -0,0 +1,36 @@ +// Copyright (c) 2015 The Chromium Embedded Framework Authors. All rights +// reserved. Use of this source code is governed by a BSD-style license that +// can be found in the LICENSE file. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#ifndef CEF_LIBCEF_DLL_CPPTOC_DELETE_COOKIES_CALLBACK_CPPTOC_H_ +#define CEF_LIBCEF_DLL_CPPTOC_DELETE_COOKIES_CALLBACK_CPPTOC_H_ +#pragma once + +#ifndef USING_CEF_SHARED +#pragma message("Warning: "__FILE__" may be accessed wrapper-side only") +#else // USING_CEF_SHARED + +#include "include/cef_cookie.h" +#include "include/capi/cef_cookie_capi.h" +#include "libcef_dll/cpptoc/cpptoc.h" + +// Wrap a C++ class with a C structure. +// This class may be instantiated and accessed wrapper-side only. +class CefDeleteCookiesCallbackCppToC + : public CefCppToC { + public: + explicit CefDeleteCookiesCallbackCppToC(CefDeleteCookiesCallback* cls); +}; + +#endif // USING_CEF_SHARED +#endif // CEF_LIBCEF_DLL_CPPTOC_DELETE_COOKIES_CALLBACK_CPPTOC_H_ + diff --git a/libcef_dll/cpptoc/request_context_cpptoc.cc b/libcef_dll/cpptoc/request_context_cpptoc.cc index 8286666f9..5b5a79601 100644 --- a/libcef_dll/cpptoc/request_context_cpptoc.cc +++ b/libcef_dll/cpptoc/request_context_cpptoc.cc @@ -10,8 +10,11 @@ // for more information. // +#include "libcef_dll/cpptoc/cookie_manager_cpptoc.h" #include "libcef_dll/cpptoc/request_context_cpptoc.h" +#include "libcef_dll/ctocpp/completion_callback_ctocpp.h" #include "libcef_dll/ctocpp/request_context_handler_ctocpp.h" +#include "libcef_dll/ctocpp/scheme_handler_factory_ctocpp.h" // GLOBAL FUNCTIONS - Body may be edited by hand. @@ -27,13 +30,44 @@ CEF_EXPORT cef_request_context_t* cef_request_context_get_global_context() { } CEF_EXPORT cef_request_context_t* cef_request_context_create_context( + const struct _cef_request_context_settings_t* settings, struct _cef_request_context_handler_t* handler) { // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + // Verify param: settings; type: struct_byref_const + DCHECK(settings); + if (!settings) + return NULL; + // Unverified params: handler + + // Translate param: settings; type: struct_byref_const + CefRequestContextSettings settingsObj; + if (settings) + settingsObj.Set(*settings, false); + + // Execute + CefRefPtr _retval = CefRequestContext::CreateContext( + settingsObj, + CefRequestContextHandlerCToCpp::Wrap(handler)); + + // Return type: refptr_same + return CefRequestContextCppToC::Wrap(_retval); +} + +CEF_EXPORT cef_request_context_t* create_context_shared( + cef_request_context_t* other, + struct _cef_request_context_handler_t* handler) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: other; type: refptr_same + DCHECK(other); + if (!other) + return NULL; // Unverified params: handler // Execute CefRefPtr _retval = CefRequestContext::CreateContext( + CefRequestContextCppToC::Unwrap(other), CefRequestContextHandlerCToCpp::Wrap(handler)); // Return type: refptr_same @@ -63,6 +97,27 @@ int CEF_CALLBACK request_context_is_same(struct _cef_request_context_t* self, return _retval; } +int CEF_CALLBACK request_context_is_sharing_with( + struct _cef_request_context_t* self, + struct _cef_request_context_t* other) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + // Verify param: other; type: refptr_same + DCHECK(other); + if (!other) + return 0; + + // Execute + bool _retval = CefRequestContextCppToC::Get(self)->IsSharingWith( + CefRequestContextCppToC::Unwrap(other)); + + // Return type: bool + return _retval; +} + int CEF_CALLBACK request_context_is_global( struct _cef_request_context_t* self) { // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING @@ -94,6 +149,81 @@ struct _cef_request_context_handler_t* CEF_CALLBACK request_context_get_handler( return CefRequestContextHandlerCToCpp::Unwrap(_retval); } +cef_string_userfree_t CEF_CALLBACK request_context_get_cache_path( + struct _cef_request_context_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return NULL; + + // Execute + CefString _retval = CefRequestContextCppToC::Get(self)->GetCachePath(); + + // Return type: string + return _retval.DetachToUserFree(); +} + +cef_cookie_manager_t* CEF_CALLBACK request_context_get_default_cookie_manager( + struct _cef_request_context_t* self, cef_completion_callback_t* callback) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return NULL; + // Unverified params: callback + + // Execute + CefRefPtr _retval = CefRequestContextCppToC::Get( + self)->GetDefaultCookieManager( + CefCompletionCallbackCToCpp::Wrap(callback)); + + // Return type: refptr_same + return CefCookieManagerCppToC::Wrap(_retval); +} + +int CEF_CALLBACK request_context_register_scheme_handler_factory( + struct _cef_request_context_t* self, const cef_string_t* scheme_name, + const cef_string_t* domain_name, + struct _cef_scheme_handler_factory_t* factory) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + // Verify param: scheme_name; type: string_byref_const + DCHECK(scheme_name); + if (!scheme_name) + return 0; + // Unverified params: domain_name, factory + + // Execute + bool _retval = CefRequestContextCppToC::Get( + self)->RegisterSchemeHandlerFactory( + CefString(scheme_name), + CefString(domain_name), + CefSchemeHandlerFactoryCToCpp::Wrap(factory)); + + // Return type: bool + return _retval; +} + +int CEF_CALLBACK request_context_clear_scheme_handler_factories( + struct _cef_request_context_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + + // Execute + bool _retval = CefRequestContextCppToC::Get( + self)->ClearSchemeHandlerFactories(); + + // Return type: bool + return _retval; +} + // CONSTRUCTOR - Do not edit by hand. @@ -101,8 +231,16 @@ CefRequestContextCppToC::CefRequestContextCppToC(CefRequestContext* cls) : CefCppToC(cls) { struct_.struct_.is_same = request_context_is_same; + struct_.struct_.is_sharing_with = request_context_is_sharing_with; struct_.struct_.is_global = request_context_is_global; struct_.struct_.get_handler = request_context_get_handler; + struct_.struct_.get_cache_path = request_context_get_cache_path; + struct_.struct_.get_default_cookie_manager = + request_context_get_default_cookie_manager; + struct_.struct_.register_scheme_handler_factory = + request_context_register_scheme_handler_factory; + struct_.struct_.clear_scheme_handler_factories = + request_context_clear_scheme_handler_factories; } #ifndef NDEBUG diff --git a/libcef_dll/cpptoc/request_context_cpptoc.h b/libcef_dll/cpptoc/request_context_cpptoc.h index 4dcc12251..fb610a028 100644 --- a/libcef_dll/cpptoc/request_context_cpptoc.h +++ b/libcef_dll/cpptoc/request_context_cpptoc.h @@ -20,6 +20,8 @@ #include "include/cef_request_context.h" #include "include/capi/cef_request_context_capi.h" +#include "include/cef_scheme.h" +#include "include/capi/cef_scheme_capi.h" #include "libcef_dll/cpptoc/cpptoc.h" // Wrap a C++ class with a C structure. diff --git a/libcef_dll/cpptoc/set_cookie_callback_cpptoc.cc b/libcef_dll/cpptoc/set_cookie_callback_cpptoc.cc new file mode 100644 index 000000000..13ce1f554 --- /dev/null +++ b/libcef_dll/cpptoc/set_cookie_callback_cpptoc.cc @@ -0,0 +1,45 @@ +// Copyright (c) 2015 The Chromium Embedded Framework Authors. All rights +// reserved. Use of this source code is governed by a BSD-style license that +// can be found in the LICENSE file. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#include "libcef_dll/cpptoc/set_cookie_callback_cpptoc.h" + + +// MEMBER FUNCTIONS - Body may be edited by hand. + +void CEF_CALLBACK set_cookie_callback_on_complete( + struct _cef_set_cookie_callback_t* self, int success) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return; + + // Execute + CefSetCookieCallbackCppToC::Get(self)->OnComplete( + success?true:false); +} + + +// CONSTRUCTOR - Do not edit by hand. + +CefSetCookieCallbackCppToC::CefSetCookieCallbackCppToC( + CefSetCookieCallback* cls) + : CefCppToC(cls) { + struct_.struct_.on_complete = set_cookie_callback_on_complete; +} + +#ifndef NDEBUG +template<> base::AtomicRefCount CefCppToC::DebugObjCt = 0; +#endif + diff --git a/libcef_dll/cpptoc/set_cookie_callback_cpptoc.h b/libcef_dll/cpptoc/set_cookie_callback_cpptoc.h new file mode 100644 index 000000000..e5613b456 --- /dev/null +++ b/libcef_dll/cpptoc/set_cookie_callback_cpptoc.h @@ -0,0 +1,36 @@ +// Copyright (c) 2015 The Chromium Embedded Framework Authors. All rights +// reserved. Use of this source code is governed by a BSD-style license that +// can be found in the LICENSE file. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#ifndef CEF_LIBCEF_DLL_CPPTOC_SET_COOKIE_CALLBACK_CPPTOC_H_ +#define CEF_LIBCEF_DLL_CPPTOC_SET_COOKIE_CALLBACK_CPPTOC_H_ +#pragma once + +#ifndef USING_CEF_SHARED +#pragma message("Warning: "__FILE__" may be accessed wrapper-side only") +#else // USING_CEF_SHARED + +#include "include/cef_cookie.h" +#include "include/capi/cef_cookie_capi.h" +#include "libcef_dll/cpptoc/cpptoc.h" + +// Wrap a C++ class with a C structure. +// This class may be instantiated and accessed wrapper-side only. +class CefSetCookieCallbackCppToC + : public CefCppToC { + public: + explicit CefSetCookieCallbackCppToC(CefSetCookieCallback* cls); +}; + +#endif // USING_CEF_SHARED +#endif // CEF_LIBCEF_DLL_CPPTOC_SET_COOKIE_CALLBACK_CPPTOC_H_ + diff --git a/libcef_dll/cpptoc/urlrequest_cpptoc.cc b/libcef_dll/cpptoc/urlrequest_cpptoc.cc index 9f301ea87..a0736aa84 100644 --- a/libcef_dll/cpptoc/urlrequest_cpptoc.cc +++ b/libcef_dll/cpptoc/urlrequest_cpptoc.cc @@ -11,6 +11,7 @@ // #include "libcef_dll/cpptoc/request_cpptoc.h" +#include "libcef_dll/cpptoc/request_context_cpptoc.h" #include "libcef_dll/cpptoc/response_cpptoc.h" #include "libcef_dll/cpptoc/urlrequest_cpptoc.h" #include "libcef_dll/ctocpp/urlrequest_client_ctocpp.h" @@ -19,7 +20,8 @@ // GLOBAL FUNCTIONS - Body may be edited by hand. CEF_EXPORT cef_urlrequest_t* cef_urlrequest_create(cef_request_t* request, - struct _cef_urlrequest_client_t* client) { + struct _cef_urlrequest_client_t* client, + cef_request_context_t* request_context) { // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING // Verify param: request; type: refptr_same @@ -30,11 +32,13 @@ CEF_EXPORT cef_urlrequest_t* cef_urlrequest_create(cef_request_t* request, DCHECK(client); if (!client) return NULL; + // Unverified params: request_context // Execute CefRefPtr _retval = CefURLRequest::Create( CefRequestCppToC::Unwrap(request), - CefURLRequestClientCToCpp::Wrap(client)); + CefURLRequestClientCToCpp::Wrap(client), + CefRequestContextCppToC::Unwrap(request_context)); // Return type: refptr_same return CefURLRequestCppToC::Wrap(_retval); diff --git a/libcef_dll/ctocpp/cookie_manager_ctocpp.cc b/libcef_dll/ctocpp/cookie_manager_ctocpp.cc index 8953bf79c..b6be7f5b1 100644 --- a/libcef_dll/ctocpp/cookie_manager_ctocpp.cc +++ b/libcef_dll/ctocpp/cookie_manager_ctocpp.cc @@ -12,32 +12,40 @@ #include "libcef_dll/cpptoc/completion_callback_cpptoc.h" #include "libcef_dll/cpptoc/cookie_visitor_cpptoc.h" +#include "libcef_dll/cpptoc/delete_cookies_callback_cpptoc.h" +#include "libcef_dll/cpptoc/set_cookie_callback_cpptoc.h" #include "libcef_dll/ctocpp/cookie_manager_ctocpp.h" #include "libcef_dll/transfer_util.h" // STATIC METHODS - Body may be edited by hand. -CefRefPtr CefCookieManager::GetGlobalManager() { +CefRefPtr CefCookieManager::GetGlobalManager( + CefRefPtr callback) { // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + // Unverified params: callback + // Execute - cef_cookie_manager_t* _retval = cef_cookie_manager_get_global_manager(); + cef_cookie_manager_t* _retval = cef_cookie_manager_get_global_manager( + CefCompletionCallbackCppToC::Wrap(callback)); // Return type: refptr_same return CefCookieManagerCToCpp::Wrap(_retval); } CefRefPtr CefCookieManager::CreateManager( - const CefString& path, bool persist_session_cookies) { + const CefString& path, bool persist_session_cookies, + CefRefPtr callback) { // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING - // Unverified params: path + // Unverified params: path, callback // Execute cef_cookie_manager_t* _retval = cef_cookie_manager_create_manager( path.GetStruct(), - persist_session_cookies); + persist_session_cookies, + CefCompletionCallbackCppToC::Wrap(callback)); // Return type: refptr_same return CefCookieManagerCToCpp::Wrap(_retval); @@ -47,12 +55,15 @@ CefRefPtr CefCookieManager::CreateManager( // VIRTUAL METHODS - Body may be edited by hand. void CefCookieManagerCToCpp::SetSupportedSchemes( - const std::vector& schemes) { + const std::vector& schemes, + CefRefPtr callback) { if (CEF_MEMBER_MISSING(struct_, set_supported_schemes)) return; // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + // Unverified params: callback + // Translate param: schemes; type: string_vec_byref_const cef_string_list_t schemesList = cef_string_list_alloc(); DCHECK(schemesList); @@ -61,7 +72,8 @@ void CefCookieManagerCToCpp::SetSupportedSchemes( // Execute struct_->set_supported_schemes(struct_, - schemesList); + schemesList, + CefCompletionCallbackCppToC::Wrap(callback)); // Restore param:schemes; type: string_vec_byref_const if (schemesList) @@ -115,7 +127,7 @@ bool CefCookieManagerCToCpp::VisitUrlCookies(const CefString& url, } bool CefCookieManagerCToCpp::SetCookie(const CefString& url, - const CefCookie& cookie) { + const CefCookie& cookie, CefRefPtr callback) { if (CEF_MEMBER_MISSING(struct_, set_cookie)) return false; @@ -125,47 +137,52 @@ bool CefCookieManagerCToCpp::SetCookie(const CefString& url, DCHECK(!url.empty()); if (url.empty()) return false; + // Unverified params: callback // Execute int _retval = struct_->set_cookie(struct_, url.GetStruct(), - &cookie); + &cookie, + CefSetCookieCallbackCppToC::Wrap(callback)); // Return type: bool return _retval?true:false; } bool CefCookieManagerCToCpp::DeleteCookies(const CefString& url, - const CefString& cookie_name) { + const CefString& cookie_name, + CefRefPtr callback) { if (CEF_MEMBER_MISSING(struct_, delete_cookies)) return false; // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING - // Unverified params: url, cookie_name + // Unverified params: url, cookie_name, callback // Execute int _retval = struct_->delete_cookies(struct_, url.GetStruct(), - cookie_name.GetStruct()); + cookie_name.GetStruct(), + CefDeleteCookiesCallbackCppToC::Wrap(callback)); // Return type: bool return _retval?true:false; } bool CefCookieManagerCToCpp::SetStoragePath(const CefString& path, - bool persist_session_cookies) { + bool persist_session_cookies, CefRefPtr callback) { if (CEF_MEMBER_MISSING(struct_, set_storage_path)) return false; // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING - // Unverified params: path + // Unverified params: path, callback // Execute int _retval = struct_->set_storage_path(struct_, path.GetStruct(), - persist_session_cookies); + persist_session_cookies, + CefCompletionCallbackCppToC::Wrap(callback)); // Return type: bool return _retval?true:false; @@ -178,10 +195,7 @@ bool CefCookieManagerCToCpp::FlushStore( // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING - // Verify param: callback; type: refptr_diff - DCHECK(callback.get()); - if (!callback.get()) - return false; + // Unverified params: callback // Execute int _retval = struct_->flush_store(struct_, diff --git a/libcef_dll/ctocpp/cookie_manager_ctocpp.h b/libcef_dll/ctocpp/cookie_manager_ctocpp.h index c96025a28..b7f9f5e53 100644 --- a/libcef_dll/ctocpp/cookie_manager_ctocpp.h +++ b/libcef_dll/ctocpp/cookie_manager_ctocpp.h @@ -34,17 +34,18 @@ class CefCookieManagerCToCpp cef_cookie_manager_t>(str) {} // CefCookieManager methods - virtual void SetSupportedSchemes( - const std::vector& schemes) OVERRIDE; + virtual void SetSupportedSchemes(const std::vector& schemes, + CefRefPtr callback) OVERRIDE; virtual bool VisitAllCookies(CefRefPtr visitor) OVERRIDE; virtual bool VisitUrlCookies(const CefString& url, bool includeHttpOnly, CefRefPtr visitor) OVERRIDE; - virtual bool SetCookie(const CefString& url, - const CefCookie& cookie) OVERRIDE; - virtual bool DeleteCookies(const CefString& url, - const CefString& cookie_name) OVERRIDE; + virtual bool SetCookie(const CefString& url, const CefCookie& cookie, + CefRefPtr callback) OVERRIDE; + virtual bool DeleteCookies(const CefString& url, const CefString& cookie_name, + CefRefPtr callback) OVERRIDE; virtual bool SetStoragePath(const CefString& path, - bool persist_session_cookies) OVERRIDE; + bool persist_session_cookies, + CefRefPtr callback) OVERRIDE; virtual bool FlushStore(CefRefPtr callback) OVERRIDE; }; diff --git a/libcef_dll/ctocpp/delete_cookies_callback_ctocpp.cc b/libcef_dll/ctocpp/delete_cookies_callback_ctocpp.cc new file mode 100644 index 000000000..fd56dcd6a --- /dev/null +++ b/libcef_dll/ctocpp/delete_cookies_callback_ctocpp.cc @@ -0,0 +1,34 @@ +// Copyright (c) 2015 The Chromium Embedded Framework Authors. All rights +// reserved. Use of this source code is governed by a BSD-style license that +// can be found in the LICENSE file. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#include "libcef_dll/ctocpp/delete_cookies_callback_ctocpp.h" + + +// VIRTUAL METHODS - Body may be edited by hand. + +void CefDeleteCookiesCallbackCToCpp::OnComplete(int num_deleted) { + if (CEF_MEMBER_MISSING(struct_, on_complete)) + return; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + struct_->on_complete(struct_, + num_deleted); +} + + +#ifndef NDEBUG +template<> base::AtomicRefCount CefCToCpp::DebugObjCt = 0; +#endif + diff --git a/libcef_dll/ctocpp/delete_cookies_callback_ctocpp.h b/libcef_dll/ctocpp/delete_cookies_callback_ctocpp.h new file mode 100644 index 000000000..a83b7d617 --- /dev/null +++ b/libcef_dll/ctocpp/delete_cookies_callback_ctocpp.h @@ -0,0 +1,41 @@ +// Copyright (c) 2015 The Chromium Embedded Framework Authors. All rights +// reserved. Use of this source code is governed by a BSD-style license that +// can be found in the LICENSE file. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#ifndef CEF_LIBCEF_DLL_CTOCPP_DELETE_COOKIES_CALLBACK_CTOCPP_H_ +#define CEF_LIBCEF_DLL_CTOCPP_DELETE_COOKIES_CALLBACK_CTOCPP_H_ +#pragma once + +#ifndef BUILDING_CEF_SHARED +#pragma message("Warning: "__FILE__" may be accessed DLL-side only") +#else // BUILDING_CEF_SHARED + +#include "include/cef_cookie.h" +#include "include/capi/cef_cookie_capi.h" +#include "libcef_dll/ctocpp/ctocpp.h" + +// Wrap a C structure with a C++ class. +// This class may be instantiated and accessed DLL-side only. +class CefDeleteCookiesCallbackCToCpp + : public CefCToCpp { + public: + explicit CefDeleteCookiesCallbackCToCpp(cef_delete_cookies_callback_t* str) + : CefCToCpp(str) {} + + // CefDeleteCookiesCallback methods + void OnComplete(int num_deleted) override; +}; + +#endif // BUILDING_CEF_SHARED +#endif // CEF_LIBCEF_DLL_CTOCPP_DELETE_COOKIES_CALLBACK_CTOCPP_H_ + diff --git a/libcef_dll/ctocpp/request_context_ctocpp.cc b/libcef_dll/ctocpp/request_context_ctocpp.cc index 9ca570821..c2801388a 100644 --- a/libcef_dll/ctocpp/request_context_ctocpp.cc +++ b/libcef_dll/ctocpp/request_context_ctocpp.cc @@ -10,7 +10,10 @@ // for more information. // +#include "libcef_dll/cpptoc/completion_callback_cpptoc.h" #include "libcef_dll/cpptoc/request_context_handler_cpptoc.h" +#include "libcef_dll/cpptoc/scheme_handler_factory_cpptoc.h" +#include "libcef_dll/ctocpp/cookie_manager_ctocpp.h" #include "libcef_dll/ctocpp/request_context_ctocpp.h" @@ -27,6 +30,7 @@ CefRefPtr CefRequestContext::GetGlobalContext() { } CefRefPtr CefRequestContext::CreateContext( + const CefRequestContextSettings& settings, CefRefPtr handler) { // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING @@ -34,6 +38,27 @@ CefRefPtr CefRequestContext::CreateContext( // Execute cef_request_context_t* _retval = cef_request_context_create_context( + &settings, + CefRequestContextHandlerCppToC::Wrap(handler)); + + // Return type: refptr_same + return CefRequestContextCToCpp::Wrap(_retval); +} + +CefRefPtr CefRequestContext::CreateContext( + CefRefPtr other, + CefRefPtr handler) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: other; type: refptr_same + DCHECK(other.get()); + if (!other.get()) + return NULL; + // Unverified params: handler + + // Execute + cef_request_context_t* _retval = create_context_shared( + CefRequestContextCToCpp::Unwrap(other), CefRequestContextHandlerCppToC::Wrap(handler)); // Return type: refptr_same @@ -62,6 +87,26 @@ bool CefRequestContextCToCpp::IsSame(CefRefPtr other) { return _retval?true:false; } +bool CefRequestContextCToCpp::IsSharingWith( + CefRefPtr other) { + if (CEF_MEMBER_MISSING(struct_, is_sharing_with)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: other; type: refptr_same + DCHECK(other.get()); + if (!other.get()) + return false; + + // Execute + int _retval = struct_->is_sharing_with(struct_, + CefRequestContextCToCpp::Unwrap(other)); + + // Return type: bool + return _retval?true:false; +} + bool CefRequestContextCToCpp::IsGlobal() { if (CEF_MEMBER_MISSING(struct_, is_global)) return false; @@ -88,6 +133,75 @@ CefRefPtr CefRequestContextCToCpp::GetHandler() { return CefRequestContextHandlerCppToC::Unwrap(_retval); } +CefString CefRequestContextCToCpp::GetCachePath() { + if (CEF_MEMBER_MISSING(struct_, get_cache_path)) + return CefString(); + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + cef_string_userfree_t _retval = struct_->get_cache_path(struct_); + + // Return type: string + CefString _retvalStr; + _retvalStr.AttachToUserFree(_retval); + return _retvalStr; +} + +CefRefPtr CefRequestContextCToCpp::GetDefaultCookieManager( + CefRefPtr callback) { + if (CEF_MEMBER_MISSING(struct_, get_default_cookie_manager)) + return NULL; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Unverified params: callback + + // Execute + cef_cookie_manager_t* _retval = struct_->get_default_cookie_manager(struct_, + CefCompletionCallbackCppToC::Wrap(callback)); + + // Return type: refptr_same + return CefCookieManagerCToCpp::Wrap(_retval); +} + +bool CefRequestContextCToCpp::RegisterSchemeHandlerFactory( + const CefString& scheme_name, const CefString& domain_name, + CefRefPtr factory) { + if (CEF_MEMBER_MISSING(struct_, register_scheme_handler_factory)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: scheme_name; type: string_byref_const + DCHECK(!scheme_name.empty()); + if (scheme_name.empty()) + return false; + // Unverified params: domain_name, factory + + // Execute + int _retval = struct_->register_scheme_handler_factory(struct_, + scheme_name.GetStruct(), + domain_name.GetStruct(), + CefSchemeHandlerFactoryCppToC::Wrap(factory)); + + // Return type: bool + return _retval?true:false; +} + +bool CefRequestContextCToCpp::ClearSchemeHandlerFactories() { + if (CEF_MEMBER_MISSING(struct_, clear_scheme_handler_factories)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + int _retval = struct_->clear_scheme_handler_factories(struct_); + + // Return type: bool + return _retval?true:false; +} + #ifndef NDEBUG template<> base::AtomicRefCount CefCToCpp other) OVERRIDE; + virtual bool IsSharingWith(CefRefPtr other) OVERRIDE; virtual bool IsGlobal() OVERRIDE; virtual CefRefPtr GetHandler() OVERRIDE; + virtual CefString GetCachePath() OVERRIDE; + virtual CefRefPtr GetDefaultCookieManager( + CefRefPtr callback) OVERRIDE; + virtual bool RegisterSchemeHandlerFactory(const CefString& scheme_name, + const CefString& domain_name, + CefRefPtr factory) OVERRIDE; + virtual bool ClearSchemeHandlerFactories() OVERRIDE; }; #endif // USING_CEF_SHARED diff --git a/libcef_dll/ctocpp/set_cookie_callback_ctocpp.cc b/libcef_dll/ctocpp/set_cookie_callback_ctocpp.cc new file mode 100644 index 000000000..f69195762 --- /dev/null +++ b/libcef_dll/ctocpp/set_cookie_callback_ctocpp.cc @@ -0,0 +1,34 @@ +// Copyright (c) 2015 The Chromium Embedded Framework Authors. All rights +// reserved. Use of this source code is governed by a BSD-style license that +// can be found in the LICENSE file. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#include "libcef_dll/ctocpp/set_cookie_callback_ctocpp.h" + + +// VIRTUAL METHODS - Body may be edited by hand. + +void CefSetCookieCallbackCToCpp::OnComplete(bool success) { + if (CEF_MEMBER_MISSING(struct_, on_complete)) + return; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + struct_->on_complete(struct_, + success); +} + + +#ifndef NDEBUG +template<> base::AtomicRefCount CefCToCpp::DebugObjCt = 0; +#endif + diff --git a/libcef_dll/ctocpp/set_cookie_callback_ctocpp.h b/libcef_dll/ctocpp/set_cookie_callback_ctocpp.h new file mode 100644 index 000000000..c95d313dc --- /dev/null +++ b/libcef_dll/ctocpp/set_cookie_callback_ctocpp.h @@ -0,0 +1,41 @@ +// Copyright (c) 2015 The Chromium Embedded Framework Authors. All rights +// reserved. Use of this source code is governed by a BSD-style license that +// can be found in the LICENSE file. +// +// --------------------------------------------------------------------------- +// +// This file was generated by the CEF translator tool. If making changes by +// hand only do so within the body of existing method and function +// implementations. See the translator.README.txt file in the tools directory +// for more information. +// + +#ifndef CEF_LIBCEF_DLL_CTOCPP_SET_COOKIE_CALLBACK_CTOCPP_H_ +#define CEF_LIBCEF_DLL_CTOCPP_SET_COOKIE_CALLBACK_CTOCPP_H_ +#pragma once + +#ifndef BUILDING_CEF_SHARED +#pragma message("Warning: "__FILE__" may be accessed DLL-side only") +#else // BUILDING_CEF_SHARED + +#include "include/cef_cookie.h" +#include "include/capi/cef_cookie_capi.h" +#include "libcef_dll/ctocpp/ctocpp.h" + +// Wrap a C structure with a C++ class. +// This class may be instantiated and accessed DLL-side only. +class CefSetCookieCallbackCToCpp + : public CefCToCpp { + public: + explicit CefSetCookieCallbackCToCpp(cef_set_cookie_callback_t* str) + : CefCToCpp(str) {} + + // CefSetCookieCallback methods + void OnComplete(bool success) override; +}; + +#endif // BUILDING_CEF_SHARED +#endif // CEF_LIBCEF_DLL_CTOCPP_SET_COOKIE_CALLBACK_CTOCPP_H_ + diff --git a/libcef_dll/ctocpp/urlrequest_ctocpp.cc b/libcef_dll/ctocpp/urlrequest_ctocpp.cc index ac2fcca97..b99047504 100644 --- a/libcef_dll/ctocpp/urlrequest_ctocpp.cc +++ b/libcef_dll/ctocpp/urlrequest_ctocpp.cc @@ -12,6 +12,7 @@ #include "libcef_dll/cpptoc/urlrequest_client_cpptoc.h" #include "libcef_dll/ctocpp/request_ctocpp.h" +#include "libcef_dll/ctocpp/request_context_ctocpp.h" #include "libcef_dll/ctocpp/response_ctocpp.h" #include "libcef_dll/ctocpp/urlrequest_ctocpp.h" @@ -19,7 +20,8 @@ // STATIC METHODS - Body may be edited by hand. CefRefPtr CefURLRequest::Create(CefRefPtr request, - CefRefPtr client) { + CefRefPtr client, + CefRefPtr request_context) { // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING // Verify param: request; type: refptr_same @@ -30,11 +32,13 @@ CefRefPtr CefURLRequest::Create(CefRefPtr request, DCHECK(client.get()); if (!client.get()) return NULL; + // Unverified params: request_context // Execute cef_urlrequest_t* _retval = cef_urlrequest_create( CefRequestCToCpp::Unwrap(request), - CefURLRequestClientCppToC::Wrap(client)); + CefURLRequestClientCppToC::Wrap(client), + CefRequestContextCToCpp::Unwrap(request_context)); // Return type: refptr_same return CefURLRequestCToCpp::Wrap(_retval); diff --git a/libcef_dll/libcef_dll.cc b/libcef_dll/libcef_dll.cc index 10a906711..ea5e82518 100644 --- a/libcef_dll/libcef_dll.cc +++ b/libcef_dll/libcef_dll.cc @@ -80,6 +80,7 @@ #include "libcef_dll/ctocpp/context_menu_handler_ctocpp.h" #include "libcef_dll/ctocpp/cookie_visitor_ctocpp.h" #include "libcef_dll/ctocpp/domvisitor_ctocpp.h" +#include "libcef_dll/ctocpp/delete_cookies_callback_ctocpp.h" #include "libcef_dll/ctocpp/dialog_handler_ctocpp.h" #include "libcef_dll/ctocpp/display_handler_ctocpp.h" #include "libcef_dll/ctocpp/download_handler_ctocpp.h" @@ -103,6 +104,7 @@ #include "libcef_dll/ctocpp/resource_handler_ctocpp.h" #include "libcef_dll/ctocpp/run_file_dialog_callback_ctocpp.h" #include "libcef_dll/ctocpp/scheme_handler_factory_ctocpp.h" +#include "libcef_dll/ctocpp/set_cookie_callback_ctocpp.h" #include "libcef_dll/ctocpp/string_visitor_ctocpp.h" #include "libcef_dll/ctocpp/task_ctocpp.h" #include "libcef_dll/ctocpp/urlrequest_client_ctocpp.h" @@ -202,6 +204,8 @@ CEF_EXPORT void cef_shutdown() { DCHECK(base::AtomicRefCountIsZero(&CefDOMDocumentCppToC::DebugObjCt)); DCHECK(base::AtomicRefCountIsZero(&CefDOMNodeCppToC::DebugObjCt)); DCHECK(base::AtomicRefCountIsZero(&CefDOMVisitorCToCpp::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero( + &CefDeleteCookiesCallbackCToCpp::DebugObjCt)); DCHECK(base::AtomicRefCountIsZero(&CefDialogHandlerCToCpp::DebugObjCt)); DCHECK(base::AtomicRefCountIsZero(&CefDictionaryValueCppToC::DebugObjCt)); DCHECK(base::AtomicRefCountIsZero(&CefDisplayHandlerCToCpp::DebugObjCt)); @@ -251,6 +255,7 @@ CEF_EXPORT void cef_shutdown() { DCHECK(base::AtomicRefCountIsZero( &CefSchemeHandlerFactoryCToCpp::DebugObjCt)); DCHECK(base::AtomicRefCountIsZero(&CefSchemeRegistrarCppToC::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefSetCookieCallbackCToCpp::DebugObjCt)); DCHECK(base::AtomicRefCountIsZero(&CefStreamReaderCppToC::DebugObjCt)); DCHECK(base::AtomicRefCountIsZero(&CefStreamWriterCppToC::DebugObjCt)); DCHECK(base::AtomicRefCountIsZero(&CefStringVisitorCToCpp::DebugObjCt)); diff --git a/libcef_dll/wrapper/libcef_dll_wrapper.cc b/libcef_dll/wrapper/libcef_dll_wrapper.cc index ddfcb4262..b8b1aa3e8 100644 --- a/libcef_dll/wrapper/libcef_dll_wrapper.cc +++ b/libcef_dll/wrapper/libcef_dll_wrapper.cc @@ -39,6 +39,7 @@ #include "libcef_dll/cpptoc/context_menu_handler_cpptoc.h" #include "libcef_dll/cpptoc/cookie_visitor_cpptoc.h" #include "libcef_dll/cpptoc/domvisitor_cpptoc.h" +#include "libcef_dll/cpptoc/delete_cookies_callback_cpptoc.h" #include "libcef_dll/cpptoc/dialog_handler_cpptoc.h" #include "libcef_dll/cpptoc/display_handler_cpptoc.h" #include "libcef_dll/cpptoc/download_handler_cpptoc.h" @@ -62,6 +63,7 @@ #include "libcef_dll/cpptoc/resource_handler_cpptoc.h" #include "libcef_dll/cpptoc/run_file_dialog_callback_cpptoc.h" #include "libcef_dll/cpptoc/scheme_handler_factory_cpptoc.h" +#include "libcef_dll/cpptoc/set_cookie_callback_cpptoc.h" #include "libcef_dll/cpptoc/string_visitor_cpptoc.h" #include "libcef_dll/cpptoc/task_cpptoc.h" #include "libcef_dll/cpptoc/urlrequest_client_cpptoc.h" @@ -194,6 +196,8 @@ CEF_GLOBAL void CefShutdown() { DCHECK(base::AtomicRefCountIsZero(&CefDOMDocumentCToCpp::DebugObjCt)); DCHECK(base::AtomicRefCountIsZero(&CefDOMNodeCToCpp::DebugObjCt)); DCHECK(base::AtomicRefCountIsZero(&CefDOMVisitorCppToC::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero( + &CefDeleteCookiesCallbackCppToC::DebugObjCt)); DCHECK(base::AtomicRefCountIsZero(&CefDialogHandlerCppToC::DebugObjCt)); DCHECK(base::AtomicRefCountIsZero(&CefDictionaryValueCToCpp::DebugObjCt)); DCHECK(base::AtomicRefCountIsZero(&CefDisplayHandlerCppToC::DebugObjCt)); @@ -243,6 +247,7 @@ CEF_GLOBAL void CefShutdown() { DCHECK(base::AtomicRefCountIsZero( &CefSchemeHandlerFactoryCppToC::DebugObjCt)); DCHECK(base::AtomicRefCountIsZero(&CefSchemeRegistrarCToCpp::DebugObjCt)); + DCHECK(base::AtomicRefCountIsZero(&CefSetCookieCallbackCppToC::DebugObjCt)); DCHECK(base::AtomicRefCountIsZero(&CefStreamReaderCToCpp::DebugObjCt)); DCHECK(base::AtomicRefCountIsZero(&CefStreamWriterCToCpp::DebugObjCt)); DCHECK(base::AtomicRefCountIsZero(&CefStringVisitorCppToC::DebugObjCt)); diff --git a/patch/patch.cfg b/patch/patch.cfg index 3173a26f7..05354c2a2 100644 --- a/patch/patch.cfg +++ b/patch/patch.cfg @@ -132,6 +132,13 @@ patches = [ 'name': 'base_atomicops_455263', 'path': '../base/allocator/', }, + { + # Fix assertion on Linux when ProxyConfigServiceLinux is deleted on the IO + # thread. + # https://code.google.com/p/chromium/issues/detail?id=462624 + 'name': 'net_proxy_462624', + 'path': '../net/proxy/', + }, { # Disable scollbar bounce and overlay on OS X. # http://code.google.com/p/chromiumembedded/issues/detail?id=364 diff --git a/patch/patches/net_proxy_462624.patch b/patch/patches/net_proxy_462624.patch new file mode 100644 index 000000000..702288692 --- /dev/null +++ b/patch/patches/net_proxy_462624.patch @@ -0,0 +1,130 @@ +diff --git proxy_config_service_linux.cc proxy_config_service_linux.cc +index e0a9372..be8068d 100644 +--- proxy_config_service_linux.cc ++++ proxy_config_service_linux.cc +@@ -202,8 +202,11 @@ const int kDebounceTimeoutMilliseconds = 250; + class SettingGetterImplGConf : public ProxyConfigServiceLinux::SettingGetter { + public: + SettingGetterImplGConf() +- : client_(NULL), system_proxy_id_(0), system_http_proxy_id_(0), +- notify_delegate_(NULL) { ++ : client_(NULL), ++ system_proxy_id_(0), ++ system_http_proxy_id_(0), ++ notify_delegate_(NULL), ++ debounce_timer_(new base::OneShotTimer()) { + } + + ~SettingGetterImplGConf() override { +@@ -287,6 +290,7 @@ class SettingGetterImplGConf : public ProxyConfigServiceLinux::SettingGetter { + client_ = NULL; + task_runner_ = NULL; + } ++ debounce_timer_.reset(); + } + + bool SetUpNotifications( +@@ -475,8 +479,8 @@ class SettingGetterImplGConf : public ProxyConfigServiceLinux::SettingGetter { + void OnChangeNotification() { + // We don't use Reset() because the timer may not yet be running. + // (In that case Stop() is a no-op.) +- debounce_timer_.Stop(); +- debounce_timer_.Start(FROM_HERE, ++ debounce_timer_->Stop(); ++ debounce_timer_->Start(FROM_HERE, + base::TimeDelta::FromMilliseconds(kDebounceTimeoutMilliseconds), + this, &SettingGetterImplGConf::OnDebouncedNotification); + } +@@ -499,7 +503,7 @@ class SettingGetterImplGConf : public ProxyConfigServiceLinux::SettingGetter { + guint system_http_proxy_id_; + + ProxyConfigServiceLinux::Delegate* notify_delegate_; +- base::OneShotTimer debounce_timer_; ++ scoped_ptr > debounce_timer_; + + // Task runner for the thread that we make gconf calls on. It should + // be the UI thread and all our methods should be called on this +@@ -523,7 +527,8 @@ class SettingGetterImplGSettings + https_client_(NULL), + ftp_client_(NULL), + socks_client_(NULL), +- notify_delegate_(NULL) { ++ notify_delegate_(NULL), ++ debounce_timer_(new base::OneShotTimer()) { + } + + ~SettingGetterImplGSettings() override { +@@ -598,6 +603,7 @@ class SettingGetterImplGSettings + client_ = NULL; + task_runner_ = NULL; + } ++ debounce_timer_.reset(); + } + + bool SetUpNotifications( +@@ -746,8 +752,8 @@ class SettingGetterImplGSettings + void OnChangeNotification() { + // We don't use Reset() because the timer may not yet be running. + // (In that case Stop() is a no-op.) +- debounce_timer_.Stop(); +- debounce_timer_.Start(FROM_HERE, ++ debounce_timer_->Stop(); ++ debounce_timer_->Start(FROM_HERE, + base::TimeDelta::FromMilliseconds(kDebounceTimeoutMilliseconds), + this, &SettingGetterImplGSettings::OnDebouncedNotification); + } +@@ -768,7 +774,7 @@ class SettingGetterImplGSettings + GSettings* ftp_client_; + GSettings* socks_client_; + ProxyConfigServiceLinux::Delegate* notify_delegate_; +- base::OneShotTimer debounce_timer_; ++ scoped_ptr > debounce_timer_; + + // Task runner for the thread that we make gsettings calls on. It should + // be the UI thread and all our methods should be called on this +@@ -852,9 +858,14 @@ class SettingGetterImplKDE : public ProxyConfigServiceLinux::SettingGetter, + public base::MessagePumpLibevent::Watcher { + public: + explicit SettingGetterImplKDE(base::Environment* env_var_getter) +- : inotify_fd_(-1), notify_delegate_(NULL), indirect_manual_(false), +- auto_no_pac_(false), reversed_bypass_list_(false), +- env_var_getter_(env_var_getter), file_task_runner_(NULL) { ++ : inotify_fd_(-1), ++ notify_delegate_(NULL), ++ debounce_timer_(new base::OneShotTimer()), ++ indirect_manual_(false), ++ auto_no_pac_(false), ++ reversed_bypass_list_(false), ++ env_var_getter_(env_var_getter), ++ file_task_runner_(NULL) { + // This has to be called on the UI thread (http://crbug.com/69057). + base::ThreadRestrictions::ScopedAllowIO allow_io; + +@@ -956,6 +967,7 @@ class SettingGetterImplKDE : public ProxyConfigServiceLinux::SettingGetter, + close(inotify_fd_); + inotify_fd_ = -1; + } ++ debounce_timer_.reset(); + } + + bool SetUpNotifications( +@@ -1305,8 +1317,8 @@ class SettingGetterImplKDE : public ProxyConfigServiceLinux::SettingGetter, + if (kioslaverc_touched) { + // We don't use Reset() because the timer may not yet be running. + // (In that case Stop() is a no-op.) +- debounce_timer_.Stop(); +- debounce_timer_.Start(FROM_HERE, base::TimeDelta::FromMilliseconds( ++ debounce_timer_->Stop(); ++ debounce_timer_->Start(FROM_HERE, base::TimeDelta::FromMilliseconds( + kDebounceTimeoutMilliseconds), this, + &SettingGetterImplKDE::OnDebouncedNotification); + } +@@ -1319,7 +1331,7 @@ class SettingGetterImplKDE : public ProxyConfigServiceLinux::SettingGetter, + int inotify_fd_; + base::MessagePumpLibevent::FileDescriptorWatcher inotify_watcher_; + ProxyConfigServiceLinux::Delegate* notify_delegate_; +- base::OneShotTimer debounce_timer_; ++ scoped_ptr > debounce_timer_; + base::FilePath kde_config_dir_; + bool indirect_manual_; + bool auto_no_pac_; diff --git a/tests/cefclient/browser/client_app_browser.cc b/tests/cefclient/browser/client_app_browser.cc index 05569ebce..2302a6ec3 100644 --- a/tests/cefclient/browser/client_app_browser.cc +++ b/tests/cefclient/browser/client_app_browser.cc @@ -16,9 +16,10 @@ void ClientAppBrowser::OnContextInitialized() { CreateDelegates(delegates_); // Register cookieable schemes with the global cookie manager. - CefRefPtr manager = CefCookieManager::GetGlobalManager(); + CefRefPtr manager = + CefCookieManager::GetGlobalManager(NULL); DCHECK(manager.get()); - manager->SetSupportedSchemes(cookieable_schemes_); + manager->SetSupportedSchemes(cookieable_schemes_, NULL); print_handler_ = CreatePrintHandler(); diff --git a/tests/cefclient/browser/resource.h b/tests/cefclient/browser/resource.h index 75a3da3b6..f89353ac2 100644 --- a/tests/cefclient/browser/resource.h +++ b/tests/cefclient/browser/resource.h @@ -29,15 +29,16 @@ #define ID_TESTS_GETTEXT 32701 #define ID_TESTS_OTHER_TESTS 32702 #define ID_TESTS_PLUGIN_INFO 32703 -#define ID_TESTS_POPUP 32704 -#define ID_TESTS_PRINT 32705 -#define ID_TESTS_REQUEST 32706 -#define ID_TESTS_TRACING_BEGIN 32707 -#define ID_TESTS_TRACING_END 32708 -#define ID_TESTS_ZOOM_IN 32709 -#define ID_TESTS_ZOOM_OUT 32710 -#define ID_TESTS_ZOOM_RESET 32711 -#define ID_TESTS_LAST 32711 +#define ID_TESTS_WINDOW_NEW 32704 +#define ID_TESTS_WINDOW_POPUP 32705 +#define ID_TESTS_PRINT 32706 +#define ID_TESTS_REQUEST 32707 +#define ID_TESTS_TRACING_BEGIN 32708 +#define ID_TESTS_TRACING_END 32709 +#define ID_TESTS_ZOOM_IN 32710 +#define ID_TESTS_ZOOM_OUT 32711 +#define ID_TESTS_ZOOM_RESET 32712 +#define ID_TESTS_LAST 32712 #define IDC_STATIC -1 #define IDS_BINDING 1000 #define IDS_DIALOGS 1001 diff --git a/tests/cefclient/browser/root_window_gtk.cc b/tests/cefclient/browser/root_window_gtk.cc index d48194bcd..cd57909dc 100644 --- a/tests/cefclient/browser/root_window_gtk.cc +++ b/tests/cefclient/browser/root_window_gtk.cc @@ -579,7 +579,8 @@ GtkWidget* RootWindowGtk::CreateMenuBar() { GtkWidget* test_menu = CreateMenu(menu_bar, "Tests"); AddMenuEntry(test_menu, "Get Source", ID_TESTS_GETSOURCE); AddMenuEntry(test_menu, "Get Text", ID_TESTS_GETTEXT); - AddMenuEntry(test_menu, "Popup Window", ID_TESTS_POPUP); + AddMenuEntry(test_menu, "New Window", ID_TESTS_WINDOW_NEW); + AddMenuEntry(test_menu, "Popup Window", ID_TESTS_WINDOW_POPUP); AddMenuEntry(test_menu, "Request", ID_TESTS_REQUEST); AddMenuEntry(test_menu, "Plugin Info", ID_TESTS_PLUGIN_INFO); AddMenuEntry(test_menu, "Zoom In", ID_TESTS_ZOOM_IN); diff --git a/tests/cefclient/browser/root_window_manager.cc b/tests/cefclient/browser/root_window_manager.cc index 6c69ed838..8c9d3ee44 100644 --- a/tests/cefclient/browser/root_window_manager.cc +++ b/tests/cefclient/browser/root_window_manager.cc @@ -4,6 +4,8 @@ #include "cefclient/browser/root_window_manager.h" +#include + #include "include/base/cef_bind.h" #include "include/base/cef_logging.h" #include "include/wrapper/cef_helpers.h" @@ -113,7 +115,20 @@ CefRefPtr RootWindowManager::GetRequestContext( if (request_context_per_browser_) { // Create a new request context for each browser. - return CefRequestContext::CreateContext(NULL); + CefRequestContextSettings settings; + + CefRefPtr command_line = + CefCommandLine::GetGlobalCommandLine(); + if (command_line->HasSwitch(switches::kCachePath)) { + // If a global cache path value is specified then give each browser a + // unique cache path. + std::stringstream ss; + ss << command_line->GetSwitchValue(switches::kCachePath).ToString() << + time(NULL); + CefString(&settings.cache_path) = ss.str(); + } + + return CefRequestContext::CreateContext(settings, NULL); } // All browsers will share the global request context. diff --git a/tests/cefclient/browser/test_runner.cc b/tests/cefclient/browser/test_runner.cc index 4a0a3310a..9d5ac617f 100644 --- a/tests/cefclient/browser/test_runner.cc +++ b/tests/cefclient/browser/test_runner.cc @@ -18,6 +18,7 @@ #include "cefclient/browser/main_context.h" #include "cefclient/browser/resource.h" #include "cefclient/browser/resource_util.h" +#include "cefclient/browser/root_window_manager.h" #include "cefclient/browser/scheme_test.h" #include "cefclient/browser/urlrequest_test.h" #include "cefclient/browser/window_test.h" @@ -112,7 +113,15 @@ void RunRequestTest(CefRefPtr browser) { browser->GetMainFrame()->LoadRequest(request); } -void RunPopupTest(CefRefPtr browser) { +void RunNewWindowTest(CefRefPtr browser) { + MainContext::Get()->GetRootWindowManager()->CreateRootWindow( + true, // Show controls. + browser->GetHost()->IsWindowRenderingDisabled(), + CefRect(), // Use default system size. + std::string()); // Use default URL. +} + +void RunPopupWindowTest(CefRefPtr browser) { browser->GetMainFrame()->ExecuteJavaScript( "window.open('http://www.google.com');", "about:blank", 0); } @@ -288,8 +297,11 @@ void RunTest(CefRefPtr browser, int id) { case ID_TESTS_GETTEXT: RunGetTextTest(browser); break; - case ID_TESTS_POPUP: - RunPopupTest(browser); + case ID_TESTS_WINDOW_NEW: + RunNewWindowTest(browser); + break; + case ID_TESTS_WINDOW_POPUP: + RunPopupWindowTest(browser); break; case ID_TESTS_REQUEST: RunRequestTest(browser); diff --git a/tests/cefclient/browser/urlrequest_test.cc b/tests/cefclient/browser/urlrequest_test.cc index 006579033..4f3f328b6 100644 --- a/tests/cefclient/browser/urlrequest_test.cc +++ b/tests/cefclient/browser/urlrequest_test.cc @@ -131,7 +131,9 @@ class Handler : public CefMessageRouterBrowserSide::Handler { base::Bind(&Handler::OnRequestComplete, base::Unretained(this)); // Create and start the new CefURLRequest. - urlrequest_ = CefURLRequest::Create(request, new RequestClient(callback)); + urlrequest_ = CefURLRequest::Create(request, + new RequestClient(callback), + NULL); return true; } diff --git a/tests/cefclient/cefclient_mac.mm b/tests/cefclient/cefclient_mac.mm index bb21f8737..4e768e906 100644 --- a/tests/cefclient/cefclient_mac.mm +++ b/tests/cefclient/cefclient_mac.mm @@ -128,7 +128,8 @@ void AddMenuItem(NSMenu *menu, NSString* label, int idval) { NSMenu *testMenu = [[[NSMenu alloc] initWithTitle:@"Tests"] autorelease]; AddMenuItem(testMenu, @"Get Text", ID_TESTS_GETSOURCE); AddMenuItem(testMenu, @"Get Source", ID_TESTS_GETTEXT); - AddMenuItem(testMenu, @"Popup Window", ID_TESTS_POPUP); + AddMenuItem(testMenu, @"New Window", ID_TESTS_WINDOW_NEW); + AddMenuItem(testMenu, @"Popup Window", ID_TESTS_WINDOW_POPUP); AddMenuItem(testMenu, @"Request", ID_TESTS_REQUEST); AddMenuItem(testMenu, @"Plugin Info", ID_TESTS_PLUGIN_INFO); AddMenuItem(testMenu, @"Zoom In", ID_TESTS_ZOOM_IN); diff --git a/tests/cefclient/resources/win/cefclient.rc b/tests/cefclient/resources/win/cefclient.rc index 973c6e195..ea91465a0 100644 --- a/tests/cefclient/resources/win/cefclient.rc +++ b/tests/cefclient/resources/win/cefclient.rc @@ -73,7 +73,8 @@ BEGIN BEGIN MENUITEM "Get Source", ID_TESTS_GETSOURCE MENUITEM "Get Text", ID_TESTS_GETTEXT - MENUITEM "Popup Window", ID_TESTS_POPUP + MENUITEM "New Window", ID_TESTS_WINDOW_NEW + MENUITEM "Popup Window", ID_TESTS_WINDOW_POPUP MENUITEM "Request", ID_TESTS_REQUEST MENUITEM "Plugin Info", ID_TESTS_PLUGIN_INFO MENUITEM "Zoom In", ID_TESTS_ZOOM_IN diff --git a/tests/unittests/cookie_unittest.cc b/tests/unittests/cookie_unittest.cc index 2655d9de4..60649e141 100644 --- a/tests/unittests/cookie_unittest.cc +++ b/tests/unittests/cookie_unittest.cc @@ -26,23 +26,66 @@ const char* kTestUrl = "http://www.test.com/path/to/cookietest/foo.html"; const char* kTestDomain = "www.test.com"; const char* kTestPath = "/path/to/cookietest"; +const int kIgnoreNumDeleted = -2; + typedef std::vector CookieVector; -void IOT_Set(CefRefPtr manager, - const CefString& url, CookieVector* cookies, - base::WaitableEvent* event) { - CookieVector::const_iterator it = cookies->begin(); - for (; it != cookies->end(); ++it) - EXPECT_TRUE(manager->SetCookie(url, *it)); - event->Signal(); -} +class TestCompletionCallback : public CefCompletionCallback { + public: + explicit TestCompletionCallback(base::WaitableEvent* event) + : event_(event) {} -void IOT_Delete(CefRefPtr manager, - const CefString& url, const CefString& cookie_name, - base::WaitableEvent* event) { - EXPECT_TRUE(manager->DeleteCookies(url, cookie_name)); - event->Signal(); -} + void OnComplete() override { + event_->Signal(); + } + + private: + base::WaitableEvent* event_; + + IMPLEMENT_REFCOUNTING(TestCompletionCallback); + DISALLOW_COPY_AND_ASSIGN(TestCompletionCallback); +}; + +class TestSetCookieCallback : public CefSetCookieCallback { + public: + TestSetCookieCallback(bool expected_success, + base::WaitableEvent* event) + : expected_success_(expected_success), + event_(event) {} + + void OnComplete(bool success) override { + EXPECT_EQ(expected_success_, success); + event_->Signal(); + } + + private: + bool expected_success_; + base::WaitableEvent* event_; + + IMPLEMENT_REFCOUNTING(TestSetCookieCallback); + DISALLOW_COPY_AND_ASSIGN(TestSetCookieCallback); +}; + +class TestDeleteCookiesCallback : public CefDeleteCookiesCallback { + public: + TestDeleteCookiesCallback(int expected_num_deleted, + base::WaitableEvent* event) + : expected_num_deleted_(expected_num_deleted), + event_(event) {} + + void OnComplete(int num_deleted) override { + if (expected_num_deleted_ != kIgnoreNumDeleted) + EXPECT_EQ(expected_num_deleted_, num_deleted); + event_->Signal(); + } + + private: + int expected_num_deleted_; + base::WaitableEvent* event_; + + IMPLEMENT_REFCOUNTING(TestDeleteCookiesCallback); + DISALLOW_COPY_AND_ASSIGN(TestDeleteCookiesCallback); +}; class TestVisitor : public CefCookieVisitor { public: @@ -73,18 +116,25 @@ class TestVisitor : public CefCookieVisitor { // Set the cookies. void SetCookies(CefRefPtr manager, - const CefString& url, CookieVector& cookies, + const CefString& url, const CookieVector& cookies, + bool expected_success, base::WaitableEvent& event) { - CefPostTask(TID_IO, base::Bind(IOT_Set, manager, url, &cookies, &event)); - event.Wait(); + CookieVector::const_iterator it = cookies.begin(); + for (; it != cookies.end(); ++it) { + EXPECT_TRUE(manager->SetCookie( + url, *it, new TestSetCookieCallback(expected_success, &event))); + event.Wait(); + } } // Delete the cookie. void DeleteCookies(CefRefPtr manager, const CefString& url, const CefString& cookie_name, + int expected_num_deleted, base::WaitableEvent& event) { - CefPostTask(TID_IO, - base::Bind(IOT_Delete, manager, url, cookie_name, &event)); + EXPECT_TRUE(manager->DeleteCookies( + url, cookie_name, + new TestDeleteCookiesCallback(expected_num_deleted, &event))); event.Wait(); } @@ -110,7 +160,7 @@ void CreateCookie(CefRefPtr manager, CookieVector cookies; cookies.push_back(cookie); - SetCookies(manager, kTestUrl, cookies, event); + SetCookies(manager, kTestUrl, cookies, true, event); } // Retrieve the test cookie. If |withDomain| is true check that the cookie @@ -126,7 +176,9 @@ void GetCookie(CefRefPtr manager, new TestVisitor(&cookies, deleteCookies, &event))); event.Wait(); - EXPECT_EQ((CookieVector::size_type)1, cookies.size()); + EXPECT_EQ(1U, cookies.size()); + if (cookies.size() != 1U) + return; const CefCookie& cookie_read = cookies[0]; EXPECT_EQ(CefString(&cookie_read.name), "my_cookie"); @@ -185,19 +237,17 @@ void VerifyNoCookies(CefRefPtr manager, } event.Wait(); - EXPECT_EQ((CookieVector::size_type)0, cookies.size()); + EXPECT_EQ(0U, cookies.size()); } // Delete all system cookies. void DeleteAllCookies(CefRefPtr manager, base::WaitableEvent& event) { - CefPostTask(TID_IO, - base::Bind(IOT_Delete, manager, CefString(), CefString(), &event)); - event.Wait(); + DeleteCookies(manager, CefString(), CefString(), kIgnoreNumDeleted, event); } -void TestDomainCookie(CefRefPtr manager) { - base::WaitableEvent event(false, false); +void TestDomainCookie(CefRefPtr manager, + base::WaitableEvent& event) { CefCookie cookie; // Create a domain cookie. @@ -210,8 +260,8 @@ void TestDomainCookie(CefRefPtr manager) { VerifyNoCookies(manager, event, true); } -void TestHostCookie(CefRefPtr manager) { - base::WaitableEvent event(false, false); +void TestHostCookie(CefRefPtr manager, + base::WaitableEvent& event) { CefCookie cookie; // Create a host cookie. @@ -224,8 +274,8 @@ void TestHostCookie(CefRefPtr manager) { VerifyNoCookies(manager, event, true); } -void TestMultipleCookies(CefRefPtr manager) { - base::WaitableEvent event(false, false); +void TestMultipleCookies(CefRefPtr manager, + base::WaitableEvent& event) { std::stringstream ss; int i; @@ -248,7 +298,7 @@ void TestMultipleCookies(CefRefPtr manager) { } // Set the cookies. - SetCookies(manager, kTestUrl, cookies, event); + SetCookies(manager, kTestUrl, cookies, true, event); cookies.clear(); // Get the cookies without deleting them. @@ -271,12 +321,15 @@ void TestMultipleCookies(CefRefPtr manager) { cookies.clear(); // Delete the 2nd cookie. - DeleteCookies(manager, kTestUrl, CefString("my_cookie1"), event); + DeleteCookies(manager, kTestUrl, CefString("my_cookie1"), -1, event); // Verify that the cookie has been deleted. VisitUrlCookies(manager, kTestUrl, false, cookies, false, event); - EXPECT_EQ((CookieVector::size_type)3, cookies.size()); + EXPECT_EQ(3U, cookies.size()); + if (cookies.size() != 3U) + return; + EXPECT_EQ(CefString(&cookies[0].name), "my_cookie0"); EXPECT_EQ(CefString(&cookies[1].name), "my_cookie2"); EXPECT_EQ(CefString(&cookies[2].name), "my_cookie3"); @@ -284,12 +337,12 @@ void TestMultipleCookies(CefRefPtr manager) { cookies.clear(); // Delete the rest of the cookies. - DeleteCookies(manager, kTestUrl, CefString(), event); + DeleteCookies(manager, kTestUrl, CefString(), 3, event); // Verify that the cookies have been deleted. VisitUrlCookies(manager, kTestUrl, false, cookies, false, event); - EXPECT_EQ((CookieVector::size_type)0, cookies.size()); + EXPECT_EQ(0U, cookies.size()); // Create the cookies. for (i = 0; i < kNumCookies; i++) { @@ -313,21 +366,21 @@ void TestMultipleCookies(CefRefPtr manager) { // Verify that the cookies have been deleted. VisitUrlCookies(manager, kTestUrl, false, cookies, false, event); - EXPECT_EQ((CookieVector::size_type)0, cookies.size()); + EXPECT_EQ(0U, cookies.size()); } -void TestAllCookies(CefRefPtr manager) { - base::WaitableEvent event(false, false); +void TestAllCookies(CefRefPtr manager, + base::WaitableEvent& event) { CookieVector cookies; // Delete all system cookies just in case something is left over from a // different test. - DeleteCookies(manager, CefString(), CefString(), event); + DeleteAllCookies(manager, event); // Verify that all system cookies have been deleted. VisitAllCookies(manager, cookies, false, event); - EXPECT_EQ((CookieVector::size_type)0, cookies.size()); + EXPECT_EQ(0U, cookies.size()); // Create cookies with 2 separate hosts. CefCookie cookie1; @@ -336,7 +389,7 @@ void TestAllCookies(CefRefPtr manager) { CefString(&cookie1.value).FromASCII("My Value 1"); cookies.push_back(cookie1); - SetCookies(manager, kUrl1, cookies, event); + SetCookies(manager, kUrl1, cookies, true, event); cookies.clear(); CefCookie cookie2; @@ -345,13 +398,16 @@ void TestAllCookies(CefRefPtr manager) { CefString(&cookie2.value).FromASCII("My Value 2"); cookies.push_back(cookie2); - SetCookies(manager, kUrl2, cookies, event); + SetCookies(manager, kUrl2, cookies, true, event); cookies.clear(); // Verify that all system cookies can be retrieved. VisitAllCookies(manager, cookies, false, event); - EXPECT_EQ((CookieVector::size_type)2, cookies.size()); + EXPECT_EQ(2U, cookies.size()); + if (cookies.size() != 2U) + return; + EXPECT_EQ(CefString(&cookies[0].name), "my_cookie1"); EXPECT_EQ(CefString(&cookies[0].value), "My Value 1"); EXPECT_EQ(CefString(&cookies[0].domain), "www.foo.com"); @@ -363,7 +419,10 @@ void TestAllCookies(CefRefPtr manager) { // Verify that the cookies can be retrieved separately. VisitUrlCookies(manager, kUrl1, false, cookies, false, event); - EXPECT_EQ((CookieVector::size_type)1, cookies.size()); + EXPECT_EQ(1U, cookies.size()); + if (cookies.size() != 1U) + return; + EXPECT_EQ(CefString(&cookies[0].name), "my_cookie1"); EXPECT_EQ(CefString(&cookies[0].value), "My Value 1"); EXPECT_EQ(CefString(&cookies[0].domain), "www.foo.com"); @@ -371,7 +430,10 @@ void TestAllCookies(CefRefPtr manager) { VisitUrlCookies(manager, kUrl2, false, cookies, false, event); - EXPECT_EQ((CookieVector::size_type)1, cookies.size()); + EXPECT_EQ(1U, cookies.size()); + if (cookies.size() != 1U) + return; + EXPECT_EQ(CefString(&cookies[0].name), "my_cookie2"); EXPECT_EQ(CefString(&cookies[0].value), "My Value 2"); EXPECT_EQ(CefString(&cookies[0].domain), "www.bar.com"); @@ -385,8 +447,8 @@ void TestAllCookies(CefRefPtr manager) { } void TestChangeDirectory(CefRefPtr manager, + base::WaitableEvent& event, const CefString& original_dir) { - base::WaitableEvent event(false, false); CefCookie cookie; base::ScopedTempDir temp_dir; @@ -398,7 +460,7 @@ void TestChangeDirectory(CefRefPtr manager, DeleteAllCookies(manager, event); // Set the new temporary directory as the storage location. - EXPECT_TRUE(manager->SetStoragePath(temp_dir.path().value(), false)); + EXPECT_TRUE(manager->SetStoragePath(temp_dir.path().value(), false, NULL)); // Wait for the storage location change to complete on the IO thread. WaitForIOThread(); @@ -413,7 +475,7 @@ void TestChangeDirectory(CefRefPtr manager, GetCookie(manager, cookie, true, event, false); // Restore the original storage location. - EXPECT_TRUE(manager->SetStoragePath(original_dir, false)); + EXPECT_TRUE(manager->SetStoragePath(original_dir, false, NULL)); // Wait for the storage location change to complete on the IO thread. WaitForIOThread(); @@ -422,7 +484,7 @@ void TestChangeDirectory(CefRefPtr manager, VerifyNoCookies(manager, event, true); // Set the new temporary directory as the storage location. - EXPECT_TRUE(manager->SetStoragePath(temp_dir.path().value(), false)); + EXPECT_TRUE(manager->SetStoragePath(temp_dir.path().value(), false, NULL)); // Wait for the storage location change to complete on the IO thread. WaitForIOThread(); @@ -431,7 +493,7 @@ void TestChangeDirectory(CefRefPtr manager, GetCookie(manager, cookie, true, event, false); // Restore the original storage location. - EXPECT_TRUE(manager->SetStoragePath(original_dir, false)); + EXPECT_TRUE(manager->SetStoragePath(original_dir, false, NULL)); // Wait for the storage location change to complete on the IO thread. WaitForIOThread(); @@ -441,19 +503,27 @@ void TestChangeDirectory(CefRefPtr manager, // Test creation of a domain cookie. TEST(CookieTest, DomainCookieGlobal) { - CefRefPtr manager = CefCookieManager::GetGlobalManager(); + base::WaitableEvent event(false, false); + + CefRefPtr manager = + CefCookieManager::GetGlobalManager(new TestCompletionCallback(&event)); + event.Wait(); EXPECT_TRUE(manager.get()); - TestDomainCookie(manager); + TestDomainCookie(manager, event); } // Test creation of a domain cookie. TEST(CookieTest, DomainCookieInMemory) { + base::WaitableEvent event(false, false); + CefRefPtr manager = - CefCookieManager::CreateManager(CefString(), false); + CefCookieManager::CreateManager(CefString(), false, + new TestCompletionCallback(&event)); + event.Wait(); EXPECT_TRUE(manager.get()); - TestDomainCookie(manager); + TestDomainCookie(manager, event); } // Test creation of a domain cookie. @@ -463,28 +533,40 @@ TEST(CookieTest, DomainCookieOnDisk) { // Create a new temporary directory. EXPECT_TRUE(temp_dir.CreateUniqueTempDir()); + base::WaitableEvent event(false, false); + CefRefPtr manager = - CefCookieManager::CreateManager(temp_dir.path().value(), false); + CefCookieManager::CreateManager(temp_dir.path().value(), false, + new TestCompletionCallback(&event)); + event.Wait(); EXPECT_TRUE(manager.get()); - TestDomainCookie(manager); + TestDomainCookie(manager, event); } // Test creation of a host cookie. TEST(CookieTest, HostCookieGlobal) { - CefRefPtr manager = CefCookieManager::GetGlobalManager(); + base::WaitableEvent event(false, false); + + CefRefPtr manager = + CefCookieManager::GetGlobalManager(new TestCompletionCallback(&event)); + event.Wait(); EXPECT_TRUE(manager.get()); - TestHostCookie(manager); + TestHostCookie(manager, event); } // Test creation of a host cookie. TEST(CookieTest, HostCookieInMemory) { + base::WaitableEvent event(false, false); + CefRefPtr manager = - CefCookieManager::CreateManager(CefString(), false); + CefCookieManager::CreateManager(CefString(), false, + new TestCompletionCallback(&event)); + event.Wait(); EXPECT_TRUE(manager.get()); - TestHostCookie(manager); + TestHostCookie(manager, event); } // Test creation of a host cookie. @@ -494,28 +576,40 @@ TEST(CookieTest, HostCookieOnDisk) { // Create a new temporary directory. EXPECT_TRUE(temp_dir.CreateUniqueTempDir()); + base::WaitableEvent event(false, false); + CefRefPtr manager = - CefCookieManager::CreateManager(temp_dir.path().value(), false); + CefCookieManager::CreateManager(temp_dir.path().value(), false, + new TestCompletionCallback(&event)); + event.Wait(); EXPECT_TRUE(manager.get()); - TestHostCookie(manager); + TestHostCookie(manager, event); } // Test creation of multiple cookies. TEST(CookieTest, MultipleCookiesGlobal) { - CefRefPtr manager = CefCookieManager::GetGlobalManager(); + base::WaitableEvent event(false, false); + + CefRefPtr manager = + CefCookieManager::GetGlobalManager(new TestCompletionCallback(&event)); + event.Wait(); EXPECT_TRUE(manager.get()); - TestMultipleCookies(manager); + TestMultipleCookies(manager, event); } // Test creation of multiple cookies. TEST(CookieTest, MultipleCookiesInMemory) { + base::WaitableEvent event(false, false); + CefRefPtr manager = - CefCookieManager::CreateManager(CefString(), false); + CefCookieManager::CreateManager(CefString(), false, + new TestCompletionCallback(&event)); + event.Wait(); EXPECT_TRUE(manager.get()); - TestMultipleCookies(manager); + TestMultipleCookies(manager, event); } // Test creation of multiple cookies. @@ -525,26 +619,38 @@ TEST(CookieTest, MultipleCookiesOnDisk) { // Create a new temporary directory. EXPECT_TRUE(temp_dir.CreateUniqueTempDir()); + base::WaitableEvent event(false, false); + CefRefPtr manager = - CefCookieManager::CreateManager(temp_dir.path().value(), false); + CefCookieManager::CreateManager(temp_dir.path().value(), false, + new TestCompletionCallback(&event)); + event.Wait(); EXPECT_TRUE(manager.get()); - TestMultipleCookies(manager); + TestMultipleCookies(manager, event); } TEST(CookieTest, AllCookiesGlobal) { - CefRefPtr manager = CefCookieManager::GetGlobalManager(); + base::WaitableEvent event(false, false); + + CefRefPtr manager = + CefCookieManager::GetGlobalManager(new TestCompletionCallback(&event)); + event.Wait(); EXPECT_TRUE(manager.get()); - TestAllCookies(manager); + TestAllCookies(manager, event); } TEST(CookieTest, AllCookiesInMemory) { + base::WaitableEvent event(false, false); + CefRefPtr manager = - CefCookieManager::CreateManager(CefString(), false); + CefCookieManager::CreateManager(CefString(), false, + new TestCompletionCallback(&event)); + event.Wait(); EXPECT_TRUE(manager.get()); - TestAllCookies(manager); + TestAllCookies(manager, event); } TEST(CookieTest, AllCookiesOnDisk) { @@ -553,51 +659,43 @@ TEST(CookieTest, AllCookiesOnDisk) { // Create a new temporary directory. EXPECT_TRUE(temp_dir.CreateUniqueTempDir()); + base::WaitableEvent event(false, false); + CefRefPtr manager = - CefCookieManager::CreateManager(temp_dir.path().value(), false); + CefCookieManager::CreateManager(temp_dir.path().value(), false, + new TestCompletionCallback(&event)); + event.Wait(); EXPECT_TRUE(manager.get()); - TestAllCookies(manager); + TestAllCookies(manager, event); } TEST(CookieTest, ChangeDirectoryGlobal) { - CefRefPtr manager = CefCookieManager::GetGlobalManager(); + base::WaitableEvent event(false, false); + + CefRefPtr manager = + CefCookieManager::GetGlobalManager(new TestCompletionCallback(&event)); + event.Wait(); EXPECT_TRUE(manager.get()); std::string cache_path; CefTestSuite::GetCachePath(cache_path); - TestChangeDirectory(manager, cache_path); + TestChangeDirectory(manager, event, cache_path); } TEST(CookieTest, ChangeDirectoryCreated) { + base::WaitableEvent event(false, false); + CefRefPtr manager = - CefCookieManager::CreateManager(CefString(), false); + CefCookieManager::CreateManager(CefString(), false, + new TestCompletionCallback(&event)); + event.Wait(); EXPECT_TRUE(manager.get()); - TestChangeDirectory(manager, CefString()); + TestChangeDirectory(manager, event, CefString()); } - -namespace { - -class TestCompletionCallback : public CefCompletionCallback { - public: - explicit TestCompletionCallback(base::WaitableEvent* event) - : event_(event) {} - - void OnComplete() override { - event_->Signal(); - } - - private: - base::WaitableEvent* event_; - - IMPLEMENT_REFCOUNTING(TestCompletionCallback); -}; - -} // namespace - TEST(CookieTest, SessionCookieNoPersist) { base::ScopedTempDir temp_dir; base::WaitableEvent event(false, false); @@ -607,7 +705,9 @@ TEST(CookieTest, SessionCookieNoPersist) { EXPECT_TRUE(temp_dir.CreateUniqueTempDir()); CefRefPtr manager = - CefCookieManager::CreateManager(temp_dir.path().value(), false); + CefCookieManager::CreateManager(temp_dir.path().value(), false, + new TestCompletionCallback(&event)); + event.Wait(); EXPECT_TRUE(manager.get()); // Create a session cookie. @@ -619,10 +719,12 @@ TEST(CookieTest, SessionCookieNoPersist) { // Flush the cookie store to disk. manager->FlushStore(new TestCompletionCallback(&event)); event.Wait(); - + // Create a new manager to read the same cookie store. - manager = - CefCookieManager::CreateManager(temp_dir.path().value(), false); + manager = CefCookieManager::CreateManager(temp_dir.path().value(), false, + new TestCompletionCallback(&event)); + event.Wait(); + EXPECT_TRUE(manager.get()); // Verify that the cookie doesn't exist. VerifyNoCookies(manager, event, true); @@ -637,7 +739,9 @@ TEST(CookieTest, SessionCookieWillPersist) { EXPECT_TRUE(temp_dir.CreateUniqueTempDir()); CefRefPtr manager = - CefCookieManager::CreateManager(temp_dir.path().value(), true); + CefCookieManager::CreateManager(temp_dir.path().value(), true, + new TestCompletionCallback(&event)); + event.Wait(); EXPECT_TRUE(manager.get()); // Create a session cookie. @@ -651,8 +755,10 @@ TEST(CookieTest, SessionCookieWillPersist) { event.Wait(); // Create a new manager to read the same cookie store. - manager = - CefCookieManager::CreateManager(temp_dir.path().value(), true); + manager = CefCookieManager::CreateManager(temp_dir.path().value(), true, + new TestCompletionCallback(&event)); + event.Wait(); + EXPECT_TRUE(manager.get()); // Verify that the cookie exists. GetCookie(manager, cookie, true, event, false); @@ -704,9 +810,9 @@ class CookieTestJSHandler : public TestHandler { CookieTestJSHandler() {} void RunTest() override { - // Create =new in-memory managers. - manager1_ = CefCookieManager::CreateManager(CefString(), false); - manager2_ = CefCookieManager::CreateManager(CefString(), false); + // Create new in-memory managers. + manager1_ = CefCookieManager::CreateManager(CefString(), false, NULL); + manager2_ = CefCookieManager::CreateManager(CefString(), false, NULL); std::string page = "" @@ -727,9 +833,13 @@ class CookieTestJSHandler : public TestHandler { context_handler_ = new RequestContextHandler(this); context_handler_->SetURL(kCookieJSUrl1); - // Create the browser - CreateBrowser(kCookieJSUrl1, - CefRequestContext::CreateContext(context_handler_.get())); + // Create the request context that will use an in-memory cache. + CefRequestContextSettings settings; + CefRefPtr request_context = + CefRequestContext::CreateContext(settings, context_handler_.get()); + + // Create the browser. + CreateBrowser(kCookieJSUrl1, request_context); // Time out the test after a reasonable period of time. SetTestTimeout(); @@ -773,7 +883,7 @@ class CookieTestJSHandler : public TestHandler { // Get the cookie. VisitUrlCookies(manager, url, false, cookies, false, event); - if (cookies.size() == 1 && CefString(&cookies[0].name) == name && + if (cookies.size() == 1U && CefString(&cookies[0].name) == name && CefString(&cookies[0].value) == value) { callback.yes(); } @@ -968,8 +1078,8 @@ class CookieTestSchemeHandler : public TestHandler { void RunTest() override { // Create new in-memory managers. - manager1_ = CefCookieManager::CreateManager(CefString(), false); - manager2_ = CefCookieManager::CreateManager(CefString(), false); + manager1_ = CefCookieManager::CreateManager(CefString(), false, NULL); + manager2_ = CefCookieManager::CreateManager(CefString(), false, NULL); if (scheme_ != "http") { std::vector schemes; @@ -977,20 +1087,24 @@ class CookieTestSchemeHandler : public TestHandler { schemes.push_back("https"); schemes.push_back(scheme_); - manager1_->SetSupportedSchemes(schemes); - manager2_->SetSupportedSchemes(schemes); + manager1_->SetSupportedSchemes(schemes, NULL); + manager2_->SetSupportedSchemes(schemes, NULL); } - // Register the scheme handler. - CefRegisterSchemeHandlerFactory(scheme_, "cookie-tests", - new SchemeHandlerFactory(this)); - context_handler_ = new RequestContextHandler(this); context_handler_->SetURL(url1_); - // Create the browser - CreateBrowser(url1_, - CefRequestContext::CreateContext(context_handler_.get())); + // Create the request context that will use an in-memory cache. + CefRequestContextSettings settings; + CefRefPtr request_context = + CefRequestContext::CreateContext(settings, context_handler_.get()); + + // Register the scheme handler. + request_context->RegisterSchemeHandlerFactory(scheme_, "cookie-tests", + new SchemeHandlerFactory(this)); + + // Create the browser. + CreateBrowser(url1_, request_context); // Time out the test after a reasonable period of time. SetTestTimeout(); @@ -1019,7 +1133,8 @@ class CookieTestSchemeHandler : public TestHandler { VerifyCookie(manager2_, url, "name2", "value2", got_cookie3_); // Unregister the scheme handler. - CefRegisterSchemeHandlerFactory(scheme_, "cookie-tests", NULL); + browser->GetHost()->GetRequestContext()->RegisterSchemeHandlerFactory( + scheme_, "cookie-tests", NULL); DestroyTest(); } @@ -1044,7 +1159,7 @@ class CookieTestSchemeHandler : public TestHandler { // Get the cookie. VisitUrlCookies(manager, url, false, cookies, false, event); - if (cookies.size() == 1 && CefString(&cookies[0].name) == name && + if (cookies.size() == 1U && CefString(&cookies[0].name) == name && CefString(&cookies[0].value) == value) { callback.yes(); } diff --git a/tests/unittests/request_context_unittest.cc b/tests/unittests/request_context_unittest.cc index bbe3bcd2e..70aebdf8f 100644 --- a/tests/unittests/request_context_unittest.cc +++ b/tests/unittests/request_context_unittest.cc @@ -6,6 +6,7 @@ #include "tests/unittests/chromium_includes.h" #include "include/base/cef_bind.h" +#include "base/files/scoped_temp_dir.h" #include "include/cef_request_context.h" #include "include/cef_request_context_handler.h" #include "include/wrapper/cef_closure_task.h" @@ -18,15 +19,19 @@ TEST(RequestContextTest, GetGlobalContext) { EXPECT_TRUE(context1.get()); EXPECT_TRUE(context1->IsGlobal()); EXPECT_TRUE(context1->IsSame(context1)); + EXPECT_TRUE(context1->IsSharingWith(context1)); CefRefPtr context2 = CefRequestContext::GetGlobalContext(); EXPECT_TRUE(context2.get()); EXPECT_TRUE(context2->IsGlobal()); EXPECT_TRUE(context2->IsSame(context2)); + EXPECT_TRUE(context2->IsSharingWith(context2)); EXPECT_TRUE(context1->IsSame(context2)); EXPECT_TRUE(context2->IsSame(context1)); + EXPECT_TRUE(context1->IsSharingWith(context2)); + EXPECT_TRUE(context2->IsSharingWith(context1)); } TEST(RequestContextTest, CreateContext) { @@ -40,57 +45,193 @@ TEST(RequestContextTest, CreateContext) { CefRefPtr handler = new Handler(); + CefRequestContextSettings settings; + CefRefPtr context1 = - CefRequestContext::CreateContext(handler.get()); + CefRequestContext::CreateContext(settings, handler.get()); EXPECT_TRUE(context1.get()); EXPECT_FALSE(context1->IsGlobal()); EXPECT_TRUE(context1->IsSame(context1)); + EXPECT_TRUE(context1->IsSharingWith(context1)); EXPECT_EQ(context1->GetHandler().get(), handler.get()); CefRefPtr context2 = - CefRequestContext::CreateContext(handler.get()); + CefRequestContext::CreateContext(settings, handler.get()); EXPECT_TRUE(context2.get()); EXPECT_FALSE(context2->IsGlobal()); EXPECT_TRUE(context2->IsSame(context2)); + EXPECT_TRUE(context2->IsSharingWith(context2)); EXPECT_EQ(context2->GetHandler().get(), handler.get()); EXPECT_FALSE(context1->IsSame(context2)); + EXPECT_FALSE(context1->IsSharingWith(context2)); EXPECT_FALSE(context2->IsSame(context1)); + EXPECT_FALSE(context2->IsSharingWith(context1)); CefRefPtr context3 = CefRequestContext::GetGlobalContext(); EXPECT_TRUE(context3.get()); EXPECT_FALSE(context3->IsSame(context1)); + EXPECT_FALSE(context3->IsSharingWith(context1)); EXPECT_FALSE(context3->IsSame(context2)); + EXPECT_FALSE(context3->IsSharingWith(context2)); EXPECT_FALSE(context1->IsSame(context3)); + EXPECT_FALSE(context1->IsSharingWith(context3)); EXPECT_FALSE(context2->IsSame(context3)); + EXPECT_FALSE(context2->IsSharingWith(context3)); } TEST(RequestContextTest, CreateContextNoHandler) { + CefRequestContextSettings settings; + CefRefPtr context1 = - CefRequestContext::CreateContext(NULL); + CefRequestContext::CreateContext(settings, NULL); EXPECT_TRUE(context1.get()); EXPECT_FALSE(context1->IsGlobal()); EXPECT_TRUE(context1->IsSame(context1)); + EXPECT_TRUE(context1->IsSharingWith(context1)); EXPECT_FALSE(context1->GetHandler().get()); CefRefPtr context2 = - CefRequestContext::CreateContext(NULL); + CefRequestContext::CreateContext(settings, NULL); EXPECT_TRUE(context2.get()); EXPECT_FALSE(context2->IsGlobal()); EXPECT_TRUE(context2->IsSame(context2)); + EXPECT_TRUE(context2->IsSharingWith(context2)); EXPECT_FALSE(context2->GetHandler().get()); EXPECT_FALSE(context1->IsSame(context2)); + EXPECT_FALSE(context1->IsSharingWith(context2)); EXPECT_FALSE(context2->IsSame(context1)); + EXPECT_FALSE(context2->IsSharingWith(context1)); CefRefPtr context3 = CefRequestContext::GetGlobalContext(); EXPECT_TRUE(context3.get()); EXPECT_FALSE(context3->IsSame(context1)); + EXPECT_FALSE(context3->IsSharingWith(context1)); EXPECT_FALSE(context3->IsSame(context2)); + EXPECT_FALSE(context3->IsSharingWith(context2)); + EXPECT_FALSE(context1->IsSame(context3)); + EXPECT_FALSE(context1->IsSharingWith(context3)); + EXPECT_FALSE(context2->IsSame(context3)); + EXPECT_FALSE(context2->IsSharingWith(context3)); +} + +TEST(RequestContextTest, CreateContextSharedGlobal) { + CefRequestContextSettings settings; + + CefRefPtr context1 = + CefRequestContext::GetGlobalContext(); + EXPECT_TRUE(context1.get()); + EXPECT_TRUE(context1->IsGlobal()); + EXPECT_TRUE(context1->IsSame(context1)); + EXPECT_TRUE(context1->IsSharingWith(context1)); + + CefRefPtr context2 = + CefRequestContext::CreateContext(context1, NULL); + EXPECT_TRUE(context2.get()); + EXPECT_FALSE(context2->IsGlobal()); + EXPECT_TRUE(context2->IsSame(context2)); + EXPECT_FALSE(context2->IsSame(context1)); + EXPECT_FALSE(context1->IsSame(context2)); + EXPECT_TRUE(context2->IsSharingWith(context2)); + EXPECT_TRUE(context2->IsSharingWith(context1)); + EXPECT_TRUE(context1->IsSharingWith(context2)); + + CefRefPtr context3 = + CefRequestContext::CreateContext(context2, NULL); + EXPECT_TRUE(context3.get()); + EXPECT_FALSE(context3->IsGlobal()); + EXPECT_TRUE(context3->IsSame(context3)); + EXPECT_FALSE(context3->IsSame(context2)); + EXPECT_FALSE(context3->IsSame(context1)); EXPECT_FALSE(context1->IsSame(context3)); EXPECT_FALSE(context2->IsSame(context3)); + EXPECT_TRUE(context3->IsSharingWith(context3)); + EXPECT_TRUE(context3->IsSharingWith(context2)); + EXPECT_TRUE(context3->IsSharingWith(context1)); + EXPECT_TRUE(context1->IsSharingWith(context3)); + EXPECT_TRUE(context2->IsSharingWith(context3)); + + CefRefPtr context4 = + CefRequestContext::CreateContext(context1, NULL); + EXPECT_TRUE(context4.get()); + EXPECT_FALSE(context4->IsGlobal()); + EXPECT_TRUE(context4->IsSame(context4)); + EXPECT_FALSE(context4->IsSame(context3)); + EXPECT_FALSE(context4->IsSame(context2)); + EXPECT_FALSE(context4->IsSame(context1)); + EXPECT_FALSE(context1->IsSame(context4)); + EXPECT_FALSE(context2->IsSame(context4)); + EXPECT_FALSE(context3->IsSame(context4)); + EXPECT_TRUE(context4->IsSharingWith(context4)); + EXPECT_TRUE(context4->IsSharingWith(context3)); + EXPECT_TRUE(context4->IsSharingWith(context2)); + EXPECT_TRUE(context4->IsSharingWith(context1)); + EXPECT_TRUE(context1->IsSharingWith(context4)); + EXPECT_TRUE(context2->IsSharingWith(context4)); + EXPECT_TRUE(context3->IsSharingWith(context4)); +} + +TEST(RequestContextTest, CreateContextSharedOnDisk) { + base::ScopedTempDir tempdir; + EXPECT_TRUE(tempdir.CreateUniqueTempDir()); + + CefRequestContextSettings settings; + CefString(&settings.cache_path) = tempdir.path().value(); + + CefRefPtr context1 = + CefRequestContext::CreateContext(settings, NULL); + EXPECT_TRUE(context1.get()); + EXPECT_FALSE(context1->IsGlobal()); + EXPECT_TRUE(context1->IsSame(context1)); + EXPECT_TRUE(context1->IsSharingWith(context1)); + + CefRefPtr context2 = + CefRequestContext::CreateContext(context1, NULL); + EXPECT_TRUE(context2.get()); + EXPECT_FALSE(context2->IsGlobal()); + EXPECT_TRUE(context2->IsSame(context2)); + EXPECT_FALSE(context2->IsSame(context1)); + EXPECT_FALSE(context1->IsSame(context2)); + EXPECT_TRUE(context2->IsSharingWith(context2)); + EXPECT_TRUE(context2->IsSharingWith(context1)); + EXPECT_TRUE(context1->IsSharingWith(context2)); + + CefRefPtr context3 = + CefRequestContext::CreateContext(context2, NULL); + EXPECT_TRUE(context3.get()); + EXPECT_FALSE(context3->IsGlobal()); + EXPECT_TRUE(context3->IsSame(context3)); + EXPECT_FALSE(context3->IsSame(context2)); + EXPECT_FALSE(context3->IsSame(context1)); + EXPECT_FALSE(context1->IsSame(context3)); + EXPECT_FALSE(context2->IsSame(context3)); + EXPECT_TRUE(context3->IsSharingWith(context3)); + EXPECT_TRUE(context3->IsSharingWith(context2)); + EXPECT_TRUE(context3->IsSharingWith(context1)); + EXPECT_TRUE(context1->IsSharingWith(context3)); + EXPECT_TRUE(context2->IsSharingWith(context3)); + + CefRefPtr context4 = + CefRequestContext::CreateContext(context1, NULL); + EXPECT_TRUE(context4.get()); + EXPECT_FALSE(context4->IsGlobal()); + EXPECT_TRUE(context4->IsSame(context4)); + EXPECT_FALSE(context4->IsSame(context3)); + EXPECT_FALSE(context4->IsSame(context2)); + EXPECT_FALSE(context4->IsSame(context1)); + EXPECT_FALSE(context1->IsSame(context4)); + EXPECT_FALSE(context2->IsSame(context4)); + EXPECT_FALSE(context3->IsSame(context4)); + EXPECT_TRUE(context4->IsSharingWith(context4)); + EXPECT_TRUE(context4->IsSharingWith(context3)); + EXPECT_TRUE(context4->IsSharingWith(context2)); + EXPECT_TRUE(context4->IsSharingWith(context1)); + EXPECT_TRUE(context1->IsSharingWith(context4)); + EXPECT_TRUE(context2->IsSharingWith(context4)); + EXPECT_TRUE(context3->IsSharingWith(context4)); } namespace { @@ -128,9 +269,12 @@ class CookieTestHandler : public TestHandler { "Nav1" "", "text/html"); + CefRequestContextSettings settings; + context_handler_ = new RequestContextHandler(this); - context_ = CefRequestContext::CreateContext(context_handler_.get()); - cookie_manager_ = CefCookieManager::CreateManager(CefString(), true); + context_ = + CefRequestContext::CreateContext(settings, context_handler_.get()); + cookie_manager_ = CefCookieManager::CreateManager(CefString(), true, NULL); // Create browser that loads the 1st URL. CreateBrowser(url_, context_); @@ -142,7 +286,8 @@ class CookieTestHandler : public TestHandler { void OnLoadEnd(CefRefPtr browser, CefRefPtr frame, int httpStatusCode) override { - CefRefPtr context = browser->GetHost()->GetRequestContext(); + CefRefPtr context = + browser->GetHost()->GetRequestContext(); EXPECT_TRUE(context.get()); EXPECT_TRUE(context->IsSame(context_)); EXPECT_FALSE(context->IsGlobal()); @@ -287,10 +432,13 @@ class PopupTestHandler : public TestHandler { "Nav1" "", "text/html"); + CefRequestContextSettings settings; + context_handler_ = new RequestContextHandler(this); context_handler_->SetURL(url_); - context_ = CefRequestContext::CreateContext(context_handler_.get()); - cookie_manager_ = CefCookieManager::CreateManager(CefString(), true); + context_ = + CefRequestContext::CreateContext(settings, context_handler_.get()); + cookie_manager_ = CefCookieManager::CreateManager(CefString(), true, NULL); // Create browser that loads the 1st URL. CreateBrowser(url_, context_); @@ -302,7 +450,8 @@ class PopupTestHandler : public TestHandler { void OnLoadEnd(CefRefPtr browser, CefRefPtr frame, int httpStatusCode) override { - CefRefPtr context = browser->GetHost()->GetRequestContext(); + CefRefPtr context = + browser->GetHost()->GetRequestContext(); EXPECT_TRUE(context.get()); EXPECT_TRUE(context->IsSame(context_)); EXPECT_FALSE(context->IsGlobal()); diff --git a/tests/unittests/request_handler_unittest.cc b/tests/unittests/request_handler_unittest.cc index 4d18c7dfb..580179621 100644 --- a/tests/unittests/request_handler_unittest.cc +++ b/tests/unittests/request_handler_unittest.cc @@ -102,7 +102,7 @@ class NetNotifyTestHandler : public TestHandler { url2_ = base::StringPrintf("%snav2.html?t=%d", same_origin_ ? kNetNotifyOrigin1 : kNetNotifyOrigin2, test_type_); - cookie_manager_ = CefCookieManager::CreateManager(CefString(), true); + cookie_manager_ = CefCookieManager::CreateManager(CefString(), true, NULL); AddResource(url1_, "" @@ -118,9 +118,13 @@ class NetNotifyTestHandler : public TestHandler { context_handler_ = new RequestContextHandler(this); context_handler_->SetURL(url1_); + // Create the request context that will use an in-memory cache. + CefRequestContextSettings settings; + CefRefPtr request_context = + CefRequestContext::CreateContext(settings, context_handler_.get()); + // Create browser that loads the 1st URL. - CreateBrowser(url1_, - CefRequestContext::CreateContext(context_handler_.get())); + CreateBrowser(url1_, request_context); } void RunTest() override { diff --git a/tests/unittests/test_handler.cc b/tests/unittests/test_handler.cc index a94937cb4..247e3654c 100644 --- a/tests/unittests/test_handler.cc +++ b/tests/unittests/test_handler.cc @@ -32,9 +32,11 @@ TestHandler::CompletionState::CompletionState(int total) void TestHandler::CompletionState::TestComplete() { if (++count_ == total_) { - // Signal that the test is now complete. - event_.Signal(); count_ = 0; + + // Signal that the test is now complete. Do not access any object members + // after this call because |this| might be deleted. + event_.Signal(); } } diff --git a/tests/unittests/urlrequest_unittest.cc b/tests/unittests/urlrequest_unittest.cc index cdebd142d..6df61b9ac 100644 --- a/tests/unittests/urlrequest_unittest.cc +++ b/tests/unittests/urlrequest_unittest.cc @@ -55,6 +55,12 @@ enum RequestTestMode { REQTEST_HEAD, }; +enum ContextTestMode { + CONTEXT_GLOBAL, + CONTEXT_INMEMORY, + CONTEXT_ONDISK, +}; + struct RequestRunSettings { RequestRunSettings() : expect_upload_progress(false), @@ -140,9 +146,43 @@ void GetUploadData(CefRefPtr request, EXPECT_EQ(size, element->GetBytes(size, const_cast(data.c_str()))); } +// Set a cookie so that we can test if it's sent with the request. +void SetTestCookie(CefRefPtr request_context, + base::WaitableEvent* event) { + class Callback : public CefSetCookieCallback { + public: + explicit Callback(base::WaitableEvent* event) + : event_(event) {} + + void OnComplete(bool success) override { + EXPECT_TRUE(success); + event_->Signal(); + } + + private: + base::WaitableEvent* event_; + + IMPLEMENT_REFCOUNTING(Callback); + }; + + CefCookie cookie; + CefString(&cookie.name) = kRequestSendCookieName; + CefString(&cookie.value) = "send-cookie-value"; + CefString(&cookie.domain) = kRequestHost; + CefString(&cookie.path) = "/"; + cookie.has_expires = false; + EXPECT_TRUE(request_context->GetDefaultCookieManager(NULL)->SetCookie( + kRequestOrigin, cookie, new Callback(event))); + + // Wait for the Callback. + event->Wait(); +} + // Tests if the save cookie has been set. If set, it will be deleted at the same // time. -void TestSaveCookie(base::WaitableEvent* event, bool* cookie_exists) { +void GetTestCookie(CefRefPtr request_context, + base::WaitableEvent* event, + bool* cookie_exists) { class Visitor : public CefCookieVisitor { public: Visitor(base::WaitableEvent* event, bool* cookie_exists) @@ -172,10 +212,11 @@ void TestSaveCookie(base::WaitableEvent* event, bool* cookie_exists) { }; CefRefPtr cookie_manager = - CefCookieManager::GetGlobalManager(); - EXPECT_TRUE(cookie_manager.get()); - cookie_manager->VisitUrlCookies(kRequestOrigin, true, - new Visitor(event, cookie_exists)); + request_context->GetDefaultCookieManager(NULL); + cookie_manager->VisitUrlCookies( + kRequestOrigin, true, new Visitor(event, cookie_exists)); + + // Wait for the Visitor. event->Wait(); } @@ -431,11 +472,14 @@ class RequestClient : public CefURLRequestClient { virtual ~Delegate() {} }; - static CefRefPtr Create(Delegate* delegate, - CefRefPtr request) { - CefRefPtr client = new RequestClient(delegate); - CefURLRequest::Create(request, client.get()); - return client; + explicit RequestClient(Delegate* delegate) + : delegate_(delegate), + request_complete_ct_(0), + upload_progress_ct_(0), + download_progress_ct_(0), + download_data_ct_(0), + upload_total_(0), + download_total_(0) { } void OnRequestComplete(CefRefPtr request) override { @@ -489,16 +533,6 @@ class RequestClient : public CefURLRequestClient { } private: - explicit RequestClient(Delegate* delegate) - : delegate_(delegate), - request_complete_ct_(0), - upload_progress_ct_(0), - download_progress_ct_(0), - download_data_ct_(0), - upload_total_(0), - download_total_(0) { - } - Delegate* delegate_; public: @@ -521,7 +555,7 @@ class RequestClient : public CefURLRequestClient { // Executes the tests. -class RequestTestRunner { +class RequestTestRunner : public base::RefCountedThreadSafe { public: typedef base::Callback TestCallback; @@ -533,16 +567,15 @@ class RequestTestRunner { virtual ~Delegate() {} }; - RequestTestRunner(Delegate* delegate, bool is_browser_process) + RequestTestRunner(Delegate* delegate, + bool is_browser_process) : delegate_(delegate), is_browser_process_(is_browser_process) { // Helper macro for registering test callbacks. #define REGISTER_TEST(test_mode, setup_method, run_method) \ RegisterTest(test_mode, \ - base::Bind(&RequestTestRunner::setup_method, \ - base::Unretained(this)), \ - base::Bind(&RequestTestRunner::run_method, \ - base::Unretained(this))); + base::Bind(&RequestTestRunner::setup_method, this), \ + base::Bind(&RequestTestRunner::run_method, this)); // Register the test callbacks. REGISTER_TEST(REQTEST_GET, SetupGetTest, GenericRunTest); @@ -557,6 +590,15 @@ class RequestTestRunner { REGISTER_TEST(REQTEST_HEAD, SetupHeadTest, GenericRunTest); } + // Called in the browser process to set the request context that will be used + // when creating the URL request. + void SetRequestContext(CefRefPtr request_context) { + request_context_ = request_context; + } + CefRefPtr GetRequestContext() const { + return request_context_; + } + // Called in both the browser and render process to setup the test. void SetupTest(RequestTestMode test_mode) { TestMap::const_iterator it = test_map_.find(test_mode); @@ -701,7 +743,8 @@ class RequestTestRunner { void GenericRunTest() { class Test : public RequestClient::Delegate { public: - Test(RequestTestRunner* runner, const RequestRunSettings& settings) + Test(scoped_refptr runner, + const RequestRunSettings& settings) : runner_(runner), settings_(settings) { } @@ -765,7 +808,7 @@ class RequestTestRunner { } private: - RequestTestRunner* runner_; + scoped_refptr runner_; RequestRunSettings settings_; }; @@ -776,7 +819,10 @@ class RequestTestRunner { request = settings_.request; EXPECT_TRUE(request.get()); - RequestClient::Create(new Test(this, settings_), request); + CefRefPtr client = + new RequestClient(new Test(this, settings_)); + + CefURLRequest::Create(request, client.get(), request_context_); } // Register a test. Called in the constructor. @@ -791,7 +837,8 @@ class RequestTestRunner { void DestroyTest() { if (scheme_factory_.get()) { // Remove the factory registration. - CefRegisterSchemeHandlerFactory(kRequestScheme, kRequestHost, NULL); + request_context_->RegisterSchemeHandlerFactory( + kRequestScheme, kRequestHost, NULL); scheme_factory_ = NULL; } @@ -815,8 +862,8 @@ class RequestTestRunner { if (!scheme_factory_.get()) { // Add the factory registration. scheme_factory_ = new RequestSchemeHandlerFactory(); - CefRegisterSchemeHandlerFactory(kRequestScheme, kRequestHost, - scheme_factory_.get()); + request_context_->RegisterSchemeHandlerFactory( + kRequestScheme, kRequestHost, scheme_factory_.get()); } EXPECT_TRUE(settings_.request.get()); @@ -832,6 +879,7 @@ class RequestTestRunner { Delegate* delegate_; bool is_browser_process_; + CefRefPtr request_context_; struct TestEntry { TestCallback setup; @@ -854,7 +902,7 @@ class RequestRendererTest : public ClientAppRenderer::Delegate, public RequestTestRunner::Delegate { public: RequestRendererTest() - : test_runner_(this, false) { + : test_runner_(new RequestTestRunner(this, false)) { } bool OnProcessMessageReceived( @@ -871,10 +919,10 @@ class RequestRendererTest : public ClientAppRenderer::Delegate, // Setup the test. This will create the objects that we test against but // not register any scheme handlers (because we're in the render process). - test_runner_.SetupTest(test_mode); + test_runner_->SetupTest(test_mode); // Run the test. - test_runner_.RunTest(test_mode); + test_runner_->RunTest(test_mode); return true; } @@ -901,7 +949,7 @@ class RequestRendererTest : public ClientAppRenderer::Delegate, CefRefPtr app_; CefRefPtr browser_; - RequestTestRunner test_runner_; + scoped_refptr test_runner_; IMPLEMENT_REFCOUNTING(RequestRendererTest); }; @@ -914,51 +962,97 @@ class RequestTestHandler : public TestHandler, using TestHandler::DestroyTest; RequestTestHandler(RequestTestMode test_mode, + ContextTestMode context_mode, bool test_in_browser, const char* test_url) : test_mode_(test_mode), + context_mode_(context_mode), test_in_browser_(test_in_browser), test_url_(test_url), - test_runner_(this, true) { + test_runner_(new RequestTestRunner(this, true)) { } void RunTest() override { - EXPECT_TRUE(test_url_ != NULL); - AddResource(test_url_, "TEST", "text/html"); + // Get or create the request context. + if (context_mode_ == CONTEXT_GLOBAL) { + CefRefPtr request_context = + CefRequestContext::GetGlobalContext(); + EXPECT_TRUE(request_context.get()); + test_runner_->SetRequestContext(request_context); - base::WaitableEvent event(false, false); - SetTestCookie(&event); - event.Wait(); + // Continue the test now. + RunTestContinue(); + } else { + // Don't end the test until the temporary request context has been + // destroyed. + SetSignalCompletionWhenAllBrowsersClose(false); + + CefRequestContextSettings settings; + + if (context_mode_ == CONTEXT_ONDISK) { + EXPECT_TRUE(context_tmpdir_.CreateUniqueTempDir()); + CefString(&settings.cache_path) = context_tmpdir_.path().value(); + } + + // Create a new temporary request context. + CefRefPtr request_context = + CefRequestContext::CreateContext(settings, + new RequestContextHandler(this)); + EXPECT_TRUE(request_context.get()); + test_runner_->SetRequestContext(request_context); + + // Set the schemes that are allowed to store cookies. + std::vector supported_schemes; + supported_schemes.push_back("http"); + supported_schemes.push_back("https"); + supported_schemes.push_back(kRequestScheme); + + // Continue the test once supported schemes has been set. + request_context->GetDefaultCookieManager(NULL)->SetSupportedSchemes( + supported_schemes, new SupportedSchemesCompletionCallback(this)); + } + } + + void RunTestContinue() { + if (!CefCurrentlyOn(TID_UI)) { + CefPostTask(TID_UI, + base::Bind(&RequestTestHandler::RunTestContinue, this)); + return; + } // Setup the test. This will create the objects that we test against and // register any scheme handlers. - test_runner_.SetupTest(test_mode_); + test_runner_->SetupTest(test_mode_); - CreateBrowser(test_url_); + base::WaitableEvent event(false, false); + SetTestCookie(test_runner_->GetRequestContext(), &event); + + if (test_in_browser_) { + // Run the test now. + test_runner_->RunTest(test_mode_); + } else { + EXPECT_TRUE(test_url_ != NULL); + AddResource(test_url_, "TEST", "text/html"); + + // Create a browser to run the test in the renderer process. + CreateBrowser(test_url_, test_runner_->GetRequestContext()); + } // Time out the test after a reasonable period of time. SetTestTimeout(); } - CefRefPtr CreateTestMessage() { - CefRefPtr msg = - CefProcessMessage::Create(kRequestTestMsg); - EXPECT_TRUE(msg->GetArgumentList()->SetInt(0, test_mode_)); - return msg; - } - void OnLoadEnd(CefRefPtr browser, CefRefPtr frame, int httpStatusCode) override { + EXPECT_FALSE(test_in_browser_); if (frame->IsMain()) { - if (test_in_browser_) { - // Run the test in the browser process. - test_runner_.RunTest(test_mode_); - } else { - // Send a message to the renderer process to run the test. - EXPECT_TRUE(browser->SendProcessMessage(PID_RENDERER, - CreateTestMessage())); - } + CefRefPtr test_message = + CefProcessMessage::Create(kRequestTestMsg); + EXPECT_TRUE(test_message->GetArgumentList()->SetInt(0, test_mode_)); + + // Send a message to the renderer process to run the test. + EXPECT_TRUE(browser->SendProcessMessage(PID_RENDERER, test_message)); } } @@ -970,6 +1064,7 @@ class RequestTestHandler : public TestHandler, EXPECT_EQ(PID_RENDERER, source_process); EXPECT_TRUE(message.get()); EXPECT_TRUE(message->IsReadOnly()); + EXPECT_FALSE(test_in_browser_); got_message_.yes(); @@ -977,7 +1072,7 @@ class RequestTestHandler : public TestHandler, got_success_.yes(); // Test is complete. - DestroyTest(test_runner_.settings_); + DestroyTest(test_runner_->settings_); return true; } @@ -986,62 +1081,69 @@ class RequestTestHandler : public TestHandler, base::WaitableEvent event(false, false); bool has_save_cookie = false; - TestSaveCookie(&event, &has_save_cookie); - if (settings.expect_save_cookie) - EXPECT_TRUE(has_save_cookie); - else - EXPECT_FALSE(has_save_cookie); - - ClearTestCookie(&event); - event.Wait(); + GetTestCookie(test_runner_->GetRequestContext(), &event, &has_save_cookie); + EXPECT_EQ(settings.expect_save_cookie, has_save_cookie); TestHandler::DestroyTest(); + + // Need to call TestComplete() explicitly if testing in the browser and + // using the global context. Otherwise, TestComplete() will be called when + // the browser is destroyed (for render test + global context) or when the + // temporary context is destroyed. + const bool call_test_complete = + (test_in_browser_ && context_mode_ == CONTEXT_GLOBAL); + + // Release our reference to the context. Do not access any object members + // after this call because |this| might be deleted. + test_runner_->SetRequestContext(NULL); + + if (call_test_complete) + TestComplete(); } - protected: - // Set a cookie so that we can test if it's sent with the request. - void SetTestCookie(base::WaitableEvent* event) { - if (CefCurrentlyOn(TID_IO)) { - CefRefPtr cookie_manager = - CefCookieManager::GetGlobalManager(); - EXPECT_TRUE(cookie_manager.get()); - - CefCookie cookie; - CefString(&cookie.name) = kRequestSendCookieName; - CefString(&cookie.value) = "send-cookie-value"; - CefString(&cookie.domain) = kRequestHost; - CefString(&cookie.path) = "/"; - cookie.has_expires = false; - EXPECT_TRUE(cookie_manager->SetCookie(kRequestOrigin, cookie)); - event->Signal(); - } else { - // Execute on the IO thread. - CefPostTask(TID_IO, - base::Bind(&RequestTestHandler::SetTestCookie, this, event)); + private: + // Used with temporary request contexts to signal test completion once the + // temporary context has been destroyed. + class RequestContextHandler : public CefRequestContextHandler { + public: + explicit RequestContextHandler(CefRefPtr test_handler) + : test_handler_(test_handler) { } - } - - // Remove the cookie that we set above. - void ClearTestCookie(base::WaitableEvent* event) { - if (CefCurrentlyOn(TID_IO)) { - CefRefPtr cookie_manager = - CefCookieManager::GetGlobalManager(); - EXPECT_TRUE(cookie_manager.get()); - EXPECT_TRUE(cookie_manager->DeleteCookies(kRequestOrigin, - kRequestSendCookieName)); - event->Signal(); - } else { - // Execute on the IO thread. - CefPostTask(TID_IO, - base::Bind(&RequestTestHandler::ClearTestCookie, this, event)); + ~RequestContextHandler() override { + test_handler_->TestComplete(); } - } + + private: + CefRefPtr test_handler_; + + IMPLEMENT_REFCOUNTING(RequestContextHandler); + }; + + // Continue the rest once supported schemes have been set. + class SupportedSchemesCompletionCallback : public CefCompletionCallback { + public: + explicit SupportedSchemesCompletionCallback( + CefRefPtr test_handler) + : test_handler_(test_handler) { + } + void OnComplete() override { + test_handler_->RunTestContinue(); + } + + private: + CefRefPtr test_handler_; + + IMPLEMENT_REFCOUNTING(SupportedSchemesCompletionCallback); + }; RequestTestMode test_mode_; + ContextTestMode context_mode_; bool test_in_browser_; const char* test_url_; - RequestTestRunner test_runner_; + scoped_refptr test_runner_; + + base::ScopedTempDir context_tmpdir_; public: // Only used when the test runs in the render process. @@ -1069,10 +1171,11 @@ void RegisterURLRequestCustomSchemes( // Helpers for defining URLRequest tests. -#define REQ_TEST_EX(name, test_mode, test_in_browser, test_url) \ +#define REQ_TEST_EX(name, test_mode, context_mode, test_in_browser, test_url) \ TEST(URLRequestTest, name) { \ CefRefPtr handler = \ - new RequestTestHandler(test_mode, test_in_browser, test_url); \ + new RequestTestHandler(test_mode, context_mode, test_in_browser, \ + test_url); \ handler->ExecuteTest(); \ if (!test_in_browser) { \ EXPECT_TRUE(handler->got_message_); \ @@ -1081,28 +1184,38 @@ void RegisterURLRequestCustomSchemes( ReleaseAndWaitForDestructor(handler); \ } -#define REQ_TEST(name, test_mode, test_in_browser) \ - REQ_TEST_EX(name, test_mode, test_in_browser, kRequestTestUrl) +#define REQ_TEST(name, test_mode, context_mode, test_in_browser) \ + REQ_TEST_EX(name, test_mode, context_mode, test_in_browser, kRequestTestUrl) // Define the tests. -REQ_TEST(BrowserGET, REQTEST_GET, true); -REQ_TEST(BrowserGETNoData, REQTEST_GET_NODATA, true); -REQ_TEST(BrowserGETAllowCookies, REQTEST_GET_ALLOWCOOKIES, true); -REQ_TEST(BrowserGETRedirect, REQTEST_GET_REDIRECT, true); -REQ_TEST(BrowserPOST, REQTEST_POST, true); -REQ_TEST(BrowserPOSTFile, REQTEST_POST_FILE, true); -REQ_TEST(BrowserPOSTWithProgress, REQTEST_POST_WITHPROGRESS, true); -REQ_TEST(BrowserHEAD, REQTEST_HEAD, true); - -REQ_TEST(RendererGET, REQTEST_GET, false); -REQ_TEST(RendererGETNoData, REQTEST_GET_NODATA, false); -REQ_TEST(RendererGETAllowCookies, REQTEST_GET_ALLOWCOOKIES, false); -REQ_TEST(RendererGETRedirect, REQTEST_GET_REDIRECT, false); -REQ_TEST(RendererPOST, REQTEST_POST, false); -REQ_TEST(RendererPOSTWithProgress, REQTEST_POST_WITHPROGRESS, false); -REQ_TEST(RendererHEAD, REQTEST_HEAD, false); +#define REQ_TEST_SET(suffix, context_mode) \ + REQ_TEST(BrowserGET##suffix, REQTEST_GET, context_mode, true); \ + REQ_TEST(BrowserGETNoData##suffix, REQTEST_GET_NODATA, context_mode, true); \ + REQ_TEST(BrowserGETAllowCookies##suffix, \ + REQTEST_GET_ALLOWCOOKIES, context_mode, true); \ + REQ_TEST(BrowserGETRedirect##suffix, \ + REQTEST_GET_REDIRECT, context_mode, true); \ + REQ_TEST(BrowserPOST##suffix, REQTEST_POST, context_mode, true); \ + REQ_TEST(BrowserPOSTFile##suffix, REQTEST_POST_FILE, context_mode, true); \ + REQ_TEST(BrowserPOSTWithProgress##suffix, \ + REQTEST_POST_WITHPROGRESS, context_mode, true); \ + REQ_TEST(BrowserHEAD##suffix, REQTEST_HEAD, context_mode, true); \ + REQ_TEST(RendererGET##suffix, REQTEST_GET, context_mode, false); \ + REQ_TEST(RendererGETNoData##suffix, \ + REQTEST_GET_NODATA, context_mode, false); \ + REQ_TEST(RendererGETAllowCookies##suffix, \ + REQTEST_GET_ALLOWCOOKIES, context_mode, false); \ + REQ_TEST(RendererGETRedirect##suffix, \ + REQTEST_GET_REDIRECT, context_mode, false); \ + REQ_TEST(RendererPOST##suffix, REQTEST_POST, context_mode, false); \ + REQ_TEST(RendererPOSTWithProgress##suffix, \ + REQTEST_POST_WITHPROGRESS, context_mode, false); \ + REQ_TEST(RendererHEAD##suffix, REQTEST_HEAD, context_mode, false) +REQ_TEST_SET(ContextGlobal, CONTEXT_GLOBAL); +REQ_TEST_SET(ContextInMemory, CONTEXT_INMEMORY); +REQ_TEST_SET(ContextOnDisk, CONTEXT_ONDISK); namespace { @@ -1163,7 +1276,7 @@ class InvalidURLTestClient : public CefURLRequestClient { request->SetMethod("GET"); request->SetURL("foo://invalidurl"); - CefURLRequest::Create(request, this); + CefURLRequest::Create(request, this, NULL); } void CompleteOnUIThread() {