1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #ifndef NET_COOKIES_COOKIE_STORE_UNITTEST_H_
6 #define NET_COOKIES_COOKIE_STORE_UNITTEST_H_
9 #include "base/location.h"
10 #include "base/message_loop/message_loop.h"
11 #include "base/single_thread_task_runner.h"
12 #include "base/strings/string_tokenizer.h"
13 #include "base/thread_task_runner_handle.h"
14 #include "base/threading/thread.h"
15 #include "net/cookies/cookie_monster.h"
16 #include "net/cookies/cookie_store.h"
17 #include "net/cookies/cookie_store_test_callbacks.h"
18 #include "testing/gtest/include/gtest/gtest.h"
22 #include "base/ios/ios_util.h"
25 // This file declares unittest templates that can be used to test common
26 // behavior of any CookieStore implementation.
27 // See cookie_monster_unittest.cc for an example of an implementation.
33 const int kTimeout
= 1000;
35 const char kUrlFtp
[] = "ftp://ftp.google.izzle/";
36 const char kUrlGoogle
[] = "http://www.google.izzle";
37 const char kUrlGoogleFoo
[] = "http://www.google.izzle/foo";
38 const char kUrlGoogleBar
[] = "http://www.google.izzle/bar";
39 const char kUrlGoogleSecure
[] = "https://www.google.izzle";
40 const char kUrlGoogleWebSocket
[] = "ws://www.google.izzle";
41 const char kUrlGoogleWebSocketSecure
[] = "wss://www.google.izzle";
42 const char kValidCookieLine
[] = "A=B; path=/";
43 const char kValidDomainCookieLine
[] = "A=B; path=/; domain=google.izzle";
45 // The CookieStoreTestTraits must have the following members:
46 // struct CookieStoreTestTraits {
47 // // Factory function.
48 // static scoped_refptr<CookieStore> Create();
50 // // The cookie store is a CookieMonster. Only used to test
51 // // GetCookieMonster().
52 // static const bool is_cookie_monster;
54 // // The cookie store supports cookies with the exclude_httponly() option.
55 // static const bool supports_http_only;
57 // // The cookie store is able to make the difference between the ".com"
58 // // and the "com" domains.
59 // static const bool supports_non_dotted_domains;
61 // // The cookie store handles the domains with trailing dots (such as "com.")
63 // static const bool supports_trailing_dots;
65 // // The cookie store rejects cookies for invalid schemes such as ftp.
66 // static const bool filters_schemes;
68 // // The cookie store has a bug happening when a path is a substring of
70 // static const bool has_path_prefix_bug;
72 // // Time to wait between two cookie insertions to ensure that cookies have
73 // // different creation times.
74 // static const int creation_time_granularity_in_ms;
77 template <class CookieStoreTestTraits
>
78 class CookieStoreTest
: public testing::Test
{
81 : url_google_(kUrlGoogle
),
82 url_google_secure_(kUrlGoogleSecure
),
83 url_google_foo_(kUrlGoogleFoo
),
84 url_google_bar_(kUrlGoogleBar
) {
85 // This test may be used outside of the net test suite, and thus may not
86 // have a message loop.
87 if (!base::MessageLoop::current())
88 message_loop_
.reset(new base::MessageLoop
);
89 weak_factory_
.reset(new base::WeakPtrFactory
<base::MessageLoop
>(
90 base::MessageLoop::current()));
93 // Helper methods for the asynchronous Cookie Store API that call the
94 // asynchronous method and then pump the loop until the callback is invoked,
95 // finally returning the value.
97 std::string
GetCookies(CookieStore
* cs
, const GURL
& url
) {
99 CookieOptions options
;
100 if (!CookieStoreTestTraits::supports_http_only
)
101 options
.set_include_httponly();
102 StringResultCookieCallback callback
;
103 cs
->GetCookiesWithOptionsAsync(
105 base::Bind(&StringResultCookieCallback::Run
,
106 base::Unretained(&callback
)));
108 EXPECT_TRUE(callback
.did_run());
109 return callback
.result();
112 std::string
GetCookiesWithOptions(CookieStore
* cs
,
114 const CookieOptions
& options
) {
116 StringResultCookieCallback callback
;
117 cs
->GetCookiesWithOptionsAsync(
118 url
, options
, base::Bind(&StringResultCookieCallback::Run
,
119 base::Unretained(&callback
)));
121 EXPECT_TRUE(callback
.did_run());
122 return callback
.result();
125 bool SetCookieWithOptions(CookieStore
* cs
,
127 const std::string
& cookie_line
,
128 const CookieOptions
& options
) {
130 ResultSavingCookieCallback
<bool> callback
;
131 cs
->SetCookieWithOptionsAsync(
132 url
, cookie_line
, options
,
134 &ResultSavingCookieCallback
<bool>::Run
,
135 base::Unretained(&callback
)));
137 EXPECT_TRUE(callback
.did_run());
138 return callback
.result();
141 bool SetCookieWithServerTime(CookieStore
* cs
,
143 const std::string
& cookie_line
,
144 const base::Time
& server_time
) {
145 CookieOptions options
;
146 if (!CookieStoreTestTraits::supports_http_only
)
147 options
.set_include_httponly();
148 options
.set_server_time(server_time
);
149 return SetCookieWithOptions(cs
, url
, cookie_line
, options
);
152 bool SetCookie(CookieStore
* cs
,
154 const std::string
& cookie_line
) {
155 CookieOptions options
;
156 if (!CookieStoreTestTraits::supports_http_only
)
157 options
.set_include_httponly();
158 return SetCookieWithOptions(cs
, url
, cookie_line
, options
);
161 void DeleteCookie(CookieStore
* cs
,
163 const std::string
& cookie_name
) {
165 NoResultCookieCallback callback
;
166 cs
->DeleteCookieAsync(
168 base::Bind(&NoResultCookieCallback::Run
, base::Unretained(&callback
)));
170 EXPECT_TRUE(callback
.did_run());
173 int DeleteCreatedBetween(CookieStore
* cs
,
174 const base::Time
& delete_begin
,
175 const base::Time
& delete_end
) {
177 ResultSavingCookieCallback
<int> callback
;
178 cs
->DeleteAllCreatedBetweenAsync(
179 delete_begin
, delete_end
,
181 &ResultSavingCookieCallback
<int>::Run
,
182 base::Unretained(&callback
)));
184 EXPECT_TRUE(callback
.did_run());
185 return callback
.result();
188 int DeleteAllCreatedBetweenForHost(CookieStore
* cs
,
189 const base::Time delete_begin
,
190 const base::Time delete_end
,
193 ResultSavingCookieCallback
<int> callback
;
194 cs
->DeleteAllCreatedBetweenForHostAsync(
195 delete_begin
, delete_end
, url
,
197 &ResultSavingCookieCallback
<int>::Run
,
198 base::Unretained(&callback
)));
200 EXPECT_TRUE(callback
.did_run());
201 return callback
.result();
204 int DeleteSessionCookies(CookieStore
* cs
) {
206 ResultSavingCookieCallback
<int> callback
;
207 cs
->DeleteSessionCookiesAsync(
209 &ResultSavingCookieCallback
<int>::Run
,
210 base::Unretained(&callback
)));
212 EXPECT_TRUE(callback
.did_run());
213 return callback
.result();
216 void RunFor(int ms
) {
217 // Runs the test thread message loop for up to |ms| milliseconds.
218 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
220 base::Bind(&base::MessageLoop::Quit
, weak_factory_
->GetWeakPtr()),
221 base::TimeDelta::FromMilliseconds(ms
));
222 base::MessageLoop::current()->Run();
223 weak_factory_
->InvalidateWeakPtrs();
226 scoped_refptr
<CookieStore
> GetCookieStore() {
227 return CookieStoreTestTraits::Create();
230 // Compares two cookie lines.
231 void MatchCookieLines(const std::string
& line1
, const std::string
& line2
) {
232 EXPECT_EQ(TokenizeCookieLine(line1
), TokenizeCookieLine(line2
));
235 // Check the cookie line by polling until equality or a timeout is reached.
236 void MatchCookieLineWithTimeout(CookieStore
* cs
,
238 const std::string
& line
) {
239 std::string cookies
= GetCookies(cs
, url
);
240 bool matched
= (TokenizeCookieLine(line
) == TokenizeCookieLine(cookies
));
241 base::Time polling_end_date
= base::Time::Now() +
242 base::TimeDelta::FromMilliseconds(
243 CookieStoreTestTraits::creation_time_granularity_in_ms
);
245 while (!matched
&& base::Time::Now() <= polling_end_date
) {
246 base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(10));
247 cookies
= GetCookies(cs
, url
);
248 matched
= (TokenizeCookieLine(line
) == TokenizeCookieLine(cookies
));
251 EXPECT_TRUE(matched
) << "\"" << cookies
252 << "\" does not match \"" << line
<< "\"";
256 GURL url_google_secure_
;
257 GURL url_google_foo_
;
258 GURL url_google_bar_
;
260 scoped_ptr
<base::WeakPtrFactory
<base::MessageLoop
> > weak_factory_
;
261 scoped_ptr
<base::MessageLoop
> message_loop_
;
264 // Returns a set of strings of type "name=value". Fails in case of duplicate.
265 std::set
<std::string
> TokenizeCookieLine(const std::string
& line
) {
266 std::set
<std::string
> tokens
;
267 base::StringTokenizer
tokenizer(line
, " ;");
268 while (tokenizer
.GetNext())
269 EXPECT_TRUE(tokens
.insert(tokenizer
.token()).second
);
274 TYPED_TEST_CASE_P(CookieStoreTest
);
276 TYPED_TEST_P(CookieStoreTest
, TypeTest
) {
277 scoped_refptr
<CookieStore
> cs(this->GetCookieStore());
278 EXPECT_EQ(cs
->GetCookieMonster(),
279 (TypeParam::is_cookie_monster
) ?
280 static_cast<CookieMonster
*>(cs
.get()) : NULL
);
283 TYPED_TEST_P(CookieStoreTest
, DomainTest
) {
284 scoped_refptr
<CookieStore
> cs(this->GetCookieStore());
285 EXPECT_TRUE(this->SetCookie(cs
.get(), this->url_google_
, "A=B"));
286 this->MatchCookieLines("A=B", this->GetCookies(cs
.get(), this->url_google_
));
287 EXPECT_TRUE(this->SetCookie(
288 cs
.get(), this->url_google_
, "C=D; domain=.google.izzle"));
289 this->MatchCookieLines("A=B; C=D",
290 this->GetCookies(cs
.get(), this->url_google_
));
292 // Verify that A=B was set as a host cookie rather than a domain
293 // cookie -- should not be accessible from a sub sub-domain.
294 this->MatchCookieLines(
295 "C=D", this->GetCookies(cs
.get(), GURL("http://foo.www.google.izzle")));
297 // Test and make sure we find domain cookies on the same domain.
298 EXPECT_TRUE(this->SetCookie(
299 cs
.get(), this->url_google_
, "E=F; domain=.www.google.izzle"));
300 this->MatchCookieLines("A=B; C=D; E=F",
301 this->GetCookies(cs
.get(), this->url_google_
));
303 // Test setting a domain= that doesn't start w/ a dot, should
304 // treat it as a domain cookie, as if there was a pre-pended dot.
305 EXPECT_TRUE(this->SetCookie(
306 cs
.get(), this->url_google_
, "G=H; domain=www.google.izzle"));
307 this->MatchCookieLines("A=B; C=D; E=F; G=H",
308 this->GetCookies(cs
.get(), this->url_google_
));
310 // Test domain enforcement, should fail on a sub-domain or something too deep.
312 this->SetCookie(cs
.get(), this->url_google_
, "I=J; domain=.izzle"));
313 this->MatchCookieLines(std::string(),
314 this->GetCookies(cs
.get(), GURL("http://a.izzle")));
315 EXPECT_FALSE(this->SetCookie(
316 cs
.get(), this->url_google_
, "K=L; domain=.bla.www.google.izzle"));
317 this->MatchCookieLines(
319 this->GetCookies(cs
.get(), GURL("http://bla.www.google.izzle")));
320 this->MatchCookieLines("A=B; C=D; E=F; G=H",
321 this->GetCookies(cs
.get(), this->url_google_
));
324 // FireFox recognizes domains containing trailing periods as valid.
325 // IE and Safari do not. Assert the expected policy here.
326 TYPED_TEST_P(CookieStoreTest
, DomainWithTrailingDotTest
) {
327 scoped_refptr
<CookieStore
> cs(this->GetCookieStore());
328 EXPECT_FALSE(this->SetCookie(
329 cs
.get(), this->url_google_
, "a=1; domain=.www.google.com."));
330 EXPECT_FALSE(this->SetCookie(
331 cs
.get(), this->url_google_
, "b=2; domain=.www.google.com.."));
332 this->MatchCookieLines(std::string(),
333 this->GetCookies(cs
.get(), this->url_google_
));
336 // Test that cookies can bet set on higher level domains.
337 // http://b/issue?id=896491
338 TYPED_TEST_P(CookieStoreTest
, ValidSubdomainTest
) {
339 scoped_refptr
<CookieStore
> cs(this->GetCookieStore());
340 GURL
url_abcd("http://a.b.c.d.com");
341 GURL
url_bcd("http://b.c.d.com");
342 GURL
url_cd("http://c.d.com");
343 GURL
url_d("http://d.com");
345 EXPECT_TRUE(this->SetCookie(cs
.get(), url_abcd
, "a=1; domain=.a.b.c.d.com"));
346 EXPECT_TRUE(this->SetCookie(cs
.get(), url_abcd
, "b=2; domain=.b.c.d.com"));
347 EXPECT_TRUE(this->SetCookie(cs
.get(), url_abcd
, "c=3; domain=.c.d.com"));
348 EXPECT_TRUE(this->SetCookie(cs
.get(), url_abcd
, "d=4; domain=.d.com"));
350 this->MatchCookieLines("a=1; b=2; c=3; d=4",
351 this->GetCookies(cs
.get(), url_abcd
));
352 this->MatchCookieLines("b=2; c=3; d=4", this->GetCookies(cs
.get(), url_bcd
));
353 this->MatchCookieLines("c=3; d=4", this->GetCookies(cs
.get(), url_cd
));
354 this->MatchCookieLines("d=4", this->GetCookies(cs
.get(), url_d
));
356 // Check that the same cookie can exist on different sub-domains.
357 EXPECT_TRUE(this->SetCookie(cs
.get(), url_bcd
, "X=bcd; domain=.b.c.d.com"));
358 EXPECT_TRUE(this->SetCookie(cs
.get(), url_bcd
, "X=cd; domain=.c.d.com"));
359 this->MatchCookieLines("b=2; c=3; d=4; X=bcd; X=cd",
360 this->GetCookies(cs
.get(), url_bcd
));
361 this->MatchCookieLines("c=3; d=4; X=cd", this->GetCookies(cs
.get(), url_cd
));
364 // Test that setting a cookie which specifies an invalid domain has
365 // no side-effect. An invalid domain in this context is one which does
366 // not match the originating domain.
367 // http://b/issue?id=896472
368 TYPED_TEST_P(CookieStoreTest
, InvalidDomainTest
) {
370 scoped_refptr
<CookieStore
> cs(this->GetCookieStore());
371 GURL
url_foobar("http://foo.bar.com");
373 // More specific sub-domain than allowed.
375 this->SetCookie(cs
.get(), url_foobar
, "a=1; domain=.yo.foo.bar.com"));
377 EXPECT_FALSE(this->SetCookie(cs
.get(), url_foobar
, "b=2; domain=.foo.com"));
379 this->SetCookie(cs
.get(), url_foobar
, "c=3; domain=.bar.foo.com"));
381 // Different TLD, but the rest is a substring.
383 this->SetCookie(cs
.get(), url_foobar
, "d=4; domain=.foo.bar.com.net"));
385 // A substring that isn't really a parent domain.
386 EXPECT_FALSE(this->SetCookie(cs
.get(), url_foobar
, "e=5; domain=ar.com"));
388 // Completely invalid domains:
389 EXPECT_FALSE(this->SetCookie(cs
.get(), url_foobar
, "f=6; domain=."));
390 EXPECT_FALSE(this->SetCookie(cs
.get(), url_foobar
, "g=7; domain=/"));
391 EXPECT_FALSE(this->SetCookie(
392 cs
.get(), url_foobar
, "h=8; domain=http://foo.bar.com"));
394 this->SetCookie(cs
.get(), url_foobar
, "i=9; domain=..foo.bar.com"));
396 this->SetCookie(cs
.get(), url_foobar
, "j=10; domain=..bar.com"));
398 // Make sure there isn't something quirky in the domain canonicalization
399 // that supports full URL semantics.
400 EXPECT_FALSE(this->SetCookie(
401 cs
.get(), url_foobar
, "k=11; domain=.foo.bar.com?blah"));
402 EXPECT_FALSE(this->SetCookie(
403 cs
.get(), url_foobar
, "l=12; domain=.foo.bar.com/blah"));
405 this->SetCookie(cs
.get(), url_foobar
, "m=13; domain=.foo.bar.com:80"));
407 this->SetCookie(cs
.get(), url_foobar
, "n=14; domain=.foo.bar.com:"));
409 this->SetCookie(cs
.get(), url_foobar
, "o=15; domain=.foo.bar.com#sup"));
411 this->MatchCookieLines(std::string(),
412 this->GetCookies(cs
.get(), url_foobar
));
416 // Make sure the cookie code hasn't gotten its subdomain string handling
417 // reversed, missed a suffix check, etc. It's important here that the two
418 // hosts below have the same domain + registry.
419 scoped_refptr
<CookieStore
> cs(this->GetCookieStore());
420 GURL
url_foocom("http://foo.com.com");
422 this->SetCookie(cs
.get(), url_foocom
, "a=1; domain=.foo.com.com.com"));
423 this->MatchCookieLines(std::string(),
424 this->GetCookies(cs
.get(), url_foocom
));
428 // Test the behavior of omitting dot prefix from domain, should
429 // function the same as FireFox.
430 // http://b/issue?id=889898
431 TYPED_TEST_P(CookieStoreTest
, DomainWithoutLeadingDotTest
) {
432 { // The omission of dot results in setting a domain cookie.
433 scoped_refptr
<CookieStore
> cs(this->GetCookieStore());
434 GURL
url_hosted("http://manage.hosted.filefront.com");
435 GURL
url_filefront("http://www.filefront.com");
437 this->SetCookie(cs
.get(), url_hosted
, "sawAd=1; domain=filefront.com"));
438 this->MatchCookieLines("sawAd=1", this->GetCookies(cs
.get(), url_hosted
));
439 this->MatchCookieLines("sawAd=1",
440 this->GetCookies(cs
.get(), url_filefront
));
443 { // Even when the domains match exactly, don't consider it host cookie.
444 scoped_refptr
<CookieStore
> cs(this->GetCookieStore());
445 GURL
url("http://www.google.com");
446 EXPECT_TRUE(this->SetCookie(cs
.get(), url
, "a=1; domain=www.google.com"));
447 this->MatchCookieLines("a=1", this->GetCookies(cs
.get(), url
));
448 this->MatchCookieLines(
449 "a=1", this->GetCookies(cs
.get(), GURL("http://sub.www.google.com")));
450 this->MatchCookieLines(
452 this->GetCookies(cs
.get(), GURL("http://something-else.com")));
456 // Test that the domain specified in cookie string is treated case-insensitive
457 // http://b/issue?id=896475.
458 TYPED_TEST_P(CookieStoreTest
, CaseInsensitiveDomainTest
) {
459 scoped_refptr
<CookieStore
> cs(this->GetCookieStore());
460 GURL
url("http://www.google.com");
461 EXPECT_TRUE(this->SetCookie(cs
.get(), url
, "a=1; domain=.GOOGLE.COM"));
462 EXPECT_TRUE(this->SetCookie(cs
.get(), url
, "b=2; domain=.wWw.gOOgLE.coM"));
463 this->MatchCookieLines("a=1; b=2", this->GetCookies(cs
.get(), url
));
466 TYPED_TEST_P(CookieStoreTest
, TestIpAddress
) {
467 GURL
url_ip("http://1.2.3.4/weee");
469 scoped_refptr
<CookieStore
> cs(this->GetCookieStore());
470 EXPECT_TRUE(this->SetCookie(cs
.get(), url_ip
, kValidCookieLine
));
471 this->MatchCookieLines("A=B", this->GetCookies(cs
.get(), url_ip
));
474 { // IP addresses should not be able to set domain cookies.
475 scoped_refptr
<CookieStore
> cs(this->GetCookieStore());
476 EXPECT_FALSE(this->SetCookie(cs
.get(), url_ip
, "b=2; domain=.1.2.3.4"));
477 EXPECT_FALSE(this->SetCookie(cs
.get(), url_ip
, "c=3; domain=.3.4"));
478 this->MatchCookieLines(std::string(), this->GetCookies(cs
.get(), url_ip
));
479 // It should be allowed to set a cookie if domain= matches the IP address
480 // exactly. This matches IE/Firefox, even though it seems a bit wrong.
481 EXPECT_FALSE(this->SetCookie(cs
.get(), url_ip
, "b=2; domain=1.2.3.3"));
482 this->MatchCookieLines(std::string(), this->GetCookies(cs
.get(), url_ip
));
483 EXPECT_TRUE(this->SetCookie(cs
.get(), url_ip
, "b=2; domain=1.2.3.4"));
484 this->MatchCookieLines("b=2", this->GetCookies(cs
.get(), url_ip
));
488 // Test host cookies, and setting of cookies on TLD.
489 TYPED_TEST_P(CookieStoreTest
, TestNonDottedAndTLD
) {
491 // TODO(ellyjones): thoses tests fails with iOS 9, disabled.
492 // Tracked by http://crbug.com/516603 issue.
493 if (!TypeParam::supports_non_dotted_domains
&&
494 base::ios::IsRunningOnIOS9OrLater()) {
500 scoped_refptr
<CookieStore
> cs(this->GetCookieStore());
501 GURL
url("http://com/");
502 // Allow setting on "com", (but only as a host cookie).
503 EXPECT_TRUE(this->SetCookie(cs
.get(), url
, "a=1"));
504 EXPECT_FALSE(this->SetCookie(cs
.get(), url
, "b=2; domain=.com"));
505 EXPECT_FALSE(this->SetCookie(cs
.get(), url
, "c=3; domain=com"));
506 this->MatchCookieLines("a=1", this->GetCookies(cs
.get(), url
));
507 // Make sure it doesn't show up for a normal .com, it should be a host
508 // not a domain cookie.
509 this->MatchCookieLines(
511 this->GetCookies(cs
.get(), GURL("http://hopefully-no-cookies.com/")));
512 if (TypeParam::supports_non_dotted_domains
) {
513 this->MatchCookieLines(std::string(),
514 this->GetCookies(cs
.get(), GURL("http://.com/")));
519 // http://com. should be treated the same as http://com.
520 scoped_refptr
<CookieStore
> cs(this->GetCookieStore());
521 GURL
url("http://com./index.html");
522 if (TypeParam::supports_trailing_dots
) {
523 EXPECT_TRUE(this->SetCookie(cs
.get(), url
, "a=1"));
524 this->MatchCookieLines("a=1", this->GetCookies(cs
.get(), url
));
525 this->MatchCookieLines(
527 this->GetCookies(cs
.get(),
528 GURL("http://hopefully-no-cookies.com./")));
530 EXPECT_FALSE(this->SetCookie(cs
.get(), url
, "a=1"));
534 { // Should not be able to set host cookie from a subdomain.
535 scoped_refptr
<CookieStore
> cs(this->GetCookieStore());
536 GURL
url("http://a.b");
537 EXPECT_FALSE(this->SetCookie(cs
.get(), url
, "a=1; domain=.b"));
538 EXPECT_FALSE(this->SetCookie(cs
.get(), url
, "b=2; domain=b"));
539 this->MatchCookieLines(std::string(), this->GetCookies(cs
.get(), url
));
542 { // Same test as above, but explicitly on a known TLD (com).
543 scoped_refptr
<CookieStore
> cs(this->GetCookieStore());
544 GURL
url("http://google.com");
545 EXPECT_FALSE(this->SetCookie(cs
.get(), url
, "a=1; domain=.com"));
546 EXPECT_FALSE(this->SetCookie(cs
.get(), url
, "b=2; domain=com"));
547 this->MatchCookieLines(std::string(), this->GetCookies(cs
.get(), url
));
550 { // Make sure can't set cookie on TLD which is dotted.
551 scoped_refptr
<CookieStore
> cs(this->GetCookieStore());
552 GURL
url("http://google.co.uk");
553 EXPECT_FALSE(this->SetCookie(cs
.get(), url
, "a=1; domain=.co.uk"));
554 EXPECT_FALSE(this->SetCookie(cs
.get(), url
, "b=2; domain=.uk"));
555 this->MatchCookieLines(std::string(), this->GetCookies(cs
.get(), url
));
556 this->MatchCookieLines(
558 this->GetCookies(cs
.get(), GURL("http://something-else.co.uk")));
559 this->MatchCookieLines(
561 this->GetCookies(cs
.get(), GURL("http://something-else.uk")));
564 { // Intranet URLs should only be able to set host cookies.
565 scoped_refptr
<CookieStore
> cs(this->GetCookieStore());
566 GURL
url("http://b");
567 EXPECT_TRUE(this->SetCookie(cs
.get(), url
, "a=1"));
568 EXPECT_FALSE(this->SetCookie(cs
.get(), url
, "b=2; domain=.b"));
569 EXPECT_FALSE(this->SetCookie(cs
.get(), url
, "c=3; domain=b"));
570 this->MatchCookieLines("a=1", this->GetCookies(cs
.get(), url
));
574 // Test reading/writing cookies when the domain ends with a period,
575 // as in "www.google.com."
576 TYPED_TEST_P(CookieStoreTest
, TestHostEndsWithDot
) {
577 scoped_refptr
<CookieStore
> cs(this->GetCookieStore());
578 GURL
url("http://www.google.com");
579 GURL
url_with_dot("http://www.google.com.");
580 EXPECT_TRUE(this->SetCookie(cs
.get(), url
, "a=1"));
581 this->MatchCookieLines("a=1", this->GetCookies(cs
.get(), url
));
583 if (TypeParam::supports_trailing_dots
) {
584 // Do not share cookie space with the dot version of domain.
585 // Note: this is not what FireFox does, but it _is_ what IE+Safari do.
587 this->SetCookie(cs
.get(), url
, "b=2; domain=.www.google.com."));
588 this->MatchCookieLines("a=1", this->GetCookies(cs
.get(), url
));
591 this->SetCookie(cs
.get(), url_with_dot
, "b=2; domain=.google.com."));
592 this->MatchCookieLines("b=2", this->GetCookies(cs
.get(), url_with_dot
));
594 EXPECT_TRUE(this->SetCookie(cs
.get(), url
, "b=2; domain=.www.google.com."));
596 this->SetCookie(cs
.get(), url_with_dot
, "b=2; domain=.google.com."));
599 // Make sure there weren't any side effects.
600 this->MatchCookieLines(
602 this->GetCookies(cs
.get(), GURL("http://hopefully-no-cookies.com/")));
603 this->MatchCookieLines(std::string(),
604 this->GetCookies(cs
.get(), GURL("http://.com/")));
607 TYPED_TEST_P(CookieStoreTest
, InvalidScheme
) {
608 if (!TypeParam::filters_schemes
)
611 scoped_refptr
<CookieStore
> cs(this->GetCookieStore());
612 EXPECT_FALSE(this->SetCookie(cs
.get(), GURL(kUrlFtp
), kValidCookieLine
));
615 TYPED_TEST_P(CookieStoreTest
, InvalidScheme_Read
) {
616 if (!TypeParam::filters_schemes
)
619 scoped_refptr
<CookieStore
> cs(this->GetCookieStore());
621 this->SetCookie(cs
.get(), GURL(kUrlGoogle
), kValidDomainCookieLine
));
622 this->MatchCookieLines(std::string(),
623 this->GetCookies(cs
.get(), GURL(kUrlFtp
)));
626 TYPED_TEST_P(CookieStoreTest
, PathTest
) {
627 scoped_refptr
<CookieStore
> cs(this->GetCookieStore());
628 std::string
url("http://www.google.izzle");
629 EXPECT_TRUE(this->SetCookie(cs
.get(), GURL(url
), "A=B; path=/wee"));
630 this->MatchCookieLines("A=B", this->GetCookies(cs
.get(), GURL(url
+ "/wee")));
631 this->MatchCookieLines("A=B",
632 this->GetCookies(cs
.get(), GURL(url
+ "/wee/")));
633 this->MatchCookieLines("A=B",
634 this->GetCookies(cs
.get(), GURL(url
+ "/wee/war")));
635 this->MatchCookieLines(
636 "A=B", this->GetCookies(cs
.get(), GURL(url
+ "/wee/war/more/more")));
637 if (!TypeParam::has_path_prefix_bug
)
638 this->MatchCookieLines(std::string(),
639 this->GetCookies(cs
.get(), GURL(url
+ "/weehee")));
640 this->MatchCookieLines(std::string(),
641 this->GetCookies(cs
.get(), GURL(url
+ "/")));
643 // If we add a 0 length path, it should default to /
644 EXPECT_TRUE(this->SetCookie(cs
.get(), GURL(url
), "A=C; path="));
645 this->MatchCookieLines("A=B; A=C",
646 this->GetCookies(cs
.get(), GURL(url
+ "/wee")));
647 this->MatchCookieLines("A=C", this->GetCookies(cs
.get(), GURL(url
+ "/")));
650 TYPED_TEST_P(CookieStoreTest
, EmptyExpires
) {
651 scoped_refptr
<CookieStore
> cs(this->GetCookieStore());
652 CookieOptions options
;
653 if (!TypeParam::supports_http_only
)
654 options
.set_include_httponly();
655 GURL
url("http://www7.ipdl.inpit.go.jp/Tokujitu/tjkta.ipdl?N0000=108");
656 std::string set_cookie_line
=
657 "ACSTM=20130308043820420042; path=/; domain=ipdl.inpit.go.jp; Expires=";
658 std::string cookie_line
= "ACSTM=20130308043820420042";
660 this->SetCookieWithOptions(cs
.get(), url
, set_cookie_line
, options
);
661 this->MatchCookieLines(cookie_line
,
662 this->GetCookiesWithOptions(cs
.get(), url
, options
));
664 options
.set_server_time(base::Time::Now() - base::TimeDelta::FromHours(1));
665 this->SetCookieWithOptions(cs
.get(), url
, set_cookie_line
, options
);
666 this->MatchCookieLines(cookie_line
,
667 this->GetCookiesWithOptions(cs
.get(), url
, options
));
669 options
.set_server_time(base::Time::Now() + base::TimeDelta::FromHours(1));
670 this->SetCookieWithOptions(cs
.get(), url
, set_cookie_line
, options
);
671 this->MatchCookieLines(cookie_line
,
672 this->GetCookiesWithOptions(cs
.get(), url
, options
));
675 TYPED_TEST_P(CookieStoreTest
, HttpOnlyTest
) {
676 if (!TypeParam::supports_http_only
)
679 scoped_refptr
<CookieStore
> cs(this->GetCookieStore());
680 CookieOptions options
;
681 options
.set_include_httponly();
683 // Create a httponly cookie.
684 EXPECT_TRUE(this->SetCookieWithOptions(
685 cs
.get(), this->url_google_
, "A=B; httponly", options
));
687 // Check httponly read protection.
688 this->MatchCookieLines(std::string(),
689 this->GetCookies(cs
.get(), this->url_google_
));
690 this->MatchCookieLines(
691 "A=B", this->GetCookiesWithOptions(cs
.get(), this->url_google_
, options
));
693 // Check httponly overwrite protection.
694 EXPECT_FALSE(this->SetCookie(cs
.get(), this->url_google_
, "A=C"));
695 this->MatchCookieLines(std::string(),
696 this->GetCookies(cs
.get(), this->url_google_
));
697 this->MatchCookieLines(
698 "A=B", this->GetCookiesWithOptions(cs
.get(), this->url_google_
, options
));
700 this->SetCookieWithOptions(cs
.get(), this->url_google_
, "A=C", options
));
701 this->MatchCookieLines("A=C", this->GetCookies(cs
.get(), this->url_google_
));
703 // Check httponly create protection.
704 EXPECT_FALSE(this->SetCookie(cs
.get(), this->url_google_
, "B=A; httponly"));
705 this->MatchCookieLines(
706 "A=C", this->GetCookiesWithOptions(cs
.get(), this->url_google_
, options
));
707 EXPECT_TRUE(this->SetCookieWithOptions(
708 cs
.get(), this->url_google_
, "B=A; httponly", options
));
709 this->MatchCookieLines(
711 this->GetCookiesWithOptions(cs
.get(), this->url_google_
, options
));
712 this->MatchCookieLines("A=C", this->GetCookies(cs
.get(), this->url_google_
));
715 TYPED_TEST_P(CookieStoreTest
, TestCookieDeletion
) {
716 scoped_refptr
<CookieStore
> cs(this->GetCookieStore());
718 // Create a session cookie.
719 EXPECT_TRUE(this->SetCookie(cs
.get(), this->url_google_
, kValidCookieLine
));
720 this->MatchCookieLines("A=B", this->GetCookies(cs
.get(), this->url_google_
));
721 // Delete it via Max-Age.
722 EXPECT_TRUE(this->SetCookie(cs
.get(),
724 std::string(kValidCookieLine
) + "; max-age=0"));
725 this->MatchCookieLineWithTimeout(cs
.get(), this->url_google_
, std::string());
727 // Create a session cookie.
728 EXPECT_TRUE(this->SetCookie(cs
.get(), this->url_google_
, kValidCookieLine
));
729 this->MatchCookieLines("A=B", this->GetCookies(cs
.get(), this->url_google_
));
730 // Delete it via Expires.
731 EXPECT_TRUE(this->SetCookie(cs
.get(),
733 std::string(kValidCookieLine
) +
734 "; expires=Mon, 18-Apr-1977 22:50:13 GMT"));
735 this->MatchCookieLines(std::string(),
736 this->GetCookies(cs
.get(), this->url_google_
));
738 // Create a persistent cookie.
739 EXPECT_TRUE(this->SetCookie(
742 std::string(kValidCookieLine
) + "; expires=Mon, 18-Apr-22 22:50:13 GMT"));
744 this->MatchCookieLines("A=B", this->GetCookies(cs
.get(), this->url_google_
));
745 // Delete it via Max-Age.
746 EXPECT_TRUE(this->SetCookie(cs
.get(),
748 std::string(kValidCookieLine
) + "; max-age=0"));
749 this->MatchCookieLineWithTimeout(cs
.get(), this->url_google_
, std::string());
751 // Create a persistent cookie.
752 EXPECT_TRUE(this->SetCookie(
755 std::string(kValidCookieLine
) + "; expires=Mon, 18-Apr-22 22:50:13 GMT"));
756 this->MatchCookieLines("A=B", this->GetCookies(cs
.get(), this->url_google_
));
757 // Delete it via Expires.
758 EXPECT_TRUE(this->SetCookie(cs
.get(),
760 std::string(kValidCookieLine
) +
761 "; expires=Mon, 18-Apr-1977 22:50:13 GMT"));
762 this->MatchCookieLines(std::string(),
763 this->GetCookies(cs
.get(), this->url_google_
));
765 // Create a persistent cookie.
766 EXPECT_TRUE(this->SetCookie(
769 std::string(kValidCookieLine
) + "; expires=Mon, 18-Apr-22 22:50:13 GMT"));
770 this->MatchCookieLines("A=B", this->GetCookies(cs
.get(), this->url_google_
));
771 // Check that it is not deleted with significant enough clock skew.
772 base::Time server_time
;
773 EXPECT_TRUE(base::Time::FromString("Sun, 17-Apr-1977 22:50:13 GMT",
775 EXPECT_TRUE(this->SetCookieWithServerTime(
778 std::string(kValidCookieLine
) + "; expires=Mon, 18-Apr-1977 22:50:13 GMT",
780 this->MatchCookieLines("A=B", this->GetCookies(cs
.get(), this->url_google_
));
782 // Create a persistent cookie.
783 EXPECT_TRUE(this->SetCookie(
786 std::string(kValidCookieLine
) + "; expires=Mon, 18-Apr-22 22:50:13 GMT"));
787 this->MatchCookieLines("A=B", this->GetCookies(cs
.get(), this->url_google_
));
788 // Delete it via Expires, with a unix epoch of 0.
789 EXPECT_TRUE(this->SetCookie(cs
.get(),
791 std::string(kValidCookieLine
) +
792 "; expires=Thu, 1-Jan-1970 00:00:00 GMT"));
793 this->MatchCookieLines(std::string(),
794 this->GetCookies(cs
.get(), this->url_google_
));
797 TYPED_TEST_P(CookieStoreTest
, TestDeleteAllCreatedBetween
) {
798 scoped_refptr
<CookieStore
> cs(this->GetCookieStore());
799 const base::Time last_month
= base::Time::Now() -
800 base::TimeDelta::FromDays(30);
801 const base::Time last_minute
= base::Time::Now() -
802 base::TimeDelta::FromMinutes(1);
803 const base::Time next_minute
= base::Time::Now() +
804 base::TimeDelta::FromMinutes(1);
805 const base::Time next_month
= base::Time::Now() +
806 base::TimeDelta::FromDays(30);
809 EXPECT_TRUE(this->SetCookie(cs
.get(), this->url_google_
, "A=B"));
810 // Check that the cookie is in the store.
811 this->MatchCookieLines("A=B", this->GetCookies(cs
.get(), this->url_google_
));
813 // Remove cookies in empty intervals.
814 EXPECT_EQ(0, this->DeleteCreatedBetween(cs
.get(), last_month
, last_minute
));
815 EXPECT_EQ(0, this->DeleteCreatedBetween(cs
.get(), next_minute
, next_month
));
816 // Check that the cookie is still there.
817 this->MatchCookieLines("A=B", this->GetCookies(cs
.get(), this->url_google_
));
819 // Remove the cookie with an interval defined by two dates.
820 EXPECT_EQ(1, this->DeleteCreatedBetween(cs
.get(), last_minute
, next_minute
));
821 // Check that the cookie disappeared.
822 this->MatchCookieLines(std::string(),
823 this->GetCookies(cs
.get(), this->url_google_
));
825 // Add another cookie.
826 EXPECT_TRUE(this->SetCookie(cs
.get(), this->url_google_
, "C=D"));
827 // Check that the cookie is in the store.
828 this->MatchCookieLines("C=D", this->GetCookies(cs
.get(), this->url_google_
));
830 // Remove the cookie with a null ending time.
831 EXPECT_EQ(1, this->DeleteCreatedBetween(cs
.get(), last_minute
, base::Time()));
832 // Check that the cookie disappeared.
833 this->MatchCookieLines(std::string(),
834 this->GetCookies(cs
.get(), this->url_google_
));
837 TYPED_TEST_P(CookieStoreTest
, TestDeleteAllCreatedBetweenForHost
) {
838 scoped_refptr
<CookieStore
> cs(this->GetCookieStore());
839 GURL
url_not_google("http://www.notgoogle.com");
840 base::Time now
= base::Time::Now();
842 // These 3 cookies match the time range and host.
843 EXPECT_TRUE(this->SetCookie(cs
.get(), this->url_google_
, "A=B"));
844 EXPECT_TRUE(this->SetCookie(cs
.get(), this->url_google_
, "C=D"));
845 EXPECT_TRUE(this->SetCookie(cs
.get(), this->url_google_
, "Y=Z"));
847 // This cookie does not match host.
848 EXPECT_TRUE(this->SetCookie(cs
.get(), url_not_google
, "E=F"));
852 3, // Deletes A=B, C=D, Y=Z
853 this->DeleteAllCreatedBetweenForHost(
854 cs
.get(), now
, base::Time::Max(), this->url_google_
));
857 TYPED_TEST_P(CookieStoreTest
, TestSecure
) {
858 scoped_refptr
<CookieStore
> cs(this->GetCookieStore());
860 EXPECT_TRUE(this->SetCookie(cs
.get(), this->url_google_
, "A=B"));
861 this->MatchCookieLines("A=B",
862 this->GetCookies(cs
.get(), this->url_google_
));
863 this->MatchCookieLines(
864 "A=B", this->GetCookies(cs
.get(), this->url_google_secure_
));
867 this->SetCookie(cs
.get(), this->url_google_secure_
, "A=B; secure"));
868 // The secure should overwrite the non-secure.
869 this->MatchCookieLines(std::string(),
870 this->GetCookies(cs
.get(), this->url_google_
));
871 this->MatchCookieLines("A=B",
872 this->GetCookies(cs
.get(), this->url_google_secure_
));
875 this->SetCookie(cs
.get(), this->url_google_secure_
, "D=E; secure"));
876 this->MatchCookieLines(std::string(),
877 this->GetCookies(cs
.get(), this->url_google_
));
878 this->MatchCookieLines("A=B; D=E",
879 this->GetCookies(cs
.get(), this->url_google_secure_
));
881 EXPECT_TRUE(this->SetCookie(cs
.get(), this->url_google_secure_
, "A=B"));
882 // The non-secure should overwrite the secure.
883 this->MatchCookieLines("A=B", this->GetCookies(cs
.get(), this->url_google_
));
884 this->MatchCookieLines("D=E; A=B",
885 this->GetCookies(cs
.get(), this->url_google_secure_
));
888 static const int kLastAccessThresholdMilliseconds
= 200;
890 // Formerly NetUtilTest.CookieTest back when we used wininet's cookie handling.
891 TYPED_TEST_P(CookieStoreTest
, NetUtilCookieTest
) {
892 const GURL
test_url("http://mojo.jojo.google.izzle/");
894 scoped_refptr
<CookieStore
> cs(this->GetCookieStore());
896 EXPECT_TRUE(this->SetCookie(cs
.get(), test_url
, "foo=bar"));
897 std::string value
= this->GetCookies(cs
.get(), test_url
);
898 this->MatchCookieLines("foo=bar", value
);
900 // test that we can retrieve all cookies:
901 EXPECT_TRUE(this->SetCookie(cs
.get(), test_url
, "x=1"));
902 EXPECT_TRUE(this->SetCookie(cs
.get(), test_url
, "y=2"));
904 std::string result
= this->GetCookies(cs
.get(), test_url
);
905 EXPECT_FALSE(result
.empty());
906 EXPECT_NE(result
.find("x=1"), std::string::npos
) << result
;
907 EXPECT_NE(result
.find("y=2"), std::string::npos
) << result
;
910 TYPED_TEST_P(CookieStoreTest
, OverwritePersistentCookie
) {
911 GURL
url_google("http://www.google.com/");
912 GURL
url_chromium("http://chromium.org");
913 scoped_refptr
<CookieStore
> cs(this->GetCookieStore());
915 // Insert a cookie "a" for path "/path1"
916 EXPECT_TRUE(this->SetCookie(cs
.get(),
918 "a=val1; path=/path1; "
919 "expires=Mon, 18-Apr-22 22:50:13 GMT"));
921 // Insert a cookie "b" for path "/path1"
922 EXPECT_TRUE(this->SetCookie(cs
.get(),
924 "b=val1; path=/path1; "
925 "expires=Mon, 18-Apr-22 22:50:14 GMT"));
927 // Insert a cookie "b" for path "/path1", that is httponly. This should
928 // overwrite the non-http-only version.
929 CookieOptions allow_httponly
;
930 allow_httponly
.set_include_httponly();
931 EXPECT_TRUE(this->SetCookieWithOptions(cs
.get(),
933 "b=val2; path=/path1; httponly; "
934 "expires=Mon, 18-Apr-22 22:50:14 GMT",
937 // Insert a cookie "a" for path "/path1". This should overwrite.
938 EXPECT_TRUE(this->SetCookie(cs
.get(),
940 "a=val33; path=/path1; "
941 "expires=Mon, 18-Apr-22 22:50:14 GMT"));
943 // Insert a cookie "a" for path "/path2". This should NOT overwrite
944 // cookie "a", since the path is different.
945 EXPECT_TRUE(this->SetCookie(cs
.get(),
947 "a=val9; path=/path2; "
948 "expires=Mon, 18-Apr-22 22:50:14 GMT"));
950 // Insert a cookie "a" for path "/path1", but this time for "chromium.org".
951 // Although the name and path match, the hostnames do not, so shouldn't
953 EXPECT_TRUE(this->SetCookie(cs
.get(),
955 "a=val99; path=/path1; "
956 "expires=Mon, 18-Apr-22 22:50:14 GMT"));
958 if (TypeParam::supports_http_only
) {
959 this->MatchCookieLines(
961 this->GetCookies(cs
.get(), GURL("http://www.google.com/path1")));
963 this->MatchCookieLines(
965 this->GetCookies(cs
.get(), GURL("http://www.google.com/path1")));
967 this->MatchCookieLines(
969 this->GetCookies(cs
.get(), GURL("http://www.google.com/path2")));
970 this->MatchCookieLines(
971 "a=val99", this->GetCookies(cs
.get(), GURL("http://chromium.org/path1")));
974 TYPED_TEST_P(CookieStoreTest
, CookieOrdering
) {
975 // Put a random set of cookies into a store and make sure they're returned in
977 // Cookies should be sorted by path length and creation time, as per RFC6265.
978 scoped_refptr
<CookieStore
> cs(this->GetCookieStore());
979 EXPECT_TRUE(this->SetCookie(
980 cs
.get(), GURL("http://d.c.b.a.google.com/aa/x.html"), "c=1"));
981 EXPECT_TRUE(this->SetCookie(cs
.get(),
982 GURL("http://b.a.google.com/aa/bb/cc/x.html"),
983 "d=1; domain=b.a.google.com"));
984 base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(
985 TypeParam::creation_time_granularity_in_ms
));
986 EXPECT_TRUE(this->SetCookie(cs
.get(),
987 GURL("http://b.a.google.com/aa/bb/cc/x.html"),
988 "a=4; domain=b.a.google.com"));
989 base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(
990 TypeParam::creation_time_granularity_in_ms
));
991 EXPECT_TRUE(this->SetCookie(cs
.get(),
992 GURL("http://c.b.a.google.com/aa/bb/cc/x.html"),
993 "e=1; domain=c.b.a.google.com"));
994 EXPECT_TRUE(this->SetCookie(
995 cs
.get(), GURL("http://d.c.b.a.google.com/aa/bb/x.html"), "b=1"));
996 EXPECT_TRUE(this->SetCookie(
997 cs
.get(), GURL("http://news.bbc.co.uk/midpath/x.html"), "g=10"));
998 EXPECT_EQ("d=1; a=4; e=1; b=1; c=1",
999 this->GetCookies(cs
.get(),
1000 GURL("http://d.c.b.a.google.com/aa/bb/cc/dd")));
1003 TYPED_TEST_P(CookieStoreTest
, DeleteSessionCookie
) {
1004 scoped_refptr
<CookieStore
> cs(this->GetCookieStore());
1005 // Create a session cookie and a persistent cookie.
1006 EXPECT_TRUE(this->SetCookie(
1007 cs
.get(), this->url_google_
, std::string(kValidCookieLine
)));
1008 EXPECT_TRUE(this->SetCookie(cs
.get(),
1010 "C=D; path=/; domain=google.izzle;"
1011 "expires=Mon, 18-Apr-22 22:50:13 GMT"));
1012 this->MatchCookieLines("A=B; C=D",
1013 this->GetCookies(cs
.get(), this->url_google_
));
1014 // Delete the session cookie.
1015 this->DeleteSessionCookies(cs
.get());
1016 // Check that the session cookie has been deleted but not the persistent one.
1017 EXPECT_EQ("C=D", this->GetCookies(cs
.get(), this->url_google_
));
1020 REGISTER_TYPED_TEST_CASE_P(CookieStoreTest
,
1023 DomainWithTrailingDotTest
,
1026 DomainWithoutLeadingDotTest
,
1027 CaseInsensitiveDomainTest
,
1029 TestNonDottedAndTLD
,
1030 TestHostEndsWithDot
,
1037 TestDeleteAllCreatedBetween
,
1038 TestDeleteAllCreatedBetweenForHost
,
1041 OverwritePersistentCookie
,
1043 DeleteSessionCookie
);
1045 template<class CookieStoreTestTraits
>
1046 class MultiThreadedCookieStoreTest
:
1047 public CookieStoreTest
<CookieStoreTestTraits
> {
1049 MultiThreadedCookieStoreTest() : other_thread_("CMTthread") {}
1051 // Helper methods for calling the asynchronous CookieStore methods
1052 // from a different thread.
1054 void GetCookiesTask(CookieStore
* cs
,
1056 StringResultCookieCallback
* callback
) {
1057 CookieOptions options
;
1058 if (!CookieStoreTestTraits::supports_http_only
)
1059 options
.set_include_httponly();
1060 cs
->GetCookiesWithOptionsAsync(
1062 base::Bind(&StringResultCookieCallback::Run
,
1063 base::Unretained(callback
)));
1066 void GetCookiesWithOptionsTask(CookieStore
* cs
,
1068 const CookieOptions
& options
,
1069 StringResultCookieCallback
* callback
) {
1070 cs
->GetCookiesWithOptionsAsync(
1072 base::Bind(&StringResultCookieCallback::Run
,
1073 base::Unretained(callback
)));
1076 void SetCookieWithOptionsTask(CookieStore
* cs
,
1078 const std::string
& cookie_line
,
1079 const CookieOptions
& options
,
1080 ResultSavingCookieCallback
<bool>* callback
) {
1081 cs
->SetCookieWithOptionsAsync(
1082 url
, cookie_line
, options
,
1084 &ResultSavingCookieCallback
<bool>::Run
,
1085 base::Unretained(callback
)));
1088 void DeleteCookieTask(CookieStore
* cs
,
1090 const std::string
& cookie_name
,
1091 NoResultCookieCallback
* callback
) {
1092 cs
->DeleteCookieAsync(
1094 base::Bind(&NoResultCookieCallback::Run
, base::Unretained(callback
)));
1097 void DeleteSessionCookiesTask(CookieStore
* cs
,
1098 ResultSavingCookieCallback
<int>* callback
) {
1099 cs
->DeleteSessionCookiesAsync(
1101 &ResultSavingCookieCallback
<int>::Run
,
1102 base::Unretained(callback
)));
1106 void RunOnOtherThread(const base::Closure
& task
) {
1107 other_thread_
.Start();
1108 other_thread_
.task_runner()->PostTask(FROM_HERE
, task
);
1109 CookieStoreTest
<CookieStoreTestTraits
>::RunFor(kTimeout
);
1110 other_thread_
.Stop();
1113 Thread other_thread_
;
1116 TYPED_TEST_CASE_P(MultiThreadedCookieStoreTest
);
1118 // TODO(ycxiao): Eventually, we will need to create a separate thread, create
1119 // the cookie store on that thread (or at least its store, i.e., the DB
1121 TYPED_TEST_P(MultiThreadedCookieStoreTest
, ThreadCheckGetCookies
) {
1122 scoped_refptr
<CookieStore
> cs(this->GetCookieStore());
1123 EXPECT_TRUE(this->SetCookie(cs
.get(), this->url_google_
, "A=B"));
1124 this->MatchCookieLines("A=B", this->GetCookies(cs
.get(), this->url_google_
));
1125 StringResultCookieCallback
callback(&this->other_thread_
);
1126 base::Closure task
=
1127 base::Bind(&MultiThreadedCookieStoreTest
<TypeParam
>::GetCookiesTask
,
1128 base::Unretained(this), cs
, this->url_google_
, &callback
);
1129 this->RunOnOtherThread(task
);
1130 EXPECT_TRUE(callback
.did_run());
1131 EXPECT_EQ("A=B", callback
.result());
1134 TYPED_TEST_P(MultiThreadedCookieStoreTest
, ThreadCheckGetCookiesWithOptions
) {
1135 scoped_refptr
<CookieStore
> cs(this->GetCookieStore());
1136 CookieOptions options
;
1137 if (!TypeParam::supports_http_only
)
1138 options
.set_include_httponly();
1139 EXPECT_TRUE(this->SetCookie(cs
.get(), this->url_google_
, "A=B"));
1140 this->MatchCookieLines(
1141 "A=B", this->GetCookiesWithOptions(cs
.get(), this->url_google_
, options
));
1142 StringResultCookieCallback
callback(&this->other_thread_
);
1143 base::Closure task
= base::Bind(
1144 &MultiThreadedCookieStoreTest
<TypeParam
>::GetCookiesWithOptionsTask
,
1145 base::Unretained(this), cs
, this->url_google_
, options
, &callback
);
1146 this->RunOnOtherThread(task
);
1147 EXPECT_TRUE(callback
.did_run());
1148 EXPECT_EQ("A=B", callback
.result());
1151 TYPED_TEST_P(MultiThreadedCookieStoreTest
, ThreadCheckSetCookieWithOptions
) {
1152 scoped_refptr
<CookieStore
> cs(this->GetCookieStore());
1153 CookieOptions options
;
1154 if (!TypeParam::supports_http_only
)
1155 options
.set_include_httponly();
1157 this->SetCookieWithOptions(cs
.get(), this->url_google_
, "A=B", options
));
1158 ResultSavingCookieCallback
<bool> callback(&this->other_thread_
);
1159 base::Closure task
= base::Bind(
1160 &MultiThreadedCookieStoreTest
<TypeParam
>::SetCookieWithOptionsTask
,
1161 base::Unretained(this), cs
, this->url_google_
, "A=B", options
, &callback
);
1162 this->RunOnOtherThread(task
);
1163 EXPECT_TRUE(callback
.did_run());
1164 EXPECT_TRUE(callback
.result());
1167 TYPED_TEST_P(MultiThreadedCookieStoreTest
, ThreadCheckDeleteCookie
) {
1168 scoped_refptr
<CookieStore
> cs(this->GetCookieStore());
1169 CookieOptions options
;
1170 if (!TypeParam::supports_http_only
)
1171 options
.set_include_httponly();
1173 this->SetCookieWithOptions(cs
.get(), this->url_google_
, "A=B", options
));
1174 this->DeleteCookie(cs
.get(), this->url_google_
, "A");
1176 this->SetCookieWithOptions(cs
.get(), this->url_google_
, "A=B", options
));
1177 NoResultCookieCallback
callback(&this->other_thread_
);
1178 base::Closure task
=
1179 base::Bind(&MultiThreadedCookieStoreTest
<TypeParam
>::DeleteCookieTask
,
1180 base::Unretained(this), cs
, this->url_google_
, "A", &callback
);
1181 this->RunOnOtherThread(task
);
1182 EXPECT_TRUE(callback
.did_run());
1185 TYPED_TEST_P(MultiThreadedCookieStoreTest
, ThreadCheckDeleteSessionCookies
) {
1186 scoped_refptr
<CookieStore
> cs(this->GetCookieStore());
1187 CookieOptions options
;
1188 if (!TypeParam::supports_http_only
)
1189 options
.set_include_httponly();
1191 this->SetCookieWithOptions(cs
.get(), this->url_google_
, "A=B", options
));
1193 this->SetCookieWithOptions(cs
.get(),
1195 "B=C; expires=Mon, 18-Apr-22 22:50:13 GMT",
1197 EXPECT_EQ(1, this->DeleteSessionCookies(cs
.get()));
1198 EXPECT_EQ(0, this->DeleteSessionCookies(cs
.get()));
1200 this->SetCookieWithOptions(cs
.get(), this->url_google_
, "A=B", options
));
1201 ResultSavingCookieCallback
<int> callback(&this->other_thread_
);
1202 base::Closure task
= base::Bind(
1203 &MultiThreadedCookieStoreTest
<TypeParam
>::DeleteSessionCookiesTask
,
1204 base::Unretained(this), cs
, &callback
);
1205 this->RunOnOtherThread(task
);
1206 EXPECT_TRUE(callback
.did_run());
1207 EXPECT_EQ(1, callback
.result());
1210 REGISTER_TYPED_TEST_CASE_P(MultiThreadedCookieStoreTest
,
1211 ThreadCheckGetCookies
,
1212 ThreadCheckGetCookiesWithOptions
,
1213 ThreadCheckSetCookieWithOptions
,
1214 ThreadCheckDeleteCookie
,
1215 ThreadCheckDeleteSessionCookies
);
1219 #endif // NET_COOKIES_COOKIE_STORE_UNITTEST_H_