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

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

Issue 2368923003: Support the Clear-Site-Data header on resource requests (Closed)
Patch Set: Created 4 years, 2 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
1 // Copyright 2016 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "content/browser/browsing_data/clear_site_data_throttle.h" 5 #include "content/browser/browsing_data/clear_site_data_throttle.h"
6 6
7 #include <memory> 7 #include <memory>
8 8
9 #include "base/bind.h" 9 #include "base/bind.h"
10 #include "base/callback.h" 10 #include "base/callback.h"
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after
105 } 105 }
106 106
107 TestContentBrowserClient* GetContentBrowserClient() { return &test_client_; } 107 TestContentBrowserClient* GetContentBrowserClient() { return &test_client_; }
108 108
109 net::EmbeddedTestServer* https_server() { return https_server_.get(); } 109 net::EmbeddedTestServer* https_server() { return https_server_.get(); }
110 110
111 private: 111 private:
112 // Handles all requests. If the request url query contains a "header" key, 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. 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 114 // If the query contains a "redirect" key, responds with a redirect to a url
115 // given by the corresponding value. 115 // given by the corresponding value. If the query contains a "html" key,
116 // the response will contain a text/html content given by the corresponding
117 // value. If the query contains a "file" key, it will instead serve content
118 // from a file with the corresponding
116 // 119 //
117 // Example: "https://localhost/?header={}&redirect=example.com" will respond 120 // Example: "https://localhost/?header={}&redirect=example.com" will respond
118 // with headers 121 // with headers
119 // Clear-Site-Data: {} 122 // Clear-Site-Data: {}
120 // Location: example.com 123 // Location: example.com
124 //
125 // Example: "https://localhost/?html=<html><head></head><body></body></html>"
126 // will respond with the header
127 // Content-Type: text/html
128 // and content
129 // <html><head></head><body></body></html>
130 //
131 // Example: "https://localhost/?file=file.html
132 // will respond with the header
133 // Content-Type: text/html
134 // and content from the file content/test/data/file.html
121 std::unique_ptr<net::test_server::HttpResponse> HandleRequest( 135 std::unique_ptr<net::test_server::HttpResponse> HandleRequest(
122 const net::test_server::HttpRequest& request) { 136 const net::test_server::HttpRequest& request) {
123 std::unique_ptr<net::test_server::BasicHttpResponse> response( 137 std::unique_ptr<net::test_server::BasicHttpResponse> response(
124 new net::test_server::BasicHttpResponse()); 138 new net::test_server::BasicHttpResponse());
125 139
126 std::string value; 140 std::string value;
127 if (net::GetValueForKeyInQuery(request.GetURL(), "header", &value)) 141 if (net::GetValueForKeyInQuery(request.GetURL(), "header", &value))
128 response->AddCustomHeader("Clear-Site-Data", value); 142 response->AddCustomHeader("Clear-Site-Data", value);
129 143
130 if (net::GetValueForKeyInQuery(request.GetURL(), "redirect", &value)) { 144 if (net::GetValueForKeyInQuery(request.GetURL(), "redirect", &value)) {
131 response->set_code(net::HTTP_FOUND); 145 response->set_code(net::HTTP_FOUND);
132 response->AddCustomHeader("Location", value); 146 response->AddCustomHeader("Location", value);
133 } else { 147 } else {
134 response->set_code(net::HTTP_OK); 148 response->set_code(net::HTTP_OK);
135 } 149 }
136 150
151 if (net::GetValueForKeyInQuery(request.GetURL(), "html", &value)) {
152 response->set_content_type("text/html");
153 response->set_content(value);
154 }
155
156 if (net::GetValueForKeyInQuery(request.GetURL(), "file", &value)) {
157 base::FilePath path(GetTestFilePath("browsing_data", value.c_str()));
158 base::File file(path, base::File::FLAG_OPEN | base::File::FLAG_READ);
159 EXPECT_TRUE(file.IsValid());
160 int64_t length = file.GetLength();
161 EXPECT_GE(length, 0);
162 std::unique_ptr<char[]> buffer(new char[length + 1]);
163 file.Read(0, buffer.get(), length);
164 buffer[length] = '\0';
165
166 if (path.Extension() == ".js")
167 response->set_content_type("application/javascript");
168 else if (path.Extension() == ".html")
169 response->set_content_type("text/html");
170 else
171 NOTREACHED();
172
173 response->set_content(buffer.get());
174 }
175
137 return std::move(response); 176 return std::move(response);
138 } 177 }
139 178
140 TestContentBrowserClient test_client_; 179 TestContentBrowserClient test_client_;
141 std::unique_ptr<net::EmbeddedTestServer> https_server_; 180 std::unique_ptr<net::EmbeddedTestServer> https_server_;
142 }; 181 };
143 182
144 // Tests that the header is recognized on the beginning, in the middle, and on 183 // Tests that the header is recognized on the beginning, in the middle, and on
145 // the end of a redirect chain. Each of the three parts of the chain may or 184 // the end of a navigation redirect chain. Each of the three parts of the chain
146 // may not send the header, so there are 8 configurations to test. 185 // may or may not send the header, so there are 8 configurations to test.
147 IN_PROC_BROWSER_TEST_F(ClearSiteDataThrottleBrowserTest, Redirect) { 186 IN_PROC_BROWSER_TEST_F(ClearSiteDataThrottleBrowserTest, RedirectNavigation) {
148 GURL base_urls[3] = { 187 GURL base_urls[3] = {
149 https_server()->GetURL("origin1.com", "/"), 188 https_server()->GetURL("origin1.com", "/"),
150 https_server()->GetURL("origin2.com", "/foo/bar"), 189 https_server()->GetURL("origin2.com", "/foo/bar"),
151 https_server()->GetURL("origin3.com", "/index.html"), 190 https_server()->GetURL("origin3.com", "/index.html"),
152 }; 191 };
153 192
154 // Iterate through the configurations. URLs whose index is matched by the mask 193 // Iterate through the configurations. URLs whose index is matched by the mask
155 // will send the header, the others won't. 194 // will send the header, the others won't.
156 for (int mask = 0; mask < (1 << 3); ++mask) { 195 for (int mask = 0; mask < (1 << 3); ++mask) {
157 GURL urls[3]; 196 GURL urls[3];
(...skipping 17 matching lines...) Expand all
175 // Navigate to the first url of the redirect chain. 214 // Navigate to the first url of the redirect chain.
176 NavigateToURL(shell(), urls[0]); 215 NavigateToURL(shell(), urls[0]);
177 216
178 // We reached the end of the redirect chain. 217 // We reached the end of the redirect chain.
179 EXPECT_EQ(urls[2], shell()->web_contents()->GetURL()); 218 EXPECT_EQ(urls[2], shell()->web_contents()->GetURL());
180 219
181 testing::Mock::VerifyAndClearExpectations(GetContentBrowserClient()); 220 testing::Mock::VerifyAndClearExpectations(GetContentBrowserClient());
182 } 221 }
183 } 222 }
184 223
224 // Tests that the header is recognized on the beginning, in the middle, and on
225 // the end of a resource load redirect chain. Each of the three parts of the
226 // chain may or may not send the header, so there are 8 configurations to test.
227 IN_PROC_BROWSER_TEST_F(ClearSiteDataThrottleBrowserTest, RedirectResourceLoad) {
228 GURL base_urls[3] = {
229 https_server()->GetURL("origin1.com", "/image.png"),
230 https_server()->GetURL("origin2.com", "/redirected-image.png"),
231 https_server()->GetURL("origin3.com", "/actual-image.png"),
232 };
233
234 // Iterate through the configurations. URLs whose index is matched by the mask
235 // will send the header, the others won't.
236 for (int mask = 0; mask < (1 << 3); ++mask) {
237 GURL urls[3];
238
239 // Set up the expectations.
240 for (int i = 0; i < 3; ++i) {
241 urls[i] = base_urls[i];
242 if (mask & (1 << i))
243 AddQuery(&urls[i], "header", kClearCookiesHeader);
244
245 EXPECT_CALL(*GetContentBrowserClient(),
246 ClearSiteData(shell()->web_contents()->GetBrowserContext(),
247 url::Origin(urls[i]), _, _, _, _))
248 .Times((mask & (1 << i)) ? 1 : 0);
249 }
250
251 // Set up redirects between urls 0 --> 1 --> 2.
252 AddQuery(&urls[1], "redirect", urls[2].spec());
253 AddQuery(&urls[0], "redirect", urls[1].spec());
254
255 // Navigate to a page that embeds "https://origin1.com/image.png"
256 // and observe the loading of that resource.
257 GURL page_with_image = https_server()->GetURL("origin4.com", "/index.html");
258 std::string content_with_image =
259 "<html><head></head><body>"
260 "<img src=\"" +
261 urls[0].spec() +
262 "\" />"
263 "</body></html>";
264 AddQuery(&page_with_image, "html", content_with_image);
265 NavigateToURL(shell(), page_with_image);
266
267 testing::Mock::VerifyAndClearExpectations(GetContentBrowserClient());
268 }
269 }
270
185 // Tests that the Clear-Site-Data header is ignored for insecure origins. 271 // Tests that the Clear-Site-Data header is ignored for insecure origins.
186 IN_PROC_BROWSER_TEST_F(ClearSiteDataThrottleBrowserTest, Insecure) { 272 IN_PROC_BROWSER_TEST_F(ClearSiteDataThrottleBrowserTest, InsecureNavigation) {
187 // ClearSiteData() should not be called on HTTP. 273 // ClearSiteData() should not be called on HTTP.
188 GURL url = embedded_test_server()->GetURL("example.com", "/"); 274 GURL url = embedded_test_server()->GetURL("example.com", "/");
189 AddQuery(&url, "header", kClearCookiesHeader); 275 AddQuery(&url, "header", kClearCookiesHeader);
190 ASSERT_FALSE(url.SchemeIsCryptographic()); 276 ASSERT_FALSE(url.SchemeIsCryptographic());
191 277
192 EXPECT_CALL(*GetContentBrowserClient(), ClearSiteData(_, _, _, _, _, _)) 278 EXPECT_CALL(*GetContentBrowserClient(), ClearSiteData(_, _, _, _, _, _))
193 .Times(0); 279 .Times(0);
194 280
195 NavigateToURL(shell(), url); 281 NavigateToURL(shell(), url);
196 } 282 }
197 283
284 // Tests that the Clear-Site-Data header is honored for secure resource loads
285 // and ignored for insecure ones.
286 IN_PROC_BROWSER_TEST_F(ClearSiteDataThrottleBrowserTest,
287 SecureAndInsecureResourceLoad) {
288 EXPECT_CALL(*GetContentBrowserClient(), ClearSiteData(_, _, _, _, _, _))
msramek 2016/10/13 14:26:03 Removing this as it's duplicated below.
289 .Times(0);
290
291 GURL insecure_image =
292 embedded_test_server()->GetURL("example.com", "/image.png");
293 GURL secure_image = https_server()->GetURL("example.com", "/image.png");
294
295 ASSERT_TRUE(secure_image.SchemeIsCryptographic());
296 ASSERT_FALSE(insecure_image.SchemeIsCryptographic());
297
298 AddQuery(&secure_image, "header", kClearCookiesHeader);
299 AddQuery(&insecure_image, "header", kClearCookiesHeader);
300
301 std::string content_with_insecure_image =
302 "<html><head></head><body>"
303 "<img src=\"" +
304 insecure_image.spec() +
305 "\" />"
306 "</body></html>";
307
308 std::string content_with_secure_image =
309 "<html><head></head><body>"
310 "<img src=\"" +
311 secure_image.spec() +
312 "\" />"
313 "</body></html>";
314
315 // Test insecure resources.
316 GURL insecure_page = embedded_test_server()->GetURL("example.com", "/");
317 GURL secure_page = https_server()->GetURL("example.com", "/");
318
319 AddQuery(&insecure_page, "html", content_with_insecure_image);
320 AddQuery(&secure_page, "html", content_with_insecure_image);
321
322 EXPECT_CALL(*GetContentBrowserClient(), ClearSiteData(_, _, _, _, _, _))
323 .Times(0);
324
325 // Insecure resource on an insecure page does not execute Clear-Site-Data.
326 NavigateToURL(shell(), insecure_page);
327
328 // Insecure resource on a secure page does not execute Clear-Site-Data.
329 NavigateToURL(shell(), secure_page);
330
331 testing::Mock::VerifyAndClearExpectations(GetContentBrowserClient());
332
333 // Test secure resources.
334 insecure_page = embedded_test_server()->GetURL("example.com", "/");
335 secure_page = https_server()->GetURL("example.com", "/");
336
337 AddQuery(&insecure_page, "html", content_with_secure_image);
338 AddQuery(&secure_page, "html", content_with_secure_image);
339
340 // Secure resource on an insecure page does execute Clear-Site-Data.
341 EXPECT_CALL(*GetContentBrowserClient(), ClearSiteData(_, _, _, _, _, _))
342 .Times(1);
343
344 NavigateToURL(shell(), secure_page);
345 testing::Mock::VerifyAndClearExpectations(GetContentBrowserClient());
346
347 // Secure resource on a secure page does execute Clear-Site-Data.
348 EXPECT_CALL(*GetContentBrowserClient(), ClearSiteData(_, _, _, _, _, _))
349 .Times(1);
350
351 NavigateToURL(shell(), secure_page);
352 }
353
354 // Tests that the Clear-Site-Data header is ignored for service worker resource
355 // loads. Specifically, we test it on a cross-origin request; the header is
356 // ignored for same-origin requests as well, but there it isn't harmful.
357 IN_PROC_BROWSER_TEST_F(ClearSiteDataThrottleBrowserTest,
358 DISABLED_ServiceWorker) {
359 GURL origin1 = https_server()->GetURL("origin1.com", "/");
360 GURL origin2 = https_server()->GetURL("origin2.com", "/");
361
362 // We will load |origin1| and make cross-origin requests for |origin2| from
363 // there. We need to inform the JS side about |origin2| using a query
364 // parameter; it cannot be hardcoded in the JS code, as the port number
365 // of the test server is chosen randomly.
mmenke 2016/09/26 12:59:17 The service worker should redirect requests to |or
msramek 2016/10/13 14:26:03 The first part of the test makes a fetch from |ori
366 GURL url = origin1;
367 AddQuery(&url, "file", "worker_setup.html");
368 AddQuery(&url, "other_origin", origin2.spec());
369
370 // Navigation to worker_setup.html will first request a resource with the
371 // Clear-Site-Data header. This is done for control - to make sure that
372 // the second part of this test will ignore the header because it's processed
373 // by a service worker, and not because the test is set up incorrectly.
374 EXPECT_CALL(*GetContentBrowserClient(), ClearSiteData(_, _, _, _, _, _))
375 .Times(1);
376 NavigateToURL(shell(), url);
377
378 // After the resource was fetched, a service worker should have been
379 // installed and the page reloaded. The service worker will now serve a page
380 // containing an image, and fetching that image will again return the
381 // Clear-Site-Data header. This time, it should be ignored.
382 //
383 // Since the installation of a service worker is asynchronous, the JS side
384 // will inform us about it in its URL hash.
385 // TODO(msramek): Find a solution without polling.
386 while (true) {
387 if (shell()->web_contents()->GetLastCommittedURL().ref_piece() ==
388 "service-worker-registered") {
389 break;
390 }
391
392 base::RunLoop run_loop;
393 run_loop.RunUntilIdle();
394 }
395 testing::Mock::VerifyAndClearExpectations(GetContentBrowserClient());
396
397 // The service worker should be now installed. Stop the server so that we
398 // lose connectivity and the service worker can handle requests.
399 ASSERT_TRUE(https_server()->ShutdownAndWaitUntilComplete());
400
401 EXPECT_CALL(*GetContentBrowserClient(), ClearSiteData(_, _, _, _, _, _))
402 .Times(0);
403
404 NavigateToURL(shell(), origin1);
405 while (true) {
406 if (shell()->web_contents()->GetVisibleURL().ref_piece() ==
407 "service-worker-active") {
408 break;
409 }
410
411 base::RunLoop run_loop;
412 run_loop.RunUntilIdle();
413 }
414 }
415
mmenke 2016/09/27 18:24:02 Should also check CORS and non-CORS cross-site res
msramek 2016/10/13 14:26:03 I chatted with mkwst@ about this as well. While A
198 // Tests that ClearSiteData() is called for the correct datatypes. 416 // Tests that ClearSiteData() is called for the correct datatypes.
199 IN_PROC_BROWSER_TEST_F(ClearSiteDataThrottleBrowserTest, Types) { 417 IN_PROC_BROWSER_TEST_F(ClearSiteDataThrottleBrowserTest, Types) {
200 GURL base_url = https_server()->GetURL("example.com", "/"); 418 GURL base_url = https_server()->GetURL("example.com", "/");
201 419
202 struct TestCase { 420 struct TestCase {
203 const char* value; 421 const char* value;
204 bool remove_cookies; 422 bool remove_cookies;
205 bool remove_storage; 423 bool remove_storage;
206 bool remove_cache; 424 bool remove_cache;
207 } test_cases[] = { 425 } test_cases[] = {
(...skipping 17 matching lines...) Expand all
225 url::Origin(url), test_case.remove_cookies, 443 url::Origin(url), test_case.remove_cookies,
226 test_case.remove_storage, test_case.remove_cache, _)); 444 test_case.remove_storage, test_case.remove_cache, _));
227 445
228 NavigateToURL(shell(), url); 446 NavigateToURL(shell(), url);
229 447
230 testing::Mock::VerifyAndClearExpectations(GetContentBrowserClient()); 448 testing::Mock::VerifyAndClearExpectations(GetContentBrowserClient());
231 } 449 }
232 } 450 }
233 451
234 } // namespace content 452 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698