| Index: content/browser/browsing_data/clear_site_data_throttle_browsertest.cc
|
| diff --git a/content/browser/browsing_data/clear_site_data_throttle_browsertest.cc b/content/browser/browsing_data/clear_site_data_throttle_browsertest.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..f5e43643bc67802e5fd264bf70fd51cd243394c3
|
| --- /dev/null
|
| +++ b/content/browser/browsing_data/clear_site_data_throttle_browsertest.cc
|
| @@ -0,0 +1,234 @@
|
| +// Copyright 2016 The Chromium Authors. All rights reserved.
|
| +// Use of this source code is governed by a BSD-style license that can be
|
| +// found in the LICENSE file.
|
| +
|
| +#include "content/browser/browsing_data/clear_site_data_throttle.h"
|
| +
|
| +#include <memory>
|
| +
|
| +#include "base/bind.h"
|
| +#include "base/callback.h"
|
| +#include "base/command_line.h"
|
| +#include "content/public/browser/content_browser_client.h"
|
| +#include "content/public/browser/web_contents.h"
|
| +#include "content/public/common/content_switches.h"
|
| +#include "content/public/test/content_browser_test.h"
|
| +#include "content/public/test/content_browser_test_utils.h"
|
| +#include "content/public/test/test_navigation_observer.h"
|
| +#include "content/shell/browser/shell.h"
|
| +#include "net/base/escape.h"
|
| +#include "net/base/url_util.h"
|
| +#include "net/dns/mock_host_resolver.h"
|
| +#include "net/test/embedded_test_server/http_request.h"
|
| +#include "net/test/embedded_test_server/http_response.h"
|
| +#include "testing/gmock/include/gmock/gmock.h"
|
| +#include "url/origin.h"
|
| +#include "url/url_constants.h"
|
| +
|
| +using testing::_;
|
| +
|
| +namespace content {
|
| +
|
| +namespace {
|
| +
|
| +class MockContentBrowserClient : public ContentBrowserClient {
|
| + public:
|
| + MOCK_METHOD6(ClearSiteData,
|
| + void(content::BrowserContext* browser_context,
|
| + const url::Origin& origin,
|
| + bool remove_cookies,
|
| + bool remove_storage,
|
| + bool remove_cache,
|
| + const base::Closure& callback));
|
| +};
|
| +
|
| +class TestContentBrowserClient : public MockContentBrowserClient {
|
| + public:
|
| + void ClearSiteData(content::BrowserContext* browser_context,
|
| + const url::Origin& origin,
|
| + bool remove_cookies,
|
| + bool remove_storage,
|
| + bool remove_cache,
|
| + const base::Closure& callback) override {
|
| + // Record the method call and run the |callback|.
|
| + MockContentBrowserClient::ClearSiteData(browser_context, origin,
|
| + remove_cookies, remove_storage,
|
| + remove_cache, callback);
|
| + callback.Run();
|
| + }
|
| +};
|
| +
|
| +// Adds a key=value pair to the url's query.
|
| +void AddQuery(GURL* url, const std::string& key, const std::string& value) {
|
| + *url = GURL(url->spec() + (url->has_query() ? "&" : "?") + key + "=" +
|
| + net::EscapeQueryParamValue(value, false));
|
| +}
|
| +
|
| +// A value of the Clear-Site-Data header that requests cookie deletion. Reused
|
| +// in tests that need a valid header but do not depend on its value.
|
| +static const char* kClearCookiesHeader = "{ \"types\": [ \"cookies\" ] }";
|
| +
|
| +} // namespace
|
| +
|
| +class ClearSiteDataThrottleBrowserTest : public ContentBrowserTest {
|
| + public:
|
| + void SetUpCommandLine(base::CommandLine* command_line) override {
|
| + ContentBrowserTest::SetUpCommandLine(command_line);
|
| + command_line->AppendSwitch(
|
| + switches::kEnableExperimentalWebPlatformFeatures);
|
| +
|
| + // We're redirecting all hosts to localhost even on HTTPS, so we'll get
|
| + // certificate errors.
|
| + command_line->AppendSwitch(switches::kIgnoreCertificateErrors);
|
| + }
|
| +
|
| + void SetUpOnMainThread() override {
|
| + ContentBrowserTest::SetUpOnMainThread();
|
| +
|
| + SetBrowserClientForTesting(&test_client_);
|
| +
|
| + // Set up HTTP and HTTPS test servers that handle all hosts.
|
| + host_resolver()->AddRule("*", "127.0.0.1");
|
| +
|
| + embedded_test_server()->RegisterRequestHandler(
|
| + base::Bind(&ClearSiteDataThrottleBrowserTest::HandleRequest,
|
| + base::Unretained(this)));
|
| + ASSERT_TRUE(embedded_test_server()->Start());
|
| +
|
| + https_server_.reset(new net::EmbeddedTestServer(
|
| + net::test_server::EmbeddedTestServer::TYPE_HTTPS));
|
| + https_server_->SetSSLConfig(net::EmbeddedTestServer::CERT_OK);
|
| + https_server_->RegisterRequestHandler(
|
| + base::Bind(&ClearSiteDataThrottleBrowserTest::HandleRequest,
|
| + base::Unretained(this)));
|
| + ASSERT_TRUE(https_server_->Start());
|
| + }
|
| +
|
| + TestContentBrowserClient* GetContentBrowserClient() { return &test_client_; }
|
| +
|
| + net::EmbeddedTestServer* https_server() { return https_server_.get(); }
|
| +
|
| + private:
|
| + // Handles all requests. If the request url query contains a "header" key,
|
| + // responds with the "Clear-Site-Data" header of the corresponding value.
|
| + // If the query contains a "redirect" key, responds with a redirect to a url
|
| + // given by the corresponding value.
|
| + //
|
| + // Example: "https://localhost/?header={}&redirect=example.com" will respond
|
| + // with headers
|
| + // Clear-Site-Data: {}
|
| + // Location: example.com
|
| + std::unique_ptr<net::test_server::HttpResponse> HandleRequest(
|
| + const net::test_server::HttpRequest& request) {
|
| + std::unique_ptr<net::test_server::BasicHttpResponse> response(
|
| + new net::test_server::BasicHttpResponse());
|
| +
|
| + std::string value;
|
| + if (net::GetValueForKeyInQuery(request.GetURL(), "header", &value))
|
| + response->AddCustomHeader("Clear-Site-Data", value);
|
| +
|
| + if (net::GetValueForKeyInQuery(request.GetURL(), "redirect", &value)) {
|
| + response->set_code(net::HTTP_FOUND);
|
| + response->AddCustomHeader("Location", value);
|
| + } else {
|
| + response->set_code(net::HTTP_OK);
|
| + }
|
| +
|
| + return std::move(response);
|
| + }
|
| +
|
| + TestContentBrowserClient test_client_;
|
| + std::unique_ptr<net::EmbeddedTestServer> https_server_;
|
| +};
|
| +
|
| +// Tests that the header is recognized on the beginning, in the middle, and on
|
| +// the end of a redirect chain. Each of the three parts of the chain may or
|
| +// may not send the header, so there are 8 configurations to test.
|
| +IN_PROC_BROWSER_TEST_F(ClearSiteDataThrottleBrowserTest, Redirect) {
|
| + GURL base_urls[3] = {
|
| + https_server()->GetURL("origin1.com", "/"),
|
| + https_server()->GetURL("origin2.com", "/foo/bar"),
|
| + https_server()->GetURL("origin3.com", "/index.html"),
|
| + };
|
| +
|
| + // Iterate through the configurations. URLs whose index is matched by the mask
|
| + // will send the header, the others won't.
|
| + for (int mask = 0; mask < (1 << 3); ++mask) {
|
| + GURL urls[3];
|
| +
|
| + // Set up the expectations.
|
| + for (int i = 0; i < 3; ++i) {
|
| + urls[i] = base_urls[i];
|
| + if (mask & (1 << i))
|
| + AddQuery(&urls[i], "header", kClearCookiesHeader);
|
| +
|
| + EXPECT_CALL(*GetContentBrowserClient(),
|
| + ClearSiteData(shell()->web_contents()->GetBrowserContext(),
|
| + url::Origin(urls[i]), _, _, _, _))
|
| + .Times((mask & (1 << i)) ? 1 : 0);
|
| + }
|
| +
|
| + // Set up redirects between urls 0 --> 1 --> 2.
|
| + AddQuery(&urls[1], "redirect", urls[2].spec());
|
| + AddQuery(&urls[0], "redirect", urls[1].spec());
|
| +
|
| + // Navigate to the first url of the redirect chain.
|
| + NavigateToURL(shell(), urls[0]);
|
| +
|
| + // We reached the end of the redirect chain.
|
| + EXPECT_EQ(urls[2], shell()->web_contents()->GetURL());
|
| +
|
| + testing::Mock::VerifyAndClearExpectations(GetContentBrowserClient());
|
| + }
|
| +}
|
| +
|
| +// Tests that the Clear-Site-Data header is ignored for insecure origins.
|
| +IN_PROC_BROWSER_TEST_F(ClearSiteDataThrottleBrowserTest, Insecure) {
|
| + // ClearSiteData() should not be called on HTTP.
|
| + GURL url = embedded_test_server()->GetURL("example.com", "/");
|
| + AddQuery(&url, "header", kClearCookiesHeader);
|
| + ASSERT_FALSE(url.SchemeIsCryptographic());
|
| +
|
| + EXPECT_CALL(*GetContentBrowserClient(), ClearSiteData(_, _, _, _, _, _))
|
| + .Times(0);
|
| +
|
| + NavigateToURL(shell(), url);
|
| +}
|
| +
|
| +// Tests that ClearSiteData() is called for the correct datatypes.
|
| +IN_PROC_BROWSER_TEST_F(ClearSiteDataThrottleBrowserTest, Types) {
|
| + GURL base_url = https_server()->GetURL("example.com", "/");
|
| +
|
| + struct TestCase {
|
| + const char* value;
|
| + bool remove_cookies;
|
| + bool remove_storage;
|
| + bool remove_cache;
|
| + } test_cases[] = {
|
| + {"{ \"types\": [ \"cookies\" ] }", true, false, false},
|
| + {"{ \"types\": [ \"storage\" ] }", false, true, false},
|
| + {"{ \"types\": [ \"cache\" ] }", false, false, true},
|
| + {"{ \"types\": [ \"cookies\", \"storage\" ] }", true, true, false},
|
| + {"{ \"types\": [ \"cookies\", \"cache\" ] }", true, false, true},
|
| + {"{ \"types\": [ \"storage\", \"cache\" ] }", false, true, true},
|
| + {"{ \"types\": [ \"cookies\", \"storage\", \"cache\" ] }", true, true,
|
| + true},
|
| + };
|
| +
|
| + for (const TestCase& test_case : test_cases) {
|
| + GURL url = base_url;
|
| + AddQuery(&url, "header", test_case.value);
|
| +
|
| + EXPECT_CALL(
|
| + *GetContentBrowserClient(),
|
| + ClearSiteData(shell()->web_contents()->GetBrowserContext(),
|
| + url::Origin(url), test_case.remove_cookies,
|
| + test_case.remove_storage, test_case.remove_cache, _));
|
| +
|
| + NavigateToURL(shell(), url);
|
| +
|
| + testing::Mock::VerifyAndClearExpectations(GetContentBrowserClient());
|
| + }
|
| +}
|
| +
|
| +} // namespace content
|
|
|