Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(668)

Side by Side Diff: content/browser/browsing_data/clear_site_data_throttle_browsertest.cc

Issue 2025683003: First experimental implementation of the Clear-Site-Data header (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Many changes, most importantly synchronous deletion. Created 4 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2016 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "content/browser/browsing_data/clear_site_data_throttle.h"
6
7 #include <memory>
8
9 #include "base/bind.h"
10 #include "base/callback.h"
11 #include "base/command_line.h"
12 #include "content/public/browser/content_browser_client.h"
13 #include "content/public/browser/web_contents.h"
14 #include "content/public/common/content_switches.h"
15 #include "content/public/test/content_browser_test.h"
16 #include "content/public/test/content_browser_test_utils.h"
17 #include "content/public/test/test_navigation_observer.h"
18 #include "content/shell/browser/shell.h"
19 #include "net/base/escape.h"
20 #include "net/base/url_util.h"
21 #include "net/dns/mock_host_resolver.h"
22 #include "net/test/embedded_test_server/http_request.h"
23 #include "net/test/embedded_test_server/http_response.h"
24 #include "testing/gmock/include/gmock/gmock.h"
25 #include "url/origin.h"
26 #include "url/url_constants.h"
27
28 using testing::_;
29
30 namespace content {
31
32 namespace {
33
34 class MockContentBrowserClient : public ContentBrowserClient {
35 public:
36 MOCK_METHOD6(ClearSiteData,
37 void(content::BrowserContext* browser_context,
38 const url::Origin& origin,
39 bool remove_cookies,
40 bool remove_storage,
41 bool remove_cache,
42 const base::Closure& callback));
43 };
44
45 class TestContentBrowserClient : public MockContentBrowserClient {
46 public:
47 void ClearSiteData(content::BrowserContext* browser_context,
48 const url::Origin& origin,
49 bool remove_cookies,
50 bool remove_storage,
51 bool remove_cache,
52 const base::Closure& callback) override {
53 // Record the method call and run the |callback|.
54 MockContentBrowserClient::ClearSiteData(browser_context, origin,
55 remove_cookies, remove_storage,
56 remove_cache, callback);
57 callback.Run();
58 }
59 };
60
61 // Adds a key=value pair to the url's query.
62 void AddQuery(GURL* url, const std::string& key, const std::string& value) {
63 *url = GURL(url->spec() + (url->has_query() ? "&" : "?") + key + "=" +
64 net::EscapeQueryParamValue(value, false));
65 }
66
67 // A value of the Clear-Site-Data header that requests cookie deletion. Reused
68 // in tests that need a valid header but do not depend on its value.
69 static const char* kClearCookiesHeader = "{ \"types\": [ \"cookies\" ] }";
70
71 } // namespace
72
73 class ClearSiteDataThrottleBrowsertest : public ContentBrowserTest {
nasko 2016/08/11 20:07:22 Capitalize: BrowserTest.
msramek 2016/08/12 15:06:27 Done.
74 public:
75 void SetUpCommandLine(base::CommandLine* command_line) override {
76 ContentBrowserTest::SetUpCommandLine(command_line);
77 command_line->AppendSwitch(
78 switches::kEnableExperimentalWebPlatformFeatures);
79
80 // We're redirecting all hosts to localhost even on HTTPS, so we'll get
81 // certificate errors.
82 command_line->AppendSwitch(switches::kIgnoreCertificateErrors);
83 }
84
85 void SetUpOnMainThread() override {
86 ContentBrowserTest::SetUpOnMainThread();
87
88 SetBrowserClientForTesting(&test_client_);
89
90 // Set up HTTP and HTTPS test servers that handle all hosts.
91 host_resolver()->AddRule("*", "127.0.0.1");
92
93 embedded_test_server()->RegisterRequestHandler(
94 base::Bind(&ClearSiteDataThrottleBrowsertest::HandleRequest,
95 base::Unretained(this)));
96 ASSERT_TRUE(embedded_test_server()->Start());
97
98 https_server_.reset(new net::EmbeddedTestServer(
99 net::test_server::EmbeddedTestServer::TYPE_HTTPS));
100 https_server_->SetSSLConfig(net::EmbeddedTestServer::CERT_OK);
101 https_server_->RegisterRequestHandler(
102 base::Bind(&ClearSiteDataThrottleBrowsertest::HandleRequest,
103 base::Unretained(this)));
104 ASSERT_TRUE(https_server_->Start());
105 }
106
107 TestContentBrowserClient* GetContentBrowserClient() { return &test_client_; }
108
109 net::EmbeddedTestServer* https_server() { return https_server_.get(); }
110
111 private:
112 // Handles all requests. If the request url query contains a "header" key,
113 // responds with the "Clear-Site-Data" header of the corresponding value.
114 // If the query contains a "redirect" key, responds with a redirect to a url
115 // given by the corresponding value.
116 //
117 // Example: "https://localhost/?header={}&redirect=example.com" will respond
118 // with headers
119 // Clear-Site-Data: {}
120 // Location: example.com
121 std::unique_ptr<net::test_server::HttpResponse> HandleRequest(
122 const net::test_server::HttpRequest& request) {
123 std::unique_ptr<net::test_server::BasicHttpResponse> response(
124 new net::test_server::BasicHttpResponse());
125
126 std::string value;
127 if (net::GetValueForKeyInQuery(request.GetURL(), "header", &value))
128 response->AddCustomHeader("Clear-Site-Data", value);
129
130 if (net::GetValueForKeyInQuery(request.GetURL(), "redirect", &value)) {
131 response->set_code(net::HTTP_FOUND);
132 response->AddCustomHeader("Location", value);
133 } else {
134 response->set_code(net::HTTP_OK);
135 }
136
137 return std::move(response);
138 }
139
140 TestContentBrowserClient test_client_;
141 std::unique_ptr<net::EmbeddedTestServer> https_server_;
142 std::map<GURL, std::string> headers_;
nasko 2016/08/11 20:07:22 Unused?
msramek 2016/08/12 15:06:27 Done. Remnants of old design, thanks for catching!
143 std::map<GURL, GURL> redirects_;
nasko 2016/08/11 20:07:22 Unused?
msramek 2016/08/12 15:06:28 Done.
144 };
145
146 // Tests that the header is recognized on the beginning, in the middle, and on
147 // the end of a redirect chain. Each of the three parts of the chain may or
148 // may not send the header, so there are 8 configurations to test.
149 IN_PROC_BROWSER_TEST_F(ClearSiteDataThrottleBrowsertest, Redirect) {
150 GURL base_urls[3] = {
151 https_server()->GetURL("origin1.com", "/"),
152 https_server()->GetURL("origin2.com", "/foo/bar"),
153 https_server()->GetURL("origin3.com", "/index.html"),
154 };
155
156 // Iterate through the configurations. URLs whose index is matched by the mask
157 // will send the header, the others won't.
158 for (int mask = 0; mask < (1 << 3); ++mask) {
nasko 2016/08/11 20:07:22 Why use "(1 << 3)" instead of the actual constant?
msramek 2016/08/12 15:06:27 I think this is a bit better semantically. As in,
159 GURL urls[3];
160
161 // Set up the expectations.
162 for (int i = 0; i < 3; ++i) {
163 urls[i] = base_urls[i];
164 if (mask & (1 << i))
165 AddQuery(&urls[i], "header", kClearCookiesHeader);
166
167 EXPECT_CALL(*GetContentBrowserClient(),
168 ClearSiteData(shell()->web_contents()->GetBrowserContext(),
169 url::Origin(urls[i]), _, _, _, _))
170 .Times((mask & (1 << i)) ? 1 : 0);
171 }
172
173 // Set up redirects between urls 0 --> 1 --> 2.
174 AddQuery(&urls[1], "redirect", urls[2].spec());
175 AddQuery(&urls[0], "redirect", urls[1].spec());
176
177 // Navigate to the first url of the redirect chain.
178 NavigateToURL(shell(), urls[0]);
179
180 // We reached the end of the redirect chain.
181 EXPECT_EQ(urls[2], shell()->web_contents()->GetURL());
182
183 testing::Mock::VerifyAndClearExpectations(GetContentBrowserClient());
184 }
185 }
186
187 // Tests that the Clear-Site-Data header is ignored for insecure origins.
188 IN_PROC_BROWSER_TEST_F(ClearSiteDataThrottleBrowsertest, Insecure) {
189 // ClearSiteData() should not be called on HTTP.
190 GURL url = embedded_test_server()->GetURL("example.com", "/");
191 AddQuery(&url, "header", kClearCookiesHeader);
192 ASSERT_FALSE(url.SchemeIsCryptographic());
193
194 EXPECT_CALL(*GetContentBrowserClient(), ClearSiteData(_, _, _, _, _, _))
195 .Times(0);
196
197 NavigateToURL(shell(), url);
198 }
199
200 // Tests that ClearSiteData() is called for the correct datatypes.
201 IN_PROC_BROWSER_TEST_F(ClearSiteDataThrottleBrowsertest, Types) {
202 GURL base_url = https_server()->GetURL("example.com", "/");
203
204 struct TestCase {
205 const char* value;
206 bool remove_cookies;
207 bool remove_storage;
208 bool remove_cache;
209 } test_cases[] = {
210 {"{ \"types\": [ \"cookies\" ] }", true, false, false},
211 {"{ \"types\": [ \"storage\" ] }", false, true, false},
212 {"{ \"types\": [ \"cache\" ] }", false, false, true},
213 {"{ \"types\": [ \"cookies\", \"storage\" ] }", true, true, false},
214 {"{ \"types\": [ \"cookies\", \"cache\" ] }", true, false, true},
215 {"{ \"types\": [ \"storage\", \"cache\" ] }", false, true, true},
216 {"{ \"types\": [ \"cookies\", \"storage\", \"cache\" ] }", true, true,
217 true},
218 };
219
220 for (const TestCase& test_case : test_cases) {
221 GURL url = base_url;
222 AddQuery(&url, "header", test_case.value);
223
224 EXPECT_CALL(
225 *GetContentBrowserClient(),
226 ClearSiteData(shell()->web_contents()->GetBrowserContext(),
227 url::Origin(url), test_case.remove_cookies,
228 test_case.remove_storage, test_case.remove_cache, _));
229
230 NavigateToURL(shell(), url);
231
232 testing::Mock::VerifyAndClearExpectations(GetContentBrowserClient());
233 }
234 }
235
236 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698