mirror of
https://bitbucket.org/chromiumembedded/cef
synced 2025-02-09 08:38:41 +01:00
Don't save or load cookies for non-cookieable scheme requests.
This fixes an IsCanonical() DCHECK failure triggered by calling CanonicalCookie::Create for a non-cookieable URL. This change also adds unit test coverage for cross-origin cookie behavior with sub-resource requests (iframe, XHR, Fetch).
This commit is contained in:
parent
19391d8ab0
commit
4791109a28
@ -103,7 +103,7 @@ class AlloyBrowserContext : public ChromeProfileAlloy,
|
|||||||
return !!settings_.persist_session_cookies;
|
return !!settings_.persist_session_cookies;
|
||||||
}
|
}
|
||||||
base::Optional<std::vector<std::string>> GetCookieableSchemes() override {
|
base::Optional<std::vector<std::string>> GetCookieableSchemes() override {
|
||||||
return cookieable_schemes_;
|
return cookieable_schemes();
|
||||||
}
|
}
|
||||||
|
|
||||||
// visitedlink::VisitedLinkDelegate methods.
|
// visitedlink::VisitedLinkDelegate methods.
|
||||||
|
@ -196,10 +196,11 @@ class CefBrowserContext {
|
|||||||
|
|
||||||
CefMediaRouterManager* GetMediaRouterManager();
|
CefMediaRouterManager* GetMediaRouterManager();
|
||||||
|
|
||||||
void set_cookieable_schemes(
|
using CookieableSchemes = base::Optional<std::vector<std::string>>;
|
||||||
base::Optional<std::vector<std::string>> schemes) {
|
void set_cookieable_schemes(const CookieableSchemes& schemes) {
|
||||||
cookieable_schemes_ = schemes;
|
cookieable_schemes_ = schemes;
|
||||||
}
|
}
|
||||||
|
CookieableSchemes cookieable_schemes() const { return cookieable_schemes_; }
|
||||||
|
|
||||||
// These accessors are safe to call from any thread because the values don't
|
// These accessors are safe to call from any thread because the values don't
|
||||||
// change during this object's lifespan.
|
// change during this object's lifespan.
|
||||||
@ -227,10 +228,9 @@ class CefBrowserContext {
|
|||||||
const CefRequestContextSettings settings_;
|
const CefRequestContextSettings settings_;
|
||||||
base::FilePath cache_path_;
|
base::FilePath cache_path_;
|
||||||
|
|
||||||
base::Optional<std::vector<std::string>> cookieable_schemes_;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::unique_ptr<CefIOThreadState> iothread_state_;
|
std::unique_ptr<CefIOThreadState> iothread_state_;
|
||||||
|
CookieableSchemes cookieable_schemes_;
|
||||||
std::unique_ptr<CefMediaRouterManager> media_router_manager_;
|
std::unique_ptr<CefMediaRouterManager> media_router_manager_;
|
||||||
|
|
||||||
// CefRequestContextImpl objects referencing this object.
|
// CefRequestContextImpl objects referencing this object.
|
||||||
|
@ -17,6 +17,7 @@
|
|||||||
#include "services/network/public/cpp/resource_request.h"
|
#include "services/network/public/cpp/resource_request.h"
|
||||||
|
|
||||||
namespace net_service {
|
namespace net_service {
|
||||||
|
namespace cookie_helper {
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
@ -137,6 +138,28 @@ void SaveCookiesOnUIThread(content::BrowserContext* browser_context,
|
|||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
|
bool IsCookieableScheme(
|
||||||
|
const GURL& url,
|
||||||
|
const base::Optional<std::vector<std::string>>& cookieable_schemes) {
|
||||||
|
if (!url.has_scheme())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (cookieable_schemes) {
|
||||||
|
// The client has explicitly registered the full set of schemes that should
|
||||||
|
// be supported.
|
||||||
|
const auto url_scheme = url.scheme_piece();
|
||||||
|
for (auto scheme : *cookieable_schemes) {
|
||||||
|
if (url_scheme == scheme)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Schemes that support cookies by default.
|
||||||
|
// This should match CookieMonster::kDefaultCookieableSchemes.
|
||||||
|
return url.SchemeIsHTTPOrHTTPS() || url.SchemeIsWSOrWSS();
|
||||||
|
}
|
||||||
|
|
||||||
void LoadCookies(content::BrowserContext* browser_context,
|
void LoadCookies(content::BrowserContext* browser_context,
|
||||||
const network::ResourceRequest& request,
|
const network::ResourceRequest& request,
|
||||||
const AllowCookieCallback& allow_cookie_callback,
|
const AllowCookieCallback& allow_cookie_callback,
|
||||||
@ -228,4 +251,5 @@ void SaveCookies(content::BrowserContext* browser_context,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} // namespace cookie_helper
|
||||||
} // namespace net_service
|
} // namespace net_service
|
@ -21,6 +21,14 @@ struct ResourceRequest;
|
|||||||
} // namespace network
|
} // namespace network
|
||||||
|
|
||||||
namespace net_service {
|
namespace net_service {
|
||||||
|
namespace cookie_helper {
|
||||||
|
|
||||||
|
// Returns true if the scheme for |url| supports cookies. |cookieable_schemes|
|
||||||
|
// is the optional list of schemes that the client has explicitly registered as
|
||||||
|
// cookieable, which may intentionally exclude standard schemes.
|
||||||
|
bool IsCookieableScheme(
|
||||||
|
const GURL& url,
|
||||||
|
const base::Optional<std::vector<std::string>>& cookieable_schemes);
|
||||||
|
|
||||||
using AllowCookieCallback =
|
using AllowCookieCallback =
|
||||||
base::Callback<void(const net::CanonicalCookie&, bool* /* allow */)>;
|
base::Callback<void(const net::CanonicalCookie&, bool* /* allow */)>;
|
||||||
@ -52,6 +60,7 @@ void SaveCookies(content::BrowserContext* browser_context,
|
|||||||
const AllowCookieCallback& allow_cookie_callback,
|
const AllowCookieCallback& allow_cookie_callback,
|
||||||
DoneCookieCallback done_callback);
|
DoneCookieCallback done_callback);
|
||||||
|
|
||||||
|
} // namespace cookie_helper
|
||||||
} // namespace net_service
|
} // namespace net_service
|
||||||
|
|
||||||
#endif // CEF_LIBCEF_BROWSER_NET_SERVICE_COOKIE_HELPER_H_
|
#endif // CEF_LIBCEF_BROWSER_NET_SERVICE_COOKIE_HELPER_H_
|
||||||
|
@ -264,6 +264,7 @@ class InterceptedRequestHandlerWrapper : public InterceptedRequestHandler {
|
|||||||
CefBrowserContext::FromBrowserContext(browser_context);
|
CefBrowserContext::FromBrowserContext(browser_context);
|
||||||
iothread_state_ = cef_browser_context->iothread_state();
|
iothread_state_ = cef_browser_context->iothread_state();
|
||||||
DCHECK(iothread_state_);
|
DCHECK(iothread_state_);
|
||||||
|
cookieable_schemes_ = cef_browser_context->cookieable_schemes();
|
||||||
|
|
||||||
// We register to be notified of CEF context or browser destruction so
|
// We register to be notified of CEF context or browser destruction so
|
||||||
// that we can stop accepting new requests and cancel pending/in-progress
|
// that we can stop accepting new requests and cancel pending/in-progress
|
||||||
@ -312,6 +313,7 @@ class InterceptedRequestHandlerWrapper : public InterceptedRequestHandler {
|
|||||||
CefRefPtr<CefBrowserHostImpl> browser_;
|
CefRefPtr<CefBrowserHostImpl> browser_;
|
||||||
CefRefPtr<CefFrame> frame_;
|
CefRefPtr<CefFrame> frame_;
|
||||||
CefIOThreadState* iothread_state_ = nullptr;
|
CefIOThreadState* iothread_state_ = nullptr;
|
||||||
|
CefBrowserContext::CookieableSchemes cookieable_schemes_;
|
||||||
int render_process_id_ = 0;
|
int render_process_id_ = 0;
|
||||||
int render_frame_id_ = -1;
|
int render_frame_id_ = -1;
|
||||||
int frame_tree_node_id_ = -1;
|
int frame_tree_node_id_ = -1;
|
||||||
@ -487,6 +489,13 @@ class InterceptedRequestHandlerWrapper : public InterceptedRequestHandler {
|
|||||||
base::OnceClosure callback) {
|
base::OnceClosure callback) {
|
||||||
CEF_REQUIRE_IOT();
|
CEF_REQUIRE_IOT();
|
||||||
|
|
||||||
|
if (!cookie_helper::IsCookieableScheme(request->url,
|
||||||
|
init_state_->cookieable_schemes_)) {
|
||||||
|
// The scheme does not support cookies.
|
||||||
|
std::move(callback).Run();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// We need to load/save cookies ourselves for custom-handled requests, or
|
// We need to load/save cookies ourselves for custom-handled requests, or
|
||||||
// if we're using a cookie filter.
|
// if we're using a cookie filter.
|
||||||
auto allow_cookie_callback =
|
auto allow_cookie_callback =
|
||||||
@ -499,7 +508,7 @@ class InterceptedRequestHandlerWrapper : public InterceptedRequestHandler {
|
|||||||
auto done_cookie_callback = base::BindOnce(
|
auto done_cookie_callback = base::BindOnce(
|
||||||
&InterceptedRequestHandlerWrapper::ContinueWithLoadedCookies,
|
&InterceptedRequestHandlerWrapper::ContinueWithLoadedCookies,
|
||||||
weak_ptr_factory_.GetWeakPtr(), id, request, std::move(callback));
|
weak_ptr_factory_.GetWeakPtr(), id, request, std::move(callback));
|
||||||
net_service::LoadCookies(init_state_->browser_context_, *request,
|
cookie_helper::LoadCookies(init_state_->browser_context_, *request,
|
||||||
allow_cookie_callback,
|
allow_cookie_callback,
|
||||||
std::move(done_cookie_callback));
|
std::move(done_cookie_callback));
|
||||||
}
|
}
|
||||||
@ -850,6 +859,13 @@ class InterceptedRequestHandlerWrapper : public InterceptedRequestHandler {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!cookie_helper::IsCookieableScheme(request->url,
|
||||||
|
init_state_->cookieable_schemes_)) {
|
||||||
|
// The scheme does not support cookies.
|
||||||
|
std::move(callback).Run();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// We need to load/save cookies ourselves for custom-handled requests, or
|
// We need to load/save cookies ourselves for custom-handled requests, or
|
||||||
// if we're using a cookie filter.
|
// if we're using a cookie filter.
|
||||||
auto allow_cookie_callback =
|
auto allow_cookie_callback =
|
||||||
@ -862,7 +878,7 @@ class InterceptedRequestHandlerWrapper : public InterceptedRequestHandler {
|
|||||||
auto done_cookie_callback = base::BindOnce(
|
auto done_cookie_callback = base::BindOnce(
|
||||||
&InterceptedRequestHandlerWrapper::ContinueWithSavedCookies,
|
&InterceptedRequestHandlerWrapper::ContinueWithSavedCookies,
|
||||||
weak_ptr_factory_.GetWeakPtr(), id, std::move(callback));
|
weak_ptr_factory_.GetWeakPtr(), id, std::move(callback));
|
||||||
net_service::SaveCookies(init_state_->browser_context_, *request, headers,
|
cookie_helper::SaveCookies(init_state_->browser_context_, *request, headers,
|
||||||
allow_cookie_callback,
|
allow_cookie_callback,
|
||||||
std::move(done_cookie_callback));
|
std::move(done_cookie_callback));
|
||||||
}
|
}
|
||||||
|
@ -1569,20 +1569,24 @@ class CookieAccessTestHandler : public RoutingTestHandler,
|
|||||||
EXPECT_EQ(0, can_save_cookie1_ct_);
|
EXPECT_EQ(0, can_save_cookie1_ct_);
|
||||||
EXPECT_EQ(0, can_send_cookie2_ct_);
|
EXPECT_EQ(0, can_send_cookie2_ct_);
|
||||||
} else {
|
} else {
|
||||||
// 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_ALL_COOKIES) {
|
if (test_mode_ == BLOCK_ALL_COOKIES) {
|
||||||
// Never send any cookies.
|
// Never send any cookies.
|
||||||
EXPECT_EQ(0, can_send_cookie2_ct_);
|
EXPECT_EQ(0, can_send_cookie2_ct_);
|
||||||
|
EXPECT_EQ(0, can_save_cookie1_ct_);
|
||||||
} else if (test_mode_ & BLOCK_WRITE) {
|
} else if (test_mode_ & BLOCK_WRITE) {
|
||||||
// Get 1 calls to CanSendCookie for the 2nd network request due to the
|
// Get 1 calls to CanSendCookie for the 2nd network request due to the
|
||||||
// JS cookie (network cookie is blocked).
|
// JS cookie (network cookie is blocked).
|
||||||
EXPECT_EQ(1, can_send_cookie2_ct_);
|
EXPECT_EQ(1, can_send_cookie2_ct_);
|
||||||
|
// Get 1 call to CanSaveCookie for the 1st network request due to the
|
||||||
|
// network cookie.
|
||||||
|
EXPECT_EQ(1, can_save_cookie1_ct_);
|
||||||
} else {
|
} else {
|
||||||
// Get 2 calls to CanSendCookie for the 2nd network request due to the
|
// Get 2 calls to CanSendCookie for the 2nd network request due to the
|
||||||
// network cookie + JS cookie.
|
// network cookie + JS cookie.
|
||||||
EXPECT_EQ(2, can_send_cookie2_ct_);
|
EXPECT_EQ(2, can_send_cookie2_ct_);
|
||||||
|
// Get 1 call to CanSaveCookie for the 1st network request due to the
|
||||||
|
// network cookie.
|
||||||
|
EXPECT_EQ(1, can_save_cookie1_ct_);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -22,6 +22,7 @@ const char kMimeTypeText[] = "text/plain";
|
|||||||
|
|
||||||
const char kDefaultHtml[] = "<html><body>TEST</body></html>";
|
const char kDefaultHtml[] = "<html><body>TEST</body></html>";
|
||||||
const char kDefaultText[] = "TEST";
|
const char kDefaultText[] = "TEST";
|
||||||
|
const char kDefaultCookie[] = "testCookie=testVal";
|
||||||
|
|
||||||
const char kSuccessMsg[] = "CorsTestHandler.Success";
|
const char kSuccessMsg[] = "CorsTestHandler.Success";
|
||||||
const char kFailureMsg[] = "CorsTestHandler.Failure";
|
const char kFailureMsg[] = "CorsTestHandler.Failure";
|
||||||
@ -144,6 +145,9 @@ struct TestSetup {
|
|||||||
// Used for testing received console messages.
|
// Used for testing received console messages.
|
||||||
std::vector<std::string> console_messages;
|
std::vector<std::string> console_messages;
|
||||||
|
|
||||||
|
// If true cookies will be cleared after every test run.
|
||||||
|
bool clear_cookies = false;
|
||||||
|
|
||||||
void AddResource(Resource* resource) {
|
void AddResource(Resource* resource) {
|
||||||
DCHECK(resource);
|
DCHECK(resource);
|
||||||
resource->Validate();
|
resource->Validate();
|
||||||
@ -206,6 +210,12 @@ struct TestSetup {
|
|||||||
(*it)->AssertDone();
|
(*it)->AssertDone();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Optionally override to verify cleared cookie contents.
|
||||||
|
virtual bool VerifyClearedCookies(
|
||||||
|
const test_request::CookieVector& cookies) const {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class TestServerObserver : public test_server::ObserverHelper {
|
class TestServerObserver : public test_server::ObserverHelper {
|
||||||
@ -284,6 +294,18 @@ class CorsTestHandler : public RoutingTestHandler {
|
|||||||
void DestroyTest() override {
|
void DestroyTest() override {
|
||||||
EXPECT_TRUE(shutting_down_);
|
EXPECT_TRUE(shutting_down_);
|
||||||
|
|
||||||
|
if (setup_->NeedsServer()) {
|
||||||
|
EXPECT_TRUE(got_stopped_server_);
|
||||||
|
} else {
|
||||||
|
EXPECT_FALSE(got_stopped_server_);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (setup_->clear_cookies) {
|
||||||
|
EXPECT_TRUE(got_cleared_cookies_);
|
||||||
|
} else {
|
||||||
|
EXPECT_FALSE(got_cleared_cookies_);
|
||||||
|
}
|
||||||
|
|
||||||
setup_->AssertDone();
|
setup_->AssertDone();
|
||||||
EXPECT_TRUE(setup_->console_messages.empty())
|
EXPECT_TRUE(setup_->console_messages.empty())
|
||||||
<< "Did not receive expected console message: "
|
<< "Did not receive expected console message: "
|
||||||
@ -292,17 +314,6 @@ class CorsTestHandler : public RoutingTestHandler {
|
|||||||
RoutingTestHandler::DestroyTest();
|
RoutingTestHandler::DestroyTest();
|
||||||
}
|
}
|
||||||
|
|
||||||
void DestroyTestIfDone() {
|
|
||||||
CEF_REQUIRE_UI_THREAD();
|
|
||||||
if (shutting_down_)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (setup_->IsDone()) {
|
|
||||||
shutting_down_ = true;
|
|
||||||
StopServer();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
CefRefPtr<CefResourceHandler> GetResourceHandler(
|
CefRefPtr<CefResourceHandler> GetResourceHandler(
|
||||||
CefRefPtr<CefBrowser> browser,
|
CefRefPtr<CefBrowser> browser,
|
||||||
CefRefPtr<CefFrame> frame,
|
CefRefPtr<CefFrame> frame,
|
||||||
@ -412,6 +423,17 @@ class CorsTestHandler : public RoutingTestHandler {
|
|||||||
CefPostTask(TID_UI, base::Bind(&CorsTestHandler::DestroyTestIfDone, this));
|
CefPostTask(TID_UI, base::Bind(&CorsTestHandler::DestroyTestIfDone, this));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DestroyTestIfDone() {
|
||||||
|
CEF_REQUIRE_UI_THREAD();
|
||||||
|
if (shutting_down_)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (setup_->IsDone()) {
|
||||||
|
shutting_down_ = true;
|
||||||
|
StopServer();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void StartServer(const base::Closure& next_step) {
|
void StartServer(const base::Closure& next_step) {
|
||||||
if (!CefCurrentlyOn(TID_UI)) {
|
if (!CefCurrentlyOn(TID_UI)) {
|
||||||
CefPostTask(TID_UI,
|
CefPostTask(TID_UI,
|
||||||
@ -433,7 +455,7 @@ class CorsTestHandler : public RoutingTestHandler {
|
|||||||
CEF_REQUIRE_UI_THREAD();
|
CEF_REQUIRE_UI_THREAD();
|
||||||
if (!server_) {
|
if (!server_) {
|
||||||
DCHECK(!setup_->NeedsServer());
|
DCHECK(!setup_->NeedsServer());
|
||||||
DestroyTest();
|
AfterStoppedServer();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -443,7 +465,32 @@ class CorsTestHandler : public RoutingTestHandler {
|
|||||||
|
|
||||||
void StoppedServer() {
|
void StoppedServer() {
|
||||||
CEF_REQUIRE_UI_THREAD();
|
CEF_REQUIRE_UI_THREAD();
|
||||||
|
got_stopped_server_.yes();
|
||||||
server_ = nullptr;
|
server_ = nullptr;
|
||||||
|
AfterStoppedServer();
|
||||||
|
}
|
||||||
|
|
||||||
|
void AfterStoppedServer() {
|
||||||
|
CEF_REQUIRE_UI_THREAD();
|
||||||
|
if (setup_->clear_cookies) {
|
||||||
|
ClearCookies();
|
||||||
|
} else {
|
||||||
|
DestroyTest();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ClearCookies() {
|
||||||
|
CEF_REQUIRE_UI_THREAD();
|
||||||
|
DCHECK(setup_->clear_cookies);
|
||||||
|
test_request::GetAllCookies(
|
||||||
|
CefCookieManager::GetGlobalManager(nullptr), /*delete_cookies=*/true,
|
||||||
|
base::Bind(&CorsTestHandler::ClearedCookies, this));
|
||||||
|
}
|
||||||
|
|
||||||
|
void ClearedCookies(const test_request::CookieVector& cookies) {
|
||||||
|
CEF_REQUIRE_UI_THREAD();
|
||||||
|
got_cleared_cookies_.yes();
|
||||||
|
EXPECT_TRUE(setup_->VerifyClearedCookies(cookies));
|
||||||
DestroyTest();
|
DestroyTest();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -458,6 +505,9 @@ class CorsTestHandler : public RoutingTestHandler {
|
|||||||
TestServerObserver* server_ = nullptr;
|
TestServerObserver* server_ = nullptr;
|
||||||
bool shutting_down_ = false;
|
bool shutting_down_ = false;
|
||||||
|
|
||||||
|
TrackCallback got_stopped_server_;
|
||||||
|
TrackCallback got_cleared_cookies_;
|
||||||
|
|
||||||
IMPLEMENT_REFCOUNTING(CorsTestHandler);
|
IMPLEMENT_REFCOUNTING(CorsTestHandler);
|
||||||
DISALLOW_COPY_AND_ASSIGN(CorsTestHandler);
|
DISALLOW_COPY_AND_ASSIGN(CorsTestHandler);
|
||||||
};
|
};
|
||||||
@ -558,6 +608,68 @@ TEST(CorsTest, BasicCustomStandardSchemeWithQuery) {
|
|||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
|
struct CookieTestSetup : TestSetup {
|
||||||
|
CookieTestSetup() {}
|
||||||
|
|
||||||
|
bool expect_cookie = false;
|
||||||
|
|
||||||
|
bool VerifyClearedCookies(
|
||||||
|
const test_request::CookieVector& cookies) const override {
|
||||||
|
if (!expect_cookie) {
|
||||||
|
EXPECT_TRUE(cookies.empty());
|
||||||
|
return cookies.empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
EXPECT_EQ(1U, cookies.size());
|
||||||
|
const std::string& cookie = CefString(&cookies[0].name).ToString() + "=" +
|
||||||
|
CefString(&cookies[0].value).ToString();
|
||||||
|
EXPECT_STREQ(kDefaultCookie, cookie.c_str());
|
||||||
|
return cookie == kDefaultCookie;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct CookieResource : Resource {
|
||||||
|
CookieResource() {}
|
||||||
|
|
||||||
|
bool expect_cookie = false;
|
||||||
|
|
||||||
|
void InitSetCookie() {
|
||||||
|
response->SetHeaderByName("Set-Cookie", kDefaultCookie,
|
||||||
|
/*override=*/true);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool VerifyRequest(CefRefPtr<CefRequest> request) const override {
|
||||||
|
const std::string& cookie = request->GetHeaderByName("Cookie");
|
||||||
|
const std::string& expected_cookie =
|
||||||
|
expect_cookie ? kDefaultCookie : std::string();
|
||||||
|
EXPECT_STREQ(expected_cookie.c_str(), cookie.c_str()) << GetPathURL();
|
||||||
|
return expected_cookie == cookie;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
void SetupCookieExpectations(CookieTestSetup* setup,
|
||||||
|
CookieResource* main_resource,
|
||||||
|
CookieResource* sub_resource) {
|
||||||
|
// All schemes except custom non-standard support cookies.
|
||||||
|
const bool supports_cookies =
|
||||||
|
main_resource->handler != HandlerType::CUSTOM_NONSTANDARD_SCHEME;
|
||||||
|
|
||||||
|
// The main resource may set the cookie (if cookies are supported), but should
|
||||||
|
// not receive one.
|
||||||
|
main_resource->InitSetCookie();
|
||||||
|
main_resource->expect_cookie = false;
|
||||||
|
|
||||||
|
// A cookie will be set only for schemes that support cookies.
|
||||||
|
setup->expect_cookie = supports_cookies;
|
||||||
|
// Always clear cookies so we can verify that one wasn't set unexpectedly.
|
||||||
|
setup->clear_cookies = true;
|
||||||
|
|
||||||
|
// Expect the sub-resource to receive the cookie for same-origin requests
|
||||||
|
// only.
|
||||||
|
sub_resource->expect_cookie =
|
||||||
|
supports_cookies && main_resource->handler == sub_resource->handler;
|
||||||
|
}
|
||||||
|
|
||||||
std::string GetIframeMainHtml(const std::string& iframe_url,
|
std::string GetIframeMainHtml(const std::string& iframe_url,
|
||||||
const std::string& sandbox_attribs) {
|
const std::string& sandbox_attribs) {
|
||||||
return "<html><body>TEST<iframe src=\"" + iframe_url + "\" sandbox=\"" +
|
return "<html><body>TEST<iframe src=\"" + iframe_url + "\" sandbox=\"" +
|
||||||
@ -576,12 +688,12 @@ bool HasSandboxAttrib(const std::string& sandbox_attribs,
|
|||||||
return sandbox_attribs.find(attrib) != std::string::npos;
|
return sandbox_attribs.find(attrib) != std::string::npos;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetupIframeRequest(TestSetup* setup,
|
void SetupIframeRequest(CookieTestSetup* setup,
|
||||||
const std::string& test_name,
|
const std::string& test_name,
|
||||||
HandlerType main_handler,
|
HandlerType main_handler,
|
||||||
Resource* main_resource,
|
CookieResource* main_resource,
|
||||||
HandlerType iframe_handler,
|
HandlerType iframe_handler,
|
||||||
Resource* iframe_resource,
|
CookieResource* iframe_resource,
|
||||||
const std::string& sandbox_attribs) {
|
const std::string& sandbox_attribs) {
|
||||||
const std::string& base_path = "/" + test_name;
|
const std::string& base_path = "/" + test_name;
|
||||||
|
|
||||||
@ -594,6 +706,8 @@ void SetupIframeRequest(TestSetup* setup,
|
|||||||
main_resource->Init(main_handler, base_path, kMimeTypeHtml,
|
main_resource->Init(main_handler, base_path, kMimeTypeHtml,
|
||||||
GetIframeMainHtml(iframe_url, sandbox_attribs));
|
GetIframeMainHtml(iframe_url, sandbox_attribs));
|
||||||
|
|
||||||
|
SetupCookieExpectations(setup, main_resource, iframe_resource);
|
||||||
|
|
||||||
if (HasSandboxAttrib(sandbox_attribs, "allow-scripts")) {
|
if (HasSandboxAttrib(sandbox_attribs, "allow-scripts")) {
|
||||||
// Expect the iframe to load successfully and send the SuccessMsg.
|
// Expect the iframe to load successfully and send the SuccessMsg.
|
||||||
iframe_resource->expected_success_query_ct = 1;
|
iframe_resource->expected_success_query_ct = 1;
|
||||||
@ -636,8 +750,8 @@ void SetupIframeRequest(TestSetup* setup,
|
|||||||
#define CORS_TEST_IFRAME(test_name, handler_main, handler_iframe, \
|
#define CORS_TEST_IFRAME(test_name, handler_main, handler_iframe, \
|
||||||
sandbox_attribs) \
|
sandbox_attribs) \
|
||||||
TEST(CorsTest, Iframe##test_name) { \
|
TEST(CorsTest, Iframe##test_name) { \
|
||||||
TestSetup setup; \
|
CookieTestSetup setup; \
|
||||||
Resource resource_main, resource_iframe; \
|
CookieResource resource_main, resource_iframe; \
|
||||||
SetupIframeRequest(&setup, "CorsTest.Iframe" #test_name, \
|
SetupIframeRequest(&setup, "CorsTest.Iframe" #test_name, \
|
||||||
HandlerType::handler_main, &resource_main, \
|
HandlerType::handler_main, &resource_main, \
|
||||||
HandlerType::handler_iframe, &resource_iframe, \
|
HandlerType::handler_iframe, &resource_iframe, \
|
||||||
@ -698,7 +812,7 @@ CORS_TEST_IFRAME_ALL(AllowScriptsAndSameOrigin,
|
|||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
struct SubResource : Resource {
|
struct SubResource : CookieResource {
|
||||||
SubResource() {}
|
SubResource() {}
|
||||||
|
|
||||||
std::string main_origin;
|
std::string main_origin;
|
||||||
@ -733,14 +847,15 @@ struct SubResource : Resource {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool VerifyRequest(CefRefPtr<CefRequest> request) const override {
|
bool VerifyRequest(CefRefPtr<CefRequest> request) const override {
|
||||||
|
if (!CookieResource::VerifyRequest(request))
|
||||||
|
return false;
|
||||||
|
|
||||||
// Verify that the "Origin" header contains the expected value.
|
// Verify that the "Origin" header contains the expected value.
|
||||||
const std::string& origin = request->GetHeaderByName("Origin");
|
const std::string& origin = request->GetHeaderByName("Origin");
|
||||||
if (is_cross_origin) {
|
const std::string& expected_origin =
|
||||||
EXPECT_STREQ(main_origin.c_str(), origin.c_str());
|
is_cross_origin ? main_origin : std::string();
|
||||||
return main_origin == origin;
|
EXPECT_STREQ(expected_origin.c_str(), origin.c_str()) << GetPathURL();
|
||||||
}
|
return expected_origin == origin;
|
||||||
EXPECT_TRUE(origin.empty());
|
|
||||||
return origin.empty();
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -809,10 +924,10 @@ std::string GetExecMainHtml(ExecMode mode, const std::string& sub_url) {
|
|||||||
|
|
||||||
// XHR and fetch requests behave the same, except for console message contents.
|
// XHR and fetch requests behave the same, except for console message contents.
|
||||||
void SetupExecRequest(ExecMode mode,
|
void SetupExecRequest(ExecMode mode,
|
||||||
TestSetup* setup,
|
CookieTestSetup* setup,
|
||||||
const std::string& test_name,
|
const std::string& test_name,
|
||||||
HandlerType main_handler,
|
HandlerType main_handler,
|
||||||
Resource* main_resource,
|
CookieResource* main_resource,
|
||||||
HandlerType sub_handler,
|
HandlerType sub_handler,
|
||||||
SubResource* sub_resource,
|
SubResource* sub_resource,
|
||||||
bool add_header) {
|
bool add_header) {
|
||||||
@ -828,6 +943,8 @@ void SetupExecRequest(ExecMode mode,
|
|||||||
main_resource->Init(main_handler, base_path, kMimeTypeHtml,
|
main_resource->Init(main_handler, base_path, kMimeTypeHtml,
|
||||||
GetExecMainHtml(mode, sub_url));
|
GetExecMainHtml(mode, sub_url));
|
||||||
|
|
||||||
|
SetupCookieExpectations(setup, main_resource, sub_resource);
|
||||||
|
|
||||||
if (sub_resource->is_cross_origin &&
|
if (sub_resource->is_cross_origin &&
|
||||||
(!sub_resource->supports_cors || !add_header)) {
|
(!sub_resource->supports_cors || !add_header)) {
|
||||||
// Expect the cross-origin XHR to be blocked.
|
// Expect the cross-origin XHR to be blocked.
|
||||||
@ -877,8 +994,8 @@ void SetupExecRequest(ExecMode mode,
|
|||||||
// Test XHR requests with different origin combinations.
|
// Test XHR requests with different origin combinations.
|
||||||
#define CORS_TEST_XHR(test_name, handler_main, handler_sub, add_header) \
|
#define CORS_TEST_XHR(test_name, handler_main, handler_sub, add_header) \
|
||||||
TEST(CorsTest, Xhr##test_name) { \
|
TEST(CorsTest, Xhr##test_name) { \
|
||||||
TestSetup setup; \
|
CookieTestSetup setup; \
|
||||||
Resource resource_main; \
|
CookieResource resource_main; \
|
||||||
SubResource resource_sub; \
|
SubResource resource_sub; \
|
||||||
SetupExecRequest(ExecMode::XHR, &setup, "CorsTest.Xhr" #test_name, \
|
SetupExecRequest(ExecMode::XHR, &setup, "CorsTest.Xhr" #test_name, \
|
||||||
HandlerType::handler_main, &resource_main, \
|
HandlerType::handler_main, &resource_main, \
|
||||||
@ -930,8 +1047,8 @@ CORS_TEST_XHR_ALL(WithHeader, true)
|
|||||||
// Test fetch requests with different origin combinations.
|
// Test fetch requests with different origin combinations.
|
||||||
#define CORS_TEST_FETCH(test_name, handler_main, handler_sub, add_header) \
|
#define CORS_TEST_FETCH(test_name, handler_main, handler_sub, add_header) \
|
||||||
TEST(CorsTest, Fetch##test_name) { \
|
TEST(CorsTest, Fetch##test_name) { \
|
||||||
TestSetup setup; \
|
CookieTestSetup setup; \
|
||||||
Resource resource_main; \
|
CookieResource resource_main; \
|
||||||
SubResource resource_sub; \
|
SubResource resource_sub; \
|
||||||
SetupExecRequest(ExecMode::FETCH, &setup, "CorsTest.Fetch" #test_name, \
|
SetupExecRequest(ExecMode::FETCH, &setup, "CorsTest.Fetch" #test_name, \
|
||||||
HandlerType::handler_main, &resource_main, \
|
HandlerType::handler_main, &resource_main, \
|
||||||
|
@ -2605,11 +2605,13 @@ void RegisterSchemeHandlerCustomSchemes(
|
|||||||
// Add a custom standard scheme.
|
// Add a custom standard scheme.
|
||||||
registrar->AddCustomScheme(
|
registrar->AddCustomScheme(
|
||||||
"customstd", CEF_SCHEME_OPTION_STANDARD | CEF_SCHEME_OPTION_CORS_ENABLED);
|
"customstd", CEF_SCHEME_OPTION_STANDARD | CEF_SCHEME_OPTION_CORS_ENABLED);
|
||||||
|
cookiable_schemes.push_back("customstd");
|
||||||
// Also used in cors_unittest.cc.
|
// Also used in cors_unittest.cc.
|
||||||
registrar->AddCustomScheme("customstdfetch",
|
registrar->AddCustomScheme("customstdfetch",
|
||||||
CEF_SCHEME_OPTION_STANDARD |
|
CEF_SCHEME_OPTION_STANDARD |
|
||||||
CEF_SCHEME_OPTION_CORS_ENABLED |
|
CEF_SCHEME_OPTION_CORS_ENABLED |
|
||||||
CEF_SCHEME_OPTION_FETCH_ENABLED);
|
CEF_SCHEME_OPTION_FETCH_ENABLED);
|
||||||
|
cookiable_schemes.push_back("customstdfetch");
|
||||||
// Add a custom non-standard scheme.
|
// Add a custom non-standard scheme.
|
||||||
registrar->AddCustomScheme("customnonstd", CEF_SCHEME_OPTION_NONE);
|
registrar->AddCustomScheme("customnonstd", CEF_SCHEME_OPTION_NONE);
|
||||||
registrar->AddCustomScheme("customnonstdfetch",
|
registrar->AddCustomScheme("customnonstdfetch",
|
||||||
|
@ -94,6 +94,40 @@ class RequestClient : public CefURLRequestClient, public State {
|
|||||||
const RequestDoneCallback done_callback_;
|
const RequestDoneCallback done_callback_;
|
||||||
|
|
||||||
IMPLEMENT_REFCOUNTING(RequestClient);
|
IMPLEMENT_REFCOUNTING(RequestClient);
|
||||||
|
DISALLOW_COPY_AND_ASSIGN(RequestClient);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Implementation that collects all cookies, and optionally deletes them.
|
||||||
|
class CookieVisitor : public CefCookieVisitor {
|
||||||
|
public:
|
||||||
|
CookieVisitor(bool deleteCookies, const CookieDoneCallback& callback)
|
||||||
|
: delete_cookies_(deleteCookies), callback_(callback) {
|
||||||
|
DCHECK(!callback_.is_null());
|
||||||
|
}
|
||||||
|
|
||||||
|
~CookieVisitor() override {
|
||||||
|
CEF_REQUIRE_UI_THREAD();
|
||||||
|
callback_.Run(cookies_);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Visit(const CefCookie& cookie,
|
||||||
|
int count,
|
||||||
|
int total,
|
||||||
|
bool& deleteCookie) override {
|
||||||
|
CEF_REQUIRE_UI_THREAD();
|
||||||
|
cookies_.push_back(cookie);
|
||||||
|
if (delete_cookies_)
|
||||||
|
deleteCookie = true;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
CookieVector cookies_;
|
||||||
|
bool delete_cookies_;
|
||||||
|
CookieDoneCallback callback_;
|
||||||
|
|
||||||
|
IMPLEMENT_REFCOUNTING(CookieVisitor);
|
||||||
|
DISALLOW_COPY_AND_ASSIGN(CookieVisitor);
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
@ -145,4 +179,24 @@ CefRefPtr<CefResourceHandler> CreateResourceHandler(
|
|||||||
headerMap, stream);
|
headerMap, stream);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GetAllCookies(CefRefPtr<CefCookieManager> manager,
|
||||||
|
bool deleteCookies,
|
||||||
|
const CookieDoneCallback& callback) {
|
||||||
|
bool result =
|
||||||
|
manager->VisitAllCookies(new CookieVisitor(deleteCookies, callback));
|
||||||
|
DCHECK(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Retrieves URL cookies from |manager| and executes |callback| upon completion.
|
||||||
|
// If |deleteCookies| is true the cookies will also be deleted.
|
||||||
|
void GetUrlCookies(CefRefPtr<CefCookieManager> manager,
|
||||||
|
const CefString& url,
|
||||||
|
bool includeHttpOnly,
|
||||||
|
bool deleteCookies,
|
||||||
|
const CookieDoneCallback& callback) {
|
||||||
|
bool result = manager->VisitUrlCookies(
|
||||||
|
url, includeHttpOnly, new CookieVisitor(deleteCookies, callback));
|
||||||
|
DCHECK(result);
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace test_request
|
} // namespace test_request
|
||||||
|
@ -9,6 +9,7 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
#include "include/base/cef_bind.h"
|
#include "include/base/cef_bind.h"
|
||||||
|
#include "include/cef_cookie.h"
|
||||||
#include "include/cef_frame.h"
|
#include "include/cef_frame.h"
|
||||||
#include "include/cef_request.h"
|
#include "include/cef_request.h"
|
||||||
#include "include/cef_request_context.h"
|
#include "include/cef_request_context.h"
|
||||||
@ -73,6 +74,23 @@ CefRefPtr<CefResourceHandler> CreateResourceHandler(
|
|||||||
CefRefPtr<CefResponse> response,
|
CefRefPtr<CefResponse> response,
|
||||||
const std::string& response_data);
|
const std::string& response_data);
|
||||||
|
|
||||||
|
typedef std::vector<CefCookie> CookieVector;
|
||||||
|
typedef base::Callback<void(const CookieVector& cookies)> CookieDoneCallback;
|
||||||
|
|
||||||
|
// Retrieves all cookies from |manager| and executes |callback| upon completion.
|
||||||
|
// If |deleteCookies| is true the cookies will also be deleted.
|
||||||
|
void GetAllCookies(CefRefPtr<CefCookieManager> manager,
|
||||||
|
bool deleteCookies,
|
||||||
|
const CookieDoneCallback& callback);
|
||||||
|
|
||||||
|
// Retrieves URL cookies from |manager| and executes |callback| upon completion.
|
||||||
|
// If |deleteCookies| is true the cookies will also be deleted.
|
||||||
|
void GetUrlCookies(CefRefPtr<CefCookieManager> manager,
|
||||||
|
const CefString& url,
|
||||||
|
bool includeHttpOnly,
|
||||||
|
bool deleteCookies,
|
||||||
|
const CookieDoneCallback& callback);
|
||||||
|
|
||||||
} // namespace test_request
|
} // namespace test_request
|
||||||
|
|
||||||
#endif // CEF_TESTS_CEFTESTS_TEST_REQUEST_H_
|
#endif // CEF_TESTS_CEFTESTS_TEST_REQUEST_H_
|
||||||
|
Loading…
x
Reference in New Issue
Block a user