Sorted include files.
[chromium-blink-merge.git] / net / cookies / cookie_store_unittest.h
blobf0fcd71fd97e27cf59dfffc36c161601c4ed7fb6
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 ResultSavingCookieCallback<bool> callback;
122 cs->SetCookieWithOptionsAsync(
123 url, cookie_line, options,
124 base::Bind(
125 &ResultSavingCookieCallback<bool>::Run,
126 base::Unretained(&callback)));
127 RunFor(kTimeout);
128 EXPECT_TRUE(callback.did_run());
129 return callback.result();
132 bool SetCookieWithServerTime(CookieStore* cs,
133 const GURL& url,
134 const std::string& cookie_line,
135 const base::Time& server_time) {
136 CookieOptions options;
137 if (!CookieStoreTestTraits::supports_http_only)
138 options.set_include_httponly();
139 options.set_server_time(server_time);
140 return SetCookieWithOptions(cs, url, cookie_line, options);
143 bool SetCookie(CookieStore* cs,
144 const GURL& url,
145 const std::string& cookie_line) {
146 CookieOptions options;
147 if (!CookieStoreTestTraits::supports_http_only)
148 options.set_include_httponly();
149 return SetCookieWithOptions(cs, url, cookie_line, options);
152 void DeleteCookie(CookieStore* cs,
153 const GURL& url,
154 const std::string& cookie_name) {
155 DCHECK(cs);
156 NoResultCookieCallback callback;
157 cs->DeleteCookieAsync(
158 url, cookie_name,
159 base::Bind(&NoResultCookieCallback::Run, base::Unretained(&callback)));
160 RunFor(kTimeout);
161 EXPECT_TRUE(callback.did_run());
164 int DeleteCreatedBetween(CookieStore* cs,
165 const base::Time& delete_begin,
166 const base::Time& delete_end) {
167 DCHECK(cs);
168 ResultSavingCookieCallback<int> callback;
169 cs->DeleteAllCreatedBetweenAsync(
170 delete_begin, delete_end,
171 base::Bind(
172 &ResultSavingCookieCallback<int>::Run,
173 base::Unretained(&callback)));
174 RunFor(kTimeout);
175 EXPECT_TRUE(callback.did_run());
176 return callback.result();
179 int DeleteAllCreatedBetweenForHost(CookieStore* cs,
180 const base::Time delete_begin,
181 const base::Time delete_end,
182 const GURL& url) {
183 DCHECK(cs);
184 ResultSavingCookieCallback<int> callback;
185 cs->DeleteAllCreatedBetweenForHostAsync(
186 delete_begin, delete_end, url,
187 base::Bind(
188 &ResultSavingCookieCallback<int>::Run,
189 base::Unretained(&callback)));
190 RunFor(kTimeout);
191 EXPECT_TRUE(callback.did_run());
192 return callback.result();
195 int DeleteSessionCookies(CookieStore* cs) {
196 DCHECK(cs);
197 ResultSavingCookieCallback<int> callback;
198 cs->DeleteSessionCookiesAsync(
199 base::Bind(
200 &ResultSavingCookieCallback<int>::Run,
201 base::Unretained(&callback)));
202 RunFor(kTimeout);
203 EXPECT_TRUE(callback.did_run());
204 return callback.result();
207 void RunFor(int ms) {
208 // Runs the test thread message loop for up to |ms| milliseconds.
209 base::MessageLoop::current()->PostDelayedTask(
210 FROM_HERE,
211 base::Bind(&base::MessageLoop::Quit, weak_factory_->GetWeakPtr()),
212 base::TimeDelta::FromMilliseconds(ms));
213 base::MessageLoop::current()->Run();
214 weak_factory_->InvalidateWeakPtrs();
217 scoped_refptr<CookieStore> GetCookieStore() {
218 return CookieStoreTestTraits::Create();
221 // Compares two cookie lines.
222 void MatchCookieLines(const std::string& line1, const std::string& line2) {
223 EXPECT_EQ(TokenizeCookieLine(line1), TokenizeCookieLine(line2));
226 // Check the cookie line by polling until equality or a timeout is reached.
227 void MatchCookieLineWithTimeout(CookieStore* cs,
228 const GURL& url,
229 const std::string& line) {
230 std::string cookies = GetCookies(cs, url);
231 bool matched = (TokenizeCookieLine(line) == TokenizeCookieLine(cookies));
232 base::Time polling_end_date = base::Time::Now() +
233 base::TimeDelta::FromMilliseconds(
234 CookieStoreTestTraits::creation_time_granularity_in_ms);
236 while (!matched && base::Time::Now() <= polling_end_date) {
237 base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(10));
238 cookies = GetCookies(cs, url);
239 matched = (TokenizeCookieLine(line) == TokenizeCookieLine(cookies));
242 EXPECT_TRUE(matched) << "\"" << cookies
243 << "\" does not match \"" << line << "\"";
246 GURL url_google_;
247 GURL url_google_secure_;
248 GURL url_google_foo_;
249 GURL url_google_bar_;
251 scoped_ptr<base::WeakPtrFactory<base::MessageLoop> > weak_factory_;
252 scoped_ptr<base::MessageLoop> message_loop_;
254 private:
255 // Returns a set of strings of type "name=value". Fails in case of duplicate.
256 std::set<std::string> TokenizeCookieLine(const std::string& line) {
257 std::set<std::string> tokens;
258 base::StringTokenizer tokenizer(line, " ;");
259 while (tokenizer.GetNext())
260 EXPECT_TRUE(tokens.insert(tokenizer.token()).second);
261 return tokens;
265 TYPED_TEST_CASE_P(CookieStoreTest);
267 TYPED_TEST_P(CookieStoreTest, TypeTest) {
268 scoped_refptr<CookieStore> cs(this->GetCookieStore());
269 EXPECT_EQ(cs->GetCookieMonster(),
270 (TypeParam::is_cookie_monster) ?
271 static_cast<CookieMonster*>(cs.get()) : NULL);
274 TYPED_TEST_P(CookieStoreTest, DomainTest) {
275 scoped_refptr<CookieStore> cs(this->GetCookieStore());
276 EXPECT_TRUE(this->SetCookie(cs.get(), this->url_google_, "A=B"));
277 this->MatchCookieLines("A=B", this->GetCookies(cs.get(), this->url_google_));
278 EXPECT_TRUE(this->SetCookie(
279 cs.get(), this->url_google_, "C=D; domain=.google.izzle"));
280 this->MatchCookieLines("A=B; C=D",
281 this->GetCookies(cs.get(), this->url_google_));
283 // Verify that A=B was set as a host cookie rather than a domain
284 // cookie -- should not be accessible from a sub sub-domain.
285 this->MatchCookieLines(
286 "C=D", this->GetCookies(cs.get(), GURL("http://foo.www.google.izzle")));
288 // Test and make sure we find domain cookies on the same domain.
289 EXPECT_TRUE(this->SetCookie(
290 cs.get(), this->url_google_, "E=F; domain=.www.google.izzle"));
291 this->MatchCookieLines("A=B; C=D; E=F",
292 this->GetCookies(cs.get(), this->url_google_));
294 // Test setting a domain= that doesn't start w/ a dot, should
295 // treat it as a domain cookie, as if there was a pre-pended dot.
296 EXPECT_TRUE(this->SetCookie(
297 cs.get(), this->url_google_, "G=H; domain=www.google.izzle"));
298 this->MatchCookieLines("A=B; C=D; E=F; G=H",
299 this->GetCookies(cs.get(), this->url_google_));
301 // Test domain enforcement, should fail on a sub-domain or something too deep.
302 EXPECT_FALSE(
303 this->SetCookie(cs.get(), this->url_google_, "I=J; domain=.izzle"));
304 this->MatchCookieLines(std::string(),
305 this->GetCookies(cs.get(), GURL("http://a.izzle")));
306 EXPECT_FALSE(this->SetCookie(
307 cs.get(), this->url_google_, "K=L; domain=.bla.www.google.izzle"));
308 this->MatchCookieLines(
309 "C=D; E=F; G=H",
310 this->GetCookies(cs.get(), GURL("http://bla.www.google.izzle")));
311 this->MatchCookieLines("A=B; C=D; E=F; G=H",
312 this->GetCookies(cs.get(), this->url_google_));
315 // FireFox recognizes domains containing trailing periods as valid.
316 // IE and Safari do not. Assert the expected policy here.
317 TYPED_TEST_P(CookieStoreTest, DomainWithTrailingDotTest) {
318 scoped_refptr<CookieStore> cs(this->GetCookieStore());
319 EXPECT_FALSE(this->SetCookie(
320 cs.get(), this->url_google_, "a=1; domain=.www.google.com."));
321 EXPECT_FALSE(this->SetCookie(
322 cs.get(), this->url_google_, "b=2; domain=.www.google.com.."));
323 this->MatchCookieLines(std::string(),
324 this->GetCookies(cs.get(), this->url_google_));
327 // Test that cookies can bet set on higher level domains.
328 // http://b/issue?id=896491
329 TYPED_TEST_P(CookieStoreTest, ValidSubdomainTest) {
330 scoped_refptr<CookieStore> cs(this->GetCookieStore());
331 GURL url_abcd("http://a.b.c.d.com");
332 GURL url_bcd("http://b.c.d.com");
333 GURL url_cd("http://c.d.com");
334 GURL url_d("http://d.com");
336 EXPECT_TRUE(this->SetCookie(cs.get(), url_abcd, "a=1; domain=.a.b.c.d.com"));
337 EXPECT_TRUE(this->SetCookie(cs.get(), url_abcd, "b=2; domain=.b.c.d.com"));
338 EXPECT_TRUE(this->SetCookie(cs.get(), url_abcd, "c=3; domain=.c.d.com"));
339 EXPECT_TRUE(this->SetCookie(cs.get(), url_abcd, "d=4; domain=.d.com"));
341 this->MatchCookieLines("a=1; b=2; c=3; d=4",
342 this->GetCookies(cs.get(), url_abcd));
343 this->MatchCookieLines("b=2; c=3; d=4", this->GetCookies(cs.get(), url_bcd));
344 this->MatchCookieLines("c=3; d=4", this->GetCookies(cs.get(), url_cd));
345 this->MatchCookieLines("d=4", this->GetCookies(cs.get(), url_d));
347 // Check that the same cookie can exist on different sub-domains.
348 EXPECT_TRUE(this->SetCookie(cs.get(), url_bcd, "X=bcd; domain=.b.c.d.com"));
349 EXPECT_TRUE(this->SetCookie(cs.get(), url_bcd, "X=cd; domain=.c.d.com"));
350 this->MatchCookieLines("b=2; c=3; d=4; X=bcd; X=cd",
351 this->GetCookies(cs.get(), url_bcd));
352 this->MatchCookieLines("c=3; d=4; X=cd", this->GetCookies(cs.get(), url_cd));
355 // Test that setting a cookie which specifies an invalid domain has
356 // no side-effect. An invalid domain in this context is one which does
357 // not match the originating domain.
358 // http://b/issue?id=896472
359 TYPED_TEST_P(CookieStoreTest, InvalidDomainTest) {
361 scoped_refptr<CookieStore> cs(this->GetCookieStore());
362 GURL url_foobar("http://foo.bar.com");
364 // More specific sub-domain than allowed.
365 EXPECT_FALSE(
366 this->SetCookie(cs.get(), url_foobar, "a=1; domain=.yo.foo.bar.com"));
368 EXPECT_FALSE(this->SetCookie(cs.get(), url_foobar, "b=2; domain=.foo.com"));
369 EXPECT_FALSE(
370 this->SetCookie(cs.get(), url_foobar, "c=3; domain=.bar.foo.com"));
372 // Different TLD, but the rest is a substring.
373 EXPECT_FALSE(
374 this->SetCookie(cs.get(), url_foobar, "d=4; domain=.foo.bar.com.net"));
376 // A substring that isn't really a parent domain.
377 EXPECT_FALSE(this->SetCookie(cs.get(), url_foobar, "e=5; domain=ar.com"));
379 // Completely invalid domains:
380 EXPECT_FALSE(this->SetCookie(cs.get(), url_foobar, "f=6; domain=."));
381 EXPECT_FALSE(this->SetCookie(cs.get(), url_foobar, "g=7; domain=/"));
382 EXPECT_FALSE(this->SetCookie(
383 cs.get(), url_foobar, "h=8; domain=http://foo.bar.com"));
384 EXPECT_FALSE(
385 this->SetCookie(cs.get(), url_foobar, "i=9; domain=..foo.bar.com"));
386 EXPECT_FALSE(
387 this->SetCookie(cs.get(), url_foobar, "j=10; domain=..bar.com"));
389 // Make sure there isn't something quirky in the domain canonicalization
390 // that supports full URL semantics.
391 EXPECT_FALSE(this->SetCookie(
392 cs.get(), url_foobar, "k=11; domain=.foo.bar.com?blah"));
393 EXPECT_FALSE(this->SetCookie(
394 cs.get(), url_foobar, "l=12; domain=.foo.bar.com/blah"));
395 EXPECT_FALSE(
396 this->SetCookie(cs.get(), url_foobar, "m=13; domain=.foo.bar.com:80"));
397 EXPECT_FALSE(
398 this->SetCookie(cs.get(), url_foobar, "n=14; domain=.foo.bar.com:"));
399 EXPECT_FALSE(
400 this->SetCookie(cs.get(), url_foobar, "o=15; domain=.foo.bar.com#sup"));
402 this->MatchCookieLines(std::string(),
403 this->GetCookies(cs.get(), url_foobar));
407 // Make sure the cookie code hasn't gotten its subdomain string handling
408 // reversed, missed a suffix check, etc. It's important here that the two
409 // hosts below have the same domain + registry.
410 scoped_refptr<CookieStore> cs(this->GetCookieStore());
411 GURL url_foocom("http://foo.com.com");
412 EXPECT_FALSE(
413 this->SetCookie(cs.get(), url_foocom, "a=1; domain=.foo.com.com.com"));
414 this->MatchCookieLines(std::string(),
415 this->GetCookies(cs.get(), url_foocom));
419 // Test the behavior of omitting dot prefix from domain, should
420 // function the same as FireFox.
421 // http://b/issue?id=889898
422 TYPED_TEST_P(CookieStoreTest, DomainWithoutLeadingDotTest) {
423 { // The omission of dot results in setting a domain cookie.
424 scoped_refptr<CookieStore> cs(this->GetCookieStore());
425 GURL url_hosted("http://manage.hosted.filefront.com");
426 GURL url_filefront("http://www.filefront.com");
427 EXPECT_TRUE(
428 this->SetCookie(cs.get(), url_hosted, "sawAd=1; domain=filefront.com"));
429 this->MatchCookieLines("sawAd=1", this->GetCookies(cs.get(), url_hosted));
430 this->MatchCookieLines("sawAd=1",
431 this->GetCookies(cs.get(), url_filefront));
434 { // Even when the domains match exactly, don't consider it host cookie.
435 scoped_refptr<CookieStore> cs(this->GetCookieStore());
436 GURL url("http://www.google.com");
437 EXPECT_TRUE(this->SetCookie(cs.get(), url, "a=1; domain=www.google.com"));
438 this->MatchCookieLines("a=1", this->GetCookies(cs.get(), url));
439 this->MatchCookieLines(
440 "a=1", this->GetCookies(cs.get(), GURL("http://sub.www.google.com")));
441 this->MatchCookieLines(
442 std::string(),
443 this->GetCookies(cs.get(), GURL("http://something-else.com")));
447 // Test that the domain specified in cookie string is treated case-insensitive
448 // http://b/issue?id=896475.
449 TYPED_TEST_P(CookieStoreTest, CaseInsensitiveDomainTest) {
450 scoped_refptr<CookieStore> cs(this->GetCookieStore());
451 GURL url("http://www.google.com");
452 EXPECT_TRUE(this->SetCookie(cs.get(), url, "a=1; domain=.GOOGLE.COM"));
453 EXPECT_TRUE(this->SetCookie(cs.get(), url, "b=2; domain=.wWw.gOOgLE.coM"));
454 this->MatchCookieLines("a=1; b=2", this->GetCookies(cs.get(), url));
457 TYPED_TEST_P(CookieStoreTest, TestIpAddress) {
458 GURL url_ip("http://1.2.3.4/weee");
460 scoped_refptr<CookieStore> cs(this->GetCookieStore());
461 EXPECT_TRUE(this->SetCookie(cs.get(), url_ip, kValidCookieLine));
462 this->MatchCookieLines("A=B", this->GetCookies(cs.get(), url_ip));
465 { // IP addresses should not be able to set domain cookies.
466 scoped_refptr<CookieStore> cs(this->GetCookieStore());
467 EXPECT_FALSE(this->SetCookie(cs.get(), url_ip, "b=2; domain=.1.2.3.4"));
468 EXPECT_FALSE(this->SetCookie(cs.get(), url_ip, "c=3; domain=.3.4"));
469 this->MatchCookieLines(std::string(), this->GetCookies(cs.get(), url_ip));
470 // It should be allowed to set a cookie if domain= matches the IP address
471 // exactly. This matches IE/Firefox, even though it seems a bit wrong.
472 EXPECT_FALSE(this->SetCookie(cs.get(), url_ip, "b=2; domain=1.2.3.3"));
473 this->MatchCookieLines(std::string(), this->GetCookies(cs.get(), url_ip));
474 EXPECT_TRUE(this->SetCookie(cs.get(), url_ip, "b=2; domain=1.2.3.4"));
475 this->MatchCookieLines("b=2", this->GetCookies(cs.get(), url_ip));
479 // Test host cookies, and setting of cookies on TLD.
480 TYPED_TEST_P(CookieStoreTest, TestNonDottedAndTLD) {
482 scoped_refptr<CookieStore> cs(this->GetCookieStore());
483 GURL url("http://com/");
484 // Allow setting on "com", (but only as a host cookie).
485 EXPECT_TRUE(this->SetCookie(cs.get(), url, "a=1"));
486 EXPECT_FALSE(this->SetCookie(cs.get(), url, "b=2; domain=.com"));
487 EXPECT_FALSE(this->SetCookie(cs.get(), url, "c=3; domain=com"));
488 this->MatchCookieLines("a=1", this->GetCookies(cs.get(), url));
489 // Make sure it doesn't show up for a normal .com, it should be a host
490 // not a domain cookie.
491 this->MatchCookieLines(
492 std::string(),
493 this->GetCookies(cs.get(), GURL("http://hopefully-no-cookies.com/")));
494 if (TypeParam::supports_non_dotted_domains) {
495 this->MatchCookieLines(std::string(),
496 this->GetCookies(cs.get(), GURL("http://.com/")));
501 // http://com. should be treated the same as http://com.
502 scoped_refptr<CookieStore> cs(this->GetCookieStore());
503 GURL url("http://com./index.html");
504 if (TypeParam::supports_trailing_dots) {
505 EXPECT_TRUE(this->SetCookie(cs.get(), url, "a=1"));
506 this->MatchCookieLines("a=1", this->GetCookies(cs.get(), url));
507 this->MatchCookieLines(
508 std::string(),
509 this->GetCookies(cs.get(),
510 GURL("http://hopefully-no-cookies.com./")));
511 } else {
512 EXPECT_FALSE(this->SetCookie(cs.get(), url, "a=1"));
516 { // Should not be able to set host cookie from a subdomain.
517 scoped_refptr<CookieStore> cs(this->GetCookieStore());
518 GURL url("http://a.b");
519 EXPECT_FALSE(this->SetCookie(cs.get(), url, "a=1; domain=.b"));
520 EXPECT_FALSE(this->SetCookie(cs.get(), url, "b=2; domain=b"));
521 this->MatchCookieLines(std::string(), this->GetCookies(cs.get(), url));
524 { // Same test as above, but explicitly on a known TLD (com).
525 scoped_refptr<CookieStore> cs(this->GetCookieStore());
526 GURL url("http://google.com");
527 EXPECT_FALSE(this->SetCookie(cs.get(), url, "a=1; domain=.com"));
528 EXPECT_FALSE(this->SetCookie(cs.get(), url, "b=2; domain=com"));
529 this->MatchCookieLines(std::string(), this->GetCookies(cs.get(), url));
532 { // Make sure can't set cookie on TLD which is dotted.
533 scoped_refptr<CookieStore> cs(this->GetCookieStore());
534 GURL url("http://google.co.uk");
535 EXPECT_FALSE(this->SetCookie(cs.get(), url, "a=1; domain=.co.uk"));
536 EXPECT_FALSE(this->SetCookie(cs.get(), url, "b=2; domain=.uk"));
537 this->MatchCookieLines(std::string(), this->GetCookies(cs.get(), url));
538 this->MatchCookieLines(
539 std::string(),
540 this->GetCookies(cs.get(), GURL("http://something-else.co.uk")));
541 this->MatchCookieLines(
542 std::string(),
543 this->GetCookies(cs.get(), GURL("http://something-else.uk")));
546 { // Intranet URLs should only be able to set host cookies.
547 scoped_refptr<CookieStore> cs(this->GetCookieStore());
548 GURL url("http://b");
549 EXPECT_TRUE(this->SetCookie(cs.get(), url, "a=1"));
550 EXPECT_FALSE(this->SetCookie(cs.get(), url, "b=2; domain=.b"));
551 EXPECT_FALSE(this->SetCookie(cs.get(), url, "c=3; domain=b"));
552 this->MatchCookieLines("a=1", this->GetCookies(cs.get(), url));
556 // Test reading/writing cookies when the domain ends with a period,
557 // as in "www.google.com."
558 TYPED_TEST_P(CookieStoreTest, TestHostEndsWithDot) {
559 scoped_refptr<CookieStore> cs(this->GetCookieStore());
560 GURL url("http://www.google.com");
561 GURL url_with_dot("http://www.google.com.");
562 EXPECT_TRUE(this->SetCookie(cs.get(), url, "a=1"));
563 this->MatchCookieLines("a=1", this->GetCookies(cs.get(), url));
565 if (TypeParam::supports_trailing_dots) {
566 // Do not share cookie space with the dot version of domain.
567 // Note: this is not what FireFox does, but it _is_ what IE+Safari do.
568 EXPECT_FALSE(
569 this->SetCookie(cs.get(), url, "b=2; domain=.www.google.com."));
570 this->MatchCookieLines("a=1", this->GetCookies(cs.get(), url));
572 EXPECT_TRUE(
573 this->SetCookie(cs.get(), url_with_dot, "b=2; domain=.google.com."));
574 this->MatchCookieLines("b=2", this->GetCookies(cs.get(), url_with_dot));
575 } else {
576 EXPECT_TRUE(this->SetCookie(cs.get(), url, "b=2; domain=.www.google.com."));
577 EXPECT_FALSE(
578 this->SetCookie(cs.get(), url_with_dot, "b=2; domain=.google.com."));
581 // Make sure there weren't any side effects.
582 this->MatchCookieLines(
583 std::string(),
584 this->GetCookies(cs.get(), GURL("http://hopefully-no-cookies.com/")));
585 this->MatchCookieLines(std::string(),
586 this->GetCookies(cs.get(), GURL("http://.com/")));
589 TYPED_TEST_P(CookieStoreTest, InvalidScheme) {
590 if (!TypeParam::filters_schemes)
591 return;
593 scoped_refptr<CookieStore> cs(this->GetCookieStore());
594 EXPECT_FALSE(this->SetCookie(cs.get(), GURL(kUrlFtp), kValidCookieLine));
597 TYPED_TEST_P(CookieStoreTest, InvalidScheme_Read) {
598 if (!TypeParam::filters_schemes)
599 return;
601 scoped_refptr<CookieStore> cs(this->GetCookieStore());
602 EXPECT_TRUE(
603 this->SetCookie(cs.get(), GURL(kUrlGoogle), kValidDomainCookieLine));
604 this->MatchCookieLines(std::string(),
605 this->GetCookies(cs.get(), GURL(kUrlFtp)));
608 TYPED_TEST_P(CookieStoreTest, PathTest) {
609 scoped_refptr<CookieStore> cs(this->GetCookieStore());
610 std::string url("http://www.google.izzle");
611 EXPECT_TRUE(this->SetCookie(cs.get(), GURL(url), "A=B; path=/wee"));
612 this->MatchCookieLines("A=B", this->GetCookies(cs.get(), GURL(url + "/wee")));
613 this->MatchCookieLines("A=B",
614 this->GetCookies(cs.get(), GURL(url + "/wee/")));
615 this->MatchCookieLines("A=B",
616 this->GetCookies(cs.get(), GURL(url + "/wee/war")));
617 this->MatchCookieLines(
618 "A=B", this->GetCookies(cs.get(), GURL(url + "/wee/war/more/more")));
619 if (!TypeParam::has_path_prefix_bug)
620 this->MatchCookieLines(std::string(),
621 this->GetCookies(cs.get(), GURL(url + "/weehee")));
622 this->MatchCookieLines(std::string(),
623 this->GetCookies(cs.get(), GURL(url + "/")));
625 // If we add a 0 length path, it should default to /
626 EXPECT_TRUE(this->SetCookie(cs.get(), GURL(url), "A=C; path="));
627 this->MatchCookieLines("A=B; A=C",
628 this->GetCookies(cs.get(), GURL(url + "/wee")));
629 this->MatchCookieLines("A=C", this->GetCookies(cs.get(), GURL(url + "/")));
632 TYPED_TEST_P(CookieStoreTest, EmptyExpires) {
633 scoped_refptr<CookieStore> cs(this->GetCookieStore());
634 CookieOptions options;
635 if (!TypeParam::supports_http_only)
636 options.set_include_httponly();
637 GURL url("http://www7.ipdl.inpit.go.jp/Tokujitu/tjkta.ipdl?N0000=108");
638 std::string set_cookie_line =
639 "ACSTM=20130308043820420042; path=/; domain=ipdl.inpit.go.jp; Expires=";
640 std::string cookie_line = "ACSTM=20130308043820420042";
642 this->SetCookieWithOptions(cs.get(), url, set_cookie_line, options);
643 this->MatchCookieLines(cookie_line,
644 this->GetCookiesWithOptions(cs.get(), url, options));
646 options.set_server_time(base::Time::Now() - base::TimeDelta::FromHours(1));
647 this->SetCookieWithOptions(cs.get(), url, set_cookie_line, options);
648 this->MatchCookieLines(cookie_line,
649 this->GetCookiesWithOptions(cs.get(), url, options));
651 options.set_server_time(base::Time::Now() + base::TimeDelta::FromHours(1));
652 this->SetCookieWithOptions(cs.get(), url, set_cookie_line, options);
653 this->MatchCookieLines(cookie_line,
654 this->GetCookiesWithOptions(cs.get(), url, options));
657 TYPED_TEST_P(CookieStoreTest, HttpOnlyTest) {
658 if (!TypeParam::supports_http_only)
659 return;
661 scoped_refptr<CookieStore> cs(this->GetCookieStore());
662 CookieOptions options;
663 options.set_include_httponly();
665 // Create a httponly cookie.
666 EXPECT_TRUE(this->SetCookieWithOptions(
667 cs.get(), this->url_google_, "A=B; httponly", options));
669 // Check httponly read protection.
670 this->MatchCookieLines(std::string(),
671 this->GetCookies(cs.get(), this->url_google_));
672 this->MatchCookieLines(
673 "A=B", this->GetCookiesWithOptions(cs.get(), this->url_google_, options));
675 // Check httponly overwrite protection.
676 EXPECT_FALSE(this->SetCookie(cs.get(), this->url_google_, "A=C"));
677 this->MatchCookieLines(std::string(),
678 this->GetCookies(cs.get(), this->url_google_));
679 this->MatchCookieLines(
680 "A=B", this->GetCookiesWithOptions(cs.get(), this->url_google_, options));
681 EXPECT_TRUE(
682 this->SetCookieWithOptions(cs.get(), this->url_google_, "A=C", options));
683 this->MatchCookieLines("A=C", this->GetCookies(cs.get(), this->url_google_));
685 // Check httponly create protection.
686 EXPECT_FALSE(this->SetCookie(cs.get(), this->url_google_, "B=A; httponly"));
687 this->MatchCookieLines(
688 "A=C", this->GetCookiesWithOptions(cs.get(), this->url_google_, options));
689 EXPECT_TRUE(this->SetCookieWithOptions(
690 cs.get(), this->url_google_, "B=A; httponly", options));
691 this->MatchCookieLines(
692 "A=C; B=A",
693 this->GetCookiesWithOptions(cs.get(), this->url_google_, options));
694 this->MatchCookieLines("A=C", this->GetCookies(cs.get(), this->url_google_));
697 TYPED_TEST_P(CookieStoreTest, TestCookieDeletion) {
698 scoped_refptr<CookieStore> cs(this->GetCookieStore());
700 // Create a session cookie.
701 EXPECT_TRUE(this->SetCookie(cs.get(), this->url_google_, kValidCookieLine));
702 this->MatchCookieLines("A=B", this->GetCookies(cs.get(), this->url_google_));
703 // Delete it via Max-Age.
704 EXPECT_TRUE(this->SetCookie(cs.get(),
705 this->url_google_,
706 std::string(kValidCookieLine) + "; max-age=0"));
707 this->MatchCookieLineWithTimeout(cs.get(), this->url_google_, std::string());
709 // Create a session cookie.
710 EXPECT_TRUE(this->SetCookie(cs.get(), this->url_google_, kValidCookieLine));
711 this->MatchCookieLines("A=B", this->GetCookies(cs.get(), this->url_google_));
712 // Delete it via Expires.
713 EXPECT_TRUE(this->SetCookie(cs.get(),
714 this->url_google_,
715 std::string(kValidCookieLine) +
716 "; expires=Mon, 18-Apr-1977 22:50:13 GMT"));
717 this->MatchCookieLines(std::string(),
718 this->GetCookies(cs.get(), this->url_google_));
720 // Create a persistent cookie.
721 EXPECT_TRUE(this->SetCookie(
722 cs.get(),
723 this->url_google_,
724 std::string(kValidCookieLine) + "; expires=Mon, 18-Apr-22 22:50:13 GMT"));
726 this->MatchCookieLines("A=B", this->GetCookies(cs.get(), this->url_google_));
727 // Delete it via Max-Age.
728 EXPECT_TRUE(this->SetCookie(cs.get(),
729 this->url_google_,
730 std::string(kValidCookieLine) + "; max-age=0"));
731 this->MatchCookieLineWithTimeout(cs.get(), this->url_google_, std::string());
733 // Create a persistent cookie.
734 EXPECT_TRUE(this->SetCookie(
735 cs.get(),
736 this->url_google_,
737 std::string(kValidCookieLine) + "; expires=Mon, 18-Apr-22 22:50:13 GMT"));
738 this->MatchCookieLines("A=B", this->GetCookies(cs.get(), this->url_google_));
739 // Delete it via Expires.
740 EXPECT_TRUE(this->SetCookie(cs.get(),
741 this->url_google_,
742 std::string(kValidCookieLine) +
743 "; expires=Mon, 18-Apr-1977 22:50:13 GMT"));
744 this->MatchCookieLines(std::string(),
745 this->GetCookies(cs.get(), this->url_google_));
747 // Create a persistent cookie.
748 EXPECT_TRUE(this->SetCookie(
749 cs.get(),
750 this->url_google_,
751 std::string(kValidCookieLine) + "; expires=Mon, 18-Apr-22 22:50:13 GMT"));
752 this->MatchCookieLines("A=B", this->GetCookies(cs.get(), this->url_google_));
753 // Check that it is not deleted with significant enough clock skew.
754 base::Time server_time;
755 EXPECT_TRUE(base::Time::FromString("Sun, 17-Apr-1977 22:50:13 GMT",
756 &server_time));
757 EXPECT_TRUE(this->SetCookieWithServerTime(
758 cs.get(),
759 this->url_google_,
760 std::string(kValidCookieLine) + "; expires=Mon, 18-Apr-1977 22:50:13 GMT",
761 server_time));
762 this->MatchCookieLines("A=B", this->GetCookies(cs.get(), this->url_google_));
764 // Create a persistent cookie.
765 EXPECT_TRUE(this->SetCookie(
766 cs.get(),
767 this->url_google_,
768 std::string(kValidCookieLine) + "; expires=Mon, 18-Apr-22 22:50:13 GMT"));
769 this->MatchCookieLines("A=B", this->GetCookies(cs.get(), this->url_google_));
770 // Delete it via Expires, with a unix epoch of 0.
771 EXPECT_TRUE(this->SetCookie(cs.get(),
772 this->url_google_,
773 std::string(kValidCookieLine) +
774 "; expires=Thu, 1-Jan-1970 00:00:00 GMT"));
775 this->MatchCookieLines(std::string(),
776 this->GetCookies(cs.get(), this->url_google_));
779 TYPED_TEST_P(CookieStoreTest, TestDeleteAllCreatedBetween) {
780 scoped_refptr<CookieStore> cs(this->GetCookieStore());
781 const base::Time last_month = base::Time::Now() -
782 base::TimeDelta::FromDays(30);
783 const base::Time last_minute = base::Time::Now() -
784 base::TimeDelta::FromMinutes(1);
785 const base::Time next_minute = base::Time::Now() +
786 base::TimeDelta::FromMinutes(1);
787 const base::Time next_month = base::Time::Now() +
788 base::TimeDelta::FromDays(30);
790 // Add a cookie.
791 EXPECT_TRUE(this->SetCookie(cs.get(), this->url_google_, "A=B"));
792 // Check that the cookie is in the store.
793 this->MatchCookieLines("A=B", this->GetCookies(cs.get(), this->url_google_));
795 // Remove cookies in empty intervals.
796 EXPECT_EQ(0, this->DeleteCreatedBetween(cs.get(), last_month, last_minute));
797 EXPECT_EQ(0, this->DeleteCreatedBetween(cs.get(), next_minute, next_month));
798 // Check that the cookie is still there.
799 this->MatchCookieLines("A=B", this->GetCookies(cs.get(), this->url_google_));
801 // Remove the cookie with an interval defined by two dates.
802 EXPECT_EQ(1, this->DeleteCreatedBetween(cs.get(), last_minute, next_minute));
803 // Check that the cookie disappeared.
804 this->MatchCookieLines(std::string(),
805 this->GetCookies(cs.get(), this->url_google_));
807 // Add another cookie.
808 EXPECT_TRUE(this->SetCookie(cs.get(), this->url_google_, "C=D"));
809 // Check that the cookie is in the store.
810 this->MatchCookieLines("C=D", this->GetCookies(cs.get(), this->url_google_));
812 // Remove the cookie with a null ending time.
813 EXPECT_EQ(1, this->DeleteCreatedBetween(cs.get(), last_minute, base::Time()));
814 // Check that the cookie disappeared.
815 this->MatchCookieLines(std::string(),
816 this->GetCookies(cs.get(), this->url_google_));
819 TYPED_TEST_P(CookieStoreTest, TestDeleteAllCreatedBetweenForHost) {
820 scoped_refptr<CookieStore> cs(this->GetCookieStore());
821 GURL url_not_google("http://www.notgoogle.com");
822 base::Time now = base::Time::Now();
824 // These 3 cookies match the time range and host.
825 EXPECT_TRUE(this->SetCookie(cs.get(), this->url_google_, "A=B"));
826 EXPECT_TRUE(this->SetCookie(cs.get(), this->url_google_, "C=D"));
827 EXPECT_TRUE(this->SetCookie(cs.get(), this->url_google_, "Y=Z"));
829 // This cookie does not match host.
830 EXPECT_TRUE(this->SetCookie(cs.get(), url_not_google, "E=F"));
832 // Delete cookies.
833 EXPECT_EQ(
834 3, // Deletes A=B, C=D, Y=Z
835 this->DeleteAllCreatedBetweenForHost(
836 cs.get(), now, base::Time::Max(), this->url_google_));
839 TYPED_TEST_P(CookieStoreTest, TestSecure) {
840 scoped_refptr<CookieStore> cs(this->GetCookieStore());
842 EXPECT_TRUE(this->SetCookie(cs.get(), this->url_google_, "A=B"));
843 this->MatchCookieLines("A=B",
844 this->GetCookies(cs.get(), this->url_google_));
845 this->MatchCookieLines(
846 "A=B", this->GetCookies(cs.get(), this->url_google_secure_));
848 EXPECT_TRUE(
849 this->SetCookie(cs.get(), this->url_google_secure_, "A=B; secure"));
850 // The secure should overwrite the non-secure.
851 this->MatchCookieLines(std::string(),
852 this->GetCookies(cs.get(), this->url_google_));
853 this->MatchCookieLines("A=B",
854 this->GetCookies(cs.get(), this->url_google_secure_));
856 EXPECT_TRUE(
857 this->SetCookie(cs.get(), this->url_google_secure_, "D=E; secure"));
858 this->MatchCookieLines(std::string(),
859 this->GetCookies(cs.get(), this->url_google_));
860 this->MatchCookieLines("A=B; D=E",
861 this->GetCookies(cs.get(), this->url_google_secure_));
863 EXPECT_TRUE(this->SetCookie(cs.get(), this->url_google_secure_, "A=B"));
864 // The non-secure should overwrite the secure.
865 this->MatchCookieLines("A=B", this->GetCookies(cs.get(), this->url_google_));
866 this->MatchCookieLines("D=E; A=B",
867 this->GetCookies(cs.get(), this->url_google_secure_));
870 static const int kLastAccessThresholdMilliseconds = 200;
872 // Formerly NetUtilTest.CookieTest back when we used wininet's cookie handling.
873 TYPED_TEST_P(CookieStoreTest, NetUtilCookieTest) {
874 const GURL test_url("http://mojo.jojo.google.izzle/");
876 scoped_refptr<CookieStore> cs(this->GetCookieStore());
878 EXPECT_TRUE(this->SetCookie(cs.get(), test_url, "foo=bar"));
879 std::string value = this->GetCookies(cs.get(), test_url);
880 this->MatchCookieLines("foo=bar", value);
882 // test that we can retrieve all cookies:
883 EXPECT_TRUE(this->SetCookie(cs.get(), test_url, "x=1"));
884 EXPECT_TRUE(this->SetCookie(cs.get(), test_url, "y=2"));
886 std::string result = this->GetCookies(cs.get(), test_url);
887 EXPECT_FALSE(result.empty());
888 EXPECT_NE(result.find("x=1"), std::string::npos) << result;
889 EXPECT_NE(result.find("y=2"), std::string::npos) << result;
892 TYPED_TEST_P(CookieStoreTest, OverwritePersistentCookie) {
893 GURL url_google("http://www.google.com/");
894 GURL url_chromium("http://chromium.org");
895 scoped_refptr<CookieStore> cs(this->GetCookieStore());
897 // Insert a cookie "a" for path "/path1"
898 EXPECT_TRUE(this->SetCookie(cs.get(),
899 url_google,
900 "a=val1; path=/path1; "
901 "expires=Mon, 18-Apr-22 22:50:13 GMT"));
903 // Insert a cookie "b" for path "/path1"
904 EXPECT_TRUE(this->SetCookie(cs.get(),
905 url_google,
906 "b=val1; path=/path1; "
907 "expires=Mon, 18-Apr-22 22:50:14 GMT"));
909 // Insert a cookie "b" for path "/path1", that is httponly. This should
910 // overwrite the non-http-only version.
911 CookieOptions allow_httponly;
912 allow_httponly.set_include_httponly();
913 EXPECT_TRUE(this->SetCookieWithOptions(cs.get(),
914 url_google,
915 "b=val2; path=/path1; httponly; "
916 "expires=Mon, 18-Apr-22 22:50:14 GMT",
917 allow_httponly));
919 // Insert a cookie "a" for path "/path1". This should overwrite.
920 EXPECT_TRUE(this->SetCookie(cs.get(),
921 url_google,
922 "a=val33; path=/path1; "
923 "expires=Mon, 18-Apr-22 22:50:14 GMT"));
925 // Insert a cookie "a" for path "/path2". This should NOT overwrite
926 // cookie "a", since the path is different.
927 EXPECT_TRUE(this->SetCookie(cs.get(),
928 url_google,
929 "a=val9; path=/path2; "
930 "expires=Mon, 18-Apr-22 22:50:14 GMT"));
932 // Insert a cookie "a" for path "/path1", but this time for "chromium.org".
933 // Although the name and path match, the hostnames do not, so shouldn't
934 // overwrite.
935 EXPECT_TRUE(this->SetCookie(cs.get(),
936 url_chromium,
937 "a=val99; path=/path1; "
938 "expires=Mon, 18-Apr-22 22:50:14 GMT"));
940 if (TypeParam::supports_http_only) {
941 this->MatchCookieLines(
942 "a=val33",
943 this->GetCookies(cs.get(), GURL("http://www.google.com/path1")));
944 } else {
945 this->MatchCookieLines(
946 "a=val33; b=val2",
947 this->GetCookies(cs.get(), GURL("http://www.google.com/path1")));
949 this->MatchCookieLines(
950 "a=val9",
951 this->GetCookies(cs.get(), GURL("http://www.google.com/path2")));
952 this->MatchCookieLines(
953 "a=val99", this->GetCookies(cs.get(), GURL("http://chromium.org/path1")));
956 TYPED_TEST_P(CookieStoreTest, CookieOrdering) {
957 // Put a random set of cookies into a store and make sure they're returned in
958 // the right order.
959 // Cookies should be sorted by path length and creation time, as per RFC6265.
960 scoped_refptr<CookieStore> cs(this->GetCookieStore());
961 EXPECT_TRUE(this->SetCookie(
962 cs.get(), GURL("http://d.c.b.a.google.com/aa/x.html"), "c=1"));
963 EXPECT_TRUE(this->SetCookie(cs.get(),
964 GURL("http://b.a.google.com/aa/bb/cc/x.html"),
965 "d=1; domain=b.a.google.com"));
966 base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(
967 TypeParam::creation_time_granularity_in_ms));
968 EXPECT_TRUE(this->SetCookie(cs.get(),
969 GURL("http://b.a.google.com/aa/bb/cc/x.html"),
970 "a=4; domain=b.a.google.com"));
971 base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(
972 TypeParam::creation_time_granularity_in_ms));
973 EXPECT_TRUE(this->SetCookie(cs.get(),
974 GURL("http://c.b.a.google.com/aa/bb/cc/x.html"),
975 "e=1; domain=c.b.a.google.com"));
976 EXPECT_TRUE(this->SetCookie(
977 cs.get(), GURL("http://d.c.b.a.google.com/aa/bb/x.html"), "b=1"));
978 EXPECT_TRUE(this->SetCookie(
979 cs.get(), GURL("http://news.bbc.co.uk/midpath/x.html"), "g=10"));
980 EXPECT_EQ("d=1; a=4; e=1; b=1; c=1",
981 this->GetCookies(cs.get(),
982 GURL("http://d.c.b.a.google.com/aa/bb/cc/dd")));
985 TYPED_TEST_P(CookieStoreTest, DeleteSessionCookie) {
986 scoped_refptr<CookieStore> cs(this->GetCookieStore());
987 // Create a session cookie and a persistent cookie.
988 EXPECT_TRUE(this->SetCookie(
989 cs.get(), this->url_google_, std::string(kValidCookieLine)));
990 EXPECT_TRUE(this->SetCookie(cs.get(),
991 this->url_google_,
992 "C=D; path=/; domain=google.izzle;"
993 "expires=Mon, 18-Apr-22 22:50:13 GMT"));
994 this->MatchCookieLines("A=B; C=D",
995 this->GetCookies(cs.get(), this->url_google_));
996 // Delete the session cookie.
997 this->DeleteSessionCookies(cs.get());
998 // Check that the session cookie has been deleted but not the persistent one.
999 EXPECT_EQ("C=D", this->GetCookies(cs.get(), this->url_google_));
1002 REGISTER_TYPED_TEST_CASE_P(CookieStoreTest,
1003 TypeTest,
1004 DomainTest,
1005 DomainWithTrailingDotTest,
1006 ValidSubdomainTest,
1007 InvalidDomainTest,
1008 DomainWithoutLeadingDotTest,
1009 CaseInsensitiveDomainTest,
1010 TestIpAddress,
1011 TestNonDottedAndTLD,
1012 TestHostEndsWithDot,
1013 InvalidScheme,
1014 InvalidScheme_Read,
1015 PathTest,
1016 EmptyExpires,
1017 HttpOnlyTest,
1018 TestCookieDeletion,
1019 TestDeleteAllCreatedBetween,
1020 TestDeleteAllCreatedBetweenForHost,
1021 TestSecure,
1022 NetUtilCookieTest,
1023 OverwritePersistentCookie,
1024 CookieOrdering,
1025 DeleteSessionCookie);
1027 template<class CookieStoreTestTraits>
1028 class MultiThreadedCookieStoreTest :
1029 public CookieStoreTest<CookieStoreTestTraits> {
1030 public:
1031 MultiThreadedCookieStoreTest() : other_thread_("CMTthread") {}
1033 // Helper methods for calling the asynchronous CookieStore methods
1034 // from a different thread.
1036 void GetCookiesTask(CookieStore* cs,
1037 const GURL& url,
1038 StringResultCookieCallback* callback) {
1039 CookieOptions options;
1040 if (!CookieStoreTestTraits::supports_http_only)
1041 options.set_include_httponly();
1042 cs->GetCookiesWithOptionsAsync(
1043 url, options,
1044 base::Bind(&StringResultCookieCallback::Run,
1045 base::Unretained(callback)));
1048 void GetCookiesWithOptionsTask(CookieStore* cs,
1049 const GURL& url,
1050 const CookieOptions& options,
1051 StringResultCookieCallback* callback) {
1052 cs->GetCookiesWithOptionsAsync(
1053 url, options,
1054 base::Bind(&StringResultCookieCallback::Run,
1055 base::Unretained(callback)));
1058 void SetCookieWithOptionsTask(CookieStore* cs,
1059 const GURL& url,
1060 const std::string& cookie_line,
1061 const CookieOptions& options,
1062 ResultSavingCookieCallback<bool>* callback) {
1063 cs->SetCookieWithOptionsAsync(
1064 url, cookie_line, options,
1065 base::Bind(
1066 &ResultSavingCookieCallback<bool>::Run,
1067 base::Unretained(callback)));
1070 void DeleteCookieTask(CookieStore* cs,
1071 const GURL& url,
1072 const std::string& cookie_name,
1073 NoResultCookieCallback* callback) {
1074 cs->DeleteCookieAsync(
1075 url, cookie_name,
1076 base::Bind(&NoResultCookieCallback::Run, base::Unretained(callback)));
1079 void DeleteSessionCookiesTask(CookieStore* cs,
1080 ResultSavingCookieCallback<int>* callback) {
1081 cs->DeleteSessionCookiesAsync(
1082 base::Bind(
1083 &ResultSavingCookieCallback<int>::Run,
1084 base::Unretained(callback)));
1087 protected:
1088 void RunOnOtherThread(const base::Closure& task) {
1089 other_thread_.Start();
1090 other_thread_.message_loop()->PostTask(FROM_HERE, task);
1091 CookieStoreTest<CookieStoreTestTraits>::RunFor(kTimeout);
1092 other_thread_.Stop();
1095 Thread other_thread_;
1098 TYPED_TEST_CASE_P(MultiThreadedCookieStoreTest);
1100 // TODO(ycxiao): Eventually, we will need to create a separate thread, create
1101 // the cookie store on that thread (or at least its store, i.e., the DB
1102 // thread).
1103 TYPED_TEST_P(MultiThreadedCookieStoreTest, ThreadCheckGetCookies) {
1104 scoped_refptr<CookieStore> cs(this->GetCookieStore());
1105 EXPECT_TRUE(this->SetCookie(cs.get(), this->url_google_, "A=B"));
1106 this->MatchCookieLines("A=B", this->GetCookies(cs.get(), this->url_google_));
1107 StringResultCookieCallback callback(&this->other_thread_);
1108 base::Closure task = base::Bind(
1109 &net::MultiThreadedCookieStoreTest<TypeParam>::GetCookiesTask,
1110 base::Unretained(this),
1111 cs, this->url_google_, &callback);
1112 this->RunOnOtherThread(task);
1113 EXPECT_TRUE(callback.did_run());
1114 EXPECT_EQ("A=B", callback.result());
1117 TYPED_TEST_P(MultiThreadedCookieStoreTest, ThreadCheckGetCookiesWithOptions) {
1118 scoped_refptr<CookieStore> cs(this->GetCookieStore());
1119 CookieOptions options;
1120 if (!TypeParam::supports_http_only)
1121 options.set_include_httponly();
1122 EXPECT_TRUE(this->SetCookie(cs.get(), this->url_google_, "A=B"));
1123 this->MatchCookieLines(
1124 "A=B", this->GetCookiesWithOptions(cs.get(), this->url_google_, options));
1125 StringResultCookieCallback callback(&this->other_thread_);
1126 base::Closure task = base::Bind(
1127 &net::MultiThreadedCookieStoreTest<TypeParam>::GetCookiesWithOptionsTask,
1128 base::Unretained(this),
1129 cs, this->url_google_, options, &callback);
1130 this->RunOnOtherThread(task);
1131 EXPECT_TRUE(callback.did_run());
1132 EXPECT_EQ("A=B", callback.result());
1135 TYPED_TEST_P(MultiThreadedCookieStoreTest, ThreadCheckSetCookieWithOptions) {
1136 scoped_refptr<CookieStore> cs(this->GetCookieStore());
1137 CookieOptions options;
1138 if (!TypeParam::supports_http_only)
1139 options.set_include_httponly();
1140 EXPECT_TRUE(
1141 this->SetCookieWithOptions(cs.get(), this->url_google_, "A=B", options));
1142 ResultSavingCookieCallback<bool> callback(&this->other_thread_);
1143 base::Closure task = base::Bind(
1144 &net::MultiThreadedCookieStoreTest<TypeParam>::SetCookieWithOptionsTask,
1145 base::Unretained(this),
1146 cs, this->url_google_, "A=B", options, &callback);
1147 this->RunOnOtherThread(task);
1148 EXPECT_TRUE(callback.did_run());
1149 EXPECT_TRUE(callback.result());
1152 TYPED_TEST_P(MultiThreadedCookieStoreTest, ThreadCheckDeleteCookie) {
1153 scoped_refptr<CookieStore> cs(this->GetCookieStore());
1154 CookieOptions options;
1155 if (!TypeParam::supports_http_only)
1156 options.set_include_httponly();
1157 EXPECT_TRUE(
1158 this->SetCookieWithOptions(cs.get(), this->url_google_, "A=B", options));
1159 this->DeleteCookie(cs.get(), this->url_google_, "A");
1160 EXPECT_TRUE(
1161 this->SetCookieWithOptions(cs.get(), this->url_google_, "A=B", options));
1162 NoResultCookieCallback callback(&this->other_thread_);
1163 base::Closure task = base::Bind(
1164 &net::MultiThreadedCookieStoreTest<TypeParam>::DeleteCookieTask,
1165 base::Unretained(this),
1166 cs, this->url_google_, "A", &callback);
1167 this->RunOnOtherThread(task);
1168 EXPECT_TRUE(callback.did_run());
1171 TYPED_TEST_P(MultiThreadedCookieStoreTest, ThreadCheckDeleteSessionCookies) {
1172 scoped_refptr<CookieStore> cs(this->GetCookieStore());
1173 CookieOptions options;
1174 if (!TypeParam::supports_http_only)
1175 options.set_include_httponly();
1176 EXPECT_TRUE(
1177 this->SetCookieWithOptions(cs.get(), this->url_google_, "A=B", options));
1178 EXPECT_TRUE(
1179 this->SetCookieWithOptions(cs.get(),
1180 this->url_google_,
1181 "B=C; expires=Mon, 18-Apr-22 22:50:13 GMT",
1182 options));
1183 EXPECT_EQ(1, this->DeleteSessionCookies(cs.get()));
1184 EXPECT_EQ(0, this->DeleteSessionCookies(cs.get()));
1185 EXPECT_TRUE(
1186 this->SetCookieWithOptions(cs.get(), this->url_google_, "A=B", options));
1187 ResultSavingCookieCallback<int> callback(&this->other_thread_);
1188 base::Closure task = base::Bind(
1189 &net::MultiThreadedCookieStoreTest<TypeParam>::DeleteSessionCookiesTask,
1190 base::Unretained(this),
1191 cs, &callback);
1192 this->RunOnOtherThread(task);
1193 EXPECT_TRUE(callback.did_run());
1194 EXPECT_EQ(1, callback.result());
1197 REGISTER_TYPED_TEST_CASE_P(MultiThreadedCookieStoreTest,
1198 ThreadCheckGetCookies,
1199 ThreadCheckGetCookiesWithOptions,
1200 ThreadCheckSetCookieWithOptions,
1201 ThreadCheckDeleteCookie,
1202 ThreadCheckDeleteSessionCookies);
1204 } // namespace net
1206 #endif // NET_COOKIES_COOKIE_STORE_UNITTEST_H_