Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(586)

Side by Side Diff: net/base/cookie_monster_unittest.cc

Issue 9703011: Move the cookie store implementation into its own directory. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: net/base/cookies/ -> net/cookies/ Created 8 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « net/base/cookie_monster_store_test.cc ('k') | net/base/cookie_options.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(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
OLDNEW
« no previous file with comments | « net/base/cookie_monster_store_test.cc ('k') | net/base/cookie_options.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698