Support disabling of cookie load/save via SetSupportedSchemes (see issue #2622).

With this change the CefCookieManager::SetSupportedSchemes method can be used
to disable all loading and saving of cookies for the associated request context.
This matches functionality that was previously available via GetBlockingManager.

This change also fixes a bug where Set-Cookie headers returned for a request
handled via CefSchemeHandlerFactory would be ignored if there was not also a
CefResourceRequestHandler returned for the request.

To test: All CookieTest.* tests pass.
This commit is contained in:
Marshall Greenblatt 2019-05-02 18:23:57 -04:00
parent cef882616b
commit 8b400331c7
18 changed files with 322 additions and 161 deletions

View File

@ -33,7 +33,7 @@
// by hand. See the translator.README.txt file in the tools directory for
// more information.
//
// $hash=7ec5f39057b2a75576fe732fc7bff7b953956fe6$
// $hash=ef1fc4ab41a3fc6046a8754ce1a64bc2732332e6$
//
#ifndef CEF_INCLUDE_CAPI_CEF_COOKIE_CAPI_H_
@ -62,14 +62,18 @@ typedef struct _cef_cookie_manager_t {
cef_base_ref_counted_t base;
///
// Set the schemes supported by this manager. The default schemes ("http",
// "https", "ws" and "wss") will always be supported. If |callback| is non-
// NULL it will be executed asnychronously on the UI thread after the change
// has been applied. Must be called before any cookies are accessed.
// Set the schemes supported by this manager. If |include_defaults| is true
// (1) the default schemes ("http", "https", "ws" and "wss") will also be
// supported. Calling this function with an NULL |schemes| value and
// |include_defaults| set to false (0) will disable all loading and saving of
// cookies for this manager. If |callback| is non-NULL it will be executed
// asnychronously on the UI thread after the change has been applied. Must be
// called before any cookies are accessed.
///
void(CEF_CALLBACK* set_supported_schemes)(
struct _cef_cookie_manager_t* self,
cef_string_list_t schemes,
int include_defaults,
struct _cef_completion_callback_t* callback);
///

View File

@ -34,7 +34,7 @@
// implementations. See the translator.README.txt file in the tools directory
// for more information.
//
// $hash=9d23feaba9aac41aff230ff51bb08a5f18ddda48$
// $hash=dd6129d832b33b4da283d86722ba5a7b743a15a5$
//
#ifndef CEF_INCLUDE_API_HASH_H_
@ -47,13 +47,13 @@
// way that may cause binary incompatibility with other builds. The universal
// hash value will change if any platform is affected whereas the platform hash
// values will change only if that particular platform is affected.
#define CEF_API_HASH_UNIVERSAL "02918155c74c1f12406114bce5f668fba5fb8b8a"
#define CEF_API_HASH_UNIVERSAL "91bb58af264779076e95dfd1a63033bc7da296cd"
#if defined(OS_WIN)
#define CEF_API_HASH_PLATFORM "d331dc982255599b7a6929cc38fdf133e58c16e6"
#define CEF_API_HASH_PLATFORM "7cacaf3f958d22f84e4ee6b5216dc5ccc4c18e31"
#elif defined(OS_MACOSX)
#define CEF_API_HASH_PLATFORM "8ab0117e584d529145dee6aac2409a0d523fae95"
#define CEF_API_HASH_PLATFORM "b471cf826966f5917fd3855996c8998898df2334"
#elif defined(OS_LINUX)
#define CEF_API_HASH_PLATFORM "6663ec2c35cbc01eec7a1bd939fcb7bf45203a42"
#define CEF_API_HASH_PLATFORM "1b0a73214b4f50b23e2dab96d7a1d6def2c195dc"
#endif
#ifdef __cplusplus

View File

@ -65,14 +65,18 @@ class CefCookieManager : public virtual CefBaseRefCounted {
CefRefPtr<CefCompletionCallback> callback);
///
// Set the schemes supported by this manager. The default schemes ("http",
// "https", "ws" and "wss") will always be supported. If |callback| is non-
// NULL it will be executed asnychronously on the UI thread after the change
// has been applied. Must be called before any cookies are accessed.
// Set the schemes supported by this manager. If |include_defaults| is true
// the default schemes ("http", "https", "ws" and "wss") will also be
// supported. Calling this method with an empty |schemes| value and
// |include_defaults| set to false will disable all loading and saving of
// cookies for this manager. If |callback| is non-NULL it will be executed
// asnychronously on the UI thread after the change has been applied. Must be
// called before any cookies are accessed.
///
/*--cef(optional_param=callback)--*/
virtual void SetSupportedSchemes(
const std::vector<CefString>& schemes,
bool include_defaults,
CefRefPtr<CefCompletionCallback> callback) = 0;
///

View File

@ -186,7 +186,7 @@ class CefBrowserContext : public ChromeProfileStub,
bool ShouldPersistSessionCookies() override {
return should_persist_session_cookies_;
}
std::vector<std::string> GetCookieableSchemes() override {
base::Optional<std::vector<std::string>> GetCookieableSchemes() override {
return cookieable_schemes_;
}
@ -233,7 +233,8 @@ class CefBrowserContext : public ChromeProfileStub,
void set_should_persist_session_cookies(bool value) {
should_persist_session_cookies_ = value;
}
void set_cookieable_schemes(const std::vector<std::string>& schemes) {
void set_cookieable_schemes(
base::Optional<std::vector<std::string>> schemes) {
cookieable_schemes_ = schemes;
}
@ -273,7 +274,7 @@ class CefBrowserContext : public ChromeProfileStub,
// |visitedlink_listener_| is owned by visitedlink_master_.
CefVisitedLinkListener* visitedlink_listener_;
bool should_persist_session_cookies_ = false;
std::vector<std::string> cookieable_schemes_;
base::Optional<std::vector<std::string>> cookieable_schemes_;
std::unique_ptr<CefResourceContext> resource_context_;

View File

@ -165,11 +165,12 @@ net::CookieStore* CefCookieManagerOldImpl::GetExistingCookieStore() {
void CefCookieManagerOldImpl::SetSupportedSchemes(
const std::vector<CefString>& schemes,
bool include_defaults,
CefRefPtr<CefCompletionCallback> callback) {
if (!CEF_CURRENTLY_ON_IOT()) {
CEF_POST_TASK(
CEF_IOT, base::Bind(&CefCookieManagerOldImpl::SetSupportedSchemes, this,
schemes, callback));
schemes, include_defaults, callback));
return;
}
@ -178,7 +179,7 @@ void CefCookieManagerOldImpl::SetSupportedSchemes(
for (; it != schemes.end(); ++it)
scheme_set.push_back(*it);
SetSupportedSchemesInternal(scheme_set, callback);
SetSupportedSchemesInternal(scheme_set, include_defaults, callback);
}
bool CefCookieManagerOldImpl::VisitAllCookies(
@ -243,16 +244,19 @@ bool CefCookieManagerOldImpl::FlushStore(
// static
void CefCookieManagerOldImpl::SetCookieMonsterSchemes(
net::CookieMonster* cookie_monster,
const std::vector<std::string>& schemes) {
const std::vector<std::string>& schemes,
bool include_defaults) {
CEF_REQUIRE_IOT();
std::vector<std::string> all_schemes = schemes;
// Add default schemes that should always support cookies.
all_schemes.push_back("http");
all_schemes.push_back("https");
all_schemes.push_back("ws");
all_schemes.push_back("wss");
if (include_defaults) {
// Add default schemes that should always support cookies.
all_schemes.push_back("http");
all_schemes.push_back("https");
all_schemes.push_back("ws");
all_schemes.push_back("wss");
}
cookie_monster->SetCookieableSchemes(
all_schemes, net::CookieStore::SetCookieableSchemesCallback());
@ -292,11 +296,12 @@ void CefCookieManagerOldImpl::InitWithContext(
void CefCookieManagerOldImpl::SetSupportedSchemesWithContext(
const std::vector<std::string>& schemes,
bool include_defaults,
CefRefPtr<CefCompletionCallback> callback,
scoped_refptr<CefURLRequestContextGetter> request_context) {
CEF_REQUIRE_IOT();
request_context->SetCookieSupportedSchemes(schemes);
request_context->SetCookieSupportedSchemes(schemes, include_defaults);
RunAsyncCompletionOnUIThread(callback);
}
@ -322,12 +327,13 @@ void CefCookieManagerOldImpl::GetCookieStoreWithContext(
void CefCookieManagerOldImpl::SetSupportedSchemesInternal(
const std::vector<std::string>& schemes,
bool include_defaults,
CefRefPtr<CefCompletionCallback> callback) {
CEF_REQUIRE_IOT();
RunMethodWithContext(
base::Bind(&CefCookieManagerOldImpl::SetSupportedSchemesWithContext, this,
schemes, callback));
schemes, include_defaults, callback));
}
void CefCookieManagerOldImpl::VisitAllCookiesInternal(

View File

@ -43,6 +43,7 @@ class CefCookieManagerOldImpl : public CefCookieManager {
// CefCookieManager methods.
void SetSupportedSchemes(const std::vector<CefString>& schemes,
bool include_defaults,
CefRefPtr<CefCompletionCallback> callback) override;
bool VisitAllCookies(CefRefPtr<CefCookieVisitor> visitor) override;
bool VisitUrlCookies(const CefString& url,
@ -56,10 +57,10 @@ class CefCookieManagerOldImpl : public CefCookieManager {
CefRefPtr<CefDeleteCookiesCallback> callback) override;
bool FlushStore(CefRefPtr<CefCompletionCallback> callback) override;
// Set the schemes supported by |cookie_monster|. Default schemes will always
// be supported.
// Set the schemes supported by |cookie_monster|.
static void SetCookieMonsterSchemes(net::CookieMonster* cookie_monster,
const std::vector<std::string>& schemes);
const std::vector<std::string>& schemes,
bool include_defaults);
private:
// Execute |method| on the IO thread once the request context is available.
@ -71,6 +72,7 @@ class CefCookieManagerOldImpl : public CefCookieManager {
scoped_refptr<CefURLRequestContextGetter> request_context);
void SetSupportedSchemesWithContext(
const std::vector<std::string>& schemes,
bool include_defaults,
CefRefPtr<CefCompletionCallback> callback,
scoped_refptr<CefURLRequestContextGetter> request_context);
void GetCookieStoreWithContext(
@ -79,6 +81,7 @@ class CefCookieManagerOldImpl : public CefCookieManager {
scoped_refptr<CefURLRequestContextGetter> request_context);
void SetSupportedSchemesInternal(const std::vector<std::string>& schemes,
bool include_defaults,
CefRefPtr<CefCompletionCallback> callback);
void VisitAllCookiesInternal(CefRefPtr<CefCookieVisitor> visitor,
const CookieStoreGetter& cookie_store_getter);

View File

@ -480,13 +480,15 @@ net::HostResolver* CefURLRequestContextGetter::GetHostResolver() const {
}
void CefURLRequestContextGetter::SetCookieSupportedSchemes(
const std::vector<std::string>& schemes) {
const std::vector<std::string>& schemes,
bool include_defaults) {
CEF_REQUIRE_IOT();
io_state_->cookie_supported_schemes_ = schemes;
io_state_->include_defaults_ = include_defaults;
CefCookieManagerOldImpl::SetCookieMonsterSchemes(
static_cast<net::CookieMonster*>(GetExistingCookieStore()),
io_state_->cookie_supported_schemes_);
static_cast<net::CookieMonster*>(GetExistingCookieStore()), schemes,
include_defaults);
}
void CefURLRequestContextGetter::AddHandler(
@ -541,15 +543,16 @@ void CefURLRequestContextGetter::SetCookieStoragePath(
// 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.
std::unique_ptr<net::CookieMonster> cookie_monster(new net::CookieMonster(
persistent_store.get(), io_state_->net_log_));
std::unique_ptr<net::CookieMonster> cookie_monster(
new net::CookieMonster(persistent_store.get(), io_state_->net_log_));
if (persistent_store.get() && persist_session_cookies)
cookie_monster->SetPersistSessionCookies(true);
io_state_->cookie_store_path_ = path;
// Restore the previously supported schemes.
CefCookieManagerOldImpl::SetCookieMonsterSchemes(
cookie_monster.get(), io_state_->cookie_supported_schemes_);
cookie_monster.get(), io_state_->cookie_supported_schemes_,
io_state_->include_defaults_);
io_state_->storage_->set_cookie_store(std::move(cookie_monster));
}

View File

@ -68,7 +68,8 @@ class CefURLRequestContextGetter : public net::URLRequestContextGetter {
// CefURLRequestContextGetter implementation.
net::HostResolver* GetHostResolver() const;
void SetCookieSupportedSchemes(const std::vector<std::string>& schemes);
void SetCookieSupportedSchemes(const std::vector<std::string>& schemes,
bool include_defaults);
// Keep a reference to all handlers sharing this context so that they'll be
// kept alive until the context is destroyed.
@ -116,6 +117,7 @@ class CefURLRequestContextGetter : public net::URLRequestContextGetter {
base::FilePath cookie_store_path_;
std::vector<std::string> cookie_supported_schemes_;
bool include_defaults_ = true;
std::vector<CefRefPtr<CefRequestContextHandler>> handler_list_;

View File

@ -98,11 +98,12 @@ void CefCookieManagerImpl::Initialize(
void CefCookieManagerImpl::SetSupportedSchemes(
const std::vector<CefString>& schemes,
bool include_defaults,
CefRefPtr<CefCompletionCallback> callback) {
if (!CEF_CURRENTLY_ON_UIT()) {
CEF_POST_TASK(CEF_UIT,
base::Bind(&CefCookieManagerImpl::SetSupportedSchemes, this,
schemes, callback));
schemes, include_defaults, callback));
return;
}
@ -110,16 +111,20 @@ void CefCookieManagerImpl::SetSupportedSchemes(
for (const auto& scheme : schemes)
all_schemes.push_back(scheme);
// This list should match CookieMonster::kDefaultCookieableSchemes.
all_schemes.push_back("http");
all_schemes.push_back("https");
all_schemes.push_back("ws");
all_schemes.push_back("wss");
if (include_defaults) {
// Add default schemes that should always support cookies.
// This list should match CookieMonster::kDefaultCookieableSchemes.
all_schemes.push_back("http");
all_schemes.push_back("https");
all_schemes.push_back("ws");
all_schemes.push_back("wss");
}
// This will be forwarded to the CookieMonster that lives in the
// NetworkService process when the NetworkContext is created via
// CefContentBrowserClient::CreateNetworkContext.
request_context_->GetBrowserContext()->set_cookieable_schemes(all_schemes);
request_context_->GetBrowserContext()->set_cookieable_schemes(
base::make_optional(all_schemes));
RunAsyncCompletionOnUIThread(callback);
}

View File

@ -23,6 +23,7 @@ class CefCookieManagerImpl : public CefCookieManager {
// CefCookieManager methods.
void SetSupportedSchemes(const std::vector<CefString>& schemes,
bool include_defaults,
CefRefPtr<CefCompletionCallback> callback) override;
bool VisitAllCookies(CefRefPtr<CefCookieVisitor> visitor) override;
bool VisitUrlCookies(const CefString& url,

View File

@ -453,8 +453,12 @@ class InterceptedRequestHandlerWrapper : public InterceptedRequestHandler {
RequestState* state = GetState(id);
DCHECK(state);
if (!state->handler_) {
InterceptedRequestHandler::OnRequestResponse(
id, request, head, redirect_info, std::move(callback));
// Cookies may come from a scheme handler.
MaybeSaveCookies(
state, request, head,
base::BindOnce(
std::move(callback), ResponseMode::CONTINUE, nullptr,
redirect_info.has_value() ? redirect_info->new_url : GURL()));
return;
}

View File

@ -9,7 +9,7 @@
// implementations. See the translator.README.txt file in the tools directory
// for more information.
//
// $hash=a672fab541f9c28f77a06c31d89f5a9d66c78751$
// $hash=887754026eb62e631a0279fbba8fb1c370f0bcf7$
//
#include "libcef_dll/cpptoc/cookie_manager_cpptoc.h"
@ -42,6 +42,7 @@ namespace {
void CEF_CALLBACK
cookie_manager_set_supported_schemes(struct _cef_cookie_manager_t* self,
cef_string_list_t schemes,
int include_defaults,
cef_completion_callback_t* callback) {
// AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING
@ -60,7 +61,8 @@ cookie_manager_set_supported_schemes(struct _cef_cookie_manager_t* self,
// Execute
CefCookieManagerCppToC::Get(self)->SetSupportedSchemes(
schemesList, CefCompletionCallbackCToCpp::Wrap(callback));
schemesList, include_defaults ? true : false,
CefCompletionCallbackCToCpp::Wrap(callback));
}
int CEF_CALLBACK

View File

@ -9,7 +9,7 @@
// implementations. See the translator.README.txt file in the tools directory
// for more information.
//
// $hash=fdbb50cba70b9638aaaadc2e4040b18390ae3a6d$
// $hash=87369bed5916a070a4f1a7f4bb9fcff5885cd31f$
//
#include "libcef_dll/ctocpp/cookie_manager_ctocpp.h"
@ -41,6 +41,7 @@ CefRefPtr<CefCookieManager> CefCookieManager::GetGlobalManager(
NO_SANITIZE("cfi-icall")
void CefCookieManagerCToCpp::SetSupportedSchemes(
const std::vector<CefString>& schemes,
bool include_defaults,
CefRefPtr<CefCompletionCallback> callback) {
cef_cookie_manager_t* _struct = GetStruct();
if (CEF_MEMBER_MISSING(_struct, set_supported_schemes))
@ -57,7 +58,7 @@ void CefCookieManagerCToCpp::SetSupportedSchemes(
transfer_string_list_contents(schemes, schemesList);
// Execute
_struct->set_supported_schemes(_struct, schemesList,
_struct->set_supported_schemes(_struct, schemesList, include_defaults,
CefCompletionCallbackCppToC::Wrap(callback));
// Restore param:schemes; type: string_vec_byref_const

View File

@ -9,7 +9,7 @@
// implementations. See the translator.README.txt file in the tools directory
// for more information.
//
// $hash=99bb8be3c19be11e4abf2cf904d75667723ae643$
// $hash=c08c701ad13790067983a7b5eb964975bc1f186b$
//
#ifndef CEF_LIBCEF_DLL_CTOCPP_COOKIE_MANAGER_CTOCPP_H_
@ -37,6 +37,7 @@ class CefCookieManagerCToCpp
// CefCookieManager methods.
void SetSupportedSchemes(const std::vector<CefString>& schemes,
bool include_defaults,
CefRefPtr<CefCompletionCallback> callback) OVERRIDE;
bool VisitAllCookies(CefRefPtr<CefCookieVisitor> visitor) OVERRIDE;
bool VisitUrlCookies(const CefString& url,

View File

@ -35,7 +35,7 @@ index 2b24d1ac1b5b..6577495d87a9 100644
base_cache_path.Append(chrome::kCacheDirname);
network_context_params->http_cache_max_size =
diff --git chrome/browser/profiles/profile.h chrome/browser/profiles/profile.h
index c70a4c0f48ac..8aaadf324a0e 100644
index c70a4c0f48ac..f76776fb39bf 100644
--- chrome/browser/profiles/profile.h
+++ chrome/browser/profiles/profile.h
@@ -310,6 +310,11 @@ class Profile : public content::BrowserContext {
@ -43,15 +43,15 @@ index c70a4c0f48ac..8aaadf324a0e 100644
virtual bool ShouldPersistSessionCookies();
+ // Returns schemes that should be cookieable, if other than the defaults.
+ virtual std::vector<std::string> GetCookieableSchemes() {
+ return std::vector<std::string>();
+ virtual base::Optional<std::vector<std::string>> GetCookieableSchemes() {
+ return base::nullopt;
+ }
+
// Creates NetworkContext for the specified isolated app (or for the profile
// itself, if |relative_path| is empty).
virtual network::mojom::NetworkContextPtr CreateNetworkContext(
diff --git services/network/network_context.cc services/network/network_context.cc
index b882aa825923..f1921814e1d8 100644
index b882aa825923..eedf167ee32b 100644
--- services/network/network_context.cc
+++ services/network/network_context.cc
@@ -1733,6 +1733,7 @@ URLRequestContextOwner NetworkContext::ApplyContextParamsToBuilder(
@ -82,9 +82,9 @@ index b882aa825923..f1921814e1d8 100644
+ std::make_unique<net::CookieMonster>(nullptr /* store */, net_log);
}
+ if (!params_->cookieable_schemes.empty()) {
+ if (params_->cookieable_schemes.has_value()) {
+ cookie_store->SetCookieableSchemes(
+ params_->cookieable_schemes,
+ *params_->cookieable_schemes,
+ net::CookieStore::SetCookieableSchemesCallback());
+ }
+
@ -94,7 +94,7 @@ index b882aa825923..f1921814e1d8 100644
std::make_unique<net::StaticHttpUserAgentSettings>(
params_->accept_language, params_->user_agent);
diff --git services/network/public/mojom/network_context.mojom services/network/public/mojom/network_context.mojom
index 864e55731cdf..9fea7361d730 100644
index 864e55731cdf..ef70c6f30168 100644
--- services/network/public/mojom/network_context.mojom
+++ services/network/public/mojom/network_context.mojom
@@ -189,6 +189,9 @@ struct NetworkContextParams {
@ -102,7 +102,7 @@ index 864e55731cdf..9fea7361d730 100644
bool persist_session_cookies = false;
+ // Schemes that will be passed to CookieMonster::SetCookieableSchemes.
+ array<string> cookieable_schemes;
+ array<string>? cookieable_schemes;
+
// True if an HTTP cache should be used.
bool http_cache_enabled = true;

View File

@ -658,6 +658,21 @@ namespace {
const char kCustomCookieScheme[] = "ccustom";
class CompletionCallback : public CefCompletionCallback {
public:
explicit CompletionCallback(const base::Closure& callback)
: callback_(callback) {}
void OnComplete() override {
callback_.Run();
callback_.Reset();
}
private:
base::Closure callback_;
IMPLEMENT_REFCOUNTING(CompletionCallback);
};
class CookieTestSchemeHandler : public TestHandler {
public:
class SchemeHandler : public CefResourceHandler {
@ -768,23 +783,12 @@ class CookieTestSchemeHandler : public TestHandler {
IMPLEMENT_REFCOUNTING(SchemeHandlerFactory);
};
class CompletionCallback : public CefCompletionCallback {
public:
explicit CompletionCallback(const base::Closure& callback)
: callback_(callback) {}
void OnComplete() override {
callback_.Run();
callback_.Reset();
}
private:
base::Closure callback_;
IMPLEMENT_REFCOUNTING(CompletionCallback);
};
CookieTestSchemeHandler(const std::string& scheme, bool use_global)
: scheme_(scheme), use_global_(use_global) {
CookieTestSchemeHandler(const std::string& scheme,
bool use_global,
bool block_cookies = false)
: scheme_(scheme),
use_global_(use_global),
block_cookies_(block_cookies) {
url1_ = scheme + "://cookie-tests/cookie1.html";
url2_ = scheme + "://cookie-tests/cookie2.html";
url3_ = scheme + "://cookie-tests/cookie3.html";
@ -803,14 +807,16 @@ class CookieTestSchemeHandler : public TestHandler {
request_context_->RegisterSchemeHandlerFactory(
scheme_, "cookie-tests", new SchemeHandlerFactory(this));
manager_ = request_context_->GetCookieManager(NULL);
if (!use_global_) {
if (!use_global_ && (scheme_ == kCustomCookieScheme || block_cookies_)) {
std::vector<CefString> schemes;
schemes.push_back(kCustomCookieScheme);
if (!block_cookies_)
schemes.push_back(kCustomCookieScheme);
// Need to wait for completion before creating the browser.
manager_->SetSupportedSchemes(
schemes, new CompletionCallback(base::Bind(
&CookieTestSchemeHandler::CreateBrowserContinue, this)));
schemes, !block_cookies_ /* include_defaults */,
new CompletionCallback(base::Bind(
&CookieTestSchemeHandler::CreateBrowserContinue, this)));
} else {
CreateBrowserContinue();
}
@ -875,17 +881,26 @@ class CookieTestSchemeHandler : public TestHandler {
EXPECT_TRUE(got_process_request1_);
EXPECT_TRUE(got_process_request2_);
EXPECT_TRUE(got_process_request3_);
if (IsNetworkServiceEnabled())
EXPECT_TRUE(got_create_cookie_);
else
EXPECT_FALSE(got_create_cookie_);
EXPECT_TRUE(got_process_request_cookie_);
EXPECT_TRUE(got_load_end1_);
EXPECT_TRUE(got_load_end2_);
EXPECT_TRUE(got_load_end3_);
EXPECT_TRUE(got_cookie1_);
EXPECT_TRUE(got_cookie2_);
EXPECT_TRUE(got_cookie3_);
if (block_cookies_) {
EXPECT_FALSE(got_create_cookie_);
EXPECT_FALSE(got_process_request_cookie_);
EXPECT_FALSE(got_cookie1_);
EXPECT_FALSE(got_cookie2_);
EXPECT_FALSE(got_cookie3_);
} else {
if (IsNetworkServiceEnabled())
EXPECT_TRUE(got_create_cookie_);
else
EXPECT_FALSE(got_create_cookie_);
EXPECT_TRUE(got_process_request_cookie_);
EXPECT_TRUE(got_cookie1_);
EXPECT_TRUE(got_cookie2_);
EXPECT_TRUE(got_cookie3_);
}
// Unregister the scheme handler.
request_context_->RegisterSchemeHandlerFactory(scheme_, "cookie-tests",
@ -925,6 +940,7 @@ class CookieTestSchemeHandler : public TestHandler {
const std::string scheme_;
const bool use_global_;
const bool block_cookies_;
std::string url1_;
std::string url2_;
std::string url3_;
@ -967,6 +983,14 @@ TEST(CookieTest, GetCookieManagerHttpInMemory) {
ReleaseAndWaitForDestructor(handler);
}
// Verify use of an in-memory cookie manager with HTTP to block all cookies.
TEST(CookieTest, GetCookieManagerHttpInMemoryBlocked) {
CefRefPtr<CookieTestSchemeHandler> handler =
new CookieTestSchemeHandler("http", false, true);
handler->ExecuteTest();
ReleaseAndWaitForDestructor(handler);
}
// Verify use of the global cookie manager with a custom scheme.
TEST(CookieTest, GetCookieManagerCustomGlobal) {
CefRefPtr<CookieTestSchemeHandler> handler =
@ -990,24 +1014,27 @@ const char kCookieAccessDomain[] = "test-cookies.com";
const char kCookieAccessServerIP[] = "127.0.0.1";
const uint16 kCookieAccessServerPort = 8099;
std::string GetCookieAccessOrigin(bool server_backend) {
std::string GetCookieAccessOrigin(const std::string& scheme,
bool server_backend) {
std::stringstream ss;
if (server_backend) {
ss << kCookieAccessScheme << "://" << kCookieAccessServerIP << ":"
ss << scheme << "://" << kCookieAccessServerIP << ":"
<< kCookieAccessServerPort;
} else {
ss << kCookieAccessScheme << "://" << kCookieAccessDomain;
ss << scheme << "://" << kCookieAccessDomain;
}
ss << "/";
return ss.str();
}
std::string GetCookieAccessUrl1(bool server_backend) {
return GetCookieAccessOrigin(server_backend) + "cookie1.html";
std::string GetCookieAccessUrl1(const std::string& scheme,
bool server_backend) {
return GetCookieAccessOrigin(scheme, server_backend) + "cookie1.html";
}
std::string GetCookieAccessUrl2(bool server_backend) {
return GetCookieAccessOrigin(server_backend) + "cookie2.html";
std::string GetCookieAccessUrl2(const std::string& scheme,
bool server_backend) {
return GetCookieAccessOrigin(scheme, server_backend) + "cookie2.html";
}
void TestCookieString(const std::string& cookie_str,
@ -1459,8 +1486,15 @@ class CookieAccessTestHandler : public RoutingTestHandler,
BLOCK_READ_WRITE = BLOCK_READ | BLOCK_WRITE,
ALLOW_NO_FILTER = 1 << 2,
// Can only be used in combination with the SERVER backend.
ALLOW_NO_HANDLER = 1 << 3,
// Block all cookies using SetSupportedSchemes. Can only be used with a
// non-global request context because it's too late (during test execution)
// to call this method on the global context.
BLOCK_ALL_COOKIES = 1 << 3,
// Return nullptr from GetResourceRequestHandler. Can only be used in
// combination with the SERVER or SCHEME_HANDLER backend (the
// RESOURCE_HANDLER backend would not be called).
ALLOW_NO_HANDLER = 1 << 4,
};
enum TestBackend {
@ -1474,17 +1508,49 @@ class CookieAccessTestHandler : public RoutingTestHandler,
RESOURCE_HANDLER,
};
CookieAccessTestHandler(TestMode test_mode, TestBackend test_backend)
: test_mode_(test_mode), test_backend_(test_backend) {}
CookieAccessTestHandler(TestMode test_mode,
TestBackend test_backend,
bool custom_scheme,
bool use_global)
: test_mode_(test_mode),
test_backend_(test_backend),
scheme_(custom_scheme ? kCustomCookieScheme : kCookieAccessScheme),
use_global_(use_global) {
if (test_mode_ == BLOCK_ALL_COOKIES)
CHECK(!use_global_);
else if (test_mode_ == ALLOW_NO_HANDLER)
CHECK_NE(RESOURCE_HANDLER, test_backend_);
if (test_backend_ == SERVER)
CHECK(!custom_scheme);
}
void RunTest() override {
cookie_manager_ = CefCookieManager::GetGlobalManager(nullptr);
if (use_global_) {
context_ = CefRequestContext::GetGlobalContext();
} else {
// Create the request context that will use an in-memory cache.
CefRequestContextSettings settings;
context_ = CefRequestContext::CreateContext(settings, NULL);
}
cookie_manager_ = context_->GetCookieManager(nullptr);
SetTestTimeout();
CefPostTask(TID_UI,
base::Bind(&CookieAccessTestHandler::StartBackend, this,
base::Bind(&CookieAccessTestHandler::RunTestContinue,
this)));
const bool block_cookies = (test_mode_ == BLOCK_ALL_COOKIES);
if (!use_global_ && (scheme_ == kCustomCookieScheme || block_cookies)) {
std::vector<CefString> schemes;
if (!block_cookies)
schemes.push_back(kCustomCookieScheme);
// Need to wait for completion before creating the browser.
cookie_manager_->SetSupportedSchemes(
schemes, !block_cookies /* include_defaults */,
new CompletionCallback(base::Bind(
&CookieAccessTestHandler::RunTestSetupContinue, this)));
} else {
RunTestSetupContinue();
}
}
void DestroyTest() override {
@ -1495,8 +1561,7 @@ class CookieAccessTestHandler : public RoutingTestHandler,
}
cookie_manager_ = NULL;
if (context_)
context_ = NULL;
context_ = NULL;
// Got both network requests.
EXPECT_TRUE(data1_.got_request_);
@ -1511,7 +1576,10 @@ class CookieAccessTestHandler : public RoutingTestHandler,
// Get 1 call to CanSaveCookie for the 1st network request due to the
// network cookie.
EXPECT_EQ(1, can_save_cookie1_ct_);
if (test_mode_ & BLOCK_WRITE) {
if (test_mode_ == BLOCK_ALL_COOKIES) {
// Never send any cookies.
EXPECT_EQ(0, can_send_cookie2_ct_);
} else if (test_mode_ & BLOCK_WRITE) {
// Get 1 calls to CanSendCookie for the 2nd network request due to the
// JS cookie (network cookie is blocked).
EXPECT_EQ(1, can_send_cookie2_ct_);
@ -1522,13 +1590,20 @@ class CookieAccessTestHandler : public RoutingTestHandler,
}
}
// Always get the JS cookie via JS.
EXPECT_TRUE(got_cookie_js1_);
EXPECT_TRUE(got_cookie_js2_);
EXPECT_TRUE(got_cookie_js3_);
if (test_mode_ == BLOCK_ALL_COOKIES) {
// Never get the JS cookie via JS.
EXPECT_FALSE(got_cookie_js1_);
EXPECT_FALSE(got_cookie_js2_);
EXPECT_FALSE(got_cookie_js3_);
} else {
// 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) {
if ((test_mode_ & BLOCK_WRITE) || test_mode_ == BLOCK_ALL_COOKIES) {
EXPECT_FALSE(got_cookie_net1_);
EXPECT_FALSE(got_cookie_net2_);
EXPECT_FALSE(got_cookie_net3_);
@ -1543,7 +1618,7 @@ class CookieAccessTestHandler : public RoutingTestHandler,
EXPECT_FALSE(data1_.got_cookie_net_);
// 2nd network request...
if (test_mode_ & BLOCK_READ) {
if ((test_mode_ & BLOCK_READ) || test_mode_ == BLOCK_ALL_COOKIES) {
// No cookies sent if reading was blocked.
EXPECT_FALSE(data2_.got_cookie_js_);
EXPECT_FALSE(data2_.got_cookie_net_);
@ -1580,10 +1655,8 @@ class CookieAccessTestHandler : public RoutingTestHandler,
bool is_download,
const CefString& request_initiator,
bool& disable_default_handling) override {
if (test_mode_ == ALLOW_NO_HANDLER) {
DCHECK_EQ(SERVER, test_backend_);
if (test_mode_ == ALLOW_NO_HANDLER)
return nullptr;
}
return this;
}
@ -1593,8 +1666,7 @@ class CookieAccessTestHandler : public RoutingTestHandler,
CefRefPtr<CefFrame> frame,
CefRefPtr<CefRequest> request) override {
if (test_backend_ == RESOURCE_HANDLER) {
return scheme_factory_->Create(browser, frame, kCookieAccessScheme,
request);
return scheme_factory_->Create(browser, frame, scheme_, request);
}
return nullptr;
@ -1607,7 +1679,7 @@ class CookieAccessTestHandler : public RoutingTestHandler,
EXPECT_IO_THREAD();
const std::string& url = request->GetURL();
if (url == GetCookieAccessUrl2(test_backend_ == SERVER)) {
if (url == GetCookieAccessUrl2(scheme_, test_backend_ == SERVER)) {
can_send_cookie2_ct_++;
} else {
ADD_FAILURE() << "Unexpected url: " << url;
@ -1628,7 +1700,7 @@ class CookieAccessTestHandler : public RoutingTestHandler,
EXPECT_STREQ("value_net", CefString(&cookie.value).ToString().c_str());
const std::string& url = request->GetURL();
if (url == GetCookieAccessUrl1(test_backend_ == SERVER)) {
if (url == GetCookieAccessUrl1(scheme_, test_backend_ == SERVER)) {
can_save_cookie1_ct_++;
} else {
ADD_FAILURE() << "Unexpected url: " << url;
@ -1645,11 +1717,11 @@ class CookieAccessTestHandler : public RoutingTestHandler,
CefRefPtr<Callback> callback) override {
const std::string& url = frame->GetURL();
const std::string& cookie_str = request.ToString();
if (url == GetCookieAccessUrl1(test_backend_ == SERVER)) {
if (url == GetCookieAccessUrl1(scheme_, test_backend_ == SERVER)) {
TestCookieString(cookie_str, got_cookie_js1_, got_cookie_net1_);
browser->GetMainFrame()->LoadURL(
GetCookieAccessUrl2(test_backend_ == SERVER));
} else if (url == GetCookieAccessUrl2(test_backend_ == SERVER)) {
GetCookieAccessUrl2(scheme_, test_backend_ == SERVER));
} else if (url == GetCookieAccessUrl2(scheme_, test_backend_ == SERVER)) {
TestCookieString(cookie_str, got_cookie_js2_, got_cookie_net2_);
FinishTest();
} else {
@ -1681,8 +1753,8 @@ class CookieAccessTestHandler : public RoutingTestHandler,
"</script>"
"</head><body>COOKIE ACCESS TEST 1</body></html>";
handler->AddResponse(GetCookieAccessUrl1(test_backend_ == SERVER),
&data1_);
handler->AddResponse(
GetCookieAccessUrl1(scheme_, test_backend_ == SERVER), &data1_);
}
// 2nd request retrieves the cookies via JS.
@ -1699,11 +1771,18 @@ class CookieAccessTestHandler : public RoutingTestHandler,
"</script>"
"</head><body>COOKIE ACCESS TEST 2</body></html>";
handler->AddResponse(GetCookieAccessUrl2(test_backend_ == SERVER),
&data2_);
handler->AddResponse(
GetCookieAccessUrl2(scheme_, test_backend_ == SERVER), &data2_);
}
}
void RunTestSetupContinue() {
CefPostTask(TID_UI,
base::Bind(&CookieAccessTestHandler::StartBackend, this,
base::Bind(&CookieAccessTestHandler::RunTestContinue,
this)));
}
void StartBackend(const base::Closure& complete_callback) {
if (test_backend_ == SERVER) {
StartServer(complete_callback);
@ -1725,13 +1804,8 @@ class CookieAccessTestHandler : public RoutingTestHandler,
scheme_factory_ = new CookieAccessSchemeHandlerFactory();
AddResponses(scheme_factory_.get());
if (test_backend_ == SCHEME_HANDLER) {
if (context_) {
context_->RegisterSchemeHandlerFactory(
kCookieAccessScheme, kCookieAccessDomain, scheme_factory_.get());
} else {
CefRegisterSchemeHandlerFactory(
kCookieAccessScheme, kCookieAccessDomain, scheme_factory_.get());
}
context_->RegisterSchemeHandlerFactory(scheme_, kCookieAccessDomain,
scheme_factory_.get());
}
complete_callback.Run();
@ -1744,7 +1818,8 @@ class CookieAccessTestHandler : public RoutingTestHandler,
return;
}
CreateBrowser(GetCookieAccessUrl1(test_backend_ == SERVER), context_);
CreateBrowser(GetCookieAccessUrl1(scheme_, test_backend_ == SERVER),
context_);
}
void FinishTest() {
@ -1806,13 +1881,8 @@ class CookieAccessTestHandler : public RoutingTestHandler,
EXPECT_TRUE(scheme_factory_);
if (test_backend_ == SCHEME_HANDLER) {
if (context_) {
context_->RegisterSchemeHandlerFactory(kCookieAccessScheme,
kCookieAccessDomain, nullptr);
} else {
CefRegisterSchemeHandlerFactory(kCookieAccessScheme,
kCookieAccessDomain, nullptr);
}
context_->RegisterSchemeHandlerFactory(scheme_, kCookieAccessDomain,
nullptr);
}
scheme_factory_->Shutdown(complete_callback);
scheme_factory_ = nullptr;
@ -1820,6 +1890,8 @@ class CookieAccessTestHandler : public RoutingTestHandler,
const TestMode test_mode_;
const TestBackend test_backend_;
const std::string scheme_;
const bool use_global_;
CefRefPtr<CefRequestContext> context_;
CefRefPtr<CefCookieManager> cookie_manager_;
@ -1849,29 +1921,81 @@ class CookieAccessTestHandler : public RoutingTestHandler,
IMPLEMENT_REFCOUNTING(CookieAccessTestHandler);
};
bool IsTestSupported(CookieAccessTestHandler::TestMode test_mode,
CookieAccessTestHandler::TestBackend backend_mode,
bool custom_scheme,
bool use_global) {
if (!IsNetworkServiceEnabled() &&
backend_mode == CookieAccessTestHandler::RESOURCE_HANDLER &&
custom_scheme) {
// The old network implementation does not support the same functionality
// for intercepting custom scheme requests via GetResourceHandler().
return false;
}
return true;
}
} // namespace
#define ACCESS_TEST(name, test_mode, backend_mode) \
TEST(CookieTest, Access##name) { \
CefRefPtr<CookieAccessTestHandler> handler = \
new CookieAccessTestHandler(CookieAccessTestHandler::test_mode, \
CookieAccessTestHandler::backend_mode); \
handler->ExecuteTest(); \
ReleaseAndWaitForDestructor(handler); \
#define ACCESS_TEST(name, test_mode, backend_mode, custom_scheme, use_global) \
TEST(CookieTest, Access##name) { \
if (!IsTestSupported(CookieAccessTestHandler::test_mode, \
CookieAccessTestHandler::backend_mode, custom_scheme, \
use_global)) { \
return; \
} \
CefRefPtr<CookieAccessTestHandler> handler = new CookieAccessTestHandler( \
CookieAccessTestHandler::test_mode, \
CookieAccessTestHandler::backend_mode, custom_scheme, use_global); \
handler->ExecuteTest(); \
ReleaseAndWaitForDestructor(handler); \
}
#define ACCESS_TEST_ALL_MODES(name, backend_mode) \
ACCESS_TEST(name##Allow, ALLOW, backend_mode) \
ACCESS_TEST(name##AllowNoFilter, ALLOW_NO_FILTER, backend_mode) \
ACCESS_TEST(name##BlockRead, BLOCK_READ, backend_mode) \
ACCESS_TEST(name##BlockWrite, BLOCK_WRITE, backend_mode) \
ACCESS_TEST(name##BlockReadWrite, BLOCK_READ_WRITE, backend_mode)
#define ACCESS_TEST_ALL_MODES(name, backend_mode, custom_scheme, use_global) \
ACCESS_TEST(name##Allow, ALLOW, backend_mode, custom_scheme, use_global) \
ACCESS_TEST(name##AllowNoFilter, ALLOW_NO_FILTER, backend_mode, \
custom_scheme, use_global) \
ACCESS_TEST(name##BlockRead, BLOCK_READ, backend_mode, custom_scheme, \
use_global) \
ACCESS_TEST(name##BlockWrite, BLOCK_WRITE, backend_mode, custom_scheme, \
use_global) \
ACCESS_TEST(name##BlockReadWrite, BLOCK_READ_WRITE, backend_mode, \
custom_scheme, use_global)
ACCESS_TEST(ServerAllowNoHandler, ALLOW_NO_HANDLER, SERVER)
// These tests only work with a non-global context.
#define ACCESS_TEST_BLOCKALLCOOKIES_MODES(name, backend_mode, custom_scheme) \
ACCESS_TEST(name##BlockAllCookies, BLOCK_ALL_COOKIES, backend_mode, \
custom_scheme, false)
ACCESS_TEST_ALL_MODES(Server, SERVER)
ACCESS_TEST_ALL_MODES(Scheme, SCHEME_HANDLER)
ACCESS_TEST_ALL_MODES(Resource, RESOURCE_HANDLER)
// These tests only work with SERVER and SCHEME_HANDLER backends.
#define ACCESS_TEST_ALLOWNOHANDLER_MODES(name, backend_mode, custom_scheme) \
ACCESS_TEST(name##GlobalAllowNoHandler, ALLOW_NO_HANDLER, backend_mode, \
custom_scheme, false) \
ACCESS_TEST(name##InMemoryAllowNoHandler, ALLOW_NO_HANDLER, backend_mode, \
custom_scheme, true)
#define ACCESS_TEST_CUSTOM(name, backend_mode) \
ACCESS_TEST_ALL_MODES(name##CustomGlobal, backend_mode, true, true) \
ACCESS_TEST_ALL_MODES(name##CustomInMemory, backend_mode, true, false) \
ACCESS_TEST_BLOCKALLCOOKIES_MODES(name##CustomInMemory, backend_mode, true)
#define ACCESS_TEST_STANDARD(name, backend_mode) \
ACCESS_TEST_ALL_MODES(name##StandardGlobal, backend_mode, false, true) \
ACCESS_TEST_ALL_MODES(name##StandardInMemory, backend_mode, false, false) \
ACCESS_TEST_BLOCKALLCOOKIES_MODES(name##StandardInMemory, backend_mode, false)
// Server backend only works with standard schemes.
ACCESS_TEST_STANDARD(Server, SERVER)
ACCESS_TEST_ALLOWNOHANDLER_MODES(ServerStandard, SERVER, false)
// Other backends work with all schemes.
ACCESS_TEST_CUSTOM(Scheme, SCHEME_HANDLER)
ACCESS_TEST_ALLOWNOHANDLER_MODES(SchemeCustom, SCHEME_HANDLER, true)
ACCESS_TEST_STANDARD(Scheme, SCHEME_HANDLER)
ACCESS_TEST_ALLOWNOHANDLER_MODES(SchemeStandard, SCHEME_HANDLER, false)
ACCESS_TEST_CUSTOM(Resource, RESOURCE_HANDLER)
ACCESS_TEST_STANDARD(Resource, RESOURCE_HANDLER)
// Entry point for registering custom schemes.
// Called from client_app_delegates.cc.

View File

@ -2185,7 +2185,7 @@ class RequestTestHandler : public TestHandler {
// Continue the test once supported schemes has been set.
request_context->GetCookieManager(NULL)->SetSupportedSchemes(
supported_schemes,
supported_schemes, true,
new SupportedSchemesCompletionCallback(
base::Bind(&RequestTestHandler::PreSetupComplete, this)));
} else {

View File

@ -59,7 +59,7 @@ void ClientAppBrowser::OnContextInitialized() {
CefRefPtr<CefCookieManager> manager =
CefCookieManager::GetGlobalManager(NULL);
DCHECK(manager.get());
manager->SetSupportedSchemes(cookieable_schemes_, NULL);
manager->SetSupportedSchemes(cookieable_schemes_, true, NULL);
}
print_handler_ = CreatePrintHandler();