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