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