Update include paths in miscellaneous content/ directories for base/process changes.
[chromium-blink-merge.git] / net / cookies / cookie_store_unittest.h
blob90999ecdc3171927164a44101515b8828a045930
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_
8 #include "base/bind.h"
9 #include "base/message_loop/message_loop.h"
10 #include "base/strings/string_tokenizer.h"
11 #include "base/threading/thread.h"
12 #include "net/cookies/cookie_monster.h"
13 #include "net/cookies/cookie_store.h"
14 #include "net/cookies/cookie_store_test_callbacks.h"
15 #include "testing/gtest/include/gtest/gtest.h"
16 #include "url/gurl.h"
18 // This file declares unittest templates that can be used to test common
19 // behavior of any CookieStore implementation.
20 // See cookie_monster_unittest.cc for an example of an implementation.
22 namespace net {
24 using base::Thread;
26 const int kTimeout = 1000;
28 const char kUrlFtp[] = "ftp://ftp.google.izzle/";
29 const char kUrlGoogle[] = "http://www.google.izzle";
30 const char kUrlGoogleFoo[] = "http://www.google.izzle/foo";
31 const char kUrlGoogleBar[] = "http://www.google.izzle/bar";
32 const char kUrlGoogleSecure[] = "https://www.google.izzle";
33 const char kValidCookieLine[] = "A=B; path=/";
34 const char kValidDomainCookieLine[] = "A=B; path=/; domain=google.izzle";
36 // The CookieStoreTestTraits must have the following members:
37 // struct CookieStoreTestTraits {
38 // // Factory function.
39 // static scoped_refptr<CookieStore> Create();
41 // // The cookie store is a CookieMonster. Only used to test
42 // // GetCookieMonster().
43 // static const bool is_cookie_monster;
45 // // The cookie store supports cookies with the exclude_httponly() option.
46 // static const bool supports_http_only;
48 // // The cookie store is able to make the difference between the ".com"
49 // // and the "com" domains.
50 // static const bool supports_non_dotted_domains;
52 // // The cookie store handles the domains with trailing dots (such as "com.")
53 // // correctly.
54 // static const bool supports_trailing_dots;
56 // // The cookie store rejects cookies for invalid schemes such as ftp.
57 // static const bool filters_schemes;
59 // // The cookie store has a bug happening when a path is a substring of
60 // // another.
61 // static const bool has_path_prefix_bug;
63 // // Time to wait between two cookie insertions to ensure that cookies have
64 // // different creation times.
65 // static const int creation_time_granularity_in_ms;
66 // };
68 template <class CookieStoreTestTraits>
69 class CookieStoreTest : public testing::Test {
70 protected:
71 CookieStoreTest()
72 : url_google_(kUrlGoogle),
73 url_google_secure_(kUrlGoogleSecure),
74 url_google_foo_(kUrlGoogleFoo),
75 url_google_bar_(kUrlGoogleBar) {
76 // This test may be used outside of the net test suite, and thus may not
77 // have a message loop.
78 if (!base::MessageLoop::current())
79 message_loop_.reset(new base::MessageLoop);
80 weak_factory_.reset(new base::WeakPtrFactory<base::MessageLoop>(
81 base::MessageLoop::current()));
84 // Helper methods for the asynchronous Cookie Store API that call the
85 // asynchronous method and then pump the loop until the callback is invoked,
86 // finally returning the value.
88 std::string GetCookies(CookieStore* cs, const GURL& url) {
89 DCHECK(cs);
90 CookieOptions options;
91 if (!CookieStoreTestTraits::supports_http_only)
92 options.set_include_httponly();
93 StringResultCookieCallback callback;
94 cs->GetCookiesWithOptionsAsync(
95 url, options,
96 base::Bind(&StringResultCookieCallback::Run,
97 base::Unretained(&callback)));
98 RunFor(kTimeout);
99 EXPECT_TRUE(callback.did_run());
100 return callback.result();
103 std::string GetCookiesWithOptions(CookieStore* cs,
104 const GURL& url,
105 const CookieOptions& options) {
106 DCHECK(cs);
107 StringResultCookieCallback callback;
108 cs->GetCookiesWithOptionsAsync(
109 url, options, base::Bind(&StringResultCookieCallback::Run,
110 base::Unretained(&callback)));
111 RunFor(kTimeout);
112 EXPECT_TRUE(callback.did_run());
113 return callback.result();
116 bool SetCookieWithOptions(CookieStore* cs,
117 const GURL& url,
118 const std::string& cookie_line,
119 const CookieOptions& options) {
120 DCHECK(cs);
121 BoolResultCookieCallback callback;
122 cs->SetCookieWithOptionsAsync(
123 url, cookie_line, options,
124 base::Bind(&BoolResultCookieCallback::Run,
125 base::Unretained(&callback)));
126 RunFor(kTimeout);
127 EXPECT_TRUE(callback.did_run());
128 return callback.result();
131 bool SetCookieWithServerTime(CookieStore* cs,
132 const GURL& url,
133 const std::string& cookie_line,
134 const base::Time& server_time) {
135 CookieOptions options;
136 if (!CookieStoreTestTraits::supports_http_only)
137 options.set_include_httponly();
138 options.set_server_time(server_time);
139 return SetCookieWithOptions(cs, url, cookie_line, options);
142 bool SetCookie(CookieStore* cs,
143 const GURL& url,
144 const std::string& cookie_line) {
145 CookieOptions options;
146 if (!CookieStoreTestTraits::supports_http_only)
147 options.set_include_httponly();
148 return SetCookieWithOptions(cs, url, cookie_line, options);
151 void DeleteCookie(CookieStore* cs,
152 const GURL& url,
153 const std::string& cookie_name) {
154 DCHECK(cs);
155 NoResultCookieCallback callback;
156 cs->DeleteCookieAsync(
157 url, cookie_name,
158 base::Bind(&NoResultCookieCallback::Run, base::Unretained(&callback)));
159 RunFor(kTimeout);
160 EXPECT_TRUE(callback.did_run());
163 int DeleteCreatedBetween(CookieStore* cs,
164 const base::Time& delete_begin,
165 const base::Time& delete_end) {
166 DCHECK(cs);
167 IntResultCookieCallback callback;
168 cs->DeleteAllCreatedBetweenAsync(
169 delete_begin, delete_end,
170 base::Bind(&IntResultCookieCallback::Run, base::Unretained(&callback)));
171 RunFor(kTimeout);
172 EXPECT_TRUE(callback.did_run());
173 return callback.result();
176 int DeleteSessionCookies(CookieStore* cs) {
177 DCHECK(cs);
178 IntResultCookieCallback callback;
179 cs->DeleteSessionCookiesAsync(
180 base::Bind(&IntResultCookieCallback::Run, base::Unretained(&callback)));
181 RunFor(kTimeout);
182 EXPECT_TRUE(callback.did_run());
183 return callback.result();
186 void RunFor(int ms) {
187 // Runs the test thread message loop for up to |ms| milliseconds.
188 base::MessageLoop::current()->PostDelayedTask(
189 FROM_HERE,
190 base::Bind(&base::MessageLoop::Quit, weak_factory_->GetWeakPtr()),
191 base::TimeDelta::FromMilliseconds(ms));
192 base::MessageLoop::current()->Run();
193 weak_factory_->InvalidateWeakPtrs();
196 scoped_refptr<CookieStore> GetCookieStore() {
197 return CookieStoreTestTraits::Create();
200 // Compares two cookie lines.
201 void MatchCookieLines(const std::string& line1, const std::string& line2) {
202 EXPECT_EQ(TokenizeCookieLine(line1), TokenizeCookieLine(line2));
205 // Check the cookie line by polling until equality or a timeout is reached.
206 void MatchCookieLineWithTimeout(CookieStore* cs,
207 const GURL& url,
208 const std::string& line) {
209 std::string cookies = GetCookies(cs, url);
210 bool matched = (TokenizeCookieLine(line) == TokenizeCookieLine(cookies));
211 base::Time polling_end_date = base::Time::Now() +
212 base::TimeDelta::FromMilliseconds(
213 CookieStoreTestTraits::creation_time_granularity_in_ms);
215 while (!matched && base::Time::Now() <= polling_end_date) {
216 base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(10));
217 cookies = GetCookies(cs, url);
218 matched = (TokenizeCookieLine(line) == TokenizeCookieLine(cookies));
221 EXPECT_TRUE(matched) << "\"" << cookies
222 << "\" does not match \"" << line << "\"";
225 GURL url_google_;
226 GURL url_google_secure_;
227 GURL url_google_foo_;
228 GURL url_google_bar_;
230 scoped_ptr<base::WeakPtrFactory<base::MessageLoop> > weak_factory_;
231 scoped_ptr<base::MessageLoop> message_loop_;
233 private:
234 // Returns a set of strings of type "name=value". Fails in case of duplicate.
235 std::set<std::string> TokenizeCookieLine(const std::string& line) {
236 std::set<std::string> tokens;
237 base::StringTokenizer tokenizer(line, " ;");
238 while (tokenizer.GetNext())
239 EXPECT_TRUE(tokens.insert(tokenizer.token()).second);
240 return tokens;
244 TYPED_TEST_CASE_P(CookieStoreTest);
246 TYPED_TEST_P(CookieStoreTest, TypeTest) {
247 scoped_refptr<CookieStore> cs(this->GetCookieStore());
248 EXPECT_EQ(cs->GetCookieMonster(),
249 (TypeParam::is_cookie_monster) ?
250 static_cast<CookieMonster*>(cs.get()) : NULL);
253 TYPED_TEST_P(CookieStoreTest, DomainTest) {
254 scoped_refptr<CookieStore> cs(this->GetCookieStore());
255 EXPECT_TRUE(this->SetCookie(cs.get(), this->url_google_, "A=B"));
256 this->MatchCookieLines("A=B", this->GetCookies(cs.get(), this->url_google_));
257 EXPECT_TRUE(this->SetCookie(
258 cs.get(), this->url_google_, "C=D; domain=.google.izzle"));
259 this->MatchCookieLines("A=B; C=D",
260 this->GetCookies(cs.get(), this->url_google_));
262 // Verify that A=B was set as a host cookie rather than a domain
263 // cookie -- should not be accessible from a sub sub-domain.
264 this->MatchCookieLines(
265 "C=D", this->GetCookies(cs.get(), GURL("http://foo.www.google.izzle")));
267 // Test and make sure we find domain cookies on the same domain.
268 EXPECT_TRUE(this->SetCookie(
269 cs.get(), this->url_google_, "E=F; domain=.www.google.izzle"));
270 this->MatchCookieLines("A=B; C=D; E=F",
271 this->GetCookies(cs.get(), this->url_google_));
273 // Test setting a domain= that doesn't start w/ a dot, should
274 // treat it as a domain cookie, as if there was a pre-pended dot.
275 EXPECT_TRUE(this->SetCookie(
276 cs.get(), this->url_google_, "G=H; domain=www.google.izzle"));
277 this->MatchCookieLines("A=B; C=D; E=F; G=H",
278 this->GetCookies(cs.get(), this->url_google_));
280 // Test domain enforcement, should fail on a sub-domain or something too deep.
281 EXPECT_FALSE(
282 this->SetCookie(cs.get(), this->url_google_, "I=J; domain=.izzle"));
283 this->MatchCookieLines(std::string(),
284 this->GetCookies(cs.get(), GURL("http://a.izzle")));
285 EXPECT_FALSE(this->SetCookie(
286 cs.get(), this->url_google_, "K=L; domain=.bla.www.google.izzle"));
287 this->MatchCookieLines(
288 "C=D; E=F; G=H",
289 this->GetCookies(cs.get(), GURL("http://bla.www.google.izzle")));
290 this->MatchCookieLines("A=B; C=D; E=F; G=H",
291 this->GetCookies(cs.get(), this->url_google_));
294 // FireFox recognizes domains containing trailing periods as valid.
295 // IE and Safari do not. Assert the expected policy here.
296 TYPED_TEST_P(CookieStoreTest, DomainWithTrailingDotTest) {
297 scoped_refptr<CookieStore> cs(this->GetCookieStore());
298 EXPECT_FALSE(this->SetCookie(
299 cs.get(), this->url_google_, "a=1; domain=.www.google.com."));
300 EXPECT_FALSE(this->SetCookie(
301 cs.get(), this->url_google_, "b=2; domain=.www.google.com.."));
302 this->MatchCookieLines(std::string(),
303 this->GetCookies(cs.get(), this->url_google_));
306 // Test that cookies can bet set on higher level domains.
307 // http://b/issue?id=896491
308 TYPED_TEST_P(CookieStoreTest, ValidSubdomainTest) {
309 scoped_refptr<CookieStore> cs(this->GetCookieStore());
310 GURL url_abcd("http://a.b.c.d.com");
311 GURL url_bcd("http://b.c.d.com");
312 GURL url_cd("http://c.d.com");
313 GURL url_d("http://d.com");
315 EXPECT_TRUE(this->SetCookie(cs.get(), url_abcd, "a=1; domain=.a.b.c.d.com"));
316 EXPECT_TRUE(this->SetCookie(cs.get(), url_abcd, "b=2; domain=.b.c.d.com"));
317 EXPECT_TRUE(this->SetCookie(cs.get(), url_abcd, "c=3; domain=.c.d.com"));
318 EXPECT_TRUE(this->SetCookie(cs.get(), url_abcd, "d=4; domain=.d.com"));
320 this->MatchCookieLines("a=1; b=2; c=3; d=4",
321 this->GetCookies(cs.get(), url_abcd));
322 this->MatchCookieLines("b=2; c=3; d=4", this->GetCookies(cs.get(), url_bcd));
323 this->MatchCookieLines("c=3; d=4", this->GetCookies(cs.get(), url_cd));
324 this->MatchCookieLines("d=4", this->GetCookies(cs.get(), url_d));
326 // Check that the same cookie can exist on different sub-domains.
327 EXPECT_TRUE(this->SetCookie(cs.get(), url_bcd, "X=bcd; domain=.b.c.d.com"));
328 EXPECT_TRUE(this->SetCookie(cs.get(), url_bcd, "X=cd; domain=.c.d.com"));
329 this->MatchCookieLines("b=2; c=3; d=4; X=bcd; X=cd",
330 this->GetCookies(cs.get(), url_bcd));
331 this->MatchCookieLines("c=3; d=4; X=cd", this->GetCookies(cs.get(), url_cd));
334 // Test that setting a cookie which specifies an invalid domain has
335 // no side-effect. An invalid domain in this context is one which does
336 // not match the originating domain.
337 // http://b/issue?id=896472
338 TYPED_TEST_P(CookieStoreTest, InvalidDomainTest) {
340 scoped_refptr<CookieStore> cs(this->GetCookieStore());
341 GURL url_foobar("http://foo.bar.com");
343 // More specific sub-domain than allowed.
344 EXPECT_FALSE(
345 this->SetCookie(cs.get(), url_foobar, "a=1; domain=.yo.foo.bar.com"));
347 EXPECT_FALSE(this->SetCookie(cs.get(), url_foobar, "b=2; domain=.foo.com"));
348 EXPECT_FALSE(
349 this->SetCookie(cs.get(), url_foobar, "c=3; domain=.bar.foo.com"));
351 // Different TLD, but the rest is a substring.
352 EXPECT_FALSE(
353 this->SetCookie(cs.get(), url_foobar, "d=4; domain=.foo.bar.com.net"));
355 // A substring that isn't really a parent domain.
356 EXPECT_FALSE(this->SetCookie(cs.get(), url_foobar, "e=5; domain=ar.com"));
358 // Completely invalid domains:
359 EXPECT_FALSE(this->SetCookie(cs.get(), url_foobar, "f=6; domain=."));
360 EXPECT_FALSE(this->SetCookie(cs.get(), url_foobar, "g=7; domain=/"));
361 EXPECT_FALSE(this->SetCookie(
362 cs.get(), url_foobar, "h=8; domain=http://foo.bar.com"));
363 EXPECT_FALSE(
364 this->SetCookie(cs.get(), url_foobar, "i=9; domain=..foo.bar.com"));
365 EXPECT_FALSE(
366 this->SetCookie(cs.get(), url_foobar, "j=10; domain=..bar.com"));
368 // Make sure there isn't something quirky in the domain canonicalization
369 // that supports full URL semantics.
370 EXPECT_FALSE(this->SetCookie(
371 cs.get(), url_foobar, "k=11; domain=.foo.bar.com?blah"));
372 EXPECT_FALSE(this->SetCookie(
373 cs.get(), url_foobar, "l=12; domain=.foo.bar.com/blah"));
374 EXPECT_FALSE(
375 this->SetCookie(cs.get(), url_foobar, "m=13; domain=.foo.bar.com:80"));
376 EXPECT_FALSE(
377 this->SetCookie(cs.get(), url_foobar, "n=14; domain=.foo.bar.com:"));
378 EXPECT_FALSE(
379 this->SetCookie(cs.get(), url_foobar, "o=15; domain=.foo.bar.com#sup"));
381 this->MatchCookieLines(std::string(),
382 this->GetCookies(cs.get(), url_foobar));
386 // Make sure the cookie code hasn't gotten its subdomain string handling
387 // reversed, missed a suffix check, etc. It's important here that the two
388 // hosts below have the same domain + registry.
389 scoped_refptr<CookieStore> cs(this->GetCookieStore());
390 GURL url_foocom("http://foo.com.com");
391 EXPECT_FALSE(
392 this->SetCookie(cs.get(), url_foocom, "a=1; domain=.foo.com.com.com"));
393 this->MatchCookieLines(std::string(),
394 this->GetCookies(cs.get(), url_foocom));
398 // Test the behavior of omitting dot prefix from domain, should
399 // function the same as FireFox.
400 // http://b/issue?id=889898
401 TYPED_TEST_P(CookieStoreTest, DomainWithoutLeadingDotTest) {
402 { // The omission of dot results in setting a domain cookie.
403 scoped_refptr<CookieStore> cs(this->GetCookieStore());
404 GURL url_hosted("http://manage.hosted.filefront.com");
405 GURL url_filefront("http://www.filefront.com");
406 EXPECT_TRUE(
407 this->SetCookie(cs.get(), url_hosted, "sawAd=1; domain=filefront.com"));
408 this->MatchCookieLines("sawAd=1", this->GetCookies(cs.get(), url_hosted));
409 this->MatchCookieLines("sawAd=1",
410 this->GetCookies(cs.get(), url_filefront));
413 { // Even when the domains match exactly, don't consider it host cookie.
414 scoped_refptr<CookieStore> cs(this->GetCookieStore());
415 GURL url("http://www.google.com");
416 EXPECT_TRUE(this->SetCookie(cs.get(), url, "a=1; domain=www.google.com"));
417 this->MatchCookieLines("a=1", this->GetCookies(cs.get(), url));
418 this->MatchCookieLines(
419 "a=1", this->GetCookies(cs.get(), GURL("http://sub.www.google.com")));
420 this->MatchCookieLines(
421 std::string(),
422 this->GetCookies(cs.get(), GURL("http://something-else.com")));
426 // Test that the domain specified in cookie string is treated case-insensitive
427 // http://b/issue?id=896475.
428 TYPED_TEST_P(CookieStoreTest, CaseInsensitiveDomainTest) {
429 scoped_refptr<CookieStore> cs(this->GetCookieStore());
430 GURL url("http://www.google.com");
431 EXPECT_TRUE(this->SetCookie(cs.get(), url, "a=1; domain=.GOOGLE.COM"));
432 EXPECT_TRUE(this->SetCookie(cs.get(), url, "b=2; domain=.wWw.gOOgLE.coM"));
433 this->MatchCookieLines("a=1; b=2", this->GetCookies(cs.get(), url));
436 TYPED_TEST_P(CookieStoreTest, TestIpAddress) {
437 GURL url_ip("http://1.2.3.4/weee");
439 scoped_refptr<CookieStore> cs(this->GetCookieStore());
440 EXPECT_TRUE(this->SetCookie(cs.get(), url_ip, kValidCookieLine));
441 this->MatchCookieLines("A=B", this->GetCookies(cs.get(), url_ip));
444 { // IP addresses should not be able to set domain cookies.
445 scoped_refptr<CookieStore> cs(this->GetCookieStore());
446 EXPECT_FALSE(this->SetCookie(cs.get(), url_ip, "b=2; domain=.1.2.3.4"));
447 EXPECT_FALSE(this->SetCookie(cs.get(), url_ip, "c=3; domain=.3.4"));
448 this->MatchCookieLines(std::string(), this->GetCookies(cs.get(), url_ip));
449 // It should be allowed to set a cookie if domain= matches the IP address
450 // exactly. This matches IE/Firefox, even though it seems a bit wrong.
451 EXPECT_FALSE(this->SetCookie(cs.get(), url_ip, "b=2; domain=1.2.3.3"));
452 this->MatchCookieLines(std::string(), this->GetCookies(cs.get(), url_ip));
453 EXPECT_TRUE(this->SetCookie(cs.get(), url_ip, "b=2; domain=1.2.3.4"));
454 this->MatchCookieLines("b=2", this->GetCookies(cs.get(), url_ip));
458 // Test host cookies, and setting of cookies on TLD.
459 TYPED_TEST_P(CookieStoreTest, TestNonDottedAndTLD) {
461 scoped_refptr<CookieStore> cs(this->GetCookieStore());
462 GURL url("http://com/");
463 // Allow setting on "com", (but only as a host cookie).
464 EXPECT_TRUE(this->SetCookie(cs.get(), url, "a=1"));
465 EXPECT_FALSE(this->SetCookie(cs.get(), url, "b=2; domain=.com"));
466 EXPECT_FALSE(this->SetCookie(cs.get(), url, "c=3; domain=com"));
467 this->MatchCookieLines("a=1", this->GetCookies(cs.get(), url));
468 // Make sure it doesn't show up for a normal .com, it should be a host
469 // not a domain cookie.
470 this->MatchCookieLines(
471 std::string(),
472 this->GetCookies(cs.get(), GURL("http://hopefully-no-cookies.com/")));
473 if (TypeParam::supports_non_dotted_domains) {
474 this->MatchCookieLines(std::string(),
475 this->GetCookies(cs.get(), GURL("http://.com/")));
480 // http://com. should be treated the same as http://com.
481 scoped_refptr<CookieStore> cs(this->GetCookieStore());
482 GURL url("http://com./index.html");
483 if (TypeParam::supports_trailing_dots) {
484 EXPECT_TRUE(this->SetCookie(cs.get(), url, "a=1"));
485 this->MatchCookieLines("a=1", this->GetCookies(cs.get(), url));
486 this->MatchCookieLines(
487 std::string(),
488 this->GetCookies(cs.get(),
489 GURL("http://hopefully-no-cookies.com./")));
490 } else {
491 EXPECT_FALSE(this->SetCookie(cs.get(), url, "a=1"));
495 { // Should not be able to set host cookie from a subdomain.
496 scoped_refptr<CookieStore> cs(this->GetCookieStore());
497 GURL url("http://a.b");
498 EXPECT_FALSE(this->SetCookie(cs.get(), url, "a=1; domain=.b"));
499 EXPECT_FALSE(this->SetCookie(cs.get(), url, "b=2; domain=b"));
500 this->MatchCookieLines(std::string(), this->GetCookies(cs.get(), url));
503 { // Same test as above, but explicitly on a known TLD (com).
504 scoped_refptr<CookieStore> cs(this->GetCookieStore());
505 GURL url("http://google.com");
506 EXPECT_FALSE(this->SetCookie(cs.get(), url, "a=1; domain=.com"));
507 EXPECT_FALSE(this->SetCookie(cs.get(), url, "b=2; domain=com"));
508 this->MatchCookieLines(std::string(), this->GetCookies(cs.get(), url));
511 { // Make sure can't set cookie on TLD which is dotted.
512 scoped_refptr<CookieStore> cs(this->GetCookieStore());
513 GURL url("http://google.co.uk");
514 EXPECT_FALSE(this->SetCookie(cs.get(), url, "a=1; domain=.co.uk"));
515 EXPECT_FALSE(this->SetCookie(cs.get(), url, "b=2; domain=.uk"));
516 this->MatchCookieLines(std::string(), this->GetCookies(cs.get(), url));
517 this->MatchCookieLines(
518 std::string(),
519 this->GetCookies(cs.get(), GURL("http://something-else.co.uk")));
520 this->MatchCookieLines(
521 std::string(),
522 this->GetCookies(cs.get(), GURL("http://something-else.uk")));
525 { // Intranet URLs should only be able to set host cookies.
526 scoped_refptr<CookieStore> cs(this->GetCookieStore());
527 GURL url("http://b");
528 EXPECT_TRUE(this->SetCookie(cs.get(), url, "a=1"));
529 EXPECT_FALSE(this->SetCookie(cs.get(), url, "b=2; domain=.b"));
530 EXPECT_FALSE(this->SetCookie(cs.get(), url, "c=3; domain=b"));
531 this->MatchCookieLines("a=1", this->GetCookies(cs.get(), url));
535 // Test reading/writing cookies when the domain ends with a period,
536 // as in "www.google.com."
537 TYPED_TEST_P(CookieStoreTest, TestHostEndsWithDot) {
538 scoped_refptr<CookieStore> cs(this->GetCookieStore());
539 GURL url("http://www.google.com");
540 GURL url_with_dot("http://www.google.com.");
541 EXPECT_TRUE(this->SetCookie(cs.get(), url, "a=1"));
542 this->MatchCookieLines("a=1", this->GetCookies(cs.get(), url));
544 if (TypeParam::supports_trailing_dots) {
545 // Do not share cookie space with the dot version of domain.
546 // Note: this is not what FireFox does, but it _is_ what IE+Safari do.
547 EXPECT_FALSE(
548 this->SetCookie(cs.get(), url, "b=2; domain=.www.google.com."));
549 this->MatchCookieLines("a=1", this->GetCookies(cs.get(), url));
551 EXPECT_TRUE(
552 this->SetCookie(cs.get(), url_with_dot, "b=2; domain=.google.com."));
553 this->MatchCookieLines("b=2", this->GetCookies(cs.get(), url_with_dot));
554 } else {
555 EXPECT_TRUE(this->SetCookie(cs.get(), url, "b=2; domain=.www.google.com."));
556 EXPECT_FALSE(
557 this->SetCookie(cs.get(), url_with_dot, "b=2; domain=.google.com."));
560 // Make sure there weren't any side effects.
561 this->MatchCookieLines(
562 std::string(),
563 this->GetCookies(cs.get(), GURL("http://hopefully-no-cookies.com/")));
564 this->MatchCookieLines(std::string(),
565 this->GetCookies(cs.get(), GURL("http://.com/")));
568 TYPED_TEST_P(CookieStoreTest, InvalidScheme) {
569 if (!TypeParam::filters_schemes)
570 return;
572 scoped_refptr<CookieStore> cs(this->GetCookieStore());
573 EXPECT_FALSE(this->SetCookie(cs.get(), GURL(kUrlFtp), kValidCookieLine));
576 TYPED_TEST_P(CookieStoreTest, InvalidScheme_Read) {
577 if (!TypeParam::filters_schemes)
578 return;
580 scoped_refptr<CookieStore> cs(this->GetCookieStore());
581 EXPECT_TRUE(
582 this->SetCookie(cs.get(), GURL(kUrlGoogle), kValidDomainCookieLine));
583 this->MatchCookieLines(std::string(),
584 this->GetCookies(cs.get(), GURL(kUrlFtp)));
587 TYPED_TEST_P(CookieStoreTest, PathTest) {
588 scoped_refptr<CookieStore> cs(this->GetCookieStore());
589 std::string url("http://www.google.izzle");
590 EXPECT_TRUE(this->SetCookie(cs.get(), GURL(url), "A=B; path=/wee"));
591 this->MatchCookieLines("A=B", this->GetCookies(cs.get(), GURL(url + "/wee")));
592 this->MatchCookieLines("A=B",
593 this->GetCookies(cs.get(), GURL(url + "/wee/")));
594 this->MatchCookieLines("A=B",
595 this->GetCookies(cs.get(), GURL(url + "/wee/war")));
596 this->MatchCookieLines(
597 "A=B", this->GetCookies(cs.get(), GURL(url + "/wee/war/more/more")));
598 if (!TypeParam::has_path_prefix_bug)
599 this->MatchCookieLines(std::string(),
600 this->GetCookies(cs.get(), GURL(url + "/weehee")));
601 this->MatchCookieLines(std::string(),
602 this->GetCookies(cs.get(), GURL(url + "/")));
604 // If we add a 0 length path, it should default to /
605 EXPECT_TRUE(this->SetCookie(cs.get(), GURL(url), "A=C; path="));
606 this->MatchCookieLines("A=B; A=C",
607 this->GetCookies(cs.get(), GURL(url + "/wee")));
608 this->MatchCookieLines("A=C", this->GetCookies(cs.get(), GURL(url + "/")));
611 TYPED_TEST_P(CookieStoreTest, EmptyExpires) {
612 scoped_refptr<CookieStore> cs(this->GetCookieStore());
613 CookieOptions options;
614 if (!TypeParam::supports_http_only)
615 options.set_include_httponly();
616 GURL url("http://www7.ipdl.inpit.go.jp/Tokujitu/tjkta.ipdl?N0000=108");
617 std::string set_cookie_line =
618 "ACSTM=20130308043820420042; path=/; domain=ipdl.inpit.go.jp; Expires=";
619 std::string cookie_line = "ACSTM=20130308043820420042";
621 this->SetCookieWithOptions(cs.get(), url, set_cookie_line, options);
622 this->MatchCookieLines(cookie_line,
623 this->GetCookiesWithOptions(cs.get(), url, options));
625 options.set_server_time(base::Time::Now() - base::TimeDelta::FromHours(1));
626 this->SetCookieWithOptions(cs.get(), url, set_cookie_line, options);
627 this->MatchCookieLines(cookie_line,
628 this->GetCookiesWithOptions(cs.get(), url, options));
630 options.set_server_time(base::Time::Now() + base::TimeDelta::FromHours(1));
631 this->SetCookieWithOptions(cs.get(), url, set_cookie_line, options);
632 this->MatchCookieLines(cookie_line,
633 this->GetCookiesWithOptions(cs.get(), url, options));
636 TYPED_TEST_P(CookieStoreTest, HttpOnlyTest) {
637 if (!TypeParam::supports_http_only)
638 return;
640 scoped_refptr<CookieStore> cs(this->GetCookieStore());
641 CookieOptions options;
642 options.set_include_httponly();
644 // Create a httponly cookie.
645 EXPECT_TRUE(this->SetCookieWithOptions(
646 cs.get(), this->url_google_, "A=B; httponly", options));
648 // Check httponly read protection.
649 this->MatchCookieLines(std::string(),
650 this->GetCookies(cs.get(), this->url_google_));
651 this->MatchCookieLines(
652 "A=B", this->GetCookiesWithOptions(cs.get(), this->url_google_, options));
654 // Check httponly overwrite protection.
655 EXPECT_FALSE(this->SetCookie(cs.get(), this->url_google_, "A=C"));
656 this->MatchCookieLines(std::string(),
657 this->GetCookies(cs.get(), this->url_google_));
658 this->MatchCookieLines(
659 "A=B", this->GetCookiesWithOptions(cs.get(), this->url_google_, options));
660 EXPECT_TRUE(
661 this->SetCookieWithOptions(cs.get(), this->url_google_, "A=C", options));
662 this->MatchCookieLines("A=C", this->GetCookies(cs.get(), this->url_google_));
664 // Check httponly create protection.
665 EXPECT_FALSE(this->SetCookie(cs.get(), this->url_google_, "B=A; httponly"));
666 this->MatchCookieLines(
667 "A=C", this->GetCookiesWithOptions(cs.get(), this->url_google_, options));
668 EXPECT_TRUE(this->SetCookieWithOptions(
669 cs.get(), this->url_google_, "B=A; httponly", options));
670 this->MatchCookieLines(
671 "A=C; B=A",
672 this->GetCookiesWithOptions(cs.get(), this->url_google_, options));
673 this->MatchCookieLines("A=C", this->GetCookies(cs.get(), this->url_google_));
676 TYPED_TEST_P(CookieStoreTest, TestCookieDeletion) {
677 scoped_refptr<CookieStore> cs(this->GetCookieStore());
679 // Create a session cookie.
680 EXPECT_TRUE(this->SetCookie(cs.get(), this->url_google_, kValidCookieLine));
681 this->MatchCookieLines("A=B", this->GetCookies(cs.get(), this->url_google_));
682 // Delete it via Max-Age.
683 EXPECT_TRUE(this->SetCookie(cs.get(),
684 this->url_google_,
685 std::string(kValidCookieLine) + "; max-age=0"));
686 this->MatchCookieLineWithTimeout(cs.get(), this->url_google_, std::string());
688 // Create a session cookie.
689 EXPECT_TRUE(this->SetCookie(cs.get(), this->url_google_, kValidCookieLine));
690 this->MatchCookieLines("A=B", this->GetCookies(cs.get(), this->url_google_));
691 // Delete it via Expires.
692 EXPECT_TRUE(this->SetCookie(cs.get(),
693 this->url_google_,
694 std::string(kValidCookieLine) +
695 "; expires=Mon, 18-Apr-1977 22:50:13 GMT"));
696 this->MatchCookieLines(std::string(),
697 this->GetCookies(cs.get(), this->url_google_));
699 // Create a persistent cookie.
700 EXPECT_TRUE(this->SetCookie(
701 cs.get(),
702 this->url_google_,
703 std::string(kValidCookieLine) + "; expires=Mon, 18-Apr-22 22:50:13 GMT"));
705 this->MatchCookieLines("A=B", this->GetCookies(cs.get(), this->url_google_));
706 // Delete it via Max-Age.
707 EXPECT_TRUE(this->SetCookie(cs.get(),
708 this->url_google_,
709 std::string(kValidCookieLine) + "; max-age=0"));
710 this->MatchCookieLineWithTimeout(cs.get(), this->url_google_, std::string());
712 // Create a persistent cookie.
713 EXPECT_TRUE(this->SetCookie(
714 cs.get(),
715 this->url_google_,
716 std::string(kValidCookieLine) + "; expires=Mon, 18-Apr-22 22:50:13 GMT"));
717 this->MatchCookieLines("A=B", this->GetCookies(cs.get(), this->url_google_));
718 // Delete it via Expires.
719 EXPECT_TRUE(this->SetCookie(cs.get(),
720 this->url_google_,
721 std::string(kValidCookieLine) +
722 "; expires=Mon, 18-Apr-1977 22:50:13 GMT"));
723 this->MatchCookieLines(std::string(),
724 this->GetCookies(cs.get(), this->url_google_));
726 // Create a persistent cookie.
727 EXPECT_TRUE(this->SetCookie(
728 cs.get(),
729 this->url_google_,
730 std::string(kValidCookieLine) + "; expires=Mon, 18-Apr-22 22:50:13 GMT"));
731 this->MatchCookieLines("A=B", this->GetCookies(cs.get(), this->url_google_));
732 // Check that it is not deleted with significant enough clock skew.
733 base::Time server_time;
734 EXPECT_TRUE(base::Time::FromString("Sun, 17-Apr-1977 22:50:13 GMT",
735 &server_time));
736 EXPECT_TRUE(this->SetCookieWithServerTime(
737 cs.get(),
738 this->url_google_,
739 std::string(kValidCookieLine) + "; expires=Mon, 18-Apr-1977 22:50:13 GMT",
740 server_time));
741 this->MatchCookieLines("A=B", this->GetCookies(cs.get(), this->url_google_));
743 // Create a persistent cookie.
744 EXPECT_TRUE(this->SetCookie(
745 cs.get(),
746 this->url_google_,
747 std::string(kValidCookieLine) + "; expires=Mon, 18-Apr-22 22:50:13 GMT"));
748 this->MatchCookieLines("A=B", this->GetCookies(cs.get(), this->url_google_));
749 // Delete it via Expires, with a unix epoch of 0.
750 EXPECT_TRUE(this->SetCookie(cs.get(),
751 this->url_google_,
752 std::string(kValidCookieLine) +
753 "; expires=Thu, 1-Jan-1970 00:00:00 GMT"));
754 this->MatchCookieLines(std::string(),
755 this->GetCookies(cs.get(), this->url_google_));
758 TYPED_TEST_P(CookieStoreTest, TestDeleteAllCreatedBetween) {
759 scoped_refptr<CookieStore> cs(this->GetCookieStore());
760 const base::Time last_month = base::Time::Now() -
761 base::TimeDelta::FromDays(30);
762 const base::Time last_minute = base::Time::Now() -
763 base::TimeDelta::FromMinutes(1);
764 const base::Time next_minute = base::Time::Now() +
765 base::TimeDelta::FromMinutes(1);
766 const base::Time next_month = base::Time::Now() +
767 base::TimeDelta::FromDays(30);
769 // Add a cookie.
770 EXPECT_TRUE(this->SetCookie(cs.get(), this->url_google_, "A=B"));
771 // Check that the cookie is in the store.
772 this->MatchCookieLines("A=B", this->GetCookies(cs.get(), this->url_google_));
774 // Remove cookies in empty intervals.
775 EXPECT_EQ(0, this->DeleteCreatedBetween(cs.get(), last_month, last_minute));
776 EXPECT_EQ(0, this->DeleteCreatedBetween(cs.get(), next_minute, next_month));
777 // Check that the cookie is still there.
778 this->MatchCookieLines("A=B", this->GetCookies(cs.get(), this->url_google_));
780 // Remove the cookie with an interval defined by two dates.
781 EXPECT_EQ(1, this->DeleteCreatedBetween(cs.get(), last_minute, next_minute));
782 // Check that the cookie disappeared.
783 this->MatchCookieLines(std::string(),
784 this->GetCookies(cs.get(), this->url_google_));
786 // Add another cookie.
787 EXPECT_TRUE(this->SetCookie(cs.get(), this->url_google_, "C=D"));
788 // Check that the cookie is in the store.
789 this->MatchCookieLines("C=D", this->GetCookies(cs.get(), this->url_google_));
791 // Remove the cookie with a null ending time.
792 EXPECT_EQ(1, this->DeleteCreatedBetween(cs.get(), last_minute, base::Time()));
793 // Check that the cookie disappeared.
794 this->MatchCookieLines(std::string(),
795 this->GetCookies(cs.get(), this->url_google_));
798 TYPED_TEST_P(CookieStoreTest, TestSecure) {
799 scoped_refptr<CookieStore> cs(this->GetCookieStore());
801 EXPECT_TRUE(this->SetCookie(cs.get(), this->url_google_, "A=B"));
802 this->MatchCookieLines("A=B",
803 this->GetCookies(cs.get(), this->url_google_));
804 this->MatchCookieLines(
805 "A=B", this->GetCookies(cs.get(), this->url_google_secure_));
807 EXPECT_TRUE(
808 this->SetCookie(cs.get(), this->url_google_secure_, "A=B; secure"));
809 // The secure should overwrite the non-secure.
810 this->MatchCookieLines(std::string(),
811 this->GetCookies(cs.get(), this->url_google_));
812 this->MatchCookieLines("A=B",
813 this->GetCookies(cs.get(), this->url_google_secure_));
815 EXPECT_TRUE(
816 this->SetCookie(cs.get(), this->url_google_secure_, "D=E; secure"));
817 this->MatchCookieLines(std::string(),
818 this->GetCookies(cs.get(), this->url_google_));
819 this->MatchCookieLines("A=B; D=E",
820 this->GetCookies(cs.get(), this->url_google_secure_));
822 EXPECT_TRUE(this->SetCookie(cs.get(), this->url_google_secure_, "A=B"));
823 // The non-secure should overwrite the secure.
824 this->MatchCookieLines("A=B", this->GetCookies(cs.get(), this->url_google_));
825 this->MatchCookieLines("D=E; A=B",
826 this->GetCookies(cs.get(), this->url_google_secure_));
829 static const int kLastAccessThresholdMilliseconds = 200;
831 // Formerly NetUtilTest.CookieTest back when we used wininet's cookie handling.
832 TYPED_TEST_P(CookieStoreTest, NetUtilCookieTest) {
833 const GURL test_url("http://mojo.jojo.google.izzle/");
835 scoped_refptr<CookieStore> cs(this->GetCookieStore());
837 EXPECT_TRUE(this->SetCookie(cs.get(), test_url, "foo=bar"));
838 std::string value = this->GetCookies(cs.get(), test_url);
839 this->MatchCookieLines("foo=bar", value);
841 // test that we can retrieve all cookies:
842 EXPECT_TRUE(this->SetCookie(cs.get(), test_url, "x=1"));
843 EXPECT_TRUE(this->SetCookie(cs.get(), test_url, "y=2"));
845 std::string result = this->GetCookies(cs.get(), test_url);
846 EXPECT_FALSE(result.empty());
847 EXPECT_NE(result.find("x=1"), std::string::npos) << result;
848 EXPECT_NE(result.find("y=2"), std::string::npos) << result;
851 TYPED_TEST_P(CookieStoreTest, OverwritePersistentCookie) {
852 GURL url_google("http://www.google.com/");
853 GURL url_chromium("http://chromium.org");
854 scoped_refptr<CookieStore> cs(this->GetCookieStore());
856 // Insert a cookie "a" for path "/path1"
857 EXPECT_TRUE(this->SetCookie(cs.get(),
858 url_google,
859 "a=val1; path=/path1; "
860 "expires=Mon, 18-Apr-22 22:50:13 GMT"));
862 // Insert a cookie "b" for path "/path1"
863 EXPECT_TRUE(this->SetCookie(cs.get(),
864 url_google,
865 "b=val1; path=/path1; "
866 "expires=Mon, 18-Apr-22 22:50:14 GMT"));
868 // Insert a cookie "b" for path "/path1", that is httponly. This should
869 // overwrite the non-http-only version.
870 CookieOptions allow_httponly;
871 allow_httponly.set_include_httponly();
872 EXPECT_TRUE(this->SetCookieWithOptions(cs.get(),
873 url_google,
874 "b=val2; path=/path1; httponly; "
875 "expires=Mon, 18-Apr-22 22:50:14 GMT",
876 allow_httponly));
878 // Insert a cookie "a" for path "/path1". This should overwrite.
879 EXPECT_TRUE(this->SetCookie(cs.get(),
880 url_google,
881 "a=val33; path=/path1; "
882 "expires=Mon, 18-Apr-22 22:50:14 GMT"));
884 // Insert a cookie "a" for path "/path2". This should NOT overwrite
885 // cookie "a", since the path is different.
886 EXPECT_TRUE(this->SetCookie(cs.get(),
887 url_google,
888 "a=val9; path=/path2; "
889 "expires=Mon, 18-Apr-22 22:50:14 GMT"));
891 // Insert a cookie "a" for path "/path1", but this time for "chromium.org".
892 // Although the name and path match, the hostnames do not, so shouldn't
893 // overwrite.
894 EXPECT_TRUE(this->SetCookie(cs.get(),
895 url_chromium,
896 "a=val99; path=/path1; "
897 "expires=Mon, 18-Apr-22 22:50:14 GMT"));
899 if (TypeParam::supports_http_only) {
900 this->MatchCookieLines(
901 "a=val33",
902 this->GetCookies(cs.get(), GURL("http://www.google.com/path1")));
903 } else {
904 this->MatchCookieLines(
905 "a=val33; b=val2",
906 this->GetCookies(cs.get(), GURL("http://www.google.com/path1")));
908 this->MatchCookieLines(
909 "a=val9",
910 this->GetCookies(cs.get(), GURL("http://www.google.com/path2")));
911 this->MatchCookieLines(
912 "a=val99", this->GetCookies(cs.get(), GURL("http://chromium.org/path1")));
915 TYPED_TEST_P(CookieStoreTest, CookieOrdering) {
916 // Put a random set of cookies into a store and make sure they're returned in
917 // the right order.
918 // Cookies should be sorted by path length and creation time, as per RFC6265.
919 scoped_refptr<CookieStore> cs(this->GetCookieStore());
920 EXPECT_TRUE(this->SetCookie(
921 cs.get(), GURL("http://d.c.b.a.google.com/aa/x.html"), "c=1"));
922 EXPECT_TRUE(this->SetCookie(cs.get(),
923 GURL("http://b.a.google.com/aa/bb/cc/x.html"),
924 "d=1; domain=b.a.google.com"));
925 base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(
926 TypeParam::creation_time_granularity_in_ms));
927 EXPECT_TRUE(this->SetCookie(cs.get(),
928 GURL("http://b.a.google.com/aa/bb/cc/x.html"),
929 "a=4; domain=b.a.google.com"));
930 base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(
931 TypeParam::creation_time_granularity_in_ms));
932 EXPECT_TRUE(this->SetCookie(cs.get(),
933 GURL("http://c.b.a.google.com/aa/bb/cc/x.html"),
934 "e=1; domain=c.b.a.google.com"));
935 EXPECT_TRUE(this->SetCookie(
936 cs.get(), GURL("http://d.c.b.a.google.com/aa/bb/x.html"), "b=1"));
937 EXPECT_TRUE(this->SetCookie(
938 cs.get(), GURL("http://news.bbc.co.uk/midpath/x.html"), "g=10"));
939 EXPECT_EQ("d=1; a=4; e=1; b=1; c=1",
940 this->GetCookies(cs.get(),
941 GURL("http://d.c.b.a.google.com/aa/bb/cc/dd")));
944 TYPED_TEST_P(CookieStoreTest, DeleteSessionCookie) {
945 scoped_refptr<CookieStore> cs(this->GetCookieStore());
946 // Create a session cookie and a persistent cookie.
947 EXPECT_TRUE(this->SetCookie(
948 cs.get(), this->url_google_, std::string(kValidCookieLine)));
949 EXPECT_TRUE(this->SetCookie(cs.get(),
950 this->url_google_,
951 "C=D; path=/; domain=google.izzle;"
952 "expires=Mon, 18-Apr-22 22:50:13 GMT"));
953 this->MatchCookieLines("A=B; C=D",
954 this->GetCookies(cs.get(), this->url_google_));
955 // Delete the session cookie.
956 this->DeleteSessionCookies(cs.get());
957 // Check that the session cookie has been deleted but not the persistent one.
958 EXPECT_EQ("C=D", this->GetCookies(cs.get(), this->url_google_));
961 REGISTER_TYPED_TEST_CASE_P(CookieStoreTest,
962 TypeTest,
963 DomainTest,
964 DomainWithTrailingDotTest,
965 ValidSubdomainTest,
966 InvalidDomainTest,
967 DomainWithoutLeadingDotTest,
968 CaseInsensitiveDomainTest,
969 TestIpAddress,
970 TestNonDottedAndTLD,
971 TestHostEndsWithDot,
972 InvalidScheme,
973 InvalidScheme_Read,
974 PathTest,
975 EmptyExpires,
976 HttpOnlyTest,
977 TestCookieDeletion,
978 TestDeleteAllCreatedBetween,
979 TestSecure,
980 NetUtilCookieTest,
981 OverwritePersistentCookie,
982 CookieOrdering,
983 DeleteSessionCookie);
985 template<class CookieStoreTestTraits>
986 class MultiThreadedCookieStoreTest :
987 public CookieStoreTest<CookieStoreTestTraits> {
988 public:
989 MultiThreadedCookieStoreTest() : other_thread_("CMTthread") {}
991 // Helper methods for calling the asynchronous CookieStore methods
992 // from a different thread.
994 void GetCookiesTask(CookieStore* cs,
995 const GURL& url,
996 StringResultCookieCallback* callback) {
997 CookieOptions options;
998 if (!CookieStoreTestTraits::supports_http_only)
999 options.set_include_httponly();
1000 cs->GetCookiesWithOptionsAsync(
1001 url, options,
1002 base::Bind(&StringResultCookieCallback::Run,
1003 base::Unretained(callback)));
1006 void GetCookiesWithOptionsTask(CookieStore* cs,
1007 const GURL& url,
1008 const CookieOptions& options,
1009 StringResultCookieCallback* callback) {
1010 cs->GetCookiesWithOptionsAsync(
1011 url, options,
1012 base::Bind(&StringResultCookieCallback::Run,
1013 base::Unretained(callback)));
1016 void SetCookieWithOptionsTask(CookieStore* cs,
1017 const GURL& url,
1018 const std::string& cookie_line,
1019 const CookieOptions& options,
1020 BoolResultCookieCallback* callback) {
1021 cs->SetCookieWithOptionsAsync(
1022 url, cookie_line, options,
1023 base::Bind(&BoolResultCookieCallback::Run, base::Unretained(callback)));
1026 void DeleteCookieTask(CookieStore* cs,
1027 const GURL& url,
1028 const std::string& cookie_name,
1029 NoResultCookieCallback* callback) {
1030 cs->DeleteCookieAsync(
1031 url, cookie_name,
1032 base::Bind(&NoResultCookieCallback::Run, base::Unretained(callback)));
1035 void DeleteSessionCookiesTask(CookieStore* cs,
1036 IntResultCookieCallback* callback) {
1037 cs->DeleteSessionCookiesAsync(
1038 base::Bind(&IntResultCookieCallback::Run, base::Unretained(callback)));
1041 protected:
1042 void RunOnOtherThread(const base::Closure& task) {
1043 other_thread_.Start();
1044 other_thread_.message_loop()->PostTask(FROM_HERE, task);
1045 CookieStoreTest<CookieStoreTestTraits>::RunFor(kTimeout);
1046 other_thread_.Stop();
1049 Thread other_thread_;
1052 TYPED_TEST_CASE_P(MultiThreadedCookieStoreTest);
1054 // TODO(ycxiao): Eventually, we will need to create a separate thread, create
1055 // the cookie store on that thread (or at least its store, i.e., the DB
1056 // thread).
1057 TYPED_TEST_P(MultiThreadedCookieStoreTest, ThreadCheckGetCookies) {
1058 scoped_refptr<CookieStore> cs(this->GetCookieStore());
1059 EXPECT_TRUE(this->SetCookie(cs.get(), this->url_google_, "A=B"));
1060 this->MatchCookieLines("A=B", this->GetCookies(cs.get(), this->url_google_));
1061 StringResultCookieCallback callback(&this->other_thread_);
1062 base::Closure task = base::Bind(
1063 &net::MultiThreadedCookieStoreTest<TypeParam>::GetCookiesTask,
1064 base::Unretained(this),
1065 cs, this->url_google_, &callback);
1066 this->RunOnOtherThread(task);
1067 EXPECT_TRUE(callback.did_run());
1068 EXPECT_EQ("A=B", callback.result());
1071 TYPED_TEST_P(MultiThreadedCookieStoreTest, ThreadCheckGetCookiesWithOptions) {
1072 scoped_refptr<CookieStore> cs(this->GetCookieStore());
1073 CookieOptions options;
1074 if (!TypeParam::supports_http_only)
1075 options.set_include_httponly();
1076 EXPECT_TRUE(this->SetCookie(cs.get(), this->url_google_, "A=B"));
1077 this->MatchCookieLines(
1078 "A=B", this->GetCookiesWithOptions(cs.get(), this->url_google_, options));
1079 StringResultCookieCallback callback(&this->other_thread_);
1080 base::Closure task = base::Bind(
1081 &net::MultiThreadedCookieStoreTest<TypeParam>::GetCookiesWithOptionsTask,
1082 base::Unretained(this),
1083 cs, this->url_google_, options, &callback);
1084 this->RunOnOtherThread(task);
1085 EXPECT_TRUE(callback.did_run());
1086 EXPECT_EQ("A=B", callback.result());
1089 TYPED_TEST_P(MultiThreadedCookieStoreTest, ThreadCheckSetCookieWithOptions) {
1090 scoped_refptr<CookieStore> cs(this->GetCookieStore());
1091 CookieOptions options;
1092 if (!TypeParam::supports_http_only)
1093 options.set_include_httponly();
1094 EXPECT_TRUE(
1095 this->SetCookieWithOptions(cs.get(), this->url_google_, "A=B", options));
1096 BoolResultCookieCallback callback(&this->other_thread_);
1097 base::Closure task = base::Bind(
1098 &net::MultiThreadedCookieStoreTest<TypeParam>::SetCookieWithOptionsTask,
1099 base::Unretained(this),
1100 cs, this->url_google_, "A=B", options, &callback);
1101 this->RunOnOtherThread(task);
1102 EXPECT_TRUE(callback.did_run());
1103 EXPECT_TRUE(callback.result());
1106 TYPED_TEST_P(MultiThreadedCookieStoreTest, ThreadCheckDeleteCookie) {
1107 scoped_refptr<CookieStore> cs(this->GetCookieStore());
1108 CookieOptions options;
1109 if (!TypeParam::supports_http_only)
1110 options.set_include_httponly();
1111 EXPECT_TRUE(
1112 this->SetCookieWithOptions(cs.get(), this->url_google_, "A=B", options));
1113 this->DeleteCookie(cs.get(), this->url_google_, "A");
1114 EXPECT_TRUE(
1115 this->SetCookieWithOptions(cs.get(), this->url_google_, "A=B", options));
1116 NoResultCookieCallback callback(&this->other_thread_);
1117 base::Closure task = base::Bind(
1118 &net::MultiThreadedCookieStoreTest<TypeParam>::DeleteCookieTask,
1119 base::Unretained(this),
1120 cs, this->url_google_, "A", &callback);
1121 this->RunOnOtherThread(task);
1122 EXPECT_TRUE(callback.did_run());
1125 TYPED_TEST_P(MultiThreadedCookieStoreTest, ThreadCheckDeleteSessionCookies) {
1126 scoped_refptr<CookieStore> cs(this->GetCookieStore());
1127 CookieOptions options;
1128 if (!TypeParam::supports_http_only)
1129 options.set_include_httponly();
1130 EXPECT_TRUE(
1131 this->SetCookieWithOptions(cs.get(), this->url_google_, "A=B", options));
1132 EXPECT_TRUE(
1133 this->SetCookieWithOptions(cs.get(),
1134 this->url_google_,
1135 "B=C; expires=Mon, 18-Apr-22 22:50:13 GMT",
1136 options));
1137 EXPECT_EQ(1, this->DeleteSessionCookies(cs.get()));
1138 EXPECT_EQ(0, this->DeleteSessionCookies(cs.get()));
1139 EXPECT_TRUE(
1140 this->SetCookieWithOptions(cs.get(), this->url_google_, "A=B", options));
1141 IntResultCookieCallback callback(&this->other_thread_);
1142 base::Closure task = base::Bind(
1143 &net::MultiThreadedCookieStoreTest<TypeParam>::DeleteSessionCookiesTask,
1144 base::Unretained(this),
1145 cs, &callback);
1146 this->RunOnOtherThread(task);
1147 EXPECT_TRUE(callback.did_run());
1148 EXPECT_EQ(1, callback.result());
1151 REGISTER_TYPED_TEST_CASE_P(MultiThreadedCookieStoreTest,
1152 ThreadCheckGetCookies,
1153 ThreadCheckGetCookiesWithOptions,
1154 ThreadCheckSetCookieWithOptions,
1155 ThreadCheckDeleteCookie,
1156 ThreadCheckDeleteSessionCookies);
1158 } // namespace net
1160 #endif // NET_COOKIES_COOKIE_STORE_UNITTEST_H_