diff --git a/cef.gyp b/cef.gyp index 5a8350dc2..3b58efac3 100644 --- a/cef.gyp +++ b/cef.gyp @@ -679,6 +679,8 @@ 'libcef/browser_persistent_cookie_store.h', 'libcef/browser_request_context.cc', 'libcef/browser_request_context.h', + 'libcef/browser_request_context_proxy.cc', + 'libcef/browser_request_context_proxy.h', 'libcef/browser_resource_loader_bridge.cc', 'libcef/browser_resource_loader_bridge.h', 'libcef/browser_settings.cc', @@ -720,7 +722,10 @@ 'libcef/cef_time.cc', 'libcef/cef_time_util.h', 'libcef/command_line_impl.cc', - 'libcef/cookie_impl.cc', + 'libcef/cookie_manager_impl.cc', + 'libcef/cookie_manager_impl.h', + 'libcef/cookie_store_proxy.cc', + 'libcef/cookie_store_proxy.h', 'libcef/drag_data_impl.cc', 'libcef/drag_data_impl.h', 'libcef/drag_download_file.cc', diff --git a/cef_paths.gypi b/cef_paths.gypi index 630bdf6f1..5c9075fdd 100644 --- a/cef_paths.gypi +++ b/cef_paths.gypi @@ -102,6 +102,8 @@ 'libcef_dll/cpptoc/command_line_cpptoc.h', 'libcef_dll/ctocpp/content_filter_ctocpp.cc', 'libcef_dll/ctocpp/content_filter_ctocpp.h', + 'libcef_dll/cpptoc/cookie_manager_cpptoc.cc', + 'libcef_dll/cpptoc/cookie_manager_cpptoc.h', 'libcef_dll/ctocpp/cookie_visitor_ctocpp.cc', 'libcef_dll/ctocpp/cookie_visitor_ctocpp.h', 'libcef_dll/cpptoc/domdocument_cpptoc.cc', @@ -208,6 +210,8 @@ 'libcef_dll/ctocpp/command_line_ctocpp.h', 'libcef_dll/cpptoc/content_filter_cpptoc.cc', 'libcef_dll/cpptoc/content_filter_cpptoc.h', + 'libcef_dll/ctocpp/cookie_manager_ctocpp.cc', + 'libcef_dll/ctocpp/cookie_manager_ctocpp.h', 'libcef_dll/cpptoc/cookie_visitor_cpptoc.cc', 'libcef_dll/cpptoc/cookie_visitor_cpptoc.h', 'libcef_dll/ctocpp/domdocument_ctocpp.cc', diff --git a/include/capi/cef_cookie_capi.h b/include/capi/cef_cookie_capi.h index cf5dd535c..941652832 100644 --- a/include/capi/cef_cookie_capi.h +++ b/include/capi/cef_cookie_capi.h @@ -46,49 +46,79 @@ extern "C" { /// -// Visit all cookies. The returned cookies are ordered by longest path, then by -// earliest creation date. Returns false (0) if cookies cannot be accessed. +// Structure used for managing cookies. The functions of this structure may be +// called on any thread unless otherwise indicated. /// -CEF_EXPORT int cef_visit_all_cookies(struct _cef_cookie_visitor_t* visitor); +typedef struct _cef_cookie_manager_t { + /// + // Base structure. + /// + cef_base_t base; + + /// + // Visit all cookies. 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. + /// + int (CEF_CALLBACK *visit_url_cookies)(struct _cef_cookie_manager_t* self, + const cef_string_t* url, int includeHttpOnly, + struct _cef_cookie_visitor_t* visitor); + + /// + // 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. + /// + int (CEF_CALLBACK *set_cookie)(struct _cef_cookie_manager_t* self, + const cef_string_t* url, const struct _cef_cookie_t* cookie); + + /// + // Delete all cookies that match the specified parameters. If both |url| and + // values |cookie_name| 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. + /// + int (CEF_CALLBACK *delete_cookies)(struct _cef_cookie_manager_t* self, + const cef_string_t* url, const cef_string_t* cookie_name); + + /// + // Sets the directory path that will be used for storing cookie data. If + // |path| is NULL data will be stored in memory only. 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); +} cef_cookie_manager_t; + /// -// 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. +// Returns the global cookie manager. By default data will be stored at +// CefSettings.cache_path if specified or in memory otherwise. /// -CEF_EXPORT int cef_visit_url_cookies(const cef_string_t* url, - int includeHttpOnly, struct _cef_cookie_visitor_t* visitor); +CEF_EXPORT cef_cookie_manager_t* cef_cookie_manager_get_global_manager(); /// -// 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. +// Creates a new cookie manager. If |path| is NULL data will be stored in memory +// only. Returns NULL if creation fails. /// -CEF_EXPORT int cef_set_cookie(const cef_string_t* url, - const struct _cef_cookie_t* cookie); +CEF_EXPORT cef_cookie_manager_t* cef_cookie_manager_create_manager( + const cef_string_t* path); -/// -// Delete all cookies that match the specified parameters. If both |url| and -// |cookie_name| are specified all host and domain cookies matching both values -// 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. -/// -CEF_EXPORT int cef_delete_cookies(const cef_string_t* url, - const cef_string_t* cookie_name); - -/// -// Sets the directory path that will be used for storing cookie data. If |path| -// is NULL data will be stored in memory only. By default the cookie path is the -// same as the cache path. Returns false (0) if cookies cannot be accessed. -/// -CEF_EXPORT int cef_set_cookie_path(const cef_string_t* path); /// // Structure to implement for visiting cookie values. The functions of this diff --git a/include/capi/cef_frame_capi.h b/include/capi/cef_frame_capi.h index 763cb9a74..4009ac63c 100644 --- a/include/capi/cef_frame_capi.h +++ b/include/capi/cef_frame_capi.h @@ -174,8 +174,7 @@ typedef struct _cef_frame_t { cef_string_userfree_t (CEF_CALLBACK *get_name)(struct _cef_frame_t* self); /// - // Returns the globally unique identifier for this frame. This function should - // only be called on the UI thread. + // Returns the globally unique identifier for this frame. /// int64 (CEF_CALLBACK *get_identifier)(struct _cef_frame_t* self); @@ -186,8 +185,7 @@ typedef struct _cef_frame_t { struct _cef_frame_t* (CEF_CALLBACK *get_parent)(struct _cef_frame_t* self); /// - // Returns the URL currently loaded in this frame. This function should only - // be called on the UI thread. + // Returns the URL currently loaded in this frame. /// // The resulting string must be freed by calling cef_string_userfree_free(). cef_string_userfree_t (CEF_CALLBACK *get_url)(struct _cef_frame_t* self); diff --git a/include/capi/cef_request_handler_capi.h b/include/capi/cef_request_handler_capi.h index 3fe0ab48f..3414001b9 100644 --- a/include/capi/cef_request_handler_capi.h +++ b/include/capi/cef_request_handler_capi.h @@ -139,6 +139,16 @@ typedef struct _cef_request_handler_t { struct _cef_browser_t* browser, int isProxy, const cef_string_t* host, int port, const cef_string_t* realm, const cef_string_t* scheme, cef_string_t* username, cef_string_t* password); + + /// + // Called on the IO thread to retrieve the cookie manager. |main_url| is the + // URL of the top-level frame. Cookies managers can be unique per browser or + // shared across multiple browsers. The global cookie manager will be used if + // this function returns NULL. + /// + struct _cef_cookie_manager_t* (CEF_CALLBACK *get_cookie_manager)( + struct _cef_request_handler_t* self, struct _cef_browser_t* browser, + const cef_string_t* main_url); } cef_request_handler_t; diff --git a/include/capi/cef_scheme_capi.h b/include/capi/cef_scheme_capi.h index 039efa8df..b3806580b 100644 --- a/include/capi/cef_scheme_capi.h +++ b/include/capi/cef_scheme_capi.h @@ -127,7 +127,8 @@ typedef struct _cef_scheme_handler_factory_t { /// // Return a new scheme handler instance to handle the request. |browser| will // be the browser window that initiated the request. If the request was - // initiated using the cef_web_urlrequest_t API |browser| will be NULL. + // initiated using the cef_web_urlrequest_t API |browser| will be NULL. The + // |request| object passed to this function will not contain cookie data. /// struct _cef_scheme_handler_t* (CEF_CALLBACK *create)( struct _cef_scheme_handler_factory_t* self, diff --git a/include/cef_cookie.h b/include/cef_cookie.h index 932bab20f..fa5086034 100644 --- a/include/cef_cookie.h +++ b/include/cef_cookie.h @@ -1,4 +1,4 @@ -// Copyright (c) 2011 Marshall A. Greenblatt. All rights reserved. +// Copyright (c) 2012 Marshall A. Greenblatt. All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are @@ -42,53 +42,78 @@ class CefCookieVisitor; -/// -// Visit all cookies. The returned cookies are ordered by longest path, then by -// earliest creation date. Returns false if cookies cannot be accessed. -/// -/*--cef()--*/ -bool CefVisitAllCookies(CefRefPtr visitor); /// -// 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. +// Class used for managing cookies. The methods of this class may be called on +// any thread unless otherwise indicated. /// -/*--cef()--*/ -bool CefVisitUrlCookies(const CefString& url, bool includeHttpOnly, - CefRefPtr visitor); +/*--cef(source=library)--*/ +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. + /// + /*--cef()--*/ + static CefRefPtr GetGlobalManager(); -/// -// 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. -/// -/*--cef()--*/ -bool CefSetCookie(const CefString& url, const CefCookie& cookie); + /// + // Creates a new cookie manager. If |path| is empty data will be stored in + // memory only. Returns NULL if creation fails. + /// + /*--cef(optional_param=path)--*/ + static CefRefPtr CreateManager(const CefString& path); -/// -// Delete all cookies that match the specified parameters. If both |url| and -// |cookie_name| are specified all host and domain cookies matching both values -// 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. -/// -/*--cef(optional_param=url,optional_param=cookie_name)--*/ -bool CefDeleteCookies(const CefString& url, const CefString& cookie_name); + /// + // Visit all cookies. 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; -/// -// Sets the directory path that will be used for storing cookie data. If |path| -// is empty data will be stored in memory only. By default the cookie path is -// the same as the cache path. Returns false if cookies cannot be accessed. -/// -/*--cef(optional_param=path)--*/ -bool CefSetCookiePath(const CefString& path); + /// + // 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. + /// + /*--cef()--*/ + 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. + /// + /*--cef()--*/ + virtual bool SetCookie(const CefString& url, const CefCookie& cookie) =0; + + /// + // Delete all cookies that match the specified parameters. If both |url| and + // values |cookie_name| 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. + /// + /*--cef(optional_param=url,optional_param=cookie_name)--*/ + virtual bool DeleteCookies(const CefString& url, + const CefString& cookie_name) =0; + + /// + // Sets the directory path that will be used for storing cookie data. If + // |path| is empty data will be stored in memory only. Returns false if + // cookies cannot be accessed. + /// + /*--cef(optional_param=path)--*/ + virtual bool SetStoragePath(const CefString& path) =0; +}; /// diff --git a/include/cef_frame.h b/include/cef_frame.h index edc40e00d..f0ac6ef7a 100644 --- a/include/cef_frame.h +++ b/include/cef_frame.h @@ -179,8 +179,7 @@ class CefFrame : public virtual CefBase { virtual CefString GetName() =0; /// - // Returns the globally unique identifier for this frame. This method should - // only be called on the UI thread. + // Returns the globally unique identifier for this frame. /// /*--cef()--*/ virtual int64 GetIdentifier() =0; @@ -193,8 +192,7 @@ class CefFrame : public virtual CefBase { virtual CefRefPtr GetParent() =0; /// - // Returns the URL currently loaded in this frame. This method should only be - // called on the UI thread. + // Returns the URL currently loaded in this frame. /// /*--cef()--*/ virtual CefString GetURL() =0; diff --git a/include/cef_request_handler.h b/include/cef_request_handler.h index ceb005de0..0ee758f07 100644 --- a/include/cef_request_handler.h +++ b/include/cef_request_handler.h @@ -40,6 +40,7 @@ #include "include/cef_base.h" #include "include/cef_browser.h" +#include "include/cef_cookie.h" #include "include/cef_download_handler.h" #include "include/cef_frame.h" #include "include/cef_content_filter.h" @@ -154,6 +155,17 @@ class CefRequestHandler : public virtual CefBase { const CefString& scheme, CefString& username, CefString& password) { return false; } + + /// + // Called on the IO thread to retrieve the cookie manager. |main_url| is the + // URL of the top-level frame. Cookies managers can be unique per browser or + // shared across multiple browsers. The global cookie manager will be used if + // this method returns NULL. + /// + /*--cef()--*/ + virtual CefRefPtr GetCookieManager( + CefRefPtr browser, + const CefString& main_url) { return NULL; } }; #endif // CEF_INCLUDE_CEF_REQUEST_HANDLER_H_ diff --git a/include/cef_scheme.h b/include/cef_scheme.h index 939dba72a..1bd9a39b2 100644 --- a/include/cef_scheme.h +++ b/include/cef_scheme.h @@ -132,7 +132,8 @@ class CefSchemeHandlerFactory : public virtual CefBase { /// // Return a new scheme handler instance to handle the request. |browser| will // be the browser window that initiated the request. If the request was - // initiated using the CefWebURLRequest API |browser| will be NULL. + // initiated using the CefWebURLRequest API |browser| will be NULL. The + // |request| object passed to this method will not contain cookie data. /// /*--cef()--*/ virtual CefRefPtr Create(CefRefPtr browser, diff --git a/libcef/browser_impl.cc b/libcef/browser_impl.cc index 06330ee0a..d5d2f94c1 100644 --- a/libcef/browser_impl.cc +++ b/libcef/browser_impl.cc @@ -169,7 +169,6 @@ CefBrowserImpl::CefBrowserImpl(const CefWindowInfo& windowInfo, can_go_forward_(false), has_document_(false), is_dropping_(false), - main_frame_(NULL), unique_id_(0) #if defined(OS_WIN) , opener_was_disabled_by_modal_loop_(false), @@ -180,11 +179,17 @@ CefBrowserImpl::CefBrowserImpl(const CefWindowInfo& windowInfo, popup_delegate_.reset(new BrowserWebViewDelegate(this)); nav_controller_.reset(new BrowserNavigationController(this)); + request_context_proxy_ = + new BrowserRequestContextProxy(_Context->request_context(), this); + if (!file_system_root_.CreateUniqueTempDir()) { LOG(WARNING) << "Failed to create a temp dir for the filesystem." "FileSystem feature will be disabled."; DCHECK(file_system_root_.path().empty()); } + + // Create the singleton main frame reference. + main_frame_ = new CefFrameImpl(this, 0, CefString(), CefString()); } void CefBrowserImpl::CloseBrowser() { @@ -205,7 +210,7 @@ void CefBrowserImpl::GoForward() { } void CefBrowserImpl::Reload() { - CefThread::PostTask(CefThread::UI, FROM_HERE, + CefThread::PostTask(CefThread::UI, FROM_HERE, base::Bind(&CefBrowserImpl::UIT_HandleActionView, this, MENU_ID_NAV_RELOAD)); } @@ -231,6 +236,10 @@ void CefBrowserImpl::SetFocus(bool enable) { } } +CefRefPtr CefBrowserImpl::GetMainFrame() { + return GetMainCefFrame(0, GURL()).get(); +} + CefRefPtr CefBrowserImpl::GetFocusedFrame() { // Verify that this method is being called on the UI thread. if (!CefThread::CurrentlyOn(CefThread::UI)) { @@ -575,19 +584,6 @@ void CefBrowserImpl::ExecuteJavaScript(CefRefPtr frame, scriptUrl, startLine)); } -int64 CefBrowserImpl::GetIdentifier(CefRefPtr frame) { - // Verify that this method is being called on the UI thread. - if (!CefThread::CurrentlyOn(CefThread::UI)) { - NOTREACHED() << "called on invalid thread"; - return 0; - } - - WebFrame* web_frame = UIT_GetWebFrame(frame); - if (web_frame) - return web_frame->identifier(); - return 0; -} - CefRefPtr CefBrowserImpl::GetParent(CefRefPtr frame) { // Verify that this method is being called on the UI thread. if (!CefThread::CurrentlyOn(CefThread::UI)) { @@ -606,77 +602,91 @@ CefRefPtr CefBrowserImpl::GetParent(CefRefPtr frame) { return NULL; } -CefString CefBrowserImpl::GetURL(CefRefPtr frame) { - // Verify that this method is being called on the UI thread. - if (!CefThread::CurrentlyOn(CefThread::UI)) { - NOTREACHED() << "called on invalid thread"; - return CefString(); - } +CefRefPtr CefBrowserImpl::GetCefFrame(int64 id) { + AutoLock lock_scope(this); + FrameMap::const_iterator it = frames_.find(id); + if (it != frames_.end()) + return it->second; - WebFrame* web_frame = UIT_GetWebFrame(frame); - if (web_frame) - return std::string(web_frame->document().url().spec()); - return CefString(); + return NULL; } -CefRefPtr CefBrowserImpl::GetCefFrame(const CefString& name) { - CefRefPtr cef_frame; +CefRefPtr CefBrowserImpl::GetOrCreateCefFrame( + int64 id, + const CefString& name, + const GURL& url) { + CefRefPtr cef_frame; if (name.empty()) { // Use the single main frame reference. - cef_frame = GetMainCefFrame(); + cef_frame = GetMainCefFrame(id, url); } else { // Locate or create the appropriate named reference. AutoLock lock_scope(this); - FrameMap::const_iterator it = frames_.find(name); + FrameMap::const_iterator it = frames_.find(id); if (it != frames_.end()) { cef_frame = it->second; + cef_frame->set_url(url.spec()); } else { - cef_frame = new CefFrameImpl(this, name); - frames_.insert(std::make_pair(name, cef_frame.get())); + cef_frame = new CefFrameImpl(this, id, name, url.spec()); + frames_.insert(std::make_pair(id, cef_frame.get())); } } return cef_frame; } -void CefBrowserImpl::RemoveCefFrame(const CefString& name) { +void CefBrowserImpl::RemoveCefFrame(int64 id) { AutoLock lock_scope(this); - if (name.empty()) { - // Clear the single main frame reference. - main_frame_ = NULL; - } else { - // Remove the appropriate named reference. - FrameMap::iterator it = frames_.find(name); - if (it != frames_.end()) - frames_.erase(it); - } + // Remove the appropriate reference. + FrameMap::iterator it = frames_.find(id); + if (it != frames_.end()) + frames_.erase(it); } -CefRefPtr CefBrowserImpl::GetMainCefFrame() { - // Return the single main frame reference. - AutoLock lock_scope(this); - if (main_frame_ == NULL) - main_frame_ = new CefFrameImpl(this, CefString()); +CefRefPtr CefBrowserImpl::GetMainCefFrame(int64 id, + const GURL& url) { + if (id != 0) + main_frame_->set_id(id); + + main_frame_->set_url(url.spec()); + return main_frame_; } CefRefPtr CefBrowserImpl::UIT_GetCefFrame(WebFrame* frame) { REQUIRE_UIT(); - CefRefPtr cef_frame; + CefRefPtr cef_frame; + GURL url = frame->document().url(); if (frame->parent() == 0) { // Use the single main frame reference. - cef_frame = GetMainCefFrame(); + cef_frame = GetMainCefFrame(frame->identifier(), url); } else { - // Locate or create the appropriate named reference. + // Locate or create the appropriate reference. CefString name = string16(frame->name()); DCHECK(!name.empty()); - cef_frame = GetCefFrame(name); + cef_frame = GetOrCreateCefFrame(frame->identifier(), name, url); } - return cef_frame; + return cef_frame.get(); +} + +void CefBrowserImpl::UIT_UpdateCefFrame(WebKit::WebFrame* frame) { + REQUIRE_UIT(); + + GURL url = frame->document().url(); + + if (frame->parent() == 0) { + // Update the single main frame reference. + GetMainCefFrame(frame->identifier(), url); + } else { + // Update the appropriate reference if it currently exists. + CefRefPtr cef_frame = GetCefFrame(frame->identifier()); + if (cef_frame.get()) + cef_frame->set_url(url.spec()); + } } WebFrame* CefBrowserImpl::UIT_GetMainWebFrame() { @@ -751,6 +761,9 @@ void CefBrowserImpl::UIT_DestroyBrowser() { // Remove the reference to the window handle. UIT_ClearMainWndHandle(); + main_frame_ = NULL; + request_context_proxy_ = NULL; + // Remove the reference added in UIT_CreateBrowser(). Release(); @@ -1539,6 +1552,16 @@ bool CefBrowserImpl::has_document() { return has_document_; } +void CefBrowserImpl::set_pending_url(const GURL& url) { + AutoLock lock_scope(this); + pending_url_ = url; +} + +GURL CefBrowserImpl::pending_url() { + AutoLock lock_scope(this); + return pending_url_; +} + void CefBrowserImpl::UIT_CreateDevToolsClient(BrowserDevToolsAgent *agent) { dev_tools_client_.reset(new BrowserDevToolsClient(this, agent)); } @@ -1554,12 +1577,19 @@ void CefBrowserImpl::UIT_DestroyDevToolsClient() { // CefFrameImpl -CefFrameImpl::CefFrameImpl(CefBrowserImpl* browser, const CefString& name) - : browser_(browser), name_(name) { +CefFrameImpl::CefFrameImpl(CefBrowserImpl* browser, + int64 id, + const CefString& name, + const CefString& url) + : browser_(browser), + id_(id), + name_(name), + url_(url) { } CefFrameImpl::~CefFrameImpl() { - browser_->RemoveCefFrame(name_); + if (!IsMain()) + browser_->RemoveCefFrame(id_); } bool CefFrameImpl::IsFocused() { @@ -1574,6 +1604,16 @@ bool CefFrameImpl::IsFocused() { browser_->UIT_GetWebView()->focusedFrame())); } +int64 CefFrameImpl::GetIdentifier() { + base::AutoLock lock_scope(lock_); + return id_; +} + +CefString CefFrameImpl::GetURL() { + base::AutoLock lock_scope(lock_); + return url_; +} + void CefFrameImpl::VisitDOM(CefRefPtr visitor) { if (!visitor.get()) { NOTREACHED() << "invalid parameter"; @@ -1600,3 +1640,13 @@ CefRefPtr CefFrameImpl::GetV8Context() { return NULL; } } + +void CefFrameImpl::set_id(int64 id) { + base::AutoLock lock_scope(lock_); + id_ = id; +} + +void CefFrameImpl::set_url(const CefString& url) { + base::AutoLock lock_scope(lock_); + url_ = url; +} diff --git a/libcef/browser_impl.h b/libcef/browser_impl.h index 576847d5d..375effb0f 100644 --- a/libcef/browser_impl.h +++ b/libcef/browser_impl.h @@ -20,6 +20,7 @@ #include "libcef/browser_devtools_client.h" #include "libcef/browser_webview_delegate.h" #include "libcef/browser_navigation_controller.h" +#include "libcef/browser_request_context_proxy.h" #include "libcef/cef_thread.h" #include "libcef/tracker.h" #if defined(OS_WIN) @@ -36,6 +37,8 @@ namespace WebKit { class WebView; } +class CefFrameImpl; + #define BUFFER_SIZE 32768 @@ -83,8 +86,7 @@ class CefBrowserImpl : public CefBrowser { virtual bool IsPopup() OVERRIDE { return is_popup(); } virtual bool HasDocument() OVERRIDE { return has_document(); } virtual CefRefPtr GetClient() OVERRIDE { return client_; } - virtual CefRefPtr GetMainFrame() OVERRIDE - { return GetMainCefFrame(); } + virtual CefRefPtr GetMainFrame() OVERRIDE; virtual CefRefPtr GetFocusedFrame() OVERRIDE; virtual CefRefPtr GetFrame(const CefString& name) OVERRIDE; virtual void GetFrameNames(std::vector& names) OVERRIDE; @@ -139,24 +141,25 @@ class CefBrowserImpl : public CefBrowser { const CefString& jsCode, const CefString& scriptUrl, int startLine); - int64 GetIdentifier(CefRefPtr frame); CefRefPtr GetParent(CefRefPtr frame); - CefString GetURL(CefRefPtr frame); // CefFrames are light-weight objects managed by the browser and loosely - // coupled to a WebFrame object by name. If a CefFrame object does not - // already exist for the specified name one will be created. There is no - // guarantee that the same CefFrame object will be returned across different - // calls to this function. - CefRefPtr GetCefFrame(const CefString& name); - void RemoveCefFrame(const CefString& name); - CefRefPtr GetMainCefFrame(); + // coupled to a WebFrame object by id. If a CefFrame object does not already + // exist for the specified id one will be created. There is no guarantee that + // the same CefFrame object will be returned across different calls to this + // function. + CefRefPtr GetCefFrame(int64 id); + CefRefPtr GetOrCreateCefFrame(int64 id, const CefString& name, + const GURL& url); + void RemoveCefFrame(int64 id); + CefRefPtr GetMainCefFrame(int64 id, const GURL& url); //////////////////////////////////////////////////////////// // ALL UIT_* METHODS MUST ONLY BE CALLED ON THE UI THREAD // //////////////////////////////////////////////////////////// CefRefPtr UIT_GetCefFrame(WebKit::WebFrame* frame); + void UIT_UpdateCefFrame(WebKit::WebFrame* frame); // Return the main WebFrame object. WebKit::WebFrame* UIT_GetMainWebFrame(); @@ -335,6 +338,10 @@ class CefBrowserImpl : public CefBrowser { void set_has_document(bool has_document); bool has_document(); + // URL currently being loaded in the main frame. + void set_pending_url(const GURL& url); + GURL pending_url(); + void set_is_dropping(bool is_dropping) { is_dropping_ = is_dropping; } bool is_dropping() { return is_dropping_; } @@ -349,6 +356,10 @@ class CefBrowserImpl : public CefBrowser { void set_popup_rect(const gfx::Rect& rect) { popup_rect_ = rect; } + net::URLRequestContext* request_context_proxy() { + return request_context_proxy_; + } + static bool ImplementsThreadSafeReferenceCounting() { return true; } protected: @@ -375,12 +386,15 @@ class CefBrowserImpl : public CefBrowser { scoped_ptr dev_tools_agent_; scoped_ptr dev_tools_client_; + scoped_refptr request_context_proxy_; + CefString title_; double zoom_level_; bool can_go_back_; bool can_go_forward_; bool has_document_; + GURL pending_url_; // True if a drop action is occuring. bool is_dropping_; @@ -394,9 +408,12 @@ class CefBrowserImpl : public CefBrowser { bool internal_modal_message_loop_is_active_; #endif - typedef std::map FrameMap; + // Map of frame id to reference. + typedef std::map FrameMap; FrameMap frames_; - CefFrame* main_frame_; + + // Singleton main frame reference. + CefRefPtr main_frame_; typedef std::map > FrameObjectMap; @@ -416,7 +433,10 @@ class CefBrowserImpl : public CefBrowser { // Implementation of CefFrame. class CefFrameImpl : public CefFrame { public: - CefFrameImpl(CefBrowserImpl* browser, const CefString& name); + CefFrameImpl(CefBrowserImpl* browser, + int64 frame_id, + const CefString& name, + const CefString& url); virtual ~CefFrameImpl(); // CefFrame methods @@ -453,20 +473,26 @@ class CefFrameImpl : public CefFrame { virtual bool IsMain() OVERRIDE { return name_.empty(); } virtual bool IsFocused() OVERRIDE; virtual CefString GetName() OVERRIDE { return name_; } - virtual int64 GetIdentifier() OVERRIDE { - return browser_->GetIdentifier(this); - } + virtual int64 GetIdentifier() OVERRIDE; virtual CefRefPtr GetParent() OVERRIDE { return browser_->GetParent(this); } - virtual CefString GetURL() OVERRIDE { return browser_->GetURL(this); } + virtual CefString GetURL() OVERRIDE; virtual CefRefPtr GetBrowser() OVERRIDE { return browser_.get(); } virtual void VisitDOM(CefRefPtr visitor) OVERRIDE; virtual CefRefPtr GetV8Context() OVERRIDE; + void set_id(int64 id); + void set_url(const CefString& url); + private: CefRefPtr browser_; CefString name_; + + // The below values must be protected by the lock. + base::Lock lock_; + int64 id_; + CefString url_; IMPLEMENT_REFCOUNTING(CefFrameImpl); }; diff --git a/libcef/browser_request_context.h b/libcef/browser_request_context.h index 27d2d6cc5..69eead3d8 100644 --- a/libcef/browser_request_context.h +++ b/libcef/browser_request_context.h @@ -34,7 +34,7 @@ class BrowserRequestContext : public net::URLRequestContext { net::HttpCache::Mode cache_mode, bool no_proxy); - virtual const std::string& GetUserAgent(const GURL& url) const; + virtual const std::string& GetUserAgent(const GURL& url) const OVERRIDE; void SetAcceptAllCookies(bool accept_all_cookies); bool AcceptAllCookies(); diff --git a/libcef/browser_request_context_proxy.cc b/libcef/browser_request_context_proxy.cc new file mode 100644 index 000000000..444464ab2 --- /dev/null +++ b/libcef/browser_request_context_proxy.cc @@ -0,0 +1,44 @@ +// Copyright (c) 2012 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 "libcef/browser_request_context_proxy.h" +#include "libcef/browser_request_context.h" +#include "libcef/cookie_store_proxy.h" + +BrowserRequestContextProxy::BrowserRequestContextProxy( + BrowserRequestContext* context, + CefBrowserImpl* browser) + : context_(context), + browser_(browser) { + DCHECK(context_); + DCHECK(browser_); + + // Cookie store that proxies to the browser implementation. + set_cookie_store(new CefCookieStoreProxy(browser_)); + + // All other values refer to the global request context. + set_net_log(context->net_log()); + set_host_resolver(context->host_resolver()); + set_cert_verifier(context->cert_verifier()); + set_origin_bound_cert_service(context->origin_bound_cert_service()); + set_fraudulent_certificate_reporter( + context->fraudulent_certificate_reporter()); + set_proxy_service(context->proxy_service()); + set_ssl_config_service(context->ssl_config_service()); + set_http_auth_handler_factory(context->http_auth_handler_factory()); + set_http_transaction_factory(context->http_transaction_factory()); + set_ftp_transaction_factory(context->ftp_transaction_factory()); + set_network_delegate(context->network_delegate()); + set_http_server_properties(context->http_server_properties()); + set_transport_security_state(context->transport_security_state()); + set_accept_charset(context->accept_charset()); + set_accept_language(context->accept_language()); + set_referrer_charset(context->referrer_charset()); + set_job_factory(context->job_factory()); +} + +const std::string& + BrowserRequestContextProxy::GetUserAgent(const GURL& url) const { + return context_->GetUserAgent(url); +} diff --git a/libcef/browser_request_context_proxy.h b/libcef/browser_request_context_proxy.h new file mode 100644 index 000000000..4678b184a --- /dev/null +++ b/libcef/browser_request_context_proxy.h @@ -0,0 +1,29 @@ +// Copyright (c) 2012 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_REQUEST_CONTEXT_PROXY_H_ +#define CEF_LIBCEF_BROWSER_REQUEST_CONTEXT_PROXY_H_ +#pragma once + +#include +#include "net/url_request/url_request_context.h" + +class BrowserRequestContext; +class CefBrowserImpl; + +// A basic URLRequestContext that only provides an in-memory cookie store. +class BrowserRequestContextProxy : public net::URLRequestContext { + public: + // Use an in-memory cache + BrowserRequestContextProxy(BrowserRequestContext* context, + CefBrowserImpl* browser); + + virtual const std::string& GetUserAgent(const GURL& url) const OVERRIDE; + + private: + BrowserRequestContext* context_; + CefBrowserImpl* browser_; +}; + +#endif // CEF_LIBCEF_BROWSER_REQUEST_CONTEXT_PROXY_H_ diff --git a/libcef/browser_resource_loader_bridge.cc b/libcef/browser_resource_loader_bridge.cc index b191950d1..795f59b83 100644 --- a/libcef/browser_resource_loader_bridge.cc +++ b/libcef/browser_resource_loader_bridge.cc @@ -20,10 +20,6 @@ // \ -> net::URLRequest // o-------> SyncRequestProxy (synchronous case) // -> net::URLRequest -// SetCookie <------------------------> CookieSetter -// -> net_util::SetCookie -// GetCookies <-----------------------> CookieGetter -// -> net_util::GetCookies // // NOTE: The implementation in this file may be used to have WebKit fetch // resources in-process. For example, it is handy for building a single- @@ -51,13 +47,11 @@ #include "base/memory/ref_counted.h" #include "base/message_loop.h" #include "base/message_loop_proxy.h" -#include "base/synchronization/waitable_event.h" #include "base/time.h" #include "base/timer.h" #include "base/threading/thread.h" #include "base/utf_string_conversions.h" #include "net/base/auth.h" -#include "net/base/cookie_store.h" #include "net/base/file_stream.h" #include "net/base/io_buffer.h" #include "net/base/load_flags.h" @@ -115,7 +109,7 @@ static const int kUpdateUploadProgressIntervalMsec = 100; class ExtraRequestInfo : public net::URLRequest::UserData { public: - ExtraRequestInfo(CefBrowser* browser, ResourceType::Type resource_type) + ExtraRequestInfo(CefBrowserImpl* browser, ResourceType::Type resource_type) : browser_(browser), resource_type_(resource_type), allow_download_(resource_type == ResourceType::MAIN_FRAME || @@ -125,14 +119,14 @@ class ExtraRequestInfo : public net::URLRequest::UserData { // The browser pointer is guaranteed to be valid for the lifespan of the // request. The pointer will be NULL in cases where the request was // initiated via the CefWebURLRequest API instead of by a browser window. - CefBrowser* browser() const { return browser_; } + CefBrowserImpl* browser() const { return browser_; } // Identifies the type of resource, such as subframe, media, etc. ResourceType::Type resource_type() const { return resource_type_; } bool allow_download() const { return allow_download_; } private: - CefBrowser* browser_; + CefBrowserImpl* browser_; ResourceType::Type resource_type_; bool allow_download_; }; @@ -195,7 +189,7 @@ class RequestProxy : public net::URLRequest::Delegate, public base::RefCountedThreadSafe { public: // Takes ownership of the params. - explicit RequestProxy(CefRefPtr browser) + explicit RequestProxy(CefRefPtr browser) : download_to_file_(false), buf_(new net::IOBuffer(kDataSize)), browser_(browser), @@ -292,7 +286,7 @@ class RequestProxy : public net::URLRequest::Delegate, response->SetStatus(info.headers->response_code()); } response->SetMimeType(info.mime_type); - handler->OnResourceResponse(browser_, url.spec(), response, + handler->OnResourceResponse(browser_.get(), url.spec(), response, content_filter_); std::string content_disposition; @@ -305,7 +299,7 @@ class RequestProxy : public net::URLRequest::Delegate, content_disposition, info.charset, "", info.mime_type, "download"); CefRefPtr dl_handler; - if (handler->GetDownloadHandler(browser_, info.mime_type, + if (handler->GetDownloadHandler(browser_.get(), info.mime_type, filename, info.content_length, dl_handler)) { download_handler_ = dl_handler; @@ -462,8 +456,8 @@ class RequestProxy : public net::URLRequest::Delegate, CefRefPtr resourceStream; CefRefPtr response(new CefResponseImpl()); - handled = handler->OnBeforeResourceLoad(browser_, request, redirectUrl, - resourceStream, response, loadFlags); + handled = handler->OnBeforeResourceLoad(browser_.get(), request, + redirectUrl, resourceStream, response, loadFlags); if (!handled) { // Observe URL from request. const std::string requestUrl(request->GetURL()); @@ -539,8 +533,8 @@ class RequestProxy : public net::URLRequest::Delegate, if (!handled && ResourceType::IsFrame(params->request_type) && !net::URLRequest::IsHandledProtocol(params->url.scheme())) { bool allow_os_execution = false; - handled = handler->OnProtocolExecution(browser_, params->url.spec(), - allow_os_execution); + handled = handler->OnProtocolExecution(browser_.get(), + params->url.spec(), allow_os_execution); if (!handled && allow_os_execution && ExternalProtocolHandler::HandleExternalProtocol(params->url)) { handled = true; @@ -572,7 +566,8 @@ class RequestProxy : public net::URLRequest::Delegate, request_->SetExtraRequestHeaders(headers); request_->set_load_flags(params->load_flags); request_->set_upload(params->upload.get()); - request_->set_context(_Context->request_context()); + request_->set_context(browser_.get() ? browser_->request_context_proxy() : + _Context->request_context()); request_->SetUserData(kCefUserData, new ExtraRequestInfo(browser_.get(), params->request_type)); BrowserAppCacheSystem::SetExtraRequestInfo( @@ -758,7 +753,7 @@ class RequestProxy : public net::URLRequest::Delegate, CefRefPtr handler = client->GetRequestHandler(); if (handler.get()) { CefString username, password; - if (handler->GetAuthCredentials(browser_, + if (handler->GetAuthCredentials(browser_.get(), auth_info->is_proxy, auth_info->challenger.host(), auth_info->challenger.port(), @@ -905,7 +900,7 @@ class RequestProxy : public net::URLRequest::Delegate, // read buffer for async IO scoped_refptr buf_; - CefRefPtr browser_; + CefRefPtr browser_; MessageLoop* owner_loop_; @@ -935,7 +930,7 @@ class RequestProxy : public net::URLRequest::Delegate, class SyncRequestProxy : public RequestProxy { public: - explicit SyncRequestProxy(CefRefPtr browser, + explicit SyncRequestProxy(CefRefPtr browser, ResourceLoaderBridge::SyncLoadResponse* result) : RequestProxy(browser), result_(result), event_(true, false) { } @@ -1002,7 +997,7 @@ class SyncRequestProxy : public RequestProxy { class ResourceLoaderBridgeImpl : public ResourceLoaderBridge { public: - ResourceLoaderBridgeImpl(CefRefPtr browser, + ResourceLoaderBridgeImpl(CefRefPtr browser, const webkit_glue::ResourceLoaderBridge::RequestInfo& request_info) : browser_(browser), params_(new RequestParams), @@ -1100,7 +1095,7 @@ class ResourceLoaderBridgeImpl : public ResourceLoaderBridge { virtual void UpdateRoutingId(int new_routing_id) OVERRIDE {} private: - CefRefPtr browser_; + CefRefPtr browser_; // Ownership of params_ is transfered to the proxy when the proxy is created. scoped_ptr params_; @@ -1110,61 +1105,6 @@ class ResourceLoaderBridgeImpl : public ResourceLoaderBridge { RequestProxy* proxy_; }; -//----------------------------------------------------------------------------- - -class CookieSetter : public base::RefCountedThreadSafe { - public: - void Set(const GURL& url, const std::string& cookie) { - REQUIRE_IOT(); - net::CookieStore* cookie_store = - _Context->request_context()->cookie_store(); - if (cookie_store) { - cookie_store->SetCookieWithOptionsAsync( - url, cookie, net::CookieOptions(), - net::CookieStore::SetCookiesCallback()); - } - } - - private: - friend class base::RefCountedThreadSafe; - - ~CookieSetter() {} -}; - -class CookieGetter : public base::RefCountedThreadSafe { - public: - CookieGetter() : event_(false, false) { - } - - void Get(const GURL& url) { - REQUIRE_IOT(); - net::CookieStore* cookie_store = - _Context->request_context()->cookie_store(); - if (cookie_store) { - cookie_store->GetCookiesWithOptionsAsync( - url, net::CookieOptions(), - base::Bind(&CookieGetter::OnGetCookies, this)); - } - } - - std::string GetResult() { - event_.Wait(); - return result_; - } - - private: - void OnGetCookies(const std::string& cookie_line) { - result_ = cookie_line; - event_.Signal(); - } - friend class base::RefCountedThreadSafe; - - ~CookieGetter() {} - - base::WaitableEvent event_; - std::string result_; -}; - } // anonymous namespace //----------------------------------------------------------------------------- @@ -1180,37 +1120,7 @@ webkit_glue::ResourceLoaderBridge* BrowserResourceLoaderBridge::Create( //----------------------------------------------------------------------------- // static -void BrowserResourceLoaderBridge::SetCookie(const GURL& url, - const GURL& first_party_for_cookies, - const std::string& cookie) { - // Proxy to IO thread to synchronize w/ network loading. - scoped_refptr cookie_setter = new CookieSetter(); - CefThread::PostTask(CefThread::IO, FROM_HERE, base::Bind( - &CookieSetter::Set, cookie_setter.get(), url, cookie)); -} - -// static -std::string BrowserResourceLoaderBridge::GetCookies( - const GURL& url, const GURL& first_party_for_cookies) { - // Proxy to IO thread to synchronize w/ network loading. - scoped_refptr cookie_getter = new CookieGetter(); - CefThread::PostTask(CefThread::IO, FROM_HERE, base::Bind( - &CookieGetter::Get, cookie_getter.get(), url)); - - // Blocks until the result is available. - return cookie_getter->GetResult(); -} - -// static -void BrowserResourceLoaderBridge::SetAcceptAllCookies(bool accept_all_cookies) { - // Proxy to IO thread to synchronize w/ network loading. - CefThread::PostTask(CefThread::IO, FROM_HERE, base::Bind( - &BrowserRequestContext::SetAcceptAllCookies, - _Context->request_context().get(), accept_all_cookies)); -} - -// static -CefRefPtr BrowserResourceLoaderBridge::GetBrowserForRequest( +CefRefPtr BrowserResourceLoaderBridge::GetBrowserForRequest( net::URLRequest* request) { REQUIRE_IOT(); ExtraRequestInfo* extra_info = diff --git a/libcef/browser_resource_loader_bridge.h b/libcef/browser_resource_loader_bridge.h index 47219ea2d..d8ac3acb2 100644 --- a/libcef/browser_resource_loader_bridge.h +++ b/libcef/browser_resource_loader_bridge.h @@ -14,23 +14,16 @@ #include "net/url_request/url_request.h" #include "webkit/glue/resource_loader_bridge.h" -class CefBrowser; +class CefBrowserImpl; class GURL; class BrowserResourceLoaderBridge { public: - // May only be called after Init. - static void SetCookie(const GURL& url, - const GURL& first_party_for_cookies, - const std::string& cookie); - static std::string GetCookies(const GURL& url, - const GURL& first_party_for_cookies); - static void SetAcceptAllCookies(bool accept_all_cookies); - // Return the CefBrowser associated with the specified request. The browser // will be NULL in cases where the request was initiated using the // CefWebURLRequest API. - static CefRefPtr GetBrowserForRequest(net::URLRequest* request); + static CefRefPtr GetBrowserForRequest( + net::URLRequest* request); // Creates a ResourceLoaderBridge instance. static webkit_glue::ResourceLoaderBridge* Create( diff --git a/libcef/browser_webcookiejar_impl.cc b/libcef/browser_webcookiejar_impl.cc index 3ce8d0eaa..d929de6d4 100644 --- a/libcef/browser_webcookiejar_impl.cc +++ b/libcef/browser_webcookiejar_impl.cc @@ -1,25 +1,139 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Copyright (c) 2012 the Chromium Embedded Framework authors. +// Portions copyright (c) 2010 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_webcookiejar_impl.h" -#include "libcef/browser_resource_loader_bridge.h" +#include + +#include "libcef/browser_resource_loader_bridge.h" +#include "libcef/browser_impl.h" +#include "libcef/cookie_manager_impl.h" +#include "libcef/cef_context.h" +#include "libcef/cef_thread.h" + +#include "base/synchronization/waitable_event.h" +#include "net/base/cookie_store.h" #include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebURL.h" using WebKit::WebString; using WebKit::WebURL; +namespace { + +net::CookieStore* GetCookieStore(CefRefPtr browser) { + scoped_refptr cookie_store; + if (browser) { + CefRefPtr client = browser->GetClient(); + if (client.get()) { + CefRefPtr handler = client->GetRequestHandler(); + if (handler.get()) { + // Get the manager from the handler. + CefRefPtr manager = + handler->GetCookieManager(browser.get(), + browser->pending_url().spec()); + if (manager.get()) { + cookie_store = + reinterpret_cast( + manager.get())->cookie_monster(); + } + } + } + } + + if (!cookie_store) { + // Use the global cookie store. + cookie_store = _Context->request_context()->cookie_store(); + } + + DCHECK(cookie_store); + return cookie_store; +} + +class CookieSetter : public base::RefCountedThreadSafe { + public: + void Set(CefRefPtr browser, + const GURL& url, + const std::string& cookie) { + REQUIRE_IOT(); + + scoped_refptr cookie_store = GetCookieStore(browser); + cookie_store->SetCookieWithOptionsAsync( + url, cookie, net::CookieOptions(), + net::CookieStore::SetCookiesCallback()); + } + + private: + friend class base::RefCountedThreadSafe; + + ~CookieSetter() {} +}; + +class CookieGetter : public base::RefCountedThreadSafe { + public: + CookieGetter() : event_(false, false) { + } + + void Get(CefRefPtr browser, const GURL& url) { + REQUIRE_IOT(); + + scoped_refptr cookie_store = GetCookieStore(browser); + cookie_store->GetCookiesWithOptionsAsync( + url, net::CookieOptions(), + base::Bind(&CookieGetter::OnGetCookies, this)); + } + + std::string GetResult() { + event_.Wait(); + return result_; + } + + private: + void OnGetCookies(const std::string& cookie_line) { + result_ = cookie_line; + event_.Signal(); + } + friend class base::RefCountedThreadSafe; + + ~CookieGetter() {} + + base::WaitableEvent event_; + std::string result_; +}; + +} // namespace + +BrowserWebCookieJarImpl::BrowserWebCookieJarImpl() + : browser_(NULL) { +} + +BrowserWebCookieJarImpl::BrowserWebCookieJarImpl(CefBrowserImpl* browser) + : browser_(browser) { +} + void BrowserWebCookieJarImpl::setCookie(const WebURL& url, - const WebURL& first_party_for_cookies, - const WebString& value) { - BrowserResourceLoaderBridge::SetCookie( - url, first_party_for_cookies, value.utf8()); + const WebURL& first_party_for_cookies, + const WebString& value) { + GURL gurl = url; + std::string cookie = value.utf8(); + + // Proxy to IO thread to synchronize w/ network loading. + scoped_refptr cookie_setter = new CookieSetter(); + CefThread::PostTask(CefThread::IO, FROM_HERE, base::Bind( + &CookieSetter::Set, cookie_setter.get(), browser_, gurl, cookie)); } WebString BrowserWebCookieJarImpl::cookies( const WebURL& url, const WebURL& first_party_for_cookies) { - return WebString::fromUTF8( - BrowserResourceLoaderBridge::GetCookies(url, first_party_for_cookies)); + GURL gurl = url; + + // Proxy to IO thread to synchronize w/ network loading. + scoped_refptr cookie_getter = new CookieGetter(); + CefThread::PostTask(CefThread::IO, FROM_HERE, base::Bind( + &CookieGetter::Get, cookie_getter.get(), browser_, gurl)); + + // Blocks until the result is available. + return WebString::fromUTF8(cookie_getter->GetResult()); } diff --git a/libcef/browser_webcookiejar_impl.h b/libcef/browser_webcookiejar_impl.h index 705f0d133..6508b465d 100644 --- a/libcef/browser_webcookiejar_impl.h +++ b/libcef/browser_webcookiejar_impl.h @@ -1,4 +1,5 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Copyright (c) 2012 the Chromium Embedded Framework authors. +// Portions copyright (c) 2010 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. @@ -6,18 +7,30 @@ #define CEF_LIBCEF_BROWSER_WEBCOOKIEJAR_IMPL_H_ #pragma once -// TODO(darin): WebCookieJar.h is missing a WebString.h include! -#include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebString.h" #include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebCookieJar.h" +namespace net { +class CookieStore; +} + +class CefBrowserImpl; + +// Handles cookie requests from the renderer. class BrowserWebCookieJarImpl : public WebKit::WebCookieJar { public: - // WebKit::WebCookieJar methods: + BrowserWebCookieJarImpl(); + explicit BrowserWebCookieJarImpl(CefBrowserImpl* browser); + + // WebKit::WebCookieJar methods. virtual void setCookie( const WebKit::WebURL& url, const WebKit::WebURL& first_party_for_cookies, const WebKit::WebString& cookie); virtual WebKit::WebString cookies( const WebKit::WebURL& url, const WebKit::WebURL& first_party_for_cookies); + + private: + // May be NULL for the global implementation. + CefBrowserImpl* browser_; }; #endif // CEF_LIBCEF_BROWSER_WEBCOOKIEJAR_IMPL_H_ diff --git a/libcef/browser_webview_delegate.cc b/libcef/browser_webview_delegate.cc index 3edb1a1bb..9f3fdf9a7 100644 --- a/libcef/browser_webview_delegate.cc +++ b/libcef/browser_webview_delegate.cc @@ -502,7 +502,7 @@ bool BrowserWebViewDelegate::allowScriptExtension( // WebPluginPageDelegate ----------------------------------------------------- WebCookieJar* BrowserWebViewDelegate::GetCookieJar() { - return WebKit::webKitPlatformSupport()->cookieJar(); + return &cookie_jar_; } // WebWidgetClient ----------------------------------------------------------- @@ -680,6 +680,10 @@ WebApplicationCacheHost* BrowserWebViewDelegate::createApplicationCacheHost( return BrowserAppCacheSystem::CreateApplicationCacheHost(client); } +WebKit::WebCookieJar* BrowserWebViewDelegate::cookieJar(WebFrame* frame) { + return &cookie_jar_; +} + void BrowserWebViewDelegate::willClose(WebFrame* frame) { browser_->UIT_BeforeFrameClosed(frame); } @@ -774,6 +778,12 @@ WebURLError BrowserWebViewDelegate::cancelledError( void BrowserWebViewDelegate::didCreateDataSource( WebFrame* frame, WebDataSource* ds) { ds->setExtraData(pending_extra_data_.release()); + + if (frame->parent() == 0) { + GURL url = ds->request().url(); + if (!url.is_empty()) + browser_->set_pending_url(url); + } } void BrowserWebViewDelegate::didStartProvisionalLoad(WebFrame* frame) { @@ -999,7 +1009,8 @@ BrowserWebViewDelegate::BrowserWebViewDelegate(CefBrowserImpl* browser) #else select_trailing_whitespace_enabled_(false), #endif - block_redirects_(false) { + block_redirects_(false), + cookie_jar_(browser) { } BrowserWebViewDelegate::~BrowserWebViewDelegate() { @@ -1166,6 +1177,9 @@ void BrowserWebViewDelegate::UpdateURL(WebFrame* frame) { entry->SetURL(request.url()); } + // Update attributes of the CefFrame if it currently exists. + browser_->UIT_UpdateCefFrame(frame); + bool is_main_frame = (frame->parent() == 0); CefRefPtr client = browser_->GetClient(); diff --git a/libcef/browser_webview_delegate.h b/libcef/browser_webview_delegate.h index 11692e375..312d4c9b0 100644 --- a/libcef/browser_webview_delegate.h +++ b/libcef/browser_webview_delegate.h @@ -16,6 +16,7 @@ #include #include "libcef/browser_navigation_controller.h" +#include "libcef/browser_webcookiejar_impl.h" #include "base/basictypes.h" #include "base/compiler_specific.h" @@ -154,6 +155,7 @@ class BrowserWebViewDelegate : public WebKit::WebViewClient, virtual WebKit::WebApplicationCacheHost* createApplicationCacheHost( WebKit::WebFrame* frame, WebKit::WebApplicationCacheHostClient* client) OVERRIDE; + virtual WebKit::WebCookieJar* cookieJar(WebKit::WebFrame*) OVERRIDE; virtual void willClose(WebKit::WebFrame*) OVERRIDE; virtual void loadURLExternally( WebKit::WebFrame*, const WebKit::WebURLRequest&, @@ -381,6 +383,8 @@ class BrowserWebViewDelegate : public WebKit::WebViewClient, std::string edit_command_name_; std::string edit_command_value_; + BrowserWebCookieJarImpl cookie_jar_; + DISALLOW_COPY_AND_ASSIGN(BrowserWebViewDelegate); }; diff --git a/libcef/cef_context.h b/libcef/cef_context.h index 06d3b850b..beca3cca5 100644 --- a/libcef/cef_context.h +++ b/libcef/cef_context.h @@ -76,9 +76,7 @@ class CefContext : public CefBase { void set_request_context(BrowserRequestContext* request_context) { request_context_ = request_context; } - scoped_refptr request_context() { - return request_context_; - } + BrowserRequestContext* request_context() { return request_context_; } // The DOMStorageContext object is managed by CefProcessUIThread. void set_storage_context(DOMStorageContext* storage_context) { diff --git a/libcef/cookie_impl.cc b/libcef/cookie_impl.cc deleted file mode 100644 index a420285a4..000000000 --- a/libcef/cookie_impl.cc +++ /dev/null @@ -1,232 +0,0 @@ -// Copyright (c) 2011 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/cef_cookie.h" -#include "libcef/cef_context.h" -#include "libcef/cef_thread.h" -#include "libcef/cef_time_util.h" - -#include "base/bind.h" -#include "net/base/cookie_monster.h" - -namespace { - -// Callback class for visiting cookies. -class VisitCookiesCallback : public base::RefCounted { - public: - explicit VisitCookiesCallback(CefRefPtr visitor) - : visitor_(visitor) { - } - - void Run(const net::CookieList& list) { - REQUIRE_IOT(); - - net::CookieMonster* cookie_monster = static_cast( - _Context->request_context()->cookie_store()); - if (!cookie_monster) - return; - - int total = list.size(), count = 0; - - net::CookieList::const_iterator it = list.begin(); - for (; it != list.end(); ++it, ++count) { - CefCookie cookie; - const net::CookieMonster::CanonicalCookie& cc = *(it); - - CefString(&cookie.name).FromString(cc.Name()); - CefString(&cookie.value).FromString(cc.Value()); - CefString(&cookie.domain).FromString(cc.Domain()); - CefString(&cookie.path).FromString(cc.Path()); - cookie.secure = cc.IsSecure(); - cookie.httponly = cc.IsHttpOnly(); - cef_time_from_basetime(cc.CreationDate(), cookie.creation); - cef_time_from_basetime(cc.LastAccessDate(), cookie.last_access); - cookie.has_expires = cc.DoesExpire(); - if (cookie.has_expires) - cef_time_from_basetime(cc.ExpiryDate(), cookie.expires); - - bool deleteCookie = false; - bool keepLooping = visitor_->Visit(cookie, count, total, deleteCookie); - if (deleteCookie) { - cookie_monster->DeleteCanonicalCookieAsync(cc, - net::CookieMonster::DeleteCookieCallback()); - } - if (!keepLooping) - break; - } - } - - private: - CefRefPtr visitor_; -}; - -void IOT_VisitAllCookies(CefRefPtr visitor) { - REQUIRE_IOT(); - - net::CookieMonster* cookie_monster = static_cast( - _Context->request_context()->cookie_store()); - if (!cookie_monster) - return; - - scoped_refptr callback( - new VisitCookiesCallback(visitor)); - - cookie_monster->GetAllCookiesAsync( - base::Bind(&VisitCookiesCallback::Run, callback.get())); -} - -void IOT_VisitUrlCookies(const GURL& url, bool includeHttpOnly, - CefRefPtr visitor) { - REQUIRE_IOT(); - - net::CookieMonster* cookie_monster = static_cast( - _Context->request_context()->cookie_store()); - if (!cookie_monster) - return; - - net::CookieOptions options; - if (includeHttpOnly) - options.set_include_httponly(); - - scoped_refptr callback( - new VisitCookiesCallback(visitor)); - - cookie_monster->GetAllCookiesForURLWithOptionsAsync(url, options, - base::Bind(&VisitCookiesCallback::Run, callback.get())); -} - -void IOT_SetCookiePath(const CefString& path) { - REQUIRE_IOT(); - - FilePath cookie_path; - if (!path.empty()) - cookie_path = FilePath(path); - - _Context->request_context()->SetCookieStoragePath(cookie_path); -} - -} // namespace - -bool CefVisitAllCookies(CefRefPtr visitor) { - // Verify that the context is in a valid state. - if (!CONTEXT_STATE_VALID()) { - NOTREACHED() << "context not valid"; - return false; - } - - return CefThread::PostTask(CefThread::IO, FROM_HERE, - base::Bind(IOT_VisitAllCookies, visitor)); -} - -bool CefVisitUrlCookies(const CefString& url, bool includeHttpOnly, - CefRefPtr visitor) { - // Verify that the context is in a valid state. - if (!CONTEXT_STATE_VALID()) { - NOTREACHED() << "context not valid"; - return false; - } - - std::string urlStr = url; - GURL gurl = GURL(urlStr); - if (!gurl.is_valid()) - return false; - - return CefThread::PostTask(CefThread::IO, FROM_HERE, - base::Bind(IOT_VisitUrlCookies, gurl, includeHttpOnly, visitor)); -} - -bool CefSetCookie(const CefString& url, const CefCookie& cookie) { - // Verify that the context is in a valid state. - if (!CONTEXT_STATE_VALID()) { - NOTREACHED() << "context not valid"; - return false; - } - - // Verify that this function is being called on the IO thread. - if (!CefThread::CurrentlyOn(CefThread::IO)) { - NOTREACHED() << "called on invalid thread"; - return false; - } - - net::CookieMonster* cookie_monster = static_cast( - _Context->request_context()->cookie_store()); - if (!cookie_monster) - return false; - - std::string urlStr = url; - GURL gurl = GURL(urlStr); - 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, cookie.httponly, - net::CookieStore::SetCookiesCallback()); - return true; -} - -bool CefDeleteCookies(const CefString& url, const CefString& cookie_name) { - // Verify that the context is in a valid state. - if (!CONTEXT_STATE_VALID()) { - NOTREACHED() << "context not valid"; - return false; - } - - // Verify that this function is being called on the IO thread. - if (!CefThread::CurrentlyOn(CefThread::IO)) { - NOTREACHED() << "called on invalid thread"; - return false; - } - - net::CookieMonster* cookie_monster = static_cast( - _Context->request_context()->cookie_store()); - if (!cookie_monster) - return false; - - if (url.empty()) { - // Delete all cookies. - cookie_monster->DeleteAllAsync(net::CookieMonster::DeleteCallback()); - return true; - } - - std::string urlStr = url; - GURL gurl = GURL(urlStr); - if (!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()); - } - return true; -} - -bool CefSetCookiePath(const CefString& path) { - // Verify that the context is in a valid state. - if (!CONTEXT_STATE_VALID()) { - NOTREACHED() << "context not valid"; - return false; - } - - if (CefThread::CurrentlyOn(CefThread::IO)) { - IOT_SetCookiePath(path); - } else { - CefThread::PostTask(CefThread::IO, FROM_HERE, - base::Bind(&IOT_SetCookiePath, path)); - } - - return true; -} diff --git a/libcef/cookie_manager_impl.cc b/libcef/cookie_manager_impl.cc new file mode 100644 index 000000000..3f68ca960 --- /dev/null +++ b/libcef/cookie_manager_impl.cc @@ -0,0 +1,255 @@ +// Copyright (c) 2012 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 "libcef/cookie_manager_impl.h" + +#include + +#include "libcef/browser_persistent_cookie_store.h" +#include "libcef/cef_context.h" +#include "libcef/cef_thread.h" +#include "libcef/cef_time_util.h" + +#include "base/bind.h" +#include "base/logging.h" + +namespace { + +// Callback class for visiting cookies. +class VisitCookiesCallback : public base::RefCounted { + public: + explicit VisitCookiesCallback(net::CookieMonster* cookie_monster, + CefRefPtr visitor) + : cookie_monster_(cookie_monster), + visitor_(visitor) { + } + + void Run(const net::CookieList& list) { + REQUIRE_IOT(); + + int total = list.size(), count = 0; + + net::CookieList::const_iterator it = list.begin(); + for (; it != list.end(); ++it, ++count) { + CefCookie cookie; + const net::CookieMonster::CanonicalCookie& cc = *(it); + + CefString(&cookie.name).FromString(cc.Name()); + CefString(&cookie.value).FromString(cc.Value()); + CefString(&cookie.domain).FromString(cc.Domain()); + CefString(&cookie.path).FromString(cc.Path()); + cookie.secure = cc.IsSecure(); + cookie.httponly = cc.IsHttpOnly(); + cef_time_from_basetime(cc.CreationDate(), cookie.creation); + cef_time_from_basetime(cc.LastAccessDate(), cookie.last_access); + cookie.has_expires = cc.DoesExpire(); + if (cookie.has_expires) + cef_time_from_basetime(cc.ExpiryDate(), cookie.expires); + + bool deleteCookie = false; + bool keepLooping = visitor_->Visit(cookie, count, total, deleteCookie); + if (deleteCookie) { + cookie_monster_->DeleteCanonicalCookieAsync(cc, + net::CookieMonster::DeleteCookieCallback()); + } + if (!keepLooping) + break; + } + } + + private: + scoped_refptr cookie_monster_; + CefRefPtr visitor_; +}; + +} // namespace + + +CefCookieManagerImpl::CefCookieManagerImpl() + : is_global_(true) { + cookie_monster_ = + static_cast( + _Context->request_context()->cookie_store()); + DCHECK(cookie_monster_); +} + + // Creates a new cookie monster with storage at the specified |path|. +CefCookieManagerImpl::CefCookieManagerImpl(const CefString& path) + :is_global_(false) { + SetStoragePath(path); +} + +CefCookieManagerImpl::~CefCookieManagerImpl() { +} + +bool CefCookieManagerImpl::VisitAllCookies( + CefRefPtr visitor) { + if (CefThread::CurrentlyOn(CefThread::IO)) { + scoped_refptr callback( + new VisitCookiesCallback(cookie_monster_, visitor)); + + cookie_monster_->GetAllCookiesAsync( + base::Bind(&VisitCookiesCallback::Run, callback.get())); + } else { + // Execute on the IO thread. + CefThread::PostTask(CefThread::IO, FROM_HERE, + base::Bind(base::IgnoreResult(&CefCookieManagerImpl::VisitAllCookies), + this, visitor)); + } + + return true; +} + +bool CefCookieManagerImpl::VisitUrlCookies( + const CefString& url, bool includeHttpOnly, + CefRefPtr visitor) { + if (CefThread::CurrentlyOn(CefThread::IO)) { + 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())); + } else { + // Execute on the IO thread. + CefThread::PostTask(CefThread::IO, FROM_HERE, + base::Bind(base::IgnoreResult(&CefCookieManagerImpl::VisitUrlCookies), + this, url, includeHttpOnly, visitor)); + } + + return true; +} + +bool CefCookieManagerImpl::SetCookie(const CefString& url, + const CefCookie& cookie) { + // Verify that this function is being called on the IO thread. + if (!CefThread::CurrentlyOn(CefThread::IO)) { + NOTREACHED() << "called on invalid thread"; + return false; + } + + 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, cookie.httponly, + net::CookieStore::SetCookiesCallback()); + return true; +} + +bool CefCookieManagerImpl::DeleteCookies(const CefString& url, + const CefString& cookie_name) { + // Verify that this function is being called on the IO thread. + if (!CefThread::CurrentlyOn(CefThread::IO)) { + NOTREACHED() << "called on invalid thread"; + return false; + } + + if (url.empty()) { + // Delete all cookies. + cookie_monster_->DeleteAllAsync(net::CookieMonster::DeleteCallback()); + return true; + } + + GURL gurl = GURL(url.ToString()); + if (!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()); + } + return true; +} + +bool CefCookieManagerImpl::SetStoragePath(const CefString& path) { + if (CefThread::CurrentlyOn(CefThread::IO)) { + FilePath new_path; + if (!path.empty()) + new_path = FilePath(path); + + if (is_global_) { + // Global path changes are handled by the request context. + _Context->request_context()->SetCookieStoragePath(new_path); + cookie_monster_ = + static_cast( + _Context->request_context()->cookie_store()); + return true; + } + + if (cookie_monster_ && ((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()) { + if (file_util::CreateDirectory(new_path)) { + const FilePath& cookie_path = new_path.AppendASCII("Cookies"); + persistent_store = new BrowserPersistentCookieStore(cookie_path, false); + } 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); + storage_path_ = new_path; + } else { + // Execute on the IO thread. + CefThread::PostTask(CefThread::IO, FROM_HERE, + base::Bind(base::IgnoreResult(&CefCookieManagerImpl::SetStoragePath), + this, path)); + } + + return true; +} + + +// CefCookieManager methods ---------------------------------------------------- + +// static +CefRefPtr CefCookieManager::GetGlobalManager() { + // Verify that the context is in a valid state. + if (!CONTEXT_STATE_VALID()) { + NOTREACHED() << "context not valid"; + return NULL; + } + + return new CefCookieManagerImpl(); +} + +// static +CefRefPtr CefCookieManager::CreateManager( + const CefString& path) { + // Verify that the context is in a valid state. + if (!CONTEXT_STATE_VALID()) { + NOTREACHED() << "context not valid"; + return NULL; + } + + return new CefCookieManagerImpl(path); +} diff --git a/libcef/cookie_manager_impl.h b/libcef/cookie_manager_impl.h new file mode 100644 index 000000000..de582bfb2 --- /dev/null +++ b/libcef/cookie_manager_impl.h @@ -0,0 +1,43 @@ +// Copyright (c) 2012 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_COOKIE_IMPL_H_ +#define CEF_LIBCEF_COOKIE_IMPL_H_ + +#include "include/cef_cookie.h" +#include "base/file_path.h" +#include "net/base/cookie_monster.h" + +// Implementation of the CefCookieManager interface. +class CefCookieManagerImpl : public CefCookieManager { + public: + // Creates a new reference to the existing global cookie monster. + CefCookieManagerImpl(); + + // Creates a new cookie monster with storage at the specified |path|. + explicit CefCookieManagerImpl(const CefString& path); + + ~CefCookieManagerImpl(); + + // CefCookieManager methods. + 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 SetStoragePath(const CefString& path) OVERRIDE; + + net::CookieMonster* cookie_monster() { return cookie_monster_; } + + private: + scoped_refptr cookie_monster_; + bool is_global_; + FilePath storage_path_; + + IMPLEMENT_REFCOUNTING(CefCookieManagerImpl); +}; + +#endif // CEF_LIBCEF_COOKIE_IMPL_H_ diff --git a/libcef/cookie_store_proxy.cc b/libcef/cookie_store_proxy.cc new file mode 100644 index 000000000..c5313f8d1 --- /dev/null +++ b/libcef/cookie_store_proxy.cc @@ -0,0 +1,92 @@ +// Copyright (c) 2012 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 "libcef/cookie_store_proxy.h" + +#include + +#include "libcef/browser_impl.h" +#include "libcef/cef_context.h" +#include "libcef/cookie_manager_impl.h" + +#include "base/logging.h" + + +CefCookieStoreProxy::CefCookieStoreProxy(CefBrowserImpl* browser) + : browser_(browser) { + DCHECK(browser_); +} + +void CefCookieStoreProxy::SetCookieWithOptionsAsync( + const GURL& url, + const std::string& cookie_line, + const net::CookieOptions& options, + const SetCookiesCallback& callback) { + scoped_refptr cookie_store = GetCookieStore(); + cookie_store->SetCookieWithOptionsAsync(url, cookie_line, options, callback); +} + +void CefCookieStoreProxy::GetCookiesWithOptionsAsync( + const GURL& url, const net::CookieOptions& options, + const GetCookiesCallback& callback) { + scoped_refptr cookie_store = GetCookieStore(); + cookie_store->GetCookiesWithOptionsAsync(url, options, callback); +} + +void CefCookieStoreProxy::GetCookiesWithInfoAsync( + const GURL& url, + const net::CookieOptions& options, + const GetCookieInfoCallback& callback) { + scoped_refptr cookie_store = GetCookieStore(); + cookie_store->GetCookiesWithInfoAsync(url, options, callback); +} + +void CefCookieStoreProxy::DeleteCookieAsync( + const GURL& url, + const std::string& cookie_name, + const base::Closure& callback) { + scoped_refptr cookie_store = GetCookieStore(); + cookie_store->DeleteCookieAsync(url, cookie_name, callback); +} + +void CefCookieStoreProxy::DeleteAllCreatedBetweenAsync( + const base::Time& delete_begin, + const base::Time& delete_end, + const DeleteCallback& callback) { + scoped_refptr cookie_store = GetCookieStore(); + cookie_store->DeleteAllCreatedBetweenAsync(delete_begin, delete_end, + callback); +} + +net::CookieMonster* CefCookieStoreProxy::GetCookieMonster() { + scoped_refptr cookie_store = GetCookieStore(); + return cookie_store->GetCookieMonster(); +} + +net::CookieStore* CefCookieStoreProxy::GetCookieStore() { + scoped_refptr cookie_store; + + CefRefPtr client = browser_->GetClient(); + if (client.get()) { + CefRefPtr handler = client->GetRequestHandler(); + if (handler.get()) { + // Get the manager from the handler. + CefRefPtr manager = + handler->GetCookieManager(browser_, browser_->pending_url().spec()); + if (manager.get()) { + cookie_store = + reinterpret_cast( + manager.get())->cookie_monster(); + } + } + } + + if (!cookie_store) { + // Use the global cookie store. + cookie_store = _Context->request_context()->cookie_store(); + } + + DCHECK(cookie_store); + return cookie_store; +} diff --git a/libcef/cookie_store_proxy.h b/libcef/cookie_store_proxy.h new file mode 100644 index 000000000..8bcfac50d --- /dev/null +++ b/libcef/cookie_store_proxy.h @@ -0,0 +1,46 @@ +// Copyright (c) 2012 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_COOKIE_STORE_PROXY_H_ +#define CEF_LIBCEF_COOKIE_STORE_PROXY_H_ +#pragma once + +#include "net/base/cookie_store.h" + +class CefBrowserImpl; + +// Handles cookie requests from the network stack. +class CefCookieStoreProxy : public net::CookieStore { + public: + explicit CefCookieStoreProxy(CefBrowserImpl* browser); + + // net::CookieStore methods. + virtual void SetCookieWithOptionsAsync( + const GURL& url, + const std::string& cookie_line, + const net::CookieOptions& options, + const SetCookiesCallback& callback) OVERRIDE; + virtual void GetCookiesWithOptionsAsync( + const GURL& url, const net::CookieOptions& options, + const GetCookiesCallback& callback) OVERRIDE; + void GetCookiesWithInfoAsync( + const GURL& url, + const net::CookieOptions& options, + const GetCookieInfoCallback& callback) OVERRIDE; + virtual void DeleteCookieAsync(const GURL& url, + const std::string& cookie_name, + const base::Closure& callback) OVERRIDE; + virtual void DeleteAllCreatedBetweenAsync(const base::Time& delete_begin, + const base::Time& delete_end, + const DeleteCallback& callback) + OVERRIDE; + virtual net::CookieMonster* GetCookieMonster() OVERRIDE; + + private: + net::CookieStore* GetCookieStore(); + + CefBrowserImpl* browser_; +}; + +#endif // CEF_LIBCEF_COOKIE_STORE_PROXY_H_ diff --git a/libcef/request_impl.cc b/libcef/request_impl.cc index 6c9e0cca7..547a069c2 100644 --- a/libcef/request_impl.cc +++ b/libcef/request_impl.cc @@ -3,6 +3,10 @@ // can be found in the LICENSE file. #include "libcef/request_impl.h" + +#include +#include + #include "libcef/http_header_utils.h" #include "base/logging.h" @@ -80,9 +84,23 @@ void CefRequestImpl::Set(net::URLRequest* request) { url_ = request->url().spec(); method_ = request->method(); + net::HttpRequestHeaders headers = request->extra_request_headers(); + + // Ensure that we do not send username and password fields in the referrer. + GURL referrer(request->GetSanitizedReferrer()); + + // Strip Referer from request_info_.extra_headers to prevent, e.g., plugins + // from overriding headers that are controlled using other means. Otherwise a + // plugin could set a referrer although sending the referrer is inhibited. + headers.RemoveHeader(net::HttpRequestHeaders::kReferer); + + // Our consumer should have made sure that this is a safe referrer. See for + // instance WebCore::FrameLoader::HideReferrer. + if (referrer.is_valid()) + headers.SetHeader(net::HttpRequestHeaders::kReferer, referrer.spec()); + // Transfer request headers - GetHeaderMap(request->extra_request_headers(), headermap_); - headermap_.insert(std::make_pair(L"Referrer", request->referrer())); + GetHeaderMap(headers, headermap_); // Transfer post data, if any net::UploadData* data = request->get_upload(); diff --git a/libcef/scheme_impl.cc b/libcef/scheme_impl.cc index 2711c4045..5fda6d30b 100644 --- a/libcef/scheme_impl.cc +++ b/libcef/scheme_impl.cc @@ -5,9 +5,9 @@ #include -#include "include/cef_browser.h" #include "include/cef_scheme.h" #include "libcef/browser_devtools_scheme_handler.h" +#include "libcef/browser_impl.h" #include "libcef/browser_resource_loader_bridge.h" #include "libcef/cef_context.h" #include "libcef/cef_thread.h" @@ -22,6 +22,7 @@ #include "base/synchronization/lock.h" #include "googleurl/src/url_util.h" #include "net/base/completion_callback.h" +#include "net/base/cookie_monster.h" #include "net/base/io_buffer.h" #include "net/base/upload_data.h" #include "net/http/http_response_headers.h" @@ -107,7 +108,9 @@ class CefUrlRequestJob : public net::URLRequestJob { CefRefPtr handler) : net::URLRequestJob(request), handler_(handler), - remaining_bytes_(0) { + remaining_bytes_(0), + response_cookies_save_index_(0), + ALLOW_THIS_IN_INITIALIZER_LIST(weak_factory_(this)) { } virtual ~CefUrlRequestJob() { @@ -116,22 +119,132 @@ class CefUrlRequestJob : public net::URLRequestJob { virtual void Start() OVERRIDE { REQUIRE_IOT(); + cef_request_ = CefRequest::CreateRequest(); + + // Populate the request data. + static_cast(cef_request_.get())->Set(request_); + + // Add default headers if not already specified. + const net::URLRequestContext* context = request_->context(); + if (context) { + CefRequest::HeaderMap::const_iterator it; + CefRequest::HeaderMap headerMap; + cef_request_->GetHeaderMap(headerMap); + bool changed = false; + + if (!context->accept_language().empty()) { + it = headerMap.find(net::HttpRequestHeaders::kAcceptLanguage); + if (it == headerMap.end()) { + headerMap.insert( + std::make_pair(net::HttpRequestHeaders::kAcceptLanguage, + context->accept_language())); + } + changed = true; + } + + if (!context->accept_charset().empty()) { + it = headerMap.find(net::HttpRequestHeaders::kAcceptCharset); + if (it == headerMap.end()) { + headerMap.insert( + std::make_pair(net::HttpRequestHeaders::kAcceptCharset, + context->accept_charset())); + } + changed = true; + } + + it = headerMap.find(net::HttpRequestHeaders::kUserAgent); + if (it == headerMap.end()) { + headerMap.insert( + std::make_pair(net::HttpRequestHeaders::kUserAgent, + context->GetUserAgent(request_->url()))); + changed = true; + } + + if (changed) + cef_request_->SetHeaderMap(headerMap); + } + + AddCookieHeaderAndStart(); + } + + void AddCookieHeaderAndStart() { + // No matter what, we want to report our status as IO pending since we will + // be notifying our consumer asynchronously via OnStartCompleted. + SetStatus(URLRequestStatus(URLRequestStatus::IO_PENDING, 0)); + + // If the request was destroyed, then there is no more work to do. + if (!request_) + return; + + net::CookieStore* cookie_store = + request_->context()->cookie_store(); + if (cookie_store) { + net::CookieMonster* cookie_monster = cookie_store->GetCookieMonster(); + if (cookie_monster) { + cookie_monster->GetAllCookiesForURLAsync( + request_->url(), + base::Bind(&CefUrlRequestJob::CheckCookiePolicyAndLoad, + weak_factory_.GetWeakPtr())); + } else { + DoLoadCookies(); + } + } else { + DoStartTransaction(); + } + } + + void DoLoadCookies() { + net::CookieOptions options; + options.set_include_httponly(); + request_->context()->cookie_store()->GetCookiesWithInfoAsync( + request_->url(), options, + base::Bind(&CefUrlRequestJob::OnCookiesLoaded, + weak_factory_.GetWeakPtr())); + } + + void CheckCookiePolicyAndLoad( + const net::CookieList& cookie_list) { + if (CanGetCookies(cookie_list)) + DoLoadCookies(); + else + DoStartTransaction(); + } + + void OnCookiesLoaded( + const std::string& cookie_line, + const std::vector& cookie_infos) { + if (!cookie_line.empty()) { + CefRequest::HeaderMap headerMap; + cef_request_->GetHeaderMap(headerMap); + headerMap.insert( + std::make_pair(net::HttpRequestHeaders::kCookie, cookie_line)); + cef_request_->SetHeaderMap(headerMap); + } + DoStartTransaction(); + } + + void DoStartTransaction() { + // We may have been canceled while retrieving cookies. + if (GetStatus().is_success()) { + StartTransaction(); + } else { + NotifyCanceled(); + } + } + + void StartTransaction() { if (!callback_) callback_ = new Callback(this); - CefRefPtr req(CefRequest::CreateRequest()); - - // Populate the request data. - static_cast(req.get())->Set(request()); + // Protect against deletion of this object. + base::WeakPtr weak_ptr(weak_factory_.GetWeakPtr()); // Handler can decide whether to process the request. - bool rv = handler_->ProcessRequest(req, callback_.get()); - if (!rv) { + bool rv = handler_->ProcessRequest(cef_request_, callback_.get()); + if (weak_ptr.get() && !rv) { // Cancel the request. - NotifyStartError(URLRequestStatus(URLRequestStatus::FAILED, ERR_ABORTED)); + NotifyCanceled(); } - - return; } virtual void Kill() OVERRIDE { @@ -193,11 +306,7 @@ class CefUrlRequestJob : public net::URLRequestJob { virtual void GetResponseInfo(net::HttpResponseInfo* info) OVERRIDE { REQUIRE_IOT(); - if (response_.get()) { - CefResponseImpl* responseImpl = - static_cast(response_.get()); - info->headers = responseImpl->GetResponseHeaders(); - } + info->headers = GetResponseHeaders(); } virtual bool IsRedirectResponse(GURL* location, int* http_status_code) @@ -265,7 +374,81 @@ class CefUrlRequestJob : public net::URLRequestJob { set_expected_content_size(remaining_bytes_); // Continue processing the request. - NotifyHeadersComplete(); + SaveCookiesAndNotifyHeadersComplete(); + } + + net::HttpResponseHeaders* GetResponseHeaders() { + DCHECK(response_); + if (!response_headers_.get()) { + CefResponseImpl* responseImpl = + static_cast(response_.get()); + response_headers_ = responseImpl->GetResponseHeaders(); + } + return response_headers_; + } + + void SaveCookiesAndNotifyHeadersComplete() { + response_cookies_.clear(); + response_cookies_save_index_ = 0; + + FetchResponseCookies(&response_cookies_); + + // Now, loop over the response cookies, and attempt to persist each. + SaveNextCookie(); + } + + void SaveNextCookie() { + if (response_cookies_save_index_ == response_cookies_.size()) { + response_cookies_.clear(); + response_cookies_save_index_ = 0; + SetStatus(URLRequestStatus()); // Clear the IO_PENDING status + NotifyHeadersComplete(); + return; + } + + // No matter what, we want to report our status as IO pending since we will + // be notifying our consumer asynchronously via OnStartCompleted. + SetStatus(URLRequestStatus(URLRequestStatus::IO_PENDING, 0)); + + net::CookieOptions options; + options.set_include_httponly(); + if (CanSetCookie( + response_cookies_[response_cookies_save_index_], &options)) { + request_->context()->cookie_store()->SetCookieWithOptionsAsync( + request_->url(), response_cookies_[response_cookies_save_index_], + options, base::Bind(&CefUrlRequestJob::OnCookieSaved, + weak_factory_.GetWeakPtr())); + return; + } + + CookieHandled(); + } + + void OnCookieSaved(bool cookie_status) { + CookieHandled(); + } + + void CookieHandled() { + response_cookies_save_index_++; + // We may have been canceled within OnSetCookie. + if (GetStatus().is_success()) { + SaveNextCookie(); + } else { + NotifyCanceled(); + } + } + + void FetchResponseCookies( + std::vector* cookies) { + const std::string name = "Set-Cookie"; + std::string value; + + void* iter = NULL; + net::HttpResponseHeaders* headers = GetResponseHeaders(); + while (headers->EnumerateHeader(&iter, name, &value)) { + if (!value.empty()) + cookies->push_back(value); + } } // Client callback for asynchronous response continuation. @@ -355,7 +538,12 @@ class CefUrlRequestJob : public net::URLRequestJob { GURL redirect_url_; int64 remaining_bytes_; + CefRefPtr cef_request_; CefRefPtr callback_; + scoped_refptr response_headers_; + std::vector response_cookies_; + size_t response_cookies_save_index_; + base::WeakPtrFactory weak_factory_; DISALLOW_COPY_AND_ASSIGN(CefUrlRequestJob); }; @@ -539,10 +727,10 @@ class CefUrlRequestManager { // Call the handler factory to create the handler for the request. CefRefPtr requestPtr(new CefRequestImpl()); static_cast(requestPtr.get())->Set(request); - CefRefPtr browser = + CefRefPtr browser = BrowserResourceLoaderBridge::GetBrowserForRequest(request); CefRefPtr handler = - factory->Create(browser, scheme, requestPtr); + factory->Create(browser.get(), scheme, requestPtr); if (handler.get()) job = new CefUrlRequestJob(request, handler); } diff --git a/libcef_dll/cpptoc/cookie_manager_cpptoc.cc b/libcef_dll/cpptoc/cookie_manager_cpptoc.cc new file mode 100644 index 000000000..034a873f8 --- /dev/null +++ b/libcef_dll/cpptoc/cookie_manager_cpptoc.cc @@ -0,0 +1,177 @@ +// Copyright (c) 2012 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/cookie_manager_cpptoc.h" +#include "libcef_dll/ctocpp/cookie_visitor_ctocpp.h" + + +// GLOBAL FUNCTIONS - Body may be edited by hand. + +CEF_EXPORT cef_cookie_manager_t* cef_cookie_manager_get_global_manager() { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + CefRefPtr _retval = CefCookieManager::GetGlobalManager(); + + // Return type: refptr_same + return CefCookieManagerCppToC::Wrap(_retval); +} + +CEF_EXPORT cef_cookie_manager_t* cef_cookie_manager_create_manager( + const cef_string_t* path) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Unverified params: path + + // Execute + CefRefPtr _retval = CefCookieManager::CreateManager( + CefString(path)); + + // Return type: refptr_same + return CefCookieManagerCppToC::Wrap(_retval); +} + + +// MEMBER FUNCTIONS - Body may be edited by hand. + +int CEF_CALLBACK cookie_manager_visit_all_cookies( + struct _cef_cookie_manager_t* self, + struct _cef_cookie_visitor_t* visitor) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + // Verify param: visitor; type: refptr_diff + DCHECK(visitor); + if (!visitor) + return 0; + + // Execute + bool _retval = CefCookieManagerCppToC::Get(self)->VisitAllCookies( + CefCookieVisitorCToCpp::Wrap(visitor)); + + // Return type: bool + return _retval; +} + +int CEF_CALLBACK cookie_manager_visit_url_cookies( + struct _cef_cookie_manager_t* self, const cef_string_t* url, + int includeHttpOnly, struct _cef_cookie_visitor_t* visitor) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + // Verify param: url; type: string_byref_const + DCHECK(url); + if (!url) + return 0; + // Verify param: visitor; type: refptr_diff + DCHECK(visitor); + if (!visitor) + return 0; + + // Execute + bool _retval = CefCookieManagerCppToC::Get(self)->VisitUrlCookies( + CefString(url), + includeHttpOnly?true:false, + CefCookieVisitorCToCpp::Wrap(visitor)); + + // Return type: bool + return _retval; +} + +int CEF_CALLBACK cookie_manager_set_cookie(struct _cef_cookie_manager_t* self, + const cef_string_t* url, const struct _cef_cookie_t* cookie) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + // Verify param: url; type: string_byref_const + DCHECK(url); + if (!url) + return 0; + // Verify param: cookie; type: struct_byref_const + DCHECK(cookie); + if (!cookie) + return 0; + + // Translate param: cookie; type: struct_byref_const + CefCookie cookieObj; + if (cookie) + cookieObj.Set(*cookie, false); + + // Execute + bool _retval = CefCookieManagerCppToC::Get(self)->SetCookie( + CefString(url), + cookieObj); + + // Return type: bool + return _retval; +} + +int CEF_CALLBACK cookie_manager_delete_cookies( + struct _cef_cookie_manager_t* self, const cef_string_t* url, + const cef_string_t* cookie_name) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + // Unverified params: url, cookie_name + + // Execute + bool _retval = CefCookieManagerCppToC::Get(self)->DeleteCookies( + CefString(url), + CefString(cookie_name)); + + // Return type: bool + return _retval; +} + +int CEF_CALLBACK cookie_manager_set_storage_path( + struct _cef_cookie_manager_t* self, const cef_string_t* path) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return 0; + // Unverified params: path + + // Execute + bool _retval = CefCookieManagerCppToC::Get(self)->SetStoragePath( + CefString(path)); + + // Return type: bool + return _retval; +} + + +// CONSTRUCTOR - Do not edit by hand. + +CefCookieManagerCppToC::CefCookieManagerCppToC(CefCookieManager* cls) + : CefCppToC( + cls) { + struct_.struct_.visit_all_cookies = cookie_manager_visit_all_cookies; + struct_.struct_.visit_url_cookies = cookie_manager_visit_url_cookies; + struct_.struct_.set_cookie = cookie_manager_set_cookie; + struct_.struct_.delete_cookies = cookie_manager_delete_cookies; + struct_.struct_.set_storage_path = cookie_manager_set_storage_path; +} + +#ifndef NDEBUG +template<> long CefCppToC::DebugObjCt = 0; +#endif + diff --git a/libcef_dll/cpptoc/cookie_manager_cpptoc.h b/libcef_dll/cpptoc/cookie_manager_cpptoc.h new file mode 100644 index 000000000..cacc919f4 --- /dev/null +++ b/libcef_dll/cpptoc/cookie_manager_cpptoc.h @@ -0,0 +1,37 @@ +// Copyright (c) 2012 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_COOKIE_MANAGER_CPPTOC_H_ +#define CEF_LIBCEF_DLL_CPPTOC_COOKIE_MANAGER_CPPTOC_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/cpptoc/cpptoc.h" + +// Wrap a C++ class with a C structure. +// This class may be instantiated and accessed DLL-side only. +class CefCookieManagerCppToC + : public CefCppToC { + public: + explicit CefCookieManagerCppToC(CefCookieManager* cls); + virtual ~CefCookieManagerCppToC() {} +}; + +#endif // BUILDING_CEF_SHARED +#endif // CEF_LIBCEF_DLL_CPPTOC_COOKIE_MANAGER_CPPTOC_H_ + diff --git a/libcef_dll/cpptoc/request_handler_cpptoc.cc b/libcef_dll/cpptoc/request_handler_cpptoc.cc index 6e9d66bb1..9dfe7aed7 100644 --- a/libcef_dll/cpptoc/request_handler_cpptoc.cc +++ b/libcef_dll/cpptoc/request_handler_cpptoc.cc @@ -14,6 +14,7 @@ #include "libcef_dll/cpptoc/download_handler_cpptoc.h" #include "libcef_dll/cpptoc/request_handler_cpptoc.h" #include "libcef_dll/ctocpp/browser_ctocpp.h" +#include "libcef_dll/ctocpp/cookie_manager_ctocpp.h" #include "libcef_dll/ctocpp/frame_ctocpp.h" #include "libcef_dll/ctocpp/request_ctocpp.h" #include "libcef_dll/ctocpp/response_ctocpp.h" @@ -347,6 +348,33 @@ int CEF_CALLBACK request_handler_get_auth_credentials( return _retval; } +cef_cookie_manager_t* CEF_CALLBACK request_handler_get_cookie_manager( + struct _cef_request_handler_t* self, cef_browser_t* browser, + const cef_string_t* main_url) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return NULL; + // Verify param: browser; type: refptr_diff + DCHECK(browser); + if (!browser) + return NULL; + // Verify param: main_url; type: string_byref_const + DCHECK(main_url); + if (!main_url) + return NULL; + + // Execute + CefRefPtr _retval = CefRequestHandlerCppToC::Get( + self)->GetCookieManager( + CefBrowserCToCpp::Wrap(browser), + CefString(main_url)); + + // Return type: refptr_diff + return CefCookieManagerCToCpp::Unwrap(_retval); +} + // CONSTRUCTOR - Do not edit by hand. @@ -361,6 +389,7 @@ CefRequestHandlerCppToC::CefRequestHandlerCppToC(CefRequestHandler* cls) struct_.struct_.on_protocol_execution = request_handler_on_protocol_execution; struct_.struct_.get_download_handler = request_handler_get_download_handler; struct_.struct_.get_auth_credentials = request_handler_get_auth_credentials; + struct_.struct_.get_cookie_manager = request_handler_get_cookie_manager; } #ifndef NDEBUG diff --git a/libcef_dll/ctocpp/cookie_manager_ctocpp.cc b/libcef_dll/ctocpp/cookie_manager_ctocpp.cc new file mode 100644 index 000000000..aef6394a1 --- /dev/null +++ b/libcef_dll/ctocpp/cookie_manager_ctocpp.cc @@ -0,0 +1,152 @@ +// Copyright (c) 2012 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/cookie_visitor_cpptoc.h" +#include "libcef_dll/ctocpp/cookie_manager_ctocpp.h" + + +// STATIC METHODS - Body may be edited by hand. + +CefRefPtr CefCookieManager::GetGlobalManager() { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + cef_cookie_manager_t* _retval = cef_cookie_manager_get_global_manager(); + + // Return type: refptr_same + return CefCookieManagerCToCpp::Wrap(_retval); +} + +CefRefPtr CefCookieManager::CreateManager( + const CefString& path) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Unverified params: path + + // Execute + cef_cookie_manager_t* _retval = cef_cookie_manager_create_manager( + path.GetStruct()); + + // Return type: refptr_same + return CefCookieManagerCToCpp::Wrap(_retval); +} + + +// VIRTUAL METHODS - Body may be edited by hand. + +bool CefCookieManagerCToCpp::VisitAllCookies( + CefRefPtr visitor) { + if (CEF_MEMBER_MISSING(struct_, visit_all_cookies)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: visitor; type: refptr_diff + DCHECK(visitor.get()); + if (!visitor.get()) + return false; + + // Execute + int _retval = struct_->visit_all_cookies(struct_, + CefCookieVisitorCppToC::Wrap(visitor)); + + // Return type: bool + return _retval?true:false; +} + +bool CefCookieManagerCToCpp::VisitUrlCookies(const CefString& url, + bool includeHttpOnly, CefRefPtr visitor) { + if (CEF_MEMBER_MISSING(struct_, visit_url_cookies)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: url; type: string_byref_const + DCHECK(!url.empty()); + if (url.empty()) + return false; + // Verify param: visitor; type: refptr_diff + DCHECK(visitor.get()); + if (!visitor.get()) + return false; + + // Execute + int _retval = struct_->visit_url_cookies(struct_, + url.GetStruct(), + includeHttpOnly, + CefCookieVisitorCppToC::Wrap(visitor)); + + // Return type: bool + return _retval?true:false; +} + +bool CefCookieManagerCToCpp::SetCookie(const CefString& url, + const CefCookie& cookie) { + if (CEF_MEMBER_MISSING(struct_, set_cookie)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: url; type: string_byref_const + DCHECK(!url.empty()); + if (url.empty()) + return false; + + // Execute + int _retval = struct_->set_cookie(struct_, + url.GetStruct(), + &cookie); + + // Return type: bool + return _retval?true:false; +} + +bool CefCookieManagerCToCpp::DeleteCookies(const CefString& url, + const CefString& cookie_name) { + if (CEF_MEMBER_MISSING(struct_, delete_cookies)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Unverified params: url, cookie_name + + // Execute + int _retval = struct_->delete_cookies(struct_, + url.GetStruct(), + cookie_name.GetStruct()); + + // Return type: bool + return _retval?true:false; +} + +bool CefCookieManagerCToCpp::SetStoragePath(const CefString& path) { + if (CEF_MEMBER_MISSING(struct_, set_storage_path)) + return false; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Unverified params: path + + // Execute + int _retval = struct_->set_storage_path(struct_, + path.GetStruct()); + + // Return type: bool + return _retval?true:false; +} + + +#ifndef NDEBUG +template<> long CefCToCpp::DebugObjCt = 0; +#endif + diff --git a/libcef_dll/ctocpp/cookie_manager_ctocpp.h b/libcef_dll/ctocpp/cookie_manager_ctocpp.h new file mode 100644 index 000000000..ae2f4e627 --- /dev/null +++ b/libcef_dll/ctocpp/cookie_manager_ctocpp.h @@ -0,0 +1,49 @@ +// Copyright (c) 2012 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_COOKIE_MANAGER_CTOCPP_H_ +#define CEF_LIBCEF_DLL_CTOCPP_COOKIE_MANAGER_CTOCPP_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/ctocpp/ctocpp.h" + +// Wrap a C structure with a C++ class. +// This class may be instantiated and accessed wrapper-side only. +class CefCookieManagerCToCpp + : public CefCToCpp { + public: + explicit CefCookieManagerCToCpp(cef_cookie_manager_t* str) + : CefCToCpp(str) {} + virtual ~CefCookieManagerCToCpp() {} + + // CefCookieManager methods + 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 SetStoragePath(const CefString& path) OVERRIDE; +}; + +#endif // USING_CEF_SHARED +#endif // CEF_LIBCEF_DLL_CTOCPP_COOKIE_MANAGER_CTOCPP_H_ + diff --git a/libcef_dll/ctocpp/request_handler_ctocpp.cc b/libcef_dll/ctocpp/request_handler_ctocpp.cc index 79b035172..69cb54f52 100644 --- a/libcef_dll/ctocpp/request_handler_ctocpp.cc +++ b/libcef_dll/ctocpp/request_handler_ctocpp.cc @@ -11,6 +11,7 @@ // #include "libcef_dll/cpptoc/browser_cpptoc.h" +#include "libcef_dll/cpptoc/cookie_manager_cpptoc.h" #include "libcef_dll/cpptoc/frame_cpptoc.h" #include "libcef_dll/cpptoc/request_cpptoc.h" #include "libcef_dll/cpptoc/response_cpptoc.h" @@ -289,6 +290,31 @@ bool CefRequestHandlerCToCpp::GetAuthCredentials(CefRefPtr browser, return _retval?true:false; } +CefRefPtr CefRequestHandlerCToCpp::GetCookieManager( + CefRefPtr browser, const CefString& main_url) { + if (CEF_MEMBER_MISSING(struct_, get_cookie_manager)) + return NULL; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: browser; type: refptr_diff + DCHECK(browser.get()); + if (!browser.get()) + return NULL; + // Verify param: main_url; type: string_byref_const + DCHECK(!main_url.empty()); + if (main_url.empty()) + return NULL; + + // Execute + cef_cookie_manager_t* _retval = struct_->get_cookie_manager(struct_, + CefBrowserCppToC::Wrap(browser), + main_url.GetStruct()); + + // Return type: refptr_diff + return CefCookieManagerCppToC::Unwrap(_retval); +} + #ifndef NDEBUG template<> long CefCToCpp GetCookieManager( + CefRefPtr browser, const CefString& main_url) OVERRIDE; }; #endif // BUILDING_CEF_SHARED diff --git a/libcef_dll/libcef_dll.cc b/libcef_dll/libcef_dll.cc index 05097c7f2..4052ad84a 100644 --- a/libcef_dll/libcef_dll.cc +++ b/libcef_dll/libcef_dll.cc @@ -12,8 +12,6 @@ #include "include/cef_app.h" #include "include/capi/cef_app_capi.h" -#include "include/cef_cookie.h" -#include "include/capi/cef_cookie_capi.h" #include "include/cef_origin_whitelist.h" #include "include/capi/cef_origin_whitelist_capi.h" #include "include/cef_scheme.h" @@ -27,6 +25,7 @@ #include "include/cef_v8.h" #include "include/capi/cef_v8_capi.h" #include "libcef_dll/cpptoc/browser_cpptoc.h" +#include "libcef_dll/cpptoc/cookie_manager_cpptoc.h" #include "libcef_dll/cpptoc/domdocument_cpptoc.h" #include "libcef_dll/cpptoc/domevent_cpptoc.h" #include "libcef_dll/cpptoc/domnode_cpptoc.h" @@ -114,6 +113,7 @@ CEF_EXPORT void cef_shutdown() { // Check that all wrapper objects have been destroyed DCHECK_EQ(CefBrowserCppToC::DebugObjCt, 0); DCHECK_EQ(CefContentFilterCToCpp::DebugObjCt, 0); + DCHECK_EQ(CefCookieManagerCppToC::DebugObjCt, 0); DCHECK_EQ(CefCookieVisitorCToCpp::DebugObjCt, 0); DCHECK_EQ(CefDOMDocumentCppToC::DebugObjCt, 0); DCHECK_EQ(CefDOMEventCppToC::DebugObjCt, 0); @@ -185,100 +185,6 @@ CEF_EXPORT void cef_quit_message_loop() { CefQuitMessageLoop(); } -CEF_EXPORT int cef_visit_all_cookies(struct _cef_cookie_visitor_t* visitor) { - // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING - - // Verify param: visitor; type: refptr_diff - DCHECK(visitor); - if (!visitor) - return 0; - - // Execute - bool _retval = CefVisitAllCookies( - CefCookieVisitorCToCpp::Wrap(visitor)); - - // Return type: bool - return _retval; -} - -CEF_EXPORT int cef_visit_url_cookies(const cef_string_t* url, - int includeHttpOnly, struct _cef_cookie_visitor_t* visitor) { - // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING - - // Verify param: url; type: string_byref_const - DCHECK(url); - if (!url) - return 0; - // Verify param: visitor; type: refptr_diff - DCHECK(visitor); - if (!visitor) - return 0; - - // Execute - bool _retval = CefVisitUrlCookies( - CefString(url), - includeHttpOnly?true:false, - CefCookieVisitorCToCpp::Wrap(visitor)); - - // Return type: bool - return _retval; -} - -CEF_EXPORT int cef_set_cookie(const cef_string_t* url, - const struct _cef_cookie_t* cookie) { - // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING - - // Verify param: url; type: string_byref_const - DCHECK(url); - if (!url) - return 0; - // Verify param: cookie; type: struct_byref_const - DCHECK(cookie); - if (!cookie) - return 0; - - // Translate param: cookie; type: struct_byref_const - CefCookie cookieObj; - if (cookie) - cookieObj.Set(*cookie, false); - - // Execute - bool _retval = CefSetCookie( - CefString(url), - cookieObj); - - // Return type: bool - return _retval; -} - -CEF_EXPORT int cef_delete_cookies(const cef_string_t* url, - const cef_string_t* cookie_name) { - // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING - - // Unverified params: url, cookie_name - - // Execute - bool _retval = CefDeleteCookies( - CefString(url), - CefString(cookie_name)); - - // Return type: bool - return _retval; -} - -CEF_EXPORT int cef_set_cookie_path(const cef_string_t* path) { - // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING - - // Unverified params: path - - // Execute - bool _retval = CefSetCookiePath( - CefString(path)); - - // Return type: bool - return _retval; -} - CEF_EXPORT int cef_add_cross_origin_whitelist_entry( const cef_string_t* source_origin, const cef_string_t* target_protocol, const cef_string_t* target_domain, int allow_target_subdomains) { diff --git a/libcef_dll/wrapper/libcef_dll_wrapper.cc b/libcef_dll/wrapper/libcef_dll_wrapper.cc index 9f00bc4a1..f275c1d8b 100644 --- a/libcef_dll/wrapper/libcef_dll_wrapper.cc +++ b/libcef_dll/wrapper/libcef_dll_wrapper.cc @@ -12,8 +12,6 @@ #include "include/cef_app.h" #include "include/capi/cef_app_capi.h" -#include "include/cef_cookie.h" -#include "include/capi/cef_cookie_capi.h" #include "include/cef_origin_whitelist.h" #include "include/capi/cef_origin_whitelist_capi.h" #include "include/cef_scheme.h" @@ -59,6 +57,7 @@ #include "libcef_dll/cpptoc/web_urlrequest_client_cpptoc.h" #include "libcef_dll/cpptoc/write_handler_cpptoc.h" #include "libcef_dll/ctocpp/browser_ctocpp.h" +#include "libcef_dll/ctocpp/cookie_manager_ctocpp.h" #include "libcef_dll/ctocpp/domdocument_ctocpp.h" #include "libcef_dll/ctocpp/domevent_ctocpp.h" #include "libcef_dll/ctocpp/domnode_ctocpp.h" @@ -116,6 +115,7 @@ CEF_GLOBAL void CefShutdown() { // Check that all wrapper objects have been destroyed DCHECK_EQ(CefBrowserCToCpp::DebugObjCt, 0); DCHECK_EQ(CefContentFilterCppToC::DebugObjCt, 0); + DCHECK_EQ(CefCookieManagerCToCpp::DebugObjCt, 0); DCHECK_EQ(CefCookieVisitorCppToC::DebugObjCt, 0); DCHECK_EQ(CefDOMDocumentCToCpp::DebugObjCt, 0); DCHECK_EQ(CefDOMEventCToCpp::DebugObjCt, 0); @@ -187,90 +187,6 @@ CEF_GLOBAL void CefQuitMessageLoop() { cef_quit_message_loop(); } -CEF_GLOBAL bool CefVisitAllCookies(CefRefPtr visitor) { - // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING - - // Verify param: visitor; type: refptr_diff - DCHECK(visitor.get()); - if (!visitor.get()) - return false; - - // Execute - int _retval = cef_visit_all_cookies( - CefCookieVisitorCppToC::Wrap(visitor)); - - // Return type: bool - return _retval?true:false; -} - -CEF_GLOBAL bool CefVisitUrlCookies(const CefString& url, bool includeHttpOnly, - CefRefPtr visitor) { - // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING - - // Verify param: url; type: string_byref_const - DCHECK(!url.empty()); - if (url.empty()) - return false; - // Verify param: visitor; type: refptr_diff - DCHECK(visitor.get()); - if (!visitor.get()) - return false; - - // Execute - int _retval = cef_visit_url_cookies( - url.GetStruct(), - includeHttpOnly, - CefCookieVisitorCppToC::Wrap(visitor)); - - // Return type: bool - return _retval?true:false; -} - -CEF_GLOBAL bool CefSetCookie(const CefString& url, const CefCookie& cookie) { - // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING - - // Verify param: url; type: string_byref_const - DCHECK(!url.empty()); - if (url.empty()) - return false; - - // Execute - int _retval = cef_set_cookie( - url.GetStruct(), - &cookie); - - // Return type: bool - return _retval?true:false; -} - -CEF_GLOBAL bool CefDeleteCookies(const CefString& url, - const CefString& cookie_name) { - // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING - - // Unverified params: url, cookie_name - - // Execute - int _retval = cef_delete_cookies( - url.GetStruct(), - cookie_name.GetStruct()); - - // Return type: bool - return _retval?true:false; -} - -CEF_GLOBAL bool CefSetCookiePath(const CefString& path) { - // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING - - // Unverified params: path - - // Execute - int _retval = cef_set_cookie_path( - path.GetStruct()); - - // Return type: bool - return _retval?true:false; -} - CEF_GLOBAL bool CefAddCrossOriginWhitelistEntry(const CefString& source_origin, const CefString& target_protocol, const CefString& target_domain, bool allow_target_subdomains) { diff --git a/tests/unittests/cookie_unittest.cc b/tests/unittests/cookie_unittest.cc index b0c096087..89306e317 100644 --- a/tests/unittests/cookie_unittest.cc +++ b/tests/unittests/cookie_unittest.cc @@ -1,10 +1,12 @@ -// Copyright (c) 2011 The Chromium Embedded Framework Authors. All rights +// Copyright (c) 2012 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_cookie.h" #include "include/cef_runnable.h" +#include "include/cef_scheme.h" +#include "tests/unittests/test_handler.h" #include "tests/unittests/test_suite.h" #include "base/scoped_temp_dir.h" #include "base/synchronization/waitable_event.h" @@ -18,17 +20,19 @@ const char* kTestPath = "/path/to/cookietest"; typedef std::vector CookieVector; -void IOT_Set(const CefString& url, CookieVector* cookies, +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(CefSetCookie(url, *it)); + EXPECT_TRUE(manager->SetCookie(url, *it)); event->Signal(); } -void IOT_Delete(const CefString& url, const CefString& cookie_name, +void IOT_Delete(CefRefPtr manager, + const CefString& url, const CefString& cookie_name, base::WaitableEvent* event) { - EXPECT_TRUE(CefDeleteCookies(url, cookie_name)); + EXPECT_TRUE(manager->DeleteCookies(url, cookie_name)); event->Signal(); } @@ -59,10 +63,29 @@ class TestVisitor : public CefCookieVisitor { IMPLEMENT_REFCOUNTING(TestVisitor); }; +// Set the cookies. +void SetCookies(CefRefPtr manager, + const CefString& url, CookieVector& cookies, + base::WaitableEvent& event) { + CefPostTask(TID_IO, NewCefRunnableFunction(IOT_Set, manager, url, + &cookies, &event)); + event.Wait(); +} + +// Delete the cookie. +void DeleteCookies(CefRefPtr manager, + const CefString& url, const CefString& cookie_name, + base::WaitableEvent& event) { + CefPostTask(TID_IO, NewCefRunnableFunction(IOT_Delete, manager, url, + cookie_name, &event)); + event.Wait(); +} + // Create a test cookie. If |withDomain| is true a domain cookie will be // created, otherwise a host cookie will be created. -void CreateCookie(CefCookie& cookie, bool withDomain, - base::WaitableEvent& event) { +void CreateCookie(CefRefPtr manager, + CefCookie& cookie, bool withDomain, + base::WaitableEvent& event) { CefString(&cookie.name).FromASCII("my_cookie"); CefString(&cookie.value).FromASCII("My Value"); if (withDomain) @@ -79,21 +102,19 @@ void CreateCookie(CefCookie& cookie, bool withDomain, CookieVector cookies; cookies.push_back(cookie); - // Set the cookie. - CefPostTask(TID_IO, NewCefRunnableFunction(IOT_Set, kTestUrl, &cookies, - &event)); - event.Wait(); + SetCookies(manager, kTestUrl, cookies, event); } // Retrieve the test cookie. If |withDomain| is true check that the cookie // is a domain cookie, otherwise a host cookie. if |deleteCookies| is true // the cookie will be deleted when it's retrieved. -void GetCookie(const CefCookie& cookie, bool withDomain, +void GetCookie(CefRefPtr manager, + const CefCookie& cookie, bool withDomain, base::WaitableEvent& event, bool deleteCookies) { CookieVector cookies; // Get the cookie and delete it. - EXPECT_TRUE(CefVisitUrlCookies(kTestUrl, false, + EXPECT_TRUE(manager->VisitUrlCookies(kTestUrl, false, new TestVisitor(&cookies, deleteCookies, &event))); event.Wait(); @@ -120,17 +141,41 @@ void GetCookie(const CefCookie& cookie, bool withDomain, EXPECT_EQ(cookie.expires.millisecond, cookie_read.expires.millisecond); } +// Visit URL cookies. +void VisitUrlCookies(CefRefPtr manager, + const CefString& url, + bool includeHttpOnly, + CookieVector& cookies, + bool deleteCookies, + base::WaitableEvent& event) { + EXPECT_TRUE(manager->VisitUrlCookies(url, includeHttpOnly, + new TestVisitor(&cookies, deleteCookies, &event))); + event.Wait(); +} + +// Visit all cookies. +void VisitAllCookies(CefRefPtr manager, + CookieVector& cookies, + bool deleteCookies, + base::WaitableEvent& event) { + EXPECT_TRUE(manager->VisitAllCookies( + new TestVisitor(&cookies, deleteCookies, &event))); + event.Wait(); +} + // Verify that no cookies exist. If |withUrl| is true it will only check for // cookies matching the URL. -void VerifyNoCookies(base::WaitableEvent& event, bool withUrl) { +void VerifyNoCookies(CefRefPtr manager, + base::WaitableEvent& event, bool withUrl) { CookieVector cookies; // Verify that the cookie has been deleted. if (withUrl) { - EXPECT_TRUE(CefVisitUrlCookies(kTestUrl, false, + EXPECT_TRUE(manager->VisitUrlCookies(kTestUrl, false, new TestVisitor(&cookies, false, &event))); } else { - EXPECT_TRUE(CefVisitAllCookies(new TestVisitor(&cookies, false, &event))); + EXPECT_TRUE(manager->VisitAllCookies( + new TestVisitor(&cookies, false, &event))); } event.Wait(); @@ -138,46 +183,42 @@ void VerifyNoCookies(base::WaitableEvent& event, bool withUrl) { } // Delete all system cookies. -void DeleteAllCookies(base::WaitableEvent& event) { - CefPostTask(TID_IO, NewCefRunnableFunction(IOT_Delete, CefString(), +void DeleteAllCookies(CefRefPtr manager, + base::WaitableEvent& event) { + CefPostTask(TID_IO, NewCefRunnableFunction(IOT_Delete, manager, CefString(), CefString(), &event)); event.Wait(); } -} // namespace - -// Test creation of a domain cookie. -TEST(CookieTest, DomainCookie) { +void TestDomainCookie(CefRefPtr manager) { base::WaitableEvent event(false, false); CefCookie cookie; // Create a domain cookie. - CreateCookie(cookie, true, event); + CreateCookie(manager, cookie, true, event); // Retrieve, verify and delete the domain cookie. - GetCookie(cookie, true, event, true); + GetCookie(manager, cookie, true, event, true); // Verify that the cookie was deleted. - VerifyNoCookies(event, true); + VerifyNoCookies(manager, event, true); } -// Test creation of a host cookie. -TEST(CookieTest, HostCookie) { +void TestHostCookie(CefRefPtr manager) { base::WaitableEvent event(false, false); CefCookie cookie; // Create a host cookie. - CreateCookie(cookie, false, event); + CreateCookie(manager, cookie, false, event); // Retrieve, verify and delete the host cookie. - GetCookie(cookie, false, event, true); + GetCookie(manager, cookie, false, event, true); // Verify that the cookie was deleted. - VerifyNoCookies(event, true); + VerifyNoCookies(manager, event, true); } -// Test creation of multiple cookies. -TEST(CookieTest, MultipleCookies) { +void TestMultipleCookies(CefRefPtr manager) { base::WaitableEvent event(false, false); std::stringstream ss; int i; @@ -201,15 +242,11 @@ TEST(CookieTest, MultipleCookies) { } // Set the cookies. - CefPostTask(TID_IO, NewCefRunnableFunction(IOT_Set, kTestUrl, &cookies, - &event)); - event.Wait(); + SetCookies(manager, kTestUrl, cookies, event); cookies.clear(); // Get the cookies without deleting them. - EXPECT_TRUE(CefVisitUrlCookies(kTestUrl, false, - new TestVisitor(&cookies, false, &event))); - event.Wait(); + VisitUrlCookies(manager, kTestUrl, false, cookies, false, event); EXPECT_EQ((CookieVector::size_type)kNumCookies, cookies.size()); @@ -228,14 +265,10 @@ TEST(CookieTest, MultipleCookies) { cookies.clear(); // Delete the 2nd cookie. - CefPostTask(TID_IO, NewCefRunnableFunction(IOT_Delete, kTestUrl, - CefString("my_cookie1"), &event)); - event.Wait(); + DeleteCookies(manager, kTestUrl, CefString("my_cookie1"), event); // Verify that the cookie has been deleted. - EXPECT_TRUE(CefVisitUrlCookies(kTestUrl, false, - new TestVisitor(&cookies, false, &event))); - event.Wait(); + VisitUrlCookies(manager, kTestUrl, false, cookies, false, event); EXPECT_EQ((CookieVector::size_type)3, cookies.size()); EXPECT_EQ(CefString(&cookies[0].name), "my_cookie0"); @@ -245,14 +278,10 @@ TEST(CookieTest, MultipleCookies) { cookies.clear(); // Delete the rest of the cookies. - CefPostTask(TID_IO, NewCefRunnableFunction(IOT_Delete, kTestUrl, - CefString(), &event)); - event.Wait(); + DeleteCookies(manager, kTestUrl, CefString(), event); // Verify that the cookies have been deleted. - EXPECT_TRUE(CefVisitUrlCookies(kTestUrl, false, - new TestVisitor(&cookies, false, &event))); - event.Wait(); + VisitUrlCookies(manager, kTestUrl, false, cookies, false, event); EXPECT_EQ((CookieVector::size_type)0, cookies.size()); @@ -271,33 +300,26 @@ TEST(CookieTest, MultipleCookies) { } // Delete all of the cookies using the visitor. - EXPECT_TRUE(CefVisitUrlCookies(kTestUrl, false, - new TestVisitor(&cookies, true, &event))); - event.Wait(); + VisitUrlCookies(manager, kTestUrl, false, cookies, true, event); cookies.clear(); // Verify that the cookies have been deleted. - EXPECT_TRUE(CefVisitUrlCookies(kTestUrl, false, - new TestVisitor(&cookies, false, &event))); - event.Wait(); + VisitUrlCookies(manager, kTestUrl, false, cookies, false, event); EXPECT_EQ((CookieVector::size_type)0, cookies.size()); } -TEST(CookieTest, AllCookies) { +void TestAllCookies(CefRefPtr manager) { base::WaitableEvent event(false, false); CookieVector cookies; // Delete all system cookies just in case something is left over from a // different test. - CefPostTask(TID_IO, NewCefRunnableFunction(IOT_Delete, CefString(), - CefString(), &event)); - event.Wait(); + DeleteCookies(manager, CefString(), CefString(), event); // Verify that all system cookies have been deleted. - EXPECT_TRUE(CefVisitAllCookies(new TestVisitor(&cookies, false, &event))); - event.Wait(); + VisitAllCookies(manager, cookies, false, event); EXPECT_EQ((CookieVector::size_type)0, cookies.size()); @@ -308,8 +330,7 @@ TEST(CookieTest, AllCookies) { CefString(&cookie1.value).FromASCII("My Value 1"); cookies.push_back(cookie1); - CefPostTask(TID_IO, NewCefRunnableFunction(IOT_Set, kUrl1, &cookies, &event)); - event.Wait(); + SetCookies(manager, kUrl1, cookies, event); cookies.clear(); CefCookie cookie2; @@ -318,13 +339,11 @@ TEST(CookieTest, AllCookies) { CefString(&cookie2.value).FromASCII("My Value 2"); cookies.push_back(cookie2); - CefPostTask(TID_IO, NewCefRunnableFunction(IOT_Set, kUrl2, &cookies, &event)); - event.Wait(); + SetCookies(manager, kUrl2, cookies, event); cookies.clear(); // Verify that all system cookies can be retrieved. - EXPECT_TRUE(CefVisitAllCookies(new TestVisitor(&cookies, false, &event))); - event.Wait(); + VisitAllCookies(manager, cookies, false, event); EXPECT_EQ((CookieVector::size_type)2, cookies.size()); EXPECT_EQ(CefString(&cookies[0].name), "my_cookie1"); @@ -336,9 +355,7 @@ TEST(CookieTest, AllCookies) { cookies.clear(); // Verify that the cookies can be retrieved separately. - EXPECT_TRUE(CefVisitUrlCookies(kUrl1, false, - new TestVisitor(&cookies, false, &event))); - event.Wait(); + VisitUrlCookies(manager, kUrl1, false, cookies, false, event); EXPECT_EQ((CookieVector::size_type)1, cookies.size()); EXPECT_EQ(CefString(&cookies[0].name), "my_cookie1"); @@ -346,9 +363,7 @@ TEST(CookieTest, AllCookies) { EXPECT_EQ(CefString(&cookies[0].domain), "www.foo.com"); cookies.clear(); - EXPECT_TRUE(CefVisitUrlCookies(kUrl2, false, - new TestVisitor(&cookies, false, &event))); - event.Wait(); + VisitUrlCookies(manager, kUrl2, false, cookies, false, event); EXPECT_EQ((CookieVector::size_type)1, cookies.size()); EXPECT_EQ(CefString(&cookies[0].name), "my_cookie2"); @@ -357,51 +372,548 @@ TEST(CookieTest, AllCookies) { cookies.clear(); // Delete all of the system cookies. - DeleteAllCookies(event); + DeleteAllCookies(manager, event); // Verify that all system cookies have been deleted. - VerifyNoCookies(event, false); + VerifyNoCookies(manager, event, false); } -TEST(CookieTest, ChangeDirectory) { +void TestChangeDirectory(CefRefPtr manager, + const CefString& original_dir) { base::WaitableEvent event(false, false); CefCookie cookie; - std::string cache_path; - CefTestSuite::GetCachePath(cache_path); - ScopedTempDir temp_dir; // Create a new temporary directory. EXPECT_TRUE(temp_dir.CreateUniqueTempDir()); // Delete all of the system cookies. - DeleteAllCookies(event); + DeleteAllCookies(manager, event); // Set the new temporary directory as the storage location. - EXPECT_TRUE(CefSetCookiePath(temp_dir.path().value())); + EXPECT_TRUE(manager->SetStoragePath(temp_dir.path().value())); + + // Wait for the storage location change to complete on the IO thread. + WaitForIOThread(); // Verify that no cookies exist. - VerifyNoCookies(event, true); + VerifyNoCookies(manager, event, true); // Create a domain cookie. - CreateCookie(cookie, true, event); + CreateCookie(manager, cookie, true, event); // Retrieve and verify the domain cookie. - GetCookie(cookie, true, event, false); + GetCookie(manager, cookie, true, event, false); // Restore the original storage location. - EXPECT_TRUE(CefSetCookiePath(cache_path)); + EXPECT_TRUE(manager->SetStoragePath(original_dir)); + + // Wait for the storage location change to complete on the IO thread. + WaitForIOThread(); // Verify that no cookies exist. - VerifyNoCookies(event, true); + VerifyNoCookies(manager, event, true); // Set the new temporary directory as the storage location. - EXPECT_TRUE(CefSetCookiePath(temp_dir.path().value())); + EXPECT_TRUE(manager->SetStoragePath(temp_dir.path().value())); + + // Wait for the storage location change to complete on the IO thread. + WaitForIOThread(); // Retrieve and verify the domain cookie that was set previously. - GetCookie(cookie, true, event, false); + GetCookie(manager, cookie, true, event, false); // Restore the original storage location. - EXPECT_TRUE(CefSetCookiePath(cache_path)); + EXPECT_TRUE(manager->SetStoragePath(original_dir)); + + // Wait for the storage location change to complete on the IO thread. + WaitForIOThread(); +} + +} // namespace + +// Test creation of a domain cookie. +TEST(CookieTest, DomainCookieGlobal) { + CefRefPtr manager = CefCookieManager::GetGlobalManager(); + EXPECT_TRUE(manager.get()); + + TestDomainCookie(manager); +} + +// Test creation of a domain cookie. +TEST(CookieTest, DomainCookieInMemory) { + CefRefPtr manager = + CefCookieManager::CreateManager(CefString()); + EXPECT_TRUE(manager.get()); + + TestDomainCookie(manager); +} + +// Test creation of a domain cookie. +TEST(CookieTest, DomainCookieOnDisk) { + ScopedTempDir temp_dir; + + // Create a new temporary directory. + EXPECT_TRUE(temp_dir.CreateUniqueTempDir()); + + CefRefPtr manager = + CefCookieManager::CreateManager(temp_dir.path().value()); + EXPECT_TRUE(manager.get()); + + TestDomainCookie(manager); +} + +// Test creation of a host cookie. +TEST(CookieTest, HostCookieGlobal) { + CefRefPtr manager = CefCookieManager::GetGlobalManager(); + EXPECT_TRUE(manager.get()); + + TestHostCookie(manager); +} + +// Test creation of a host cookie. +TEST(CookieTest, HostCookieInMemory) { + CefRefPtr manager = + CefCookieManager::CreateManager(CefString()); + EXPECT_TRUE(manager.get()); + + TestHostCookie(manager); +} + +// Test creation of a host cookie. +TEST(CookieTest, HostCookieOnDisk) { + ScopedTempDir temp_dir; + + // Create a new temporary directory. + EXPECT_TRUE(temp_dir.CreateUniqueTempDir()); + + CefRefPtr manager = + CefCookieManager::CreateManager(temp_dir.path().value()); + EXPECT_TRUE(manager.get()); + + TestHostCookie(manager); +} + +// Test creation of multiple cookies. +TEST(CookieTest, MultipleCookiesGlobal) { + CefRefPtr manager = CefCookieManager::GetGlobalManager(); + EXPECT_TRUE(manager.get()); + + TestMultipleCookies(manager); +} + +// Test creation of multiple cookies. +TEST(CookieTest, MultipleCookiesInMemory) { + CefRefPtr manager = + CefCookieManager::CreateManager(CefString()); + EXPECT_TRUE(manager.get()); + + TestMultipleCookies(manager); +} + +// Test creation of multiple cookies. +TEST(CookieTest, MultipleCookiesOnDisk) { + ScopedTempDir temp_dir; + + // Create a new temporary directory. + EXPECT_TRUE(temp_dir.CreateUniqueTempDir()); + + CefRefPtr manager = + CefCookieManager::CreateManager(temp_dir.path().value()); + EXPECT_TRUE(manager.get()); + + TestMultipleCookies(manager); +} + +TEST(CookieTest, AllCookiesGlobal) { + CefRefPtr manager = CefCookieManager::GetGlobalManager(); + EXPECT_TRUE(manager.get()); + + TestAllCookies(manager); +} + +TEST(CookieTest, AllCookiesInMemory) { + CefRefPtr manager = + CefCookieManager::CreateManager(CefString()); + EXPECT_TRUE(manager.get()); + + TestAllCookies(manager); +} + +TEST(CookieTest, AllCookiesOnDisk) { + ScopedTempDir temp_dir; + + // Create a new temporary directory. + EXPECT_TRUE(temp_dir.CreateUniqueTempDir()); + + CefRefPtr manager = + CefCookieManager::CreateManager(temp_dir.path().value()); + EXPECT_TRUE(manager.get()); + + TestAllCookies(manager); +} + +TEST(CookieTest, ChangeDirectoryGlobal) { + CefRefPtr manager = CefCookieManager::GetGlobalManager(); + EXPECT_TRUE(manager.get()); + + std::string cache_path; + CefTestSuite::GetCachePath(cache_path); + + TestChangeDirectory(manager, cache_path); +} + +TEST(CookieTest, ChangeDirectoryCreated) { + CefRefPtr manager = + CefCookieManager::CreateManager(CefString()); + EXPECT_TRUE(manager.get()); + + TestChangeDirectory(manager, CefString()); +} + + +namespace { + +const char* kCookieJSUrl1 = "http://tests/cookie1.html"; +const char* kCookieJSUrl2 = "http://tests/cookie2.html"; + +class CookieTestJSHandler : public TestHandler { + public: + CookieTestJSHandler() {} + + virtual void RunTest() OVERRIDE { + // Create =new in-memory managers. + manager1_ = CefCookieManager::CreateManager(CefString()); + manager2_ = CefCookieManager::CreateManager(CefString()); + + std::string page = + "" + "" + "COOKIE TEST1"; + AddResource(kCookieJSUrl1, page, "text/html"); + + page = + "" + "" + "COOKIE TEST2"; + AddResource(kCookieJSUrl2, page, "text/html"); + + // Create the browser + CreateBrowser(kCookieJSUrl1); + } + + virtual void OnLoadEnd(CefRefPtr browser, + CefRefPtr frame, + int httpStatusCode) OVERRIDE { + std::string url = frame->GetURL(); + if (url == kCookieJSUrl1) { + got_load_end1_.yes(); + VerifyCookie(manager1_, url, "name1", "value1", got_cookie1_); + + // Go to the next URL + frame->LoadURL(kCookieJSUrl2); + } else { + got_load_end2_.yes(); + VerifyCookie(manager2_, url, "name2", "value2", got_cookie2_); + + DestroyTest(); + } + } + + virtual CefRefPtr GetCookieManager( + CefRefPtr browser, + const CefString& main_url) OVERRIDE { + if (main_url == kCookieJSUrl1) { + // Return the first cookie manager. + got_cookie_manager1_.yes(); + return manager1_; + } else { + // Return the second cookie manager. + got_cookie_manager2_.yes(); + return manager2_; + } + } + + // Verify that the cookie was set successfully. + void VerifyCookie(CefRefPtr manager, + const std::string& url, + const std::string& name, + const std::string& value, + TrackCallback& callback) { + base::WaitableEvent event(false, false); + CookieVector cookies; + + // Get the cookie. + VisitUrlCookies(manager, url, false, cookies, false, event); + + if (cookies.size() == 1 && CefString(&cookies[0].name) == name && + CefString(&cookies[0].value) == value) { + callback.yes(); + } + } + + CefRefPtr manager1_; + CefRefPtr manager2_; + + TrackCallback got_cookie_manager1_; + TrackCallback got_cookie_manager2_; + TrackCallback got_load_end1_; + TrackCallback got_load_end2_; + TrackCallback got_cookie1_; + TrackCallback got_cookie2_; +}; + +} // namespace + +// Verify use of multiple cookie managers vis JS. +TEST(CookieTest, GetCookieManagerJS) { + CefRefPtr handler = new CookieTestJSHandler(); + handler->ExecuteTest(); + + EXPECT_TRUE(handler->got_cookie_manager1_); + EXPECT_TRUE(handler->got_cookie_manager2_); + EXPECT_TRUE(handler->got_load_end1_); + EXPECT_TRUE(handler->got_load_end2_); + EXPECT_TRUE(handler->got_cookie1_); + EXPECT_TRUE(handler->got_cookie2_); +} + + +namespace { + +const char* kCookieHttpUrl1 = "http://cookie-tests/cookie1.html"; +const char* kCookieHttpUrl2 = "http://cookie-tests/cookie2.html"; +const char* kCookieHttpUrl3 = "http://cookie-tests/cookie3.html"; + +class CookieTestHttpHandler : public TestHandler { + public: + class SchemeHandler : public CefSchemeHandler { + public: + explicit SchemeHandler(CookieTestHttpHandler* handler) + : handler_(handler), + offset_(0) {} + + virtual bool ProcessRequest(CefRefPtr request, + CefRefPtr callback) + OVERRIDE { + std::string url = request->GetURL(); + if (url == kCookieHttpUrl1) { + content_ = "COOKIE TEST1"; + cookie_ = "name1=value1"; + handler_->got_process_request1_.yes(); + } else if (url == kCookieHttpUrl2) { + content_ = "COOKIE TEST2"; + cookie_ = "name2=value2"; + handler_->got_process_request2_.yes(); + } else if (url == kCookieHttpUrl3) { + content_ = "COOKIE TEST3"; + handler_->got_process_request3_.yes(); + + // Verify that the cookie was passed in. + CefRequest::HeaderMap headerMap; + request->GetHeaderMap(headerMap); + CefRequest::HeaderMap::iterator it = headerMap.find("Cookie"); + if (it != headerMap.end() && it->second == "name2=value2") + handler_->got_process_request_cookie_.yes(); + + } + callback->HeadersAvailable(); + return true; + } + + virtual void GetResponseHeaders(CefRefPtr response, + int64& response_length, + CefString& redirectUrl) OVERRIDE { + response_length = content_.size(); + + response->SetStatus(200); + response->SetMimeType("text/html"); + + if (!cookie_.empty()) { + CefResponse::HeaderMap headerMap; + response->GetHeaderMap(headerMap); + headerMap.insert(std::make_pair("Set-Cookie", cookie_)); + response->SetHeaderMap(headerMap); + } + } + + virtual bool ReadResponse(void* data_out, + int bytes_to_read, + int& bytes_read, + CefRefPtr callback) + OVERRIDE { + bool has_data = false; + bytes_read = 0; + + size_t size = content_.size(); + if (offset_ < size) { + int transfer_size = + std::min(bytes_to_read, static_cast(size - offset_)); + memcpy(data_out, content_.c_str() + offset_, transfer_size); + offset_ += transfer_size; + + bytes_read = transfer_size; + has_data = true; + } + + return has_data; + } + + virtual void Cancel() OVERRIDE { + } + + private: + CookieTestHttpHandler* handler_; + std::string content_; + size_t offset_; + std::string cookie_; + + IMPLEMENT_REFCOUNTING(SchemeHandler); + }; + + class SchemeHandlerFactory : public CefSchemeHandlerFactory { + public: + explicit SchemeHandlerFactory(CookieTestHttpHandler* handler) + : handler_(handler) {} + + virtual CefRefPtr Create(CefRefPtr browser, + const CefString& scheme_name, + CefRefPtr request) + OVERRIDE { + std::string url = request->GetURL(); + if (url == kCookieHttpUrl3) { + // Verify that the cookie was not passed in. + CefRequest::HeaderMap headerMap; + request->GetHeaderMap(headerMap); + CefRequest::HeaderMap::iterator it = headerMap.find("Cookie"); + if (it != headerMap.end() && it->second == "name2=value2") + handler_->got_create_cookie_.yes(); + } + + return new SchemeHandler(handler_); + } + + private: + CookieTestHttpHandler* handler_; + + IMPLEMENT_REFCOUNTING(SchemeHandlerFactory); + }; + + CookieTestHttpHandler() {} + + virtual void RunTest() OVERRIDE { + // Create new in-memory managers. + manager1_ = CefCookieManager::CreateManager(CefString()); + manager2_ = CefCookieManager::CreateManager(CefString()); + + // Register the scheme handler. + CefRegisterSchemeHandlerFactory("http", "cookie-tests", + new SchemeHandlerFactory(this)); + + // Create the browser + CreateBrowser(kCookieHttpUrl1); + } + + virtual void OnLoadEnd(CefRefPtr browser, + CefRefPtr frame, + int httpStatusCode) OVERRIDE { + std::string url = frame->GetURL(); + if (url == kCookieHttpUrl1) { + got_load_end1_.yes(); + VerifyCookie(manager1_, url, "name1", "value1", got_cookie1_); + + // Go to the next URL + frame->LoadURL(kCookieHttpUrl2); + } else if (url == kCookieHttpUrl2) { + got_load_end2_.yes(); + VerifyCookie(manager2_, url, "name2", "value2", got_cookie2_); + + // Go to the next URL + frame->LoadURL(kCookieHttpUrl3); + } else { + got_load_end3_.yes(); + VerifyCookie(manager2_, url, "name2", "value2", got_cookie3_); + + // Unregister the scheme handler. + CefRegisterSchemeHandlerFactory("http", "cookie-tests", NULL); + + DestroyTest(); + } + } + + virtual CefRefPtr GetCookieManager( + CefRefPtr browser, + const CefString& main_url) OVERRIDE { + if (main_url == kCookieHttpUrl1) { + // Return the first cookie manager. + got_cookie_manager1_.yes(); + return manager1_; + } else { + // Return the second cookie manager. + got_cookie_manager2_.yes(); + return manager2_; + } + } + + // Verify that the cookie was set successfully. + void VerifyCookie(CefRefPtr manager, + const std::string& url, + const std::string& name, + const std::string& value, + TrackCallback& callback) { + base::WaitableEvent event(false, false); + CookieVector cookies; + + // Get the cookie. + VisitUrlCookies(manager, url, false, cookies, false, event); + + if (cookies.size() == 1 && CefString(&cookies[0].name) == name && + CefString(&cookies[0].value) == value) { + callback.yes(); + } + } + + CefRefPtr manager1_; + CefRefPtr manager2_; + + TrackCallback got_process_request1_; + TrackCallback got_process_request2_; + TrackCallback got_process_request3_; + TrackCallback got_create_cookie_; + TrackCallback got_process_request_cookie_; + TrackCallback got_cookie_manager1_; + TrackCallback got_cookie_manager2_; + TrackCallback got_load_end1_; + TrackCallback got_load_end2_; + TrackCallback got_load_end3_; + TrackCallback got_cookie1_; + TrackCallback got_cookie2_; + TrackCallback got_cookie3_; +}; + +} // namespace + +// Verify use of multiple cookie managers vis HTTP. +TEST(CookieTest, GetCookieManagerHttp) { + CefRefPtr handler = new CookieTestHttpHandler(); + handler->ExecuteTest(); + + EXPECT_TRUE(handler->got_process_request1_); + EXPECT_TRUE(handler->got_process_request2_); + EXPECT_TRUE(handler->got_process_request3_); + EXPECT_FALSE(handler->got_create_cookie_); + EXPECT_TRUE(handler->got_process_request_cookie_); + EXPECT_TRUE(handler->got_cookie_manager1_); + EXPECT_TRUE(handler->got_cookie_manager2_); + EXPECT_TRUE(handler->got_load_end1_); + EXPECT_TRUE(handler->got_load_end2_); + EXPECT_TRUE(handler->got_load_end3_); + EXPECT_TRUE(handler->got_cookie1_); + EXPECT_TRUE(handler->got_cookie2_); + EXPECT_TRUE(handler->got_cookie3_); }