• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2012 The Chromium Embedded Framework Authors. All rights
2 // reserved. Use of this source code is governed by a BSD-style license that
3 // can be found in the LICENSE file.
4 
5 #include <algorithm>
6 #include <vector>
7 
8 #include "include/base/cef_callback.h"
9 #include "include/base/cef_logging.h"
10 #include "include/base/cef_ref_counted.h"
11 #include "include/cef_cookie.h"
12 #include "include/cef_request_context_handler.h"
13 #include "include/cef_scheme.h"
14 #include "include/cef_server.h"
15 #include "include/cef_waitable_event.h"
16 #include "include/wrapper/cef_closure_task.h"
17 #include "tests/ceftests/routing_test_handler.h"
18 #include "tests/ceftests/test_handler.h"
19 #include "tests/ceftests/test_server.h"
20 #include "tests/ceftests/test_suite.h"
21 #include "tests/ceftests/test_util.h"
22 #include "tests/gtest/include/gtest/gtest.h"
23 
24 namespace {
25 
26 const char* kTestUrl = "http://www.test.com/path/to/cookietest/foo.html";
27 const char* kTestDomain = "www.test.com";
28 const char* kTestPath = "/path/to/cookietest";
29 
30 const int kIgnoreNumDeleted = -2;
31 
32 typedef std::vector<CefCookie> CookieVector;
33 
34 class TestCompletionCallback : public CefCompletionCallback {
35  public:
TestCompletionCallback(CefRefPtr<CefWaitableEvent> event)36   explicit TestCompletionCallback(CefRefPtr<CefWaitableEvent> event)
37       : event_(event) {}
38 
OnComplete()39   void OnComplete() override {
40     EXPECT_TRUE(CefCurrentlyOn(TID_UI));
41     event_->Signal();
42   }
43 
44  private:
45   CefRefPtr<CefWaitableEvent> event_;
46 
47   IMPLEMENT_REFCOUNTING(TestCompletionCallback);
48   DISALLOW_COPY_AND_ASSIGN(TestCompletionCallback);
49 };
50 
51 class TestSetCookieCallback : public CefSetCookieCallback {
52  public:
TestSetCookieCallback(bool expected_success,CefRefPtr<CefWaitableEvent> event)53   TestSetCookieCallback(bool expected_success,
54                         CefRefPtr<CefWaitableEvent> event)
55       : expected_success_(expected_success), event_(event) {}
56 
OnComplete(bool success)57   void OnComplete(bool success) override {
58     EXPECT_TRUE(CefCurrentlyOn(TID_UI));
59     EXPECT_EQ(expected_success_, success);
60     event_->Signal();
61   }
62 
63  private:
64   bool expected_success_;
65   CefRefPtr<CefWaitableEvent> event_;
66 
67   IMPLEMENT_REFCOUNTING(TestSetCookieCallback);
68   DISALLOW_COPY_AND_ASSIGN(TestSetCookieCallback);
69 };
70 
71 class TestDeleteCookiesCallback : public CefDeleteCookiesCallback {
72  public:
TestDeleteCookiesCallback(int expected_num_deleted,CefRefPtr<CefWaitableEvent> event)73   TestDeleteCookiesCallback(int expected_num_deleted,
74                             CefRefPtr<CefWaitableEvent> event)
75       : expected_num_deleted_(expected_num_deleted), event_(event) {}
76 
OnComplete(int num_deleted)77   void OnComplete(int num_deleted) override {
78     EXPECT_TRUE(CefCurrentlyOn(TID_UI));
79     if (expected_num_deleted_ != kIgnoreNumDeleted) {
80       EXPECT_EQ(expected_num_deleted_, num_deleted);
81     }
82     event_->Signal();
83   }
84 
85  private:
86   int expected_num_deleted_;
87   CefRefPtr<CefWaitableEvent> event_;
88 
89   IMPLEMENT_REFCOUNTING(TestDeleteCookiesCallback);
90   DISALLOW_COPY_AND_ASSIGN(TestDeleteCookiesCallback);
91 };
92 
93 class TestVisitor : public CefCookieVisitor {
94  public:
TestVisitor(CookieVector * cookies,bool deleteCookies,base::OnceClosure callback)95   TestVisitor(CookieVector* cookies,
96               bool deleteCookies,
97               base::OnceClosure callback)
98       : cookies_(cookies),
99         delete_cookies_(deleteCookies),
100         callback_(std::move(callback)) {
101     EXPECT_TRUE(cookies_);
102     EXPECT_FALSE(callback_.is_null());
103   }
~TestVisitor()104   ~TestVisitor() override { std::move(callback_).Run(); }
105 
Visit(const CefCookie & cookie,int count,int total,bool & deleteCookie)106   bool Visit(const CefCookie& cookie,
107              int count,
108              int total,
109              bool& deleteCookie) override {
110     EXPECT_TRUE(CefCurrentlyOn(TID_UI));
111     cookies_->push_back(cookie);
112     if (delete_cookies_)
113       deleteCookie = true;
114     return true;
115   }
116 
117  private:
118   CookieVector* cookies_;
119   bool delete_cookies_;
120   base::OnceClosure callback_;
121 
122   IMPLEMENT_REFCOUNTING(TestVisitor);
123 };
124 
125 // Set the cookies.
SetCookies(CefRefPtr<CefCookieManager> manager,const CefString & url,const CookieVector & cookies,bool expected_success,CefRefPtr<CefWaitableEvent> event)126 void SetCookies(CefRefPtr<CefCookieManager> manager,
127                 const CefString& url,
128                 const CookieVector& cookies,
129                 bool expected_success,
130                 CefRefPtr<CefWaitableEvent> event) {
131   CookieVector::const_iterator it = cookies.begin();
132   for (; it != cookies.end(); ++it) {
133     EXPECT_TRUE(manager->SetCookie(
134         url, *it, new TestSetCookieCallback(expected_success, event)));
135     event->Wait();
136   }
137 }
138 
139 // Delete the cookie.
DeleteCookies(CefRefPtr<CefCookieManager> manager,const CefString & url,const CefString & cookie_name,int expected_num_deleted,CefRefPtr<CefWaitableEvent> event)140 void DeleteCookies(CefRefPtr<CefCookieManager> manager,
141                    const CefString& url,
142                    const CefString& cookie_name,
143                    int expected_num_deleted,
144                    CefRefPtr<CefWaitableEvent> event) {
145   EXPECT_TRUE(manager->DeleteCookies(
146       url, cookie_name,
147       new TestDeleteCookiesCallback(expected_num_deleted, event)));
148   event->Wait();
149 }
150 
151 // Create a test cookie. If |withDomain| is true a domain cookie will be
152 // created, otherwise a host cookie will be created.
CreateCookie(CefRefPtr<CefCookieManager> manager,CefCookie & cookie,bool withDomain,bool sessionCookie,CefRefPtr<CefWaitableEvent> event)153 void CreateCookie(CefRefPtr<CefCookieManager> manager,
154                   CefCookie& cookie,
155                   bool withDomain,
156                   bool sessionCookie,
157                   CefRefPtr<CefWaitableEvent> event) {
158   CefString(&cookie.name).FromASCII("my_cookie");
159   CefString(&cookie.value).FromASCII("My Value");
160   if (withDomain)
161     CefString(&cookie.domain).FromASCII(kTestDomain);
162   CefString(&cookie.path).FromASCII(kTestPath);
163   if (!sessionCookie) {
164     cookie.has_expires = true;
165     cookie.expires.year = 2200;
166     cookie.expires.month = 4;
167     cookie.expires.day_of_week = 5;
168     cookie.expires.day_of_month = 11;
169   }
170 
171   CookieVector cookies;
172   cookies.push_back(cookie);
173 
174   SetCookies(manager, kTestUrl, cookies, true, event);
175 }
176 
177 // Visit URL cookies. Execute |callback| on completion.
VisitUrlCookies(CefRefPtr<CefCookieManager> manager,const CefString & url,bool includeHttpOnly,CookieVector & cookies,bool deleteCookies,base::OnceClosure callback)178 void VisitUrlCookies(CefRefPtr<CefCookieManager> manager,
179                      const CefString& url,
180                      bool includeHttpOnly,
181                      CookieVector& cookies,
182                      bool deleteCookies,
183                      base::OnceClosure callback) {
184   EXPECT_TRUE(manager->VisitUrlCookies(
185       url, includeHttpOnly,
186       new TestVisitor(&cookies, deleteCookies, std::move(callback))));
187 }
188 
189 // Visit URL cookies. Block on |event|.
VisitUrlCookies(CefRefPtr<CefCookieManager> manager,const CefString & url,bool includeHttpOnly,CookieVector & cookies,bool deleteCookies,CefRefPtr<CefWaitableEvent> event)190 void VisitUrlCookies(CefRefPtr<CefCookieManager> manager,
191                      const CefString& url,
192                      bool includeHttpOnly,
193                      CookieVector& cookies,
194                      bool deleteCookies,
195                      CefRefPtr<CefWaitableEvent> event) {
196   VisitUrlCookies(manager, url, includeHttpOnly, cookies, deleteCookies,
197                   base::BindOnce(&CefWaitableEvent::Signal, event));
198   event->Wait();
199 }
200 
201 // Visit all cookies. Execute |callback| on completion.
VisitAllCookies(CefRefPtr<CefCookieManager> manager,CookieVector & cookies,bool deleteCookies,base::OnceClosure callback)202 void VisitAllCookies(CefRefPtr<CefCookieManager> manager,
203                      CookieVector& cookies,
204                      bool deleteCookies,
205                      base::OnceClosure callback) {
206   EXPECT_TRUE(manager->VisitAllCookies(
207       new TestVisitor(&cookies, deleteCookies, std::move(callback))));
208 }
209 
210 // Visit all cookies. Block on |event|.
VisitAllCookies(CefRefPtr<CefCookieManager> manager,CookieVector & cookies,bool deleteCookies,CefRefPtr<CefWaitableEvent> event)211 void VisitAllCookies(CefRefPtr<CefCookieManager> manager,
212                      CookieVector& cookies,
213                      bool deleteCookies,
214                      CefRefPtr<CefWaitableEvent> event) {
215   VisitAllCookies(manager, cookies, deleteCookies,
216                   base::BindOnce(&CefWaitableEvent::Signal, event));
217   event->Wait();
218 }
219 
220 // Retrieve the test cookie. If |withDomain| is true check that the cookie
221 // is a domain cookie, otherwise a host cookie. if |deleteCookies| is true
222 // the cookie will be deleted when it's retrieved.
GetCookie(CefRefPtr<CefCookieManager> manager,const CefCookie & cookie,bool withDomain,CefRefPtr<CefWaitableEvent> event,bool deleteCookies)223 void GetCookie(CefRefPtr<CefCookieManager> manager,
224                const CefCookie& cookie,
225                bool withDomain,
226                CefRefPtr<CefWaitableEvent> event,
227                bool deleteCookies) {
228   CookieVector cookies;
229 
230   // Get the cookie and delete it.
231   VisitUrlCookies(manager, kTestUrl, false, cookies, deleteCookies, event);
232 
233   EXPECT_EQ(1U, cookies.size());
234   if (cookies.size() != 1U)
235     return;
236 
237   const CefCookie& cookie_read = cookies[0];
238   EXPECT_EQ(CefString(&cookie_read.name), "my_cookie");
239   EXPECT_EQ(CefString(&cookie_read.value), "My Value");
240   if (withDomain)
241     EXPECT_EQ(CefString(&cookie_read.domain), ".www.test.com");
242   else
243     EXPECT_EQ(CefString(&cookie_read.domain), kTestDomain);
244   EXPECT_EQ(CefString(&cookie_read.path), kTestPath);
245   EXPECT_EQ(cookie.has_expires, cookie_read.has_expires);
246   EXPECT_EQ(cookie.expires.year, cookie_read.expires.year);
247   EXPECT_EQ(cookie.expires.month, cookie_read.expires.month);
248   EXPECT_EQ(cookie.expires.day_of_week, cookie_read.expires.day_of_week);
249   EXPECT_EQ(cookie.expires.day_of_month, cookie_read.expires.day_of_month);
250   EXPECT_EQ(cookie.expires.hour, cookie_read.expires.hour);
251   EXPECT_EQ(cookie.expires.minute, cookie_read.expires.minute);
252   EXPECT_EQ(cookie.expires.second, cookie_read.expires.second);
253   EXPECT_EQ(cookie.expires.millisecond, cookie_read.expires.millisecond);
254   EXPECT_EQ(cookie.same_site, cookie_read.same_site);
255   EXPECT_EQ(cookie.priority, cookie_read.priority);
256 }
257 
258 // Verify that no cookies exist. If |withUrl| is true it will only check for
259 // cookies matching the URL.
VerifyNoCookies(CefRefPtr<CefCookieManager> manager,CefRefPtr<CefWaitableEvent> event,bool withUrl)260 void VerifyNoCookies(CefRefPtr<CefCookieManager> manager,
261                      CefRefPtr<CefWaitableEvent> event,
262                      bool withUrl) {
263   CookieVector cookies;
264 
265   // Verify that the cookie has been deleted.
266   if (withUrl) {
267     VisitUrlCookies(manager, kTestUrl, false, cookies, false, event);
268   } else {
269     VisitAllCookies(manager, cookies, false, event);
270   }
271 
272   EXPECT_EQ(0U, cookies.size());
273 }
274 
275 // Delete all system cookies.
DeleteAllCookies(CefRefPtr<CefCookieManager> manager,CefRefPtr<CefWaitableEvent> event)276 void DeleteAllCookies(CefRefPtr<CefCookieManager> manager,
277                       CefRefPtr<CefWaitableEvent> event) {
278   DeleteCookies(manager, CefString(), CefString(), kIgnoreNumDeleted, event);
279 }
280 
TestDomainCookie(CefRefPtr<CefCookieManager> manager,CefRefPtr<CefWaitableEvent> event)281 void TestDomainCookie(CefRefPtr<CefCookieManager> manager,
282                       CefRefPtr<CefWaitableEvent> event) {
283   CefCookie cookie;
284 
285   // Create a domain cookie.
286   CreateCookie(manager, cookie, true, false, event);
287 
288   // Retrieve, verify and delete the domain cookie.
289   GetCookie(manager, cookie, true, event, true);
290 
291   // Verify that the cookie was deleted.
292   VerifyNoCookies(manager, event, true);
293 }
294 
TestHostCookie(CefRefPtr<CefCookieManager> manager,CefRefPtr<CefWaitableEvent> event)295 void TestHostCookie(CefRefPtr<CefCookieManager> manager,
296                     CefRefPtr<CefWaitableEvent> event) {
297   CefCookie cookie;
298 
299   // Create a host cookie.
300   CreateCookie(manager, cookie, false, false, event);
301 
302   // Retrieve, verify and delete the host cookie.
303   GetCookie(manager, cookie, false, event, true);
304 
305   // Verify that the cookie was deleted.
306   VerifyNoCookies(manager, event, true);
307 }
308 
TestInvalidCookie(CefRefPtr<CefCookieManager> manager,CefRefPtr<CefWaitableEvent> event)309 void TestInvalidCookie(CefRefPtr<CefCookieManager> manager,
310                        CefRefPtr<CefWaitableEvent> event) {
311   CookieVector cookies;
312 
313   CefCookie cookie;
314   const char* kUrl = "http://www.xyz.com";
315   CefString(&cookie.name).FromASCII("invalid1");
316   CefString(&cookie.value).FromASCII("invalid1");
317   CefString(&cookie.domain).FromASCII(".zyx.com");  // domain mismatch
318 
319   cookies.push_back(cookie);
320 
321   // No cookies will be set due to non canonical cookie
322   SetCookies(manager, kUrl, cookies, false, event);
323 }
324 
TestMultipleCookies(CefRefPtr<CefCookieManager> manager,CefRefPtr<CefWaitableEvent> event)325 void TestMultipleCookies(CefRefPtr<CefCookieManager> manager,
326                          CefRefPtr<CefWaitableEvent> event) {
327   std::stringstream ss;
328   int i;
329 
330   CookieVector cookies;
331 
332   const int kNumCookies = 4;
333 
334   // Create the cookies.
335   for (i = 0; i < kNumCookies; i++) {
336     CefCookie cookie;
337 
338     ss << "my_cookie" << i;
339     CefString(&cookie.name).FromASCII(ss.str().c_str());
340     ss.str("");
341     ss << "My Value " << i;
342     CefString(&cookie.value).FromASCII(ss.str().c_str());
343     ss.str("");
344 
345     cookies.push_back(cookie);
346   }
347 
348   // Set the cookies.
349   SetCookies(manager, kTestUrl, cookies, true, event);
350   cookies.clear();
351 
352   // Get the cookies without deleting them.
353   VisitUrlCookies(manager, kTestUrl, false, cookies, false, event);
354 
355   EXPECT_EQ((CookieVector::size_type)kNumCookies, cookies.size());
356 
357   CookieVector::const_iterator it = cookies.begin();
358   for (i = 0; it != cookies.end(); ++it, ++i) {
359     const CefCookie& cookie = *it;
360 
361     ss << "my_cookie" << i;
362     EXPECT_EQ(CefString(&cookie.name), ss.str());
363     ss.str("");
364     ss << "My Value " << i;
365     EXPECT_EQ(CefString(&cookie.value), ss.str());
366     ss.str("");
367   }
368 
369   cookies.clear();
370 
371   // Delete the 2nd cookie.
372   DeleteCookies(manager, kTestUrl, CefString("my_cookie1"), 1, event);
373 
374   // Verify that the cookie has been deleted.
375   VisitUrlCookies(manager, kTestUrl, false, cookies, false, event);
376 
377   EXPECT_EQ(3U, cookies.size());
378   if (cookies.size() != 3U)
379     return;
380 
381   EXPECT_EQ(CefString(&cookies[0].name), "my_cookie0");
382   EXPECT_EQ(CefString(&cookies[1].name), "my_cookie2");
383   EXPECT_EQ(CefString(&cookies[2].name), "my_cookie3");
384 
385   cookies.clear();
386 
387   // Delete the rest of the cookies.
388   DeleteCookies(manager, kTestUrl, CefString(), 3, event);
389 
390   // Verify that the cookies have been deleted.
391   VisitUrlCookies(manager, kTestUrl, false, cookies, false, event);
392 
393   EXPECT_EQ(0U, cookies.size());
394 
395   // Create the cookies.
396   for (i = 0; i < kNumCookies; i++) {
397     CefCookie cookie;
398 
399     ss << "my_cookie" << i;
400     CefString(&cookie.name).FromASCII(ss.str().c_str());
401     ss.str("");
402     ss << "My Value " << i;
403     CefString(&cookie.value).FromASCII(ss.str().c_str());
404     ss.str("");
405 
406     cookies.push_back(cookie);
407   }
408 
409   // Delete all of the cookies using the visitor.
410   VisitUrlCookies(manager, kTestUrl, false, cookies, true, event);
411 
412   cookies.clear();
413 
414   // Verify that the cookies have been deleted.
415   VisitUrlCookies(manager, kTestUrl, false, cookies, false, event);
416 
417   EXPECT_EQ(0U, cookies.size());
418 }
419 
TestAllCookies(CefRefPtr<CefCookieManager> manager,CefRefPtr<CefWaitableEvent> event)420 void TestAllCookies(CefRefPtr<CefCookieManager> manager,
421                     CefRefPtr<CefWaitableEvent> event) {
422   CookieVector cookies;
423 
424   // Delete all system cookies just in case something is left over from a
425   // different test.
426   DeleteAllCookies(manager, event);
427 
428   // Verify that all system cookies have been deleted.
429   VisitAllCookies(manager, cookies, false, event);
430 
431   EXPECT_EQ(0U, cookies.size());
432 
433   // Create cookies with 2 separate hosts.
434   CefCookie cookie1;
435   const char* kUrl1 = "http://www.foo.com";
436   CefString(&cookie1.name).FromASCII("my_cookie1");
437   CefString(&cookie1.value).FromASCII("My Value 1");
438 
439   cookies.push_back(cookie1);
440   SetCookies(manager, kUrl1, cookies, true, event);
441   cookies.clear();
442 
443   CefCookie cookie2;
444   const char* kUrl2 = "http://www.bar.com";
445   CefString(&cookie2.name).FromASCII("my_cookie2");
446   CefString(&cookie2.value).FromASCII("My Value 2");
447 
448   cookies.push_back(cookie2);
449   SetCookies(manager, kUrl2, cookies, true, event);
450   cookies.clear();
451 
452   // Verify that all system cookies can be retrieved.
453   VisitAllCookies(manager, cookies, false, event);
454 
455   EXPECT_EQ(2U, cookies.size());
456   if (cookies.size() != 2U)
457     return;
458 
459   EXPECT_EQ(CefString(&cookies[0].name), "my_cookie1");
460   EXPECT_EQ(CefString(&cookies[0].value), "My Value 1");
461   EXPECT_EQ(CefString(&cookies[0].domain), "www.foo.com");
462   EXPECT_EQ(CefString(&cookies[1].name), "my_cookie2");
463   EXPECT_EQ(CefString(&cookies[1].value), "My Value 2");
464   EXPECT_EQ(CefString(&cookies[1].domain), "www.bar.com");
465   cookies.clear();
466 
467   // Verify that the cookies can be retrieved separately.
468   VisitUrlCookies(manager, kUrl1, false, cookies, false, event);
469 
470   EXPECT_EQ(1U, cookies.size());
471   if (cookies.size() != 1U)
472     return;
473 
474   EXPECT_EQ(CefString(&cookies[0].name), "my_cookie1");
475   EXPECT_EQ(CefString(&cookies[0].value), "My Value 1");
476   EXPECT_EQ(CefString(&cookies[0].domain), "www.foo.com");
477   cookies.clear();
478 
479   VisitUrlCookies(manager, kUrl2, false, cookies, false, event);
480 
481   EXPECT_EQ(1U, cookies.size());
482   if (cookies.size() != 1U)
483     return;
484 
485   EXPECT_EQ(CefString(&cookies[0].name), "my_cookie2");
486   EXPECT_EQ(CefString(&cookies[0].value), "My Value 2");
487   EXPECT_EQ(CefString(&cookies[0].domain), "www.bar.com");
488   cookies.clear();
489 
490   // Delete all of the system cookies.
491   DeleteAllCookies(manager, event);
492 
493   // Verify that all system cookies have been deleted.
494   VerifyNoCookies(manager, event, false);
495 }
496 
497 }  // namespace
498 
499 // Test creation of a invalid cookie.
TEST(CookieTest,BasicInvalidCookie)500 TEST(CookieTest, BasicInvalidCookie) {
501   CefRefPtr<CefWaitableEvent> event =
502       CefWaitableEvent::CreateWaitableEvent(true, false);
503 
504   CefRefPtr<CefCookieManager> manager =
505       CefCookieManager::GetGlobalManager(new TestCompletionCallback(event));
506   event->Wait();
507   EXPECT_TRUE(manager.get());
508 
509   TestInvalidCookie(manager, event);
510 }
511 
512 // Test creation of a domain cookie.
TEST(CookieTest,BasicDomainCookie)513 TEST(CookieTest, BasicDomainCookie) {
514   CefRefPtr<CefWaitableEvent> event =
515       CefWaitableEvent::CreateWaitableEvent(true, false);
516 
517   CefRefPtr<CefCookieManager> manager =
518       CefCookieManager::GetGlobalManager(new TestCompletionCallback(event));
519   event->Wait();
520   EXPECT_TRUE(manager.get());
521 
522   TestDomainCookie(manager, event);
523 }
524 
525 // Test creation of a host cookie.
TEST(CookieTest,BasicHostCookie)526 TEST(CookieTest, BasicHostCookie) {
527   CefRefPtr<CefWaitableEvent> event =
528       CefWaitableEvent::CreateWaitableEvent(true, false);
529 
530   CefRefPtr<CefCookieManager> manager =
531       CefCookieManager::GetGlobalManager(new TestCompletionCallback(event));
532   event->Wait();
533   EXPECT_TRUE(manager.get());
534 
535   TestHostCookie(manager, event);
536 }
537 
538 // Test creation of multiple cookies.
TEST(CookieTest,BasicMultipleCookies)539 TEST(CookieTest, BasicMultipleCookies) {
540   CefRefPtr<CefWaitableEvent> event =
541       CefWaitableEvent::CreateWaitableEvent(true, false);
542 
543   CefRefPtr<CefCookieManager> manager =
544       CefCookieManager::GetGlobalManager(new TestCompletionCallback(event));
545   event->Wait();
546   EXPECT_TRUE(manager.get());
547 
548   TestMultipleCookies(manager, event);
549 }
550 
TEST(CookieTest,BasicAllCookies)551 TEST(CookieTest, BasicAllCookies) {
552   CefRefPtr<CefWaitableEvent> event =
553       CefWaitableEvent::CreateWaitableEvent(true, false);
554 
555   CefRefPtr<CefCookieManager> manager =
556       CefCookieManager::GetGlobalManager(new TestCompletionCallback(event));
557   event->Wait();
558   EXPECT_TRUE(manager.get());
559 
560   TestAllCookies(manager, event);
561 }
562 
563 namespace {
564 
565 const char* kCookieJSUrl1 = "http://tests/cookie1.html";
566 const char* kCookieJSUrl2 = "http://tests/cookie2.html";
567 
568 class CookieTestJSHandler : public TestHandler {
569  public:
CookieTestJSHandler()570   CookieTestJSHandler() {}
571 
RunTest()572   void RunTest() override {
573     std::string page =
574         "<html><head>"
575         "<script>"
576         "document.cookie='name1=value1;"
577         // Invalid date should not cause a crash (see issue #2927).
578         " expires=Tue, 07 Nov 94276 07:58:05 GMT'"
579         "</script>"
580         "</head><body>COOKIE TEST1</body></html>";
581     AddResource(kCookieJSUrl1, page, "text/html");
582 
583     page =
584         "<html><head>"
585         "<script>"
586         "document.cookie='name2=value2';"
587         "</script>"
588         "</head><body>COOKIE TEST2</body></html>";
589     AddResource(kCookieJSUrl2, page, "text/html");
590 
591     // Create the request context that will use an in-memory cache.
592     CefRequestContextSettings settings;
593     CefRefPtr<CefRequestContext> request_context =
594         CefRequestContext::CreateContext(settings, nullptr);
595     manager_ = request_context->GetCookieManager(nullptr);
596 
597     // Create the browser.
598     CreateBrowser(kCookieJSUrl1, request_context);
599 
600     // Time out the test after a reasonable period of time.
601     SetTestTimeout();
602   }
603 
604   // Go to the next URL.
LoadNextURL(CefRefPtr<CefFrame> frame)605   void LoadNextURL(CefRefPtr<CefFrame> frame) {
606     if (!CefCurrentlyOn(TID_UI)) {
607       CefPostTask(TID_UI, base::BindOnce(&CookieTestJSHandler::LoadNextURL,
608                                          this, frame));
609       return;
610     }
611 
612     frame->LoadURL(kCookieJSUrl2);
613   }
614 
CompleteTest()615   void CompleteTest() {
616     if (!CefCurrentlyOn(TID_UI)) {
617       CefPostTask(TID_UI,
618                   base::BindOnce(&CookieTestJSHandler::CompleteTest, this));
619       return;
620     }
621 
622     DestroyTest();
623   }
624 
OnLoadEnd(CefRefPtr<CefBrowser> browser,CefRefPtr<CefFrame> frame,int httpStatusCode)625   void OnLoadEnd(CefRefPtr<CefBrowser> browser,
626                  CefRefPtr<CefFrame> frame,
627                  int httpStatusCode) override {
628     std::string url = frame->GetURL();
629     if (url == kCookieJSUrl1) {
630       got_load_end1_.yes();
631       VerifyCookie(
632           manager_, url, "name1", "value1", true, &got_cookie1_,
633           base::BindOnce(&CookieTestJSHandler::LoadNextURL, this, frame));
634     } else {
635       got_load_end2_.yes();
636       VerifyCookie(manager_, url, "name2", "value2", true, &got_cookie2_,
637                    base::BindOnce(&CookieTestJSHandler::CompleteTest, this));
638     }
639   }
640 
641   // Verify that the cookie was set successfully.
VerifyCookie(CefRefPtr<CefCookieManager> manager,const std::string & url,const std::string & name,const std::string & value,bool deleteCookie,TrackCallback * callback,base::OnceClosure continue_callback)642   void VerifyCookie(CefRefPtr<CefCookieManager> manager,
643                     const std::string& url,
644                     const std::string& name,
645                     const std::string& value,
646                     bool deleteCookie,
647                     TrackCallback* callback,
648                     base::OnceClosure continue_callback) {
649     // Get the cookie.
650     EXPECT_TRUE(cookies_.empty());
651     VisitUrlCookies(
652         manager, url, false, cookies_, deleteCookie,
653         base::BindOnce(&CookieTestJSHandler::VerifyCookieComplete, this, name,
654                        value, callback, std::move(continue_callback)));
655   }
656 
VerifyCookieComplete(const std::string & name,const std::string & value,TrackCallback * callback,base::OnceClosure continue_callback)657   void VerifyCookieComplete(const std::string& name,
658                             const std::string& value,
659                             TrackCallback* callback,
660                             base::OnceClosure continue_callback) {
661     if (cookies_.size() == 1U && CefString(&cookies_[0].name) == name &&
662         CefString(&cookies_[0].value) == value) {
663       callback->yes();
664     }
665 
666     cookies_.clear();
667     std::move(continue_callback).Run();
668   }
669 
670   CefRefPtr<CefCookieManager> manager_;
671 
672   CookieVector cookies_;
673 
674   TrackCallback got_load_end1_;
675   TrackCallback got_load_end2_;
676   TrackCallback got_cookie1_;
677   TrackCallback got_cookie2_;
678 
679   IMPLEMENT_REFCOUNTING(CookieTestJSHandler);
680 };
681 
682 }  // namespace
683 
684 // Verify use of multiple cookie managers vis JS.
TEST(CookieTest,GetCookieManagerJS)685 TEST(CookieTest, GetCookieManagerJS) {
686   CefRefPtr<CookieTestJSHandler> handler = new CookieTestJSHandler();
687   handler->ExecuteTest();
688 
689   EXPECT_TRUE(handler->got_load_end1_);
690   EXPECT_TRUE(handler->got_load_end2_);
691   EXPECT_TRUE(handler->got_cookie1_);
692   EXPECT_TRUE(handler->got_cookie2_);
693 
694   ReleaseAndWaitForDestructor(handler);
695 }
696 
697 namespace {
698 
699 const char kCustomCookieScheme[] = "ccustom";
700 
701 class CompletionCallback : public CefCompletionCallback {
702  public:
CompletionCallback(base::OnceClosure callback)703   explicit CompletionCallback(base::OnceClosure callback)
704       : callback_(std::move(callback)) {}
705 
OnComplete()706   void OnComplete() override { std::move(callback_).Run(); }
707 
708  private:
709   base::OnceClosure callback_;
710   IMPLEMENT_REFCOUNTING(CompletionCallback);
711 };
712 
713 class CookieTestSchemeHandler : public TestHandler {
714  public:
715   class SchemeHandler : public CefResourceHandler {
716    public:
SchemeHandler(CookieTestSchemeHandler * handler)717     explicit SchemeHandler(CookieTestSchemeHandler* handler)
718         : handler_(handler), offset_(0) {}
719 
Open(CefRefPtr<CefRequest> request,bool & handle_request,CefRefPtr<CefCallback> callback)720     bool Open(CefRefPtr<CefRequest> request,
721               bool& handle_request,
722               CefRefPtr<CefCallback> callback) override {
723       EXPECT_FALSE(CefCurrentlyOn(TID_UI) || CefCurrentlyOn(TID_IO));
724 
725       std::string url = request->GetURL();
726       if (url == handler_->url1_) {
727         content_ = "<html><body>COOKIE TEST1</body></html>";
728         cookie_ = "name1=value1";
729         handler_->got_process_request1_.yes();
730       } else if (url == handler_->url2_) {
731         content_ = "<html><body>COOKIE TEST2</body></html>";
732         cookie_ = "name2=value2";
733         handler_->got_process_request2_.yes();
734       } else if (url == handler_->url3_) {
735         content_ = "<html><body>COOKIE TEST3</body></html>";
736         handler_->got_process_request3_.yes();
737 
738         // Verify that the cookie was passed in.
739         CefRequest::HeaderMap headerMap;
740         request->GetHeaderMap(headerMap);
741         CefRequest::HeaderMap::iterator it = headerMap.find("Cookie");
742         if (it != headerMap.end() && it->second == "name2=value2")
743           handler_->got_process_request_cookie_.yes();
744       }
745 
746       // Continue immediately.
747       handle_request = true;
748       return true;
749     }
750 
GetResponseHeaders(CefRefPtr<CefResponse> response,int64 & response_length,CefString & redirectUrl)751     void GetResponseHeaders(CefRefPtr<CefResponse> response,
752                             int64& response_length,
753                             CefString& redirectUrl) override {
754       response_length = content_.size();
755 
756       response->SetStatus(200);
757       response->SetMimeType("text/html");
758 
759       if (!cookie_.empty()) {
760         CefResponse::HeaderMap headerMap;
761         response->GetHeaderMap(headerMap);
762         headerMap.insert(std::make_pair("Set-Cookie", cookie_));
763         response->SetHeaderMap(headerMap);
764       }
765     }
766 
Read(void * data_out,int bytes_to_read,int & bytes_read,CefRefPtr<CefResourceReadCallback> callback)767     bool Read(void* data_out,
768               int bytes_to_read,
769               int& bytes_read,
770               CefRefPtr<CefResourceReadCallback> callback) override {
771       EXPECT_FALSE(CefCurrentlyOn(TID_UI) || CefCurrentlyOn(TID_IO));
772 
773       bool has_data = false;
774       bytes_read = 0;
775 
776       size_t size = content_.size();
777       if (offset_ < size) {
778         int transfer_size =
779             std::min(bytes_to_read, static_cast<int>(size - offset_));
780         memcpy(data_out, content_.c_str() + offset_, transfer_size);
781         offset_ += transfer_size;
782 
783         bytes_read = transfer_size;
784         has_data = true;
785       }
786 
787       return has_data;
788     }
789 
Cancel()790     void Cancel() override {}
791 
792    private:
793     CookieTestSchemeHandler* handler_;
794     std::string content_;
795     size_t offset_;
796     std::string cookie_;
797 
798     IMPLEMENT_REFCOUNTING(SchemeHandler);
799     DISALLOW_COPY_AND_ASSIGN(SchemeHandler);
800   };
801 
802   class SchemeHandlerFactory : public CefSchemeHandlerFactory {
803    public:
SchemeHandlerFactory(CookieTestSchemeHandler * handler)804     explicit SchemeHandlerFactory(CookieTestSchemeHandler* handler)
805         : handler_(handler) {}
806 
Create(CefRefPtr<CefBrowser> browser,CefRefPtr<CefFrame> frame,const CefString & scheme_name,CefRefPtr<CefRequest> request)807     CefRefPtr<CefResourceHandler> Create(
808         CefRefPtr<CefBrowser> browser,
809         CefRefPtr<CefFrame> frame,
810         const CefString& scheme_name,
811         CefRefPtr<CefRequest> request) override {
812       std::string url = request->GetURL();
813       if (url == handler_->url3_) {
814         // Verify that the cookie was not passed in.
815         CefRequest::HeaderMap headerMap;
816         request->GetHeaderMap(headerMap);
817         CefRequest::HeaderMap::iterator it = headerMap.find("Cookie");
818         if (it != headerMap.end() && it->second == "name2=value2")
819           handler_->got_create_cookie_.yes();
820       }
821 
822       return new SchemeHandler(handler_);
823     }
824 
825    private:
826     CookieTestSchemeHandler* handler_;
827 
828     IMPLEMENT_REFCOUNTING(SchemeHandlerFactory);
829     DISALLOW_COPY_AND_ASSIGN(SchemeHandlerFactory);
830   };
831 
CookieTestSchemeHandler(const std::string & scheme,bool use_global,bool block_cookies=false)832   CookieTestSchemeHandler(const std::string& scheme,
833                           bool use_global,
834                           bool block_cookies = false)
835       : scheme_(scheme),
836         use_global_(use_global),
837         block_cookies_(block_cookies) {
838     url1_ = scheme + "://cookie-tests/cookie1.html";
839     url2_ = scheme + "://cookie-tests/cookie2.html";
840     url3_ = scheme + "://cookie-tests/cookie3.html";
841   }
842 
RunTest()843   void RunTest() override {
844     if (use_global_) {
845       request_context_ = CefRequestContext::GetGlobalContext();
846     } else {
847       // Create the request context that will use an in-memory cache.
848       CefRequestContextSettings settings;
849 
850       if (scheme_ == kCustomCookieScheme || block_cookies_) {
851         if (!block_cookies_) {
852           CefString(&settings.cookieable_schemes_list) = kCustomCookieScheme;
853         } else {
854           settings.cookieable_schemes_exclude_defaults = true;
855         }
856       }
857 
858       request_context_ = CefRequestContext::CreateContext(settings, nullptr);
859     }
860 
861     // Register the scheme handler.
862     request_context_->RegisterSchemeHandlerFactory(
863         scheme_, "cookie-tests", new SchemeHandlerFactory(this));
864 
865     manager_ = request_context_->GetCookieManager(nullptr);
866 
867     // Create the browser.
868     CreateBrowser(url1_, request_context_);
869 
870     // Time out the test after a reasonable period of time.
871     SetTestTimeout();
872   }
873 
874   // Go to the next URL.
LoadNextURL(CefRefPtr<CefFrame> frame,const std::string & url)875   void LoadNextURL(CefRefPtr<CefFrame> frame, const std::string& url) {
876     if (!CefCurrentlyOn(TID_UI)) {
877       CefPostTask(TID_UI, base::BindOnce(&CookieTestSchemeHandler::LoadNextURL,
878                                          this, frame, url));
879       return;
880     }
881 
882     frame->LoadURL(url);
883   }
884 
CompleteTest(CefRefPtr<CefBrowser> browser)885   void CompleteTest(CefRefPtr<CefBrowser> browser) {
886     if (!CefCurrentlyOn(TID_UI)) {
887       CefPostTask(TID_UI, base::BindOnce(&CookieTestSchemeHandler::CompleteTest,
888                                          this, browser));
889       return;
890     }
891 
892     // Unregister the scheme handler.
893     browser->GetHost()->GetRequestContext()->RegisterSchemeHandlerFactory(
894         scheme_, "cookie-tests", nullptr);
895 
896     DestroyTest();
897   }
898 
OnLoadEnd(CefRefPtr<CefBrowser> browser,CefRefPtr<CefFrame> frame,int httpStatusCode)899   void OnLoadEnd(CefRefPtr<CefBrowser> browser,
900                  CefRefPtr<CefFrame> frame,
901                  int httpStatusCode) override {
902     std::string url = frame->GetURL();
903     if (url == url1_) {
904       got_load_end1_.yes();
905       VerifyCookie(manager_, url, "name1", "value1", true, &got_cookie1_,
906                    base::BindOnce(&CookieTestSchemeHandler::LoadNextURL, this,
907                                   frame, url2_));
908     } else if (url == url2_) {
909       got_load_end2_.yes();
910       VerifyCookie(manager_, url, "name2", "value2", false, &got_cookie2_,
911                    base::BindOnce(&CookieTestSchemeHandler::LoadNextURL, this,
912                                   frame, url3_));
913     } else {
914       got_load_end3_.yes();
915       VerifyCookie(manager_, url, "name2", "value2", true, &got_cookie3_,
916                    base::BindOnce(&CookieTestSchemeHandler::CompleteTest, this,
917                                   browser));
918     }
919   }
920 
DestroyTest()921   void DestroyTest() override {
922     EXPECT_TRUE(got_process_request1_);
923     EXPECT_TRUE(got_process_request2_);
924     EXPECT_TRUE(got_process_request3_);
925     EXPECT_TRUE(got_load_end1_);
926     EXPECT_TRUE(got_load_end2_);
927     EXPECT_TRUE(got_load_end3_);
928 
929     if (block_cookies_) {
930       EXPECT_FALSE(got_create_cookie_);
931       EXPECT_FALSE(got_process_request_cookie_);
932       EXPECT_FALSE(got_cookie1_);
933       EXPECT_FALSE(got_cookie2_);
934       EXPECT_FALSE(got_cookie3_);
935     } else {
936       EXPECT_TRUE(got_create_cookie_);
937       EXPECT_TRUE(got_process_request_cookie_);
938       EXPECT_TRUE(got_cookie1_);
939       EXPECT_TRUE(got_cookie2_);
940       EXPECT_TRUE(got_cookie3_);
941     }
942 
943     // Unregister the scheme handler.
944     request_context_->RegisterSchemeHandlerFactory(scheme_, "cookie-tests",
945                                                    nullptr);
946     request_context_ = nullptr;
947 
948     TestHandler::DestroyTest();
949   }
950 
951   // Verify that the cookie was set successfully.
VerifyCookie(CefRefPtr<CefCookieManager> manager,const std::string & url,const std::string & name,const std::string & value,bool deleteCookie,TrackCallback * callback,base::OnceClosure continue_callback)952   void VerifyCookie(CefRefPtr<CefCookieManager> manager,
953                     const std::string& url,
954                     const std::string& name,
955                     const std::string& value,
956                     bool deleteCookie,
957                     TrackCallback* callback,
958                     base::OnceClosure continue_callback) {
959     // Get the cookie.
960     EXPECT_TRUE(cookies_.empty());
961     VisitUrlCookies(
962         manager, url, false, cookies_, deleteCookie,
963         base::BindOnce(&CookieTestSchemeHandler::VerifyCookieComplete, this,
964                        name, value, callback, std::move(continue_callback)));
965   }
966 
VerifyCookieComplete(const std::string & name,const std::string & value,TrackCallback * callback,base::OnceClosure continue_callback)967   void VerifyCookieComplete(const std::string& name,
968                             const std::string& value,
969                             TrackCallback* callback,
970                             base::OnceClosure continue_callback) {
971     if (cookies_.size() == 1U && CefString(&cookies_[0].name) == name &&
972         CefString(&cookies_[0].value) == value) {
973       callback->yes();
974     }
975 
976     cookies_.clear();
977     std::move(continue_callback).Run();
978   }
979 
980   const std::string scheme_;
981   const bool use_global_;
982   const bool block_cookies_;
983   std::string url1_;
984   std::string url2_;
985   std::string url3_;
986 
987   CefRefPtr<CefRequestContext> request_context_;
988   CefRefPtr<CefCookieManager> manager_;
989 
990   CookieVector cookies_;
991 
992   TrackCallback got_process_request1_;
993   TrackCallback got_process_request2_;
994   TrackCallback got_process_request3_;
995   TrackCallback got_create_cookie_;
996   TrackCallback got_process_request_cookie_;
997   TrackCallback got_load_end1_;
998   TrackCallback got_load_end2_;
999   TrackCallback got_load_end3_;
1000   TrackCallback got_cookie1_;
1001   TrackCallback got_cookie2_;
1002   TrackCallback got_cookie3_;
1003 
1004   IMPLEMENT_REFCOUNTING(CookieTestSchemeHandler);
1005 };
1006 
1007 }  // namespace
1008 
1009 // Verify use of the global cookie manager with HTTP.
TEST(CookieTest,GetCookieManagerHttpGlobal)1010 TEST(CookieTest, GetCookieManagerHttpGlobal) {
1011   CefRefPtr<CookieTestSchemeHandler> handler =
1012       new CookieTestSchemeHandler("http", true);
1013   handler->ExecuteTest();
1014   ReleaseAndWaitForDestructor(handler);
1015 }
1016 
1017 // Verify use of an in-memory cookie manager with HTTP.
TEST(CookieTest,GetCookieManagerHttpInMemory)1018 TEST(CookieTest, GetCookieManagerHttpInMemory) {
1019   CefRefPtr<CookieTestSchemeHandler> handler =
1020       new CookieTestSchemeHandler("http", false);
1021   handler->ExecuteTest();
1022   ReleaseAndWaitForDestructor(handler);
1023 }
1024 
1025 // Verify use of an in-memory cookie manager with HTTP to block all cookies.
TEST(CookieTest,GetCookieManagerHttpInMemoryBlocked)1026 TEST(CookieTest, GetCookieManagerHttpInMemoryBlocked) {
1027   CefRefPtr<CookieTestSchemeHandler> handler =
1028       new CookieTestSchemeHandler("http", false, true);
1029   handler->ExecuteTest();
1030   ReleaseAndWaitForDestructor(handler);
1031 }
1032 
1033 // Verify use of the global cookie manager with a custom scheme.
TEST(CookieTest,GetCookieManagerCustomGlobal)1034 TEST(CookieTest, GetCookieManagerCustomGlobal) {
1035   CefRefPtr<CookieTestSchemeHandler> handler =
1036       new CookieTestSchemeHandler(kCustomCookieScheme, true);
1037   handler->ExecuteTest();
1038   ReleaseAndWaitForDestructor(handler);
1039 }
1040 
1041 // Verify use of an in-memory cookie manager with a custom scheme.
TEST(CookieTest,GetCookieManagerCustomInMemory)1042 TEST(CookieTest, GetCookieManagerCustomInMemory) {
1043   CefRefPtr<CookieTestSchemeHandler> handler =
1044       new CookieTestSchemeHandler(kCustomCookieScheme, false);
1045   handler->ExecuteTest();
1046   ReleaseAndWaitForDestructor(handler);
1047 }
1048 
1049 namespace {
1050 
1051 const char kCookieAccessScheme[] = "http";
1052 const char kCookieAccessDomain[] = "test-cookies.com";
1053 const char* kCookieAccessServerAddress = test_server::kServerAddress;
1054 const uint16 kCookieAccessServerPort = test_server::kServerPort;
1055 
GetCookieAccessOrigin(const std::string & scheme,bool server_backend)1056 std::string GetCookieAccessOrigin(const std::string& scheme,
1057                                   bool server_backend) {
1058   std::stringstream ss;
1059   if (server_backend) {
1060     ss << scheme << "://" << kCookieAccessServerAddress << ":"
1061        << kCookieAccessServerPort;
1062   } else {
1063     ss << scheme << "://" << kCookieAccessDomain;
1064   }
1065   return ss.str();
1066 }
1067 
GetCookieAccessUrl1(const std::string & scheme,bool server_backend)1068 std::string GetCookieAccessUrl1(const std::string& scheme,
1069                                 bool server_backend) {
1070   return GetCookieAccessOrigin(scheme, server_backend) + "/cookie1.html";
1071 }
1072 
GetCookieAccessUrl2(const std::string & scheme,bool server_backend)1073 std::string GetCookieAccessUrl2(const std::string& scheme,
1074                                 bool server_backend) {
1075   return GetCookieAccessOrigin(scheme, server_backend) + "/cookie2.html";
1076 }
1077 
TestCookieString(const std::string & cookie_str,int & cookie_js_ct,int & cookie_net_ct)1078 void TestCookieString(const std::string& cookie_str,
1079                       int& cookie_js_ct,
1080                       int& cookie_net_ct) {
1081   if (cookie_str.find("name_js=value_js") != std::string::npos) {
1082     cookie_js_ct++;
1083   }
1084   if (cookie_str.find("name_net=value_net") != std::string::npos) {
1085     cookie_net_ct++;
1086   }
1087 }
1088 
1089 struct CookieAccessData {
1090   CefRefPtr<CefResponse> response;
1091   std::string response_data;
1092 
1093   int request_ct_ = 0;
1094   int cookie_js_ct_ = 0;
1095   int cookie_net_ct_ = 0;
1096 };
1097 
1098 class CookieAccessResponseHandler {
1099  public:
CookieAccessResponseHandler()1100   CookieAccessResponseHandler() {}
1101   virtual void AddResponse(const std::string& url, CookieAccessData* data) = 0;
1102 
1103  protected:
~CookieAccessResponseHandler()1104   virtual ~CookieAccessResponseHandler() {}
1105 };
1106 
GetHeaderValue(const CefServer::HeaderMap & header_map,const std::string & header_name)1107 std::string GetHeaderValue(const CefServer::HeaderMap& header_map,
1108                            const std::string& header_name) {
1109   CefServer::HeaderMap::const_iterator it = header_map.find(header_name);
1110   if (it != header_map.end())
1111     return it->second;
1112   return std::string();
1113 }
1114 
1115 // Serves request responses.
1116 class CookieAccessSchemeHandler : public CefResourceHandler {
1117  public:
CookieAccessSchemeHandler(CookieAccessData * data)1118   explicit CookieAccessSchemeHandler(CookieAccessData* data)
1119       : data_(data), offset_(0) {}
1120 
Open(CefRefPtr<CefRequest> request,bool & handle_request,CefRefPtr<CefCallback> callback)1121   bool Open(CefRefPtr<CefRequest> request,
1122             bool& handle_request,
1123             CefRefPtr<CefCallback> callback) override {
1124     EXPECT_FALSE(CefCurrentlyOn(TID_UI) || CefCurrentlyOn(TID_IO));
1125 
1126     CefRequest::HeaderMap headerMap;
1127     request->GetHeaderMap(headerMap);
1128     const std::string& cookie_str = GetHeaderValue(headerMap, "Cookie");
1129     TestCookieString(cookie_str, data_->cookie_js_ct_, data_->cookie_net_ct_);
1130 
1131     // Continue immediately.
1132     handle_request = true;
1133     return true;
1134   }
1135 
GetResponseHeaders(CefRefPtr<CefResponse> response,int64 & response_length,CefString & redirectUrl)1136   void GetResponseHeaders(CefRefPtr<CefResponse> response,
1137                           int64& response_length,
1138                           CefString& redirectUrl) override {
1139     EXPECT_IO_THREAD();
1140 
1141     response->SetStatus(data_->response->GetStatus());
1142     response->SetStatusText(data_->response->GetStatusText());
1143     response->SetMimeType(data_->response->GetMimeType());
1144 
1145     CefResponse::HeaderMap headerMap;
1146     data_->response->GetHeaderMap(headerMap);
1147     response->SetHeaderMap(headerMap);
1148 
1149     response_length = data_->response_data.length();
1150   }
1151 
Read(void * data_out,int bytes_to_read,int & bytes_read,CefRefPtr<CefResourceReadCallback> callback)1152   bool Read(void* data_out,
1153             int bytes_to_read,
1154             int& bytes_read,
1155             CefRefPtr<CefResourceReadCallback> callback) override {
1156     EXPECT_FALSE(CefCurrentlyOn(TID_UI) || CefCurrentlyOn(TID_IO));
1157 
1158     bool has_data = false;
1159     bytes_read = 0;
1160 
1161     size_t size = data_->response_data.length();
1162     if (offset_ < size) {
1163       int transfer_size =
1164           std::min(bytes_to_read, static_cast<int>(size - offset_));
1165       memcpy(data_out, data_->response_data.c_str() + offset_, transfer_size);
1166       offset_ += transfer_size;
1167 
1168       bytes_read = transfer_size;
1169       has_data = true;
1170     }
1171 
1172     return has_data;
1173   }
1174 
Cancel()1175   void Cancel() override { EXPECT_IO_THREAD(); }
1176 
1177  private:
TestCookie(const CefCookie & cookie,TrackCallback & got_cookie_js,TrackCallback & got_cookie_net)1178   static void TestCookie(const CefCookie& cookie,
1179                          TrackCallback& got_cookie_js,
1180                          TrackCallback& got_cookie_net) {
1181     const std::string& cookie_name = CefString(&cookie.name);
1182     const std::string& cookie_val = CefString(&cookie.value);
1183     if (cookie_name == "name_js") {
1184       EXPECT_STREQ("value_js", cookie_val.c_str());
1185       got_cookie_js.yes();
1186     } else if (cookie_name == "name_net") {
1187       EXPECT_STREQ("value_net", cookie_val.c_str());
1188       got_cookie_net.yes();
1189     } else {
1190       ADD_FAILURE() << "Unexpected cookie: " << cookie_name;
1191     }
1192   }
1193 
1194   // |data_| is not owned by this object.
1195   CookieAccessData* data_;
1196 
1197   size_t offset_;
1198 
1199   IMPLEMENT_REFCOUNTING(CookieAccessSchemeHandler);
1200   DISALLOW_COPY_AND_ASSIGN(CookieAccessSchemeHandler);
1201 };
1202 
1203 class CookieAccessSchemeHandlerFactory : public CefSchemeHandlerFactory,
1204                                          public CookieAccessResponseHandler {
1205  public:
CookieAccessSchemeHandlerFactory()1206   CookieAccessSchemeHandlerFactory() {}
1207 
Create(CefRefPtr<CefBrowser> browser,CefRefPtr<CefFrame> frame,const CefString & scheme_name,CefRefPtr<CefRequest> request)1208   CefRefPtr<CefResourceHandler> Create(CefRefPtr<CefBrowser> browser,
1209                                        CefRefPtr<CefFrame> frame,
1210                                        const CefString& scheme_name,
1211                                        CefRefPtr<CefRequest> request) override {
1212     EXPECT_IO_THREAD();
1213     const std::string& url = request->GetURL();
1214     ResponseDataMap::const_iterator it = data_map_.find(url);
1215     if (it != data_map_.end()) {
1216       it->second->request_ct_++;
1217 
1218       return new CookieAccessSchemeHandler(it->second);
1219     }
1220 
1221     // Unknown test.
1222     if (!IgnoreURL(url)) {
1223       ADD_FAILURE() << "Unexpected url: " << url;
1224     }
1225     return nullptr;
1226   }
1227 
AddResponse(const std::string & url,CookieAccessData * data)1228   void AddResponse(const std::string& url, CookieAccessData* data) override {
1229     data_map_.insert(std::make_pair(url, data));
1230   }
1231 
Shutdown(base::OnceClosure complete_callback)1232   void Shutdown(base::OnceClosure complete_callback) {
1233     if (!CefCurrentlyOn(TID_IO)) {
1234       CefPostTask(TID_IO, base::BindOnce(std::move(complete_callback)));
1235       return;
1236     }
1237 
1238     std::move(complete_callback).Run();
1239   }
1240 
1241  private:
1242   // Map of URL to Data.
1243   typedef std::map<std::string, CookieAccessData*> ResponseDataMap;
1244   ResponseDataMap data_map_;
1245 
1246   IMPLEMENT_REFCOUNTING(CookieAccessSchemeHandlerFactory);
1247 };
1248 
1249 // HTTP server handler.
1250 class CookieAccessServerHandler : public test_server::ObserverHelper,
1251                                   public CookieAccessResponseHandler {
1252  public:
CookieAccessServerHandler()1253   CookieAccessServerHandler()
1254       : initialized_(false),
1255         expected_http_request_ct_(-1),
1256         actual_http_request_ct_(0) {}
1257 
~CookieAccessServerHandler()1258   virtual ~CookieAccessServerHandler() { RunCompleteCallback(); }
1259 
1260   // Must be called before CreateServer().
AddResponse(const std::string & url,CookieAccessData * data)1261   void AddResponse(const std::string& url, CookieAccessData* data) override {
1262     EXPECT_FALSE(initialized_);
1263     data_map_.insert(std::make_pair(url, data));
1264   }
1265 
1266   // Must be called before CreateServer().
SetExpectedRequestCount(int count)1267   void SetExpectedRequestCount(int count) {
1268     EXPECT_FALSE(initialized_);
1269     expected_http_request_ct_ = count;
1270   }
1271 
1272   // |complete_callback| will be executed on the UI thread after the server is
1273   // started.
CreateServer(base::OnceClosure complete_callback)1274   void CreateServer(base::OnceClosure complete_callback) {
1275     EXPECT_UI_THREAD();
1276 
1277     if (expected_http_request_ct_ < 0) {
1278       // Default to the assumption of one request per registered URL.
1279       SetExpectedRequestCount(static_cast<int>(data_map_.size()));
1280     }
1281 
1282     EXPECT_FALSE(initialized_);
1283     initialized_ = true;
1284 
1285     EXPECT_TRUE(complete_callback_.is_null());
1286     complete_callback_ = std::move(complete_callback);
1287 
1288     Initialize();
1289   }
1290 
1291   // Results in a call to VerifyResults() and eventual execution of the
1292   // |complete_callback| on the UI thread via CookieAccessServerHandler
1293   // destruction.
ShutdownServer(base::OnceClosure complete_callback)1294   void ShutdownServer(base::OnceClosure complete_callback) {
1295     EXPECT_UI_THREAD();
1296 
1297     EXPECT_TRUE(complete_callback_.is_null());
1298     complete_callback_ = std::move(complete_callback);
1299 
1300     Shutdown();
1301   }
1302 
OnInitialized(const std::string & server_origin)1303   void OnInitialized(const std::string& server_origin) override {
1304     EXPECT_UI_THREAD();
1305     EXPECT_STREQ(server_origin.c_str(),
1306                  GetCookieAccessOrigin(kCookieAccessScheme, true).c_str());
1307 
1308     EXPECT_FALSE(got_server_created_);
1309     got_server_created_.yes();
1310 
1311     RunCompleteCallback();
1312   }
1313 
OnShutdown()1314   void OnShutdown() override {
1315     EXPECT_UI_THREAD();
1316 
1317     EXPECT_FALSE(got_server_destroyed_);
1318     got_server_destroyed_.yes();
1319 
1320     VerifyResults();
1321 
1322     delete this;
1323   }
1324 
OnHttpRequest(CefRefPtr<CefServer> server,int connection_id,const CefString & client_address,CefRefPtr<CefRequest> request)1325   bool OnHttpRequest(CefRefPtr<CefServer> server,
1326                      int connection_id,
1327                      const CefString& client_address,
1328                      CefRefPtr<CefRequest> request) override {
1329     EXPECT_UI_THREAD();
1330     EXPECT_FALSE(client_address.empty());
1331 
1332     // Log the requests for better error reporting.
1333     request_log_ += request->GetMethod().ToString() + " " +
1334                     request->GetURL().ToString() + "\n";
1335 
1336     HandleRequest(server, connection_id, request);
1337 
1338     actual_http_request_ct_++;
1339 
1340     return true;
1341   }
1342 
1343  private:
VerifyResults()1344   void VerifyResults() {
1345     EXPECT_TRUE(got_server_created_);
1346     EXPECT_TRUE(got_server_destroyed_);
1347     EXPECT_EQ(expected_http_request_ct_, actual_http_request_ct_)
1348         << request_log_;
1349   }
1350 
HandleRequest(CefRefPtr<CefServer> server,int connection_id,CefRefPtr<CefRequest> request)1351   void HandleRequest(CefRefPtr<CefServer> server,
1352                      int connection_id,
1353                      CefRefPtr<CefRequest> request) {
1354     const std::string& url = request->GetURL();
1355     ResponseDataMap::const_iterator it = data_map_.find(url);
1356     if (it != data_map_.end()) {
1357       it->second->request_ct_++;
1358 
1359       CefRequest::HeaderMap headerMap;
1360       request->GetHeaderMap(headerMap);
1361       const std::string& cookie_str = GetHeaderValue(headerMap, "cookie");
1362       TestCookieString(cookie_str, it->second->cookie_js_ct_,
1363                        it->second->cookie_net_ct_);
1364 
1365       SendResponse(server, connection_id, it->second->response,
1366                    it->second->response_data);
1367     } else {
1368       // Unknown test.
1369       if (!IgnoreURL(url)) {
1370         ADD_FAILURE() << "Unexpected url: " << url;
1371       }
1372       server->SendHttp500Response(connection_id, "Unknown test");
1373     }
1374   }
1375 
SendResponse(CefRefPtr<CefServer> server,int connection_id,CefRefPtr<CefResponse> response,const std::string & response_data)1376   static void SendResponse(CefRefPtr<CefServer> server,
1377                            int connection_id,
1378                            CefRefPtr<CefResponse> response,
1379                            const std::string& response_data) {
1380     // Execute on the server thread because some methods require it.
1381     CefRefPtr<CefTaskRunner> task_runner = server->GetTaskRunner();
1382     if (!task_runner->BelongsToCurrentThread()) {
1383       task_runner->PostTask(CefCreateClosureTask(
1384           base::BindOnce(CookieAccessServerHandler::SendResponse, server,
1385                          connection_id, response, response_data)));
1386       return;
1387     }
1388 
1389     int response_code = response->GetStatus();
1390     const CefString& content_type = response->GetMimeType();
1391     int64 content_length = static_cast<int64>(response_data.size());
1392 
1393     CefResponse::HeaderMap extra_headers;
1394     response->GetHeaderMap(extra_headers);
1395 
1396     server->SendHttpResponse(connection_id, response_code, content_type,
1397                              content_length, extra_headers);
1398 
1399     if (content_length != 0) {
1400       server->SendRawData(connection_id, response_data.data(),
1401                           response_data.size());
1402       server->CloseConnection(connection_id);
1403     }
1404 
1405     // The connection should be closed.
1406     EXPECT_FALSE(server->IsValidConnection(connection_id));
1407   }
1408 
RunCompleteCallback()1409   void RunCompleteCallback() {
1410     EXPECT_UI_THREAD();
1411 
1412     EXPECT_FALSE(complete_callback_.is_null());
1413     std::move(complete_callback_).Run();
1414   }
1415 
1416   // Map of URL to Data.
1417   typedef std::map<std::string, CookieAccessData*> ResponseDataMap;
1418   ResponseDataMap data_map_;
1419 
1420   bool initialized_;
1421 
1422   // Only accessed on the UI thread.
1423   base::OnceClosure complete_callback_;
1424 
1425   // After initialization the below members are only accessed on the server
1426   // thread.
1427 
1428   TrackCallback got_server_created_;
1429   TrackCallback got_server_destroyed_;
1430 
1431   int expected_http_request_ct_;
1432   int actual_http_request_ct_;
1433 
1434   std::string request_log_;
1435 
1436   DISALLOW_COPY_AND_ASSIGN(CookieAccessServerHandler);
1437 };
1438 
1439 class CookieAccessTestHandler : public RoutingTestHandler,
1440                                 public CefCookieAccessFilter {
1441  public:
1442   enum TestMode {
1443     ALLOW = 0,
1444     BLOCK_READ = 1 << 0,
1445     BLOCK_WRITE = 1 << 1,
1446     BLOCK_READ_WRITE = BLOCK_READ | BLOCK_WRITE,
1447     ALLOW_NO_FILTER = 1 << 2,
1448 
1449     // Block all cookies using CefRequestContextSettings. Can only be used with
1450     // a non-global request context because it's too late (during test
1451     // execution) to call this method on the global context.
1452     BLOCK_ALL_COOKIES = 1 << 3,
1453 
1454     // Return nullptr from GetResourceRequestHandler. Can only be used in
1455     // combination with the SERVER or SCHEME_HANDLER backend (the
1456     // RESOURCE_HANDLER backend would not be called).
1457     ALLOW_NO_HANDLER = 1 << 4,
1458   };
1459 
1460   enum TestBackend {
1461     // Test an HTTP server backend.
1462     SERVER,
1463 
1464     // Test a custom scheme handler backend.
1465     SCHEME_HANDLER,
1466 
1467     // Test that GetResourceHandler behaves the same as a custom scheme handler.
1468     RESOURCE_HANDLER,
1469   };
1470 
CookieAccessTestHandler(TestMode test_mode,TestBackend test_backend,bool custom_scheme,bool use_global)1471   CookieAccessTestHandler(TestMode test_mode,
1472                           TestBackend test_backend,
1473                           bool custom_scheme,
1474                           bool use_global)
1475       : test_mode_(test_mode),
1476         test_backend_(test_backend),
1477         scheme_(custom_scheme ? kCustomCookieScheme : kCookieAccessScheme),
1478         use_global_(use_global) {
1479     if (test_mode_ == BLOCK_ALL_COOKIES)
1480       CHECK(!use_global_);
1481     else if (test_mode_ == ALLOW_NO_HANDLER)
1482       CHECK_NE(RESOURCE_HANDLER, test_backend_);
1483     if (test_backend_ == SERVER)
1484       CHECK(!custom_scheme);
1485   }
1486 
RunTest()1487   void RunTest() override {
1488     if (use_global_) {
1489       context_ = CefRequestContext::GetGlobalContext();
1490     } else {
1491       // Create the request context that will use an in-memory cache.
1492       CefRequestContextSettings settings;
1493 
1494       const bool block_cookies = (test_mode_ == BLOCK_ALL_COOKIES);
1495       if (scheme_ == kCustomCookieScheme || block_cookies) {
1496         if (!block_cookies) {
1497           CefString(&settings.cookieable_schemes_list) = kCustomCookieScheme;
1498         } else {
1499           settings.cookieable_schemes_exclude_defaults = true;
1500         }
1501       }
1502 
1503       context_ = CefRequestContext::CreateContext(settings, nullptr);
1504     }
1505 
1506     SetTestTimeout();
1507 
1508     cookie_manager_ = context_->GetCookieManager(nullptr);
1509     RunTestSetupContinue();
1510   }
1511 
DestroyTest()1512   void DestroyTest() override {
1513     if (!CefCurrentlyOn(TID_UI)) {
1514       CefPostTask(TID_UI,
1515                   base::BindOnce(&CookieAccessTestHandler::DestroyTest, this));
1516       return;
1517     }
1518 
1519     cookie_manager_ = nullptr;
1520     context_ = nullptr;
1521 
1522     // Got both network requests.
1523     EXPECT_EQ(1, data1_.request_ct_);
1524     EXPECT_EQ(1, data2_.request_ct_);
1525 
1526     if (test_mode_ == ALLOW_NO_FILTER || test_mode_ == ALLOW_NO_HANDLER) {
1527       EXPECT_EQ(0, can_save_cookie1_ct_);
1528       EXPECT_EQ(0, can_send_cookie2_ct_);
1529     } else {
1530       if (test_mode_ == BLOCK_ALL_COOKIES) {
1531         // Never send any cookies.
1532         EXPECT_EQ(0, can_send_cookie2_ct_);
1533         EXPECT_EQ(0, can_save_cookie1_ct_);
1534       } else if (test_mode_ & BLOCK_WRITE) {
1535         // Get 1 calls to CanSendCookie for the 2nd network request due to the
1536         // JS cookie (network cookie is blocked).
1537         EXPECT_EQ(1, can_send_cookie2_ct_);
1538         // Get 1 call to CanSaveCookie for the 1st network request due to the
1539         // network cookie.
1540         EXPECT_EQ(1, can_save_cookie1_ct_);
1541       } else {
1542         // Get 2 calls to CanSendCookie for the 2nd network request due to the
1543         // network cookie + JS cookie.
1544         EXPECT_EQ(2, can_send_cookie2_ct_);
1545         // Get 1 call to CanSaveCookie for the 1st network request due to the
1546         // network cookie.
1547         EXPECT_EQ(1, can_save_cookie1_ct_);
1548       }
1549     }
1550 
1551     if (test_mode_ == BLOCK_ALL_COOKIES) {
1552       // Never get the JS cookie via JS.
1553       EXPECT_EQ(0, cookie_js1_ct_);
1554       EXPECT_EQ(0, cookie_js2_ct_);
1555       EXPECT_EQ(0, cookie_js3_ct_);
1556     } else {
1557       // Always get the JS cookie via JS.
1558       EXPECT_EQ(1, cookie_js1_ct_);
1559       EXPECT_EQ(1, cookie_js2_ct_);
1560       EXPECT_EQ(1, cookie_js3_ct_);
1561     }
1562 
1563     // Only get the net cookie via JS if cookie write was allowed.
1564     if ((test_mode_ & BLOCK_WRITE) || test_mode_ == BLOCK_ALL_COOKIES) {
1565       EXPECT_EQ(0, cookie_net1_ct_);
1566       EXPECT_EQ(0, cookie_net2_ct_);
1567       EXPECT_EQ(0, cookie_net3_ct_);
1568     } else {
1569       EXPECT_EQ(1, cookie_net1_ct_);
1570       EXPECT_EQ(1, cookie_net2_ct_);
1571       EXPECT_EQ(1, cookie_net3_ct_);
1572     }
1573 
1574     // No cookies sent for the 1st network request.
1575     EXPECT_EQ(0, data1_.cookie_js_ct_);
1576     EXPECT_EQ(0, data1_.cookie_net_ct_);
1577 
1578     // 2nd network request...
1579     if ((test_mode_ & BLOCK_READ) || test_mode_ == BLOCK_ALL_COOKIES) {
1580       // No cookies sent if reading was blocked.
1581       EXPECT_EQ(0, data2_.cookie_js_ct_);
1582       EXPECT_EQ(0, data2_.cookie_net_ct_);
1583     } else if (test_mode_ & BLOCK_WRITE) {
1584       // Only JS cookie sent if writing was blocked.
1585       EXPECT_EQ(1, data2_.cookie_js_ct_);
1586       EXPECT_EQ(0, data2_.cookie_net_ct_);
1587     } else {
1588       // All cookies sent.
1589       EXPECT_EQ(1, data2_.cookie_js_ct_);
1590       EXPECT_EQ(1, data2_.cookie_net_ct_);
1591     }
1592 
1593     TestHandler::DestroyTest();
1594   }
1595 
GetCookieAccessFilter(CefRefPtr<CefBrowser> browser,CefRefPtr<CefFrame> frame,CefRefPtr<CefRequest> request)1596   CefRefPtr<CefCookieAccessFilter> GetCookieAccessFilter(
1597       CefRefPtr<CefBrowser> browser,
1598       CefRefPtr<CefFrame> frame,
1599       CefRefPtr<CefRequest> request) override {
1600     EXPECT_IO_THREAD();
1601 
1602     if (test_mode_ == ALLOW_NO_FILTER)
1603       return nullptr;
1604 
1605     return this;
1606   }
1607 
GetResourceRequestHandler(CefRefPtr<CefBrowser> browser,CefRefPtr<CefFrame> frame,CefRefPtr<CefRequest> request,bool is_navigation,bool is_download,const CefString & request_initiator,bool & disable_default_handling)1608   CefRefPtr<CefResourceRequestHandler> GetResourceRequestHandler(
1609       CefRefPtr<CefBrowser> browser,
1610       CefRefPtr<CefFrame> frame,
1611       CefRefPtr<CefRequest> request,
1612       bool is_navigation,
1613       bool is_download,
1614       const CefString& request_initiator,
1615       bool& disable_default_handling) override {
1616     if (test_mode_ == ALLOW_NO_HANDLER)
1617       return nullptr;
1618 
1619     return this;
1620   }
1621 
GetResourceHandler(CefRefPtr<CefBrowser> browser,CefRefPtr<CefFrame> frame,CefRefPtr<CefRequest> request)1622   CefRefPtr<CefResourceHandler> GetResourceHandler(
1623       CefRefPtr<CefBrowser> browser,
1624       CefRefPtr<CefFrame> frame,
1625       CefRefPtr<CefRequest> request) override {
1626     if (test_backend_ == RESOURCE_HANDLER && scheme_factory_) {
1627       return scheme_factory_->Create(browser, frame, scheme_, request);
1628     }
1629 
1630     return nullptr;
1631   }
1632 
CanSendCookie(CefRefPtr<CefBrowser> browser,CefRefPtr<CefFrame> frame,CefRefPtr<CefRequest> request,const CefCookie & cookie)1633   bool CanSendCookie(CefRefPtr<CefBrowser> browser,
1634                      CefRefPtr<CefFrame> frame,
1635                      CefRefPtr<CefRequest> request,
1636                      const CefCookie& cookie) override {
1637     EXPECT_IO_THREAD();
1638 
1639     const std::string& url = request->GetURL();
1640     if (url == GetCookieAccessUrl2(scheme_, test_backend_ == SERVER)) {
1641       can_send_cookie2_ct_++;
1642     } else if (!IgnoreURL(url)) {
1643       ADD_FAILURE() << "Unexpected url: " << url;
1644     }
1645 
1646     return !(test_mode_ & BLOCK_READ);
1647   }
1648 
CanSaveCookie(CefRefPtr<CefBrowser> browser,CefRefPtr<CefFrame> frame,CefRefPtr<CefRequest> request,CefRefPtr<CefResponse> response,const CefCookie & cookie)1649   bool CanSaveCookie(CefRefPtr<CefBrowser> browser,
1650                      CefRefPtr<CefFrame> frame,
1651                      CefRefPtr<CefRequest> request,
1652                      CefRefPtr<CefResponse> response,
1653                      const CefCookie& cookie) override {
1654     EXPECT_IO_THREAD();
1655 
1656     // Expecting the network cookie only.
1657     EXPECT_STREQ("name_net", CefString(&cookie.name).ToString().c_str());
1658     EXPECT_STREQ("value_net", CefString(&cookie.value).ToString().c_str());
1659 
1660     const std::string& url = request->GetURL();
1661     if (url == GetCookieAccessUrl1(scheme_, test_backend_ == SERVER)) {
1662       can_save_cookie1_ct_++;
1663     } else if (!IgnoreURL(url)) {
1664       ADD_FAILURE() << "Unexpected url: " << url;
1665     }
1666 
1667     return !(test_mode_ & BLOCK_WRITE);
1668   }
1669 
OnQuery(CefRefPtr<CefBrowser> browser,CefRefPtr<CefFrame> frame,int64 query_id,const CefString & request,bool persistent,CefRefPtr<Callback> callback)1670   bool OnQuery(CefRefPtr<CefBrowser> browser,
1671                CefRefPtr<CefFrame> frame,
1672                int64 query_id,
1673                const CefString& request,
1674                bool persistent,
1675                CefRefPtr<Callback> callback) override {
1676     const std::string& url = frame->GetURL();
1677     const std::string& cookie_str = request.ToString();
1678     if (url == GetCookieAccessUrl1(scheme_, test_backend_ == SERVER)) {
1679       TestCookieString(cookie_str, cookie_js1_ct_, cookie_net1_ct_);
1680       browser->GetMainFrame()->LoadURL(
1681           GetCookieAccessUrl2(scheme_, test_backend_ == SERVER));
1682     } else if (url == GetCookieAccessUrl2(scheme_, test_backend_ == SERVER)) {
1683       TestCookieString(cookie_str, cookie_js2_ct_, cookie_net2_ct_);
1684       FinishTest();
1685     } else {
1686       ADD_FAILURE() << "Unexpected url: " << url;
1687     }
1688     return true;
1689   }
1690 
1691  private:
AddResponses(CookieAccessResponseHandler * handler)1692   void AddResponses(CookieAccessResponseHandler* handler) {
1693     // 1st request sets a cookie via net response headers and JS, then retrieves
1694     // the cookies via JS.
1695     {
1696       data1_.response = CefResponse::Create();
1697       data1_.response->SetMimeType("text/html");
1698       data1_.response->SetStatus(200);
1699       data1_.response->SetStatusText("OK");
1700 
1701       CefResponse::HeaderMap headerMap;
1702       data1_.response->GetHeaderMap(headerMap);
1703       headerMap.insert(std::make_pair("Set-Cookie", "name_net=value_net"));
1704       data1_.response->SetHeaderMap(headerMap);
1705 
1706       data1_.response_data =
1707           "<html><head>"
1708           "<script>"
1709           "document.cookie='name_js=value_js';"
1710           "window.testQuery({request:document.cookie});"
1711           "</script>"
1712           "</head><body>COOKIE ACCESS TEST 1</body></html>";
1713 
1714       handler->AddResponse(
1715           GetCookieAccessUrl1(scheme_, test_backend_ == SERVER), &data1_);
1716     }
1717 
1718     // 2nd request retrieves the cookies via JS.
1719     {
1720       data2_.response = CefResponse::Create();
1721       data2_.response->SetMimeType("text/html");
1722       data2_.response->SetStatus(200);
1723       data2_.response->SetStatusText("OK");
1724 
1725       data2_.response_data =
1726           "<html><head>"
1727           "<script>"
1728           "window.testQuery({request:document.cookie});"
1729           "</script>"
1730           "</head><body>COOKIE ACCESS TEST 2</body></html>";
1731 
1732       handler->AddResponse(
1733           GetCookieAccessUrl2(scheme_, test_backend_ == SERVER), &data2_);
1734     }
1735   }
1736 
RunTestSetupContinue()1737   void RunTestSetupContinue() {
1738     CefPostTask(
1739         TID_UI,
1740         base::BindOnce(
1741             &CookieAccessTestHandler::StartBackend, this,
1742             base::BindOnce(&CookieAccessTestHandler::RunTestContinue, this)));
1743   }
1744 
StartBackend(base::OnceClosure complete_callback)1745   void StartBackend(base::OnceClosure complete_callback) {
1746     if (test_backend_ == SERVER) {
1747       StartServer(std::move(complete_callback));
1748     } else {
1749       StartSchemeHandler(std::move(complete_callback));
1750     }
1751   }
1752 
StartServer(base::OnceClosure complete_callback)1753   void StartServer(base::OnceClosure complete_callback) {
1754     EXPECT_FALSE(server_handler_);
1755 
1756     server_handler_ = new CookieAccessServerHandler();
1757     AddResponses(server_handler_);
1758     server_handler_->CreateServer(std::move(complete_callback));
1759   }
1760 
StartSchemeHandler(base::OnceClosure complete_callback)1761   void StartSchemeHandler(base::OnceClosure complete_callback) {
1762     // Add the factory registration.
1763     scheme_factory_ = new CookieAccessSchemeHandlerFactory();
1764     AddResponses(scheme_factory_.get());
1765     if (test_backend_ == SCHEME_HANDLER) {
1766       context_->RegisterSchemeHandlerFactory(scheme_, kCookieAccessDomain,
1767                                              scheme_factory_.get());
1768     }
1769 
1770     std::move(complete_callback).Run();
1771   }
1772 
RunTestContinue()1773   void RunTestContinue() {
1774     if (!CefCurrentlyOn(TID_UI)) {
1775       CefPostTask(TID_UI, base::BindOnce(
1776                               &CookieAccessTestHandler::RunTestContinue, this));
1777       return;
1778     }
1779 
1780     CreateBrowser(GetCookieAccessUrl1(scheme_, test_backend_ == SERVER),
1781                   context_);
1782   }
1783 
FinishTest()1784   void FinishTest() {
1785     // Verify that cookies were set correctly.
1786     class TestVisitor : public CefCookieVisitor {
1787      public:
1788       explicit TestVisitor(CookieAccessTestHandler* handler)
1789           : handler_(handler) {}
1790       ~TestVisitor() override {
1791         // Destroy the test.
1792         CefPostTask(
1793             TID_UI,
1794             base::BindOnce(&CookieAccessTestHandler::ShutdownBackend, handler_,
1795                            base::BindOnce(&CookieAccessTestHandler::DestroyTest,
1796                                           handler_)));
1797       }
1798 
1799       bool Visit(const CefCookie& cookie,
1800                  int count,
1801                  int total,
1802                  bool& deleteCookie) override {
1803         const std::string& name = CefString(&cookie.name);
1804         const std::string& value = CefString(&cookie.value);
1805         if (name == "name_js" && value == "value_js")
1806           handler_->cookie_js3_ct_++;
1807         else if (name == "name_net" && value == "value_net")
1808           handler_->cookie_net3_ct_++;
1809 
1810         // Clean up the cookies.
1811         deleteCookie = true;
1812 
1813         return true;
1814       }
1815 
1816      private:
1817       CookieAccessTestHandler* handler_;
1818       IMPLEMENT_REFCOUNTING(TestVisitor);
1819     };
1820 
1821     cookie_manager_->VisitAllCookies(new TestVisitor(this));
1822   }
1823 
ShutdownBackend(base::OnceClosure complete_callback)1824   void ShutdownBackend(base::OnceClosure complete_callback) {
1825     if (test_backend_ == SERVER) {
1826       ShutdownServer(std::move(complete_callback));
1827     } else {
1828       ShutdownSchemeHandler(std::move(complete_callback));
1829     }
1830   }
1831 
ShutdownServer(base::OnceClosure complete_callback)1832   void ShutdownServer(base::OnceClosure complete_callback) {
1833     EXPECT_TRUE(server_handler_);
1834 
1835     // |server_handler_| will delete itself after shutdown.
1836     server_handler_->ShutdownServer(std::move(complete_callback));
1837     server_handler_ = nullptr;
1838   }
1839 
ShutdownSchemeHandler(base::OnceClosure complete_callback)1840   void ShutdownSchemeHandler(base::OnceClosure complete_callback) {
1841     EXPECT_TRUE(scheme_factory_);
1842 
1843     if (test_backend_ == SCHEME_HANDLER) {
1844       context_->RegisterSchemeHandlerFactory(scheme_, kCookieAccessDomain,
1845                                              nullptr);
1846     }
1847     scheme_factory_->Shutdown(std::move(complete_callback));
1848     scheme_factory_ = nullptr;
1849   }
1850 
1851   const TestMode test_mode_;
1852   const TestBackend test_backend_;
1853   const std::string scheme_;
1854   const bool use_global_;
1855   CefRefPtr<CefRequestContext> context_;
1856   CefRefPtr<CefCookieManager> cookie_manager_;
1857 
1858   CookieAccessServerHandler* server_handler_ = nullptr;
1859   CefRefPtr<CookieAccessSchemeHandlerFactory> scheme_factory_;
1860 
1861   CookieAccessData data1_;
1862   CookieAccessData data2_;
1863 
1864   // 1st request.
1865   int can_save_cookie1_ct_ = 0;
1866   int cookie_js1_ct_ = 0;
1867   int cookie_net1_ct_ = 0;
1868 
1869   // 2nd request.
1870   int can_send_cookie2_ct_ = 0;
1871   int cookie_js2_ct_ = 0;
1872   int cookie_net2_ct_ = 0;
1873 
1874   // From cookie manager.
1875   int cookie_js3_ct_ = 0;
1876   int cookie_net3_ct_ = 0;
1877 
1878   DISALLOW_COPY_AND_ASSIGN(CookieAccessTestHandler);
1879   IMPLEMENT_REFCOUNTING(CookieAccessTestHandler);
1880 };
1881 
1882 }  // namespace
1883 
1884 #define ACCESS_TEST(name, test_mode, backend_mode, custom_scheme, use_global) \
1885   TEST(CookieTest, Access##name) {                                            \
1886     CefRefPtr<CookieAccessTestHandler> handler = new CookieAccessTestHandler( \
1887         CookieAccessTestHandler::test_mode,                                   \
1888         CookieAccessTestHandler::backend_mode, custom_scheme, use_global);    \
1889     handler->ExecuteTest();                                                   \
1890     ReleaseAndWaitForDestructor(handler);                                     \
1891   }
1892 
1893 #define ACCESS_TEST_ALL_MODES(name, backend_mode, custom_scheme, use_global) \
1894   ACCESS_TEST(name##Allow, ALLOW, backend_mode, custom_scheme, use_global)   \
1895   ACCESS_TEST(name##AllowNoFilter, ALLOW_NO_FILTER, backend_mode,            \
1896               custom_scheme, use_global)                                     \
1897   ACCESS_TEST(name##BlockRead, BLOCK_READ, backend_mode, custom_scheme,      \
1898               use_global)                                                    \
1899   ACCESS_TEST(name##BlockWrite, BLOCK_WRITE, backend_mode, custom_scheme,    \
1900               use_global)                                                    \
1901   ACCESS_TEST(name##BlockReadWrite, BLOCK_READ_WRITE, backend_mode,          \
1902               custom_scheme, use_global)
1903 
1904 // These tests only work with a non-global context.
1905 #define ACCESS_TEST_BLOCKALLCOOKIES_MODES(name, backend_mode, custom_scheme) \
1906   ACCESS_TEST(name##BlockAllCookies, BLOCK_ALL_COOKIES, backend_mode,        \
1907               custom_scheme, false)
1908 
1909 // These tests only work with SERVER and SCHEME_HANDLER backends.
1910 #define ACCESS_TEST_ALLOWNOHANDLER_MODES(name, backend_mode, custom_scheme) \
1911   ACCESS_TEST(name##GlobalAllowNoHandler, ALLOW_NO_HANDLER, backend_mode,   \
1912               custom_scheme, false)                                         \
1913   ACCESS_TEST(name##InMemoryAllowNoHandler, ALLOW_NO_HANDLER, backend_mode, \
1914               custom_scheme, true)
1915 
1916 #define ACCESS_TEST_CUSTOM(name, backend_mode)                           \
1917   ACCESS_TEST_ALL_MODES(name##CustomGlobal, backend_mode, true, true)    \
1918   ACCESS_TEST_ALL_MODES(name##CustomInMemory, backend_mode, true, false) \
1919   ACCESS_TEST_BLOCKALLCOOKIES_MODES(name##CustomInMemory, backend_mode, true)
1920 
1921 #define ACCESS_TEST_STANDARD(name, backend_mode)                            \
1922   ACCESS_TEST_ALL_MODES(name##StandardGlobal, backend_mode, false, true)    \
1923   ACCESS_TEST_ALL_MODES(name##StandardInMemory, backend_mode, false, false) \
1924   ACCESS_TEST_BLOCKALLCOOKIES_MODES(name##StandardInMemory, backend_mode, false)
1925 
1926 // Server backend only works with standard schemes.
1927 ACCESS_TEST_STANDARD(Server, SERVER)
1928 ACCESS_TEST_ALLOWNOHANDLER_MODES(ServerStandard, SERVER, false)
1929 
1930 // Other backends work with all schemes.
1931 ACCESS_TEST_CUSTOM(Scheme, SCHEME_HANDLER)
1932 ACCESS_TEST_ALLOWNOHANDLER_MODES(SchemeCustom, SCHEME_HANDLER, true)
1933 ACCESS_TEST_STANDARD(Scheme, SCHEME_HANDLER)
1934 ACCESS_TEST_ALLOWNOHANDLER_MODES(SchemeStandard, SCHEME_HANDLER, false)
1935 
1936 ACCESS_TEST_CUSTOM(Resource, RESOURCE_HANDLER)
1937 ACCESS_TEST_STANDARD(Resource, RESOURCE_HANDLER)
1938 
1939 namespace {
1940 
1941 // Tests the behavior of restarting of a network request that sets cookies and
1942 // a network request that includes cookies.
1943 // 1. Begin loading URL1, then restart the request in OnResourceResponse.
1944 //    No cookies are saved.
1945 // 2. Load URL1 successfully. Network and JS cookies are saved.
1946 // 3. Begin loading URL2, then restart the request in OnResourceResponse.
1947 //    Cookies are sent with the request/response.
1948 // 4. Load URL2 successfully. Cookies are sent with the request/response.
1949 class CookieRestartTestHandler : public RoutingTestHandler,
1950                                  public CefCookieAccessFilter {
1951  public:
CookieRestartTestHandler(bool use_global)1952   explicit CookieRestartTestHandler(bool use_global)
1953       : scheme_(kCookieAccessScheme), use_global_(use_global) {}
1954 
RunTest()1955   void RunTest() override {
1956     if (use_global_) {
1957       context_ = CefRequestContext::GetGlobalContext();
1958     } else {
1959       // Create the request context that will use an in-memory cache.
1960       CefRequestContextSettings settings;
1961       context_ = CefRequestContext::CreateContext(settings, nullptr);
1962     }
1963 
1964     cookie_manager_ = context_->GetCookieManager(nullptr);
1965 
1966     SetTestTimeout();
1967     RunTestSetupContinue();
1968   }
1969 
DestroyTest()1970   void DestroyTest() override {
1971     if (!CefCurrentlyOn(TID_UI)) {
1972       CefPostTask(TID_UI,
1973                   base::BindOnce(&CookieRestartTestHandler::DestroyTest, this));
1974       return;
1975     }
1976 
1977     cookie_manager_ = nullptr;
1978     context_ = nullptr;
1979 
1980     // Get 2 network requests for each URL.
1981     EXPECT_EQ(2, data1_.request_ct_);
1982     EXPECT_EQ(2, data2_.request_ct_);
1983 
1984     // Get resource request callbacks for all requests (2 for each URL).
1985     EXPECT_EQ(4, before_resource_load_ct_);
1986     EXPECT_EQ(4, resource_response_ct_);
1987 
1988     // Get JS query callbacks for the successful requests (1 for each URL).
1989     EXPECT_EQ(2, query_ct_);
1990 
1991     // No cookies sent for the URL1 network requests because (a) we don't have
1992     // any cookies set initially and (b) we don't save cookies from the 1st URL1
1993     // request which is restarted.
1994     EXPECT_EQ(0, data1_.cookie_js_ct_);
1995     EXPECT_EQ(0, data1_.cookie_net_ct_);
1996 
1997     // Net and JS cookies sent for both URL2 network requests.
1998     EXPECT_EQ(2, data2_.cookie_js_ct_);
1999     EXPECT_EQ(2, data2_.cookie_net_ct_);
2000 
2001     // 1 call to CanSaveCookie for the net cookie returned by the successful
2002     // URL1 request.
2003     EXPECT_EQ(1, can_save_cookie_ct_);
2004     // 4 calls to CanSendCookie because both net and JS cookies are sent for
2005     // each URL2 request.
2006     EXPECT_EQ(4, can_send_cookie_ct_);
2007 
2008     // Get the net and JS cookies from the JS query for the successful requests
2009     // (1 for each URL).
2010     EXPECT_EQ(1, cookie_js1_ct_);
2011     EXPECT_EQ(1, cookie_net1_ct_);
2012     EXPECT_EQ(1, cookie_js2_ct_);
2013     EXPECT_EQ(1, cookie_net2_ct_);
2014 
2015     // Get the net and JS cookies from the cookie manager at the end.
2016     EXPECT_EQ(1, cookie_manager_js_ct_);
2017     EXPECT_EQ(1, cookie_manager_net_ct_);
2018 
2019     TestHandler::DestroyTest();
2020   }
2021 
GetCookieAccessFilter(CefRefPtr<CefBrowser> browser,CefRefPtr<CefFrame> frame,CefRefPtr<CefRequest> request)2022   CefRefPtr<CefCookieAccessFilter> GetCookieAccessFilter(
2023       CefRefPtr<CefBrowser> browser,
2024       CefRefPtr<CefFrame> frame,
2025       CefRefPtr<CefRequest> request) override {
2026     EXPECT_IO_THREAD();
2027     return this;
2028   }
2029 
GetResourceRequestHandler(CefRefPtr<CefBrowser> browser,CefRefPtr<CefFrame> frame,CefRefPtr<CefRequest> request,bool is_navigation,bool is_download,const CefString & request_initiator,bool & disable_default_handling)2030   CefRefPtr<CefResourceRequestHandler> GetResourceRequestHandler(
2031       CefRefPtr<CefBrowser> browser,
2032       CefRefPtr<CefFrame> frame,
2033       CefRefPtr<CefRequest> request,
2034       bool is_navigation,
2035       bool is_download,
2036       const CefString& request_initiator,
2037       bool& disable_default_handling) override {
2038     return this;
2039   }
2040 
GetResourceHandler(CefRefPtr<CefBrowser> browser,CefRefPtr<CefFrame> frame,CefRefPtr<CefRequest> request)2041   CefRefPtr<CefResourceHandler> GetResourceHandler(
2042       CefRefPtr<CefBrowser> browser,
2043       CefRefPtr<CefFrame> frame,
2044       CefRefPtr<CefRequest> request) override {
2045     return nullptr;
2046   }
2047 
CanSendCookie(CefRefPtr<CefBrowser> browser,CefRefPtr<CefFrame> frame,CefRefPtr<CefRequest> request,const CefCookie & cookie)2048   bool CanSendCookie(CefRefPtr<CefBrowser> browser,
2049                      CefRefPtr<CefFrame> frame,
2050                      CefRefPtr<CefRequest> request,
2051                      const CefCookie& cookie) override {
2052     EXPECT_IO_THREAD();
2053     can_send_cookie_ct_++;
2054 
2055     // Called before the URL2 network requests.
2056     EXPECT_LE(2, before_resource_load_ct_);
2057 
2058     return true;
2059   }
2060 
CanSaveCookie(CefRefPtr<CefBrowser> browser,CefRefPtr<CefFrame> frame,CefRefPtr<CefRequest> request,CefRefPtr<CefResponse> response,const CefCookie & cookie)2061   bool CanSaveCookie(CefRefPtr<CefBrowser> browser,
2062                      CefRefPtr<CefFrame> frame,
2063                      CefRefPtr<CefRequest> request,
2064                      CefRefPtr<CefResponse> response,
2065                      const CefCookie& cookie) override {
2066     EXPECT_IO_THREAD();
2067     can_save_cookie_ct_++;
2068 
2069     // Called after the successful URL1 network request.
2070     EXPECT_EQ(2, before_resource_load_ct_);
2071 
2072     // Expecting the network cookie only.
2073     EXPECT_STREQ("name_net", CefString(&cookie.name).ToString().c_str());
2074     EXPECT_STREQ("value_net", CefString(&cookie.value).ToString().c_str());
2075 
2076     return true;
2077   }
2078 
OnBeforeResourceLoad(CefRefPtr<CefBrowser> browser,CefRefPtr<CefFrame> frame,CefRefPtr<CefRequest> request,CefRefPtr<CefCallback> callback)2079   cef_return_value_t OnBeforeResourceLoad(
2080       CefRefPtr<CefBrowser> browser,
2081       CefRefPtr<CefFrame> frame,
2082       CefRefPtr<CefRequest> request,
2083       CefRefPtr<CefCallback> callback) override {
2084     EXPECT_IO_THREAD();
2085     before_resource_load_ct_++;
2086 
2087     const std::string& url = request->GetURL();
2088 
2089     if (before_resource_load_ct_ <= 2) {
2090       EXPECT_STREQ(GetCookieAccessUrl1(scheme_, true).c_str(), url.c_str());
2091     } else {
2092       EXPECT_STREQ(GetCookieAccessUrl2(scheme_, true).c_str(), url.c_str());
2093     }
2094 
2095     const std::string& cookie_str = request->GetHeaderByName("Cookie");
2096     int cookie_js_ct = 0;
2097     int cookie_net_ct = 0;
2098     TestCookieString(cookie_str, cookie_js_ct, cookie_net_ct);
2099 
2100     // Expect both cookies with the URL2 requests only.
2101     if (before_resource_load_ct_ >= 3) {
2102       EXPECT_EQ(1, cookie_js_ct);
2103       EXPECT_EQ(1, cookie_net_ct);
2104     } else {
2105       EXPECT_EQ(0, cookie_js_ct);
2106       EXPECT_EQ(0, cookie_net_ct);
2107     }
2108 
2109     return RV_CONTINUE;
2110   }
2111 
OnResourceResponse(CefRefPtr<CefBrowser> browser,CefRefPtr<CefFrame> frame,CefRefPtr<CefRequest> request,CefRefPtr<CefResponse> response)2112   bool OnResourceResponse(CefRefPtr<CefBrowser> browser,
2113                           CefRefPtr<CefFrame> frame,
2114                           CefRefPtr<CefRequest> request,
2115                           CefRefPtr<CefResponse> response) override {
2116     EXPECT_IO_THREAD();
2117     resource_response_ct_++;
2118 
2119     const std::string& url = request->GetURL();
2120     const std::string& set_cookie_str = response->GetHeaderByName("Set-Cookie");
2121 
2122     // Expect the network cookie with URL1 requests only.
2123     if (resource_response_ct_ <= 2) {
2124       EXPECT_STREQ(GetCookieAccessUrl1(scheme_, true).c_str(), url.c_str());
2125       EXPECT_STREQ("name_net=value_net", set_cookie_str.c_str());
2126     } else {
2127       EXPECT_STREQ(GetCookieAccessUrl2(scheme_, true).c_str(), url.c_str());
2128       EXPECT_TRUE(set_cookie_str.empty());
2129     }
2130 
2131     if (resource_response_ct_ == 1 || resource_response_ct_ == 3) {
2132       // Restart the request loading this data.
2133       request->SetHeaderByName("X-Custom-Header", "value", false);
2134       return true;
2135     }
2136     return false;
2137   }
2138 
OnQuery(CefRefPtr<CefBrowser> browser,CefRefPtr<CefFrame> frame,int64 query_id,const CefString & request,bool persistent,CefRefPtr<Callback> callback)2139   bool OnQuery(CefRefPtr<CefBrowser> browser,
2140                CefRefPtr<CefFrame> frame,
2141                int64 query_id,
2142                const CefString& request,
2143                bool persistent,
2144                CefRefPtr<Callback> callback) override {
2145     query_ct_++;
2146 
2147     const std::string& url = frame->GetURL();
2148     const std::string& cookie_str = request.ToString();
2149     if (url == GetCookieAccessUrl1(scheme_, true)) {
2150       TestCookieString(cookie_str, cookie_js1_ct_, cookie_net1_ct_);
2151       browser->GetMainFrame()->LoadURL(GetCookieAccessUrl2(scheme_, true));
2152     } else if (url == GetCookieAccessUrl2(scheme_, true)) {
2153       TestCookieString(cookie_str, cookie_js2_ct_, cookie_net2_ct_);
2154       FinishTest();
2155     } else {
2156       ADD_FAILURE() << "Unexpected url: " << url;
2157     }
2158     return true;
2159   }
2160 
2161  private:
AddResponses(CookieAccessResponseHandler * handler)2162   void AddResponses(CookieAccessResponseHandler* handler) {
2163     // Sets a cookie via net response headers and JS, then retrieves the cookies
2164     // via JS.
2165     {
2166       data1_.response = CefResponse::Create();
2167       data1_.response->SetMimeType("text/html");
2168       data1_.response->SetStatus(200);
2169       data1_.response->SetStatusText("OK");
2170 
2171       CefResponse::HeaderMap headerMap;
2172       data1_.response->GetHeaderMap(headerMap);
2173       headerMap.insert(std::make_pair("Set-Cookie", "name_net=value_net"));
2174       data1_.response->SetHeaderMap(headerMap);
2175 
2176       data1_.response_data =
2177           "<html><head>"
2178           "<script>"
2179           "document.cookie='name_js=value_js';"
2180           "window.testQuery({request:document.cookie});"
2181           "</script>"
2182           "</head><body>COOKIE RESTART TEST1</body></html>";
2183 
2184       handler->AddResponse(GetCookieAccessUrl1(scheme_, true), &data1_);
2185     }
2186 
2187     // Retrieves the cookies via JS.
2188     {
2189       data2_.response = CefResponse::Create();
2190       data2_.response->SetMimeType("text/html");
2191       data2_.response->SetStatus(200);
2192       data2_.response->SetStatusText("OK");
2193 
2194       data2_.response_data =
2195           "<html><head>"
2196           "<script>"
2197           "window.testQuery({request:document.cookie});"
2198           "</script>"
2199           "</head><body>COOKIE RESTART TEST2</body></html>";
2200 
2201       handler->AddResponse(GetCookieAccessUrl2(scheme_, true), &data2_);
2202     }
2203   }
2204 
RunTestSetupContinue()2205   void RunTestSetupContinue() {
2206     CefPostTask(
2207         TID_UI,
2208         base::BindOnce(
2209             &CookieRestartTestHandler::StartServer, this,
2210             base::BindOnce(&CookieRestartTestHandler::RunTestContinue, this)));
2211   }
2212 
StartServer(base::OnceClosure complete_callback)2213   void StartServer(base::OnceClosure complete_callback) {
2214     EXPECT_FALSE(server_handler_);
2215 
2216     server_handler_ = new CookieAccessServerHandler();
2217     AddResponses(server_handler_);
2218     // 2 requests for each URL.
2219     server_handler_->SetExpectedRequestCount(4);
2220     server_handler_->CreateServer(std::move(complete_callback));
2221   }
2222 
RunTestContinue()2223   void RunTestContinue() {
2224     if (!CefCurrentlyOn(TID_UI)) {
2225       CefPostTask(
2226           TID_UI,
2227           base::BindOnce(&CookieRestartTestHandler::RunTestContinue, this));
2228       return;
2229     }
2230 
2231     CreateBrowser(GetCookieAccessUrl1(scheme_, true), context_);
2232   }
2233 
FinishTest()2234   void FinishTest() {
2235     // Verify that cookies were set correctly.
2236     class TestVisitor : public CefCookieVisitor {
2237      public:
2238       explicit TestVisitor(CookieRestartTestHandler* handler)
2239           : handler_(handler) {}
2240       ~TestVisitor() override {
2241         // Destroy the test.
2242         CefPostTask(TID_UI,
2243                     base::BindOnce(
2244                         &CookieRestartTestHandler::ShutdownServer, handler_,
2245                         base::BindOnce(&CookieRestartTestHandler::DestroyTest,
2246                                        handler_)));
2247       }
2248 
2249       bool Visit(const CefCookie& cookie,
2250                  int count,
2251                  int total,
2252                  bool& deleteCookie) override {
2253         const std::string& name = CefString(&cookie.name);
2254         const std::string& value = CefString(&cookie.value);
2255         if (name == "name_js" && value == "value_js")
2256           handler_->cookie_manager_js_ct_++;
2257         else if (name == "name_net" && value == "value_net")
2258           handler_->cookie_manager_net_ct_++;
2259 
2260         // Clean up the cookies.
2261         deleteCookie = true;
2262 
2263         return true;
2264       }
2265 
2266      private:
2267       CookieRestartTestHandler* handler_;
2268       IMPLEMENT_REFCOUNTING(TestVisitor);
2269     };
2270 
2271     cookie_manager_->VisitAllCookies(new TestVisitor(this));
2272   }
2273 
ShutdownServer(base::OnceClosure complete_callback)2274   void ShutdownServer(base::OnceClosure complete_callback) {
2275     EXPECT_TRUE(server_handler_);
2276 
2277     // |server_handler_| will delete itself after shutdown.
2278     server_handler_->ShutdownServer(std::move(complete_callback));
2279     server_handler_ = nullptr;
2280   }
2281 
2282   const std::string scheme_;
2283   const bool use_global_;
2284   CefRefPtr<CefRequestContext> context_;
2285   CefRefPtr<CefCookieManager> cookie_manager_;
2286 
2287   CookieAccessServerHandler* server_handler_ = nullptr;
2288 
2289   CookieAccessData data1_;
2290   CookieAccessData data2_;
2291 
2292   int before_resource_load_ct_ = 0;
2293   int resource_response_ct_ = 0;
2294   int query_ct_ = 0;
2295 
2296   // From network requests.
2297   int can_save_cookie_ct_ = 0;
2298   int can_send_cookie_ct_ = 0;
2299   int cookie_js1_ct_ = 0;
2300   int cookie_net1_ct_ = 0;
2301   int cookie_js2_ct_ = 0;
2302   int cookie_net2_ct_ = 0;
2303 
2304   // From cookie manager.
2305   int cookie_manager_js_ct_ = 0;
2306   int cookie_manager_net_ct_ = 0;
2307 
2308   DISALLOW_COPY_AND_ASSIGN(CookieRestartTestHandler);
2309   IMPLEMENT_REFCOUNTING(CookieRestartTestHandler);
2310 };
2311 
2312 }  // namespace
2313 
TEST(CookieTest,RestartGlobal)2314 TEST(CookieTest, RestartGlobal) {
2315   CefRefPtr<CookieRestartTestHandler> handler =
2316       new CookieRestartTestHandler(true);
2317   handler->ExecuteTest();
2318   ReleaseAndWaitForDestructor(handler);
2319 }
2320 
TEST(CookieTest,RestartInMemory)2321 TEST(CookieTest, RestartInMemory) {
2322   CefRefPtr<CookieRestartTestHandler> handler =
2323       new CookieRestartTestHandler(false);
2324   handler->ExecuteTest();
2325   ReleaseAndWaitForDestructor(handler);
2326 }
2327 
2328 // Entry point for registering custom schemes.
2329 // Called from client_app_delegates.cc.
RegisterCookieCustomSchemes(CefRawPtr<CefSchemeRegistrar> registrar)2330 void RegisterCookieCustomSchemes(CefRawPtr<CefSchemeRegistrar> registrar) {
2331   // Used by GetCookieManagerCustom* tests.
2332   registrar->AddCustomScheme(
2333       kCustomCookieScheme,
2334       CEF_SCHEME_OPTION_STANDARD | CEF_SCHEME_OPTION_CORS_ENABLED);
2335 }
2336 
2337 // Entry point for registering cookieable schemes.
2338 // Called from client_app_delegates.cc.
RegisterCookieCookieableSchemes(std::vector<std::string> & cookieable_schemes)2339 void RegisterCookieCookieableSchemes(
2340     std::vector<std::string>& cookieable_schemes) {
2341   // Used by GetCookieManagerCustom* tests.
2342   cookieable_schemes.push_back(kCustomCookieScheme);
2343 }
2344