Add callbacks for network request access to cookies (issue #2374)
This commit is contained in:
parent
d7e1312e9d
commit
d34d3d1b3b
|
@ -33,7 +33,7 @@
|
|||
// by hand. See the translator.README.txt file in the tools directory for
|
||||
// more information.
|
||||
//
|
||||
// $hash=52ba75e5a733ed0be9a064b9794c0181e714c090$
|
||||
// $hash=b8b5a62b11dbc48f0733c0522864e4dbda8b4f59$
|
||||
//
|
||||
|
||||
#ifndef CEF_INCLUDE_CAPI_CEF_REQUEST_HANDLER_CAPI_H_
|
||||
|
@ -247,6 +247,29 @@ typedef struct _cef_request_handler_t {
|
|||
const cef_string_t* scheme,
|
||||
struct _cef_auth_callback_t* callback);
|
||||
|
||||
///
|
||||
// Called on the IO thread before sending a network request with a "Cookie"
|
||||
// request header. Return true (1) to allow cookies to be included in the
|
||||
// network request or false (0) to block cookies. The |request| object should
|
||||
// not be modified in this callback.
|
||||
///
|
||||
int(CEF_CALLBACK* can_get_cookies)(struct _cef_request_handler_t* self,
|
||||
struct _cef_browser_t* browser,
|
||||
struct _cef_frame_t* frame,
|
||||
struct _cef_request_t* request);
|
||||
|
||||
///
|
||||
// Called on the IO thread when receiving a network request with a "Set-
|
||||
// Cookie" response header value represented by |cookie|. Return true (1) to
|
||||
// allow the cookie to be stored or false (0) to block the cookie. The
|
||||
// |request| object should not be modified in this callback.
|
||||
///
|
||||
int(CEF_CALLBACK* can_set_cookie)(struct _cef_request_handler_t* self,
|
||||
struct _cef_browser_t* browser,
|
||||
struct _cef_frame_t* frame,
|
||||
struct _cef_request_t* request,
|
||||
const struct _cef_cookie_t* cookie);
|
||||
|
||||
///
|
||||
// Called on the IO thread when JavaScript requests a specific storage quota
|
||||
// size via the webkitStorageInfo.requestQuota function. |origin_url| is the
|
||||
|
|
|
@ -252,6 +252,33 @@ class CefRequestHandler : public virtual CefBaseRefCounted {
|
|||
return false;
|
||||
}
|
||||
|
||||
///
|
||||
// Called on the IO thread before sending a network request with a "Cookie"
|
||||
// request header. Return true to allow cookies to be included in the network
|
||||
// request or false to block cookies. The |request| object should not be
|
||||
// modified in this callback.
|
||||
///
|
||||
/*--cef()--*/
|
||||
virtual bool CanGetCookies(CefRefPtr<CefBrowser> browser,
|
||||
CefRefPtr<CefFrame> frame,
|
||||
CefRefPtr<CefRequest> request) {
|
||||
return true;
|
||||
}
|
||||
|
||||
///
|
||||
// Called on the IO thread when receiving a network request with a
|
||||
// "Set-Cookie" response header value represented by |cookie|. Return true to
|
||||
// allow the cookie to be stored or false to block the cookie. The |request|
|
||||
// object should not be modified in this callback.
|
||||
///
|
||||
/*--cef()--*/
|
||||
virtual bool CanSetCookie(CefRefPtr<CefBrowser> browser,
|
||||
CefRefPtr<CefFrame> frame,
|
||||
CefRefPtr<CefRequest> request,
|
||||
const CefCookie& cookie) {
|
||||
return true;
|
||||
}
|
||||
|
||||
///
|
||||
// Called on the IO thread when JavaScript requests a specific storage quota
|
||||
// size via the webkitStorageInfo.requestQuota function. |origin_url| is the
|
||||
|
|
|
@ -1583,7 +1583,7 @@ void CefBrowserHostImpl::CancelContextMenu() {
|
|||
}
|
||||
|
||||
CefRefPtr<CefFrame> CefBrowserHostImpl::GetFrameForRequest(
|
||||
net::URLRequest* request) {
|
||||
const net::URLRequest* request) {
|
||||
CEF_REQUIRE_IOT();
|
||||
const content::ResourceRequestInfo* info =
|
||||
content::ResourceRequestInfo::ForRequest(request);
|
||||
|
|
|
@ -303,7 +303,7 @@ class CefBrowserHostImpl : public CefBrowserHost,
|
|||
#endif
|
||||
|
||||
// Returns the frame associated with the specified URLRequest.
|
||||
CefRefPtr<CefFrame> GetFrameForRequest(net::URLRequest* request);
|
||||
CefRefPtr<CefFrame> GetFrameForRequest(const net::URLRequest* request);
|
||||
|
||||
// Navigate as specified by the |params| argument.
|
||||
void Navigate(const CefNavigateParams& params);
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
|
||||
namespace net_util {
|
||||
|
||||
bool IsInternalRequest(net::URLRequest* request) {
|
||||
bool IsInternalRequest(const net::URLRequest* request) {
|
||||
// With PlzNavigate we now receive blob URLs. Ignore these URLs.
|
||||
// See https://crbug.com/776884 for details.
|
||||
if (request->url().SchemeIs(url::kBlobScheme)) {
|
||||
|
|
|
@ -14,7 +14,7 @@ namespace net_util {
|
|||
|
||||
// Returns true if |request| is handled internally and should not be exposed via
|
||||
// the CEF API.
|
||||
bool IsInternalRequest(net::URLRequest* request);
|
||||
bool IsInternalRequest(const net::URLRequest* request);
|
||||
|
||||
}; // namespace net_util
|
||||
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
|
||||
#include "include/cef_urlrequest.h"
|
||||
#include "libcef/browser/browser_host_impl.h"
|
||||
#include "libcef/browser/cookie_manager_impl.h"
|
||||
#include "libcef/browser/net/net_util.h"
|
||||
#include "libcef/browser/net/source_stream.h"
|
||||
#include "libcef/browser/net/url_request_user_data.h"
|
||||
|
@ -440,6 +441,64 @@ net::NetworkDelegate::AuthRequiredResponse CefNetworkDelegate::OnAuthRequired(
|
|||
return AUTH_REQUIRED_RESPONSE_NO_ACTION;
|
||||
}
|
||||
|
||||
bool CefNetworkDelegate::OnCanGetCookies(const net::URLRequest& request,
|
||||
const net::CookieList& cookie_list) {
|
||||
if (net_util::IsInternalRequest(&request))
|
||||
return true;
|
||||
|
||||
CefRefPtr<CefBrowserHostImpl> browser =
|
||||
CefBrowserHostImpl::GetBrowserForRequest(&request);
|
||||
if (browser.get()) {
|
||||
CefRefPtr<CefClient> client = browser->GetClient();
|
||||
if (client.get()) {
|
||||
CefRefPtr<CefRequestHandler> handler = client->GetRequestHandler();
|
||||
if (handler.get()) {
|
||||
CefRefPtr<CefFrame> frame = browser->GetFrameForRequest(&request);
|
||||
|
||||
CefRefPtr<CefRequestImpl> cefRequest = new CefRequestImpl();
|
||||
cefRequest->Set(&request);
|
||||
cefRequest->SetReadOnly(true);
|
||||
|
||||
return handler->CanGetCookies(browser.get(), frame, cefRequest.get());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CefNetworkDelegate::OnCanSetCookie(const net::URLRequest& request,
|
||||
const net::CanonicalCookie& cookie,
|
||||
net::CookieOptions* options) {
|
||||
if (net_util::IsInternalRequest(&request))
|
||||
return true;
|
||||
|
||||
CefRefPtr<CefBrowserHostImpl> browser =
|
||||
CefBrowserHostImpl::GetBrowserForRequest(&request);
|
||||
if (browser.get()) {
|
||||
CefRefPtr<CefClient> client = browser->GetClient();
|
||||
if (client.get()) {
|
||||
CefRefPtr<CefRequestHandler> handler = client->GetRequestHandler();
|
||||
if (handler.get()) {
|
||||
CefRefPtr<CefFrame> frame = browser->GetFrameForRequest(&request);
|
||||
|
||||
CefRefPtr<CefRequestImpl> cefRequest = new CefRequestImpl();
|
||||
cefRequest->Set(&request);
|
||||
cefRequest->SetReadOnly(true);
|
||||
|
||||
CefCookie cefCookie;
|
||||
if (!CefCookieManagerImpl::GetCefCookie(cookie, cefCookie))
|
||||
return true;
|
||||
|
||||
return handler->CanSetCookie(browser.get(), frame, cefRequest.get(),
|
||||
cefCookie);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CefNetworkDelegate::OnCanAccessFile(
|
||||
const net::URLRequest& request,
|
||||
const base::FilePath& original_path,
|
||||
|
|
|
@ -38,6 +38,11 @@ class CefNetworkDelegate : public net::NetworkDelegateImpl {
|
|||
const AuthCallback& callback,
|
||||
net::AuthCredentials* credentials) override;
|
||||
void OnCompleted(net::URLRequest* request, bool started) override;
|
||||
bool OnCanGetCookies(const net::URLRequest& request,
|
||||
const net::CookieList& cookie_list) override;
|
||||
bool OnCanSetCookie(const net::URLRequest& request,
|
||||
const net::CanonicalCookie& cookie,
|
||||
net::CookieOptions* options) override;
|
||||
bool OnCanAccessFile(const net::URLRequest& request,
|
||||
const base::FilePath& original_path,
|
||||
const base::FilePath& absolute_path) const override;
|
||||
|
|
|
@ -411,7 +411,7 @@ void CefResourceRequestJob::DoLoadCookies() {
|
|||
|
||||
void CefResourceRequestJob::CheckCookiePolicyAndLoad(
|
||||
const net::CookieList& cookie_list) {
|
||||
bool can_get_cookies = CanGetCookies(cookie_list);
|
||||
bool can_get_cookies = !cookie_list.empty() && CanGetCookies(cookie_list);
|
||||
if (can_get_cookies) {
|
||||
net::CookieList::const_iterator it = cookie_list.begin();
|
||||
for (; it != cookie_list.end(); ++it) {
|
||||
|
|
|
@ -445,7 +445,7 @@ uint64 CefRequestImpl::GetIdentifier() {
|
|||
return identifier_;
|
||||
}
|
||||
|
||||
void CefRequestImpl::Set(net::URLRequest* request) {
|
||||
void CefRequestImpl::Set(const net::URLRequest* request) {
|
||||
base::AutoLock lock_scope(lock_);
|
||||
CHECK_READONLY_RETURN_VOID();
|
||||
|
||||
|
|
|
@ -80,7 +80,7 @@ class CefRequestImpl : public CefRequest {
|
|||
uint64 GetIdentifier() override;
|
||||
|
||||
// Populate this object from the URLRequest object.
|
||||
void Set(net::URLRequest* request);
|
||||
void Set(const net::URLRequest* request);
|
||||
|
||||
// Populate the URLRequest object from this object.
|
||||
// If |changed_only| is true then only the changed fields will be updated.
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
// implementations. See the translator.README.txt file in the tools directory
|
||||
// for more information.
|
||||
//
|
||||
// $hash=419fbbe47f1b127719554892609c02a3b135c44d$
|
||||
// $hash=b4c3eec00b1889871f4e13ea05d7c00a12da1fa0$
|
||||
//
|
||||
|
||||
#include "libcef_dll/cpptoc/request_handler_cpptoc.h"
|
||||
|
@ -367,6 +367,80 @@ request_handler_get_auth_credentials(struct _cef_request_handler_t* self,
|
|||
return _retval;
|
||||
}
|
||||
|
||||
int CEF_CALLBACK
|
||||
request_handler_can_get_cookies(struct _cef_request_handler_t* self,
|
||||
cef_browser_t* browser,
|
||||
cef_frame_t* frame,
|
||||
cef_request_t* request) {
|
||||
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
|
||||
|
||||
DCHECK(self);
|
||||
if (!self)
|
||||
return 0;
|
||||
// Verify param: browser; type: refptr_diff
|
||||
DCHECK(browser);
|
||||
if (!browser)
|
||||
return 0;
|
||||
// Verify param: frame; type: refptr_diff
|
||||
DCHECK(frame);
|
||||
if (!frame)
|
||||
return 0;
|
||||
// Verify param: request; type: refptr_diff
|
||||
DCHECK(request);
|
||||
if (!request)
|
||||
return 0;
|
||||
|
||||
// Execute
|
||||
bool _retval = CefRequestHandlerCppToC::Get(self)->CanGetCookies(
|
||||
CefBrowserCToCpp::Wrap(browser), CefFrameCToCpp::Wrap(frame),
|
||||
CefRequestCToCpp::Wrap(request));
|
||||
|
||||
// Return type: bool
|
||||
return _retval;
|
||||
}
|
||||
|
||||
int CEF_CALLBACK
|
||||
request_handler_can_set_cookie(struct _cef_request_handler_t* self,
|
||||
cef_browser_t* browser,
|
||||
cef_frame_t* frame,
|
||||
cef_request_t* request,
|
||||
const struct _cef_cookie_t* cookie) {
|
||||
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
|
||||
|
||||
DCHECK(self);
|
||||
if (!self)
|
||||
return 0;
|
||||
// Verify param: browser; type: refptr_diff
|
||||
DCHECK(browser);
|
||||
if (!browser)
|
||||
return 0;
|
||||
// Verify param: frame; type: refptr_diff
|
||||
DCHECK(frame);
|
||||
if (!frame)
|
||||
return 0;
|
||||
// Verify param: request; type: refptr_diff
|
||||
DCHECK(request);
|
||||
if (!request)
|
||||
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 = CefRequestHandlerCppToC::Get(self)->CanSetCookie(
|
||||
CefBrowserCToCpp::Wrap(browser), CefFrameCToCpp::Wrap(frame),
|
||||
CefRequestCToCpp::Wrap(request), cookieObj);
|
||||
|
||||
// Return type: bool
|
||||
return _retval;
|
||||
}
|
||||
|
||||
int CEF_CALLBACK
|
||||
request_handler_on_quota_request(struct _cef_request_handler_t* self,
|
||||
cef_browser_t* browser,
|
||||
|
@ -603,6 +677,8 @@ CefRequestHandlerCppToC::CefRequestHandlerCppToC() {
|
|||
GetStruct()->on_resource_load_complete =
|
||||
request_handler_on_resource_load_complete;
|
||||
GetStruct()->get_auth_credentials = request_handler_get_auth_credentials;
|
||||
GetStruct()->can_get_cookies = request_handler_can_get_cookies;
|
||||
GetStruct()->can_set_cookie = request_handler_can_set_cookie;
|
||||
GetStruct()->on_quota_request = request_handler_on_quota_request;
|
||||
GetStruct()->on_protocol_execution = request_handler_on_protocol_execution;
|
||||
GetStruct()->on_certificate_error = request_handler_on_certificate_error;
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
// implementations. See the translator.README.txt file in the tools directory
|
||||
// for more information.
|
||||
//
|
||||
// $hash=9bcd78135c26925b3e33662e92497d1ef7d85642$
|
||||
// $hash=fbd234d6060aadc1bf5ee0efce5d8cb2c4a0e022$
|
||||
//
|
||||
|
||||
#include "libcef_dll/ctocpp/request_handler_ctocpp.h"
|
||||
|
@ -353,6 +353,69 @@ bool CefRequestHandlerCToCpp::GetAuthCredentials(
|
|||
return _retval ? true : false;
|
||||
}
|
||||
|
||||
bool CefRequestHandlerCToCpp::CanGetCookies(CefRefPtr<CefBrowser> browser,
|
||||
CefRefPtr<CefFrame> frame,
|
||||
CefRefPtr<CefRequest> request) {
|
||||
cef_request_handler_t* _struct = GetStruct();
|
||||
if (CEF_MEMBER_MISSING(_struct, can_get_cookies))
|
||||
return false;
|
||||
|
||||
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
|
||||
|
||||
// Verify param: browser; type: refptr_diff
|
||||
DCHECK(browser.get());
|
||||
if (!browser.get())
|
||||
return false;
|
||||
// Verify param: frame; type: refptr_diff
|
||||
DCHECK(frame.get());
|
||||
if (!frame.get())
|
||||
return false;
|
||||
// Verify param: request; type: refptr_diff
|
||||
DCHECK(request.get());
|
||||
if (!request.get())
|
||||
return false;
|
||||
|
||||
// Execute
|
||||
int _retval = _struct->can_get_cookies(
|
||||
_struct, CefBrowserCppToC::Wrap(browser), CefFrameCppToC::Wrap(frame),
|
||||
CefRequestCppToC::Wrap(request));
|
||||
|
||||
// Return type: bool
|
||||
return _retval ? true : false;
|
||||
}
|
||||
|
||||
bool CefRequestHandlerCToCpp::CanSetCookie(CefRefPtr<CefBrowser> browser,
|
||||
CefRefPtr<CefFrame> frame,
|
||||
CefRefPtr<CefRequest> request,
|
||||
const CefCookie& cookie) {
|
||||
cef_request_handler_t* _struct = GetStruct();
|
||||
if (CEF_MEMBER_MISSING(_struct, can_set_cookie))
|
||||
return false;
|
||||
|
||||
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
|
||||
|
||||
// Verify param: browser; type: refptr_diff
|
||||
DCHECK(browser.get());
|
||||
if (!browser.get())
|
||||
return false;
|
||||
// Verify param: frame; type: refptr_diff
|
||||
DCHECK(frame.get());
|
||||
if (!frame.get())
|
||||
return false;
|
||||
// Verify param: request; type: refptr_diff
|
||||
DCHECK(request.get());
|
||||
if (!request.get())
|
||||
return false;
|
||||
|
||||
// Execute
|
||||
int _retval = _struct->can_set_cookie(
|
||||
_struct, CefBrowserCppToC::Wrap(browser), CefFrameCppToC::Wrap(frame),
|
||||
CefRequestCppToC::Wrap(request), &cookie);
|
||||
|
||||
// Return type: bool
|
||||
return _retval ? true : false;
|
||||
}
|
||||
|
||||
bool CefRequestHandlerCToCpp::OnQuotaRequest(
|
||||
CefRefPtr<CefBrowser> browser,
|
||||
const CefString& origin_url,
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
// implementations. See the translator.README.txt file in the tools directory
|
||||
// for more information.
|
||||
//
|
||||
// $hash=a28a81ae22b7edb9dfb3a9df72c48a96971b7017$
|
||||
// $hash=cde69cb97f29cb75da85bb709470f73d9e57f5bc$
|
||||
//
|
||||
|
||||
#ifndef CEF_LIBCEF_DLL_CTOCPP_REQUEST_HANDLER_CTOCPP_H_
|
||||
|
@ -80,6 +80,13 @@ class CefRequestHandlerCToCpp
|
|||
const CefString& realm,
|
||||
const CefString& scheme,
|
||||
CefRefPtr<CefAuthCallback> callback) override;
|
||||
bool CanGetCookies(CefRefPtr<CefBrowser> browser,
|
||||
CefRefPtr<CefFrame> frame,
|
||||
CefRefPtr<CefRequest> request) override;
|
||||
bool CanSetCookie(CefRefPtr<CefBrowser> browser,
|
||||
CefRefPtr<CefFrame> frame,
|
||||
CefRefPtr<CefRequest> request,
|
||||
const CefCookie& cookie) override;
|
||||
bool OnQuotaRequest(CefRefPtr<CefBrowser> browser,
|
||||
const CefString& origin_url,
|
||||
int64 new_size,
|
||||
|
|
|
@ -10,8 +10,10 @@
|
|||
#include "include/base/cef_bind.h"
|
||||
#include "include/base/cef_scoped_ptr.h"
|
||||
#include "include/cef_cookie.h"
|
||||
#include "include/cef_server.h"
|
||||
#include "include/wrapper/cef_closure_task.h"
|
||||
#include "include/wrapper/cef_stream_resource_handler.h"
|
||||
#include "tests/ceftests/routing_test_handler.h"
|
||||
#include "tests/ceftests/test_handler.h"
|
||||
#include "tests/ceftests/test_util.h"
|
||||
#include "tests/gtest/include/gtest/gtest.h"
|
||||
|
@ -1681,6 +1683,910 @@ TEST(RequestHandlerTest, ResponseFilterError) {
|
|||
ReleaseAndWaitForDestructor(handler);
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
const char kCookieAccessScheme[] = "http";
|
||||
const char kCookieAccessDomain[] = "test-cookies.com";
|
||||
const char kCookieAccessServerIP[] = "127.0.0.1";
|
||||
const uint16 kCookieAccessServerPort = 8099;
|
||||
|
||||
std::string GetCookieAccessOrigin(bool server_backend) {
|
||||
std::stringstream ss;
|
||||
if (server_backend) {
|
||||
ss << kCookieAccessScheme << "://" << kCookieAccessServerIP << ":"
|
||||
<< kCookieAccessServerPort;
|
||||
} else {
|
||||
ss << kCookieAccessScheme << "://" << kCookieAccessDomain;
|
||||
}
|
||||
ss << "/";
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
std::string GetCookieAccessUrl1(bool server_backend) {
|
||||
return GetCookieAccessOrigin(server_backend) + "cookie1.html";
|
||||
}
|
||||
|
||||
std::string GetCookieAccessUrl2(bool server_backend) {
|
||||
return GetCookieAccessOrigin(server_backend) + "cookie2.html";
|
||||
}
|
||||
|
||||
void TestCookieString(const std::string& cookie_str,
|
||||
TrackCallback& got_cookie_js,
|
||||
TrackCallback& got_cookie_net) {
|
||||
if (cookie_str.find("name_js=value_js") != std::string::npos) {
|
||||
got_cookie_js.yes();
|
||||
}
|
||||
if (cookie_str.find("name_net=value_net") != std::string::npos) {
|
||||
got_cookie_net.yes();
|
||||
}
|
||||
}
|
||||
|
||||
struct CookieAccessData {
|
||||
CefRefPtr<CefResponse> response;
|
||||
std::string response_data;
|
||||
|
||||
TrackCallback got_request_;
|
||||
TrackCallback got_cookie_js_;
|
||||
TrackCallback got_cookie_net_;
|
||||
|
||||
// Only used with scheme handler backend.
|
||||
TrackCallback got_can_set_cookie_js_;
|
||||
TrackCallback got_can_set_cookie_net_;
|
||||
TrackCallback got_can_get_cookie_js_;
|
||||
TrackCallback got_can_get_cookie_net_;
|
||||
};
|
||||
|
||||
class CookieAccessResponseHandler {
|
||||
public:
|
||||
CookieAccessResponseHandler() {}
|
||||
virtual void AddResponse(const std::string& url, CookieAccessData* data) = 0;
|
||||
|
||||
protected:
|
||||
virtual ~CookieAccessResponseHandler() {}
|
||||
};
|
||||
|
||||
std::string GetHeaderValue(const CefServer::HeaderMap& header_map,
|
||||
const std::string& header_name) {
|
||||
CefServer::HeaderMap::const_iterator it = header_map.find(header_name);
|
||||
if (it != header_map.end())
|
||||
return it->second;
|
||||
return std::string();
|
||||
}
|
||||
|
||||
// Serves request responses.
|
||||
class CookieAccessSchemeHandler : public CefResourceHandler {
|
||||
public:
|
||||
explicit CookieAccessSchemeHandler(CookieAccessData* data)
|
||||
: data_(data), offset_(0) {}
|
||||
|
||||
bool ProcessRequest(CefRefPtr<CefRequest> request,
|
||||
CefRefPtr<CefCallback> callback) override {
|
||||
EXPECT_TRUE(CefCurrentlyOn(TID_IO));
|
||||
|
||||
CefRequest::HeaderMap headerMap;
|
||||
request->GetHeaderMap(headerMap);
|
||||
const std::string& cookie_str = GetHeaderValue(headerMap, "Cookie");
|
||||
TestCookieString(cookie_str, data_->got_cookie_js_, data_->got_cookie_net_);
|
||||
|
||||
// Continue immediately.
|
||||
callback->Continue();
|
||||
return true;
|
||||
}
|
||||
|
||||
void GetResponseHeaders(CefRefPtr<CefResponse> response,
|
||||
int64& response_length,
|
||||
CefString& redirectUrl) override {
|
||||
EXPECT_TRUE(CefCurrentlyOn(TID_IO));
|
||||
|
||||
response->SetStatus(data_->response->GetStatus());
|
||||
response->SetStatusText(data_->response->GetStatusText());
|
||||
response->SetMimeType(data_->response->GetMimeType());
|
||||
|
||||
CefResponse::HeaderMap headerMap;
|
||||
data_->response->GetHeaderMap(headerMap);
|
||||
response->SetHeaderMap(headerMap);
|
||||
|
||||
response_length = data_->response_data.length();
|
||||
}
|
||||
|
||||
bool ReadResponse(void* response_data_out,
|
||||
int bytes_to_read,
|
||||
int& bytes_read,
|
||||
CefRefPtr<CefCallback> callback) override {
|
||||
EXPECT_TRUE(CefCurrentlyOn(TID_IO));
|
||||
|
||||
bool has_data = false;
|
||||
bytes_read = 0;
|
||||
|
||||
size_t size = data_->response_data.length();
|
||||
if (offset_ < size) {
|
||||
int transfer_size =
|
||||
std::min(bytes_to_read, static_cast<int>(size - offset_));
|
||||
memcpy(response_data_out, data_->response_data.c_str() + offset_,
|
||||
transfer_size);
|
||||
offset_ += transfer_size;
|
||||
|
||||
bytes_read = transfer_size;
|
||||
has_data = true;
|
||||
}
|
||||
|
||||
return has_data;
|
||||
}
|
||||
|
||||
bool CanGetCookie(const CefCookie& cookie) override {
|
||||
EXPECT_TRUE(CefCurrentlyOn(TID_IO));
|
||||
TestCookie(cookie, data_->got_can_get_cookie_js_,
|
||||
data_->got_can_get_cookie_net_);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CanSetCookie(const CefCookie& cookie) override {
|
||||
EXPECT_TRUE(CefCurrentlyOn(TID_IO));
|
||||
TestCookie(cookie, data_->got_can_set_cookie_js_,
|
||||
data_->got_can_set_cookie_net_);
|
||||
return true;
|
||||
}
|
||||
|
||||
void Cancel() override { EXPECT_TRUE(CefCurrentlyOn(TID_IO)); }
|
||||
|
||||
private:
|
||||
static void TestCookie(const CefCookie& cookie,
|
||||
TrackCallback& got_cookie_js,
|
||||
TrackCallback& got_cookie_net) {
|
||||
const std::string& cookie_name = CefString(&cookie.name);
|
||||
const std::string& cookie_val = CefString(&cookie.value);
|
||||
if (cookie_name == "name_js") {
|
||||
EXPECT_STREQ("value_js", cookie_val.c_str());
|
||||
got_cookie_js.yes();
|
||||
} else if (cookie_name == "name_net") {
|
||||
EXPECT_STREQ("value_net", cookie_val.c_str());
|
||||
got_cookie_net.yes();
|
||||
} else {
|
||||
ADD_FAILURE() << "Unexpected cookie: " << cookie_name;
|
||||
}
|
||||
}
|
||||
|
||||
// |data_| is not owned by this object.
|
||||
CookieAccessData* data_;
|
||||
|
||||
size_t offset_;
|
||||
|
||||
IMPLEMENT_REFCOUNTING(CookieAccessSchemeHandler);
|
||||
};
|
||||
|
||||
class CookieAccessSchemeHandlerFactory : public CefSchemeHandlerFactory,
|
||||
public CookieAccessResponseHandler {
|
||||
public:
|
||||
CookieAccessSchemeHandlerFactory() {}
|
||||
|
||||
CefRefPtr<CefResourceHandler> Create(CefRefPtr<CefBrowser> browser,
|
||||
CefRefPtr<CefFrame> frame,
|
||||
const CefString& scheme_name,
|
||||
CefRefPtr<CefRequest> request) override {
|
||||
EXPECT_TRUE(CefCurrentlyOn(TID_IO));
|
||||
const std::string& url = request->GetURL();
|
||||
ResponseDataMap::const_iterator it = data_map_.find(url);
|
||||
if (it != data_map_.end()) {
|
||||
it->second->got_request_.yes();
|
||||
|
||||
// There should be no cookie data in this callback.
|
||||
CefRequest::HeaderMap headerMap;
|
||||
request->GetHeaderMap(headerMap);
|
||||
EXPECT_TRUE(headerMap.find("Cookie") == headerMap.end());
|
||||
|
||||
return new CookieAccessSchemeHandler(it->second);
|
||||
}
|
||||
|
||||
// Unknown test.
|
||||
ADD_FAILURE() << "Unexpected url: " << url;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void AddResponse(const std::string& url, CookieAccessData* data) override {
|
||||
data_map_.insert(std::make_pair(url, data));
|
||||
}
|
||||
|
||||
void Shutdown(const base::Closure& complete_callback) {
|
||||
if (!CefCurrentlyOn(TID_IO)) {
|
||||
CefPostTask(TID_IO,
|
||||
base::Bind(&CookieAccessSchemeHandlerFactory::Shutdown, this,
|
||||
complete_callback));
|
||||
return;
|
||||
}
|
||||
|
||||
complete_callback.Run();
|
||||
}
|
||||
|
||||
private:
|
||||
// Map of URL to Data.
|
||||
typedef std::map<std::string, CookieAccessData*> ResponseDataMap;
|
||||
ResponseDataMap data_map_;
|
||||
|
||||
IMPLEMENT_REFCOUNTING(CookieAccessSchemeHandlerFactory);
|
||||
};
|
||||
|
||||
// HTTP server handler.
|
||||
class CookieAccessServerHandler : public CefServerHandler,
|
||||
public CookieAccessResponseHandler {
|
||||
public:
|
||||
CookieAccessServerHandler()
|
||||
: initialized_(false),
|
||||
expected_connection_ct_(-1),
|
||||
actual_connection_ct_(0),
|
||||
expected_http_request_ct_(-1),
|
||||
actual_http_request_ct_(0) {}
|
||||
|
||||
virtual ~CookieAccessServerHandler() { RunCompleteCallback(); }
|
||||
|
||||
// Must be called before CreateServer().
|
||||
void AddResponse(const std::string& url, CookieAccessData* data) override {
|
||||
EXPECT_FALSE(initialized_);
|
||||
data_map_.insert(std::make_pair(url, data));
|
||||
}
|
||||
|
||||
// Must be called before CreateServer().
|
||||
void SetExpectedRequestCount(int count) {
|
||||
EXPECT_FALSE(initialized_);
|
||||
expected_connection_ct_ = expected_http_request_ct_ = count;
|
||||
}
|
||||
|
||||
// |complete_callback| will be executed on the UI thread after the server is
|
||||
// started.
|
||||
void CreateServer(const base::Closure& complete_callback) {
|
||||
EXPECT_UI_THREAD();
|
||||
|
||||
if (expected_connection_ct_ < 0) {
|
||||
// Default to the assumption of one request per registered URL.
|
||||
SetExpectedRequestCount(static_cast<int>(data_map_.size()));
|
||||
}
|
||||
|
||||
EXPECT_FALSE(initialized_);
|
||||
initialized_ = true;
|
||||
|
||||
EXPECT_TRUE(complete_callback_.is_null());
|
||||
complete_callback_ = complete_callback;
|
||||
|
||||
CefServer::CreateServer(kCookieAccessServerIP, kCookieAccessServerPort, 10,
|
||||
this);
|
||||
}
|
||||
|
||||
// Results in a call to VerifyResults() and eventual execution of the
|
||||
// |complete_callback| on the UI thread via CookieAccessServerHandler
|
||||
// destruction.
|
||||
void ShutdownServer(const base::Closure& complete_callback) {
|
||||
EXPECT_UI_THREAD();
|
||||
|
||||
EXPECT_TRUE(complete_callback_.is_null());
|
||||
complete_callback_ = complete_callback;
|
||||
|
||||
EXPECT_TRUE(server_);
|
||||
if (server_)
|
||||
server_->Shutdown();
|
||||
}
|
||||
|
||||
void OnServerCreated(CefRefPtr<CefServer> server) override {
|
||||
EXPECT_TRUE(server);
|
||||
EXPECT_TRUE(server->IsRunning());
|
||||
EXPECT_FALSE(server->HasConnection());
|
||||
|
||||
EXPECT_FALSE(got_server_created_);
|
||||
got_server_created_.yes();
|
||||
|
||||
EXPECT_FALSE(server_);
|
||||
server_ = server;
|
||||
|
||||
EXPECT_FALSE(server_runner_);
|
||||
server_runner_ = server_->GetTaskRunner();
|
||||
EXPECT_TRUE(server_runner_);
|
||||
EXPECT_TRUE(server_runner_->BelongsToCurrentThread());
|
||||
|
||||
CefPostTask(
|
||||
TID_UI,
|
||||
base::Bind(&CookieAccessServerHandler::RunCompleteCallback, this));
|
||||
}
|
||||
|
||||
void OnServerDestroyed(CefRefPtr<CefServer> server) override {
|
||||
EXPECT_TRUE(VerifyServer(server));
|
||||
EXPECT_FALSE(server->IsRunning());
|
||||
EXPECT_FALSE(server->HasConnection());
|
||||
|
||||
EXPECT_FALSE(got_server_destroyed_);
|
||||
got_server_destroyed_.yes();
|
||||
|
||||
server_ = nullptr;
|
||||
|
||||
VerifyResults();
|
||||
}
|
||||
|
||||
void OnClientConnected(CefRefPtr<CefServer> server,
|
||||
int connection_id) override {
|
||||
EXPECT_TRUE(VerifyServer(server));
|
||||
EXPECT_TRUE(server->HasConnection());
|
||||
EXPECT_TRUE(server->IsValidConnection(connection_id));
|
||||
|
||||
EXPECT_TRUE(connection_id_set_.find(connection_id) ==
|
||||
connection_id_set_.end());
|
||||
connection_id_set_.insert(connection_id);
|
||||
|
||||
actual_connection_ct_++;
|
||||
}
|
||||
|
||||
void OnClientDisconnected(CefRefPtr<CefServer> server,
|
||||
int connection_id) override {
|
||||
EXPECT_TRUE(VerifyServer(server));
|
||||
EXPECT_FALSE(server->IsValidConnection(connection_id));
|
||||
|
||||
ConnectionIdSet::iterator it = connection_id_set_.find(connection_id);
|
||||
EXPECT_TRUE(it != connection_id_set_.end());
|
||||
connection_id_set_.erase(it);
|
||||
}
|
||||
|
||||
void OnHttpRequest(CefRefPtr<CefServer> server,
|
||||
int connection_id,
|
||||
const CefString& client_address,
|
||||
CefRefPtr<CefRequest> request) override {
|
||||
EXPECT_TRUE(VerifyServer(server));
|
||||
EXPECT_TRUE(VerifyConnection(connection_id));
|
||||
EXPECT_FALSE(client_address.empty());
|
||||
|
||||
// Log the requests for better error reporting.
|
||||
request_log_ += request->GetMethod().ToString() + " " +
|
||||
request->GetURL().ToString() + "\n";
|
||||
|
||||
HandleRequest(server, connection_id, request);
|
||||
|
||||
actual_http_request_ct_++;
|
||||
}
|
||||
|
||||
void OnWebSocketRequest(CefRefPtr<CefServer> server,
|
||||
int connection_id,
|
||||
const CefString& client_address,
|
||||
CefRefPtr<CefRequest> request,
|
||||
CefRefPtr<CefCallback> callback) override {
|
||||
NOTREACHED();
|
||||
}
|
||||
|
||||
void OnWebSocketConnected(CefRefPtr<CefServer> server,
|
||||
int connection_id) override {
|
||||
NOTREACHED();
|
||||
}
|
||||
|
||||
void OnWebSocketMessage(CefRefPtr<CefServer> server,
|
||||
int connection_id,
|
||||
const void* data,
|
||||
size_t data_size) override {
|
||||
NOTREACHED();
|
||||
}
|
||||
|
||||
private:
|
||||
bool RunningOnServerThread() {
|
||||
return server_runner_ && server_runner_->BelongsToCurrentThread();
|
||||
}
|
||||
|
||||
bool VerifyServer(CefRefPtr<CefServer> server) {
|
||||
V_DECLARE();
|
||||
V_EXPECT_TRUE(RunningOnServerThread());
|
||||
V_EXPECT_TRUE(server);
|
||||
V_EXPECT_TRUE(server_);
|
||||
V_EXPECT_TRUE(server->GetAddress().ToString() ==
|
||||
server_->GetAddress().ToString());
|
||||
V_RETURN();
|
||||
}
|
||||
|
||||
bool VerifyConnection(int connection_id) {
|
||||
return connection_id_set_.find(connection_id) != connection_id_set_.end();
|
||||
}
|
||||
|
||||
void VerifyResults() {
|
||||
EXPECT_TRUE(RunningOnServerThread());
|
||||
|
||||
EXPECT_TRUE(got_server_created_);
|
||||
EXPECT_TRUE(got_server_destroyed_);
|
||||
EXPECT_TRUE(connection_id_set_.empty());
|
||||
EXPECT_EQ(expected_connection_ct_, actual_connection_ct_) << request_log_;
|
||||
EXPECT_EQ(expected_http_request_ct_, actual_http_request_ct_)
|
||||
<< request_log_;
|
||||
}
|
||||
|
||||
void HandleRequest(CefRefPtr<CefServer> server,
|
||||
int connection_id,
|
||||
CefRefPtr<CefRequest> request) {
|
||||
const std::string& url = request->GetURL();
|
||||
ResponseDataMap::const_iterator it = data_map_.find(url);
|
||||
if (it != data_map_.end()) {
|
||||
it->second->got_request_.yes();
|
||||
|
||||
CefRequest::HeaderMap headerMap;
|
||||
request->GetHeaderMap(headerMap);
|
||||
const std::string& cookie_str = GetHeaderValue(headerMap, "cookie");
|
||||
TestCookieString(cookie_str, it->second->got_cookie_js_,
|
||||
it->second->got_cookie_net_);
|
||||
|
||||
SendResponse(server, connection_id, it->second->response,
|
||||
it->second->response_data);
|
||||
} else {
|
||||
// Unknown test.
|
||||
ADD_FAILURE() << "Unexpected url: " << url;
|
||||
server->SendHttp500Response(connection_id, "Unknown test");
|
||||
}
|
||||
}
|
||||
|
||||
void SendResponse(CefRefPtr<CefServer> server,
|
||||
int connection_id,
|
||||
CefRefPtr<CefResponse> response,
|
||||
const std::string& response_data) {
|
||||
int response_code = response->GetStatus();
|
||||
const CefString& content_type = response->GetMimeType();
|
||||
int64 content_length = static_cast<int64>(response_data.size());
|
||||
|
||||
CefResponse::HeaderMap extra_headers;
|
||||
response->GetHeaderMap(extra_headers);
|
||||
|
||||
server->SendHttpResponse(connection_id, response_code, content_type,
|
||||
content_length, extra_headers);
|
||||
|
||||
if (content_length != 0) {
|
||||
server->SendRawData(connection_id, response_data.data(),
|
||||
response_data.size());
|
||||
server->CloseConnection(connection_id);
|
||||
}
|
||||
|
||||
// The connection should be closed.
|
||||
EXPECT_FALSE(server->IsValidConnection(connection_id));
|
||||
}
|
||||
|
||||
void RunCompleteCallback() {
|
||||
EXPECT_UI_THREAD();
|
||||
|
||||
EXPECT_FALSE(complete_callback_.is_null());
|
||||
complete_callback_.Run();
|
||||
complete_callback_.Reset();
|
||||
}
|
||||
|
||||
// Map of URL to Data.
|
||||
typedef std::map<std::string, CookieAccessData*> ResponseDataMap;
|
||||
ResponseDataMap data_map_;
|
||||
|
||||
CefRefPtr<CefServer> server_;
|
||||
CefRefPtr<CefTaskRunner> server_runner_;
|
||||
bool initialized_;
|
||||
|
||||
// Only accessed on the UI thread.
|
||||
base::Closure complete_callback_;
|
||||
|
||||
// After initialization the below members are only accessed on the server
|
||||
// thread.
|
||||
|
||||
TrackCallback got_server_created_;
|
||||
TrackCallback got_server_destroyed_;
|
||||
|
||||
typedef std::set<int> ConnectionIdSet;
|
||||
ConnectionIdSet connection_id_set_;
|
||||
|
||||
int expected_connection_ct_;
|
||||
int actual_connection_ct_;
|
||||
int expected_http_request_ct_;
|
||||
int actual_http_request_ct_;
|
||||
|
||||
std::string request_log_;
|
||||
|
||||
IMPLEMENT_REFCOUNTING(CookieAccessServerHandler);
|
||||
DISALLOW_COPY_AND_ASSIGN(CookieAccessServerHandler);
|
||||
};
|
||||
|
||||
class CookieAccessTestHandler : public RoutingTestHandler {
|
||||
public:
|
||||
enum TestMode {
|
||||
ALLOW = 0,
|
||||
BLOCK_READ = 1 << 0,
|
||||
BLOCK_WRITE = 1 << 1,
|
||||
BLOCK_ALL = BLOCK_READ | BLOCK_WRITE,
|
||||
};
|
||||
|
||||
CookieAccessTestHandler(TestMode test_mode, bool server_backend)
|
||||
: test_mode_(test_mode), server_backend_(server_backend) {}
|
||||
|
||||
void RunTest() override {
|
||||
cookie_manager_ = CefCookieManager::GetGlobalManager(nullptr);
|
||||
SetTestTimeout();
|
||||
|
||||
CefPostTask(TID_UI,
|
||||
base::Bind(&CookieAccessTestHandler::StartBackend, this,
|
||||
base::Bind(&CookieAccessTestHandler::RunTestContinue,
|
||||
this)));
|
||||
}
|
||||
|
||||
void DestroyTest() override {
|
||||
if (!CefCurrentlyOn(TID_UI)) {
|
||||
CefPostTask(TID_UI,
|
||||
base::Bind(&CookieAccessTestHandler::DestroyTest, this));
|
||||
return;
|
||||
}
|
||||
|
||||
cookie_manager_ = NULL;
|
||||
|
||||
// Always get a call to CanSetCookie for the 1st network request due to the
|
||||
// network cookie.
|
||||
EXPECT_TRUE(got_can_set_cookie1_);
|
||||
// Always get a call to CanGetCookies for the 2nd network request due to the
|
||||
// JS cookie.
|
||||
EXPECT_TRUE(got_can_get_cookies2_);
|
||||
|
||||
// Always get the JS cookie via JS.
|
||||
EXPECT_TRUE(got_cookie_js1_);
|
||||
EXPECT_TRUE(got_cookie_js2_);
|
||||
EXPECT_TRUE(got_cookie_js3_);
|
||||
|
||||
// Only get the net cookie via JS if cookie write was allowed.
|
||||
if (test_mode_ & BLOCK_WRITE) {
|
||||
EXPECT_FALSE(got_cookie_net1_);
|
||||
EXPECT_FALSE(got_cookie_net2_);
|
||||
EXPECT_FALSE(got_cookie_net3_);
|
||||
} else {
|
||||
EXPECT_TRUE(got_cookie_net1_);
|
||||
EXPECT_TRUE(got_cookie_net2_);
|
||||
EXPECT_TRUE(got_cookie_net3_);
|
||||
}
|
||||
|
||||
// Got both network requests.
|
||||
EXPECT_TRUE(data1_.got_request_);
|
||||
EXPECT_TRUE(data2_.got_request_);
|
||||
|
||||
// No cookies sent for the 1st network request.
|
||||
EXPECT_FALSE(data1_.got_cookie_js_);
|
||||
EXPECT_FALSE(data1_.got_cookie_net_);
|
||||
|
||||
// 2nd network request...
|
||||
if (test_mode_ & BLOCK_READ) {
|
||||
// No cookies sent if reading was blocked.
|
||||
EXPECT_FALSE(data2_.got_cookie_js_);
|
||||
EXPECT_FALSE(data2_.got_cookie_net_);
|
||||
} else if (test_mode_ & BLOCK_WRITE) {
|
||||
// Only JS cookie sent if writing was blocked.
|
||||
EXPECT_TRUE(data2_.got_cookie_js_);
|
||||
EXPECT_FALSE(data2_.got_cookie_net_);
|
||||
} else {
|
||||
// All cookies sent.
|
||||
EXPECT_TRUE(data2_.got_cookie_js_);
|
||||
EXPECT_TRUE(data2_.got_cookie_net_);
|
||||
}
|
||||
|
||||
if (!server_backend_) {
|
||||
// No query to get cookies with the 1st network request because none have
|
||||
// been set yet.
|
||||
EXPECT_FALSE(data1_.got_can_get_cookie_js_);
|
||||
EXPECT_FALSE(data1_.got_can_get_cookie_net_);
|
||||
|
||||
// JS cookie is not set via a network request.
|
||||
EXPECT_FALSE(data1_.got_can_set_cookie_js_);
|
||||
EXPECT_FALSE(data2_.got_can_set_cookie_js_);
|
||||
|
||||
// No query to set the net cookie for the 1st network request if write was
|
||||
// blocked.
|
||||
if (test_mode_ & BLOCK_WRITE) {
|
||||
EXPECT_FALSE(data1_.got_can_set_cookie_net_);
|
||||
} else {
|
||||
EXPECT_TRUE(data1_.got_can_set_cookie_net_);
|
||||
}
|
||||
|
||||
// Net cookie is not set via the 2nd network request.
|
||||
EXPECT_FALSE(data2_.got_can_set_cookie_net_);
|
||||
|
||||
// No query to get the JS cookie for the 2nd network request if read was
|
||||
// blocked.
|
||||
if (test_mode_ & BLOCK_READ) {
|
||||
EXPECT_FALSE(data2_.got_can_get_cookie_js_);
|
||||
} else {
|
||||
EXPECT_TRUE(data2_.got_can_get_cookie_js_);
|
||||
}
|
||||
|
||||
// No query to get the net cookie for the 2nd network request if read or
|
||||
// write (of the net cookie) was blocked.
|
||||
if (test_mode_ & (BLOCK_READ | BLOCK_WRITE)) {
|
||||
EXPECT_FALSE(data2_.got_can_get_cookie_net_);
|
||||
} else {
|
||||
EXPECT_TRUE(data2_.got_can_get_cookie_net_);
|
||||
}
|
||||
}
|
||||
|
||||
TestHandler::DestroyTest();
|
||||
}
|
||||
|
||||
bool CanGetCookies(CefRefPtr<CefBrowser> browser,
|
||||
CefRefPtr<CefFrame> frame,
|
||||
CefRefPtr<CefRequest> request) override {
|
||||
EXPECT_TRUE(CefCurrentlyOn(TID_IO));
|
||||
|
||||
const std::string& url = request->GetURL();
|
||||
if (url == GetCookieAccessUrl2(server_backend_)) {
|
||||
EXPECT_FALSE(got_can_get_cookies2_);
|
||||
got_can_get_cookies2_.yes();
|
||||
} else {
|
||||
ADD_FAILURE() << "Unexpected url: " << url;
|
||||
}
|
||||
|
||||
return !(test_mode_ & BLOCK_READ);
|
||||
}
|
||||
|
||||
bool CanSetCookie(CefRefPtr<CefBrowser> browser,
|
||||
CefRefPtr<CefFrame> frame,
|
||||
CefRefPtr<CefRequest> request,
|
||||
const CefCookie& cookie) override {
|
||||
EXPECT_TRUE(CefCurrentlyOn(TID_IO));
|
||||
|
||||
// Expecting the network cookie only.
|
||||
EXPECT_STREQ("name_net", CefString(&cookie.name).ToString().c_str());
|
||||
EXPECT_STREQ("value_net", CefString(&cookie.value).ToString().c_str());
|
||||
|
||||
const std::string& url = request->GetURL();
|
||||
if (url == GetCookieAccessUrl1(server_backend_)) {
|
||||
EXPECT_FALSE(got_can_set_cookie1_);
|
||||
got_can_set_cookie1_.yes();
|
||||
} else {
|
||||
ADD_FAILURE() << "Unexpected url: " << url;
|
||||
}
|
||||
|
||||
return !(test_mode_ & BLOCK_WRITE);
|
||||
}
|
||||
|
||||
bool OnQuery(CefRefPtr<CefBrowser> browser,
|
||||
CefRefPtr<CefFrame> frame,
|
||||
int64 query_id,
|
||||
const CefString& request,
|
||||
bool persistent,
|
||||
CefRefPtr<Callback> callback) override {
|
||||
const std::string& url = frame->GetURL();
|
||||
const std::string& cookie_str = request.ToString();
|
||||
if (url == GetCookieAccessUrl1(server_backend_)) {
|
||||
TestCookieString(cookie_str, got_cookie_js1_, got_cookie_net1_);
|
||||
browser->GetMainFrame()->LoadURL(GetCookieAccessUrl2(server_backend_));
|
||||
} else if (url == GetCookieAccessUrl2(server_backend_)) {
|
||||
TestCookieString(cookie_str, got_cookie_js2_, got_cookie_net2_);
|
||||
FinishTest();
|
||||
} else {
|
||||
ADD_FAILURE() << "Unexpected url: " << url;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
void AddResponses(CookieAccessResponseHandler* handler) {
|
||||
// 1st request sets a cookie via net response headers and JS, then retrieves
|
||||
// the cookies via JS.
|
||||
{
|
||||
data1_.response = CefResponse::Create();
|
||||
data1_.response->SetMimeType("text/html");
|
||||
data1_.response->SetStatus(200);
|
||||
data1_.response->SetStatusText("OK");
|
||||
|
||||
CefResponse::HeaderMap headerMap;
|
||||
data1_.response->GetHeaderMap(headerMap);
|
||||
headerMap.insert(std::make_pair("Set-Cookie", "name_net=value_net"));
|
||||
data1_.response->SetHeaderMap(headerMap);
|
||||
|
||||
data1_.response_data =
|
||||
"<html><head>"
|
||||
"<script>"
|
||||
"document.cookie='name_js=value_js';"
|
||||
"window.testQuery({request:document.cookie});"
|
||||
"</script>"
|
||||
"</head><body>COOKIE ACCESS TEST 1</body></html>";
|
||||
|
||||
handler->AddResponse(GetCookieAccessUrl1(server_backend_), &data1_);
|
||||
}
|
||||
|
||||
// 2nd request retrieves the cookies via JS.
|
||||
{
|
||||
data2_.response = CefResponse::Create();
|
||||
data2_.response->SetMimeType("text/html");
|
||||
data2_.response->SetStatus(200);
|
||||
data2_.response->SetStatusText("OK");
|
||||
|
||||
data2_.response_data =
|
||||
"<html><head>"
|
||||
"<script>"
|
||||
"window.testQuery({request:document.cookie});"
|
||||
"</script>"
|
||||
"</head><body>COOKIE ACCESS TEST 2</body></html>";
|
||||
|
||||
handler->AddResponse(GetCookieAccessUrl2(server_backend_), &data2_);
|
||||
}
|
||||
}
|
||||
|
||||
void StartBackend(const base::Closure& complete_callback) {
|
||||
if (server_backend_) {
|
||||
StartServer(complete_callback);
|
||||
} else {
|
||||
StartSchemeHandler(complete_callback);
|
||||
}
|
||||
}
|
||||
|
||||
void StartServer(const base::Closure& complete_callback) {
|
||||
EXPECT_FALSE(server_handler_);
|
||||
|
||||
server_handler_ = new CookieAccessServerHandler();
|
||||
AddResponses(server_handler_.get());
|
||||
server_handler_->CreateServer(complete_callback);
|
||||
}
|
||||
|
||||
void StartSchemeHandler(const base::Closure& complete_callback) {
|
||||
// Add the factory registration.
|
||||
scheme_factory_ = new CookieAccessSchemeHandlerFactory();
|
||||
AddResponses(scheme_factory_.get());
|
||||
CefRegisterSchemeHandlerFactory(kCookieAccessScheme, kCookieAccessDomain,
|
||||
scheme_factory_.get());
|
||||
|
||||
complete_callback.Run();
|
||||
}
|
||||
|
||||
void RunTestContinue() {
|
||||
if (!CefCurrentlyOn(TID_UI)) {
|
||||
CefPostTask(TID_UI,
|
||||
base::Bind(&CookieAccessTestHandler::RunTestContinue, this));
|
||||
return;
|
||||
}
|
||||
|
||||
CreateBrowser(GetCookieAccessUrl1(server_backend_));
|
||||
}
|
||||
|
||||
void FinishTest() {
|
||||
// Verify that cookies were set correctly.
|
||||
class TestVisitor : public CefCookieVisitor {
|
||||
public:
|
||||
explicit TestVisitor(CookieAccessTestHandler* handler)
|
||||
: handler_(handler) {}
|
||||
~TestVisitor() override {
|
||||
// Destroy the test.
|
||||
CefPostTask(
|
||||
TID_UI,
|
||||
base::Bind(
|
||||
&CookieAccessTestHandler::ShutdownBackend, handler_,
|
||||
base::Bind(&CookieAccessTestHandler::DestroyTest, handler_)));
|
||||
}
|
||||
|
||||
bool Visit(const CefCookie& cookie,
|
||||
int count,
|
||||
int total,
|
||||
bool& deleteCookie) override {
|
||||
const std::string& name = CefString(&cookie.name);
|
||||
const std::string& value = CefString(&cookie.value);
|
||||
if (name == "name_js" && value == "value_js")
|
||||
handler_->got_cookie_js3_.yes();
|
||||
else if (name == "name_net" && value == "value_net")
|
||||
handler_->got_cookie_net3_.yes();
|
||||
|
||||
// Clean up the cookies.
|
||||
deleteCookie = true;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
CookieAccessTestHandler* handler_;
|
||||
IMPLEMENT_REFCOUNTING(TestVisitor);
|
||||
};
|
||||
|
||||
cookie_manager_->VisitAllCookies(new TestVisitor(this));
|
||||
}
|
||||
|
||||
void ShutdownBackend(const base::Closure& complete_callback) {
|
||||
if (server_backend_) {
|
||||
ShutdownServer(complete_callback);
|
||||
} else {
|
||||
ShutdownSchemeHandler(complete_callback);
|
||||
}
|
||||
}
|
||||
|
||||
void ShutdownServer(const base::Closure& complete_callback) {
|
||||
EXPECT_TRUE(server_handler_);
|
||||
|
||||
server_handler_->ShutdownServer(complete_callback);
|
||||
server_handler_ = nullptr;
|
||||
}
|
||||
|
||||
void ShutdownSchemeHandler(const base::Closure& complete_callback) {
|
||||
EXPECT_TRUE(scheme_factory_);
|
||||
|
||||
CefRegisterSchemeHandlerFactory(kCookieAccessScheme, kCookieAccessDomain,
|
||||
nullptr);
|
||||
scheme_factory_->Shutdown(complete_callback);
|
||||
scheme_factory_ = nullptr;
|
||||
}
|
||||
|
||||
TestMode test_mode_;
|
||||
bool server_backend_;
|
||||
CefRefPtr<CefCookieManager> cookie_manager_;
|
||||
|
||||
CefRefPtr<CookieAccessServerHandler> server_handler_;
|
||||
CefRefPtr<CookieAccessSchemeHandlerFactory> scheme_factory_;
|
||||
|
||||
CookieAccessData data1_;
|
||||
CookieAccessData data2_;
|
||||
|
||||
// 1st request.
|
||||
TrackCallback got_can_set_cookie1_;
|
||||
TrackCallback got_cookie_js1_;
|
||||
TrackCallback got_cookie_net1_;
|
||||
|
||||
// 2nd request.
|
||||
TrackCallback got_can_get_cookies2_;
|
||||
TrackCallback got_cookie_js2_;
|
||||
TrackCallback got_cookie_net2_;
|
||||
|
||||
// From cookie manager.
|
||||
TrackCallback got_cookie_js3_;
|
||||
TrackCallback got_cookie_net3_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(CookieAccessTestHandler);
|
||||
IMPLEMENT_REFCOUNTING(CookieAccessTestHandler);
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
// Allow reading and writing of cookies with server backend.
|
||||
TEST(RequestHandlerTest, CookieAccessServerAllow) {
|
||||
CefRefPtr<CookieAccessTestHandler> handler =
|
||||
new CookieAccessTestHandler(CookieAccessTestHandler::ALLOW, true);
|
||||
handler->ExecuteTest();
|
||||
ReleaseAndWaitForDestructor(handler);
|
||||
}
|
||||
|
||||
// Block reading of cookies with server backend.
|
||||
TEST(RequestHandlerTest, CookieAccessServerBlockRead) {
|
||||
CefRefPtr<CookieAccessTestHandler> handler =
|
||||
new CookieAccessTestHandler(CookieAccessTestHandler::BLOCK_READ, true);
|
||||
handler->ExecuteTest();
|
||||
ReleaseAndWaitForDestructor(handler);
|
||||
}
|
||||
|
||||
// Block writing of cookies with server backend.
|
||||
TEST(RequestHandlerTest, CookieAccessServerBlockWrite) {
|
||||
CefRefPtr<CookieAccessTestHandler> handler =
|
||||
new CookieAccessTestHandler(CookieAccessTestHandler::BLOCK_WRITE, true);
|
||||
handler->ExecuteTest();
|
||||
ReleaseAndWaitForDestructor(handler);
|
||||
}
|
||||
|
||||
// Block reading and writing of cookies with server backend.
|
||||
TEST(RequestHandlerTest, CookieAccessServerBlockAll) {
|
||||
CefRefPtr<CookieAccessTestHandler> handler =
|
||||
new CookieAccessTestHandler(CookieAccessTestHandler::BLOCK_ALL, true);
|
||||
handler->ExecuteTest();
|
||||
ReleaseAndWaitForDestructor(handler);
|
||||
}
|
||||
|
||||
// Allow reading and writing of cookies with scheme handler backend.
|
||||
TEST(RequestHandlerTest, CookieAccessSchemeAllow) {
|
||||
CefRefPtr<CookieAccessTestHandler> handler =
|
||||
new CookieAccessTestHandler(CookieAccessTestHandler::ALLOW, false);
|
||||
handler->ExecuteTest();
|
||||
ReleaseAndWaitForDestructor(handler);
|
||||
}
|
||||
|
||||
// Block reading of cookies with scheme handler backend.
|
||||
TEST(RequestHandlerTest, CookieAccessSchemeBlockRead) {
|
||||
CefRefPtr<CookieAccessTestHandler> handler =
|
||||
new CookieAccessTestHandler(CookieAccessTestHandler::BLOCK_READ, false);
|
||||
handler->ExecuteTest();
|
||||
ReleaseAndWaitForDestructor(handler);
|
||||
}
|
||||
|
||||
// Block writing of cookies with scheme handler backend.
|
||||
TEST(RequestHandlerTest, CookieAccessSchemeBlockWrite) {
|
||||
CefRefPtr<CookieAccessTestHandler> handler =
|
||||
new CookieAccessTestHandler(CookieAccessTestHandler::BLOCK_WRITE, false);
|
||||
handler->ExecuteTest();
|
||||
ReleaseAndWaitForDestructor(handler);
|
||||
}
|
||||
|
||||
// Block reading and writing of cookies with scheme handler backend.
|
||||
TEST(RequestHandlerTest, CookieAccessSchemeBlockAll) {
|
||||
CefRefPtr<CookieAccessTestHandler> handler =
|
||||
new CookieAccessTestHandler(CookieAccessTestHandler::BLOCK_ALL, false);
|
||||
handler->ExecuteTest();
|
||||
ReleaseAndWaitForDestructor(handler);
|
||||
}
|
||||
|
||||
// Entry point for creating request handler browser test objects.
|
||||
// Called from client_app_delegates.cc.
|
||||
void CreateRequestHandlerBrowserTests(
|
||||
|
|
Loading…
Reference in New Issue