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 does not fold domains with trailing dots (so "com." and
62 // "com" are different domains).
63 // static const bool preserves_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 scoped_refptr
<CookieStore
> cs(this->GetCookieStore());
492 GURL
url("http://com/");
493 // Allow setting on "com", (but only as a host cookie).
494 EXPECT_TRUE(this->SetCookie(cs
.get(), url
, "a=1"));
495 EXPECT_FALSE(this->SetCookie(cs
.get(), url
, "b=2; domain=.com"));
496 EXPECT_FALSE(this->SetCookie(cs
.get(), url
, "c=3; domain=com"));
497 this->MatchCookieLines("a=1", this->GetCookies(cs
.get(), url
));
498 // Make sure it doesn't show up for a normal .com, it should be a host
499 // not a domain cookie.
500 this->MatchCookieLines(
502 this->GetCookies(cs
.get(), GURL("http://hopefully-no-cookies.com/")));
503 if (TypeParam::supports_non_dotted_domains
) {
504 this->MatchCookieLines(std::string(),
505 this->GetCookies(cs
.get(), GURL("http://.com/")));
510 // http://com. should be treated the same as http://com.
511 scoped_refptr
<CookieStore
> cs(this->GetCookieStore());
512 GURL
url("http://com./index.html");
513 EXPECT_TRUE(this->SetCookie(cs
.get(), url
, "a=1"));
514 this->MatchCookieLines("a=1", this->GetCookies(cs
.get(), url
));
515 this->MatchCookieLines(
517 this->GetCookies(cs
.get(),
518 GURL("http://hopefully-no-cookies.com./")));
521 { // Should not be able to set host cookie from a subdomain.
522 scoped_refptr
<CookieStore
> cs(this->GetCookieStore());
523 GURL
url("http://a.b");
524 EXPECT_FALSE(this->SetCookie(cs
.get(), url
, "a=1; domain=.b"));
525 EXPECT_FALSE(this->SetCookie(cs
.get(), url
, "b=2; domain=b"));
526 this->MatchCookieLines(std::string(), this->GetCookies(cs
.get(), url
));
529 { // Same test as above, but explicitly on a known TLD (com).
530 scoped_refptr
<CookieStore
> cs(this->GetCookieStore());
531 GURL
url("http://google.com");
532 EXPECT_FALSE(this->SetCookie(cs
.get(), url
, "a=1; domain=.com"));
533 EXPECT_FALSE(this->SetCookie(cs
.get(), url
, "b=2; domain=com"));
534 this->MatchCookieLines(std::string(), this->GetCookies(cs
.get(), url
));
537 { // Make sure can't set cookie on TLD which is dotted.
538 scoped_refptr
<CookieStore
> cs(this->GetCookieStore());
539 GURL
url("http://google.co.uk");
540 EXPECT_FALSE(this->SetCookie(cs
.get(), url
, "a=1; domain=.co.uk"));
541 EXPECT_FALSE(this->SetCookie(cs
.get(), url
, "b=2; domain=.uk"));
542 this->MatchCookieLines(std::string(), this->GetCookies(cs
.get(), url
));
543 this->MatchCookieLines(
545 this->GetCookies(cs
.get(), GURL("http://something-else.co.uk")));
546 this->MatchCookieLines(
548 this->GetCookies(cs
.get(), GURL("http://something-else.uk")));
551 { // Intranet URLs should only be able to set host cookies.
552 scoped_refptr
<CookieStore
> cs(this->GetCookieStore());
553 GURL
url("http://b");
554 EXPECT_TRUE(this->SetCookie(cs
.get(), url
, "a=1"));
555 EXPECT_FALSE(this->SetCookie(cs
.get(), url
, "b=2; domain=.b"));
556 EXPECT_FALSE(this->SetCookie(cs
.get(), url
, "c=3; domain=b"));
557 this->MatchCookieLines("a=1", this->GetCookies(cs
.get(), url
));
561 // Test reading/writing cookies when the domain ends with a period,
562 // as in "www.google.com."
563 TYPED_TEST_P(CookieStoreTest
, TestHostEndsWithDot
) {
564 scoped_refptr
<CookieStore
> cs(this->GetCookieStore());
565 GURL
url("http://www.google.com");
566 GURL
url_with_dot("http://www.google.com.");
567 EXPECT_TRUE(this->SetCookie(cs
.get(), url
, "a=1"));
568 this->MatchCookieLines("a=1", this->GetCookies(cs
.get(), url
));
570 // Do not share cookie space with the dot version of domain.
571 // Note: this is not what FireFox does, but it _is_ what IE+Safari do.
572 if (TypeParam::preserves_trailing_dots
) {
574 this->SetCookie(cs
.get(), url
, "b=2; domain=.www.google.com."));
575 this->MatchCookieLines("a=1", this->GetCookies(cs
.get(), url
));
577 this->SetCookie(cs
.get(), url_with_dot
, "b=2; domain=.google.com."));
578 this->MatchCookieLines("b=2", this->GetCookies(cs
.get(), url_with_dot
));
581 this->SetCookie(cs
.get(), url
, "b=2; domain=.www.google.com."));
582 this->MatchCookieLines("a=1 b=2", this->GetCookies(cs
.get(), url
));
583 // Setting this cookie should fail, since the trailing dot on the domain
584 // isn't preserved, and then the domain mismatches the URL.
586 this->SetCookie(cs
.get(), url_with_dot
, "b=2; domain=.google.com."));
589 // Make sure there weren't any side effects.
590 this->MatchCookieLines(
592 this->GetCookies(cs
.get(), GURL("http://hopefully-no-cookies.com/")));
593 this->MatchCookieLines(std::string(),
594 this->GetCookies(cs
.get(), GURL("http://.com/")));
597 TYPED_TEST_P(CookieStoreTest
, InvalidScheme
) {
598 if (!TypeParam::filters_schemes
)
601 scoped_refptr
<CookieStore
> cs(this->GetCookieStore());
602 EXPECT_FALSE(this->SetCookie(cs
.get(), GURL(kUrlFtp
), kValidCookieLine
));
605 TYPED_TEST_P(CookieStoreTest
, InvalidScheme_Read
) {
606 if (!TypeParam::filters_schemes
)
609 scoped_refptr
<CookieStore
> cs(this->GetCookieStore());
611 this->SetCookie(cs
.get(), GURL(kUrlGoogle
), kValidDomainCookieLine
));
612 this->MatchCookieLines(std::string(),
613 this->GetCookies(cs
.get(), GURL(kUrlFtp
)));
616 TYPED_TEST_P(CookieStoreTest
, PathTest
) {
617 scoped_refptr
<CookieStore
> cs(this->GetCookieStore());
618 std::string
url("http://www.google.izzle");
619 EXPECT_TRUE(this->SetCookie(cs
.get(), GURL(url
), "A=B; path=/wee"));
620 this->MatchCookieLines("A=B", this->GetCookies(cs
.get(), GURL(url
+ "/wee")));
621 this->MatchCookieLines("A=B",
622 this->GetCookies(cs
.get(), GURL(url
+ "/wee/")));
623 this->MatchCookieLines("A=B",
624 this->GetCookies(cs
.get(), GURL(url
+ "/wee/war")));
625 this->MatchCookieLines(
626 "A=B", this->GetCookies(cs
.get(), GURL(url
+ "/wee/war/more/more")));
627 if (!TypeParam::has_path_prefix_bug
)
628 this->MatchCookieLines(std::string(),
629 this->GetCookies(cs
.get(), GURL(url
+ "/weehee")));
630 this->MatchCookieLines(std::string(),
631 this->GetCookies(cs
.get(), GURL(url
+ "/")));
633 // If we add a 0 length path, it should default to /
634 EXPECT_TRUE(this->SetCookie(cs
.get(), GURL(url
), "A=C; path="));
635 this->MatchCookieLines("A=B; A=C",
636 this->GetCookies(cs
.get(), GURL(url
+ "/wee")));
637 this->MatchCookieLines("A=C", this->GetCookies(cs
.get(), GURL(url
+ "/")));
640 TYPED_TEST_P(CookieStoreTest
, EmptyExpires
) {
641 scoped_refptr
<CookieStore
> cs(this->GetCookieStore());
642 CookieOptions options
;
643 if (!TypeParam::supports_http_only
)
644 options
.set_include_httponly();
645 GURL
url("http://www7.ipdl.inpit.go.jp/Tokujitu/tjkta.ipdl?N0000=108");
646 std::string set_cookie_line
=
647 "ACSTM=20130308043820420042; path=/; domain=ipdl.inpit.go.jp; Expires=";
648 std::string cookie_line
= "ACSTM=20130308043820420042";
650 this->SetCookieWithOptions(cs
.get(), url
, set_cookie_line
, options
);
651 this->MatchCookieLines(cookie_line
,
652 this->GetCookiesWithOptions(cs
.get(), url
, options
));
654 options
.set_server_time(base::Time::Now() - base::TimeDelta::FromHours(1));
655 this->SetCookieWithOptions(cs
.get(), url
, set_cookie_line
, options
);
656 this->MatchCookieLines(cookie_line
,
657 this->GetCookiesWithOptions(cs
.get(), url
, options
));
659 options
.set_server_time(base::Time::Now() + base::TimeDelta::FromHours(1));
660 this->SetCookieWithOptions(cs
.get(), url
, set_cookie_line
, options
);
661 this->MatchCookieLines(cookie_line
,
662 this->GetCookiesWithOptions(cs
.get(), url
, options
));
665 TYPED_TEST_P(CookieStoreTest
, HttpOnlyTest
) {
666 if (!TypeParam::supports_http_only
)
669 scoped_refptr
<CookieStore
> cs(this->GetCookieStore());
670 CookieOptions options
;
671 options
.set_include_httponly();
673 // Create a httponly cookie.
674 EXPECT_TRUE(this->SetCookieWithOptions(
675 cs
.get(), this->url_google_
, "A=B; httponly", options
));
677 // Check httponly read protection.
678 this->MatchCookieLines(std::string(),
679 this->GetCookies(cs
.get(), this->url_google_
));
680 this->MatchCookieLines(
681 "A=B", this->GetCookiesWithOptions(cs
.get(), this->url_google_
, options
));
683 // Check httponly overwrite protection.
684 EXPECT_FALSE(this->SetCookie(cs
.get(), this->url_google_
, "A=C"));
685 this->MatchCookieLines(std::string(),
686 this->GetCookies(cs
.get(), this->url_google_
));
687 this->MatchCookieLines(
688 "A=B", this->GetCookiesWithOptions(cs
.get(), this->url_google_
, options
));
690 this->SetCookieWithOptions(cs
.get(), this->url_google_
, "A=C", options
));
691 this->MatchCookieLines("A=C", this->GetCookies(cs
.get(), this->url_google_
));
693 // Check httponly create protection.
694 EXPECT_FALSE(this->SetCookie(cs
.get(), this->url_google_
, "B=A; httponly"));
695 this->MatchCookieLines(
696 "A=C", this->GetCookiesWithOptions(cs
.get(), this->url_google_
, options
));
697 EXPECT_TRUE(this->SetCookieWithOptions(
698 cs
.get(), this->url_google_
, "B=A; httponly", options
));
699 this->MatchCookieLines(
701 this->GetCookiesWithOptions(cs
.get(), this->url_google_
, options
));
702 this->MatchCookieLines("A=C", this->GetCookies(cs
.get(), this->url_google_
));
705 TYPED_TEST_P(CookieStoreTest
, TestCookieDeletion
) {
706 scoped_refptr
<CookieStore
> cs(this->GetCookieStore());
708 // Create a session cookie.
709 EXPECT_TRUE(this->SetCookie(cs
.get(), this->url_google_
, kValidCookieLine
));
710 this->MatchCookieLines("A=B", this->GetCookies(cs
.get(), this->url_google_
));
711 // Delete it via Max-Age.
712 EXPECT_TRUE(this->SetCookie(cs
.get(),
714 std::string(kValidCookieLine
) + "; max-age=0"));
715 this->MatchCookieLineWithTimeout(cs
.get(), this->url_google_
, std::string());
717 // Create a session cookie.
718 EXPECT_TRUE(this->SetCookie(cs
.get(), this->url_google_
, kValidCookieLine
));
719 this->MatchCookieLines("A=B", this->GetCookies(cs
.get(), this->url_google_
));
720 // Delete it via Expires.
721 EXPECT_TRUE(this->SetCookie(cs
.get(),
723 std::string(kValidCookieLine
) +
724 "; expires=Mon, 18-Apr-1977 22:50:13 GMT"));
725 this->MatchCookieLines(std::string(),
726 this->GetCookies(cs
.get(), this->url_google_
));
728 // Create a persistent cookie.
729 EXPECT_TRUE(this->SetCookie(
732 std::string(kValidCookieLine
) + "; expires=Mon, 18-Apr-22 22:50:13 GMT"));
734 this->MatchCookieLines("A=B", this->GetCookies(cs
.get(), this->url_google_
));
735 // Delete it via Max-Age.
736 EXPECT_TRUE(this->SetCookie(cs
.get(),
738 std::string(kValidCookieLine
) + "; max-age=0"));
739 this->MatchCookieLineWithTimeout(cs
.get(), this->url_google_
, std::string());
741 // Create a persistent cookie.
742 EXPECT_TRUE(this->SetCookie(
745 std::string(kValidCookieLine
) + "; expires=Mon, 18-Apr-22 22:50:13 GMT"));
746 this->MatchCookieLines("A=B", this->GetCookies(cs
.get(), this->url_google_
));
747 // Delete it via Expires.
748 EXPECT_TRUE(this->SetCookie(cs
.get(),
750 std::string(kValidCookieLine
) +
751 "; expires=Mon, 18-Apr-1977 22:50:13 GMT"));
752 this->MatchCookieLines(std::string(),
753 this->GetCookies(cs
.get(), this->url_google_
));
755 // Create a persistent cookie.
756 EXPECT_TRUE(this->SetCookie(
759 std::string(kValidCookieLine
) + "; expires=Mon, 18-Apr-22 22:50:13 GMT"));
760 this->MatchCookieLines("A=B", this->GetCookies(cs
.get(), this->url_google_
));
761 // Check that it is not deleted with significant enough clock skew.
762 base::Time server_time
;
763 EXPECT_TRUE(base::Time::FromString("Sun, 17-Apr-1977 22:50:13 GMT",
765 EXPECT_TRUE(this->SetCookieWithServerTime(
768 std::string(kValidCookieLine
) + "; expires=Mon, 18-Apr-1977 22:50:13 GMT",
770 this->MatchCookieLines("A=B", this->GetCookies(cs
.get(), this->url_google_
));
772 // Create a persistent cookie.
773 EXPECT_TRUE(this->SetCookie(
776 std::string(kValidCookieLine
) + "; expires=Mon, 18-Apr-22 22:50:13 GMT"));
777 this->MatchCookieLines("A=B", this->GetCookies(cs
.get(), this->url_google_
));
778 // Delete it via Expires, with a unix epoch of 0.
779 EXPECT_TRUE(this->SetCookie(cs
.get(),
781 std::string(kValidCookieLine
) +
782 "; expires=Thu, 1-Jan-1970 00:00:00 GMT"));
783 this->MatchCookieLines(std::string(),
784 this->GetCookies(cs
.get(), this->url_google_
));
787 TYPED_TEST_P(CookieStoreTest
, TestDeleteAllCreatedBetween
) {
788 scoped_refptr
<CookieStore
> cs(this->GetCookieStore());
789 const base::Time last_month
= base::Time::Now() -
790 base::TimeDelta::FromDays(30);
791 const base::Time last_minute
= base::Time::Now() -
792 base::TimeDelta::FromMinutes(1);
793 const base::Time next_minute
= base::Time::Now() +
794 base::TimeDelta::FromMinutes(1);
795 const base::Time next_month
= base::Time::Now() +
796 base::TimeDelta::FromDays(30);
799 EXPECT_TRUE(this->SetCookie(cs
.get(), this->url_google_
, "A=B"));
800 // Check that the cookie is in the store.
801 this->MatchCookieLines("A=B", this->GetCookies(cs
.get(), this->url_google_
));
803 // Remove cookies in empty intervals.
804 EXPECT_EQ(0, this->DeleteCreatedBetween(cs
.get(), last_month
, last_minute
));
805 EXPECT_EQ(0, this->DeleteCreatedBetween(cs
.get(), next_minute
, next_month
));
806 // Check that the cookie is still there.
807 this->MatchCookieLines("A=B", this->GetCookies(cs
.get(), this->url_google_
));
809 // Remove the cookie with an interval defined by two dates.
810 EXPECT_EQ(1, this->DeleteCreatedBetween(cs
.get(), last_minute
, next_minute
));
811 // Check that the cookie disappeared.
812 this->MatchCookieLines(std::string(),
813 this->GetCookies(cs
.get(), this->url_google_
));
815 // Add another cookie.
816 EXPECT_TRUE(this->SetCookie(cs
.get(), this->url_google_
, "C=D"));
817 // Check that the cookie is in the store.
818 this->MatchCookieLines("C=D", this->GetCookies(cs
.get(), this->url_google_
));
820 // Remove the cookie with a null ending time.
821 EXPECT_EQ(1, this->DeleteCreatedBetween(cs
.get(), last_minute
, base::Time()));
822 // Check that the cookie disappeared.
823 this->MatchCookieLines(std::string(),
824 this->GetCookies(cs
.get(), this->url_google_
));
827 TYPED_TEST_P(CookieStoreTest
, TestDeleteAllCreatedBetweenForHost
) {
828 scoped_refptr
<CookieStore
> cs(this->GetCookieStore());
829 GURL
url_not_google("http://www.notgoogle.com");
830 base::Time now
= base::Time::Now();
832 // These 3 cookies match the time range and host.
833 EXPECT_TRUE(this->SetCookie(cs
.get(), this->url_google_
, "A=B"));
834 EXPECT_TRUE(this->SetCookie(cs
.get(), this->url_google_
, "C=D"));
835 EXPECT_TRUE(this->SetCookie(cs
.get(), this->url_google_
, "Y=Z"));
837 // This cookie does not match host.
838 EXPECT_TRUE(this->SetCookie(cs
.get(), url_not_google
, "E=F"));
842 3, // Deletes A=B, C=D, Y=Z
843 this->DeleteAllCreatedBetweenForHost(
844 cs
.get(), now
, base::Time::Max(), this->url_google_
));
847 TYPED_TEST_P(CookieStoreTest
, TestSecure
) {
848 scoped_refptr
<CookieStore
> cs(this->GetCookieStore());
850 EXPECT_TRUE(this->SetCookie(cs
.get(), this->url_google_
, "A=B"));
851 this->MatchCookieLines("A=B",
852 this->GetCookies(cs
.get(), this->url_google_
));
853 this->MatchCookieLines(
854 "A=B", this->GetCookies(cs
.get(), this->url_google_secure_
));
857 this->SetCookie(cs
.get(), this->url_google_secure_
, "A=B; secure"));
858 // The secure should overwrite the non-secure.
859 this->MatchCookieLines(std::string(),
860 this->GetCookies(cs
.get(), this->url_google_
));
861 this->MatchCookieLines("A=B",
862 this->GetCookies(cs
.get(), this->url_google_secure_
));
865 this->SetCookie(cs
.get(), this->url_google_secure_
, "D=E; secure"));
866 this->MatchCookieLines(std::string(),
867 this->GetCookies(cs
.get(), this->url_google_
));
868 this->MatchCookieLines("A=B; D=E",
869 this->GetCookies(cs
.get(), this->url_google_secure_
));
871 EXPECT_TRUE(this->SetCookie(cs
.get(), this->url_google_secure_
, "A=B"));
872 // The non-secure should overwrite the secure.
873 this->MatchCookieLines("A=B", this->GetCookies(cs
.get(), this->url_google_
));
874 this->MatchCookieLines("D=E; A=B",
875 this->GetCookies(cs
.get(), this->url_google_secure_
));
878 static const int kLastAccessThresholdMilliseconds
= 200;
880 // Formerly NetUtilTest.CookieTest back when we used wininet's cookie handling.
881 TYPED_TEST_P(CookieStoreTest
, NetUtilCookieTest
) {
882 const GURL
test_url("http://mojo.jojo.google.izzle/");
884 scoped_refptr
<CookieStore
> cs(this->GetCookieStore());
886 EXPECT_TRUE(this->SetCookie(cs
.get(), test_url
, "foo=bar"));
887 std::string value
= this->GetCookies(cs
.get(), test_url
);
888 this->MatchCookieLines("foo=bar", value
);
890 // test that we can retrieve all cookies:
891 EXPECT_TRUE(this->SetCookie(cs
.get(), test_url
, "x=1"));
892 EXPECT_TRUE(this->SetCookie(cs
.get(), test_url
, "y=2"));
894 std::string result
= this->GetCookies(cs
.get(), test_url
);
895 EXPECT_FALSE(result
.empty());
896 EXPECT_NE(result
.find("x=1"), std::string::npos
) << result
;
897 EXPECT_NE(result
.find("y=2"), std::string::npos
) << result
;
900 TYPED_TEST_P(CookieStoreTest
, OverwritePersistentCookie
) {
901 GURL
url_google("http://www.google.com/");
902 GURL
url_chromium("http://chromium.org");
903 scoped_refptr
<CookieStore
> cs(this->GetCookieStore());
905 // Insert a cookie "a" for path "/path1"
906 EXPECT_TRUE(this->SetCookie(cs
.get(),
908 "a=val1; path=/path1; "
909 "expires=Mon, 18-Apr-22 22:50:13 GMT"));
911 // Insert a cookie "b" for path "/path1"
912 EXPECT_TRUE(this->SetCookie(cs
.get(),
914 "b=val1; path=/path1; "
915 "expires=Mon, 18-Apr-22 22:50:14 GMT"));
917 // Insert a cookie "b" for path "/path1", that is httponly. This should
918 // overwrite the non-http-only version.
919 CookieOptions allow_httponly
;
920 allow_httponly
.set_include_httponly();
921 EXPECT_TRUE(this->SetCookieWithOptions(cs
.get(),
923 "b=val2; path=/path1; httponly; "
924 "expires=Mon, 18-Apr-22 22:50:14 GMT",
927 // Insert a cookie "a" for path "/path1". This should overwrite.
928 EXPECT_TRUE(this->SetCookie(cs
.get(),
930 "a=val33; path=/path1; "
931 "expires=Mon, 18-Apr-22 22:50:14 GMT"));
933 // Insert a cookie "a" for path "/path2". This should NOT overwrite
934 // cookie "a", since the path is different.
935 EXPECT_TRUE(this->SetCookie(cs
.get(),
937 "a=val9; path=/path2; "
938 "expires=Mon, 18-Apr-22 22:50:14 GMT"));
940 // Insert a cookie "a" for path "/path1", but this time for "chromium.org".
941 // Although the name and path match, the hostnames do not, so shouldn't
943 EXPECT_TRUE(this->SetCookie(cs
.get(),
945 "a=val99; path=/path1; "
946 "expires=Mon, 18-Apr-22 22:50:14 GMT"));
948 if (TypeParam::supports_http_only
) {
949 this->MatchCookieLines(
951 this->GetCookies(cs
.get(), GURL("http://www.google.com/path1")));
953 this->MatchCookieLines(
955 this->GetCookies(cs
.get(), GURL("http://www.google.com/path1")));
957 this->MatchCookieLines(
959 this->GetCookies(cs
.get(), GURL("http://www.google.com/path2")));
960 this->MatchCookieLines(
961 "a=val99", this->GetCookies(cs
.get(), GURL("http://chromium.org/path1")));
964 TYPED_TEST_P(CookieStoreTest
, CookieOrdering
) {
965 // Put a random set of cookies into a store and make sure they're returned in
967 // Cookies should be sorted by path length and creation time, as per RFC6265.
968 scoped_refptr
<CookieStore
> cs(this->GetCookieStore());
969 EXPECT_TRUE(this->SetCookie(
970 cs
.get(), GURL("http://d.c.b.a.google.com/aa/x.html"), "c=1"));
971 EXPECT_TRUE(this->SetCookie(cs
.get(),
972 GURL("http://b.a.google.com/aa/bb/cc/x.html"),
973 "d=1; domain=b.a.google.com"));
974 base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(
975 TypeParam::creation_time_granularity_in_ms
));
976 EXPECT_TRUE(this->SetCookie(cs
.get(),
977 GURL("http://b.a.google.com/aa/bb/cc/x.html"),
978 "a=4; domain=b.a.google.com"));
979 base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(
980 TypeParam::creation_time_granularity_in_ms
));
981 EXPECT_TRUE(this->SetCookie(cs
.get(),
982 GURL("http://c.b.a.google.com/aa/bb/cc/x.html"),
983 "e=1; domain=c.b.a.google.com"));
984 EXPECT_TRUE(this->SetCookie(
985 cs
.get(), GURL("http://d.c.b.a.google.com/aa/bb/x.html"), "b=1"));
986 EXPECT_TRUE(this->SetCookie(
987 cs
.get(), GURL("http://news.bbc.co.uk/midpath/x.html"), "g=10"));
988 EXPECT_EQ("d=1; a=4; e=1; b=1; c=1",
989 this->GetCookies(cs
.get(),
990 GURL("http://d.c.b.a.google.com/aa/bb/cc/dd")));
993 TYPED_TEST_P(CookieStoreTest
, DeleteSessionCookie
) {
994 scoped_refptr
<CookieStore
> cs(this->GetCookieStore());
995 // Create a session cookie and a persistent cookie.
996 EXPECT_TRUE(this->SetCookie(
997 cs
.get(), this->url_google_
, std::string(kValidCookieLine
)));
998 EXPECT_TRUE(this->SetCookie(cs
.get(),
1000 "C=D; path=/; domain=google.izzle;"
1001 "expires=Mon, 18-Apr-22 22:50:13 GMT"));
1002 this->MatchCookieLines("A=B; C=D",
1003 this->GetCookies(cs
.get(), this->url_google_
));
1004 // Delete the session cookie.
1005 this->DeleteSessionCookies(cs
.get());
1006 // Check that the session cookie has been deleted but not the persistent one.
1007 EXPECT_EQ("C=D", this->GetCookies(cs
.get(), this->url_google_
));
1010 REGISTER_TYPED_TEST_CASE_P(CookieStoreTest
,
1013 DomainWithTrailingDotTest
,
1016 DomainWithoutLeadingDotTest
,
1017 CaseInsensitiveDomainTest
,
1019 TestNonDottedAndTLD
,
1020 TestHostEndsWithDot
,
1027 TestDeleteAllCreatedBetween
,
1028 TestDeleteAllCreatedBetweenForHost
,
1031 OverwritePersistentCookie
,
1033 DeleteSessionCookie
);
1035 template<class CookieStoreTestTraits
>
1036 class MultiThreadedCookieStoreTest
:
1037 public CookieStoreTest
<CookieStoreTestTraits
> {
1039 MultiThreadedCookieStoreTest() : other_thread_("CMTthread") {}
1041 // Helper methods for calling the asynchronous CookieStore methods
1042 // from a different thread.
1044 void GetCookiesTask(CookieStore
* cs
,
1046 StringResultCookieCallback
* callback
) {
1047 CookieOptions options
;
1048 if (!CookieStoreTestTraits::supports_http_only
)
1049 options
.set_include_httponly();
1050 cs
->GetCookiesWithOptionsAsync(
1052 base::Bind(&StringResultCookieCallback::Run
,
1053 base::Unretained(callback
)));
1056 void GetCookiesWithOptionsTask(CookieStore
* cs
,
1058 const CookieOptions
& options
,
1059 StringResultCookieCallback
* callback
) {
1060 cs
->GetCookiesWithOptionsAsync(
1062 base::Bind(&StringResultCookieCallback::Run
,
1063 base::Unretained(callback
)));
1066 void SetCookieWithOptionsTask(CookieStore
* cs
,
1068 const std::string
& cookie_line
,
1069 const CookieOptions
& options
,
1070 ResultSavingCookieCallback
<bool>* callback
) {
1071 cs
->SetCookieWithOptionsAsync(
1072 url
, cookie_line
, options
,
1074 &ResultSavingCookieCallback
<bool>::Run
,
1075 base::Unretained(callback
)));
1078 void DeleteCookieTask(CookieStore
* cs
,
1080 const std::string
& cookie_name
,
1081 NoResultCookieCallback
* callback
) {
1082 cs
->DeleteCookieAsync(
1084 base::Bind(&NoResultCookieCallback::Run
, base::Unretained(callback
)));
1087 void DeleteSessionCookiesTask(CookieStore
* cs
,
1088 ResultSavingCookieCallback
<int>* callback
) {
1089 cs
->DeleteSessionCookiesAsync(
1091 &ResultSavingCookieCallback
<int>::Run
,
1092 base::Unretained(callback
)));
1096 void RunOnOtherThread(const base::Closure
& task
) {
1097 other_thread_
.Start();
1098 other_thread_
.task_runner()->PostTask(FROM_HERE
, task
);
1099 CookieStoreTest
<CookieStoreTestTraits
>::RunFor(kTimeout
);
1100 other_thread_
.Stop();
1103 Thread other_thread_
;
1106 TYPED_TEST_CASE_P(MultiThreadedCookieStoreTest
);
1108 // TODO(ycxiao): Eventually, we will need to create a separate thread, create
1109 // the cookie store on that thread (or at least its store, i.e., the DB
1111 TYPED_TEST_P(MultiThreadedCookieStoreTest
, ThreadCheckGetCookies
) {
1112 scoped_refptr
<CookieStore
> cs(this->GetCookieStore());
1113 EXPECT_TRUE(this->SetCookie(cs
.get(), this->url_google_
, "A=B"));
1114 this->MatchCookieLines("A=B", this->GetCookies(cs
.get(), this->url_google_
));
1115 StringResultCookieCallback
callback(&this->other_thread_
);
1116 base::Closure task
=
1117 base::Bind(&MultiThreadedCookieStoreTest
<TypeParam
>::GetCookiesTask
,
1118 base::Unretained(this), cs
, this->url_google_
, &callback
);
1119 this->RunOnOtherThread(task
);
1120 EXPECT_TRUE(callback
.did_run());
1121 EXPECT_EQ("A=B", callback
.result());
1124 TYPED_TEST_P(MultiThreadedCookieStoreTest
, ThreadCheckGetCookiesWithOptions
) {
1125 scoped_refptr
<CookieStore
> cs(this->GetCookieStore());
1126 CookieOptions options
;
1127 if (!TypeParam::supports_http_only
)
1128 options
.set_include_httponly();
1129 EXPECT_TRUE(this->SetCookie(cs
.get(), this->url_google_
, "A=B"));
1130 this->MatchCookieLines(
1131 "A=B", this->GetCookiesWithOptions(cs
.get(), this->url_google_
, options
));
1132 StringResultCookieCallback
callback(&this->other_thread_
);
1133 base::Closure task
= base::Bind(
1134 &MultiThreadedCookieStoreTest
<TypeParam
>::GetCookiesWithOptionsTask
,
1135 base::Unretained(this), cs
, this->url_google_
, options
, &callback
);
1136 this->RunOnOtherThread(task
);
1137 EXPECT_TRUE(callback
.did_run());
1138 EXPECT_EQ("A=B", callback
.result());
1141 TYPED_TEST_P(MultiThreadedCookieStoreTest
, ThreadCheckSetCookieWithOptions
) {
1142 scoped_refptr
<CookieStore
> cs(this->GetCookieStore());
1143 CookieOptions options
;
1144 if (!TypeParam::supports_http_only
)
1145 options
.set_include_httponly();
1147 this->SetCookieWithOptions(cs
.get(), this->url_google_
, "A=B", options
));
1148 ResultSavingCookieCallback
<bool> callback(&this->other_thread_
);
1149 base::Closure task
= base::Bind(
1150 &MultiThreadedCookieStoreTest
<TypeParam
>::SetCookieWithOptionsTask
,
1151 base::Unretained(this), cs
, this->url_google_
, "A=B", options
, &callback
);
1152 this->RunOnOtherThread(task
);
1153 EXPECT_TRUE(callback
.did_run());
1154 EXPECT_TRUE(callback
.result());
1157 TYPED_TEST_P(MultiThreadedCookieStoreTest
, ThreadCheckDeleteCookie
) {
1158 scoped_refptr
<CookieStore
> cs(this->GetCookieStore());
1159 CookieOptions options
;
1160 if (!TypeParam::supports_http_only
)
1161 options
.set_include_httponly();
1163 this->SetCookieWithOptions(cs
.get(), this->url_google_
, "A=B", options
));
1164 this->DeleteCookie(cs
.get(), this->url_google_
, "A");
1166 this->SetCookieWithOptions(cs
.get(), this->url_google_
, "A=B", options
));
1167 NoResultCookieCallback
callback(&this->other_thread_
);
1168 base::Closure task
=
1169 base::Bind(&MultiThreadedCookieStoreTest
<TypeParam
>::DeleteCookieTask
,
1170 base::Unretained(this), cs
, this->url_google_
, "A", &callback
);
1171 this->RunOnOtherThread(task
);
1172 EXPECT_TRUE(callback
.did_run());
1175 TYPED_TEST_P(MultiThreadedCookieStoreTest
, ThreadCheckDeleteSessionCookies
) {
1176 scoped_refptr
<CookieStore
> cs(this->GetCookieStore());
1177 CookieOptions options
;
1178 if (!TypeParam::supports_http_only
)
1179 options
.set_include_httponly();
1181 this->SetCookieWithOptions(cs
.get(), this->url_google_
, "A=B", options
));
1183 this->SetCookieWithOptions(cs
.get(),
1185 "B=C; expires=Mon, 18-Apr-22 22:50:13 GMT",
1187 EXPECT_EQ(1, this->DeleteSessionCookies(cs
.get()));
1188 EXPECT_EQ(0, this->DeleteSessionCookies(cs
.get()));
1190 this->SetCookieWithOptions(cs
.get(), this->url_google_
, "A=B", options
));
1191 ResultSavingCookieCallback
<int> callback(&this->other_thread_
);
1192 base::Closure task
= base::Bind(
1193 &MultiThreadedCookieStoreTest
<TypeParam
>::DeleteSessionCookiesTask
,
1194 base::Unretained(this), cs
, &callback
);
1195 this->RunOnOtherThread(task
);
1196 EXPECT_TRUE(callback
.did_run());
1197 EXPECT_EQ(1, callback
.result());
1200 REGISTER_TYPED_TEST_CASE_P(MultiThreadedCookieStoreTest
,
1201 ThreadCheckGetCookies
,
1202 ThreadCheckGetCookiesWithOptions
,
1203 ThreadCheckSetCookieWithOptions
,
1204 ThreadCheckDeleteCookie
,
1205 ThreadCheckDeleteSessionCookies
);
1209 #endif // NET_COOKIES_COOKIE_STORE_UNITTEST_H_