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..6256327b95620f65bf0bcba8ece0fa37da9d1285 |
--- /dev/null |
+++ b/content/browser/browsing_data/clear_site_data_throttle_browsertest.cc |
@@ -0,0 +1,256 @@ |
+// 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/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 TestContentBrowserClient : public ContentBrowserClient { |
+ public: |
+ MOCK_METHOD5(ClearSiteData, void( |
+ content::BrowserContext* browser_context, const url::Origin& origin, |
+ bool remove_cookies, bool remove_storage, bool remove_cache)); |
+}; |
+ |
+} // namespace |
+ |
+ |
+class ClearSiteDataThrottleBrowsertest : public ContentBrowserTest { |
+ public: |
+ void SetUpCommandLine(base::CommandLine* command_line) override { |
+ command_line->AppendSwitch( |
+ switches::kEnableExperimentalWebPlatformFeatures); |
+ } |
+ |
+ void SetUpOnMainThread() override { |
+ SetBrowserClientForTesting(&test_client_); |
+ |
+ // Header to be served by default. |
+ SetHeaderValue("{ \"types\": [ \"cookies\" ] }"); |
+ |
+ // Run three HTTPS servers, each serving 127.0.0.1 on a different port. |
Mike West
2016/06/20 07:57:38
Please add some tests that test the registrable do
msramek
2016/07/15 16:47:39
Done.
I was originally avoiding host_resolver(),
|
+ origin1_server_.reset(new net::EmbeddedTestServer( |
+ net::test_server::EmbeddedTestServer::TYPE_HTTPS)); |
+ origin1_server_->RegisterRequestHandler( |
+ base::Bind(&ClearSiteDataThrottleBrowsertest::HandleRequestForOrigin1, |
+ base::Unretained(this))); |
+ |
+ origin2_server_.reset(new net::EmbeddedTestServer( |
+ net::test_server::EmbeddedTestServer::TYPE_HTTPS)); |
+ origin2_server_->RegisterRequestHandler( |
+ base::Bind(&ClearSiteDataThrottleBrowsertest::HandleRequestForOrigin2, |
+ base::Unretained(this))); |
+ |
+ origin3_server_.reset(new net::EmbeddedTestServer( |
+ net::test_server::EmbeddedTestServer::TYPE_HTTPS)); |
+ origin3_server_->RegisterRequestHandler( |
+ base::Bind(&ClearSiteDataThrottleBrowsertest::HandleRequestForOrigin3, |
+ base::Unretained(this))); |
+ |
+ ASSERT_TRUE(origin1_server_->Start()); |
+ ASSERT_TRUE(origin2_server_->Start()); |
+ ASSERT_TRUE(origin3_server_->Start()); |
+ } |
+ |
+ // Getters for the testing server origins, i.e. http(s)://127.0.0.1:<port>. |
+ GURL origin1() { return origin1_server_->base_url(); } |
+ GURL origin2() { return origin2_server_->base_url(); } |
+ GURL origin3() { return origin3_server_->base_url(); } |
+ |
+ // Defines which of the three origins should send the Clear-Site-Data header. |
+ // This is used for testing of the redirect chain where either the start, |
+ // middle, or end of the chain sends the header. |
Mike West
2016/06/20 07:57:38
What about when two (or all three) send the header
msramek
2016/07/15 16:47:39
Added tests for that.
I'll implement the serializ
|
+ void SetOriginThatShouldSendClearSiteData(const GURL& origin) { |
+ origin_that_should_send_clear_site_data_ = origin; |
+ } |
+ |
+ // Finds out which of the three server origins should send Clear-Site-Data. |
+ GURL OriginThatShouldSendClearSiteData() { |
+ return origin_that_should_send_clear_site_data_; |
+ } |
+ |
+ // Sets the desired Clear-Site-Data header value to be sent by the servers. |
+ void SetHeaderValue(const std::string& value) { |
+ header_value_ = value; |
+ } |
+ |
+ TestContentBrowserClient* GetContentBrowserClient() { |
+ return &test_client_; |
+ } |
+ |
+ // Navigates over the redirect chain origin1()->origin2()->origin3(), sending |
+ // the Clear-Site-Data header on |origin_to_test|. |
+ void TestRedirectChainWithHeaderOn(const GURL& origin_to_test) { |
+ SCOPED_TRACE( |
+ "ClearSiteData() should have been called for " + origin_to_test.spec()); |
+ SetOriginThatShouldSendClearSiteData(origin_to_test); |
+ |
+ // The |tested_origin| is expected to call ClearSiteData(). The other two |
+ // origins are not expected to call it. |
+ const GURL origins[] = {origin1(), origin2(), origin3()}; |
+ for (const GURL& origin : origins) { |
+ EXPECT_CALL( |
+ *GetContentBrowserClient(), |
+ ClearSiteData( |
+ shell()->web_contents()->GetBrowserContext(), |
+ url::Origin(origin), |
+ _, _, _)).Times(origin == origin_to_test ? 1 : 0); |
+ } |
+ |
+ // Navigate to the first origin of the redirect chain. |
+ TestNavigationObserver observer(shell()->web_contents()); |
+ NavigateToURL(shell(), origin1()); |
+ observer.Wait(); |
+ |
+ // We reached the end of the redirect chain. |
+ EXPECT_EQ(origin3(), shell()->web_contents()->GetURL()); |
+ } |
+ |
+ private: |
+ // Requests to origin1() always redirect to origin2(). |
+ std::unique_ptr<net::test_server::HttpResponse> HandleRequestForOrigin1( |
+ const net::test_server::HttpRequest& request) { |
+ std::unique_ptr<net::test_server::BasicHttpResponse> response( |
+ new net::test_server::BasicHttpResponse()); |
+ response->set_code(net::HTTP_FOUND); |
+ response->AddCustomHeader( |
+ "Location", origin2_server_->base_url().spec()); |
+ |
+ if (origin1() == OriginThatShouldSendClearSiteData()) { |
+ response->AddCustomHeader("Clear-Site-Data", header_value_); |
+ } |
+ |
+ return std::move(response); |
+ } |
+ |
+ // Requests to origin2() always redirect to origin3(). |
+ std::unique_ptr<net::test_server::HttpResponse> HandleRequestForOrigin2( |
+ const net::test_server::HttpRequest& request) { |
+ std::unique_ptr<net::test_server::BasicHttpResponse> response( |
+ new net::test_server::BasicHttpResponse()); |
+ response->set_code(net::HTTP_FOUND); |
+ response->AddCustomHeader( |
+ "Location", origin3_server_->base_url().spec()); |
+ |
+ if (origin2() == OriginThatShouldSendClearSiteData()) |
+ response->AddCustomHeader("Clear-Site-Data", header_value_); |
+ |
+ return std::move(response); |
+ } |
+ |
+ // Requests to origin3() always successfully return an empty content. |
+ std::unique_ptr<net::test_server::HttpResponse> HandleRequestForOrigin3( |
+ const net::test_server::HttpRequest& request) { |
+ std::unique_ptr<net::test_server::BasicHttpResponse> response( |
+ new net::test_server::BasicHttpResponse()); |
+ response->set_code(net::HTTP_OK); |
+ |
+ if (origin3() == OriginThatShouldSendClearSiteData()) |
+ response->AddCustomHeader("Clear-Site-Data", header_value_); |
+ |
+ return std::move(response); |
+ } |
+ |
+ TestContentBrowserClient test_client_; |
+ std::unique_ptr<net::EmbeddedTestServer> origin1_server_; |
+ std::unique_ptr<net::EmbeddedTestServer> origin2_server_; |
+ std::unique_ptr<net::EmbeddedTestServer> origin3_server_; |
+ GURL origin_that_should_send_clear_site_data_; |
+ std::string header_value_; |
+}; |
+ |
+IN_PROC_BROWSER_TEST_F(ClearSiteDataThrottleBrowsertest, RedirectStart) { |
+ TestRedirectChainWithHeaderOn(origin1()); |
+} |
+ |
+IN_PROC_BROWSER_TEST_F(ClearSiteDataThrottleBrowsertest, RedirectMiddle) { |
+ TestRedirectChainWithHeaderOn(origin2()); |
+} |
+ |
+IN_PROC_BROWSER_TEST_F(ClearSiteDataThrottleBrowsertest, RedirectEnd) { |
+ TestRedirectChainWithHeaderOn(origin3()); |
+} |
+ |
+// Tests that the Clear-Site-Data header is ignored for insecure origins. |
+IN_PROC_BROWSER_TEST_F(ClearSiteDataThrottleBrowsertest, Insecure) { |
+ // ClearSiteData() should not be called for origin3() ... |
+ SetOriginThatShouldSendClearSiteData(origin3()); |
+ EXPECT_CALL( |
+ *GetContentBrowserClient(), ClearSiteData(_, _, _, _, _)).Times(0); |
+ |
+ // ... when we navigate to it on HTTP instead of HTTPS. |
+ GURL::Replacements replace_scheme; |
+ std::string new_scheme = url::kHttpScheme; |
+ replace_scheme.SetSchemeStr(new_scheme); |
+ GURL origin3_on_http = origin3().ReplaceComponents(replace_scheme); |
+ ASSERT_TRUE(origin3_on_http.is_valid()); |
+ ASSERT_TRUE(!origin3_on_http.SchemeIsCryptographic()); |
+ |
+ TestNavigationObserver observer(shell()->web_contents()); |
+ NavigateToURL(shell(), origin3_on_http); |
+ observer.Wait(); |
+} |
+ |
+// Tests that ClearSiteData() is called for the correct datatypes. |
+IN_PROC_BROWSER_TEST_F(ClearSiteDataThrottleBrowsertest, Types) { |
+ SetOriginThatShouldSendClearSiteData(origin3()); |
+ |
+ 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) { |
+ SetHeaderValue(test_case.value); |
+ |
+ EXPECT_CALL( |
+ *GetContentBrowserClient(), |
+ ClearSiteData( |
+ shell()->web_contents()->GetBrowserContext(), |
+ url::Origin(origin3()), |
+ test_case.remove_cookies, |
+ test_case.remove_storage, |
+ test_case.remove_cache)); |
+ |
+ TestNavigationObserver observer(shell()->web_contents()); |
+ NavigateToURL(shell(), origin3()); |
+ observer.Wait(); |
+ } |
+} |
+ |
+} // namespace content |