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

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

Issue 2368923003: Support the Clear-Site-Data header on resource requests (Closed)
Patch Set: Addressed comments. 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/command_line.h" 9 #include "base/command_line.h"
10 #include "base/memory/ptr_util.h"
11 #include "base/memory/ref_counted.h"
12 #include "base/run_loop.h"
13 #include "base/strings/stringprintf.h"
14 #include "base/test/scoped_command_line.h"
15 #include "base/test/scoped_task_environment.h"
16 #include "content/public/browser/resource_request_info.h"
10 #include "content/public/common/content_switches.h" 17 #include "content/public/common/content_switches.h"
18 #include "content/public/test/test_browser_thread.cc"
19 #include "content/public/test/test_browser_thread_bundle.h"
20 #include "net/base/load_flags.h"
21 #include "net/http/http_util.h"
22 #include "net/url_request/redirect_info.h"
23 #include "net/url_request/url_request_job.h"
24 #include "net/url_request/url_request_test_util.h"
11 #include "testing/gmock/include/gmock/gmock.h" 25 #include "testing/gmock/include/gmock/gmock.h"
12 #include "testing/gtest/include/gtest/gtest.h" 26 #include "testing/gtest/include/gtest/gtest.h"
13 27
28 using ::testing::_;
29
14 namespace content { 30 namespace content {
15 31
32 using ConsoleMessagesDelegate = ClearSiteDataThrottle::ConsoleMessagesDelegate;
33
34 namespace {
35
36 const char kClearSiteDataHeaderPrefix[] = "Clear-Site-Data: ";
37
38 const char kClearCookiesHeader[] =
39 "Clear-Site-Data: { \"types\": [ \"cookies\" ] }";
40
41 // Used to verify that resource throttle delegate calls are made.
42 class MockResourceThrottleDelegate : public ResourceThrottle::Delegate {
43 public:
44 MOCK_METHOD0(Cancel, void());
45 MOCK_METHOD0(CancelAndIgnore, void());
46 MOCK_METHOD1(CancelWithError, void(int));
47 MOCK_METHOD0(Resume, void());
48 };
49
50 // A slightly modified ClearSiteDataThrottle for testing with unconditional
51 // construction, injectable response headers, and dummy clearing functionality.
52 class TestThrottle : public ClearSiteDataThrottle {
53 public:
54 TestThrottle(net::URLRequest* request,
55 std::unique_ptr<ConsoleMessagesDelegate> delegate)
56 : ClearSiteDataThrottle(request, std::move(delegate)) {}
57 ~TestThrottle() override {}
58
59 void SetResponseHeaders(const std::string& headers) {
60 std::string headers_with_status_code = "HTTP/1.1 200\n" + headers;
61 headers_ = new net::HttpResponseHeaders(net::HttpUtil::AssembleRawHeaders(
62 headers_with_status_code.c_str(), headers_with_status_code.size()));
63 }
64
65 MOCK_METHOD4(ClearSiteData,
66 void(const url::Origin& origin,
67 bool clear_cookies,
68 bool clear_storage,
69 bool clear_cache));
70
71 protected:
72 const net::HttpResponseHeaders* GetResponseHeaders() const override {
73 return headers_.get();
74 }
75
76 void ExecuteClearingTask(const url::Origin& origin,
77 bool clear_cookies,
78 bool clear_storage,
79 bool clear_cache,
80 base::OnceClosure callback) override {
81 ClearSiteData(origin, clear_cookies, clear_storage, clear_cache);
82
83 std::move(callback).Run();
84 }
85
86 private:
87 scoped_refptr<net::HttpResponseHeaders> headers_;
88 };
89
90 // A TestThrottle with modifiable current url.
91 class RedirectableTestThrottle : public TestThrottle {
92 public:
93 RedirectableTestThrottle(net::URLRequest* request,
94 std::unique_ptr<ConsoleMessagesDelegate> delegate)
95 : TestThrottle(request, std::move(delegate)) {}
96
97 const GURL& GetCurrentURL() const override {
98 return current_url_.is_valid() ? current_url_
99 : TestThrottle::GetCurrentURL();
100 }
101
102 void SetCurrentURLForTesting(const GURL& url) { current_url_ = url; }
103
104 private:
105 GURL current_url_;
106 };
107
108 // A ConsoleDelegate that outputs messages to a string buffer instead of the
109 // console (losing the level information).
110 class StringConsoleMessagesDelegate : public ConsoleMessagesDelegate {
111 public:
112 StringConsoleMessagesDelegate() {
113 SetOutputFormattedMessageFunctionForTesting(
114 base::Bind(&StringConsoleMessagesDelegate::OutputFormattedMessage,
115 base::Unretained(this)));
116 }
117
118 ~StringConsoleMessagesDelegate() override {}
119
120 const std::string& output() { return output_; }
121
122 private:
123 void OutputFormattedMessage(WebContents* web_contents,
124 ConsoleMessageLevel level,
125 const std::string& formatted_text) {
126 output_ += formatted_text + "\n";
127 }
128
129 std::string output_;
130 };
131
132 } // namespace
133
16 class ClearSiteDataThrottleTest : public testing::Test { 134 class ClearSiteDataThrottleTest : public testing::Test {
17 public: 135 public:
18 void SetUp() override { 136 ClearSiteDataThrottleTest()
19 base::CommandLine::ForCurrentProcess()->AppendSwitch( 137 : thread_bundle_(TestBrowserThreadBundle::IO_MAINLOOP) {}
20 switches::kEnableExperimentalWebPlatformFeatures);
21 throttle_ = ClearSiteDataThrottle::CreateThrottleForNavigation(nullptr);
22 }
23
24 ClearSiteDataThrottle* GetThrottle() {
25 return static_cast<ClearSiteDataThrottle*>(throttle_.get());
26 }
27 138
28 private: 139 private:
29 std::unique_ptr<NavigationThrottle> throttle_; 140 TestBrowserThreadBundle thread_bundle_;
141
142 DISALLOW_COPY_AND_ASSIGN(ClearSiteDataThrottleTest);
30 }; 143 };
31 144
32 TEST_F(ClearSiteDataThrottleTest, ParseHeader) { 145 TEST_F(ClearSiteDataThrottleTest, MaybeCreateThrottleForRequest) {
146 // Enable experimental features.
147 std::unique_ptr<base::test::ScopedCommandLine> command_line(
148 new base::test::ScopedCommandLine());
149 command_line->GetProcessCommandLine()->AppendSwitch(
150 switches::kEnableExperimentalWebPlatformFeatures);
151
152 // Create a URL request.
153 GURL url("https://www.example.com");
154 net::TestURLRequestContext context;
155 std::unique_ptr<net::URLRequest> request(
156 context.CreateRequest(url, net::DEFAULT_PRIORITY, nullptr));
157
158 // We will not create the throttle for an empty ResourceRequestInfo.
159 EXPECT_FALSE(
160 ClearSiteDataThrottle::MaybeCreateThrottleForRequest(request.get()));
161
162 // We can create the throttle for a valid ResourceRequestInfo.
163 ResourceRequestInfo::AllocateForTesting(request.get(), RESOURCE_TYPE_IMAGE,
164 nullptr, 0, 0, 0, false, true, true,
165 true, false);
166 EXPECT_TRUE(
167 ClearSiteDataThrottle::MaybeCreateThrottleForRequest(request.get()));
168
169 // But not if experimental web features are disabled again.
170 request->SetLoadFlags(net::LOAD_NORMAL);
171 command_line.reset();
172 EXPECT_FALSE(
173 ClearSiteDataThrottle::MaybeCreateThrottleForRequest(request.get()));
174 }
175
176 TEST_F(ClearSiteDataThrottleTest, ParseHeaderAndExecuteClearingTask) {
33 struct TestCase { 177 struct TestCase {
34 const char* header; 178 const char* header;
35 bool cookies; 179 bool cookies;
36 bool storage; 180 bool storage;
37 bool cache; 181 bool cache;
38 } test_cases[] = { 182 } test_cases[] = {
39 // One data type. 183 // One data type.
40 {"{ \"types\": [\"cookies\"] }", true, false, false}, 184 {"{ \"types\": [\"cookies\"] }", true, false, false},
41 {"{ \"types\": [\"storage\"] }", false, true, false}, 185 {"{ \"types\": [\"storage\"] }", false, true, false},
42 {"{ \"types\": [\"cache\"] }", false, false, true}, 186 {"{ \"types\": [\"cache\"] }", false, false, true},
(...skipping 22 matching lines...) Expand all
65 false}, 209 false},
66 210
67 // Unknown types are ignored, but we still proceed with the deletion for 211 // Unknown types are ignored, but we still proceed with the deletion for
68 // those that we recognize. 212 // those that we recognize.
69 {"{ \"types\": [\"cache\", \"foo\"] }", false, false, true}, 213 {"{ \"types\": [\"cache\", \"foo\"] }", false, false, true},
70 }; 214 };
71 215
72 for (const TestCase& test_case : test_cases) { 216 for (const TestCase& test_case : test_cases) {
73 SCOPED_TRACE(test_case.header); 217 SCOPED_TRACE(test_case.header);
74 218
219 // Test that ParseHeader works correctly.
75 bool actual_cookies; 220 bool actual_cookies;
76 bool actual_storage; 221 bool actual_storage;
77 bool actual_cache; 222 bool actual_cache;
78 223
79 std::vector<ClearSiteDataThrottle::ConsoleMessage> messages; 224 GURL url("https://example.com");
225 ConsoleMessagesDelegate console_delegate;
80 226
81 EXPECT_TRUE(GetThrottle()->ParseHeader(test_case.header, &actual_cookies, 227 EXPECT_TRUE(ClearSiteDataThrottle::ParseHeaderForTesting(
82 &actual_storage, &actual_cache, 228 test_case.header, &actual_cookies, &actual_storage, &actual_cache,
83 &messages)); 229 &console_delegate, url));
84 230
85 EXPECT_EQ(test_case.cookies, actual_cookies); 231 EXPECT_EQ(test_case.cookies, actual_cookies);
86 EXPECT_EQ(test_case.storage, actual_storage); 232 EXPECT_EQ(test_case.storage, actual_storage);
87 EXPECT_EQ(test_case.cache, actual_cache); 233 EXPECT_EQ(test_case.cache, actual_cache);
234
235 // Test that a call with the above parameters actually reaches
236 // ExecuteClearingTask().
237 net::TestURLRequestContext context;
238 std::unique_ptr<net::URLRequest> request(
239 context.CreateRequest(url, net::DEFAULT_PRIORITY, nullptr));
240 TestThrottle throttle(request.get(),
241 base::MakeUnique<ConsoleMessagesDelegate>());
242 MockResourceThrottleDelegate delegate;
243 throttle.set_delegate_for_testing(&delegate);
244 throttle.SetResponseHeaders(std::string(kClearSiteDataHeaderPrefix) +
245 test_case.header);
246
247 EXPECT_CALL(throttle, ClearSiteData(url::Origin(url), test_case.cookies,
248 test_case.storage, test_case.cache));
249 bool defer;
250 throttle.WillProcessResponse(&defer);
251 EXPECT_TRUE(defer);
252
253 testing::Mock::VerifyAndClearExpectations(&throttle);
88 } 254 }
89 } 255 }
90 256
91 TEST_F(ClearSiteDataThrottleTest, InvalidHeader) { 257 TEST_F(ClearSiteDataThrottleTest, InvalidHeader) {
92 struct TestCase { 258 struct TestCase {
93 const char* header; 259 const char* header;
94 const char* console_message; 260 const char* console_message;
95 } test_cases[] = { 261 } test_cases[] = {
96 {"", "Not a valid JSON.\n"}, 262 {"", "Not a valid JSON.\n"},
97 {"\"unclosed quote", "Not a valid JSON.\n"}, 263 {"\"unclosed quote", "Not a valid JSON.\n"},
98 {"\"some text\"", "Expecting a JSON dictionary with a 'types' field.\n"}, 264 {"\"some text\"", "Expecting a JSON dictionary with a 'types' field.\n"},
99 {"{ \"field\" : {} }", 265 {"{ \"field\" : {} }",
100 "Expecting a JSON dictionary with a 'types' field.\n"}, 266 "Expecting a JSON dictionary with a 'types' field.\n"},
101 {"{ \"types\" : [ \"passwords\" ] }", 267 {"{ \"types\" : [ \"passwords\" ] }",
102 "Invalid type: \"passwords\".\n" 268 "Unrecognized type: \"passwords\".\n"
103 "No valid types specified in the 'types' field.\n"}, 269 "No recognized types specified in the 'types' field.\n"},
104 {"{ \"types\" : [ [ \"list in a list\" ] ] }", 270 {"{ \"types\" : [ [ \"list in a list\" ] ] }",
105 "Invalid type: [\"list in a list\"].\n" 271 "Unrecognized type: [\"list in a list\"].\n"
106 "No valid types specified in the 'types' field.\n"}, 272 "No recognized types specified in the 'types' field.\n"},
107 {"{ \"types\" : [ \"кукис\", \"сторидж\", \"кэш\" ]", 273 {"{ \"types\" : [ \"кукис\", \"сторидж\", \"кэш\" ]",
108 "Must only contain ASCII characters.\n"}}; 274 "Must only contain ASCII characters.\n"}};
109 275
110 for (const TestCase& test_case : test_cases) { 276 for (const TestCase& test_case : test_cases) {
111 SCOPED_TRACE(test_case.header); 277 SCOPED_TRACE(test_case.header);
112 278
113 bool actual_cookies; 279 bool actual_cookies;
114 bool actual_storage; 280 bool actual_storage;
115 bool actual_cache; 281 bool actual_cache;
116 282
117 std::vector<ClearSiteDataThrottle::ConsoleMessage> messages; 283 ConsoleMessagesDelegate console_delegate;
118 284
119 EXPECT_FALSE(GetThrottle()->ParseHeader(test_case.header, &actual_cookies, 285 EXPECT_FALSE(ClearSiteDataThrottle::ParseHeaderForTesting(
120 &actual_storage, &actual_cache, 286 test_case.header, &actual_cookies, &actual_storage, &actual_cache,
121 &messages)); 287 &console_delegate, GURL()));
122 288
123 std::string multiline_message; 289 std::string multiline_message;
124 for (const auto& message : messages) { 290 for (const auto& message : console_delegate.messages()) {
125 EXPECT_EQ(CONSOLE_MESSAGE_LEVEL_ERROR, message.level); 291 EXPECT_EQ(CONSOLE_MESSAGE_LEVEL_ERROR, message.level);
126 multiline_message += message.text + "\n"; 292 multiline_message += message.text + "\n";
127 } 293 }
128 294
129 EXPECT_EQ(test_case.console_message, multiline_message); 295 EXPECT_EQ(test_case.console_message, multiline_message);
130 } 296 }
131 } 297 }
132 298
299 TEST_F(ClearSiteDataThrottleTest, LoadDoNotSaveCookies) {
300 net::TestURLRequestContext context;
301 std::unique_ptr<net::URLRequest> request(context.CreateRequest(
302 GURL("https://www.example.com"), net::DEFAULT_PRIORITY, nullptr));
303 std::unique_ptr<ConsoleMessagesDelegate> scoped_console_delegate(
304 new ConsoleMessagesDelegate());
305 const ConsoleMessagesDelegate* console_delegate =
306 scoped_console_delegate.get();
307 TestThrottle throttle(request.get(), std::move(scoped_console_delegate));
308 MockResourceThrottleDelegate delegate;
309 throttle.set_delegate_for_testing(&delegate);
310 throttle.SetResponseHeaders(kClearCookiesHeader);
311
312 bool defer;
313 throttle.WillProcessResponse(&defer);
314 EXPECT_TRUE(defer);
315 EXPECT_EQ(1u, console_delegate->messages().size());
316 EXPECT_EQ("Cleared datatypes: cookies.",
317 console_delegate->messages().front().text);
318 EXPECT_EQ(console_delegate->messages().front().level,
319 CONSOLE_MESSAGE_LEVEL_INFO);
320
321 request->SetLoadFlags(net::LOAD_DO_NOT_SAVE_COOKIES);
322 throttle.WillProcessResponse(&defer);
323 EXPECT_FALSE(defer);
324 EXPECT_EQ(2u, console_delegate->messages().size());
325 EXPECT_EQ(
326 "The request's credentials mode prohibits modifying cookies "
327 "and other local data.",
328 console_delegate->messages().rbegin()->text);
329 EXPECT_EQ(CONSOLE_MESSAGE_LEVEL_ERROR,
330 console_delegate->messages().rbegin()->level);
331 }
332
333 TEST_F(ClearSiteDataThrottleTest, InvalidOrigin) {
334 struct TestCase {
335 const char* origin;
336 bool expect_success;
337 std::string error_message; // Tested only if |expect_success| = false.
338 } kTestCases[] = {
339 // The throttle only works on secure origins.
340 {"https://secure-origin.com", true, ""},
341 {"filesystem:https://secure-origin.com/temporary/", true, ""},
342
343 // That includes localhost.
344 {"http://localhost", true, ""},
345
346 // Not on insecure origins.
347 {"http://insecure-origin.com", false,
348 "Not supported for insecure origins."},
349 {"filesystem:http://insecure-origin.com/temporary/", false,
350 "Not supported for insecure origins."},
351
352 // Not on unique origins.
353 {"data:unique-origin;", false, "Not supported for unique origins."},
354 };
355
356 net::TestURLRequestContext context;
357
358 for (const TestCase& test_case : kTestCases) {
359 std::unique_ptr<net::URLRequest> request(context.CreateRequest(
360 GURL(test_case.origin), net::DEFAULT_PRIORITY, nullptr));
361 std::unique_ptr<ConsoleMessagesDelegate> scoped_console_delegate(
362 new ConsoleMessagesDelegate());
363 const ConsoleMessagesDelegate* console_delegate =
364 scoped_console_delegate.get();
365 TestThrottle throttle(request.get(), std::move(scoped_console_delegate));
366 MockResourceThrottleDelegate delegate;
367 throttle.set_delegate_for_testing(&delegate);
368 throttle.SetResponseHeaders(kClearCookiesHeader);
369
370 bool defer;
371 throttle.WillProcessResponse(&defer);
372
373 EXPECT_EQ(defer, test_case.expect_success);
374 EXPECT_EQ(console_delegate->messages().size(), 1u);
375 EXPECT_EQ(test_case.expect_success ? CONSOLE_MESSAGE_LEVEL_INFO
376 : CONSOLE_MESSAGE_LEVEL_ERROR,
377 console_delegate->messages().front().level);
378 if (!test_case.expect_success) {
379 EXPECT_EQ(test_case.error_message,
380 console_delegate->messages().front().text);
381 }
382 }
383 }
384
385 TEST_F(ClearSiteDataThrottleTest, DeferAndResume) {
386 enum Stage { START, REDIRECT, RESPONSE };
387
388 struct TestCase {
389 Stage stage;
390 std::string response_headers;
391 bool should_defer;
392 } kTestCases[] = {
393 // The throttle never interferes while the request is starting. Response
394 // headers are ignored, because URLRequest is not supposed to have any
395 // at this stage in the first place.
396 {START, "", false},
397 {START, kClearCookiesHeader, false},
398
399 // The throttle does not defer redirects if there are no interesting
400 // response headers.
401 {REDIRECT, "", false},
402 {REDIRECT, "Set-Cookie: abc=123;", false},
403 {REDIRECT, "Content-Type: image/png;", false},
404
405 // That includes malformed Clear-Site-Data headers or header values
406 // that do not lead to deletion.
407 {REDIRECT, "Clear-Site-Data: { types: cookies } ", false},
408 {REDIRECT, "Clear-Site-Data: { \"types\": [ \"unknown type\" ] }", false},
409
410 // However, redirects are deferred for valid Clear-Site-Data headers.
411 {REDIRECT,
412 "Clear-Site-Data: { \"types\": [ \"cookies\", \"unknown type\" ] }",
413 true},
414 {REDIRECT,
415 base::StringPrintf("Content-Type: image/png;\n%s", kClearCookiesHeader),
416 true},
417 {REDIRECT,
418 base::StringPrintf("%s\nContent-Type: image/png;", kClearCookiesHeader),
419 true},
420
421 // We expect at most one instance of the header. Multiple instances
422 // will not be parsed currently. This is not an inherent property of
423 // Clear-Site-Data, just a documentation of the current behavior.
424 {REDIRECT,
425 base::StringPrintf("%s\n%s", kClearCookiesHeader, kClearCookiesHeader),
426 false},
427
428 // Final response headers are treated the same way as in the case
429 // of redirect.
430 {REDIRECT, "Set-Cookie: abc=123;", false},
431 {REDIRECT, "Clear-Site-Data: { types: cookies } ", false},
432 {REDIRECT, kClearCookiesHeader, true},
433 };
434
435 struct TestOrigin {
436 const char* origin;
437 bool valid;
438 } kTestOrigins[] = {
439 // The throttle only works on secure origins.
440 {"https://secure-origin.com", true},
441 {"filesystem:https://secure-origin.com/temporary/", true},
442
443 // That includes localhost.
444 {"http://localhost", true},
445
446 // Not on insecure origins.
447 {"http://insecure-origin.com", false},
448 {"filesystem:http://insecure-origin.com/temporary/", false},
449
450 // Not on unique origins.
451 {"data:unique-origin;", false},
452 };
453
454 net::TestURLRequestContext context;
455
456 for (const TestOrigin& test_origin : kTestOrigins) {
457 for (const TestCase& test_case : kTestCases) {
458 SCOPED_TRACE(base::StringPrintf("Origin=%s\nStage=%d\nHeaders:\n%s",
459 test_origin.origin, test_case.stage,
460 test_case.response_headers.c_str()));
461
462 std::unique_ptr<net::URLRequest> request(context.CreateRequest(
463 GURL(test_origin.origin), net::DEFAULT_PRIORITY, nullptr));
464 TestThrottle throttle(request.get(),
465 base::MakeUnique<ConsoleMessagesDelegate>());
466 throttle.SetResponseHeaders(test_case.response_headers);
467
468 MockResourceThrottleDelegate delegate;
469 throttle.set_delegate_for_testing(&delegate);
470
471 // Whether we should defer is always conditional on the origin
472 // being valid.
473 bool expected_defer = test_case.should_defer && test_origin.valid;
474
475 // If we expect loading to be deferred, then we also expect data to be
476 // cleared and the load to eventually resume.
477 if (expected_defer) {
478 testing::Expectation expectation = EXPECT_CALL(
479 throttle,
480 ClearSiteData(url::Origin(GURL(test_origin.origin)), _, _, _));
481 EXPECT_CALL(delegate, Resume()).After(expectation);
482 } else {
483 EXPECT_CALL(throttle, ClearSiteData(_, _, _, _)).Times(0);
484 EXPECT_CALL(delegate, Resume()).Times(0);
485 }
486
487 bool actual_defer = false;
488
489 switch (test_case.stage) {
490 case START: {
491 throttle.WillStartRequest(&actual_defer);
492 break;
493 }
494 case REDIRECT: {
495 net::RedirectInfo redirect_info;
496 throttle.WillRedirectRequest(redirect_info, &actual_defer);
497 break;
498 }
499 case RESPONSE: {
500 throttle.WillProcessResponse(&actual_defer);
501 break;
502 }
503 }
504
505 EXPECT_EQ(expected_defer, actual_defer);
506 testing::Mock::VerifyAndClearExpectations(&delegate);
507 }
508 }
509 }
510
511 // Verifies that console outputs from various actions on different URLs
512 // are correctly pretty-printed to the console.
513 TEST_F(ClearSiteDataThrottleTest, FormattedConsoleOutput) {
514 struct TestCase {
515 const char* header;
516 const char* url;
517 } kTestCases[] = {
518 // Successful deletion outputs one line.
519 {kClearCookiesHeader, "https://origin1.com/foo"},
520
521 // Another successful deletion.
522 {"{ \"types\": [ \"storage\" ] }", "https://origin2.com/foo"},
523
524 // Redirect to the same URL. Unsuccessful deletion outputs two lines.
525 {"{ \"foo\": \"bar\" }", "https://origin2.com/foo"},
526
527 // Redirect to another URL. Another unsuccessful deletion.
528 {"\"some text\"", "https://origin3.com/bar"},
529
530 // Yet another on the same URL.
531 {"{ \"types\" : [ \"passwords\" ] }", "https://origin3.com/bar"},
532
533 // Successful deletion on the same URL.
534 {"{ \"types\": [ \"cache\" ] }", "https://origin3.com/bar"},
535
536 // Redirect to the original URL.
537 // Successful deletion outputs one line.
538 {"", "Not a valid JSON."},
539 };
540
541 const char* expected_output =
542 "Clear-Site-Data header on 'https://origin1.com/foo': "
543 "Not a valid JSON.\n"
544 "Clear-Site-Data header on 'https://origin2.com/foo': "
545 "Cleared datatypes: storage.\n"
546 "Expecting a JSON dictionary with a 'types' field.\n"
547 "Clear-Site-Data header on 'https://origin3.com/bar': "
548 "Expecting a JSON dictionary with a 'types' field.\n"
549 "Unrecognized type: \"passwords\".\n"
550 "No recognized types specified in the 'types' field.\n"
551 "Cleared datatypes: cache.\n"
552 "Clear-Site-Data header on 'https://origin1.com/foo': "
553 "Not a valid JSON.\n";
554
555 net::TestURLRequestContext context;
556 std::unique_ptr<net::URLRequest> request(context.CreateRequest(
557 GURL(kTestCases[0].url), net::DEFAULT_PRIORITY, nullptr));
558
559 std::unique_ptr<StringConsoleMessagesDelegate> scoped_console_delegate(
560 new StringConsoleMessagesDelegate());
561 StringConsoleMessagesDelegate* console_delegate =
562 scoped_console_delegate.get();
563 RedirectableTestThrottle throttle(request.get(),
564 std::move(scoped_console_delegate));
565
566 MockResourceThrottleDelegate delegate;
567 throttle.set_delegate_for_testing(&delegate);
568
569 // Simulate redirecting the throttle through the above origins with the
570 // corresponding response headers.
571 bool defer;
572 throttle.WillStartRequest(&defer);
573
574 for (size_t i = 0; i < arraysize(kTestCases); i++) {
575 throttle.SetResponseHeaders(std::string(kClearSiteDataHeaderPrefix) +
576 kTestCases[i].header);
577
578 // TODO(msramek): There is probably a better way to do this inside
579 // URLRequest.
580 throttle.SetCurrentURLForTesting(GURL(kTestCases[i].url));
581
582 net::RedirectInfo redirect_info;
583 if (i < arraysize(kTestCases) - 1)
584 throttle.WillRedirectRequest(redirect_info, &defer);
585 else
586 throttle.WillProcessResponse(&defer);
587 }
588
589 console_delegate->OutputMessages(ResourceRequestInfo::WebContentsGetter());
590
591 // Wait for the UI thread to display the messages.
592 base::RunLoop run_loop;
593 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, run_loop.QuitClosure());
594 run_loop.Run();
595
596 EXPECT_EQ(expected_output, console_delegate->output());
597 }
598
133 } // namespace content 599 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698