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