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

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

Issue 2929593002: Align `clear-site-data` syntax with the spec. (Closed)
Patch Set: Created 3 years, 6 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/memory/ptr_util.h" 9 #include "base/memory/ptr_util.h"
10 #include "base/memory/ref_counted.h" 10 #include "base/memory/ref_counted.h"
(...skipping 15 matching lines...) Expand all
26 using ::testing::_; 26 using ::testing::_;
27 27
28 namespace content { 28 namespace content {
29 29
30 using ConsoleMessagesDelegate = ClearSiteDataThrottle::ConsoleMessagesDelegate; 30 using ConsoleMessagesDelegate = ClearSiteDataThrottle::ConsoleMessagesDelegate;
31 31
32 namespace { 32 namespace {
33 33
34 const char kClearSiteDataHeaderPrefix[] = "Clear-Site-Data: "; 34 const char kClearSiteDataHeaderPrefix[] = "Clear-Site-Data: ";
35 35
36 const char kClearCookiesHeader[] = 36 const char kClearCookiesHeader[] = "Clear-Site-Data: \"cookies\"";
37 "Clear-Site-Data: { \"types\": [ \"cookies\" ] }";
38 37
39 void WaitForUIThread() { 38 void WaitForUIThread() {
40 base::RunLoop run_loop; 39 base::RunLoop run_loop;
41 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, run_loop.QuitClosure()); 40 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, run_loop.QuitClosure());
42 run_loop.Run(); 41 run_loop.Run();
43 } 42 }
44 43
45 // Used to verify that resource throttle delegate calls are made. 44 // Used to verify that resource throttle delegate calls are made.
46 class MockResourceThrottleDelegate : public ResourceThrottle::Delegate { 45 class MockResourceThrottleDelegate : public ResourceThrottle::Delegate {
47 public: 46 public:
(...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after
167 } 166 }
168 167
169 TEST_F(ClearSiteDataThrottleTest, ParseHeaderAndExecuteClearingTask) { 168 TEST_F(ClearSiteDataThrottleTest, ParseHeaderAndExecuteClearingTask) {
170 struct TestCase { 169 struct TestCase {
171 const char* header; 170 const char* header;
172 bool cookies; 171 bool cookies;
173 bool storage; 172 bool storage;
174 bool cache; 173 bool cache;
175 } test_cases[] = { 174 } test_cases[] = {
176 // One data type. 175 // One data type.
177 {"{ \"types\": [\"cookies\"] }", true, false, false}, 176 {"\"cookies\"", true, false, false},
178 {"{ \"types\": [\"storage\"] }", false, true, false}, 177 {"\"storage\"", false, true, false},
179 {"{ \"types\": [\"cache\"] }", false, false, true}, 178 {"\"cache\"", false, false, true},
180 179
181 // Two data types. 180 // Two data types.
182 {"{ \"types\": [\"cookies\", \"storage\"] }", true, true, false}, 181 {"\"cookies\", \"storage\"", true, true, false},
183 {"{ \"types\": [\"cookies\", \"cache\"] }", true, false, true}, 182 {"\"cookies\", \"cache\"", true, false, true},
184 {"{ \"types\": [\"storage\", \"cache\"] }", false, true, true}, 183 {"\"storage\", \"cache\"", false, true, true},
185 184
186 // Three data types. 185 // Three data types.
187 {"{ \"types\": [\"storage\", \"cache\", \"cookies\"] }", true, true, 186 {"\"storage\", \"cache\", \"cookies\"", true, true, true},
188 true}, 187 {"\"cache\", \"cookies\", \"storage\"", true, true, true},
189 {"{ \"types\": [\"cache\", \"cookies\", \"storage\"] }", true, true, 188 {"\"cookies\", \"storage\", \"cache\"", true, true, true},
190 true},
191 {"{ \"types\": [\"cookies\", \"storage\", \"cache\"] }", true, true,
192 true},
193 189
194 // Different formatting. 190 // Different formatting.
195 {" { \"types\": [\"cookies\" ]}", true, false, false}, 191 {"\"cookies\"", true, false, false},
196 192
197 // Duplicates. 193 // Duplicates.
198 {"{ \"types\": [\"cookies\", \"cookies\"] }", true, false, false}, 194 {"\"cookies\", \"cookies\"", true, false, false},
199 195
200 // Other entries in the dictionary. 196 // Other JSON-formatted items in the list.
201 {"{ \"types\": [\"storage\"], \"other_params\": {} }", false, true, 197 {"\"storage\", { \"other_params\": {} }", false, true, false},
202 false},
203 198
204 // Unknown types are ignored, but we still proceed with the deletion for 199 // Unknown types are ignored, but we still proceed with the deletion for
205 // those that we recognize. 200 // those that we recognize.
206 {"{ \"types\": [\"cache\", \"foo\"] }", false, false, true}, 201 {"\"cache\", \"foo\"", false, false, true},
207 }; 202 };
208 203
209 for (const TestCase& test_case : test_cases) { 204 for (const TestCase& test_case : test_cases) {
210 SCOPED_TRACE(test_case.header); 205 SCOPED_TRACE(test_case.header);
211 206
212 // Test that ParseHeader works correctly. 207 // Test that ParseHeader works correctly.
213 bool actual_cookies; 208 bool actual_cookies;
214 bool actual_storage; 209 bool actual_storage;
215 bool actual_cache; 210 bool actual_cache;
216 211
(...skipping 28 matching lines...) Expand all
245 240
246 testing::Mock::VerifyAndClearExpectations(&throttle); 241 testing::Mock::VerifyAndClearExpectations(&throttle);
247 } 242 }
248 } 243 }
249 244
250 TEST_F(ClearSiteDataThrottleTest, InvalidHeader) { 245 TEST_F(ClearSiteDataThrottleTest, InvalidHeader) {
251 struct TestCase { 246 struct TestCase {
252 const char* header; 247 const char* header;
253 const char* console_message; 248 const char* console_message;
254 } test_cases[] = { 249 } test_cases[] = {
255 {"", "Expected valid JSON.\n"}, 250 {"", "No recognized types specified.\n"},
256 {"\"unclosed quote", "Expected valid JSON.\n"}, 251 {"\"unclosed", "The header's value does not parse as valid JSON.\n"},
257 {"\"some text\"", "Expected a JSON dictionary with a 'types' field.\n"}, 252 {"\"passwords\"",
258 {"{ \"field\" : {} }",
259 "Expected a JSON dictionary with a 'types' field.\n"},
260 {"{ \"types\" : [ \"passwords\" ] }",
261 "Unrecognized type: \"passwords\".\n" 253 "Unrecognized type: \"passwords\".\n"
262 "No recognized types specified in the 'types' field.\n"}, 254 "No recognized types specified.\n"},
263 {"{ \"types\" : [ [ \"list in a list\" ] ] }", 255 {"[ \"list\" ]",
264 "Unrecognized type: [\"list in a list\"].\n" 256 "Unrecognized type: [\"list\"].\n"
265 "No recognized types specified in the 'types' field.\n"}, 257 "No recognized types specified.\n"},
266 {"{ \"types\" : [ \"кукис\", \"сторидж\", \"кэш\" ]", 258 {"[ \"list\" ]",
259 "Unrecognized type: [\"list\"].\n"
260 "No recognized types specified.\n"},
261 {"{ \"cookies\": [ \"a\" ] }",
262 "Unrecognized type: {\"cookies\":[\"a\"]}.\n"
263 "No recognized types specified.\n"},
264 {"\"кукис\", \"сторидж\", \"кэш\"",
267 "Must only contain ASCII characters.\n"}}; 265 "Must only contain ASCII characters.\n"}};
268 266
269 for (const TestCase& test_case : test_cases) { 267 for (const TestCase& test_case : test_cases) {
270 SCOPED_TRACE(test_case.header); 268 SCOPED_TRACE(test_case.header);
271 269
272 bool actual_cookies; 270 bool actual_cookies;
273 bool actual_storage; 271 bool actual_storage;
274 bool actual_cache; 272 bool actual_cache;
275 273
276 ConsoleMessagesDelegate console_delegate; 274 ConsoleMessagesDelegate console_delegate;
(...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after
398 {START, kClearCookiesHeader, false}, 396 {START, kClearCookiesHeader, false},
399 397
400 // The throttle does not defer redirects if there are no interesting 398 // The throttle does not defer redirects if there are no interesting
401 // response headers. 399 // response headers.
402 {REDIRECT, "", false}, 400 {REDIRECT, "", false},
403 {REDIRECT, "Set-Cookie: abc=123;", false}, 401 {REDIRECT, "Set-Cookie: abc=123;", false},
404 {REDIRECT, "Content-Type: image/png;", false}, 402 {REDIRECT, "Content-Type: image/png;", false},
405 403
406 // That includes malformed Clear-Site-Data headers or header values 404 // That includes malformed Clear-Site-Data headers or header values
407 // that do not lead to deletion. 405 // that do not lead to deletion.
408 {REDIRECT, "Clear-Site-Data: { types: cookies } ", false}, 406 {REDIRECT, "Clear-Site-Data: cookies", false},
409 {REDIRECT, "Clear-Site-Data: { \"types\": [ \"unknown type\" ] }", false}, 407 {REDIRECT, "Clear-Site-Data: \"unknown type\"", false},
410 408
411 // However, redirects are deferred for valid Clear-Site-Data headers. 409 // However, redirects are deferred for valid Clear-Site-Data headers.
412 {REDIRECT, 410 {REDIRECT, "Clear-Site-Data: \"cookies\", \"unknown type\"", true},
413 "Clear-Site-Data: { \"types\": [ \"cookies\", \"unknown type\" ] }",
414 true},
415 {REDIRECT, 411 {REDIRECT,
416 base::StringPrintf("Content-Type: image/png;\n%s", kClearCookiesHeader), 412 base::StringPrintf("Content-Type: image/png;\n%s", kClearCookiesHeader),
417 true}, 413 true},
418 {REDIRECT, 414 {REDIRECT,
419 base::StringPrintf("%s\nContent-Type: image/png;", kClearCookiesHeader), 415 base::StringPrintf("%s\nContent-Type: image/png;", kClearCookiesHeader),
420 true}, 416 true},
421 417
422 // We expect at most one instance of the header. Multiple instances 418 // Multiple instances of the header will be parsed correctly.
msramek 2017/06/08 09:42:50 Should the spec mention coalescing headers, or is
Mike West 2017/06/12 09:21:50 That's the default behavior (see https://tools.iet
423 // will not be parsed currently. This is not an inherent property of
424 // Clear-Site-Data, just a documentation of the current behavior.
425 {REDIRECT, 419 {REDIRECT,
426 base::StringPrintf("%s\n%s", kClearCookiesHeader, kClearCookiesHeader), 420 base::StringPrintf("%s\n%s", kClearCookiesHeader, kClearCookiesHeader),
427 false}, 421 true},
428 422
429 // Final response headers are treated the same way as in the case 423 // Final response headers are treated the same way as in the case
430 // of redirect. 424 // of redirect.
431 {REDIRECT, "Set-Cookie: abc=123;", false}, 425 {REDIRECT, "Set-Cookie: abc=123;", false},
432 {REDIRECT, "Clear-Site-Data: { types: cookies } ", false}, 426 {REDIRECT, "Clear-Site-Data: cookies", false},
433 {REDIRECT, kClearCookiesHeader, true}, 427 {REDIRECT, kClearCookiesHeader, true},
434 }; 428 };
435 429
436 struct TestOrigin { 430 struct TestOrigin {
437 const char* origin; 431 const char* origin;
438 bool valid; 432 bool valid;
439 } kTestOrigins[] = { 433 } kTestOrigins[] = {
440 // The throttle only works on secure origins. 434 // The throttle only works on secure origins.
441 {"https://secure-origin.com", true}, 435 {"https://secure-origin.com", true},
442 {"filesystem:https://secure-origin.com/temporary/", true}, 436 {"filesystem:https://secure-origin.com/temporary/", true},
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after
511 505
512 // Verifies that console outputs from various actions on different URLs 506 // Verifies that console outputs from various actions on different URLs
513 // are correctly pretty-printed to the console. 507 // are correctly pretty-printed to the console.
514 TEST_F(ClearSiteDataThrottleTest, FormattedConsoleOutput) { 508 TEST_F(ClearSiteDataThrottleTest, FormattedConsoleOutput) {
515 struct TestCase { 509 struct TestCase {
516 const char* header; 510 const char* header;
517 const char* url; 511 const char* url;
518 const char* output; 512 const char* output;
519 } kTestCases[] = { 513 } kTestCases[] = {
520 // Successful deletion outputs one line. 514 // Successful deletion outputs one line.
521 {"{ \"types\": [ \"cookies\" ] }", "https://origin1.com/foo", 515 {"\"cookies\"", "https://origin1.com/foo",
522 "Clear-Site-Data header on 'https://origin1.com/foo': " 516 "Clear-Site-Data header on 'https://origin1.com/foo': "
523 "Cleared data types: cookies.\n"}, 517 "Cleared data types: cookies.\n"},
524 518
525 // Another successful deletion. 519 // Another successful deletion.
526 {"{ \"types\": [ \"storage\" ] }", "https://origin2.com/foo", 520 {"\"storage\"", "https://origin2.com/foo",
527 "Clear-Site-Data header on 'https://origin2.com/foo': " 521 "Clear-Site-Data header on 'https://origin2.com/foo': "
528 "Cleared data types: storage.\n"}, 522 "Cleared data types: storage.\n"},
529 523
530 // Redirect to the same URL. Unsuccessful deletion outputs two lines. 524 // Redirect to the same URL. Unsuccessful deletion outputs two lines.
531 {"{ \"foo\": \"bar\" }", "https://origin2.com/foo", 525 {"\"foo\"", "https://origin2.com/foo",
532 "Clear-Site-Data header on 'https://origin2.com/foo': " 526 "Clear-Site-Data header on 'https://origin2.com/foo': "
533 "Expected a JSON dictionary with a 'types' field.\n"}, 527 "Unrecognized type: \"foo\".\n"
528 "Clear-Site-Data header on 'https://origin2.com/foo': "
529 "No recognized types specified.\n"},
534 530
535 // Redirect to another URL. Another unsuccessful deletion. 531 // Redirect to another URL. Another unsuccessful deletion.
536 {"\"some text\"", "https://origin3.com/bar", 532 {"\"some text\"", "https://origin3.com/bar",
537 "Clear-Site-Data header on 'https://origin3.com/bar': " 533 "Clear-Site-Data header on 'https://origin3.com/bar': "
538 "Expected a JSON dictionary with a 'types' field.\n"}, 534 "Unrecognized type: \"some text\".\n"
535 "Clear-Site-Data header on 'https://origin3.com/bar': "
536 "No recognized types specified.\n"},
539 537
540 // Yet another on the same URL. 538 // Yet another on the same URL.
541 {"{ \"types\" : [ \"passwords\" ] }", "https://origin3.com/bar", 539 {"\"passwords\"", "https://origin3.com/bar",
542 "Clear-Site-Data header on 'https://origin3.com/bar': " 540 "Clear-Site-Data header on 'https://origin3.com/bar': "
543 "Unrecognized type: \"passwords\".\n" 541 "Unrecognized type: \"passwords\".\n"
544 "Clear-Site-Data header on 'https://origin3.com/bar': " 542 "Clear-Site-Data header on 'https://origin3.com/bar': "
545 "No recognized types specified in the 'types' field.\n"}, 543 "No recognized types specified.\n"},
546 544
547 // Successful deletion on the same URL. 545 // Successful deletion on the same URL.
548 {"{ \"types\": [ \"cache\" ] }", "https://origin3.com/bar", 546 {"\"cache\"", "https://origin3.com/bar",
549 "Clear-Site-Data header on 'https://origin3.com/bar': " 547 "Clear-Site-Data header on 'https://origin3.com/bar': "
550 "Cleared data types: cache.\n"}, 548 "Cleared data types: cache.\n"},
551 549
552 // Redirect to the original URL. 550 // Redirect to the original URL.
553 // Successful deletion outputs one line. 551 // Successful deletion outputs one line.
554 {"", "https://origin1.com/foo", 552 {"", "https://origin1.com/foo",
555 "Clear-Site-Data header on 'https://origin1.com/foo': " 553 "Clear-Site-Data header on 'https://origin1.com/foo': "
556 "Expected valid JSON.\n"}}; 554 "No recognized types specified.\n"}};
557 555
558 bool kThrottleTypeIsNavigation[] = {true, false}; 556 bool kThrottleTypeIsNavigation[] = {true, false};
559 557
560 for (bool navigation : kThrottleTypeIsNavigation) { 558 for (bool navigation : kThrottleTypeIsNavigation) {
561 SCOPED_TRACE(navigation ? "Navigation test." : "Subresource test."); 559 SCOPED_TRACE(navigation ? "Navigation test." : "Subresource test.");
562 560
563 net::TestURLRequestContext context; 561 net::TestURLRequestContext context;
564 std::unique_ptr<net::URLRequest> request(context.CreateRequest( 562 std::unique_ptr<net::URLRequest> request(context.CreateRequest(
565 GURL(kTestCases[0].url), net::DEFAULT_PRIORITY, nullptr)); 563 GURL(kTestCases[0].url), net::DEFAULT_PRIORITY, nullptr));
566 ResourceRequestInfo::AllocateForTesting( 564 ResourceRequestInfo::AllocateForTesting(
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
619 // At the end, the console must contain all messages regardless of whether 617 // At the end, the console must contain all messages regardless of whether
620 // it was a navigation or a subresource request. 618 // it was a navigation or a subresource request.
621 std::string expected_output; 619 std::string expected_output;
622 for (struct TestCase& test_case : kTestCases) 620 for (struct TestCase& test_case : kTestCases)
623 expected_output += test_case.output; 621 expected_output += test_case.output;
624 EXPECT_EQ(expected_output, output_buffer); 622 EXPECT_EQ(expected_output, output_buffer);
625 } 623 }
626 } 624 }
627 625
628 } // namespace content 626 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698