| 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 #include "net/base/cookie_store_unittest.h" | |
| 6 | |
| 7 #include <time.h> | |
| 8 #include <string> | |
| 9 | |
| 10 #include "base/basictypes.h" | |
| 11 #include "base/bind.h" | |
| 12 #include "base/memory/ref_counted.h" | |
| 13 #include "base/memory/scoped_ptr.h" | |
| 14 #include "base/message_loop.h" | |
| 15 #include "base/metrics/histogram.h" | |
| 16 #include "base/stringprintf.h" | |
| 17 #include "base/string_tokenizer.h" | |
| 18 #include "base/threading/thread.h" | |
| 19 #include "base/time.h" | |
| 20 #include "googleurl/src/gurl.h" | |
| 21 #include "net/base/cookie_monster.h" | |
| 22 #include "net/base/cookie_monster_store_test.h" // For CookieStore mock | |
| 23 #include "net/base/cookie_util.h" | |
| 24 #include "testing/gmock/include/gmock/gmock.h" | |
| 25 #include "testing/gtest/include/gtest/gtest.h" | |
| 26 | |
| 27 namespace net { | |
| 28 | |
| 29 using base::Time; | |
| 30 using base::TimeDelta; | |
| 31 | |
| 32 namespace { | |
| 33 | |
| 34 // TODO(erikwright): Replace the pre-existing MockPersistentCookieStore (and | |
| 35 // brethren) with this one, and remove the 'New' prefix. | |
| 36 class NewMockPersistentCookieStore | |
| 37 : public CookieMonster::PersistentCookieStore { | |
| 38 public: | |
| 39 MOCK_METHOD1(Load, void(const LoadedCallback& loaded_callback)); | |
| 40 MOCK_METHOD2(LoadCookiesForKey, void(const std::string& key, | |
| 41 const LoadedCallback& loaded_callback)); | |
| 42 MOCK_METHOD1(AddCookie, void(const CookieMonster::CanonicalCookie& cc)); | |
| 43 MOCK_METHOD1(UpdateCookieAccessTime, | |
| 44 void(const CookieMonster::CanonicalCookie& cc)); | |
| 45 MOCK_METHOD1(DeleteCookie, void(const CookieMonster::CanonicalCookie& cc)); | |
| 46 MOCK_METHOD1(SetClearLocalStateOnExit, void(bool clear_local_state)); | |
| 47 MOCK_METHOD1(Flush, void(const base::Closure& callback)); | |
| 48 }; | |
| 49 | |
| 50 const char* kTopLevelDomainPlus1 = "http://www.harvard.edu"; | |
| 51 const char* kTopLevelDomainPlus2 = "http://www.math.harvard.edu"; | |
| 52 const char* kTopLevelDomainPlus2Secure = "https://www.math.harvard.edu"; | |
| 53 const char* kTopLevelDomainPlus3 = | |
| 54 "http://www.bourbaki.math.harvard.edu"; | |
| 55 const char* kOtherDomain = "http://www.mit.edu"; | |
| 56 const char kUrlGoogleSpecific[] = "http://www.gmail.google.izzle"; | |
| 57 | |
| 58 class GetCookieListCallback : public CookieCallback { | |
| 59 public: | |
| 60 GetCookieListCallback() {} | |
| 61 explicit GetCookieListCallback(Thread* run_in_thread) | |
| 62 : CookieCallback(run_in_thread) {} | |
| 63 | |
| 64 void Run(const CookieList& cookies) { | |
| 65 cookies_ = cookies; | |
| 66 CallbackEpilogue(); | |
| 67 } | |
| 68 | |
| 69 const CookieList& cookies() { return cookies_; } | |
| 70 | |
| 71 private: | |
| 72 CookieList cookies_; | |
| 73 }; | |
| 74 | |
| 75 class ParsedCookieTest : public testing::Test { }; | |
| 76 | |
| 77 } // namespace | |
| 78 | |
| 79 TEST(ParsedCookieTest, TestBasic) { | |
| 80 CookieMonster::ParsedCookie pc("a=b"); | |
| 81 EXPECT_TRUE(pc.IsValid()); | |
| 82 EXPECT_FALSE(pc.IsSecure()); | |
| 83 EXPECT_EQ("a", pc.Name()); | |
| 84 EXPECT_EQ("b", pc.Value()); | |
| 85 } | |
| 86 | |
| 87 TEST(ParsedCookieTest, TestQuoted) { | |
| 88 // These are some quoting cases which the major browsers all | |
| 89 // handle differently. I've tested Internet Explorer 6, Opera 9.6, | |
| 90 // Firefox 3, and Safari Windows 3.2.1. We originally tried to match | |
| 91 // Firefox closely, however we now match Internet Explorer and Safari. | |
| 92 const char* values[] = { | |
| 93 // Trailing whitespace after a quoted value. The whitespace after | |
| 94 // the quote is stripped in all browsers. | |
| 95 "\"zzz \" ", "\"zzz \"", | |
| 96 // Handling a quoted value with a ';', like FOO="zz;pp" ; | |
| 97 // IE and Safari: "zz; | |
| 98 // Firefox and Opera: "zz;pp" | |
| 99 "\"zz;pp\" ;", "\"zz", | |
| 100 // Handling a value with multiple quoted parts, like FOO="zzz " "ppp" ; | |
| 101 // IE and Safari: "zzz " "ppp"; | |
| 102 // Firefox: "zzz "; | |
| 103 // Opera: <rejects cookie> | |
| 104 "\"zzz \" \"ppp\" ", "\"zzz \" \"ppp\"", | |
| 105 // A quote in a value that didn't start quoted. like FOO=A"B ; | |
| 106 // IE, Safari, and Firefox: A"B; | |
| 107 // Opera: <rejects cookie> | |
| 108 "A\"B", "A\"B", | |
| 109 }; | |
| 110 | |
| 111 for (size_t i = 0; i < arraysize(values); i += 2) { | |
| 112 std::string input(values[i]); | |
| 113 std::string expected(values[i + 1]); | |
| 114 | |
| 115 CookieMonster::ParsedCookie pc( | |
| 116 "aBc=" + input + " ; path=\"/\" ; httponly "); | |
| 117 EXPECT_TRUE(pc.IsValid()); | |
| 118 EXPECT_FALSE(pc.IsSecure()); | |
| 119 EXPECT_TRUE(pc.IsHttpOnly()); | |
| 120 EXPECT_TRUE(pc.HasPath()); | |
| 121 EXPECT_EQ("aBc", pc.Name()); | |
| 122 EXPECT_EQ(expected, pc.Value()); | |
| 123 | |
| 124 // If a path was quoted, the path attribute keeps the quotes. This will | |
| 125 // make the cookie effectively useless, but path parameters aren't supposed | |
| 126 // to be quoted. Bug 1261605. | |
| 127 EXPECT_EQ("\"/\"", pc.Path()); | |
| 128 } | |
| 129 } | |
| 130 | |
| 131 TEST(ParsedCookieTest, TestNameless) { | |
| 132 CookieMonster::ParsedCookie pc("BLAHHH; path=/; secure;"); | |
| 133 EXPECT_TRUE(pc.IsValid()); | |
| 134 EXPECT_TRUE(pc.IsSecure()); | |
| 135 EXPECT_TRUE(pc.HasPath()); | |
| 136 EXPECT_EQ("/", pc.Path()); | |
| 137 EXPECT_EQ("", pc.Name()); | |
| 138 EXPECT_EQ("BLAHHH", pc.Value()); | |
| 139 } | |
| 140 | |
| 141 TEST(ParsedCookieTest, TestAttributeCase) { | |
| 142 CookieMonster::ParsedCookie pc("BLAHHH; Path=/; sECuRe; httpONLY"); | |
| 143 EXPECT_TRUE(pc.IsValid()); | |
| 144 EXPECT_TRUE(pc.IsSecure()); | |
| 145 EXPECT_TRUE(pc.IsHttpOnly()); | |
| 146 EXPECT_TRUE(pc.HasPath()); | |
| 147 EXPECT_EQ("/", pc.Path()); | |
| 148 EXPECT_EQ("", pc.Name()); | |
| 149 EXPECT_EQ("BLAHHH", pc.Value()); | |
| 150 EXPECT_EQ(3U, pc.NumberOfAttributes()); | |
| 151 } | |
| 152 | |
| 153 TEST(ParsedCookieTest, TestDoubleQuotedNameless) { | |
| 154 CookieMonster::ParsedCookie pc("\"BLA\\\"HHH\"; path=/; secure;"); | |
| 155 EXPECT_TRUE(pc.IsValid()); | |
| 156 EXPECT_TRUE(pc.IsSecure()); | |
| 157 EXPECT_TRUE(pc.HasPath()); | |
| 158 EXPECT_EQ("/", pc.Path()); | |
| 159 EXPECT_EQ("", pc.Name()); | |
| 160 EXPECT_EQ("\"BLA\\\"HHH\"", pc.Value()); | |
| 161 EXPECT_EQ(2U, pc.NumberOfAttributes()); | |
| 162 } | |
| 163 | |
| 164 TEST(ParsedCookieTest, QuoteOffTheEnd) { | |
| 165 CookieMonster::ParsedCookie pc("a=\"B"); | |
| 166 EXPECT_TRUE(pc.IsValid()); | |
| 167 EXPECT_EQ("a", pc.Name()); | |
| 168 EXPECT_EQ("\"B", pc.Value()); | |
| 169 EXPECT_EQ(0U, pc.NumberOfAttributes()); | |
| 170 } | |
| 171 | |
| 172 TEST(ParsedCookieTest, MissingName) { | |
| 173 CookieMonster::ParsedCookie pc("=ABC"); | |
| 174 EXPECT_TRUE(pc.IsValid()); | |
| 175 EXPECT_EQ("", pc.Name()); | |
| 176 EXPECT_EQ("ABC", pc.Value()); | |
| 177 EXPECT_EQ(0U, pc.NumberOfAttributes()); | |
| 178 } | |
| 179 | |
| 180 TEST(ParsedCookieTest, MissingValue) { | |
| 181 CookieMonster::ParsedCookie pc("ABC=; path = /wee"); | |
| 182 EXPECT_TRUE(pc.IsValid()); | |
| 183 EXPECT_EQ("ABC", pc.Name()); | |
| 184 EXPECT_EQ("", pc.Value()); | |
| 185 EXPECT_TRUE(pc.HasPath()); | |
| 186 EXPECT_EQ("/wee", pc.Path()); | |
| 187 EXPECT_EQ(1U, pc.NumberOfAttributes()); | |
| 188 } | |
| 189 | |
| 190 TEST(ParsedCookieTest, Whitespace) { | |
| 191 CookieMonster::ParsedCookie pc(" A = BC ;secure;;; httponly"); | |
| 192 EXPECT_TRUE(pc.IsValid()); | |
| 193 EXPECT_EQ("A", pc.Name()); | |
| 194 EXPECT_EQ("BC", pc.Value()); | |
| 195 EXPECT_FALSE(pc.HasPath()); | |
| 196 EXPECT_FALSE(pc.HasDomain()); | |
| 197 EXPECT_TRUE(pc.IsSecure()); | |
| 198 EXPECT_TRUE(pc.IsHttpOnly()); | |
| 199 // We parse anything between ; as attributes, so we end up with two | |
| 200 // attributes with an empty string name and value. | |
| 201 EXPECT_EQ(4U, pc.NumberOfAttributes()); | |
| 202 } | |
| 203 TEST(ParsedCookieTest, MultipleEquals) { | |
| 204 CookieMonster::ParsedCookie pc(" A=== BC ;secure;;; httponly"); | |
| 205 EXPECT_TRUE(pc.IsValid()); | |
| 206 EXPECT_EQ("A", pc.Name()); | |
| 207 EXPECT_EQ("== BC", pc.Value()); | |
| 208 EXPECT_FALSE(pc.HasPath()); | |
| 209 EXPECT_FALSE(pc.HasDomain()); | |
| 210 EXPECT_TRUE(pc.IsSecure()); | |
| 211 EXPECT_TRUE(pc.IsHttpOnly()); | |
| 212 EXPECT_EQ(4U, pc.NumberOfAttributes()); | |
| 213 } | |
| 214 | |
| 215 TEST(ParsedCookieTest, MACKey) { | |
| 216 CookieMonster::ParsedCookie pc("foo=bar; MAC-Key=3900ac9anw9incvw9f"); | |
| 217 EXPECT_TRUE(pc.IsValid()); | |
| 218 EXPECT_EQ("foo", pc.Name()); | |
| 219 EXPECT_EQ("bar", pc.Value()); | |
| 220 EXPECT_EQ("3900ac9anw9incvw9f", pc.MACKey()); | |
| 221 EXPECT_EQ(1U, pc.NumberOfAttributes()); | |
| 222 } | |
| 223 | |
| 224 TEST(ParsedCookieTest, MACAlgorithm) { | |
| 225 CookieMonster::ParsedCookie pc("foo=bar; MAC-Algorithm=hmac-sha-1"); | |
| 226 EXPECT_TRUE(pc.IsValid()); | |
| 227 EXPECT_EQ("foo", pc.Name()); | |
| 228 EXPECT_EQ("bar", pc.Value()); | |
| 229 EXPECT_EQ("hmac-sha-1", pc.MACAlgorithm()); | |
| 230 EXPECT_EQ(1U, pc.NumberOfAttributes()); | |
| 231 } | |
| 232 | |
| 233 TEST(ParsedCookieTest, MACKeyAndMACAlgorithm) { | |
| 234 CookieMonster::ParsedCookie pc( | |
| 235 "foo=bar; MAC-Key=voiae-09fj0302nfqf; MAC-Algorithm=hmac-sha-256"); | |
| 236 EXPECT_TRUE(pc.IsValid()); | |
| 237 EXPECT_EQ("foo", pc.Name()); | |
| 238 EXPECT_EQ("bar", pc.Value()); | |
| 239 EXPECT_EQ("voiae-09fj0302nfqf", pc.MACKey()); | |
| 240 EXPECT_EQ("hmac-sha-256", pc.MACAlgorithm()); | |
| 241 EXPECT_EQ(2U, pc.NumberOfAttributes()); | |
| 242 } | |
| 243 | |
| 244 TEST(ParsedCookieTest, QuotedTrailingWhitespace) { | |
| 245 CookieMonster::ParsedCookie pc("ANCUUID=\"zohNumRKgI0oxyhSsV3Z7D\" ; " | |
| 246 "expires=Sun, 18-Apr-2027 21:06:29 GMT ; " | |
| 247 "path=/ ; "); | |
| 248 EXPECT_TRUE(pc.IsValid()); | |
| 249 EXPECT_EQ("ANCUUID", pc.Name()); | |
| 250 // Stripping whitespace after the quotes matches all other major browsers. | |
| 251 EXPECT_EQ("\"zohNumRKgI0oxyhSsV3Z7D\"", pc.Value()); | |
| 252 EXPECT_TRUE(pc.HasExpires()); | |
| 253 EXPECT_TRUE(pc.HasPath()); | |
| 254 EXPECT_EQ("/", pc.Path()); | |
| 255 EXPECT_EQ(2U, pc.NumberOfAttributes()); | |
| 256 } | |
| 257 | |
| 258 TEST(ParsedCookieTest, TrailingWhitespace) { | |
| 259 CookieMonster::ParsedCookie pc("ANCUUID=zohNumRKgI0oxyhSsV3Z7D ; " | |
| 260 "expires=Sun, 18-Apr-2027 21:06:29 GMT ; " | |
| 261 "path=/ ; "); | |
| 262 EXPECT_TRUE(pc.IsValid()); | |
| 263 EXPECT_EQ("ANCUUID", pc.Name()); | |
| 264 EXPECT_EQ("zohNumRKgI0oxyhSsV3Z7D", pc.Value()); | |
| 265 EXPECT_TRUE(pc.HasExpires()); | |
| 266 EXPECT_TRUE(pc.HasPath()); | |
| 267 EXPECT_EQ("/", pc.Path()); | |
| 268 EXPECT_EQ(2U, pc.NumberOfAttributes()); | |
| 269 } | |
| 270 | |
| 271 TEST(ParsedCookieTest, TooManyPairs) { | |
| 272 std::string blankpairs; | |
| 273 blankpairs.resize(CookieMonster::ParsedCookie::kMaxPairs - 1, ';'); | |
| 274 | |
| 275 CookieMonster::ParsedCookie pc1(blankpairs + "secure"); | |
| 276 EXPECT_TRUE(pc1.IsValid()); | |
| 277 EXPECT_TRUE(pc1.IsSecure()); | |
| 278 | |
| 279 CookieMonster::ParsedCookie pc2(blankpairs + ";secure"); | |
| 280 EXPECT_TRUE(pc2.IsValid()); | |
| 281 EXPECT_FALSE(pc2.IsSecure()); | |
| 282 } | |
| 283 | |
| 284 // TODO(erikwright): some better test cases for invalid cookies. | |
| 285 TEST(ParsedCookieTest, InvalidWhitespace) { | |
| 286 CookieMonster::ParsedCookie pc(" "); | |
| 287 EXPECT_FALSE(pc.IsValid()); | |
| 288 } | |
| 289 | |
| 290 TEST(ParsedCookieTest, InvalidTooLong) { | |
| 291 std::string maxstr; | |
| 292 maxstr.resize(CookieMonster::ParsedCookie::kMaxCookieSize, 'a'); | |
| 293 | |
| 294 CookieMonster::ParsedCookie pc1(maxstr); | |
| 295 EXPECT_TRUE(pc1.IsValid()); | |
| 296 | |
| 297 CookieMonster::ParsedCookie pc2(maxstr + "A"); | |
| 298 EXPECT_FALSE(pc2.IsValid()); | |
| 299 } | |
| 300 | |
| 301 TEST(ParsedCookieTest, InvalidEmpty) { | |
| 302 CookieMonster::ParsedCookie pc(""); | |
| 303 EXPECT_FALSE(pc.IsValid()); | |
| 304 } | |
| 305 | |
| 306 TEST(ParsedCookieTest, EmbeddedTerminator) { | |
| 307 CookieMonster::ParsedCookie pc1("AAA=BB\0ZYX"); | |
| 308 CookieMonster::ParsedCookie pc2("AAA=BB\rZYX"); | |
| 309 CookieMonster::ParsedCookie pc3("AAA=BB\nZYX"); | |
| 310 EXPECT_TRUE(pc1.IsValid()); | |
| 311 EXPECT_EQ("AAA", pc1.Name()); | |
| 312 EXPECT_EQ("BB", pc1.Value()); | |
| 313 EXPECT_TRUE(pc2.IsValid()); | |
| 314 EXPECT_EQ("AAA", pc2.Name()); | |
| 315 EXPECT_EQ("BB", pc2.Value()); | |
| 316 EXPECT_TRUE(pc3.IsValid()); | |
| 317 EXPECT_EQ("AAA", pc3.Name()); | |
| 318 EXPECT_EQ("BB", pc3.Value()); | |
| 319 } | |
| 320 | |
| 321 TEST(ParsedCookieTest, ParseTokensAndValues) { | |
| 322 EXPECT_EQ("hello", | |
| 323 CookieMonster::ParsedCookie::ParseTokenString( | |
| 324 "hello\nworld")); | |
| 325 EXPECT_EQ("fs!!@", | |
| 326 CookieMonster::ParsedCookie::ParseTokenString( | |
| 327 "fs!!@;helloworld")); | |
| 328 EXPECT_EQ("hello world\tgood", | |
| 329 CookieMonster::ParsedCookie::ParseTokenString( | |
| 330 "hello world\tgood\rbye")); | |
| 331 EXPECT_EQ("A", | |
| 332 CookieMonster::ParsedCookie::ParseTokenString( | |
| 333 "A=B=C;D=E")); | |
| 334 EXPECT_EQ("hello", | |
| 335 CookieMonster::ParsedCookie::ParseValueString( | |
| 336 "hello\nworld")); | |
| 337 EXPECT_EQ("fs!!@", | |
| 338 CookieMonster::ParsedCookie::ParseValueString( | |
| 339 "fs!!@;helloworld")); | |
| 340 EXPECT_EQ("hello world\tgood", | |
| 341 CookieMonster::ParsedCookie::ParseValueString( | |
| 342 "hello world\tgood\rbye")); | |
| 343 EXPECT_EQ("A=B=C", | |
| 344 CookieMonster::ParsedCookie::ParseValueString( | |
| 345 "A=B=C;D=E")); | |
| 346 } | |
| 347 | |
| 348 namespace { | |
| 349 | |
| 350 struct CookieMonsterTestTraits { | |
| 351 static scoped_refptr<CookieStore> Create() { | |
| 352 return new CookieMonster(NULL, NULL); | |
| 353 } | |
| 354 | |
| 355 static const bool is_cookie_monster = true; | |
| 356 static const bool supports_http_only = true; | |
| 357 static const bool supports_cookies_with_info = true; | |
| 358 static const bool supports_non_dotted_domains = true; | |
| 359 static const bool supports_trailing_dots = true; | |
| 360 static const bool filters_schemes = true; | |
| 361 static const bool has_path_prefix_bug = false; | |
| 362 static const int creation_time_granularity_in_ms = 0; | |
| 363 }; | |
| 364 | |
| 365 INSTANTIATE_TYPED_TEST_CASE_P(CookieMonster, | |
| 366 CookieStoreTest, | |
| 367 CookieMonsterTestTraits); | |
| 368 | |
| 369 INSTANTIATE_TYPED_TEST_CASE_P(CookieMonster, | |
| 370 MultiThreadedCookieStoreTest, | |
| 371 CookieMonsterTestTraits); | |
| 372 | |
| 373 class CookieMonsterTest : public CookieStoreTest<CookieMonsterTestTraits> { | |
| 374 protected: | |
| 375 | |
| 376 CookieList GetAllCookies(CookieMonster* cm) { | |
| 377 DCHECK(cm); | |
| 378 GetCookieListCallback callback; | |
| 379 cm->GetAllCookiesAsync( | |
| 380 base::Bind(&GetCookieListCallback::Run, | |
| 381 base::Unretained(&callback))); | |
| 382 RunFor(kTimeout); | |
| 383 EXPECT_TRUE(callback.did_run()); | |
| 384 return callback.cookies(); | |
| 385 } | |
| 386 | |
| 387 CookieList GetAllCookiesForURL(CookieMonster* cm, | |
| 388 const GURL& url) { | |
| 389 DCHECK(cm); | |
| 390 GetCookieListCallback callback; | |
| 391 cm->GetAllCookiesForURLAsync( | |
| 392 url, base::Bind(&GetCookieListCallback::Run, | |
| 393 base::Unretained(&callback))); | |
| 394 RunFor(kTimeout); | |
| 395 EXPECT_TRUE(callback.did_run()); | |
| 396 return callback.cookies(); | |
| 397 } | |
| 398 | |
| 399 CookieList GetAllCookiesForURLWithOptions(CookieMonster* cm, | |
| 400 const GURL& url, | |
| 401 const CookieOptions& options) { | |
| 402 DCHECK(cm); | |
| 403 GetCookieListCallback callback; | |
| 404 cm->GetAllCookiesForURLWithOptionsAsync( | |
| 405 url, options, base::Bind(&GetCookieListCallback::Run, | |
| 406 base::Unretained(&callback))); | |
| 407 RunFor(kTimeout); | |
| 408 EXPECT_TRUE(callback.did_run()); | |
| 409 return callback.cookies(); | |
| 410 } | |
| 411 | |
| 412 bool SetCookieWithDetails(CookieMonster* cm, | |
| 413 const GURL& url, | |
| 414 const std::string& name, | |
| 415 const std::string& value, | |
| 416 const std::string& domain, | |
| 417 const std::string& path, | |
| 418 const base::Time& expiration_time, | |
| 419 bool secure, bool http_only) { | |
| 420 DCHECK(cm); | |
| 421 SetCookieCallback callback; | |
| 422 cm->SetCookieWithDetailsAsync( | |
| 423 url, name, value, domain, path, expiration_time, secure, http_only, | |
| 424 base::Bind(&SetCookieCallback::Run, base::Unretained(&callback))); | |
| 425 RunFor(kTimeout); | |
| 426 EXPECT_TRUE(callback.did_run()); | |
| 427 return callback.result(); | |
| 428 } | |
| 429 | |
| 430 int DeleteAll(CookieMonster*cm) { | |
| 431 DCHECK(cm); | |
| 432 DeleteCallback callback; | |
| 433 cm->DeleteAllAsync( | |
| 434 base::Bind(&DeleteCallback::Run, base::Unretained(&callback))); | |
| 435 RunFor(kTimeout); | |
| 436 EXPECT_TRUE(callback.did_run()); | |
| 437 return callback.num_deleted(); | |
| 438 } | |
| 439 | |
| 440 int DeleteAllCreatedBetween(CookieMonster*cm, | |
| 441 const base::Time& delete_begin, | |
| 442 const base::Time& delete_end) { | |
| 443 DCHECK(cm); | |
| 444 DeleteCallback callback; | |
| 445 cm->DeleteAllCreatedBetweenAsync( | |
| 446 delete_begin, delete_end, | |
| 447 base::Bind(&DeleteCallback::Run, base::Unretained(&callback))); | |
| 448 RunFor(kTimeout); | |
| 449 EXPECT_TRUE(callback.did_run()); | |
| 450 return callback.num_deleted(); | |
| 451 } | |
| 452 | |
| 453 int DeleteAllForHost(CookieMonster*cm, | |
| 454 const GURL& url) { | |
| 455 DCHECK(cm); | |
| 456 DeleteCallback callback; | |
| 457 cm->DeleteAllForHostAsync( | |
| 458 url, base::Bind(&DeleteCallback::Run, base::Unretained(&callback))); | |
| 459 RunFor(kTimeout); | |
| 460 EXPECT_TRUE(callback.did_run()); | |
| 461 return callback.num_deleted(); | |
| 462 } | |
| 463 | |
| 464 bool DeleteCanonicalCookie(CookieMonster*cm, | |
| 465 const CookieMonster::CanonicalCookie& cookie) { | |
| 466 DCHECK(cm); | |
| 467 SetCookieCallback callback; | |
| 468 cm->DeleteCanonicalCookieAsync( | |
| 469 cookie, | |
| 470 base::Bind(&SetCookieCallback::Run, base::Unretained(&callback))); | |
| 471 RunFor(kTimeout); | |
| 472 EXPECT_TRUE(callback.did_run()); | |
| 473 return callback.result(); | |
| 474 } | |
| 475 | |
| 476 // Helper for DeleteAllForHost test; repopulates CM with same layout | |
| 477 // each time. | |
| 478 void PopulateCmForDeleteAllForHost(scoped_refptr<CookieMonster> cm) { | |
| 479 GURL url_top_level_domain_plus_1(kTopLevelDomainPlus1); | |
| 480 GURL url_top_level_domain_plus_2(kTopLevelDomainPlus2); | |
| 481 GURL url_top_level_domain_plus_2_secure(kTopLevelDomainPlus2Secure); | |
| 482 GURL url_top_level_domain_plus_3(kTopLevelDomainPlus3); | |
| 483 GURL url_other(kOtherDomain); | |
| 484 | |
| 485 DeleteAll(cm); | |
| 486 | |
| 487 // Static population for probe: | |
| 488 // * Three levels of domain cookie (.b.a, .c.b.a, .d.c.b.a) | |
| 489 // * Three levels of host cookie (w.b.a, w.c.b.a, w.d.c.b.a) | |
| 490 // * http_only cookie (w.c.b.a) | |
| 491 // * Two secure cookies (.c.b.a, w.c.b.a) | |
| 492 // * Two domain path cookies (.c.b.a/dir1, .c.b.a/dir1/dir2) | |
| 493 // * Two host path cookies (w.c.b.a/dir1, w.c.b.a/dir1/dir2) | |
| 494 | |
| 495 // Domain cookies | |
| 496 EXPECT_TRUE(this->SetCookieWithDetails(cm, url_top_level_domain_plus_1, | |
| 497 "dom_1", "X", ".harvard.edu", "/", | |
| 498 base::Time(), false, false)); | |
| 499 EXPECT_TRUE(this->SetCookieWithDetails(cm, url_top_level_domain_plus_2, | |
| 500 "dom_2", "X", ".math.harvard.edu", | |
| 501 "/", base::Time(), false, false)); | |
| 502 EXPECT_TRUE(this->SetCookieWithDetails(cm, url_top_level_domain_plus_3, | |
| 503 "dom_3", "X", | |
| 504 ".bourbaki.math.harvard.edu", "/", | |
| 505 base::Time(), false, false)); | |
| 506 | |
| 507 // Host cookies | |
| 508 EXPECT_TRUE(this->SetCookieWithDetails(cm, url_top_level_domain_plus_1, | |
| 509 "host_1", "X", "", "/", | |
| 510 base::Time(), false, false)); | |
| 511 EXPECT_TRUE(this->SetCookieWithDetails(cm, url_top_level_domain_plus_2, | |
| 512 "host_2", "X", "", "/", | |
| 513 base::Time(), false, false)); | |
| 514 EXPECT_TRUE(this->SetCookieWithDetails(cm, url_top_level_domain_plus_3, | |
| 515 "host_3", "X", "", "/", | |
| 516 base::Time(), false, false)); | |
| 517 | |
| 518 // Http_only cookie | |
| 519 EXPECT_TRUE(this->SetCookieWithDetails(cm, url_top_level_domain_plus_2, | |
| 520 "httpo_check", "X", "", "/", | |
| 521 base::Time(), false, true)); | |
| 522 | |
| 523 // Secure cookies | |
| 524 EXPECT_TRUE(this->SetCookieWithDetails(cm, | |
| 525 url_top_level_domain_plus_2_secure, | |
| 526 "sec_dom", "X", ".math.harvard.edu", | |
| 527 "/", base::Time(), true, false)); | |
| 528 EXPECT_TRUE(this->SetCookieWithDetails(cm, | |
| 529 url_top_level_domain_plus_2_secure, | |
| 530 "sec_host", "X", "", "/", | |
| 531 base::Time(), true, false)); | |
| 532 | |
| 533 // Domain path cookies | |
| 534 EXPECT_TRUE(this->SetCookieWithDetails(cm, url_top_level_domain_plus_2, | |
| 535 "dom_path_1", "X", | |
| 536 ".math.harvard.edu", "/dir1", | |
| 537 base::Time(), false, false)); | |
| 538 EXPECT_TRUE(this->SetCookieWithDetails(cm, url_top_level_domain_plus_2, | |
| 539 "dom_path_2", "X", | |
| 540 ".math.harvard.edu", "/dir1/dir2", | |
| 541 base::Time(), false, false)); | |
| 542 | |
| 543 // Host path cookies | |
| 544 EXPECT_TRUE(this->SetCookieWithDetails(cm, url_top_level_domain_plus_2, | |
| 545 "host_path_1", "X", | |
| 546 "", "/dir1", | |
| 547 base::Time(), false, false)); | |
| 548 EXPECT_TRUE(this->SetCookieWithDetails(cm, url_top_level_domain_plus_2, | |
| 549 "host_path_2", "X", | |
| 550 "", "/dir1/dir2", | |
| 551 base::Time(), false, false)); | |
| 552 | |
| 553 EXPECT_EQ(13U, this->GetAllCookies(cm).size()); | |
| 554 } | |
| 555 | |
| 556 Time GetFirstCookieAccessDate(CookieMonster* cm) { | |
| 557 const CookieList all_cookies(this->GetAllCookies(cm)); | |
| 558 return all_cookies.front().LastAccessDate(); | |
| 559 } | |
| 560 | |
| 561 bool FindAndDeleteCookie(CookieMonster* cm, | |
| 562 const std::string& domain, | |
| 563 const std::string& name) { | |
| 564 CookieList cookies = this->GetAllCookies(cm); | |
| 565 for (CookieList::iterator it = cookies.begin(); | |
| 566 it != cookies.end(); ++it) | |
| 567 if (it->Domain() == domain && it->Name() == name) | |
| 568 return this->DeleteCanonicalCookie(cm, *it); | |
| 569 return false; | |
| 570 } | |
| 571 | |
| 572 int CountInString(const std::string& str, char c) { | |
| 573 return std::count(str.begin(), str.end(), c); | |
| 574 } | |
| 575 | |
| 576 void TestHostGarbageCollectHelper( | |
| 577 int domain_max_cookies, | |
| 578 int domain_purge_cookies) { | |
| 579 const int more_than_enough_cookies = | |
| 580 (domain_max_cookies + domain_purge_cookies) * 2; | |
| 581 // Add a bunch of cookies on a single host, should purge them. | |
| 582 { | |
| 583 scoped_refptr<CookieMonster> cm(new CookieMonster(NULL, NULL)); | |
| 584 for (int i = 0; i < more_than_enough_cookies; ++i) { | |
| 585 std::string cookie = base::StringPrintf("a%03d=b", i); | |
| 586 EXPECT_TRUE(SetCookie(cm, url_google_, cookie)); | |
| 587 std::string cookies = this->GetCookies(cm, url_google_); | |
| 588 // Make sure we find it in the cookies. | |
| 589 EXPECT_NE(cookies.find(cookie), std::string::npos); | |
| 590 // Count the number of cookies. | |
| 591 EXPECT_LE(CountInString(cookies, '='), domain_max_cookies); | |
| 592 } | |
| 593 } | |
| 594 | |
| 595 // Add a bunch of cookies on multiple hosts within a single eTLD. | |
| 596 // Should keep at least kDomainMaxCookies - kDomainPurgeCookies | |
| 597 // between them. We shouldn't go above kDomainMaxCookies for both together. | |
| 598 GURL url_google_specific(kUrlGoogleSpecific); | |
| 599 { | |
| 600 scoped_refptr<CookieMonster> cm(new CookieMonster(NULL, NULL)); | |
| 601 for (int i = 0; i < more_than_enough_cookies; ++i) { | |
| 602 std::string cookie_general = base::StringPrintf("a%03d=b", i); | |
| 603 EXPECT_TRUE(SetCookie(cm, url_google_, cookie_general)); | |
| 604 std::string cookie_specific = base::StringPrintf("c%03d=b", i); | |
| 605 EXPECT_TRUE(SetCookie(cm, url_google_specific, cookie_specific)); | |
| 606 std::string cookies_general = this->GetCookies(cm, url_google_); | |
| 607 EXPECT_NE(cookies_general.find(cookie_general), std::string::npos); | |
| 608 std::string cookies_specific = | |
| 609 this->GetCookies(cm, url_google_specific); | |
| 610 EXPECT_NE(cookies_specific.find(cookie_specific), std::string::npos); | |
| 611 EXPECT_LE((CountInString(cookies_general, '=') + | |
| 612 CountInString(cookies_specific, '=')), | |
| 613 domain_max_cookies); | |
| 614 } | |
| 615 // After all this, there should be at least | |
| 616 // kDomainMaxCookies - kDomainPurgeCookies for both URLs. | |
| 617 std::string cookies_general = this->GetCookies(cm, url_google_); | |
| 618 std::string cookies_specific = this->GetCookies(cm, url_google_specific); | |
| 619 int total_cookies = (CountInString(cookies_general, '=') + | |
| 620 CountInString(cookies_specific, '=')); | |
| 621 EXPECT_GE(total_cookies, | |
| 622 domain_max_cookies - domain_purge_cookies); | |
| 623 EXPECT_LE(total_cookies, domain_max_cookies); | |
| 624 } | |
| 625 } | |
| 626 | |
| 627 // Function for creating a CM with a number of cookies in it, | |
| 628 // no store (and hence no ability to affect access time). | |
| 629 CookieMonster* CreateMonsterForGC(int num_cookies) { | |
| 630 CookieMonster* cm(new CookieMonster(NULL, NULL)); | |
| 631 for (int i = 0; i < num_cookies; i++) { | |
| 632 SetCookie(cm, GURL(StringPrintf("http://h%05d.izzle", i)), "a=1"); | |
| 633 } | |
| 634 return cm; | |
| 635 } | |
| 636 }; | |
| 637 | |
| 638 // TODO(erikwright): Replace the other callbacks and synchronous helper methods | |
| 639 // in this test suite with these Mocks. | |
| 640 template<typename T, typename C> class MockCookieCallback { | |
| 641 public: | |
| 642 C AsCallback() { | |
| 643 return base::Bind(&T::Invoke, base::Unretained(static_cast<T*>(this))); | |
| 644 } | |
| 645 }; | |
| 646 | |
| 647 class MockGetCookiesCallback | |
| 648 : public MockCookieCallback<MockGetCookiesCallback, | |
| 649 CookieStore::GetCookiesCallback> { | |
| 650 public: | |
| 651 MOCK_METHOD1(Invoke, void(const std::string& cookies)); | |
| 652 }; | |
| 653 | |
| 654 class MockGetCookieInfoCallback | |
| 655 : public MockCookieCallback<MockGetCookieInfoCallback, | |
| 656 CookieStore::GetCookieInfoCallback> { | |
| 657 public: | |
| 658 MOCK_METHOD2(Invoke, | |
| 659 void(const std::string& cookies, | |
| 660 const std::vector<CookieStore::CookieInfo>& cookie_infos)); | |
| 661 }; | |
| 662 | |
| 663 class MockSetCookiesCallback | |
| 664 : public MockCookieCallback<MockSetCookiesCallback, | |
| 665 CookieStore::SetCookiesCallback> { | |
| 666 public: | |
| 667 MOCK_METHOD1(Invoke, void(bool success)); | |
| 668 }; | |
| 669 | |
| 670 class MockClosure | |
| 671 : public MockCookieCallback<MockClosure, base::Closure> { | |
| 672 public: | |
| 673 MOCK_METHOD0(Invoke, void(void)); | |
| 674 }; | |
| 675 | |
| 676 class MockGetCookieListCallback | |
| 677 : public MockCookieCallback<MockGetCookieListCallback, | |
| 678 CookieMonster::GetCookieListCallback> { | |
| 679 public: | |
| 680 MOCK_METHOD1(Invoke, void(const CookieList& cookies)); | |
| 681 }; | |
| 682 | |
| 683 class MockDeleteCallback | |
| 684 : public MockCookieCallback<MockDeleteCallback, | |
| 685 CookieMonster::DeleteCallback> { | |
| 686 public: | |
| 687 MOCK_METHOD1(Invoke, void(int num_deleted)); | |
| 688 }; | |
| 689 | |
| 690 class MockDeleteCookieCallback | |
| 691 : public MockCookieCallback<MockDeleteCookieCallback, | |
| 692 CookieMonster::DeleteCookieCallback> { | |
| 693 public: | |
| 694 MOCK_METHOD1(Invoke, void(bool success)); | |
| 695 }; | |
| 696 | |
| 697 ACTION(QuitCurrentMessageLoop) { | |
| 698 MessageLoop::current()->PostTask(FROM_HERE, MessageLoop::QuitClosure()); | |
| 699 } | |
| 700 | |
| 701 // TODO(erikwright): When the synchronous helpers 'GetCookies' etc. are removed, | |
| 702 // rename these, removing the 'Action' suffix. | |
| 703 ACTION_P4(DeleteCookieAction, cookie_monster, url, name, callback) { | |
| 704 cookie_monster->DeleteCookieAsync(url, name, callback->AsCallback()); | |
| 705 } | |
| 706 ACTION_P3(GetCookiesAction, cookie_monster, url, callback) { | |
| 707 cookie_monster->GetCookiesWithOptionsAsync( | |
| 708 url, CookieOptions(), callback->AsCallback()); | |
| 709 } | |
| 710 ACTION_P3(GetCookiesWithInfoAction, cookie_monster, url, callback) { | |
| 711 cookie_monster->GetCookiesWithInfoAsync( | |
| 712 url, CookieOptions(), callback->AsCallback()); | |
| 713 } | |
| 714 ACTION_P4(SetCookieAction, cookie_monster, url, cookie_line, callback) { | |
| 715 cookie_monster->SetCookieWithOptionsAsync( | |
| 716 url, cookie_line, CookieOptions(), callback->AsCallback()); | |
| 717 } | |
| 718 ACTION_P4(DeleteAllCreatedBetweenAction, | |
| 719 cookie_monster, delete_begin, delete_end, callback) { | |
| 720 cookie_monster->DeleteAllCreatedBetweenAsync( | |
| 721 delete_begin, delete_end, callback->AsCallback()); | |
| 722 } | |
| 723 ACTION_P10(SetCookieWithDetailsAction, | |
| 724 cookie_monster, url, name, value, domain, path, expiration_time, | |
| 725 secure, http_only, callback) { | |
| 726 cookie_monster->SetCookieWithDetailsAsync( | |
| 727 url, name, value, domain, path, expiration_time, secure, http_only, | |
| 728 callback->AsCallback()); | |
| 729 } | |
| 730 | |
| 731 ACTION_P2(GetAllCookiesAction, cookie_monster, callback) { | |
| 732 cookie_monster->GetAllCookiesAsync(callback->AsCallback()); | |
| 733 } | |
| 734 | |
| 735 ACTION_P3(DeleteAllForHostAction, cookie_monster, url, callback) { | |
| 736 cookie_monster->DeleteAllForHostAsync(url, callback->AsCallback()); | |
| 737 } | |
| 738 | |
| 739 ACTION_P3(DeleteCanonicalCookieAction, cookie_monster, cookie, callback) { | |
| 740 cookie_monster->DeleteCanonicalCookieAsync(cookie, callback->AsCallback()); | |
| 741 } | |
| 742 | |
| 743 ACTION_P2(DeleteAllAction, cookie_monster, callback) { | |
| 744 cookie_monster->DeleteAllAsync(callback->AsCallback()); | |
| 745 } | |
| 746 | |
| 747 ACTION_P3(GetAllCookiesForUrlWithOptionsAction, cookie_monster, url, callback) { | |
| 748 cookie_monster->GetAllCookiesForURLWithOptionsAsync( | |
| 749 url, CookieOptions(), callback->AsCallback()); | |
| 750 } | |
| 751 | |
| 752 ACTION_P3(GetAllCookiesForUrlAction, cookie_monster, url, callback) { | |
| 753 cookie_monster->GetAllCookiesForURLAsync(url, callback->AsCallback()); | |
| 754 } | |
| 755 | |
| 756 ACTION_P(PushCallbackAction, callback_vector) { | |
| 757 callback_vector->push(arg1); | |
| 758 } | |
| 759 | |
| 760 } // namespace | |
| 761 | |
| 762 // This test suite verifies the task deferral behaviour of the CookieMonster. | |
| 763 // Specifically, for each asynchronous method, verify that: | |
| 764 // 1. invoking it on an uninitialized cookie store causes the store to begin | |
| 765 // chain-loading its backing data or loading data for a specific domain key | |
| 766 // (eTLD+1). | |
| 767 // 2. The initial invocation does not complete until the loading completes. | |
| 768 // 3. Invocations after the loading has completed complete immediately. | |
| 769 class DeferredCookieTaskTest : public CookieMonsterTest { | |
| 770 protected: | |
| 771 DeferredCookieTaskTest() { | |
| 772 persistent_store_ = new NewMockPersistentCookieStore(); | |
| 773 cookie_monster_ = new CookieMonster(persistent_store_.get(), NULL); | |
| 774 } | |
| 775 | |
| 776 // Defines a cookie to be returned from PersistentCookieStore::Load | |
| 777 void DeclareLoadedCookie(const std::string& key, | |
| 778 const std::string& cookie_line, | |
| 779 const base::Time& creation_time) { | |
| 780 AddCookieToList(key, cookie_line, creation_time, &loaded_cookies_); | |
| 781 } | |
| 782 | |
| 783 // Runs the message loop, waiting until PersistentCookieStore::Load is called. | |
| 784 // Call CompleteLoadingAndWait to cause the load to complete. | |
| 785 void WaitForLoadCall() { | |
| 786 RunFor(kTimeout); | |
| 787 | |
| 788 // Verify that PeristentStore::Load was called. | |
| 789 testing::Mock::VerifyAndClear(persistent_store_.get()); | |
| 790 } | |
| 791 | |
| 792 // Invokes the PersistentCookieStore::LoadCookiesForKey completion callbacks | |
| 793 // and PersistentCookieStore::Load completion callback and waits | |
| 794 // until the message loop is quit. | |
| 795 void CompleteLoadingAndWait() { | |
| 796 while (!loaded_for_key_callbacks_.empty()) { | |
| 797 loaded_for_key_callbacks_.front().Run(loaded_cookies_); | |
| 798 loaded_cookies_.clear(); | |
| 799 loaded_for_key_callbacks_.pop(); | |
| 800 } | |
| 801 | |
| 802 loaded_callback_.Run(loaded_cookies_); | |
| 803 RunFor(kTimeout); | |
| 804 } | |
| 805 | |
| 806 // Performs the provided action, expecting it to cause a call to | |
| 807 // PersistentCookieStore::Load. Call WaitForLoadCall to verify the load call | |
| 808 // is received. | |
| 809 void BeginWith(testing::Action<void(void)> action) { | |
| 810 EXPECT_CALL(*this, Begin()).WillOnce(action); | |
| 811 ExpectLoadCall(); | |
| 812 Begin(); | |
| 813 } | |
| 814 | |
| 815 void BeginWithForDomainKey(std::string key, | |
| 816 testing::Action<void(void)> action) { | |
| 817 EXPECT_CALL(*this, Begin()).WillOnce(action); | |
| 818 ExpectLoadCall(); | |
| 819 ExpectLoadForKeyCall(key, false); | |
| 820 Begin(); | |
| 821 } | |
| 822 | |
| 823 // Declares an expectation that PersistentCookieStore::Load will be called, | |
| 824 // saving the provided callback and sending a quit to the message loop. | |
| 825 void ExpectLoadCall() { | |
| 826 EXPECT_CALL(*persistent_store_, Load(testing::_)).WillOnce(testing::DoAll( | |
| 827 testing::SaveArg<0>(&loaded_callback_), | |
| 828 QuitCurrentMessageLoop())); | |
| 829 } | |
| 830 | |
| 831 // Declares an expectation that PersistentCookieStore::LoadCookiesForKey | |
| 832 // will be called, saving the provided callback and sending a quit to the | |
| 833 // message loop. | |
| 834 void ExpectLoadForKeyCall(std::string key, bool quit_queue) { | |
| 835 if (quit_queue) | |
| 836 EXPECT_CALL(*persistent_store_, LoadCookiesForKey(key, testing::_)). | |
| 837 WillOnce(testing::DoAll( | |
| 838 PushCallbackAction(&loaded_for_key_callbacks_), | |
| 839 QuitCurrentMessageLoop())); | |
| 840 else | |
| 841 EXPECT_CALL(*persistent_store_, LoadCookiesForKey(key, testing::_)). | |
| 842 WillOnce(PushCallbackAction(&loaded_for_key_callbacks_)); | |
| 843 } | |
| 844 | |
| 845 // Invokes the initial action. | |
| 846 MOCK_METHOD0(Begin, void(void)); | |
| 847 | |
| 848 // Returns the CookieMonster instance under test. | |
| 849 CookieMonster& cookie_monster() { return *cookie_monster_; } | |
| 850 | |
| 851 private: | |
| 852 // Declares that mock expectations in this test suite are strictly ordered. | |
| 853 testing::InSequence in_sequence_; | |
| 854 // Holds cookies to be returned from PersistentCookieStore::Load or | |
| 855 // PersistentCookieStore::LoadCookiesForKey. | |
| 856 std::vector<CookieMonster::CanonicalCookie*> loaded_cookies_; | |
| 857 // Stores the callback passed from the CookieMonster to the | |
| 858 // PersistentCookieStore::Load | |
| 859 CookieMonster::PersistentCookieStore::LoadedCallback loaded_callback_; | |
| 860 // Stores the callback passed from the CookieMonster to the | |
| 861 // PersistentCookieStore::LoadCookiesForKey | |
| 862 std::queue<CookieMonster::PersistentCookieStore::LoadedCallback> | |
| 863 loaded_for_key_callbacks_; | |
| 864 | |
| 865 // Stores the CookieMonster under test. | |
| 866 scoped_refptr<CookieMonster> cookie_monster_; | |
| 867 // Stores the mock PersistentCookieStore. | |
| 868 scoped_refptr<NewMockPersistentCookieStore> persistent_store_; | |
| 869 }; | |
| 870 | |
| 871 TEST_F(DeferredCookieTaskTest, DeferredGetCookies) { | |
| 872 DeclareLoadedCookie("www.google.izzle", | |
| 873 "X=1; path=/; expires=Mon, 18-Apr-22 22:50:14 GMT", | |
| 874 Time::Now() + TimeDelta::FromDays(3)); | |
| 875 | |
| 876 MockGetCookiesCallback get_cookies_callback; | |
| 877 | |
| 878 BeginWithForDomainKey("google.izzle", GetCookiesAction( | |
| 879 &cookie_monster(), url_google_, &get_cookies_callback)); | |
| 880 | |
| 881 WaitForLoadCall(); | |
| 882 | |
| 883 EXPECT_CALL(get_cookies_callback, Invoke("X=1")).WillOnce( | |
| 884 GetCookiesAction(&cookie_monster(), url_google_, &get_cookies_callback)); | |
| 885 EXPECT_CALL(get_cookies_callback, Invoke("X=1")).WillOnce( | |
| 886 QuitCurrentMessageLoop()); | |
| 887 | |
| 888 CompleteLoadingAndWait(); | |
| 889 } | |
| 890 | |
| 891 TEST_F(DeferredCookieTaskTest, DeferredGetCookiesWithInfo) { | |
| 892 DeclareLoadedCookie("www.google.izzle", | |
| 893 "X=1; path=/; expires=Mon, 18-Apr-22 22:50:14 GMT", | |
| 894 Time::Now() + TimeDelta::FromDays(3)); | |
| 895 | |
| 896 MockGetCookieInfoCallback get_cookie_info_callback; | |
| 897 | |
| 898 BeginWithForDomainKey("google.izzle", GetCookiesWithInfoAction( | |
| 899 &cookie_monster(), url_google_, &get_cookie_info_callback)); | |
| 900 | |
| 901 WaitForLoadCall(); | |
| 902 | |
| 903 EXPECT_CALL(get_cookie_info_callback, Invoke("X=1", testing::_)).WillOnce( | |
| 904 GetCookiesWithInfoAction( | |
| 905 &cookie_monster(), url_google_, &get_cookie_info_callback)); | |
| 906 EXPECT_CALL(get_cookie_info_callback, Invoke("X=1", testing::_)).WillOnce( | |
| 907 QuitCurrentMessageLoop()); | |
| 908 | |
| 909 CompleteLoadingAndWait(); | |
| 910 } | |
| 911 | |
| 912 TEST_F(DeferredCookieTaskTest, DeferredSetCookie) { | |
| 913 MockSetCookiesCallback set_cookies_callback; | |
| 914 | |
| 915 BeginWithForDomainKey("google.izzle", SetCookieAction( | |
| 916 &cookie_monster(), url_google_, "A=B", &set_cookies_callback)); | |
| 917 | |
| 918 WaitForLoadCall(); | |
| 919 | |
| 920 EXPECT_CALL(set_cookies_callback, Invoke(true)).WillOnce( | |
| 921 SetCookieAction( | |
| 922 &cookie_monster(), url_google_, "X=Y", &set_cookies_callback)); | |
| 923 EXPECT_CALL(set_cookies_callback, Invoke(true)).WillOnce( | |
| 924 QuitCurrentMessageLoop()); | |
| 925 | |
| 926 CompleteLoadingAndWait(); | |
| 927 } | |
| 928 | |
| 929 TEST_F(DeferredCookieTaskTest, DeferredDeleteCookie) { | |
| 930 MockClosure delete_cookie_callback; | |
| 931 | |
| 932 BeginWithForDomainKey("google.izzle", DeleteCookieAction( | |
| 933 &cookie_monster(), url_google_, "A", &delete_cookie_callback)); | |
| 934 | |
| 935 WaitForLoadCall(); | |
| 936 | |
| 937 EXPECT_CALL(delete_cookie_callback, Invoke()).WillOnce( | |
| 938 DeleteCookieAction( | |
| 939 &cookie_monster(), url_google_, "X", &delete_cookie_callback)); | |
| 940 EXPECT_CALL(delete_cookie_callback, Invoke()).WillOnce( | |
| 941 QuitCurrentMessageLoop()); | |
| 942 | |
| 943 CompleteLoadingAndWait(); | |
| 944 } | |
| 945 | |
| 946 TEST_F(DeferredCookieTaskTest, DeferredSetCookieWithDetails) { | |
| 947 MockSetCookiesCallback set_cookies_callback; | |
| 948 | |
| 949 BeginWithForDomainKey("google.izzle", SetCookieWithDetailsAction( | |
| 950 &cookie_monster(), url_google_foo_, "A", "B", std::string(), "/foo", | |
| 951 base::Time(), false, false, &set_cookies_callback)); | |
| 952 | |
| 953 WaitForLoadCall(); | |
| 954 | |
| 955 EXPECT_CALL(set_cookies_callback, Invoke(true)).WillOnce( | |
| 956 SetCookieWithDetailsAction( | |
| 957 &cookie_monster(), url_google_foo_, "A", "B", std::string(), "/foo", | |
| 958 base::Time(), false, false, &set_cookies_callback)); | |
| 959 EXPECT_CALL(set_cookies_callback, Invoke(true)).WillOnce( | |
| 960 QuitCurrentMessageLoop()); | |
| 961 | |
| 962 CompleteLoadingAndWait(); | |
| 963 } | |
| 964 | |
| 965 TEST_F(DeferredCookieTaskTest, DeferredGetAllCookies) { | |
| 966 DeclareLoadedCookie("www.google.izzle", | |
| 967 "X=1; path=/; expires=Mon, 18-Apr-22 22:50:14 GMT", | |
| 968 Time::Now() + TimeDelta::FromDays(3)); | |
| 969 | |
| 970 MockGetCookieListCallback get_cookie_list_callback; | |
| 971 | |
| 972 BeginWith(GetAllCookiesAction( | |
| 973 &cookie_monster(), &get_cookie_list_callback)); | |
| 974 | |
| 975 WaitForLoadCall(); | |
| 976 | |
| 977 EXPECT_CALL(get_cookie_list_callback, Invoke(testing::_)).WillOnce( | |
| 978 GetAllCookiesAction(&cookie_monster(), &get_cookie_list_callback)); | |
| 979 EXPECT_CALL(get_cookie_list_callback, Invoke(testing::_)).WillOnce( | |
| 980 QuitCurrentMessageLoop()); | |
| 981 | |
| 982 CompleteLoadingAndWait(); | |
| 983 } | |
| 984 | |
| 985 TEST_F(DeferredCookieTaskTest, DeferredGetAllForUrlCookies) { | |
| 986 DeclareLoadedCookie("www.google.izzle", | |
| 987 "X=1; path=/; expires=Mon, 18-Apr-22 22:50:14 GMT", | |
| 988 Time::Now() + TimeDelta::FromDays(3)); | |
| 989 | |
| 990 MockGetCookieListCallback get_cookie_list_callback; | |
| 991 | |
| 992 BeginWithForDomainKey("google.izzle", GetAllCookiesForUrlAction( | |
| 993 &cookie_monster(), url_google_, &get_cookie_list_callback)); | |
| 994 | |
| 995 WaitForLoadCall(); | |
| 996 | |
| 997 EXPECT_CALL(get_cookie_list_callback, Invoke(testing::_)).WillOnce( | |
| 998 GetAllCookiesForUrlAction( | |
| 999 &cookie_monster(), url_google_, &get_cookie_list_callback)); | |
| 1000 EXPECT_CALL(get_cookie_list_callback, Invoke(testing::_)).WillOnce( | |
| 1001 QuitCurrentMessageLoop()); | |
| 1002 | |
| 1003 CompleteLoadingAndWait(); | |
| 1004 } | |
| 1005 | |
| 1006 TEST_F(DeferredCookieTaskTest, DeferredGetAllForUrlWithOptionsCookies) { | |
| 1007 DeclareLoadedCookie("www.google.izzle", | |
| 1008 "X=1; path=/; expires=Mon, 18-Apr-22 22:50:14 GMT", | |
| 1009 Time::Now() + TimeDelta::FromDays(3)); | |
| 1010 | |
| 1011 MockGetCookieListCallback get_cookie_list_callback; | |
| 1012 | |
| 1013 BeginWithForDomainKey("google.izzle", GetAllCookiesForUrlWithOptionsAction( | |
| 1014 &cookie_monster(), url_google_, &get_cookie_list_callback)); | |
| 1015 | |
| 1016 WaitForLoadCall(); | |
| 1017 | |
| 1018 EXPECT_CALL(get_cookie_list_callback, Invoke(testing::_)).WillOnce( | |
| 1019 GetAllCookiesForUrlWithOptionsAction( | |
| 1020 &cookie_monster(), url_google_, &get_cookie_list_callback)); | |
| 1021 EXPECT_CALL(get_cookie_list_callback, Invoke(testing::_)).WillOnce( | |
| 1022 QuitCurrentMessageLoop()); | |
| 1023 | |
| 1024 CompleteLoadingAndWait(); | |
| 1025 } | |
| 1026 | |
| 1027 TEST_F(DeferredCookieTaskTest, DeferredDeleteAllCookies) { | |
| 1028 MockDeleteCallback delete_callback; | |
| 1029 | |
| 1030 BeginWith(DeleteAllAction( | |
| 1031 &cookie_monster(), &delete_callback)); | |
| 1032 | |
| 1033 WaitForLoadCall(); | |
| 1034 | |
| 1035 EXPECT_CALL(delete_callback, Invoke(false)).WillOnce( | |
| 1036 DeleteAllAction(&cookie_monster(), &delete_callback)); | |
| 1037 EXPECT_CALL(delete_callback, Invoke(false)).WillOnce( | |
| 1038 QuitCurrentMessageLoop()); | |
| 1039 | |
| 1040 CompleteLoadingAndWait(); | |
| 1041 } | |
| 1042 | |
| 1043 TEST_F(DeferredCookieTaskTest, DeferredDeleteAllCreatedBetweenCookies) { | |
| 1044 MockDeleteCallback delete_callback; | |
| 1045 | |
| 1046 BeginWith(DeleteAllCreatedBetweenAction( | |
| 1047 &cookie_monster(), base::Time(), base::Time::Now(), &delete_callback)); | |
| 1048 | |
| 1049 WaitForLoadCall(); | |
| 1050 | |
| 1051 EXPECT_CALL(delete_callback, Invoke(false)).WillOnce( | |
| 1052 DeleteAllCreatedBetweenAction( | |
| 1053 &cookie_monster(), base::Time(), base::Time::Now(), | |
| 1054 &delete_callback)); | |
| 1055 EXPECT_CALL(delete_callback, Invoke(false)).WillOnce( | |
| 1056 QuitCurrentMessageLoop()); | |
| 1057 | |
| 1058 CompleteLoadingAndWait(); | |
| 1059 } | |
| 1060 | |
| 1061 TEST_F(DeferredCookieTaskTest, DeferredDeleteAllForHostCookies) { | |
| 1062 MockDeleteCallback delete_callback; | |
| 1063 | |
| 1064 BeginWithForDomainKey("google.izzle", DeleteAllForHostAction( | |
| 1065 &cookie_monster(), url_google_, &delete_callback)); | |
| 1066 | |
| 1067 WaitForLoadCall(); | |
| 1068 | |
| 1069 EXPECT_CALL(delete_callback, Invoke(false)).WillOnce( | |
| 1070 DeleteAllForHostAction( | |
| 1071 &cookie_monster(), url_google_, &delete_callback)); | |
| 1072 EXPECT_CALL(delete_callback, Invoke(false)).WillOnce( | |
| 1073 QuitCurrentMessageLoop()); | |
| 1074 | |
| 1075 CompleteLoadingAndWait(); | |
| 1076 } | |
| 1077 | |
| 1078 TEST_F(DeferredCookieTaskTest, DeferredDeleteCanonicalCookie) { | |
| 1079 std::vector<CookieMonster::CanonicalCookie*> cookies; | |
| 1080 CookieMonster::CanonicalCookie cookie = BuildCanonicalCookie( | |
| 1081 "www.google.com", "X=1; path=/", base::Time::Now()); | |
| 1082 | |
| 1083 MockDeleteCookieCallback delete_cookie_callback; | |
| 1084 | |
| 1085 BeginWith(DeleteCanonicalCookieAction( | |
| 1086 &cookie_monster(), cookie, &delete_cookie_callback)); | |
| 1087 | |
| 1088 WaitForLoadCall(); | |
| 1089 | |
| 1090 EXPECT_CALL(delete_cookie_callback, Invoke(false)).WillOnce( | |
| 1091 DeleteCanonicalCookieAction( | |
| 1092 &cookie_monster(), cookie, &delete_cookie_callback)); | |
| 1093 EXPECT_CALL(delete_cookie_callback, Invoke(false)).WillOnce( | |
| 1094 QuitCurrentMessageLoop()); | |
| 1095 | |
| 1096 CompleteLoadingAndWait(); | |
| 1097 } | |
| 1098 | |
| 1099 // Verify that a series of queued tasks are executed in order upon loading of | |
| 1100 // the backing store and that new tasks received while the queued tasks are | |
| 1101 // being dispatched go to the end of the queue. | |
| 1102 TEST_F(DeferredCookieTaskTest, DeferredTaskOrder) { | |
| 1103 DeclareLoadedCookie("www.google.izzle", | |
| 1104 "X=1; path=/; expires=Mon, 18-Apr-22 22:50:14 GMT", | |
| 1105 Time::Now() + TimeDelta::FromDays(3)); | |
| 1106 | |
| 1107 MockGetCookiesCallback get_cookies_callback; | |
| 1108 MockSetCookiesCallback set_cookies_callback; | |
| 1109 MockClosure delete_cookie_callback; | |
| 1110 MockGetCookieInfoCallback get_cookie_info_callback; | |
| 1111 | |
| 1112 EXPECT_CALL(*this, Begin()).WillOnce(testing::DoAll( | |
| 1113 GetCookiesAction( | |
| 1114 &cookie_monster(), url_google_, &get_cookies_callback), | |
| 1115 SetCookieAction( | |
| 1116 &cookie_monster(), url_google_, "A=B", &set_cookies_callback), | |
| 1117 DeleteCookieAction( | |
| 1118 &cookie_monster(), url_google_, "A", &delete_cookie_callback))); | |
| 1119 ExpectLoadCall(); | |
| 1120 ExpectLoadForKeyCall("google.izzle", false); | |
| 1121 Begin(); | |
| 1122 | |
| 1123 WaitForLoadCall(); | |
| 1124 EXPECT_CALL(get_cookies_callback, Invoke("X=1")).WillOnce( | |
| 1125 GetCookiesWithInfoAction( | |
| 1126 &cookie_monster(), url_google_, &get_cookie_info_callback)); | |
| 1127 EXPECT_CALL(get_cookie_info_callback, Invoke("X=1", testing::_)).WillOnce( | |
| 1128 QuitCurrentMessageLoop()); | |
| 1129 EXPECT_CALL(set_cookies_callback, Invoke(true)); | |
| 1130 EXPECT_CALL(delete_cookie_callback, Invoke()); | |
| 1131 | |
| 1132 CompleteLoadingAndWait(); | |
| 1133 } | |
| 1134 | |
| 1135 TEST_F(CookieMonsterTest, TestCookieDateParsing) { | |
| 1136 const struct { | |
| 1137 const char* str; | |
| 1138 const bool valid; | |
| 1139 const time_t epoch; | |
| 1140 } tests[] = { | |
| 1141 { "Sat, 15-Apr-17 21:01:22 GMT", true, 1492290082 }, | |
| 1142 { "Thu, 19-Apr-2007 16:00:00 GMT", true, 1176998400 }, | |
| 1143 { "Wed, 25 Apr 2007 21:02:13 GMT", true, 1177534933 }, | |
| 1144 { "Thu, 19/Apr\\2007 16:00:00 GMT", true, 1176998400 }, | |
| 1145 { "Fri, 1 Jan 2010 01:01:50 GMT", true, 1262307710 }, | |
| 1146 { "Wednesday, 1-Jan-2003 00:00:00 GMT", true, 1041379200 }, | |
| 1147 { ", 1-Jan-2003 00:00:00 GMT", true, 1041379200 }, | |
| 1148 { " 1-Jan-2003 00:00:00 GMT", true, 1041379200 }, | |
| 1149 { "1-Jan-2003 00:00:00 GMT", true, 1041379200 }, | |
| 1150 { "Wed,18-Apr-07 22:50:12 GMT", true, 1176936612 }, | |
| 1151 { "WillyWonka , 18-Apr-07 22:50:12 GMT", true, 1176936612 }, | |
| 1152 { "WillyWonka , 18-Apr-07 22:50:12", true, 1176936612 }, | |
| 1153 { "WillyWonka , 18-apr-07 22:50:12", true, 1176936612 }, | |
| 1154 { "Mon, 18-Apr-1977 22:50:13 GMT", true, 230251813 }, | |
| 1155 { "Mon, 18-Apr-77 22:50:13 GMT", true, 230251813 }, | |
| 1156 // If the cookie came in with the expiration quoted (which in terms of | |
| 1157 // the RFC you shouldn't do), we will get string quoted. Bug 1261605. | |
| 1158 { "\"Sat, 15-Apr-17\\\"21:01:22\\\"GMT\"", true, 1492290082 }, | |
| 1159 // Test with full month names and partial names. | |
| 1160 { "Partyday, 18- April-07 22:50:12", true, 1176936612 }, | |
| 1161 { "Partyday, 18 - Apri-07 22:50:12", true, 1176936612 }, | |
| 1162 { "Wednes, 1-Januar-2003 00:00:00 GMT", true, 1041379200 }, | |
| 1163 // Test that we always take GMT even with other time zones or bogus | |
| 1164 // values. The RFC says everything should be GMT, and in the worst case | |
| 1165 // we are 24 hours off because of zone issues. | |
| 1166 { "Sat, 15-Apr-17 21:01:22", true, 1492290082 }, | |
| 1167 { "Sat, 15-Apr-17 21:01:22 GMT-2", true, 1492290082 }, | |
| 1168 { "Sat, 15-Apr-17 21:01:22 GMT BLAH", true, 1492290082 }, | |
| 1169 { "Sat, 15-Apr-17 21:01:22 GMT-0400", true, 1492290082 }, | |
| 1170 { "Sat, 15-Apr-17 21:01:22 GMT-0400 (EDT)",true, 1492290082 }, | |
| 1171 { "Sat, 15-Apr-17 21:01:22 DST", true, 1492290082 }, | |
| 1172 { "Sat, 15-Apr-17 21:01:22 -0400", true, 1492290082 }, | |
| 1173 { "Sat, 15-Apr-17 21:01:22 (hello there)", true, 1492290082 }, | |
| 1174 // Test that if we encounter multiple : fields, that we take the first | |
| 1175 // that correctly parses. | |
| 1176 { "Sat, 15-Apr-17 21:01:22 11:22:33", true, 1492290082 }, | |
| 1177 { "Sat, 15-Apr-17 ::00 21:01:22", true, 1492290082 }, | |
| 1178 { "Sat, 15-Apr-17 boink:z 21:01:22", true, 1492290082 }, | |
| 1179 // We take the first, which in this case is invalid. | |
| 1180 { "Sat, 15-Apr-17 91:22:33 21:01:22", false, 0 }, | |
| 1181 // amazon.com formats their cookie expiration like this. | |
| 1182 { "Thu Apr 18 22:50:12 2007 GMT", true, 1176936612 }, | |
| 1183 // Test that hh:mm:ss can occur anywhere. | |
| 1184 { "22:50:12 Thu Apr 18 2007 GMT", true, 1176936612 }, | |
| 1185 { "Thu 22:50:12 Apr 18 2007 GMT", true, 1176936612 }, | |
| 1186 { "Thu Apr 22:50:12 18 2007 GMT", true, 1176936612 }, | |
| 1187 { "Thu Apr 18 22:50:12 2007 GMT", true, 1176936612 }, | |
| 1188 { "Thu Apr 18 2007 22:50:12 GMT", true, 1176936612 }, | |
| 1189 { "Thu Apr 18 2007 GMT 22:50:12", true, 1176936612 }, | |
| 1190 // Test that the day and year can be anywhere if they are unambigious. | |
| 1191 { "Sat, 15-Apr-17 21:01:22 GMT", true, 1492290082 }, | |
| 1192 { "15-Sat, Apr-17 21:01:22 GMT", true, 1492290082 }, | |
| 1193 { "15-Sat, Apr 21:01:22 GMT 17", true, 1492290082 }, | |
| 1194 { "15-Sat, Apr 21:01:22 GMT 2017", true, 1492290082 }, | |
| 1195 { "15 Apr 21:01:22 2017", true, 1492290082 }, | |
| 1196 { "15 17 Apr 21:01:22", true, 1492290082 }, | |
| 1197 { "Apr 15 17 21:01:22", true, 1492290082 }, | |
| 1198 { "Apr 15 21:01:22 17", true, 1492290082 }, | |
| 1199 { "2017 April 15 21:01:22", true, 1492290082 }, | |
| 1200 { "15 April 2017 21:01:22", true, 1492290082 }, | |
| 1201 // Some invalid dates | |
| 1202 { "98 April 17 21:01:22", false, 0 }, | |
| 1203 { "Thu, 012-Aug-2008 20:49:07 GMT", false, 0 }, | |
| 1204 { "Thu, 12-Aug-31841 20:49:07 GMT", false, 0 }, | |
| 1205 { "Thu, 12-Aug-9999999999 20:49:07 GMT", false, 0 }, | |
| 1206 { "Thu, 999999999999-Aug-2007 20:49:07 GMT", false, 0 }, | |
| 1207 { "Thu, 12-Aug-2007 20:61:99999999999 GMT", false, 0 }, | |
| 1208 { "IAintNoDateFool", false, 0 }, | |
| 1209 }; | |
| 1210 | |
| 1211 Time parsed_time; | |
| 1212 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) { | |
| 1213 parsed_time = CookieMonster::ParseCookieTime(tests[i].str); | |
| 1214 if (!tests[i].valid) { | |
| 1215 EXPECT_FALSE(!parsed_time.is_null()) << tests[i].str; | |
| 1216 continue; | |
| 1217 } | |
| 1218 EXPECT_TRUE(!parsed_time.is_null()) << tests[i].str; | |
| 1219 EXPECT_EQ(tests[i].epoch, parsed_time.ToTimeT()) << tests[i].str; | |
| 1220 } | |
| 1221 } | |
| 1222 | |
| 1223 TEST_F(CookieMonsterTest, TestCookieDeleteAll) { | |
| 1224 scoped_refptr<MockPersistentCookieStore> store( | |
| 1225 new MockPersistentCookieStore); | |
| 1226 scoped_refptr<CookieMonster> cm(new CookieMonster(store, NULL)); | |
| 1227 CookieOptions options; | |
| 1228 options.set_include_httponly(); | |
| 1229 | |
| 1230 EXPECT_TRUE(SetCookie(cm, url_google_, kValidCookieLine)); | |
| 1231 EXPECT_EQ("A=B", GetCookies(cm, url_google_)); | |
| 1232 | |
| 1233 EXPECT_TRUE(SetCookieWithOptions(cm, url_google_, "C=D; httponly", options)); | |
| 1234 EXPECT_EQ("A=B; C=D", GetCookiesWithOptions(cm, url_google_, options)); | |
| 1235 | |
| 1236 EXPECT_EQ(2, DeleteAll(cm)); | |
| 1237 EXPECT_EQ("", GetCookiesWithOptions(cm, url_google_, options)); | |
| 1238 | |
| 1239 EXPECT_EQ(0u, store->commands().size()); | |
| 1240 | |
| 1241 // Create a persistent cookie. | |
| 1242 EXPECT_TRUE(SetCookie(cm, url_google_, | |
| 1243 std::string(kValidCookieLine) + | |
| 1244 "; expires=Mon, 18-Apr-22 22:50:13 GMT")); | |
| 1245 ASSERT_EQ(1u, store->commands().size()); | |
| 1246 EXPECT_EQ(CookieStoreCommand::ADD, store->commands()[0].type); | |
| 1247 | |
| 1248 EXPECT_EQ(1, DeleteAll(cm)); // sync_to_store = true. | |
| 1249 ASSERT_EQ(2u, store->commands().size()); | |
| 1250 EXPECT_EQ(CookieStoreCommand::REMOVE, store->commands()[1].type); | |
| 1251 | |
| 1252 EXPECT_EQ("", GetCookiesWithOptions(cm, url_google_, options)); | |
| 1253 } | |
| 1254 | |
| 1255 TEST_F(CookieMonsterTest, TestCookieDeleteAllCreatedBetweenTimestamps) { | |
| 1256 scoped_refptr<CookieMonster> cm(new CookieMonster(NULL, NULL)); | |
| 1257 Time now = Time::Now(); | |
| 1258 | |
| 1259 // Nothing has been added so nothing should be deleted. | |
| 1260 EXPECT_EQ(0, DeleteAllCreatedBetween(cm, now - TimeDelta::FromDays(99), | |
| 1261 Time())); | |
| 1262 | |
| 1263 // Create 3 cookies with creation date of today, yesterday and the day before. | |
| 1264 EXPECT_TRUE(cm->SetCookieWithCreationTime(url_google_, "T-0=Now", now)); | |
| 1265 EXPECT_TRUE(cm->SetCookieWithCreationTime(url_google_, "T-1=Yesterday", | |
| 1266 now - TimeDelta::FromDays(1))); | |
| 1267 EXPECT_TRUE(cm->SetCookieWithCreationTime(url_google_, "T-2=DayBefore", | |
| 1268 now - TimeDelta::FromDays(2))); | |
| 1269 EXPECT_TRUE(cm->SetCookieWithCreationTime(url_google_, "T-3=ThreeDays", | |
| 1270 now - TimeDelta::FromDays(3))); | |
| 1271 EXPECT_TRUE(cm->SetCookieWithCreationTime(url_google_, "T-7=LastWeek", | |
| 1272 now - TimeDelta::FromDays(7))); | |
| 1273 | |
| 1274 // Try to delete threedays and the daybefore. | |
| 1275 EXPECT_EQ(2, DeleteAllCreatedBetween(cm, now - TimeDelta::FromDays(3), | |
| 1276 now - TimeDelta::FromDays(1))); | |
| 1277 | |
| 1278 // Try to delete yesterday, also make sure that delete_end is not | |
| 1279 // inclusive. | |
| 1280 EXPECT_EQ(1, DeleteAllCreatedBetween(cm, now - TimeDelta::FromDays(2), | |
| 1281 now)); | |
| 1282 | |
| 1283 // Make sure the delete_begin is inclusive. | |
| 1284 EXPECT_EQ(1, DeleteAllCreatedBetween(cm, now - TimeDelta::FromDays(7), | |
| 1285 now)); | |
| 1286 | |
| 1287 // Delete the last (now) item. | |
| 1288 EXPECT_EQ(1, DeleteAllCreatedBetween(cm, Time(), Time())); | |
| 1289 | |
| 1290 // Really make sure everything is gone. | |
| 1291 EXPECT_EQ(0, DeleteAll(cm)); | |
| 1292 } | |
| 1293 | |
| 1294 static const int kAccessDelayMs = kLastAccessThresholdMilliseconds + 20; | |
| 1295 | |
| 1296 TEST_F(CookieMonsterTest, TestLastAccess) { | |
| 1297 scoped_refptr<CookieMonster> cm( | |
| 1298 new CookieMonster(NULL, NULL, kLastAccessThresholdMilliseconds)); | |
| 1299 | |
| 1300 EXPECT_TRUE(SetCookie(cm, url_google_, "A=B")); | |
| 1301 const Time last_access_date(GetFirstCookieAccessDate(cm)); | |
| 1302 | |
| 1303 // Reading the cookie again immediately shouldn't update the access date, | |
| 1304 // since we're inside the threshold. | |
| 1305 EXPECT_EQ("A=B", GetCookies(cm, url_google_)); | |
| 1306 EXPECT_TRUE(last_access_date == GetFirstCookieAccessDate(cm)); | |
| 1307 | |
| 1308 // Reading after a short wait should update the access date. | |
| 1309 base::PlatformThread::Sleep( | |
| 1310 base::TimeDelta::FromMilliseconds(kAccessDelayMs)); | |
| 1311 EXPECT_EQ("A=B", GetCookies(cm, url_google_)); | |
| 1312 EXPECT_FALSE(last_access_date == GetFirstCookieAccessDate(cm)); | |
| 1313 } | |
| 1314 | |
| 1315 TEST_F(CookieMonsterTest, TestHostGarbageCollection) { | |
| 1316 TestHostGarbageCollectHelper( | |
| 1317 CookieMonster::kDomainMaxCookies, CookieMonster::kDomainPurgeCookies); | |
| 1318 } | |
| 1319 | |
| 1320 TEST_F(CookieMonsterTest, TestDeleteSingleCookie) { | |
| 1321 scoped_refptr<CookieMonster> cm(new CookieMonster(NULL, NULL)); | |
| 1322 | |
| 1323 EXPECT_TRUE(SetCookie(cm, url_google_, "A=B")); | |
| 1324 EXPECT_TRUE(SetCookie(cm, url_google_, "C=D")); | |
| 1325 EXPECT_TRUE(SetCookie(cm, url_google_, "E=F")); | |
| 1326 EXPECT_EQ("A=B; C=D; E=F", GetCookies(cm, url_google_)); | |
| 1327 | |
| 1328 EXPECT_TRUE(FindAndDeleteCookie(cm, url_google_.host(), "C")); | |
| 1329 EXPECT_EQ("A=B; E=F", GetCookies(cm, url_google_)); | |
| 1330 | |
| 1331 EXPECT_FALSE(FindAndDeleteCookie(cm, "random.host", "E")); | |
| 1332 EXPECT_EQ("A=B; E=F", GetCookies(cm, url_google_)); | |
| 1333 } | |
| 1334 | |
| 1335 TEST_F(CookieMonsterTest, SetCookieableSchemes) { | |
| 1336 scoped_refptr<CookieMonster> cm(new CookieMonster(NULL, NULL)); | |
| 1337 scoped_refptr<CookieMonster> cm_foo(new CookieMonster(NULL, NULL)); | |
| 1338 | |
| 1339 // Only cm_foo should allow foo:// cookies. | |
| 1340 const char* kSchemes[] = {"foo"}; | |
| 1341 cm_foo->SetCookieableSchemes(kSchemes, 1); | |
| 1342 | |
| 1343 GURL foo_url("foo://host/path"); | |
| 1344 GURL http_url("http://host/path"); | |
| 1345 | |
| 1346 EXPECT_TRUE(SetCookie(cm, http_url, "x=1")); | |
| 1347 EXPECT_FALSE(SetCookie(cm, foo_url, "x=1")); | |
| 1348 EXPECT_TRUE(SetCookie(cm_foo, foo_url, "x=1")); | |
| 1349 EXPECT_FALSE(SetCookie(cm_foo, http_url, "x=1")); | |
| 1350 } | |
| 1351 | |
| 1352 TEST_F(CookieMonsterTest, GetAllCookiesForURL) { | |
| 1353 scoped_refptr<CookieMonster> cm( | |
| 1354 new CookieMonster(NULL, NULL, kLastAccessThresholdMilliseconds)); | |
| 1355 | |
| 1356 // Create an httponly cookie. | |
| 1357 CookieOptions options; | |
| 1358 options.set_include_httponly(); | |
| 1359 | |
| 1360 EXPECT_TRUE(SetCookieWithOptions(cm, url_google_, "A=B; httponly", options)); | |
| 1361 EXPECT_TRUE(SetCookieWithOptions(cm, url_google_, | |
| 1362 "C=D; domain=.google.izzle", | |
| 1363 options)); | |
| 1364 EXPECT_TRUE(SetCookieWithOptions(cm, url_google_secure_, | |
| 1365 "E=F; domain=.google.izzle; secure", | |
| 1366 options)); | |
| 1367 | |
| 1368 const Time last_access_date(GetFirstCookieAccessDate(cm)); | |
| 1369 | |
| 1370 base::PlatformThread::Sleep( | |
| 1371 base::TimeDelta::FromMilliseconds(kAccessDelayMs)); | |
| 1372 | |
| 1373 // Check cookies for url. | |
| 1374 CookieList cookies = GetAllCookiesForURL(cm, url_google_); | |
| 1375 CookieList::iterator it = cookies.begin(); | |
| 1376 | |
| 1377 ASSERT_TRUE(it != cookies.end()); | |
| 1378 EXPECT_EQ("www.google.izzle", it->Domain()); | |
| 1379 EXPECT_EQ("A", it->Name()); | |
| 1380 | |
| 1381 ASSERT_TRUE(++it != cookies.end()); | |
| 1382 EXPECT_EQ(".google.izzle", it->Domain()); | |
| 1383 EXPECT_EQ("C", it->Name()); | |
| 1384 | |
| 1385 ASSERT_TRUE(++it == cookies.end()); | |
| 1386 | |
| 1387 // Check cookies for url excluding http-only cookies. | |
| 1388 cookies = | |
| 1389 GetAllCookiesForURLWithOptions(cm, url_google_, CookieOptions()); | |
| 1390 it = cookies.begin(); | |
| 1391 | |
| 1392 ASSERT_TRUE(it != cookies.end()); | |
| 1393 EXPECT_EQ(".google.izzle", it->Domain()); | |
| 1394 EXPECT_EQ("C", it->Name()); | |
| 1395 | |
| 1396 ASSERT_TRUE(++it == cookies.end()); | |
| 1397 | |
| 1398 // Test secure cookies. | |
| 1399 cookies = GetAllCookiesForURL(cm, url_google_secure_); | |
| 1400 it = cookies.begin(); | |
| 1401 | |
| 1402 ASSERT_TRUE(it != cookies.end()); | |
| 1403 EXPECT_EQ("www.google.izzle", it->Domain()); | |
| 1404 EXPECT_EQ("A", it->Name()); | |
| 1405 | |
| 1406 ASSERT_TRUE(++it != cookies.end()); | |
| 1407 EXPECT_EQ(".google.izzle", it->Domain()); | |
| 1408 EXPECT_EQ("C", it->Name()); | |
| 1409 | |
| 1410 ASSERT_TRUE(++it != cookies.end()); | |
| 1411 EXPECT_EQ(".google.izzle", it->Domain()); | |
| 1412 EXPECT_EQ("E", it->Name()); | |
| 1413 | |
| 1414 ASSERT_TRUE(++it == cookies.end()); | |
| 1415 | |
| 1416 // Reading after a short wait should not update the access date. | |
| 1417 EXPECT_TRUE(last_access_date == GetFirstCookieAccessDate(cm)); | |
| 1418 } | |
| 1419 | |
| 1420 TEST_F(CookieMonsterTest, GetAllCookiesForURLPathMatching) { | |
| 1421 scoped_refptr<CookieMonster> cm(new CookieMonster(NULL, NULL)); | |
| 1422 CookieOptions options; | |
| 1423 | |
| 1424 EXPECT_TRUE(SetCookieWithOptions(cm, url_google_foo_, | |
| 1425 "A=B; path=/foo;", options)); | |
| 1426 EXPECT_TRUE(SetCookieWithOptions(cm, url_google_bar_, | |
| 1427 "C=D; path=/bar;", options)); | |
| 1428 EXPECT_TRUE(SetCookieWithOptions(cm, url_google_, | |
| 1429 "E=F;", options)); | |
| 1430 | |
| 1431 CookieList cookies = GetAllCookiesForURL(cm, url_google_foo_); | |
| 1432 CookieList::iterator it = cookies.begin(); | |
| 1433 | |
| 1434 ASSERT_TRUE(it != cookies.end()); | |
| 1435 EXPECT_EQ("A", it->Name()); | |
| 1436 EXPECT_EQ("/foo", it->Path()); | |
| 1437 | |
| 1438 ASSERT_TRUE(++it != cookies.end()); | |
| 1439 EXPECT_EQ("E", it->Name()); | |
| 1440 EXPECT_EQ("/", it->Path()); | |
| 1441 | |
| 1442 ASSERT_TRUE(++it == cookies.end()); | |
| 1443 | |
| 1444 cookies = GetAllCookiesForURL(cm, url_google_bar_); | |
| 1445 it = cookies.begin(); | |
| 1446 | |
| 1447 ASSERT_TRUE(it != cookies.end()); | |
| 1448 EXPECT_EQ("C", it->Name()); | |
| 1449 EXPECT_EQ("/bar", it->Path()); | |
| 1450 | |
| 1451 ASSERT_TRUE(++it != cookies.end()); | |
| 1452 EXPECT_EQ("E", it->Name()); | |
| 1453 EXPECT_EQ("/", it->Path()); | |
| 1454 | |
| 1455 ASSERT_TRUE(++it == cookies.end()); | |
| 1456 } | |
| 1457 | |
| 1458 TEST_F(CookieMonsterTest, DeleteCookieByName) { | |
| 1459 scoped_refptr<CookieMonster> cm(new CookieMonster(NULL, NULL)); | |
| 1460 | |
| 1461 EXPECT_TRUE(SetCookie(cm, url_google_, "A=A1; path=/")); | |
| 1462 EXPECT_TRUE(SetCookie(cm, url_google_, "A=A2; path=/foo")); | |
| 1463 EXPECT_TRUE(SetCookie(cm, url_google_, "A=A3; path=/bar")); | |
| 1464 EXPECT_TRUE(SetCookie(cm, url_google_, "B=B1; path=/")); | |
| 1465 EXPECT_TRUE(SetCookie(cm, url_google_, "B=B2; path=/foo")); | |
| 1466 EXPECT_TRUE(SetCookie(cm, url_google_, "B=B3; path=/bar")); | |
| 1467 | |
| 1468 DeleteCookie(cm, GURL(std::string(kUrlGoogle) + "/foo/bar"), "A"); | |
| 1469 | |
| 1470 CookieList cookies = GetAllCookies(cm); | |
| 1471 size_t expected_size = 4; | |
| 1472 EXPECT_EQ(expected_size, cookies.size()); | |
| 1473 for (CookieList::iterator it = cookies.begin(); | |
| 1474 it != cookies.end(); ++it) { | |
| 1475 EXPECT_NE("A1", it->Value()); | |
| 1476 EXPECT_NE("A2", it->Value()); | |
| 1477 } | |
| 1478 } | |
| 1479 | |
| 1480 TEST_F(CookieMonsterTest, InitializeFromCookieMonster) { | |
| 1481 scoped_refptr<CookieMonster> cm_1(new CookieMonster(NULL, NULL)); | |
| 1482 CookieOptions options; | |
| 1483 | |
| 1484 EXPECT_TRUE(SetCookieWithOptions(cm_1.get(), url_google_foo_, | |
| 1485 "A1=B; path=/foo;", | |
| 1486 options)); | |
| 1487 EXPECT_TRUE(SetCookieWithOptions(cm_1.get(), url_google_bar_, | |
| 1488 "A2=D; path=/bar;", | |
| 1489 options)); | |
| 1490 EXPECT_TRUE(SetCookieWithOptions(cm_1.get(), url_google_, | |
| 1491 "A3=F;", | |
| 1492 options)); | |
| 1493 | |
| 1494 CookieList cookies_1 = GetAllCookies(cm_1); | |
| 1495 scoped_refptr<CookieMonster> cm_2(new CookieMonster(NULL, NULL)); | |
| 1496 ASSERT_TRUE(cm_2->InitializeFrom(cookies_1)); | |
| 1497 CookieList cookies_2 = GetAllCookies(cm_2); | |
| 1498 | |
| 1499 size_t expected_size = 3; | |
| 1500 EXPECT_EQ(expected_size, cookies_2.size()); | |
| 1501 | |
| 1502 CookieList::iterator it = cookies_2.begin(); | |
| 1503 | |
| 1504 ASSERT_TRUE(it != cookies_2.end()); | |
| 1505 EXPECT_EQ("A1", it->Name()); | |
| 1506 EXPECT_EQ("/foo", it->Path()); | |
| 1507 | |
| 1508 ASSERT_TRUE(++it != cookies_2.end()); | |
| 1509 EXPECT_EQ("A2", it->Name()); | |
| 1510 EXPECT_EQ("/bar", it->Path()); | |
| 1511 | |
| 1512 ASSERT_TRUE(++it != cookies_2.end()); | |
| 1513 EXPECT_EQ("A3", it->Name()); | |
| 1514 EXPECT_EQ("/", it->Path()); | |
| 1515 } | |
| 1516 | |
| 1517 // Tests importing from a persistent cookie store that contains duplicate | |
| 1518 // equivalent cookies. This situation should be handled by removing the | |
| 1519 // duplicate cookie (both from the in-memory cache, and from the backing store). | |
| 1520 // | |
| 1521 // This is a regression test for: http://crbug.com/17855. | |
| 1522 TEST_F(CookieMonsterTest, DontImportDuplicateCookies) { | |
| 1523 scoped_refptr<MockPersistentCookieStore> store( | |
| 1524 new MockPersistentCookieStore); | |
| 1525 | |
| 1526 // We will fill some initial cookies into the PersistentCookieStore, | |
| 1527 // to simulate a database with 4 duplicates. Note that we need to | |
| 1528 // be careful not to have any duplicate creation times at all (as it's a | |
| 1529 // violation of a CookieMonster invariant) even if Time::Now() doesn't | |
| 1530 // move between calls. | |
| 1531 std::vector<CookieMonster::CanonicalCookie*> initial_cookies; | |
| 1532 | |
| 1533 // Insert 4 cookies with name "X" on path "/", with varying creation | |
| 1534 // dates. We expect only the most recent one to be preserved following | |
| 1535 // the import. | |
| 1536 | |
| 1537 AddCookieToList("www.google.com", | |
| 1538 "X=1; path=/; expires=Mon, 18-Apr-22 22:50:14 GMT", | |
| 1539 Time::Now() + TimeDelta::FromDays(3), | |
| 1540 &initial_cookies); | |
| 1541 | |
| 1542 AddCookieToList("www.google.com", | |
| 1543 "X=2; path=/; expires=Mon, 18-Apr-22 22:50:14 GMT", | |
| 1544 Time::Now() + TimeDelta::FromDays(1), | |
| 1545 &initial_cookies); | |
| 1546 | |
| 1547 // ===> This one is the WINNER (biggest creation time). <==== | |
| 1548 AddCookieToList("www.google.com", | |
| 1549 "X=3; path=/; expires=Mon, 18-Apr-22 22:50:14 GMT", | |
| 1550 Time::Now() + TimeDelta::FromDays(4), | |
| 1551 &initial_cookies); | |
| 1552 | |
| 1553 AddCookieToList("www.google.com", | |
| 1554 "X=4; path=/; expires=Mon, 18-Apr-22 22:50:14 GMT", | |
| 1555 Time::Now(), | |
| 1556 &initial_cookies); | |
| 1557 | |
| 1558 // Insert 2 cookies with name "X" on path "/2", with varying creation | |
| 1559 // dates. We expect only the most recent one to be preserved the import. | |
| 1560 | |
| 1561 // ===> This one is the WINNER (biggest creation time). <==== | |
| 1562 AddCookieToList("www.google.com", | |
| 1563 "X=a1; path=/2; expires=Mon, 18-Apr-22 22:50:14 GMT", | |
| 1564 Time::Now() + TimeDelta::FromDays(9), | |
| 1565 &initial_cookies); | |
| 1566 | |
| 1567 AddCookieToList("www.google.com", | |
| 1568 "X=a2; path=/2; expires=Mon, 18-Apr-22 22:50:14 GMT", | |
| 1569 Time::Now() + TimeDelta::FromDays(2), | |
| 1570 &initial_cookies); | |
| 1571 | |
| 1572 // Insert 1 cookie with name "Y" on path "/". | |
| 1573 AddCookieToList("www.google.com", | |
| 1574 "Y=a; path=/; expires=Mon, 18-Apr-22 22:50:14 GMT", | |
| 1575 Time::Now() + TimeDelta::FromDays(10), | |
| 1576 &initial_cookies); | |
| 1577 | |
| 1578 // Inject our initial cookies into the mock PersistentCookieStore. | |
| 1579 store->SetLoadExpectation(true, initial_cookies); | |
| 1580 | |
| 1581 scoped_refptr<CookieMonster> cm(new CookieMonster(store, NULL)); | |
| 1582 | |
| 1583 // Verify that duplicates were not imported for path "/". | |
| 1584 // (If this had failed, GetCookies() would have also returned X=1, X=2, X=4). | |
| 1585 EXPECT_EQ("X=3; Y=a", GetCookies(cm, GURL("http://www.google.com/"))); | |
| 1586 | |
| 1587 // Verify that same-named cookie on a different path ("/x2") didn't get | |
| 1588 // messed up. | |
| 1589 EXPECT_EQ("X=a1; X=3; Y=a", | |
| 1590 GetCookies(cm, GURL("http://www.google.com/2/x"))); | |
| 1591 | |
| 1592 // Verify that the PersistentCookieStore was told to kill its 4 duplicates. | |
| 1593 ASSERT_EQ(4u, store->commands().size()); | |
| 1594 EXPECT_EQ(CookieStoreCommand::REMOVE, store->commands()[0].type); | |
| 1595 EXPECT_EQ(CookieStoreCommand::REMOVE, store->commands()[1].type); | |
| 1596 EXPECT_EQ(CookieStoreCommand::REMOVE, store->commands()[2].type); | |
| 1597 EXPECT_EQ(CookieStoreCommand::REMOVE, store->commands()[3].type); | |
| 1598 } | |
| 1599 | |
| 1600 // Tests importing from a persistent cookie store that contains cookies | |
| 1601 // with duplicate creation times. This situation should be handled by | |
| 1602 // dropping the cookies before insertion/visibility to user. | |
| 1603 // | |
| 1604 // This is a regression test for: http://crbug.com/43188. | |
| 1605 TEST_F(CookieMonsterTest, DontImportDuplicateCreationTimes) { | |
| 1606 scoped_refptr<MockPersistentCookieStore> store( | |
| 1607 new MockPersistentCookieStore); | |
| 1608 | |
| 1609 Time now(Time::Now()); | |
| 1610 Time earlier(now - TimeDelta::FromDays(1)); | |
| 1611 | |
| 1612 // Insert 8 cookies, four with the current time as creation times, and | |
| 1613 // four with the earlier time as creation times. We should only get | |
| 1614 // two cookies remaining, but which two (other than that there should | |
| 1615 // be one from each set) will be random. | |
| 1616 std::vector<CookieMonster::CanonicalCookie*> initial_cookies; | |
| 1617 AddCookieToList("www.google.com", "X=1; path=/", now, &initial_cookies); | |
| 1618 AddCookieToList("www.google.com", "X=2; path=/", now, &initial_cookies); | |
| 1619 AddCookieToList("www.google.com", "X=3; path=/", now, &initial_cookies); | |
| 1620 AddCookieToList("www.google.com", "X=4; path=/", now, &initial_cookies); | |
| 1621 | |
| 1622 AddCookieToList("www.google.com", "Y=1; path=/", earlier, &initial_cookies); | |
| 1623 AddCookieToList("www.google.com", "Y=2; path=/", earlier, &initial_cookies); | |
| 1624 AddCookieToList("www.google.com", "Y=3; path=/", earlier, &initial_cookies); | |
| 1625 AddCookieToList("www.google.com", "Y=4; path=/", earlier, &initial_cookies); | |
| 1626 | |
| 1627 // Inject our initial cookies into the mock PersistentCookieStore. | |
| 1628 store->SetLoadExpectation(true, initial_cookies); | |
| 1629 | |
| 1630 scoped_refptr<CookieMonster> cm(new CookieMonster(store, NULL)); | |
| 1631 | |
| 1632 CookieList list(GetAllCookies(cm)); | |
| 1633 EXPECT_EQ(2U, list.size()); | |
| 1634 // Confirm that we have one of each. | |
| 1635 std::string name1(list[0].Name()); | |
| 1636 std::string name2(list[1].Name()); | |
| 1637 EXPECT_TRUE(name1 == "X" || name2 == "X"); | |
| 1638 EXPECT_TRUE(name1 == "Y" || name2 == "Y"); | |
| 1639 EXPECT_NE(name1, name2); | |
| 1640 } | |
| 1641 | |
| 1642 TEST_F(CookieMonsterTest, Delegate) { | |
| 1643 scoped_refptr<MockPersistentCookieStore> store( | |
| 1644 new MockPersistentCookieStore); | |
| 1645 scoped_refptr<MockCookieMonsterDelegate> delegate( | |
| 1646 new MockCookieMonsterDelegate); | |
| 1647 scoped_refptr<CookieMonster> cm(new CookieMonster(store, delegate)); | |
| 1648 | |
| 1649 EXPECT_TRUE(SetCookie(cm, url_google_, "A=B")); | |
| 1650 EXPECT_TRUE(SetCookie(cm, url_google_, "C=D")); | |
| 1651 EXPECT_TRUE(SetCookie(cm, url_google_, "E=F")); | |
| 1652 EXPECT_EQ("A=B; C=D; E=F", GetCookies(cm, url_google_)); | |
| 1653 ASSERT_EQ(3u, delegate->changes().size()); | |
| 1654 EXPECT_FALSE(delegate->changes()[0].second); | |
| 1655 EXPECT_EQ(url_google_.host(), delegate->changes()[0].first.Domain()); | |
| 1656 EXPECT_EQ("A", delegate->changes()[0].first.Name()); | |
| 1657 EXPECT_EQ("B", delegate->changes()[0].first.Value()); | |
| 1658 EXPECT_EQ(url_google_.host(), delegate->changes()[1].first.Domain()); | |
| 1659 EXPECT_FALSE(delegate->changes()[1].second); | |
| 1660 EXPECT_EQ("C", delegate->changes()[1].first.Name()); | |
| 1661 EXPECT_EQ("D", delegate->changes()[1].first.Value()); | |
| 1662 EXPECT_EQ(url_google_.host(), delegate->changes()[2].first.Domain()); | |
| 1663 EXPECT_FALSE(delegate->changes()[2].second); | |
| 1664 EXPECT_EQ("E", delegate->changes()[2].first.Name()); | |
| 1665 EXPECT_EQ("F", delegate->changes()[2].first.Value()); | |
| 1666 delegate->reset(); | |
| 1667 | |
| 1668 EXPECT_TRUE(FindAndDeleteCookie(cm, url_google_.host(), "C")); | |
| 1669 EXPECT_EQ("A=B; E=F", GetCookies(cm, url_google_)); | |
| 1670 ASSERT_EQ(1u, delegate->changes().size()); | |
| 1671 EXPECT_EQ(url_google_.host(), delegate->changes()[0].first.Domain()); | |
| 1672 EXPECT_TRUE(delegate->changes()[0].second); | |
| 1673 EXPECT_EQ("C", delegate->changes()[0].first.Name()); | |
| 1674 EXPECT_EQ("D", delegate->changes()[0].first.Value()); | |
| 1675 delegate->reset(); | |
| 1676 | |
| 1677 EXPECT_FALSE(FindAndDeleteCookie(cm, "random.host", "E")); | |
| 1678 EXPECT_EQ("A=B; E=F", GetCookies(cm, url_google_)); | |
| 1679 EXPECT_EQ(0u, delegate->changes().size()); | |
| 1680 | |
| 1681 // Insert a cookie "a" for path "/path1" | |
| 1682 EXPECT_TRUE( | |
| 1683 SetCookie(cm, url_google_, "a=val1; path=/path1; " | |
| 1684 "expires=Mon, 18-Apr-22 22:50:13 GMT")); | |
| 1685 ASSERT_EQ(1u, store->commands().size()); | |
| 1686 EXPECT_EQ(CookieStoreCommand::ADD, store->commands()[0].type); | |
| 1687 ASSERT_EQ(1u, delegate->changes().size()); | |
| 1688 EXPECT_FALSE(delegate->changes()[0].second); | |
| 1689 EXPECT_EQ(url_google_.host(), delegate->changes()[0].first.Domain()); | |
| 1690 EXPECT_EQ("a", delegate->changes()[0].first.Name()); | |
| 1691 EXPECT_EQ("val1", delegate->changes()[0].first.Value()); | |
| 1692 delegate->reset(); | |
| 1693 | |
| 1694 // Insert a cookie "a" for path "/path1", that is httponly. This should | |
| 1695 // overwrite the non-http-only version. | |
| 1696 CookieOptions allow_httponly; | |
| 1697 allow_httponly.set_include_httponly(); | |
| 1698 EXPECT_TRUE( | |
| 1699 SetCookieWithOptions(cm, url_google_, | |
| 1700 "a=val2; path=/path1; httponly; " | |
| 1701 "expires=Mon, 18-Apr-22 22:50:14 GMT", | |
| 1702 allow_httponly)); | |
| 1703 ASSERT_EQ(3u, store->commands().size()); | |
| 1704 EXPECT_EQ(CookieStoreCommand::REMOVE, store->commands()[1].type); | |
| 1705 EXPECT_EQ(CookieStoreCommand::ADD, store->commands()[2].type); | |
| 1706 ASSERT_EQ(2u, delegate->changes().size()); | |
| 1707 EXPECT_EQ(url_google_.host(), delegate->changes()[0].first.Domain()); | |
| 1708 EXPECT_TRUE(delegate->changes()[0].second); | |
| 1709 EXPECT_EQ("a", delegate->changes()[0].first.Name()); | |
| 1710 EXPECT_EQ("val1", delegate->changes()[0].first.Value()); | |
| 1711 EXPECT_EQ(url_google_.host(), delegate->changes()[1].first.Domain()); | |
| 1712 EXPECT_FALSE(delegate->changes()[1].second); | |
| 1713 EXPECT_EQ("a", delegate->changes()[1].first.Name()); | |
| 1714 EXPECT_EQ("val2", delegate->changes()[1].first.Value()); | |
| 1715 delegate->reset(); | |
| 1716 } | |
| 1717 | |
| 1718 TEST_F(CookieMonsterTest, SetCookieWithDetails) { | |
| 1719 scoped_refptr<CookieMonster> cm(new CookieMonster(NULL, NULL)); | |
| 1720 | |
| 1721 EXPECT_TRUE(SetCookieWithDetails( | |
| 1722 cm, url_google_foo_, "A", "B", std::string(), "/foo", base::Time(), | |
| 1723 false, false)); | |
| 1724 EXPECT_TRUE(SetCookieWithDetails( | |
| 1725 cm, url_google_bar_, "C", "D", "google.izzle", "/bar", base::Time(), | |
| 1726 false, true)); | |
| 1727 EXPECT_TRUE(SetCookieWithDetails( | |
| 1728 cm, url_google_, "E", "F", std::string(), std::string(), base::Time(), | |
| 1729 true, false)); | |
| 1730 | |
| 1731 // Test that malformed attributes fail to set the cookie. | |
| 1732 EXPECT_FALSE(SetCookieWithDetails( | |
| 1733 cm, url_google_foo_, " A", "B", std::string(), "/foo", base::Time(), | |
| 1734 false, false)); | |
| 1735 EXPECT_FALSE(SetCookieWithDetails( | |
| 1736 cm, url_google_foo_, "A;", "B", std::string(), "/foo", base::Time(), | |
| 1737 false, false)); | |
| 1738 EXPECT_FALSE(SetCookieWithDetails( | |
| 1739 cm, url_google_foo_, "A=", "B", std::string(), "/foo", base::Time(), | |
| 1740 false, false)); | |
| 1741 EXPECT_FALSE(SetCookieWithDetails( | |
| 1742 cm, url_google_foo_, "A", "B", "google.ozzzzzzle", "foo", base::Time(), | |
| 1743 false, false)); | |
| 1744 EXPECT_FALSE(SetCookieWithDetails( | |
| 1745 cm, url_google_foo_, "A=", "B", std::string(), "foo", base::Time(), | |
| 1746 false, false)); | |
| 1747 | |
| 1748 CookieList cookies = GetAllCookiesForURL(cm, url_google_foo_); | |
| 1749 CookieList::iterator it = cookies.begin(); | |
| 1750 | |
| 1751 ASSERT_TRUE(it != cookies.end()); | |
| 1752 EXPECT_EQ("A", it->Name()); | |
| 1753 EXPECT_EQ("B", it->Value()); | |
| 1754 EXPECT_EQ("www.google.izzle", it->Domain()); | |
| 1755 EXPECT_EQ("/foo", it->Path()); | |
| 1756 EXPECT_FALSE(it->DoesExpire()); | |
| 1757 EXPECT_FALSE(it->IsSecure()); | |
| 1758 EXPECT_FALSE(it->IsHttpOnly()); | |
| 1759 | |
| 1760 ASSERT_TRUE(++it == cookies.end()); | |
| 1761 | |
| 1762 cookies = GetAllCookiesForURL(cm, url_google_bar_); | |
| 1763 it = cookies.begin(); | |
| 1764 | |
| 1765 ASSERT_TRUE(it != cookies.end()); | |
| 1766 EXPECT_EQ("C", it->Name()); | |
| 1767 EXPECT_EQ("D", it->Value()); | |
| 1768 EXPECT_EQ(".google.izzle", it->Domain()); | |
| 1769 EXPECT_EQ("/bar", it->Path()); | |
| 1770 EXPECT_FALSE(it->IsSecure()); | |
| 1771 EXPECT_TRUE(it->IsHttpOnly()); | |
| 1772 | |
| 1773 ASSERT_TRUE(++it == cookies.end()); | |
| 1774 | |
| 1775 cookies = GetAllCookiesForURL(cm, url_google_secure_); | |
| 1776 it = cookies.begin(); | |
| 1777 | |
| 1778 ASSERT_TRUE(it != cookies.end()); | |
| 1779 EXPECT_EQ("E", it->Name()); | |
| 1780 EXPECT_EQ("F", it->Value()); | |
| 1781 EXPECT_EQ("/", it->Path()); | |
| 1782 EXPECT_EQ("www.google.izzle", it->Domain()); | |
| 1783 EXPECT_TRUE(it->IsSecure()); | |
| 1784 EXPECT_FALSE(it->IsHttpOnly()); | |
| 1785 | |
| 1786 ASSERT_TRUE(++it == cookies.end()); | |
| 1787 } | |
| 1788 | |
| 1789 TEST_F(CookieMonsterTest, DeleteAllForHost) { | |
| 1790 scoped_refptr<CookieMonster> cm(new CookieMonster(NULL, NULL)); | |
| 1791 | |
| 1792 // Test probes: | |
| 1793 // * Non-secure URL, mid-level (http://w.c.b.a) | |
| 1794 // * Secure URL, mid-level (https://w.c.b.a) | |
| 1795 // * URL with path, mid-level (https:/w.c.b.a/dir1/xx) | |
| 1796 // All three tests should nuke only the midlevel host cookie, | |
| 1797 // the http_only cookie, the host secure cookie, and the two host | |
| 1798 // path cookies. http_only, secure, and paths are ignored by | |
| 1799 // this call, and domain cookies arent touched. | |
| 1800 PopulateCmForDeleteAllForHost(cm); | |
| 1801 EXPECT_EQ("dom_1=X; dom_2=X; dom_3=X; host_3=X", | |
| 1802 GetCookies(cm, GURL(kTopLevelDomainPlus3))); | |
| 1803 EXPECT_EQ("dom_1=X; dom_2=X; host_2=X; sec_dom=X; sec_host=X", | |
| 1804 GetCookies(cm, GURL(kTopLevelDomainPlus2Secure))); | |
| 1805 EXPECT_EQ("dom_1=X; host_1=X", GetCookies(cm, GURL(kTopLevelDomainPlus1))); | |
| 1806 EXPECT_EQ("dom_path_2=X; host_path_2=X; dom_path_1=X; host_path_1=X; " | |
| 1807 "dom_1=X; dom_2=X; host_2=X; sec_dom=X; sec_host=X", | |
| 1808 GetCookies(cm, GURL(kTopLevelDomainPlus2Secure + | |
| 1809 std::string("/dir1/dir2/xxx")))); | |
| 1810 | |
| 1811 EXPECT_EQ(5, DeleteAllForHost(cm, GURL(kTopLevelDomainPlus2))); | |
| 1812 EXPECT_EQ(8U, GetAllCookies(cm).size()); | |
| 1813 | |
| 1814 EXPECT_EQ("dom_1=X; dom_2=X; dom_3=X; host_3=X", | |
| 1815 GetCookies(cm, GURL(kTopLevelDomainPlus3))); | |
| 1816 EXPECT_EQ("dom_1=X; dom_2=X; sec_dom=X", | |
| 1817 GetCookies(cm, GURL(kTopLevelDomainPlus2Secure))); | |
| 1818 EXPECT_EQ("dom_1=X; host_1=X", GetCookies(cm, GURL(kTopLevelDomainPlus1))); | |
| 1819 EXPECT_EQ("dom_path_2=X; dom_path_1=X; dom_1=X; dom_2=X; sec_dom=X", | |
| 1820 GetCookies(cm, GURL(kTopLevelDomainPlus2Secure + | |
| 1821 std::string("/dir1/dir2/xxx")))); | |
| 1822 | |
| 1823 PopulateCmForDeleteAllForHost(cm); | |
| 1824 EXPECT_EQ(5, DeleteAllForHost(cm, GURL(kTopLevelDomainPlus2Secure))); | |
| 1825 EXPECT_EQ(8U, GetAllCookies(cm).size()); | |
| 1826 | |
| 1827 EXPECT_EQ("dom_1=X; dom_2=X; dom_3=X; host_3=X", | |
| 1828 GetCookies(cm, GURL(kTopLevelDomainPlus3))); | |
| 1829 EXPECT_EQ("dom_1=X; dom_2=X; sec_dom=X", | |
| 1830 GetCookies(cm, GURL(kTopLevelDomainPlus2Secure))); | |
| 1831 EXPECT_EQ("dom_1=X; host_1=X", GetCookies(cm, GURL(kTopLevelDomainPlus1))); | |
| 1832 EXPECT_EQ("dom_path_2=X; dom_path_1=X; dom_1=X; dom_2=X; sec_dom=X", | |
| 1833 GetCookies(cm, GURL(kTopLevelDomainPlus2Secure + | |
| 1834 std::string("/dir1/dir2/xxx")))); | |
| 1835 | |
| 1836 PopulateCmForDeleteAllForHost(cm); | |
| 1837 EXPECT_EQ(5, DeleteAllForHost(cm, GURL(kTopLevelDomainPlus2Secure + | |
| 1838 std::string("/dir1/xxx")))); | |
| 1839 EXPECT_EQ(8U, GetAllCookies(cm).size()); | |
| 1840 | |
| 1841 EXPECT_EQ("dom_1=X; dom_2=X; dom_3=X; host_3=X", | |
| 1842 GetCookies(cm, GURL(kTopLevelDomainPlus3))); | |
| 1843 EXPECT_EQ("dom_1=X; dom_2=X; sec_dom=X", | |
| 1844 GetCookies(cm, GURL(kTopLevelDomainPlus2Secure))); | |
| 1845 EXPECT_EQ("dom_1=X; host_1=X", GetCookies(cm, GURL(kTopLevelDomainPlus1))); | |
| 1846 EXPECT_EQ("dom_path_2=X; dom_path_1=X; dom_1=X; dom_2=X; sec_dom=X", | |
| 1847 GetCookies(cm, GURL(kTopLevelDomainPlus2Secure + | |
| 1848 std::string("/dir1/dir2/xxx")))); | |
| 1849 } | |
| 1850 | |
| 1851 TEST_F(CookieMonsterTest, UniqueCreationTime) { | |
| 1852 scoped_refptr<CookieMonster> cm(new CookieMonster(NULL, NULL)); | |
| 1853 CookieOptions options; | |
| 1854 | |
| 1855 // Add in three cookies through every public interface to the | |
| 1856 // CookieMonster and confirm that none of them have duplicate | |
| 1857 // creation times. | |
| 1858 | |
| 1859 // SetCookieWithCreationTime and SetCookieWithCreationTimeAndOptions | |
| 1860 // are not included as they aren't going to be public for very much | |
| 1861 // longer. | |
| 1862 | |
| 1863 // SetCookie, SetCookieWithOptions, SetCookieWithDetails | |
| 1864 | |
| 1865 SetCookie(cm, url_google_, "SetCookie1=A"); | |
| 1866 SetCookie(cm, url_google_, "SetCookie2=A"); | |
| 1867 SetCookie(cm, url_google_, "SetCookie3=A"); | |
| 1868 | |
| 1869 SetCookieWithOptions(cm, url_google_, "setCookieWithOptions1=A", options); | |
| 1870 SetCookieWithOptions(cm, url_google_, "setCookieWithOptions2=A", options); | |
| 1871 SetCookieWithOptions(cm, url_google_, "setCookieWithOptions3=A", options); | |
| 1872 | |
| 1873 SetCookieWithDetails(cm, url_google_, "setCookieWithDetails1", "A", | |
| 1874 ".google.com", "/", Time(), false, false); | |
| 1875 SetCookieWithDetails(cm, url_google_, "setCookieWithDetails2", "A", | |
| 1876 ".google.com", "/", Time(), false, false); | |
| 1877 SetCookieWithDetails(cm, url_google_, "setCookieWithDetails3", "A", | |
| 1878 ".google.com", "/", Time(), false, false); | |
| 1879 | |
| 1880 // Now we check | |
| 1881 CookieList cookie_list(GetAllCookies(cm)); | |
| 1882 typedef std::map<int64, CookieMonster::CanonicalCookie> TimeCookieMap; | |
| 1883 TimeCookieMap check_map; | |
| 1884 for (CookieList::const_iterator it = cookie_list.begin(); | |
| 1885 it != cookie_list.end(); it++) { | |
| 1886 const int64 creation_date = it->CreationDate().ToInternalValue(); | |
| 1887 TimeCookieMap::const_iterator | |
| 1888 existing_cookie_it(check_map.find(creation_date)); | |
| 1889 EXPECT_TRUE(existing_cookie_it == check_map.end()) | |
| 1890 << "Cookie " << it->Name() << " has same creation date (" | |
| 1891 << it->CreationDate().ToInternalValue() | |
| 1892 << ") as previously entered cookie " | |
| 1893 << existing_cookie_it->second.Name(); | |
| 1894 | |
| 1895 if (existing_cookie_it == check_map.end()) { | |
| 1896 check_map.insert(TimeCookieMap::value_type( | |
| 1897 it->CreationDate().ToInternalValue(), *it)); | |
| 1898 } | |
| 1899 } | |
| 1900 } | |
| 1901 | |
| 1902 // Mainly a test of GetEffectiveDomain, or more specifically, of the | |
| 1903 // expected behavior of GetEffectiveDomain within the CookieMonster. | |
| 1904 TEST_F(CookieMonsterTest, GetKey) { | |
| 1905 scoped_refptr<CookieMonster> cm(new CookieMonster(NULL, NULL)); | |
| 1906 | |
| 1907 // This test is really only interesting if GetKey() actually does something. | |
| 1908 EXPECT_EQ("google.com", cm->GetKey("www.google.com")); | |
| 1909 EXPECT_EQ("google.izzie", cm->GetKey("www.google.izzie")); | |
| 1910 EXPECT_EQ("google.izzie", cm->GetKey(".google.izzie")); | |
| 1911 EXPECT_EQ("bbc.co.uk", cm->GetKey("bbc.co.uk")); | |
| 1912 EXPECT_EQ("bbc.co.uk", cm->GetKey("a.b.c.d.bbc.co.uk")); | |
| 1913 EXPECT_EQ("apple.com", cm->GetKey("a.b.c.d.apple.com")); | |
| 1914 EXPECT_EQ("apple.izzie", cm->GetKey("a.b.c.d.apple.izzie")); | |
| 1915 | |
| 1916 // Cases where the effective domain is null, so we use the host | |
| 1917 // as the key. | |
| 1918 EXPECT_EQ("co.uk", cm->GetKey("co.uk")); | |
| 1919 const std::string extension_name("iehocdgbbocmkdidlbnnfbmbinnahbae"); | |
| 1920 EXPECT_EQ(extension_name, cm->GetKey(extension_name)); | |
| 1921 EXPECT_EQ("com", cm->GetKey("com")); | |
| 1922 EXPECT_EQ("hostalias", cm->GetKey("hostalias")); | |
| 1923 EXPECT_EQ("localhost", cm->GetKey("localhost")); | |
| 1924 } | |
| 1925 | |
| 1926 // Test that cookies transfer from/to the backing store correctly. | |
| 1927 TEST_F(CookieMonsterTest, BackingStoreCommunication) { | |
| 1928 // Store details for cookies transforming through the backing store interface. | |
| 1929 | |
| 1930 base::Time current(base::Time::Now()); | |
| 1931 scoped_refptr<MockSimplePersistentCookieStore> store( | |
| 1932 new MockSimplePersistentCookieStore); | |
| 1933 base::Time new_access_time; | |
| 1934 base::Time expires(base::Time::Now() + base::TimeDelta::FromSeconds(100)); | |
| 1935 | |
| 1936 struct CookiesInputInfo { | |
| 1937 std::string gurl; | |
| 1938 std::string name; | |
| 1939 std::string value; | |
| 1940 std::string domain; | |
| 1941 std::string path; | |
| 1942 base::Time expires; | |
| 1943 bool secure; | |
| 1944 bool http_only; | |
| 1945 }; | |
| 1946 const CookiesInputInfo input_info[] = { | |
| 1947 {"http://a.b.google.com", "a", "1", "", "/path/to/cookie", expires, | |
| 1948 false, false}, | |
| 1949 {"https://www.google.com", "b", "2", ".google.com", "/path/from/cookie", | |
| 1950 expires + TimeDelta::FromSeconds(10), true, true}, | |
| 1951 {"https://google.com", "c", "3", "", "/another/path/to/cookie", | |
| 1952 base::Time::Now() + base::TimeDelta::FromSeconds(100), | |
| 1953 true, false} | |
| 1954 }; | |
| 1955 const int INPUT_DELETE = 1; | |
| 1956 | |
| 1957 // Create new cookies and flush them to the store. | |
| 1958 { | |
| 1959 scoped_refptr<CookieMonster> cmout(new CookieMonster(store, NULL)); | |
| 1960 for (const CookiesInputInfo* p = input_info; | |
| 1961 p < &input_info[ARRAYSIZE_UNSAFE(input_info)]; p++) { | |
| 1962 EXPECT_TRUE(SetCookieWithDetails(cmout, GURL(p->gurl), p->name, p->value, | |
| 1963 p->domain, p->path, p->expires, | |
| 1964 p->secure, p->http_only)); | |
| 1965 } | |
| 1966 DeleteCookie(cmout, GURL(std::string(input_info[INPUT_DELETE].gurl) + | |
| 1967 input_info[INPUT_DELETE].path), | |
| 1968 input_info[INPUT_DELETE].name); | |
| 1969 } | |
| 1970 | |
| 1971 // Create a new cookie monster and make sure that everything is correct | |
| 1972 { | |
| 1973 scoped_refptr<CookieMonster> cmin(new CookieMonster(store, NULL)); | |
| 1974 CookieList cookies(GetAllCookies(cmin)); | |
| 1975 ASSERT_EQ(2u, cookies.size()); | |
| 1976 // Ordering is path length, then creation time. So second cookie | |
| 1977 // will come first, and we need to swap them. | |
| 1978 std::swap(cookies[0], cookies[1]); | |
| 1979 for (int output_index = 0; output_index < 2; output_index++) { | |
| 1980 int input_index = output_index * 2; | |
| 1981 const CookiesInputInfo* input = &input_info[input_index]; | |
| 1982 const CookieMonster::CanonicalCookie* output = &cookies[output_index]; | |
| 1983 | |
| 1984 EXPECT_EQ(input->name, output->Name()); | |
| 1985 EXPECT_EQ(input->value, output->Value()); | |
| 1986 EXPECT_EQ(GURL(input->gurl).host(), output->Domain()); | |
| 1987 EXPECT_EQ(input->path, output->Path()); | |
| 1988 EXPECT_LE(current.ToInternalValue(), | |
| 1989 output->CreationDate().ToInternalValue()); | |
| 1990 EXPECT_EQ(input->secure, output->IsSecure()); | |
| 1991 EXPECT_EQ(input->http_only, output->IsHttpOnly()); | |
| 1992 EXPECT_TRUE(output->IsPersistent()); | |
| 1993 EXPECT_EQ(input->expires.ToInternalValue(), | |
| 1994 output->ExpiryDate().ToInternalValue()); | |
| 1995 } | |
| 1996 } | |
| 1997 } | |
| 1998 | |
| 1999 TEST_F(CookieMonsterTest, CookieListOrdering) { | |
| 2000 // Put a random set of cookies into a monster and make sure | |
| 2001 // they're returned in the right order. | |
| 2002 scoped_refptr<CookieMonster> cm(new CookieMonster(NULL, NULL)); | |
| 2003 EXPECT_TRUE(SetCookie(cm, GURL("http://d.c.b.a.google.com/aa/x.html"), | |
| 2004 "c=1")); | |
| 2005 EXPECT_TRUE(SetCookie(cm, GURL("http://b.a.google.com/aa/bb/cc/x.html"), | |
| 2006 "d=1; domain=b.a.google.com")); | |
| 2007 EXPECT_TRUE(SetCookie(cm, GURL("http://b.a.google.com/aa/bb/cc/x.html"), | |
| 2008 "a=4; domain=b.a.google.com")); | |
| 2009 EXPECT_TRUE(SetCookie(cm, GURL("http://c.b.a.google.com/aa/bb/cc/x.html"), | |
| 2010 "e=1; domain=c.b.a.google.com")); | |
| 2011 EXPECT_TRUE(SetCookie(cm, GURL("http://d.c.b.a.google.com/aa/bb/x.html"), | |
| 2012 "b=1")); | |
| 2013 EXPECT_TRUE(SetCookie(cm, GURL("http://news.bbc.co.uk/midpath/x.html"), | |
| 2014 "g=10")); | |
| 2015 { | |
| 2016 unsigned int i = 0; | |
| 2017 CookieList cookies(GetAllCookiesForURL( | |
| 2018 cm, GURL("http://d.c.b.a.google.com/aa/bb/cc/dd"))); | |
| 2019 ASSERT_EQ(5u, cookies.size()); | |
| 2020 EXPECT_EQ("d", cookies[i++].Name()); | |
| 2021 EXPECT_EQ("a", cookies[i++].Name()); | |
| 2022 EXPECT_EQ("e", cookies[i++].Name()); | |
| 2023 EXPECT_EQ("b", cookies[i++].Name()); | |
| 2024 EXPECT_EQ("c", cookies[i++].Name()); | |
| 2025 } | |
| 2026 | |
| 2027 { | |
| 2028 unsigned int i = 0; | |
| 2029 CookieList cookies(GetAllCookies(cm)); | |
| 2030 ASSERT_EQ(6u, cookies.size()); | |
| 2031 EXPECT_EQ("d", cookies[i++].Name()); | |
| 2032 EXPECT_EQ("a", cookies[i++].Name()); | |
| 2033 EXPECT_EQ("e", cookies[i++].Name()); | |
| 2034 EXPECT_EQ("g", cookies[i++].Name()); | |
| 2035 EXPECT_EQ("b", cookies[i++].Name()); | |
| 2036 EXPECT_EQ("c", cookies[i++].Name()); | |
| 2037 } | |
| 2038 } | |
| 2039 | |
| 2040 // This test and CookieMonstertest.TestGCTimes (in cookie_monster_perftest.cc) | |
| 2041 // are somewhat complementary twins. This test is probing for whether | |
| 2042 // garbage collection always happens when it should (i.e. that we actually | |
| 2043 // get rid of cookies when we should). The perftest is probing for | |
| 2044 // whether garbage collection happens when it shouldn't. See comments | |
| 2045 // before that test for more details. | |
| 2046 TEST_F(CookieMonsterTest, GarbageCollectionTriggers) { | |
| 2047 // First we check to make sure that a whole lot of recent cookies | |
| 2048 // doesn't get rid of anything after garbage collection is checked for. | |
| 2049 { | |
| 2050 scoped_refptr<CookieMonster> cm( | |
| 2051 CreateMonsterForGC(CookieMonster::kMaxCookies * 2)); | |
| 2052 EXPECT_EQ(CookieMonster::kMaxCookies * 2, GetAllCookies(cm).size()); | |
| 2053 SetCookie(cm, GURL("http://newdomain.com"), "b=2"); | |
| 2054 EXPECT_EQ(CookieMonster::kMaxCookies * 2 + 1, GetAllCookies(cm).size()); | |
| 2055 } | |
| 2056 | |
| 2057 // Now we explore a series of relationships between cookie last access | |
| 2058 // time and size of store to make sure we only get rid of cookies when | |
| 2059 // we really should. | |
| 2060 const struct TestCase { | |
| 2061 int num_cookies; | |
| 2062 int num_old_cookies; | |
| 2063 int expected_initial_cookies; | |
| 2064 // Indexed by ExpiryAndKeyScheme | |
| 2065 int expected_cookies_after_set; | |
| 2066 } test_cases[] = { | |
| 2067 { | |
| 2068 // A whole lot of recent cookies; gc shouldn't happen. | |
| 2069 CookieMonster::kMaxCookies * 2, | |
| 2070 0, | |
| 2071 CookieMonster::kMaxCookies * 2, | |
| 2072 CookieMonster::kMaxCookies * 2 + 1 | |
| 2073 }, { | |
| 2074 // Some old cookies, but still overflowing max. | |
| 2075 CookieMonster::kMaxCookies * 2, | |
| 2076 CookieMonster::kMaxCookies / 2, | |
| 2077 CookieMonster::kMaxCookies * 2, | |
| 2078 CookieMonster::kMaxCookies * 2 - CookieMonster::kMaxCookies / 2 + 1 | |
| 2079 }, { | |
| 2080 // Old cookies enough to bring us right down to our purge line. | |
| 2081 CookieMonster::kMaxCookies * 2, | |
| 2082 CookieMonster::kMaxCookies + CookieMonster::kPurgeCookies + 1, | |
| 2083 CookieMonster::kMaxCookies * 2, | |
| 2084 CookieMonster::kMaxCookies - CookieMonster::kPurgeCookies | |
| 2085 }, { | |
| 2086 // Old cookies enough to bring below our purge line (which we | |
| 2087 // shouldn't do). | |
| 2088 CookieMonster::kMaxCookies * 2, | |
| 2089 CookieMonster::kMaxCookies * 3 / 2, | |
| 2090 CookieMonster::kMaxCookies * 2, | |
| 2091 CookieMonster::kMaxCookies - CookieMonster::kPurgeCookies | |
| 2092 } | |
| 2093 }; | |
| 2094 | |
| 2095 for (int ci = 0; ci < static_cast<int>(ARRAYSIZE_UNSAFE(test_cases)); ++ci) { | |
| 2096 const TestCase *test_case = &test_cases[ci]; | |
| 2097 scoped_refptr<CookieMonster> cm( | |
| 2098 CreateMonsterFromStoreForGC( | |
| 2099 test_case->num_cookies, test_case->num_old_cookies, | |
| 2100 CookieMonster::kSafeFromGlobalPurgeDays * 2)); | |
| 2101 EXPECT_EQ(test_case->expected_initial_cookies, | |
| 2102 static_cast<int>(GetAllCookies(cm).size())) | |
| 2103 << "For test case " << ci; | |
| 2104 // Will trigger GC | |
| 2105 SetCookie(cm, GURL("http://newdomain.com"), "b=2"); | |
| 2106 EXPECT_EQ(test_case->expected_cookies_after_set, | |
| 2107 static_cast<int>((GetAllCookies(cm).size()))) | |
| 2108 << "For test case " << ci; | |
| 2109 } | |
| 2110 } | |
| 2111 | |
| 2112 // This test checks that setting a cookie forcing it to be a session only | |
| 2113 // cookie works as expected. | |
| 2114 TEST_F(CookieMonsterTest, ForceSessionOnly) { | |
| 2115 scoped_refptr<CookieMonster> cm(new CookieMonster(NULL, NULL)); | |
| 2116 CookieOptions options; | |
| 2117 | |
| 2118 // Set a persistent cookie, but force it to be a session cookie. | |
| 2119 options.set_force_session(); | |
| 2120 ASSERT_TRUE(SetCookieWithOptions( | |
| 2121 cm, url_google_, | |
| 2122 std::string(kValidCookieLine) + "; expires=Mon, 18-Apr-22 22:50:13 GMT", | |
| 2123 options)); | |
| 2124 | |
| 2125 // Get the canonical cookie. | |
| 2126 CookieList cookie_list = GetAllCookies(cm); | |
| 2127 ASSERT_EQ(1U, cookie_list.size()); | |
| 2128 ASSERT_FALSE(cookie_list[0].IsPersistent()); | |
| 2129 | |
| 2130 // Use a past expiry date to delete the cookie, but force it to session only. | |
| 2131 ASSERT_TRUE(SetCookieWithOptions( | |
| 2132 cm, url_google_, | |
| 2133 std::string(kValidCookieLine) + "; expires=Mon, 18-Apr-1977 22:50:13 GMT", | |
| 2134 options)); | |
| 2135 | |
| 2136 // Check that the cookie was deleted. | |
| 2137 cookie_list = GetAllCookies(cm); | |
| 2138 ASSERT_EQ(0U, cookie_list.size()); | |
| 2139 } | |
| 2140 | |
| 2141 // This test checks that keep expired cookies flag is working. | |
| 2142 TEST_F(CookieMonsterTest, KeepExpiredCookies) { | |
| 2143 scoped_refptr<CookieMonster> cm(new CookieMonster(NULL, NULL)); | |
| 2144 cm->SetKeepExpiredCookies(); | |
| 2145 CookieOptions options; | |
| 2146 | |
| 2147 // Set a persistent cookie. | |
| 2148 ASSERT_TRUE(SetCookieWithOptions( | |
| 2149 cm, url_google_, | |
| 2150 std::string(kValidCookieLine) + "; expires=Mon, 18-Apr-22 22:50:13 GMT", | |
| 2151 options)); | |
| 2152 | |
| 2153 // Get the canonical cookie. | |
| 2154 CookieList cookie_list = GetAllCookies(cm); | |
| 2155 ASSERT_EQ(1U, cookie_list.size()); | |
| 2156 | |
| 2157 // Use a past expiry date to delete the cookie. | |
| 2158 ASSERT_TRUE(SetCookieWithOptions( | |
| 2159 cm, url_google_, | |
| 2160 std::string(kValidCookieLine) + "; expires=Mon, 18-Apr-1977 22:50:13 GMT", | |
| 2161 options)); | |
| 2162 | |
| 2163 // Check that the cookie with the past expiry date is still there. | |
| 2164 // GetAllCookies() also triggers garbage collection. | |
| 2165 cookie_list = GetAllCookies(cm); | |
| 2166 ASSERT_EQ(1U, cookie_list.size()); | |
| 2167 ASSERT_TRUE(cookie_list[0].IsExpired(Time::Now())); | |
| 2168 } | |
| 2169 | |
| 2170 namespace { | |
| 2171 | |
| 2172 // Mock PersistentCookieStore that keeps track of the number of Flush() calls. | |
| 2173 class FlushablePersistentStore : public CookieMonster::PersistentCookieStore { | |
| 2174 public: | |
| 2175 FlushablePersistentStore() : flush_count_(0) {} | |
| 2176 | |
| 2177 void Load(const LoadedCallback& loaded_callback) { | |
| 2178 std::vector<CookieMonster::CanonicalCookie*> out_cookies; | |
| 2179 MessageLoop::current()->PostTask(FROM_HERE, | |
| 2180 base::Bind(&net::LoadedCallbackTask::Run, | |
| 2181 new net::LoadedCallbackTask(loaded_callback, out_cookies))); | |
| 2182 } | |
| 2183 | |
| 2184 void LoadCookiesForKey(const std::string& key, | |
| 2185 const LoadedCallback& loaded_callback) { | |
| 2186 Load(loaded_callback); | |
| 2187 } | |
| 2188 | |
| 2189 void AddCookie(const CookieMonster::CanonicalCookie&) {} | |
| 2190 void UpdateCookieAccessTime(const CookieMonster::CanonicalCookie&) {} | |
| 2191 void DeleteCookie(const CookieMonster::CanonicalCookie&) {} | |
| 2192 void SetClearLocalStateOnExit(bool clear_local_state) {} | |
| 2193 | |
| 2194 void Flush(const base::Closure& callback) { | |
| 2195 ++flush_count_; | |
| 2196 if (!callback.is_null()) | |
| 2197 callback.Run(); | |
| 2198 } | |
| 2199 | |
| 2200 int flush_count() { | |
| 2201 return flush_count_; | |
| 2202 } | |
| 2203 | |
| 2204 private: | |
| 2205 volatile int flush_count_; | |
| 2206 }; | |
| 2207 | |
| 2208 // Counts the number of times Callback() has been run. | |
| 2209 class CallbackCounter : public base::RefCountedThreadSafe<CallbackCounter> { | |
| 2210 public: | |
| 2211 CallbackCounter() : callback_count_(0) {} | |
| 2212 | |
| 2213 void Callback() { | |
| 2214 ++callback_count_; | |
| 2215 } | |
| 2216 | |
| 2217 int callback_count() { | |
| 2218 return callback_count_; | |
| 2219 } | |
| 2220 | |
| 2221 private: | |
| 2222 friend class base::RefCountedThreadSafe<CallbackCounter>; | |
| 2223 volatile int callback_count_; | |
| 2224 }; | |
| 2225 | |
| 2226 } // namespace | |
| 2227 | |
| 2228 // Test that FlushStore() is forwarded to the store and callbacks are posted. | |
| 2229 TEST_F(CookieMonsterTest, FlushStore) { | |
| 2230 scoped_refptr<CallbackCounter> counter(new CallbackCounter()); | |
| 2231 scoped_refptr<FlushablePersistentStore> store(new FlushablePersistentStore()); | |
| 2232 scoped_refptr<CookieMonster> cm(new CookieMonster(store, NULL)); | |
| 2233 | |
| 2234 ASSERT_EQ(0, store->flush_count()); | |
| 2235 ASSERT_EQ(0, counter->callback_count()); | |
| 2236 | |
| 2237 // Before initialization, FlushStore() should just run the callback. | |
| 2238 cm->FlushStore(base::Bind(&CallbackCounter::Callback, counter.get())); | |
| 2239 MessageLoop::current()->RunAllPending(); | |
| 2240 | |
| 2241 ASSERT_EQ(0, store->flush_count()); | |
| 2242 ASSERT_EQ(1, counter->callback_count()); | |
| 2243 | |
| 2244 // NULL callback is safe. | |
| 2245 cm->FlushStore(base::Closure()); | |
| 2246 MessageLoop::current()->RunAllPending(); | |
| 2247 | |
| 2248 ASSERT_EQ(0, store->flush_count()); | |
| 2249 ASSERT_EQ(1, counter->callback_count()); | |
| 2250 | |
| 2251 // After initialization, FlushStore() should delegate to the store. | |
| 2252 GetAllCookies(cm); // Force init. | |
| 2253 cm->FlushStore(base::Bind(&CallbackCounter::Callback, counter.get())); | |
| 2254 MessageLoop::current()->RunAllPending(); | |
| 2255 | |
| 2256 ASSERT_EQ(1, store->flush_count()); | |
| 2257 ASSERT_EQ(2, counter->callback_count()); | |
| 2258 | |
| 2259 // NULL callback is still safe. | |
| 2260 cm->FlushStore(base::Closure()); | |
| 2261 MessageLoop::current()->RunAllPending(); | |
| 2262 | |
| 2263 ASSERT_EQ(2, store->flush_count()); | |
| 2264 ASSERT_EQ(2, counter->callback_count()); | |
| 2265 | |
| 2266 // If there's no backing store, FlushStore() is always a safe no-op. | |
| 2267 cm = new CookieMonster(NULL, NULL); | |
| 2268 GetAllCookies(cm); // Force init. | |
| 2269 cm->FlushStore(base::Closure()); | |
| 2270 MessageLoop::current()->RunAllPending(); | |
| 2271 | |
| 2272 ASSERT_EQ(2, counter->callback_count()); | |
| 2273 | |
| 2274 cm->FlushStore(base::Bind(&CallbackCounter::Callback, counter.get())); | |
| 2275 MessageLoop::current()->RunAllPending(); | |
| 2276 | |
| 2277 ASSERT_EQ(3, counter->callback_count()); | |
| 2278 } | |
| 2279 | |
| 2280 TEST_F(CookieMonsterTest, GetCookieSourceFromURL) { | |
| 2281 EXPECT_EQ("http://example.com/", | |
| 2282 CookieMonster::CanonicalCookie::GetCookieSourceFromURL( | |
| 2283 GURL("http://example.com"))); | |
| 2284 EXPECT_EQ("http://example.com/", | |
| 2285 CookieMonster::CanonicalCookie::GetCookieSourceFromURL( | |
| 2286 GURL("http://example.com/"))); | |
| 2287 EXPECT_EQ("http://example.com/", | |
| 2288 CookieMonster::CanonicalCookie::GetCookieSourceFromURL( | |
| 2289 GURL("http://example.com/test"))); | |
| 2290 EXPECT_EQ("file:///tmp/test.html", | |
| 2291 CookieMonster::CanonicalCookie::GetCookieSourceFromURL( | |
| 2292 GURL("file:///tmp/test.html"))); | |
| 2293 EXPECT_EQ("http://example.com/", | |
| 2294 CookieMonster::CanonicalCookie::GetCookieSourceFromURL( | |
| 2295 GURL("http://example.com:1234/"))); | |
| 2296 EXPECT_EQ("http://example.com/", | |
| 2297 CookieMonster::CanonicalCookie::GetCookieSourceFromURL( | |
| 2298 GURL("https://example.com/"))); | |
| 2299 EXPECT_EQ("http://example.com/", | |
| 2300 CookieMonster::CanonicalCookie::GetCookieSourceFromURL( | |
| 2301 GURL("http://user:pwd@example.com/"))); | |
| 2302 EXPECT_EQ("http://example.com/", | |
| 2303 CookieMonster::CanonicalCookie::GetCookieSourceFromURL( | |
| 2304 GURL("http://example.com/test?foo"))); | |
| 2305 EXPECT_EQ("http://example.com/", | |
| 2306 CookieMonster::CanonicalCookie::GetCookieSourceFromURL( | |
| 2307 GURL("http://example.com/test#foo"))); | |
| 2308 } | |
| 2309 | |
| 2310 TEST_F(CookieMonsterTest, HistogramCheck) { | |
| 2311 scoped_refptr<CookieMonster> cm(new CookieMonster(NULL, NULL)); | |
| 2312 // Should match call in InitializeHistograms, but doesn't really matter | |
| 2313 // since the histogram should have been initialized by the CM construction | |
| 2314 // above. | |
| 2315 base::Histogram* expired_histogram = | |
| 2316 base::Histogram::FactoryGet( | |
| 2317 "Cookie.ExpirationDurationMinutes", 1, 10 * 365 * 24 * 60, 50, | |
| 2318 base::Histogram::kUmaTargetedHistogramFlag); | |
| 2319 | |
| 2320 base::Histogram::SampleSet histogram_set_1; | |
| 2321 expired_histogram->SnapshotSample(&histogram_set_1); | |
| 2322 ASSERT_TRUE(SetCookieWithDetails( | |
| 2323 cm, GURL("http://fake.a.url"), "a", "b", "a.url", "/", | |
| 2324 base::Time::Now() + base::TimeDelta::FromMinutes(59), | |
| 2325 false, false)); | |
| 2326 | |
| 2327 base::Histogram::SampleSet histogram_set_2; | |
| 2328 expired_histogram->SnapshotSample(&histogram_set_2); | |
| 2329 EXPECT_EQ(histogram_set_1.TotalCount() + 1, | |
| 2330 histogram_set_2.TotalCount()); | |
| 2331 | |
| 2332 // kValidCookieLine creates a session cookie. | |
| 2333 ASSERT_TRUE(SetCookie(cm, url_google_, kValidCookieLine)); | |
| 2334 expired_histogram->SnapshotSample(&histogram_set_1); | |
| 2335 EXPECT_EQ(histogram_set_2.TotalCount(), | |
| 2336 histogram_set_1.TotalCount()); | |
| 2337 } | |
| 2338 | |
| 2339 namespace { | |
| 2340 | |
| 2341 class MultiThreadedCookieMonsterTest : public CookieMonsterTest { | |
| 2342 public: | |
| 2343 MultiThreadedCookieMonsterTest() : other_thread_("CMTthread") {} | |
| 2344 | |
| 2345 // Helper methods for calling the asynchronous CookieMonster methods | |
| 2346 // from a different thread. | |
| 2347 | |
| 2348 void GetAllCookiesTask(CookieMonster* cm, | |
| 2349 GetCookieListCallback* callback) { | |
| 2350 cm->GetAllCookiesAsync( | |
| 2351 base::Bind(&GetCookieListCallback::Run, base::Unretained(callback))); | |
| 2352 } | |
| 2353 | |
| 2354 void GetAllCookiesForURLTask(CookieMonster* cm, | |
| 2355 const GURL& url, | |
| 2356 GetCookieListCallback* callback) { | |
| 2357 cm->GetAllCookiesForURLAsync( | |
| 2358 url, | |
| 2359 base::Bind(&GetCookieListCallback::Run, base::Unretained(callback))); | |
| 2360 } | |
| 2361 | |
| 2362 void GetAllCookiesForURLWithOptionsTask(CookieMonster* cm, | |
| 2363 const GURL& url, | |
| 2364 const CookieOptions& options, | |
| 2365 GetCookieListCallback* callback) { | |
| 2366 cm->GetAllCookiesForURLWithOptionsAsync( | |
| 2367 url, options, | |
| 2368 base::Bind(&GetCookieListCallback::Run, base::Unretained(callback))); | |
| 2369 } | |
| 2370 | |
| 2371 void SetCookieWithDetailsTask(CookieMonster* cm, const GURL& url, | |
| 2372 SetCookieCallback* callback) { | |
| 2373 // Define the parameters here instead of in the calling fucntion. | |
| 2374 // The maximum number of parameters for Bind function is 6. | |
| 2375 std::string name = "A"; | |
| 2376 std::string value = "B"; | |
| 2377 std::string domain = std::string(); | |
| 2378 std::string path = "/foo"; | |
| 2379 base::Time expiration_time = base::Time(); | |
| 2380 bool secure = false; | |
| 2381 bool http_only = false; | |
| 2382 cm->SetCookieWithDetailsAsync( | |
| 2383 url, name, value, domain, path, expiration_time, secure, http_only, | |
| 2384 base::Bind(&SetCookieCallback::Run, base::Unretained(callback))); | |
| 2385 } | |
| 2386 | |
| 2387 void DeleteAllCreatedBetweenTask(CookieMonster* cm, | |
| 2388 const base::Time& delete_begin, | |
| 2389 const base::Time& delete_end, | |
| 2390 DeleteCallback* callback) { | |
| 2391 cm->DeleteAllCreatedBetweenAsync( | |
| 2392 delete_begin, delete_end, | |
| 2393 base::Bind(&DeleteCallback::Run, | |
| 2394 base::Unretained(callback))); | |
| 2395 } | |
| 2396 | |
| 2397 void DeleteAllForHostTask(CookieMonster* cm, | |
| 2398 const GURL& url, | |
| 2399 DeleteCallback* callback) { | |
| 2400 cm->DeleteAllForHostAsync( | |
| 2401 url, | |
| 2402 base::Bind(&DeleteCallback::Run, base::Unretained(callback))); | |
| 2403 } | |
| 2404 | |
| 2405 void DeleteCanonicalCookieTask(CookieMonster* cm, | |
| 2406 const CookieMonster::CanonicalCookie& cookie, | |
| 2407 SetCookieCallback* callback) { | |
| 2408 cm->DeleteCanonicalCookieAsync( | |
| 2409 cookie, | |
| 2410 base::Bind(&SetCookieCallback::Run, base::Unretained(callback))); | |
| 2411 } | |
| 2412 | |
| 2413 protected: | |
| 2414 void RunOnOtherThread(const base::Closure& task) { | |
| 2415 other_thread_.Start(); | |
| 2416 other_thread_.message_loop()->PostTask(FROM_HERE, task); | |
| 2417 RunFor(kTimeout); | |
| 2418 other_thread_.Stop(); | |
| 2419 } | |
| 2420 | |
| 2421 Thread other_thread_; | |
| 2422 }; | |
| 2423 | |
| 2424 } // namespace | |
| 2425 | |
| 2426 TEST_F(MultiThreadedCookieMonsterTest, ThreadCheckGetAllCookies) { | |
| 2427 scoped_refptr<CookieMonster> cm(new CookieMonster(NULL, NULL)); | |
| 2428 EXPECT_TRUE(SetCookie(cm, url_google_, "A=B")); | |
| 2429 CookieList cookies = GetAllCookies(cm); | |
| 2430 CookieList::const_iterator it = cookies.begin(); | |
| 2431 ASSERT_TRUE(it != cookies.end()); | |
| 2432 EXPECT_EQ("www.google.izzle", it->Domain()); | |
| 2433 EXPECT_EQ("A", it->Name()); | |
| 2434 ASSERT_TRUE(++it == cookies.end()); | |
| 2435 GetCookieListCallback callback(&other_thread_); | |
| 2436 base::Closure task = | |
| 2437 base::Bind(&net::MultiThreadedCookieMonsterTest::GetAllCookiesTask, | |
| 2438 base::Unretained(this), | |
| 2439 cm, &callback); | |
| 2440 RunOnOtherThread(task); | |
| 2441 EXPECT_TRUE(callback.did_run()); | |
| 2442 it = callback.cookies().begin(); | |
| 2443 ASSERT_TRUE(it != callback.cookies().end()); | |
| 2444 EXPECT_EQ("www.google.izzle", it->Domain()); | |
| 2445 EXPECT_EQ("A", it->Name()); | |
| 2446 ASSERT_TRUE(++it == callback.cookies().end()); | |
| 2447 } | |
| 2448 | |
| 2449 TEST_F(MultiThreadedCookieMonsterTest, ThreadCheckGetAllCookiesForURL) { | |
| 2450 scoped_refptr<CookieMonster> cm(new CookieMonster(NULL, NULL)); | |
| 2451 EXPECT_TRUE(SetCookie(cm, url_google_, "A=B")); | |
| 2452 CookieList cookies = GetAllCookiesForURL(cm, url_google_); | |
| 2453 CookieList::const_iterator it = cookies.begin(); | |
| 2454 ASSERT_TRUE(it != cookies.end()); | |
| 2455 EXPECT_EQ("www.google.izzle", it->Domain()); | |
| 2456 EXPECT_EQ("A", it->Name()); | |
| 2457 ASSERT_TRUE(++it == cookies.end()); | |
| 2458 GetCookieListCallback callback(&other_thread_); | |
| 2459 base::Closure task = | |
| 2460 base::Bind(&net::MultiThreadedCookieMonsterTest::GetAllCookiesForURLTask, | |
| 2461 base::Unretained(this), | |
| 2462 cm, url_google_, &callback); | |
| 2463 RunOnOtherThread(task); | |
| 2464 EXPECT_TRUE(callback.did_run()); | |
| 2465 it = callback.cookies().begin(); | |
| 2466 ASSERT_TRUE(it != callback.cookies().end()); | |
| 2467 EXPECT_EQ("www.google.izzle", it->Domain()); | |
| 2468 EXPECT_EQ("A", it->Name()); | |
| 2469 ASSERT_TRUE(++it == callback.cookies().end()); | |
| 2470 } | |
| 2471 | |
| 2472 TEST_F(MultiThreadedCookieMonsterTest, ThreadCheckGetAllCookiesForURLWithOpt) { | |
| 2473 scoped_refptr<CookieMonster> cm(new CookieMonster(NULL, NULL)); | |
| 2474 EXPECT_TRUE(SetCookie(cm, url_google_, "A=B")); | |
| 2475 CookieOptions options; | |
| 2476 CookieList cookies = | |
| 2477 GetAllCookiesForURLWithOptions(cm, url_google_, options); | |
| 2478 CookieList::const_iterator it = cookies.begin(); | |
| 2479 ASSERT_TRUE(it != cookies.end()); | |
| 2480 EXPECT_EQ("www.google.izzle", it->Domain()); | |
| 2481 EXPECT_EQ("A", it->Name()); | |
| 2482 ASSERT_TRUE(++it == cookies.end()); | |
| 2483 GetCookieListCallback callback(&other_thread_); | |
| 2484 base::Closure task = base::Bind( | |
| 2485 &net::MultiThreadedCookieMonsterTest::GetAllCookiesForURLWithOptionsTask, | |
| 2486 base::Unretained(this), | |
| 2487 cm, url_google_, options, &callback); | |
| 2488 RunOnOtherThread(task); | |
| 2489 EXPECT_TRUE(callback.did_run()); | |
| 2490 it = callback.cookies().begin(); | |
| 2491 ASSERT_TRUE(it != callback.cookies().end()); | |
| 2492 EXPECT_EQ("www.google.izzle", it->Domain()); | |
| 2493 EXPECT_EQ("A", it->Name()); | |
| 2494 ASSERT_TRUE(++it == callback.cookies().end()); | |
| 2495 } | |
| 2496 | |
| 2497 TEST_F(MultiThreadedCookieMonsterTest, ThreadCheckSetCookieWithDetails) { | |
| 2498 scoped_refptr<CookieMonster> cm(new CookieMonster(NULL, NULL)); | |
| 2499 EXPECT_TRUE(SetCookieWithDetails( | |
| 2500 cm, url_google_foo_, | |
| 2501 "A", "B", std::string(), "/foo", base::Time(), | |
| 2502 false, false)); | |
| 2503 SetCookieCallback callback(&other_thread_); | |
| 2504 base::Closure task = base::Bind( | |
| 2505 &net::MultiThreadedCookieMonsterTest::SetCookieWithDetailsTask, | |
| 2506 base::Unretained(this), | |
| 2507 cm, url_google_foo_, &callback); | |
| 2508 RunOnOtherThread(task); | |
| 2509 EXPECT_TRUE(callback.did_run()); | |
| 2510 EXPECT_TRUE(callback.result()); | |
| 2511 } | |
| 2512 | |
| 2513 | |
| 2514 TEST_F(MultiThreadedCookieMonsterTest, ThreadCheckDeleteAllCreatedBetween) { | |
| 2515 scoped_refptr<CookieMonster> cm(new CookieMonster(NULL, NULL)); | |
| 2516 CookieOptions options; | |
| 2517 Time now = Time::Now(); | |
| 2518 EXPECT_TRUE(SetCookieWithOptions(cm, url_google_, "A=B", options)); | |
| 2519 EXPECT_EQ(1, DeleteAllCreatedBetween(cm, now - TimeDelta::FromDays(99), | |
| 2520 Time())); | |
| 2521 EXPECT_TRUE(SetCookieWithOptions(cm, url_google_, "A=B", options)); | |
| 2522 DeleteCallback callback(&other_thread_); | |
| 2523 base::Closure task = base::Bind( | |
| 2524 &net::MultiThreadedCookieMonsterTest::DeleteAllCreatedBetweenTask, | |
| 2525 base::Unretained(this), | |
| 2526 cm, now - TimeDelta::FromDays(99), | |
| 2527 Time(), &callback); | |
| 2528 RunOnOtherThread(task); | |
| 2529 EXPECT_TRUE(callback.did_run()); | |
| 2530 EXPECT_EQ(1, callback.num_deleted()); | |
| 2531 } | |
| 2532 | |
| 2533 TEST_F(MultiThreadedCookieMonsterTest, ThreadCheckDeleteAllForHost) { | |
| 2534 scoped_refptr<CookieMonster> cm(new CookieMonster(NULL, NULL)); | |
| 2535 CookieOptions options; | |
| 2536 EXPECT_TRUE(SetCookieWithOptions(cm, url_google_, "A=B", options)); | |
| 2537 EXPECT_EQ(1, DeleteAllForHost(cm, url_google_)); | |
| 2538 EXPECT_TRUE(SetCookieWithOptions(cm, url_google_, "A=B", options)); | |
| 2539 DeleteCallback callback(&other_thread_); | |
| 2540 base::Closure task = base::Bind( | |
| 2541 &net::MultiThreadedCookieMonsterTest::DeleteAllForHostTask, | |
| 2542 base::Unretained(this), | |
| 2543 cm, url_google_, &callback); | |
| 2544 RunOnOtherThread(task); | |
| 2545 EXPECT_TRUE(callback.did_run()); | |
| 2546 EXPECT_EQ(1, callback.num_deleted()); | |
| 2547 } | |
| 2548 | |
| 2549 TEST_F(MultiThreadedCookieMonsterTest, ThreadCheckDeleteCanonicalCookie) { | |
| 2550 scoped_refptr<CookieMonster> cm(new CookieMonster(NULL, NULL)); | |
| 2551 CookieOptions options; | |
| 2552 EXPECT_TRUE(SetCookieWithOptions(cm, url_google_, "A=B", options)); | |
| 2553 CookieList cookies = GetAllCookies(cm); | |
| 2554 CookieList::iterator it = cookies.begin(); | |
| 2555 EXPECT_TRUE(DeleteCanonicalCookie(cm, *it)); | |
| 2556 | |
| 2557 EXPECT_TRUE(SetCookieWithOptions(cm, url_google_, "A=B", options)); | |
| 2558 SetCookieCallback callback(&other_thread_); | |
| 2559 cookies = GetAllCookies(cm); | |
| 2560 it = cookies.begin(); | |
| 2561 base::Closure task = base::Bind( | |
| 2562 &net::MultiThreadedCookieMonsterTest::DeleteCanonicalCookieTask, | |
| 2563 base::Unretained(this), | |
| 2564 cm, *it, &callback); | |
| 2565 RunOnOtherThread(task); | |
| 2566 EXPECT_TRUE(callback.did_run()); | |
| 2567 EXPECT_TRUE(callback.result()); | |
| 2568 } | |
| 2569 | |
| 2570 TEST_F(CookieMonsterTest, ShortLivedSessionCookies) { | |
| 2571 scoped_refptr<MockPersistentCookieStore> store( | |
| 2572 new MockPersistentCookieStore); | |
| 2573 scoped_refptr<CookieMonster> cm(new CookieMonster(store, NULL)); | |
| 2574 | |
| 2575 // Create a short-lived session cookie. | |
| 2576 CookieOptions options; | |
| 2577 options.set_force_session(); | |
| 2578 Time current = Time::Now(); | |
| 2579 EXPECT_TRUE(SetCookieWithOptions(cm, url_google_, | |
| 2580 std::string(kValidCookieLine) + | |
| 2581 "; max-age=10", | |
| 2582 options)); | |
| 2583 | |
| 2584 // FindCookiesForKey asserts that its caller holds this lock. | |
| 2585 base::AutoLock auto_lock(cm->lock_); | |
| 2586 | |
| 2587 // Get cookies before the cookie has expired. | |
| 2588 std::vector<CookieMonster::CanonicalCookie*> cookies; | |
| 2589 cm->FindCookiesForKey(cm->GetKey(url_google_.host()), url_google_, | |
| 2590 CookieOptions(), current, false, &cookies); | |
| 2591 EXPECT_EQ(1U, cookies.size()); | |
| 2592 | |
| 2593 // Get cookies after the cookie has expired. | |
| 2594 cookies.clear(); | |
| 2595 cm->FindCookiesForKey(cm->GetKey(url_google_.host()), url_google_, | |
| 2596 CookieOptions(), current + TimeDelta::FromSeconds(20), | |
| 2597 false, &cookies); | |
| 2598 EXPECT_EQ(0U, cookies.size()); | |
| 2599 } | |
| 2600 | |
| 2601 TEST_F(CookieMonsterTest, InvalidExpiryTime) { | |
| 2602 CookieMonster::ParsedCookie pc( | |
| 2603 std::string(kValidCookieLine) + "; expires=Blarg arg arg"); | |
| 2604 scoped_ptr<CookieMonster::CanonicalCookie> cookie( | |
| 2605 CookieMonster::CanonicalCookie::Create(url_google_, pc)); | |
| 2606 | |
| 2607 ASSERT_FALSE(cookie->DoesExpire()); | |
| 2608 } | |
| 2609 | |
| 2610 // Test that CookieMonster writes session cookies into the underlying | |
| 2611 // CookieStore if the "persist session cookies" option is on. | |
| 2612 TEST_F(CookieMonsterTest, PersistSessionCookies) { | |
| 2613 scoped_refptr<MockPersistentCookieStore> store( | |
| 2614 new MockPersistentCookieStore); | |
| 2615 scoped_refptr<CookieMonster> cm(new CookieMonster(store, NULL)); | |
| 2616 cm->SetPersistSessionCookies(true); | |
| 2617 | |
| 2618 // All cookies set with SetCookie are session cookies. | |
| 2619 EXPECT_TRUE(SetCookie(cm, url_google_, "A=B")); | |
| 2620 EXPECT_EQ("A=B", GetCookies(cm, url_google_)); | |
| 2621 | |
| 2622 // The cookie was written to the backing store. | |
| 2623 EXPECT_EQ(1u, store->commands().size()); | |
| 2624 EXPECT_EQ(CookieStoreCommand::ADD, store->commands()[0].type); | |
| 2625 EXPECT_EQ("A", store->commands()[0].cookie.Name()); | |
| 2626 EXPECT_EQ("B", store->commands()[0].cookie.Value()); | |
| 2627 | |
| 2628 // Modify the cookie. | |
| 2629 EXPECT_TRUE(SetCookie(cm, url_google_, "A=C")); | |
| 2630 EXPECT_EQ("A=C", GetCookies(cm, url_google_)); | |
| 2631 EXPECT_EQ(3u, store->commands().size()); | |
| 2632 EXPECT_EQ(CookieStoreCommand::REMOVE, store->commands()[1].type); | |
| 2633 EXPECT_EQ("A", store->commands()[1].cookie.Name()); | |
| 2634 EXPECT_EQ("B", store->commands()[1].cookie.Value()); | |
| 2635 EXPECT_EQ(CookieStoreCommand::ADD, store->commands()[2].type); | |
| 2636 EXPECT_EQ("A", store->commands()[2].cookie.Name()); | |
| 2637 EXPECT_EQ("C", store->commands()[2].cookie.Value()); | |
| 2638 | |
| 2639 // Delete the cookie. | |
| 2640 DeleteCookie(cm, url_google_, "A"); | |
| 2641 EXPECT_EQ("", GetCookies(cm, url_google_)); | |
| 2642 EXPECT_EQ(4u, store->commands().size()); | |
| 2643 EXPECT_EQ(CookieStoreCommand::REMOVE, store->commands()[3].type); | |
| 2644 EXPECT_EQ("A", store->commands()[3].cookie.Name()); | |
| 2645 EXPECT_EQ("C", store->commands()[3].cookie.Value()); | |
| 2646 } | |
| 2647 | |
| 2648 // Test the commands sent to the persistent cookie store. | |
| 2649 TEST_F(CookieMonsterTest, PersisentCookieStorageTest) { | |
| 2650 scoped_refptr<MockPersistentCookieStore> store( | |
| 2651 new MockPersistentCookieStore); | |
| 2652 scoped_refptr<CookieMonster> cm(new CookieMonster(store, NULL)); | |
| 2653 | |
| 2654 // Add a cookie. | |
| 2655 EXPECT_TRUE(SetCookie(cm, url_google_, | |
| 2656 "A=B; expires=Mon, 18-Apr-22 22:50:13 GMT")); | |
| 2657 this->MatchCookieLines("A=B", GetCookies(cm, url_google_)); | |
| 2658 ASSERT_EQ(1u, store->commands().size()); | |
| 2659 EXPECT_EQ(CookieStoreCommand::ADD, store->commands()[0].type); | |
| 2660 // Remove it. | |
| 2661 EXPECT_TRUE(SetCookie(cm, url_google_,"A=B; max-age=0")); | |
| 2662 this->MatchCookieLines("", GetCookies(cm, url_google_)); | |
| 2663 ASSERT_EQ(2u, store->commands().size()); | |
| 2664 EXPECT_EQ(CookieStoreCommand::REMOVE, store->commands()[1].type); | |
| 2665 | |
| 2666 // Add a cookie. | |
| 2667 EXPECT_TRUE(SetCookie(cm, url_google_, | |
| 2668 "A=B; expires=Mon, 18-Apr-22 22:50:13 GMT")); | |
| 2669 this->MatchCookieLines("A=B", GetCookies(cm, url_google_)); | |
| 2670 ASSERT_EQ(3u, store->commands().size()); | |
| 2671 EXPECT_EQ(CookieStoreCommand::ADD, store->commands()[2].type); | |
| 2672 // Overwrite it. | |
| 2673 EXPECT_TRUE(SetCookie(cm, url_google_, | |
| 2674 "A=Foo; expires=Mon, 18-Apr-22 22:50:14 GMT")); | |
| 2675 this->MatchCookieLines("A=Foo", GetCookies(cm, url_google_)); | |
| 2676 ASSERT_EQ(5u, store->commands().size()); | |
| 2677 EXPECT_EQ(CookieStoreCommand::REMOVE, store->commands()[3].type); | |
| 2678 EXPECT_EQ(CookieStoreCommand::ADD, store->commands()[4].type); | |
| 2679 | |
| 2680 // Create some non-persistent cookies and check that they don't go to the | |
| 2681 // persistent storage. | |
| 2682 EXPECT_TRUE(SetCookie(cm, url_google_, "B=Bar")); | |
| 2683 this->MatchCookieLines("A=Foo; B=Bar", GetCookies(cm, url_google_)); | |
| 2684 EXPECT_EQ(5u, store->commands().size()); | |
| 2685 } | |
| 2686 | |
| 2687 } // namespace net | |
| OLD | NEW |