We started redesigning GpuMemoryBuffer interface to handle multiple buffers [0].
[chromium-blink-merge.git] / net / cookies / cookie_monster_unittest.cc
blob60caa67ea6ad7533b3b7071a332b0af0dbc4874d
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "net/cookies/cookie_store_unittest.h"
7 #include <algorithm>
8 #include <string>
9 #include <vector>
11 #include "base/basictypes.h"
12 #include "base/bind.h"
13 #include "base/memory/ref_counted.h"
14 #include "base/memory/scoped_ptr.h"
15 #include "base/memory/scoped_vector.h"
16 #include "base/message_loop/message_loop.h"
17 #include "base/metrics/histogram.h"
18 #include "base/metrics/histogram_samples.h"
19 #include "base/strings/string_number_conversions.h"
20 #include "base/strings/string_piece.h"
21 #include "base/strings/string_split.h"
22 #include "base/strings/string_tokenizer.h"
23 #include "base/strings/stringprintf.h"
24 #include "base/threading/thread.h"
25 #include "base/time/time.h"
26 #include "net/cookies/canonical_cookie.h"
27 #include "net/cookies/cookie_constants.h"
28 #include "net/cookies/cookie_monster.h"
29 #include "net/cookies/cookie_monster_store_test.h" // For CookieStore mock
30 #include "net/cookies/cookie_util.h"
31 #include "net/cookies/parsed_cookie.h"
32 #include "testing/gmock/include/gmock/gmock.h"
33 #include "testing/gtest/include/gtest/gtest.h"
34 #include "url/gurl.h"
36 namespace net {
38 using base::Time;
39 using base::TimeDelta;
41 namespace {
43 // TODO(erikwright): Replace the pre-existing MockPersistentCookieStore (and
44 // brethren) with this one, and remove the 'New' prefix.
45 class NewMockPersistentCookieStore
46 : public CookieMonster::PersistentCookieStore {
47 public:
48 MOCK_METHOD1(Load, void(const LoadedCallback& loaded_callback));
49 MOCK_METHOD2(LoadCookiesForKey,
50 void(const std::string& key,
51 const LoadedCallback& loaded_callback));
52 MOCK_METHOD1(AddCookie, void(const CanonicalCookie& cc));
53 MOCK_METHOD1(UpdateCookieAccessTime, void(const CanonicalCookie& cc));
54 MOCK_METHOD1(DeleteCookie, void(const CanonicalCookie& cc));
55 virtual void Flush(const base::Closure& callback) {
56 if (!callback.is_null())
57 base::MessageLoop::current()->PostTask(FROM_HERE, callback);
59 MOCK_METHOD0(SetForceKeepSessionState, void());
61 private:
62 virtual ~NewMockPersistentCookieStore() {}
65 const char kTopLevelDomainPlus1[] = "http://www.harvard.edu";
66 const char kTopLevelDomainPlus2[] = "http://www.math.harvard.edu";
67 const char kTopLevelDomainPlus2Secure[] = "https://www.math.harvard.edu";
68 const char kTopLevelDomainPlus3[] = "http://www.bourbaki.math.harvard.edu";
69 const char kOtherDomain[] = "http://www.mit.edu";
70 const char kUrlGoogleSpecific[] = "http://www.gmail.google.izzle";
72 class GetCookieListCallback : public CookieCallback {
73 public:
74 GetCookieListCallback() {}
75 explicit GetCookieListCallback(Thread* run_in_thread)
76 : CookieCallback(run_in_thread) {}
78 void Run(const CookieList& cookies) {
79 cookies_ = cookies;
80 CallbackEpilogue();
83 const CookieList& cookies() { return cookies_; }
85 private:
86 CookieList cookies_;
89 struct CookieMonsterTestTraits {
90 static scoped_refptr<CookieStore> Create() {
91 return new CookieMonster(NULL, NULL);
94 static const bool is_cookie_monster = true;
95 static const bool supports_http_only = true;
96 static const bool supports_non_dotted_domains = true;
97 static const bool supports_trailing_dots = true;
98 static const bool filters_schemes = true;
99 static const bool has_path_prefix_bug = false;
100 static const int creation_time_granularity_in_ms = 0;
103 INSTANTIATE_TYPED_TEST_CASE_P(CookieMonster,
104 CookieStoreTest,
105 CookieMonsterTestTraits);
107 INSTANTIATE_TYPED_TEST_CASE_P(CookieMonster,
108 MultiThreadedCookieStoreTest,
109 CookieMonsterTestTraits);
111 class CookieMonsterTest : public CookieStoreTest<CookieMonsterTestTraits> {
112 protected:
113 CookieList GetAllCookies(CookieMonster* cm) {
114 DCHECK(cm);
115 GetCookieListCallback callback;
116 cm->GetAllCookiesAsync(
117 base::Bind(&GetCookieListCallback::Run, base::Unretained(&callback)));
118 RunFor(kTimeout);
119 EXPECT_TRUE(callback.did_run());
120 return callback.cookies();
123 CookieList GetAllCookiesForURL(CookieMonster* cm, const GURL& url) {
124 DCHECK(cm);
125 GetCookieListCallback callback;
126 cm->GetAllCookiesForURLAsync(url, base::Bind(&GetCookieListCallback::Run,
127 base::Unretained(&callback)));
128 RunFor(kTimeout);
129 EXPECT_TRUE(callback.did_run());
130 return callback.cookies();
133 CookieList GetAllCookiesForURLWithOptions(CookieMonster* cm,
134 const GURL& url,
135 const CookieOptions& options) {
136 DCHECK(cm);
137 GetCookieListCallback callback;
138 cm->GetAllCookiesForURLWithOptionsAsync(
139 url, options,
140 base::Bind(&GetCookieListCallback::Run, base::Unretained(&callback)));
141 RunFor(kTimeout);
142 EXPECT_TRUE(callback.did_run());
143 return callback.cookies();
146 bool SetCookieWithDetails(CookieMonster* cm,
147 const GURL& url,
148 const std::string& name,
149 const std::string& value,
150 const std::string& domain,
151 const std::string& path,
152 const base::Time& expiration_time,
153 bool secure,
154 bool http_only,
155 bool first_party_only,
156 CookiePriority priority) {
157 DCHECK(cm);
158 ResultSavingCookieCallback<bool> callback;
159 cm->SetCookieWithDetailsAsync(
160 url, name, value, domain, path, expiration_time, secure, http_only,
161 first_party_only, priority,
162 base::Bind(&ResultSavingCookieCallback<bool>::Run,
163 base::Unretained(&callback)));
164 RunFor(kTimeout);
165 EXPECT_TRUE(callback.did_run());
166 return callback.result();
169 bool SetAllCookies(CookieMonster* cm, const CookieList& list) {
170 DCHECK(cm);
171 ResultSavingCookieCallback<bool> callback;
172 cm->SetAllCookiesAsync(list,
173 base::Bind(&ResultSavingCookieCallback<bool>::Run,
174 base::Unretained(&callback)));
175 RunFor(kTimeout);
176 EXPECT_TRUE(callback.did_run());
177 return callback.result();
180 int DeleteAll(CookieMonster* cm) {
181 DCHECK(cm);
182 ResultSavingCookieCallback<int> callback;
183 cm->DeleteAllAsync(base::Bind(&ResultSavingCookieCallback<int>::Run,
184 base::Unretained(&callback)));
185 RunFor(kTimeout);
186 EXPECT_TRUE(callback.did_run());
187 return callback.result();
190 int DeleteAllCreatedBetween(CookieMonster* cm,
191 const base::Time& delete_begin,
192 const base::Time& delete_end) {
193 DCHECK(cm);
194 ResultSavingCookieCallback<int> callback;
195 cm->DeleteAllCreatedBetweenAsync(
196 delete_begin, delete_end,
197 base::Bind(&ResultSavingCookieCallback<int>::Run,
198 base::Unretained(&callback)));
199 RunFor(kTimeout);
200 EXPECT_TRUE(callback.did_run());
201 return callback.result();
204 int DeleteAllCreatedBetweenForHost(CookieMonster* cm,
205 const base::Time delete_begin,
206 const base::Time delete_end,
207 const GURL& url) {
208 DCHECK(cm);
209 ResultSavingCookieCallback<int> callback;
210 cm->DeleteAllCreatedBetweenForHostAsync(
211 delete_begin, delete_end, url,
212 base::Bind(&ResultSavingCookieCallback<int>::Run,
213 base::Unretained(&callback)));
214 RunFor(kTimeout);
215 EXPECT_TRUE(callback.did_run());
216 return callback.result();
219 int DeleteAllForHost(CookieMonster* cm, const GURL& url) {
220 DCHECK(cm);
221 ResultSavingCookieCallback<int> callback;
222 cm->DeleteAllForHostAsync(url,
223 base::Bind(&ResultSavingCookieCallback<int>::Run,
224 base::Unretained(&callback)));
225 RunFor(kTimeout);
226 EXPECT_TRUE(callback.did_run());
227 return callback.result();
230 bool DeleteCanonicalCookie(CookieMonster* cm, const CanonicalCookie& cookie) {
231 DCHECK(cm);
232 ResultSavingCookieCallback<bool> callback;
233 cm->DeleteCanonicalCookieAsync(
234 cookie, base::Bind(&ResultSavingCookieCallback<bool>::Run,
235 base::Unretained(&callback)));
236 RunFor(kTimeout);
237 EXPECT_TRUE(callback.did_run());
238 return callback.result();
241 // Helper for DeleteAllForHost test; repopulates CM with same layout
242 // each time.
243 void PopulateCmForDeleteAllForHost(scoped_refptr<CookieMonster> cm) {
244 GURL url_top_level_domain_plus_1(kTopLevelDomainPlus1);
245 GURL url_top_level_domain_plus_2(kTopLevelDomainPlus2);
246 GURL url_top_level_domain_plus_2_secure(kTopLevelDomainPlus2Secure);
247 GURL url_top_level_domain_plus_3(kTopLevelDomainPlus3);
248 GURL url_other(kOtherDomain);
250 DeleteAll(cm.get());
252 // Static population for probe:
253 // * Three levels of domain cookie (.b.a, .c.b.a, .d.c.b.a)
254 // * Three levels of host cookie (w.b.a, w.c.b.a, w.d.c.b.a)
255 // * http_only cookie (w.c.b.a)
256 // * first-party cookie (w.c.b.a)
257 // * Two secure cookies (.c.b.a, w.c.b.a)
258 // * Two domain path cookies (.c.b.a/dir1, .c.b.a/dir1/dir2)
259 // * Two host path cookies (w.c.b.a/dir1, w.c.b.a/dir1/dir2)
261 // Domain cookies
262 EXPECT_TRUE(this->SetCookieWithDetails(
263 cm.get(), url_top_level_domain_plus_1, "dom_1", "X", ".harvard.edu",
264 "/", base::Time(), false, false, false, COOKIE_PRIORITY_DEFAULT));
265 EXPECT_TRUE(this->SetCookieWithDetails(
266 cm.get(), url_top_level_domain_plus_2, "dom_2", "X",
267 ".math.harvard.edu", "/", base::Time(), false, false, false,
268 COOKIE_PRIORITY_DEFAULT));
269 EXPECT_TRUE(this->SetCookieWithDetails(
270 cm.get(), url_top_level_domain_plus_3, "dom_3", "X",
271 ".bourbaki.math.harvard.edu", "/", base::Time(), false, false, false,
272 COOKIE_PRIORITY_DEFAULT));
274 // Host cookies
275 EXPECT_TRUE(this->SetCookieWithDetails(
276 cm.get(), url_top_level_domain_plus_1, "host_1", "X", std::string(),
277 "/", base::Time(), false, false, false, COOKIE_PRIORITY_DEFAULT));
278 EXPECT_TRUE(this->SetCookieWithDetails(
279 cm.get(), url_top_level_domain_plus_2, "host_2", "X", std::string(),
280 "/", base::Time(), false, false, false, COOKIE_PRIORITY_DEFAULT));
281 EXPECT_TRUE(this->SetCookieWithDetails(
282 cm.get(), url_top_level_domain_plus_3, "host_3", "X", std::string(),
283 "/", base::Time(), false, false, false, COOKIE_PRIORITY_DEFAULT));
285 // http_only cookie
286 EXPECT_TRUE(this->SetCookieWithDetails(
287 cm.get(), url_top_level_domain_plus_2, "httpo_check", "x",
288 std::string(), "/", base::Time(), false, true, false,
289 COOKIE_PRIORITY_DEFAULT));
291 // first-party cookie
292 EXPECT_TRUE(this->SetCookieWithDetails(
293 cm.get(), url_top_level_domain_plus_2, "firstp_check", "x",
294 std::string(), "/", base::Time(), false, false, true,
295 COOKIE_PRIORITY_DEFAULT));
297 // Secure cookies
298 EXPECT_TRUE(this->SetCookieWithDetails(
299 cm.get(), url_top_level_domain_plus_2_secure, "sec_dom", "X",
300 ".math.harvard.edu", "/", base::Time(), true, false, false,
301 COOKIE_PRIORITY_DEFAULT));
302 EXPECT_TRUE(this->SetCookieWithDetails(
303 cm.get(), url_top_level_domain_plus_2_secure, "sec_host", "X",
304 std::string(), "/", base::Time(), true, false, false,
305 COOKIE_PRIORITY_DEFAULT));
307 // Domain path cookies
308 EXPECT_TRUE(this->SetCookieWithDetails(
309 cm.get(), url_top_level_domain_plus_2, "dom_path_1", "X",
310 ".math.harvard.edu", "/dir1", base::Time(), false, false, false,
311 COOKIE_PRIORITY_DEFAULT));
312 EXPECT_TRUE(this->SetCookieWithDetails(
313 cm.get(), url_top_level_domain_plus_2, "dom_path_2", "X",
314 ".math.harvard.edu", "/dir1/dir2", base::Time(), false, false, false,
315 COOKIE_PRIORITY_DEFAULT));
317 // Host path cookies
318 EXPECT_TRUE(this->SetCookieWithDetails(
319 cm.get(), url_top_level_domain_plus_2, "host_path_1", "X",
320 std::string(), "/dir1", base::Time(), false, false, false,
321 COOKIE_PRIORITY_DEFAULT));
322 EXPECT_TRUE(this->SetCookieWithDetails(
323 cm.get(), url_top_level_domain_plus_2, "host_path_2", "X",
324 std::string(), "/dir1/dir2", base::Time(), false, false, false,
325 COOKIE_PRIORITY_DEFAULT));
327 EXPECT_EQ(14U, this->GetAllCookies(cm.get()).size());
330 Time GetFirstCookieAccessDate(CookieMonster* cm) {
331 const CookieList all_cookies(this->GetAllCookies(cm));
332 return all_cookies.front().LastAccessDate();
335 bool FindAndDeleteCookie(CookieMonster* cm,
336 const std::string& domain,
337 const std::string& name) {
338 CookieList cookies = this->GetAllCookies(cm);
339 for (CookieList::iterator it = cookies.begin(); it != cookies.end(); ++it)
340 if (it->Domain() == domain && it->Name() == name)
341 return this->DeleteCanonicalCookie(cm, *it);
342 return false;
345 int CountInString(const std::string& str, char c) {
346 return std::count(str.begin(), str.end(), c);
349 void TestHostGarbageCollectHelper() {
350 int domain_max_cookies = CookieMonster::kDomainMaxCookies;
351 int domain_purge_cookies = CookieMonster::kDomainPurgeCookies;
352 const int more_than_enough_cookies =
353 (domain_max_cookies + domain_purge_cookies) * 2;
354 // Add a bunch of cookies on a single host, should purge them.
356 scoped_refptr<CookieMonster> cm(new CookieMonster(NULL, NULL));
357 for (int i = 0; i < more_than_enough_cookies; ++i) {
358 std::string cookie = base::StringPrintf("a%03d=b", i);
359 EXPECT_TRUE(SetCookie(cm.get(), url_google_, cookie));
360 std::string cookies = this->GetCookies(cm.get(), url_google_);
361 // Make sure we find it in the cookies.
362 EXPECT_NE(cookies.find(cookie), std::string::npos);
363 // Count the number of cookies.
364 EXPECT_LE(CountInString(cookies, '='), domain_max_cookies);
368 // Add a bunch of cookies on multiple hosts within a single eTLD.
369 // Should keep at least kDomainMaxCookies - kDomainPurgeCookies
370 // between them. We shouldn't go above kDomainMaxCookies for both together.
371 GURL url_google_specific(kUrlGoogleSpecific);
373 scoped_refptr<CookieMonster> cm(new CookieMonster(NULL, NULL));
374 for (int i = 0; i < more_than_enough_cookies; ++i) {
375 std::string cookie_general = base::StringPrintf("a%03d=b", i);
376 EXPECT_TRUE(SetCookie(cm.get(), url_google_, cookie_general));
377 std::string cookie_specific = base::StringPrintf("c%03d=b", i);
378 EXPECT_TRUE(SetCookie(cm.get(), url_google_specific, cookie_specific));
379 std::string cookies_general = this->GetCookies(cm.get(), url_google_);
380 EXPECT_NE(cookies_general.find(cookie_general), std::string::npos);
381 std::string cookies_specific =
382 this->GetCookies(cm.get(), url_google_specific);
383 EXPECT_NE(cookies_specific.find(cookie_specific), std::string::npos);
384 EXPECT_LE((CountInString(cookies_general, '=') +
385 CountInString(cookies_specific, '=')),
386 domain_max_cookies);
388 // After all this, there should be at least
389 // kDomainMaxCookies - kDomainPurgeCookies for both URLs.
390 std::string cookies_general = this->GetCookies(cm.get(), url_google_);
391 std::string cookies_specific =
392 this->GetCookies(cm.get(), url_google_specific);
393 int total_cookies = (CountInString(cookies_general, '=') +
394 CountInString(cookies_specific, '='));
395 EXPECT_GE(total_cookies, domain_max_cookies - domain_purge_cookies);
396 EXPECT_LE(total_cookies, domain_max_cookies);
400 CookiePriority CharToPriority(char ch) {
401 switch (ch) {
402 case 'L':
403 return COOKIE_PRIORITY_LOW;
404 case 'M':
405 return COOKIE_PRIORITY_MEDIUM;
406 case 'H':
407 return COOKIE_PRIORITY_HIGH;
409 NOTREACHED();
410 return COOKIE_PRIORITY_DEFAULT;
413 // Instantiates a CookieMonster, adds multiple cookies (to url_google_) with
414 // priorities specified by |coded_priority_str|, and tests priority-aware
415 // domain cookie eviction.
416 // |coded_priority_str| specifies a run-length-encoded string of priorities.
417 // Example: "2M 3L M 4H" means "MMLLLMHHHH", and speicifies sequential (i.e.,
418 // from least- to most-recently accessed) insertion of 2 medium-priority
419 // cookies, 3 low-priority cookies, 1 medium-priority cookie, and 4
420 // high-priority cookies.
421 // Within each priority, only the least-accessed cookies should be evicted.
422 // Thus, to describe expected suriving cookies, it suffices to specify the
423 // expected population of surviving cookies per priority, i.e.,
424 // |expected_low_count|, |expected_medium_count|, and |expected_high_count|.
425 void TestPriorityCookieCase(CookieMonster* cm,
426 const std::string& coded_priority_str,
427 size_t expected_low_count,
428 size_t expected_medium_count,
429 size_t expected_high_count) {
430 DeleteAll(cm);
431 int next_cookie_id = 0;
432 std::vector<CookiePriority> priority_list;
433 std::vector<int> id_list[3]; // Indexed by CookiePriority.
435 // Parse |coded_priority_str| and add cookies.
436 std::vector<std::string> priority_tok_list;
437 base::SplitString(coded_priority_str, ' ', &priority_tok_list);
438 for (std::vector<std::string>::iterator it = priority_tok_list.begin();
439 it != priority_tok_list.end(); ++it) {
440 size_t len = it->length();
441 DCHECK_NE(len, 0U);
442 // Take last character as priority.
443 CookiePriority priority = CharToPriority((*it)[len - 1]);
444 std::string priority_str = CookiePriorityToString(priority);
445 // The rest of the string (possibly empty) specifies repetition.
446 int rep = 1;
447 if (!it->empty()) {
448 bool result = base::StringToInt(
449 base::StringPiece(it->begin(), it->end() - 1), &rep);
450 DCHECK(result);
452 for (; rep > 0; --rep, ++next_cookie_id) {
453 std::string cookie = base::StringPrintf(
454 "a%d=b;priority=%s", next_cookie_id, priority_str.c_str());
455 EXPECT_TRUE(SetCookie(cm, url_google_, cookie));
456 priority_list.push_back(priority);
457 id_list[priority].push_back(next_cookie_id);
461 int num_cookies = static_cast<int>(priority_list.size());
462 std::vector<int> surviving_id_list[3]; // Indexed by CookiePriority.
464 // Parse the list of cookies
465 std::string cookie_str = this->GetCookies(cm, url_google_);
466 std::vector<std::string> cookie_tok_list;
467 base::SplitString(cookie_str, ';', &cookie_tok_list);
468 for (std::vector<std::string>::iterator it = cookie_tok_list.begin();
469 it != cookie_tok_list.end(); ++it) {
470 // Assuming *it is "a#=b", so extract and parse "#" portion.
471 int id = -1;
472 bool result = base::StringToInt(
473 base::StringPiece(it->begin() + 1, it->end() - 2), &id);
474 DCHECK(result);
475 DCHECK_GE(id, 0);
476 DCHECK_LT(id, num_cookies);
477 surviving_id_list[priority_list[id]].push_back(id);
480 // Validate each priority.
481 size_t expected_count[3] = {
482 expected_low_count, expected_medium_count, expected_high_count};
483 for (int i = 0; i < 3; ++i) {
484 DCHECK_LE(surviving_id_list[i].size(), id_list[i].size());
485 EXPECT_EQ(expected_count[i], surviving_id_list[i].size());
486 // Verify that the remaining cookies are the most recent among those
487 // with the same priorities.
488 if (expected_count[i] == surviving_id_list[i].size()) {
489 std::sort(surviving_id_list[i].begin(), surviving_id_list[i].end());
490 EXPECT_TRUE(std::equal(surviving_id_list[i].begin(),
491 surviving_id_list[i].end(),
492 id_list[i].end() - expected_count[i]));
497 void TestPriorityAwareGarbageCollectHelper() {
498 // Hard-coding limits in the test, but use DCHECK_EQ to enforce constraint.
499 DCHECK_EQ(180U, CookieMonster::kDomainMaxCookies);
500 DCHECK_EQ(150U, CookieMonster::kDomainMaxCookies -
501 CookieMonster::kDomainPurgeCookies);
502 DCHECK_EQ(30U, CookieMonster::kDomainCookiesQuotaLow);
503 DCHECK_EQ(50U, CookieMonster::kDomainCookiesQuotaMedium);
504 DCHECK_EQ(70U, CookieMonster::kDomainCookiesQuotaHigh);
506 scoped_refptr<CookieMonster> cm(new CookieMonster(NULL, NULL));
508 // Each test case adds 181 cookies, so 31 cookies are evicted.
509 // Cookie same priority, repeated for each priority.
510 TestPriorityCookieCase(cm.get(), "181L", 150U, 0U, 0U);
511 TestPriorityCookieCase(cm.get(), "181M", 0U, 150U, 0U);
512 TestPriorityCookieCase(cm.get(), "181H", 0U, 0U, 150U);
514 // Pairwise scenarios.
515 // Round 1 => none; round2 => 31M; round 3 => none.
516 TestPriorityCookieCase(cm.get(), "10H 171M", 0U, 140U, 10U);
517 // Round 1 => 10L; round2 => 21M; round 3 => none.
518 TestPriorityCookieCase(cm.get(), "141M 40L", 30U, 120U, 0U);
519 // Round 1 => none; round2 => none; round 3 => 31H.
520 TestPriorityCookieCase(cm.get(), "101H 80M", 0U, 80U, 70U);
522 // For {low, medium} priorities right on quota, different orders.
523 // Round 1 => 1L; round 2 => none, round3 => 30L.
524 TestPriorityCookieCase(cm.get(), "31L 50M 100H", 0U, 50U, 100U);
525 // Round 1 => none; round 2 => 1M, round3 => 30M.
526 TestPriorityCookieCase(cm.get(), "51M 100H 30L", 30U, 20U, 100U);
527 // Round 1 => none; round 2 => none; round3 => 31H.
528 TestPriorityCookieCase(cm.get(), "101H 50M 30L", 30U, 50U, 70U);
530 // Round 1 => 10L; round 2 => 10M; round3 => 11H.
531 TestPriorityCookieCase(cm.get(), "81H 60M 40L", 30U, 50U, 70U);
533 // More complex scenarios.
534 // Round 1 => 10L; round 2 => 10M; round 3 => 11H.
535 TestPriorityCookieCase(cm.get(), "21H 60M 40L 60H", 30U, 50U, 70U);
536 // Round 1 => 10L; round 2 => 11M, 10L; round 3 => none.
537 TestPriorityCookieCase(cm.get(), "11H 10M 20L 110M 20L 10H", 20U, 109U,
538 21U);
539 // Round 1 => none; round 2 => none; round 3 => 11L, 10M, 10H.
540 TestPriorityCookieCase(cm.get(), "11L 10M 140H 10M 10L", 10U, 10U, 130U);
541 // Round 1 => none; round 2 => 1M; round 3 => 10L, 10M, 10H.
542 TestPriorityCookieCase(cm.get(), "11M 10H 10L 60M 90H", 0U, 60U, 90U);
543 // Round 1 => none; round 2 => 10L, 21M; round 3 => none.
544 TestPriorityCookieCase(cm.get(), "11M 10H 10L 90M 60H", 0U, 80U, 70U);
547 // Function for creating a CM with a number of cookies in it,
548 // no store (and hence no ability to affect access time).
549 CookieMonster* CreateMonsterForGC(int num_cookies) {
550 CookieMonster* cm(new CookieMonster(NULL, NULL));
551 for (int i = 0; i < num_cookies; i++) {
552 SetCookie(cm, GURL(base::StringPrintf("http://h%05d.izzle", i)), "a=1");
554 return cm;
557 bool IsCookieInList(const CanonicalCookie& cookie, const CookieList& list) {
558 for (CookieList::const_iterator it = list.begin(); it != list.end(); ++it) {
559 if (it->Source() == cookie.Source() && it->Name() == cookie.Name() &&
560 it->Value() == cookie.Value() && it->Domain() == cookie.Domain() &&
561 it->Path() == cookie.Path() &&
562 it->CreationDate() == cookie.CreationDate() &&
563 it->ExpiryDate() == cookie.ExpiryDate() &&
564 it->LastAccessDate() == cookie.LastAccessDate() &&
565 it->IsSecure() == cookie.IsSecure() &&
566 it->IsHttpOnly() == cookie.IsHttpOnly() &&
567 it->Priority() == cookie.Priority()) {
568 return true;
572 return false;
576 // TODO(erikwright): Replace the other callbacks and synchronous helper methods
577 // in this test suite with these Mocks.
578 template <typename T, typename C>
579 class MockCookieCallback {
580 public:
581 C AsCallback() {
582 return base::Bind(&T::Invoke, base::Unretained(static_cast<T*>(this)));
586 class MockGetCookiesCallback
587 : public MockCookieCallback<MockGetCookiesCallback,
588 CookieStore::GetCookiesCallback> {
589 public:
590 MOCK_METHOD1(Invoke, void(const std::string& cookies));
593 class MockSetCookiesCallback
594 : public MockCookieCallback<MockSetCookiesCallback,
595 CookieStore::SetCookiesCallback> {
596 public:
597 MOCK_METHOD1(Invoke, void(bool success));
600 class MockClosure : public MockCookieCallback<MockClosure, base::Closure> {
601 public:
602 MOCK_METHOD0(Invoke, void(void));
605 class MockGetCookieListCallback
606 : public MockCookieCallback<MockGetCookieListCallback,
607 CookieMonster::GetCookieListCallback> {
608 public:
609 MOCK_METHOD1(Invoke, void(const CookieList& cookies));
612 class MockDeleteCallback
613 : public MockCookieCallback<MockDeleteCallback,
614 CookieMonster::DeleteCallback> {
615 public:
616 MOCK_METHOD1(Invoke, void(int num_deleted));
619 class MockDeleteCookieCallback
620 : public MockCookieCallback<MockDeleteCookieCallback,
621 CookieMonster::DeleteCookieCallback> {
622 public:
623 MOCK_METHOD1(Invoke, void(bool success));
626 struct CookiesInputInfo {
627 const GURL url;
628 const std::string name;
629 const std::string value;
630 const std::string domain;
631 const std::string path;
632 const base::Time expiration_time;
633 bool secure;
634 bool http_only;
635 bool first_party_only;
636 CookiePriority priority;
639 ACTION(QuitCurrentMessageLoop) {
640 base::MessageLoop::current()->PostTask(FROM_HERE,
641 base::MessageLoop::QuitClosure());
644 // TODO(erikwright): When the synchronous helpers 'GetCookies' etc. are removed,
645 // rename these, removing the 'Action' suffix.
646 ACTION_P4(DeleteCookieAction, cookie_monster, url, name, callback) {
647 cookie_monster->DeleteCookieAsync(url, name, callback->AsCallback());
649 ACTION_P3(GetCookiesAction, cookie_monster, url, callback) {
650 cookie_monster->GetCookiesWithOptionsAsync(url, CookieOptions(),
651 callback->AsCallback());
653 ACTION_P4(SetCookieAction, cookie_monster, url, cookie_line, callback) {
654 cookie_monster->SetCookieWithOptionsAsync(url, cookie_line, CookieOptions(),
655 callback->AsCallback());
657 ACTION_P3(SetAllCookiesAction, cookie_monster, list, callback) {
658 cookie_monster->SetAllCookiesAsync(list, callback->AsCallback());
660 ACTION_P4(DeleteAllCreatedBetweenAction,
661 cookie_monster,
662 delete_begin,
663 delete_end,
664 callback) {
665 cookie_monster->DeleteAllCreatedBetweenAsync(delete_begin, delete_end,
666 callback->AsCallback());
668 ACTION_P3(SetCookieWithDetailsAction, cookie_monster, cc, callback) {
669 cookie_monster->SetCookieWithDetailsAsync(
670 cc.url, cc.name, cc.value, cc.domain, cc.path, cc.expiration_time,
671 cc.secure, cc.http_only, cc.first_party_only, cc.priority,
672 callback->AsCallback());
675 ACTION_P2(GetAllCookiesAction, cookie_monster, callback) {
676 cookie_monster->GetAllCookiesAsync(callback->AsCallback());
679 ACTION_P3(DeleteAllForHostAction, cookie_monster, url, callback) {
680 cookie_monster->DeleteAllForHostAsync(url, callback->AsCallback());
683 ACTION_P3(DeleteCanonicalCookieAction, cookie_monster, cookie, callback) {
684 cookie_monster->DeleteCanonicalCookieAsync(cookie, callback->AsCallback());
687 ACTION_P2(DeleteAllAction, cookie_monster, callback) {
688 cookie_monster->DeleteAllAsync(callback->AsCallback());
691 ACTION_P3(GetAllCookiesForUrlWithOptionsAction, cookie_monster, url, callback) {
692 cookie_monster->GetAllCookiesForURLWithOptionsAsync(url, CookieOptions(),
693 callback->AsCallback());
696 ACTION_P3(GetAllCookiesForUrlAction, cookie_monster, url, callback) {
697 cookie_monster->GetAllCookiesForURLAsync(url, callback->AsCallback());
700 ACTION_P(PushCallbackAction, callback_vector) {
701 callback_vector->push(arg1);
704 ACTION_P2(DeleteSessionCookiesAction, cookie_monster, callback) {
705 cookie_monster->DeleteSessionCookiesAsync(callback->AsCallback());
708 } // namespace
710 // This test suite verifies the task deferral behaviour of the CookieMonster.
711 // Specifically, for each asynchronous method, verify that:
712 // 1. invoking it on an uninitialized cookie store causes the store to begin
713 // chain-loading its backing data or loading data for a specific domain key
714 // (eTLD+1).
715 // 2. The initial invocation does not complete until the loading completes.
716 // 3. Invocations after the loading has completed complete immediately.
717 class DeferredCookieTaskTest : public CookieMonsterTest {
718 protected:
719 DeferredCookieTaskTest() {
720 persistent_store_ = new NewMockPersistentCookieStore();
721 cookie_monster_ = new CookieMonster(persistent_store_.get(), NULL);
724 // Defines a cookie to be returned from PersistentCookieStore::Load
725 void DeclareLoadedCookie(const std::string& key,
726 const std::string& cookie_line,
727 const base::Time& creation_time) {
728 AddCookieToList(key, cookie_line, creation_time, &loaded_cookies_);
731 // Runs the message loop, waiting until PersistentCookieStore::Load is called.
732 // Call CompleteLoadingAndWait to cause the load to complete.
733 void WaitForLoadCall() {
734 RunFor(kTimeout);
736 // Verify that PeristentStore::Load was called.
737 testing::Mock::VerifyAndClear(persistent_store_.get());
740 // Invokes the PersistentCookieStore::LoadCookiesForKey completion callbacks
741 // and PersistentCookieStore::Load completion callback and waits
742 // until the message loop is quit.
743 void CompleteLoadingAndWait() {
744 while (!loaded_for_key_callbacks_.empty()) {
745 loaded_for_key_callbacks_.front().Run(loaded_cookies_);
746 loaded_cookies_.clear();
747 loaded_for_key_callbacks_.pop();
750 loaded_callback_.Run(loaded_cookies_);
751 RunFor(kTimeout);
754 // Performs the provided action, expecting it to cause a call to
755 // PersistentCookieStore::Load. Call WaitForLoadCall to verify the load call
756 // is received.
757 void BeginWith(testing::Action<void(void)> action) {
758 EXPECT_CALL(*this, Begin()).WillOnce(action);
759 ExpectLoadCall();
760 Begin();
763 void BeginWithForDomainKey(std::string key,
764 testing::Action<void(void)> action) {
765 EXPECT_CALL(*this, Begin()).WillOnce(action);
766 ExpectLoadCall();
767 ExpectLoadForKeyCall(key, false);
768 Begin();
771 // Declares an expectation that PersistentCookieStore::Load will be called,
772 // saving the provided callback and sending a quit to the message loop.
773 void ExpectLoadCall() {
774 EXPECT_CALL(*persistent_store_.get(), Load(testing::_))
775 .WillOnce(testing::DoAll(testing::SaveArg<0>(&loaded_callback_),
776 QuitCurrentMessageLoop()));
779 // Declares an expectation that PersistentCookieStore::LoadCookiesForKey
780 // will be called, saving the provided callback and sending a quit to the
781 // message loop.
782 void ExpectLoadForKeyCall(std::string key, bool quit_queue) {
783 if (quit_queue)
784 EXPECT_CALL(*persistent_store_.get(), LoadCookiesForKey(key, testing::_))
785 .WillOnce(
786 testing::DoAll(PushCallbackAction(&loaded_for_key_callbacks_),
787 QuitCurrentMessageLoop()));
788 else
789 EXPECT_CALL(*persistent_store_.get(), LoadCookiesForKey(key, testing::_))
790 .WillOnce(PushCallbackAction(&loaded_for_key_callbacks_));
793 // Invokes the initial action.
794 MOCK_METHOD0(Begin, void(void));
796 // Returns the CookieMonster instance under test.
797 CookieMonster& cookie_monster() { return *cookie_monster_.get(); }
799 private:
800 // Declares that mock expectations in this test suite are strictly ordered.
801 testing::InSequence in_sequence_;
802 // Holds cookies to be returned from PersistentCookieStore::Load or
803 // PersistentCookieStore::LoadCookiesForKey.
804 std::vector<CanonicalCookie*> loaded_cookies_;
805 // Stores the callback passed from the CookieMonster to the
806 // PersistentCookieStore::Load
807 CookieMonster::PersistentCookieStore::LoadedCallback loaded_callback_;
808 // Stores the callback passed from the CookieMonster to the
809 // PersistentCookieStore::LoadCookiesForKey
810 std::queue<CookieMonster::PersistentCookieStore::LoadedCallback>
811 loaded_for_key_callbacks_;
813 // Stores the CookieMonster under test.
814 scoped_refptr<CookieMonster> cookie_monster_;
815 // Stores the mock PersistentCookieStore.
816 scoped_refptr<NewMockPersistentCookieStore> persistent_store_;
819 TEST_F(DeferredCookieTaskTest, DeferredGetCookies) {
820 DeclareLoadedCookie("www.google.izzle",
821 "X=1; path=/; expires=Mon, 18-Apr-22 22:50:14 GMT",
822 Time::Now() + TimeDelta::FromDays(3));
824 MockGetCookiesCallback get_cookies_callback;
826 BeginWithForDomainKey(
827 "google.izzle",
828 GetCookiesAction(&cookie_monster(), url_google_, &get_cookies_callback));
830 WaitForLoadCall();
832 EXPECT_CALL(get_cookies_callback, Invoke("X=1"))
833 .WillOnce(GetCookiesAction(&cookie_monster(), url_google_,
834 &get_cookies_callback));
835 EXPECT_CALL(get_cookies_callback, Invoke("X=1"))
836 .WillOnce(QuitCurrentMessageLoop());
838 CompleteLoadingAndWait();
841 TEST_F(DeferredCookieTaskTest, DeferredSetCookie) {
842 MockSetCookiesCallback set_cookies_callback;
844 BeginWithForDomainKey("google.izzle",
845 SetCookieAction(&cookie_monster(), url_google_, "A=B",
846 &set_cookies_callback));
848 WaitForLoadCall();
850 EXPECT_CALL(set_cookies_callback, Invoke(true))
851 .WillOnce(SetCookieAction(&cookie_monster(), url_google_, "X=Y",
852 &set_cookies_callback));
853 EXPECT_CALL(set_cookies_callback, Invoke(true))
854 .WillOnce(QuitCurrentMessageLoop());
856 CompleteLoadingAndWait();
859 TEST_F(DeferredCookieTaskTest, DeferredSetAllCookies) {
860 MockSetCookiesCallback set_cookies_callback;
861 CookieList list;
862 list.push_back(CanonicalCookie(url_google_, "A", "B", "google.izzle", "/",
863 base::Time::Now(), base::Time(), base::Time(),
864 false, true, false, COOKIE_PRIORITY_DEFAULT));
865 list.push_back(CanonicalCookie(url_google_, "C", "D", "google.izzle", "/",
866 base::Time::Now(), base::Time(), base::Time(),
867 false, true, false, COOKIE_PRIORITY_DEFAULT));
869 BeginWith(
870 SetAllCookiesAction(&cookie_monster(), list, &set_cookies_callback));
872 WaitForLoadCall();
874 EXPECT_CALL(set_cookies_callback, Invoke(true))
875 .WillOnce(
876 SetAllCookiesAction(&cookie_monster(), list, &set_cookies_callback));
877 EXPECT_CALL(set_cookies_callback, Invoke(true))
878 .WillOnce(QuitCurrentMessageLoop());
880 CompleteLoadingAndWait();
883 TEST_F(DeferredCookieTaskTest, DeferredDeleteCookie) {
884 MockClosure delete_cookie_callback;
886 BeginWithForDomainKey("google.izzle",
887 DeleteCookieAction(&cookie_monster(), url_google_, "A",
888 &delete_cookie_callback));
890 WaitForLoadCall();
892 EXPECT_CALL(delete_cookie_callback, Invoke())
893 .WillOnce(DeleteCookieAction(&cookie_monster(), url_google_, "X",
894 &delete_cookie_callback));
895 EXPECT_CALL(delete_cookie_callback, Invoke())
896 .WillOnce(QuitCurrentMessageLoop());
898 CompleteLoadingAndWait();
901 TEST_F(DeferredCookieTaskTest, DeferredSetCookieWithDetails) {
902 MockSetCookiesCallback set_cookies_callback;
904 CookiesInputInfo cookie_info = {url_google_foo_,
905 "A",
906 "B",
907 std::string(),
908 "/foo",
909 base::Time(),
910 false,
911 false,
912 false,
913 COOKIE_PRIORITY_DEFAULT};
914 BeginWithForDomainKey(
915 "google.izzle", SetCookieWithDetailsAction(&cookie_monster(), cookie_info,
916 &set_cookies_callback));
918 WaitForLoadCall();
920 CookiesInputInfo cookie_info_exp = {url_google_foo_,
921 "A",
922 "B",
923 std::string(),
924 "/foo",
925 base::Time(),
926 false,
927 false,
928 false,
929 COOKIE_PRIORITY_DEFAULT};
930 EXPECT_CALL(set_cookies_callback, Invoke(true))
931 .WillOnce(SetCookieWithDetailsAction(&cookie_monster(), cookie_info_exp,
932 &set_cookies_callback));
933 EXPECT_CALL(set_cookies_callback, Invoke(true))
934 .WillOnce(QuitCurrentMessageLoop());
936 CompleteLoadingAndWait();
939 TEST_F(DeferredCookieTaskTest, DeferredGetAllCookies) {
940 DeclareLoadedCookie("www.google.izzle",
941 "X=1; path=/; expires=Mon, 18-Apr-22 22:50:14 GMT",
942 Time::Now() + TimeDelta::FromDays(3));
944 MockGetCookieListCallback get_cookie_list_callback;
946 BeginWith(GetAllCookiesAction(&cookie_monster(), &get_cookie_list_callback));
948 WaitForLoadCall();
950 EXPECT_CALL(get_cookie_list_callback, Invoke(testing::_))
951 .WillOnce(
952 GetAllCookiesAction(&cookie_monster(), &get_cookie_list_callback));
953 EXPECT_CALL(get_cookie_list_callback, Invoke(testing::_))
954 .WillOnce(QuitCurrentMessageLoop());
956 CompleteLoadingAndWait();
959 TEST_F(DeferredCookieTaskTest, DeferredGetAllForUrlCookies) {
960 DeclareLoadedCookie("www.google.izzle",
961 "X=1; path=/; expires=Mon, 18-Apr-22 22:50:14 GMT",
962 Time::Now() + TimeDelta::FromDays(3));
964 MockGetCookieListCallback get_cookie_list_callback;
966 BeginWithForDomainKey(
967 "google.izzle", GetAllCookiesForUrlAction(&cookie_monster(), url_google_,
968 &get_cookie_list_callback));
970 WaitForLoadCall();
972 EXPECT_CALL(get_cookie_list_callback, Invoke(testing::_))
973 .WillOnce(GetAllCookiesForUrlAction(&cookie_monster(), url_google_,
974 &get_cookie_list_callback));
975 EXPECT_CALL(get_cookie_list_callback, Invoke(testing::_))
976 .WillOnce(QuitCurrentMessageLoop());
978 CompleteLoadingAndWait();
981 TEST_F(DeferredCookieTaskTest, DeferredGetAllForUrlWithOptionsCookies) {
982 DeclareLoadedCookie("www.google.izzle",
983 "X=1; path=/; expires=Mon, 18-Apr-22 22:50:14 GMT",
984 Time::Now() + TimeDelta::FromDays(3));
986 MockGetCookieListCallback get_cookie_list_callback;
988 BeginWithForDomainKey("google.izzle", GetAllCookiesForUrlWithOptionsAction(
989 &cookie_monster(), url_google_,
990 &get_cookie_list_callback));
992 WaitForLoadCall();
994 EXPECT_CALL(get_cookie_list_callback, Invoke(testing::_))
995 .WillOnce(GetAllCookiesForUrlWithOptionsAction(
996 &cookie_monster(), url_google_, &get_cookie_list_callback));
997 EXPECT_CALL(get_cookie_list_callback, Invoke(testing::_))
998 .WillOnce(QuitCurrentMessageLoop());
1000 CompleteLoadingAndWait();
1003 TEST_F(DeferredCookieTaskTest, DeferredDeleteAllCookies) {
1004 MockDeleteCallback delete_callback;
1006 BeginWith(DeleteAllAction(&cookie_monster(), &delete_callback));
1008 WaitForLoadCall();
1010 EXPECT_CALL(delete_callback, Invoke(false))
1011 .WillOnce(DeleteAllAction(&cookie_monster(), &delete_callback));
1012 EXPECT_CALL(delete_callback, Invoke(false))
1013 .WillOnce(QuitCurrentMessageLoop());
1015 CompleteLoadingAndWait();
1018 TEST_F(DeferredCookieTaskTest, DeferredDeleteAllCreatedBetweenCookies) {
1019 MockDeleteCallback delete_callback;
1021 BeginWith(DeleteAllCreatedBetweenAction(&cookie_monster(), base::Time(),
1022 base::Time::Now(), &delete_callback));
1024 WaitForLoadCall();
1026 EXPECT_CALL(delete_callback, Invoke(false))
1027 .WillOnce(DeleteAllCreatedBetweenAction(&cookie_monster(), base::Time(),
1028 base::Time::Now(),
1029 &delete_callback));
1030 EXPECT_CALL(delete_callback, Invoke(false))
1031 .WillOnce(QuitCurrentMessageLoop());
1033 CompleteLoadingAndWait();
1036 TEST_F(DeferredCookieTaskTest, DeferredDeleteAllForHostCookies) {
1037 MockDeleteCallback delete_callback;
1039 BeginWithForDomainKey(
1040 "google.izzle",
1041 DeleteAllForHostAction(&cookie_monster(), url_google_, &delete_callback));
1043 WaitForLoadCall();
1045 EXPECT_CALL(delete_callback, Invoke(false))
1046 .WillOnce(DeleteAllForHostAction(&cookie_monster(), url_google_,
1047 &delete_callback));
1048 EXPECT_CALL(delete_callback, Invoke(false))
1049 .WillOnce(QuitCurrentMessageLoop());
1051 CompleteLoadingAndWait();
1054 TEST_F(DeferredCookieTaskTest, DeferredDeleteCanonicalCookie) {
1055 std::vector<CanonicalCookie*> cookies;
1056 CanonicalCookie cookie =
1057 BuildCanonicalCookie("www.google.com", "X=1; path=/", base::Time::Now());
1059 MockDeleteCookieCallback delete_cookie_callback;
1061 BeginWith(DeleteCanonicalCookieAction(&cookie_monster(), cookie,
1062 &delete_cookie_callback));
1064 WaitForLoadCall();
1066 EXPECT_CALL(delete_cookie_callback, Invoke(false))
1067 .WillOnce(DeleteCanonicalCookieAction(&cookie_monster(), cookie,
1068 &delete_cookie_callback));
1069 EXPECT_CALL(delete_cookie_callback, Invoke(false))
1070 .WillOnce(QuitCurrentMessageLoop());
1072 CompleteLoadingAndWait();
1075 TEST_F(DeferredCookieTaskTest, DeferredDeleteSessionCookies) {
1076 MockDeleteCallback delete_callback;
1078 BeginWith(DeleteSessionCookiesAction(&cookie_monster(), &delete_callback));
1080 WaitForLoadCall();
1082 EXPECT_CALL(delete_callback, Invoke(false))
1083 .WillOnce(
1084 DeleteSessionCookiesAction(&cookie_monster(), &delete_callback));
1085 EXPECT_CALL(delete_callback, Invoke(false))
1086 .WillOnce(QuitCurrentMessageLoop());
1088 CompleteLoadingAndWait();
1091 // Verify that a series of queued tasks are executed in order upon loading of
1092 // the backing store and that new tasks received while the queued tasks are
1093 // being dispatched go to the end of the queue.
1094 TEST_F(DeferredCookieTaskTest, DeferredTaskOrder) {
1095 DeclareLoadedCookie("www.google.izzle",
1096 "X=1; path=/; expires=Mon, 18-Apr-22 22:50:14 GMT",
1097 Time::Now() + TimeDelta::FromDays(3));
1099 MockGetCookiesCallback get_cookies_callback;
1100 MockSetCookiesCallback set_cookies_callback;
1101 MockGetCookiesCallback get_cookies_callback_deferred;
1103 EXPECT_CALL(*this, Begin())
1104 .WillOnce(testing::DoAll(GetCookiesAction(&cookie_monster(), url_google_,
1105 &get_cookies_callback),
1106 SetCookieAction(&cookie_monster(), url_google_,
1107 "A=B", &set_cookies_callback)));
1108 ExpectLoadCall();
1109 ExpectLoadForKeyCall("google.izzle", false);
1110 Begin();
1112 WaitForLoadCall();
1113 EXPECT_CALL(get_cookies_callback, Invoke("X=1"))
1114 .WillOnce(GetCookiesAction(&cookie_monster(), url_google_,
1115 &get_cookies_callback_deferred));
1116 EXPECT_CALL(set_cookies_callback, Invoke(true));
1117 EXPECT_CALL(get_cookies_callback_deferred, Invoke("A=B; X=1"))
1118 .WillOnce(QuitCurrentMessageLoop());
1120 CompleteLoadingAndWait();
1123 TEST_F(CookieMonsterTest, TestCookieDeleteAll) {
1124 scoped_refptr<MockPersistentCookieStore> store(new MockPersistentCookieStore);
1125 scoped_refptr<CookieMonster> cm(new CookieMonster(store.get(), NULL));
1126 CookieOptions options;
1127 options.set_include_httponly();
1129 EXPECT_TRUE(SetCookie(cm.get(), url_google_, kValidCookieLine));
1130 EXPECT_EQ("A=B", GetCookies(cm.get(), url_google_));
1132 EXPECT_TRUE(
1133 SetCookieWithOptions(cm.get(), url_google_, "C=D; httponly", options));
1134 EXPECT_EQ("A=B; C=D", GetCookiesWithOptions(cm.get(), url_google_, options));
1136 EXPECT_EQ(2, DeleteAll(cm.get()));
1137 EXPECT_EQ("", GetCookiesWithOptions(cm.get(), url_google_, options));
1138 EXPECT_EQ(0u, store->commands().size());
1140 // Create a persistent cookie.
1141 EXPECT_TRUE(SetCookie(
1142 cm.get(), url_google_,
1143 std::string(kValidCookieLine) + "; expires=Mon, 18-Apr-22 22:50:13 GMT"));
1144 ASSERT_EQ(1u, store->commands().size());
1145 EXPECT_EQ(CookieStoreCommand::ADD, store->commands()[0].type);
1147 EXPECT_EQ(1, DeleteAll(cm.get())); // sync_to_store = true.
1148 ASSERT_EQ(2u, store->commands().size());
1149 EXPECT_EQ(CookieStoreCommand::REMOVE, store->commands()[1].type);
1151 EXPECT_EQ("", GetCookiesWithOptions(cm.get(), url_google_, options));
1154 TEST_F(CookieMonsterTest, TestCookieDeleteAllCreatedBetweenTimestamps) {
1155 scoped_refptr<CookieMonster> cm(new CookieMonster(NULL, NULL));
1156 Time now = Time::Now();
1158 // Nothing has been added so nothing should be deleted.
1159 EXPECT_EQ(0, DeleteAllCreatedBetween(cm.get(), now - TimeDelta::FromDays(99),
1160 Time()));
1162 // Create 3 cookies with creation date of today, yesterday and the day before.
1163 EXPECT_TRUE(cm->SetCookieWithCreationTime(url_google_, "T-0=Now", now));
1164 EXPECT_TRUE(cm->SetCookieWithCreationTime(url_google_, "T-1=Yesterday",
1165 now - TimeDelta::FromDays(1)));
1166 EXPECT_TRUE(cm->SetCookieWithCreationTime(url_google_, "T-2=DayBefore",
1167 now - TimeDelta::FromDays(2)));
1168 EXPECT_TRUE(cm->SetCookieWithCreationTime(url_google_, "T-3=ThreeDays",
1169 now - TimeDelta::FromDays(3)));
1170 EXPECT_TRUE(cm->SetCookieWithCreationTime(url_google_, "T-7=LastWeek",
1171 now - TimeDelta::FromDays(7)));
1173 // Try to delete threedays and the daybefore.
1174 EXPECT_EQ(2, DeleteAllCreatedBetween(cm.get(), now - TimeDelta::FromDays(3),
1175 now - TimeDelta::FromDays(1)));
1177 // Try to delete yesterday, also make sure that delete_end is not
1178 // inclusive.
1179 EXPECT_EQ(
1180 1, DeleteAllCreatedBetween(cm.get(), now - TimeDelta::FromDays(2), now));
1182 // Make sure the delete_begin is inclusive.
1183 EXPECT_EQ(
1184 1, DeleteAllCreatedBetween(cm.get(), now - TimeDelta::FromDays(7), now));
1186 // Delete the last (now) item.
1187 EXPECT_EQ(1, DeleteAllCreatedBetween(cm.get(), Time(), Time()));
1189 // Really make sure everything is gone.
1190 EXPECT_EQ(0, DeleteAll(cm.get()));
1193 static const int kAccessDelayMs = kLastAccessThresholdMilliseconds + 20;
1195 TEST_F(CookieMonsterTest, TestLastAccess) {
1196 scoped_refptr<CookieMonster> cm(
1197 new CookieMonster(NULL, NULL, kLastAccessThresholdMilliseconds));
1199 EXPECT_TRUE(SetCookie(cm.get(), url_google_, "A=B"));
1200 const Time last_access_date(GetFirstCookieAccessDate(cm.get()));
1202 // Reading the cookie again immediately shouldn't update the access date,
1203 // since we're inside the threshold.
1204 EXPECT_EQ("A=B", GetCookies(cm.get(), url_google_));
1205 EXPECT_TRUE(last_access_date == GetFirstCookieAccessDate(cm.get()));
1207 // Reading after a short wait should update the access date.
1208 base::PlatformThread::Sleep(
1209 base::TimeDelta::FromMilliseconds(kAccessDelayMs));
1210 EXPECT_EQ("A=B", GetCookies(cm.get(), url_google_));
1211 EXPECT_FALSE(last_access_date == GetFirstCookieAccessDate(cm.get()));
1214 TEST_F(CookieMonsterTest, TestHostGarbageCollection) {
1215 TestHostGarbageCollectHelper();
1218 TEST_F(CookieMonsterTest, TestPriorityAwareGarbageCollection) {
1219 TestPriorityAwareGarbageCollectHelper();
1222 TEST_F(CookieMonsterTest, TestDeleteSingleCookie) {
1223 scoped_refptr<CookieMonster> cm(new CookieMonster(NULL, NULL));
1225 EXPECT_TRUE(SetCookie(cm.get(), url_google_, "A=B"));
1226 EXPECT_TRUE(SetCookie(cm.get(), url_google_, "C=D"));
1227 EXPECT_TRUE(SetCookie(cm.get(), url_google_, "E=F"));
1228 EXPECT_EQ("A=B; C=D; E=F", GetCookies(cm.get(), url_google_));
1230 EXPECT_TRUE(FindAndDeleteCookie(cm.get(), url_google_.host(), "C"));
1231 EXPECT_EQ("A=B; E=F", GetCookies(cm.get(), url_google_));
1233 EXPECT_FALSE(FindAndDeleteCookie(cm.get(), "random.host", "E"));
1234 EXPECT_EQ("A=B; E=F", GetCookies(cm.get(), url_google_));
1237 TEST_F(CookieMonsterTest, SetCookieableSchemes) {
1238 scoped_refptr<CookieMonster> cm(new CookieMonster(NULL, NULL));
1239 scoped_refptr<CookieMonster> cm_foo(new CookieMonster(NULL, NULL));
1241 // Only cm_foo should allow foo:// cookies.
1242 const char* const kSchemes[] = {"foo"};
1243 cm_foo->SetCookieableSchemes(kSchemes, 1);
1245 GURL foo_url("foo://host/path");
1246 GURL http_url("http://host/path");
1248 EXPECT_TRUE(SetCookie(cm.get(), http_url, "x=1"));
1249 EXPECT_FALSE(SetCookie(cm.get(), foo_url, "x=1"));
1250 EXPECT_TRUE(SetCookie(cm_foo.get(), foo_url, "x=1"));
1251 EXPECT_FALSE(SetCookie(cm_foo.get(), http_url, "x=1"));
1254 TEST_F(CookieMonsterTest, GetAllCookiesForURL) {
1255 scoped_refptr<CookieMonster> cm(
1256 new CookieMonster(NULL, NULL, kLastAccessThresholdMilliseconds));
1258 // Create an httponly cookie.
1259 CookieOptions options;
1260 options.set_include_httponly();
1262 EXPECT_TRUE(
1263 SetCookieWithOptions(cm.get(), url_google_, "A=B; httponly", options));
1264 EXPECT_TRUE(SetCookieWithOptions(cm.get(), url_google_,
1265 "C=D; domain=.google.izzle", options));
1266 EXPECT_TRUE(SetCookieWithOptions(cm.get(), url_google_secure_,
1267 "E=F; domain=.google.izzle; secure",
1268 options));
1270 const Time last_access_date(GetFirstCookieAccessDate(cm.get()));
1272 base::PlatformThread::Sleep(
1273 base::TimeDelta::FromMilliseconds(kAccessDelayMs));
1275 // Check cookies for url.
1276 CookieList cookies = GetAllCookiesForURL(cm.get(), url_google_);
1277 CookieList::iterator it = cookies.begin();
1279 ASSERT_TRUE(it != cookies.end());
1280 EXPECT_EQ("www.google.izzle", it->Domain());
1281 EXPECT_EQ("A", it->Name());
1283 ASSERT_TRUE(++it != cookies.end());
1284 EXPECT_EQ(".google.izzle", it->Domain());
1285 EXPECT_EQ("C", it->Name());
1287 ASSERT_TRUE(++it == cookies.end());
1289 // Check cookies for url excluding http-only cookies.
1290 cookies =
1291 GetAllCookiesForURLWithOptions(cm.get(), url_google_, CookieOptions());
1292 it = cookies.begin();
1294 ASSERT_TRUE(it != cookies.end());
1295 EXPECT_EQ(".google.izzle", it->Domain());
1296 EXPECT_EQ("C", it->Name());
1298 ASSERT_TRUE(++it == cookies.end());
1300 // Test secure cookies.
1301 cookies = GetAllCookiesForURL(cm.get(), url_google_secure_);
1302 it = cookies.begin();
1304 ASSERT_TRUE(it != cookies.end());
1305 EXPECT_EQ("www.google.izzle", it->Domain());
1306 EXPECT_EQ("A", it->Name());
1308 ASSERT_TRUE(++it != cookies.end());
1309 EXPECT_EQ(".google.izzle", it->Domain());
1310 EXPECT_EQ("C", it->Name());
1312 ASSERT_TRUE(++it != cookies.end());
1313 EXPECT_EQ(".google.izzle", it->Domain());
1314 EXPECT_EQ("E", it->Name());
1316 ASSERT_TRUE(++it == cookies.end());
1318 // Reading after a short wait should not update the access date.
1319 EXPECT_TRUE(last_access_date == GetFirstCookieAccessDate(cm.get()));
1322 TEST_F(CookieMonsterTest, GetAllCookiesForURLPathMatching) {
1323 scoped_refptr<CookieMonster> cm(new CookieMonster(NULL, NULL));
1324 CookieOptions options;
1326 EXPECT_TRUE(SetCookieWithOptions(cm.get(), url_google_foo_, "A=B; path=/foo;",
1327 options));
1328 EXPECT_TRUE(SetCookieWithOptions(cm.get(), url_google_bar_, "C=D; path=/bar;",
1329 options));
1330 EXPECT_TRUE(SetCookieWithOptions(cm.get(), url_google_, "E=F;", options));
1332 CookieList cookies = GetAllCookiesForURL(cm.get(), url_google_foo_);
1333 CookieList::iterator it = cookies.begin();
1335 ASSERT_TRUE(it != cookies.end());
1336 EXPECT_EQ("A", it->Name());
1337 EXPECT_EQ("/foo", it->Path());
1339 ASSERT_TRUE(++it != cookies.end());
1340 EXPECT_EQ("E", it->Name());
1341 EXPECT_EQ("/", it->Path());
1343 ASSERT_TRUE(++it == cookies.end());
1345 cookies = GetAllCookiesForURL(cm.get(), url_google_bar_);
1346 it = cookies.begin();
1348 ASSERT_TRUE(it != cookies.end());
1349 EXPECT_EQ("C", it->Name());
1350 EXPECT_EQ("/bar", it->Path());
1352 ASSERT_TRUE(++it != cookies.end());
1353 EXPECT_EQ("E", it->Name());
1354 EXPECT_EQ("/", it->Path());
1356 ASSERT_TRUE(++it == cookies.end());
1359 TEST_F(CookieMonsterTest, DeleteCookieByName) {
1360 scoped_refptr<CookieMonster> cm(new CookieMonster(NULL, NULL));
1362 EXPECT_TRUE(SetCookie(cm.get(), url_google_, "A=A1; path=/"));
1363 EXPECT_TRUE(SetCookie(cm.get(), url_google_, "A=A2; path=/foo"));
1364 EXPECT_TRUE(SetCookie(cm.get(), url_google_, "A=A3; path=/bar"));
1365 EXPECT_TRUE(SetCookie(cm.get(), url_google_, "B=B1; path=/"));
1366 EXPECT_TRUE(SetCookie(cm.get(), url_google_, "B=B2; path=/foo"));
1367 EXPECT_TRUE(SetCookie(cm.get(), url_google_, "B=B3; path=/bar"));
1369 DeleteCookie(cm.get(), GURL(std::string(kUrlGoogle) + "/foo/bar"), "A");
1371 CookieList cookies = GetAllCookies(cm.get());
1372 size_t expected_size = 4;
1373 EXPECT_EQ(expected_size, cookies.size());
1374 for (CookieList::iterator it = cookies.begin(); it != cookies.end(); ++it) {
1375 EXPECT_NE("A1", it->Value());
1376 EXPECT_NE("A2", it->Value());
1380 TEST_F(CookieMonsterTest, ImportCookiesFromCookieMonster) {
1381 scoped_refptr<CookieMonster> cm_1(new CookieMonster(NULL, NULL));
1382 CookieOptions options;
1384 EXPECT_TRUE(SetCookieWithOptions(cm_1.get(), url_google_foo_,
1385 "A1=B; path=/foo;", options));
1386 EXPECT_TRUE(SetCookieWithOptions(cm_1.get(), url_google_bar_,
1387 "A2=D; path=/bar;", options));
1388 EXPECT_TRUE(SetCookieWithOptions(cm_1.get(), url_google_, "A3=F;", options));
1390 CookieList cookies_1 = GetAllCookies(cm_1.get());
1391 scoped_refptr<CookieMonster> cm_2(new CookieMonster(NULL, NULL));
1392 ASSERT_TRUE(cm_2->ImportCookies(cookies_1));
1393 CookieList cookies_2 = GetAllCookies(cm_2.get());
1395 size_t expected_size = 3;
1396 EXPECT_EQ(expected_size, cookies_2.size());
1398 CookieList::iterator it = cookies_2.begin();
1400 ASSERT_TRUE(it != cookies_2.end());
1401 EXPECT_EQ("A1", it->Name());
1402 EXPECT_EQ("/foo", it->Path());
1404 ASSERT_TRUE(++it != cookies_2.end());
1405 EXPECT_EQ("A2", it->Name());
1406 EXPECT_EQ("/bar", it->Path());
1408 ASSERT_TRUE(++it != cookies_2.end());
1409 EXPECT_EQ("A3", it->Name());
1410 EXPECT_EQ("/", it->Path());
1413 // Tests importing from a persistent cookie store that contains duplicate
1414 // equivalent cookies. This situation should be handled by removing the
1415 // duplicate cookie (both from the in-memory cache, and from the backing store).
1417 // This is a regression test for: http://crbug.com/17855.
1418 TEST_F(CookieMonsterTest, DontImportDuplicateCookies) {
1419 scoped_refptr<MockPersistentCookieStore> store(new MockPersistentCookieStore);
1421 // We will fill some initial cookies into the PersistentCookieStore,
1422 // to simulate a database with 4 duplicates. Note that we need to
1423 // be careful not to have any duplicate creation times at all (as it's a
1424 // violation of a CookieMonster invariant) even if Time::Now() doesn't
1425 // move between calls.
1426 std::vector<CanonicalCookie*> initial_cookies;
1428 // Insert 4 cookies with name "X" on path "/", with varying creation
1429 // dates. We expect only the most recent one to be preserved following
1430 // the import.
1432 AddCookieToList("www.google.com",
1433 "X=1; path=/; expires=Mon, 18-Apr-22 22:50:14 GMT",
1434 Time::Now() + TimeDelta::FromDays(3), &initial_cookies);
1436 AddCookieToList("www.google.com",
1437 "X=2; path=/; expires=Mon, 18-Apr-22 22:50:14 GMT",
1438 Time::Now() + TimeDelta::FromDays(1), &initial_cookies);
1440 // ===> This one is the WINNER (biggest creation time). <====
1441 AddCookieToList("www.google.com",
1442 "X=3; path=/; expires=Mon, 18-Apr-22 22:50:14 GMT",
1443 Time::Now() + TimeDelta::FromDays(4), &initial_cookies);
1445 AddCookieToList("www.google.com",
1446 "X=4; path=/; expires=Mon, 18-Apr-22 22:50:14 GMT",
1447 Time::Now(), &initial_cookies);
1449 // Insert 2 cookies with name "X" on path "/2", with varying creation
1450 // dates. We expect only the most recent one to be preserved the import.
1452 // ===> This one is the WINNER (biggest creation time). <====
1453 AddCookieToList("www.google.com",
1454 "X=a1; path=/2; expires=Mon, 18-Apr-22 22:50:14 GMT",
1455 Time::Now() + TimeDelta::FromDays(9), &initial_cookies);
1457 AddCookieToList("www.google.com",
1458 "X=a2; path=/2; expires=Mon, 18-Apr-22 22:50:14 GMT",
1459 Time::Now() + TimeDelta::FromDays(2), &initial_cookies);
1461 // Insert 1 cookie with name "Y" on path "/".
1462 AddCookieToList("www.google.com",
1463 "Y=a; path=/; expires=Mon, 18-Apr-22 22:50:14 GMT",
1464 Time::Now() + TimeDelta::FromDays(10), &initial_cookies);
1466 // Inject our initial cookies into the mock PersistentCookieStore.
1467 store->SetLoadExpectation(true, initial_cookies);
1469 scoped_refptr<CookieMonster> cm(new CookieMonster(store.get(), NULL));
1471 // Verify that duplicates were not imported for path "/".
1472 // (If this had failed, GetCookies() would have also returned X=1, X=2, X=4).
1473 EXPECT_EQ("X=3; Y=a", GetCookies(cm.get(), GURL("http://www.google.com/")));
1475 // Verify that same-named cookie on a different path ("/x2") didn't get
1476 // messed up.
1477 EXPECT_EQ("X=a1; X=3; Y=a",
1478 GetCookies(cm.get(), GURL("http://www.google.com/2/x")));
1480 // Verify that the PersistentCookieStore was told to kill its 4 duplicates.
1481 ASSERT_EQ(4u, store->commands().size());
1482 EXPECT_EQ(CookieStoreCommand::REMOVE, store->commands()[0].type);
1483 EXPECT_EQ(CookieStoreCommand::REMOVE, store->commands()[1].type);
1484 EXPECT_EQ(CookieStoreCommand::REMOVE, store->commands()[2].type);
1485 EXPECT_EQ(CookieStoreCommand::REMOVE, store->commands()[3].type);
1488 // Tests importing from a persistent cookie store that contains cookies
1489 // with duplicate creation times. This situation should be handled by
1490 // dropping the cookies before insertion/visibility to user.
1492 // This is a regression test for: http://crbug.com/43188.
1493 TEST_F(CookieMonsterTest, DontImportDuplicateCreationTimes) {
1494 scoped_refptr<MockPersistentCookieStore> store(new MockPersistentCookieStore);
1496 Time now(Time::Now());
1497 Time earlier(now - TimeDelta::FromDays(1));
1499 // Insert 8 cookies, four with the current time as creation times, and
1500 // four with the earlier time as creation times. We should only get
1501 // two cookies remaining, but which two (other than that there should
1502 // be one from each set) will be random.
1503 std::vector<CanonicalCookie*> initial_cookies;
1504 AddCookieToList("www.google.com", "X=1; path=/", now, &initial_cookies);
1505 AddCookieToList("www.google.com", "X=2; path=/", now, &initial_cookies);
1506 AddCookieToList("www.google.com", "X=3; path=/", now, &initial_cookies);
1507 AddCookieToList("www.google.com", "X=4; path=/", now, &initial_cookies);
1509 AddCookieToList("www.google.com", "Y=1; path=/", earlier, &initial_cookies);
1510 AddCookieToList("www.google.com", "Y=2; path=/", earlier, &initial_cookies);
1511 AddCookieToList("www.google.com", "Y=3; path=/", earlier, &initial_cookies);
1512 AddCookieToList("www.google.com", "Y=4; path=/", earlier, &initial_cookies);
1514 // Inject our initial cookies into the mock PersistentCookieStore.
1515 store->SetLoadExpectation(true, initial_cookies);
1517 scoped_refptr<CookieMonster> cm(new CookieMonster(store.get(), NULL));
1519 CookieList list(GetAllCookies(cm.get()));
1520 EXPECT_EQ(2U, list.size());
1521 // Confirm that we have one of each.
1522 std::string name1(list[0].Name());
1523 std::string name2(list[1].Name());
1524 EXPECT_TRUE(name1 == "X" || name2 == "X");
1525 EXPECT_TRUE(name1 == "Y" || name2 == "Y");
1526 EXPECT_NE(name1, name2);
1529 TEST_F(CookieMonsterTest, CookieMonsterDelegate) {
1530 scoped_refptr<MockPersistentCookieStore> store(new MockPersistentCookieStore);
1531 scoped_refptr<MockCookieMonsterDelegate> delegate(
1532 new MockCookieMonsterDelegate);
1533 scoped_refptr<CookieMonster> cm(
1534 new CookieMonster(store.get(), delegate.get()));
1536 EXPECT_TRUE(SetCookie(cm.get(), url_google_, "A=B"));
1537 EXPECT_TRUE(SetCookie(cm.get(), url_google_, "C=D"));
1538 EXPECT_TRUE(SetCookie(cm.get(), url_google_, "E=F"));
1539 EXPECT_EQ("A=B; C=D; E=F", GetCookies(cm.get(), url_google_));
1540 ASSERT_EQ(3u, delegate->changes().size());
1541 EXPECT_FALSE(delegate->changes()[0].second);
1542 EXPECT_EQ(url_google_.host(), delegate->changes()[0].first.Domain());
1543 EXPECT_EQ("A", delegate->changes()[0].first.Name());
1544 EXPECT_EQ("B", delegate->changes()[0].first.Value());
1545 EXPECT_EQ(url_google_.host(), delegate->changes()[1].first.Domain());
1546 EXPECT_FALSE(delegate->changes()[1].second);
1547 EXPECT_EQ("C", delegate->changes()[1].first.Name());
1548 EXPECT_EQ("D", delegate->changes()[1].first.Value());
1549 EXPECT_EQ(url_google_.host(), delegate->changes()[2].first.Domain());
1550 EXPECT_FALSE(delegate->changes()[2].second);
1551 EXPECT_EQ("E", delegate->changes()[2].first.Name());
1552 EXPECT_EQ("F", delegate->changes()[2].first.Value());
1553 delegate->reset();
1555 EXPECT_TRUE(FindAndDeleteCookie(cm.get(), url_google_.host(), "C"));
1556 EXPECT_EQ("A=B; E=F", GetCookies(cm.get(), url_google_));
1557 ASSERT_EQ(1u, delegate->changes().size());
1558 EXPECT_EQ(url_google_.host(), delegate->changes()[0].first.Domain());
1559 EXPECT_TRUE(delegate->changes()[0].second);
1560 EXPECT_EQ("C", delegate->changes()[0].first.Name());
1561 EXPECT_EQ("D", delegate->changes()[0].first.Value());
1562 delegate->reset();
1564 EXPECT_FALSE(FindAndDeleteCookie(cm.get(), "random.host", "E"));
1565 EXPECT_EQ("A=B; E=F", GetCookies(cm.get(), url_google_));
1566 EXPECT_EQ(0u, delegate->changes().size());
1568 // Insert a cookie "a" for path "/path1"
1569 EXPECT_TRUE(SetCookie(cm.get(), url_google_,
1570 "a=val1; path=/path1; "
1571 "expires=Mon, 18-Apr-22 22:50:13 GMT"));
1572 ASSERT_EQ(1u, store->commands().size());
1573 EXPECT_EQ(CookieStoreCommand::ADD, store->commands()[0].type);
1574 ASSERT_EQ(1u, delegate->changes().size());
1575 EXPECT_FALSE(delegate->changes()[0].second);
1576 EXPECT_EQ(url_google_.host(), delegate->changes()[0].first.Domain());
1577 EXPECT_EQ("a", delegate->changes()[0].first.Name());
1578 EXPECT_EQ("val1", delegate->changes()[0].first.Value());
1579 delegate->reset();
1581 // Insert a cookie "a" for path "/path1", that is httponly. This should
1582 // overwrite the non-http-only version.
1583 CookieOptions allow_httponly;
1584 allow_httponly.set_include_httponly();
1585 EXPECT_TRUE(SetCookieWithOptions(cm.get(), url_google_,
1586 "a=val2; path=/path1; httponly; "
1587 "expires=Mon, 18-Apr-22 22:50:14 GMT",
1588 allow_httponly));
1589 ASSERT_EQ(3u, store->commands().size());
1590 EXPECT_EQ(CookieStoreCommand::REMOVE, store->commands()[1].type);
1591 EXPECT_EQ(CookieStoreCommand::ADD, store->commands()[2].type);
1592 ASSERT_EQ(2u, delegate->changes().size());
1593 EXPECT_EQ(url_google_.host(), delegate->changes()[0].first.Domain());
1594 EXPECT_TRUE(delegate->changes()[0].second);
1595 EXPECT_EQ("a", delegate->changes()[0].first.Name());
1596 EXPECT_EQ("val1", delegate->changes()[0].first.Value());
1597 EXPECT_EQ(url_google_.host(), delegate->changes()[1].first.Domain());
1598 EXPECT_FALSE(delegate->changes()[1].second);
1599 EXPECT_EQ("a", delegate->changes()[1].first.Name());
1600 EXPECT_EQ("val2", delegate->changes()[1].first.Value());
1601 delegate->reset();
1604 TEST_F(CookieMonsterTest, SetCookieWithDetails) {
1605 scoped_refptr<CookieMonster> cm(new CookieMonster(NULL, NULL));
1607 EXPECT_TRUE(SetCookieWithDetails(cm.get(), url_google_foo_, "A", "B",
1608 std::string(), "/foo", base::Time(), false,
1609 false, false, COOKIE_PRIORITY_DEFAULT));
1610 EXPECT_TRUE(SetCookieWithDetails(cm.get(), url_google_bar_, "C", "D",
1611 "google.izzle", "/bar", base::Time(), false,
1612 true, false, COOKIE_PRIORITY_DEFAULT));
1613 EXPECT_TRUE(SetCookieWithDetails(
1614 cm.get(), url_google_, "E", "F", std::string(), std::string(),
1615 base::Time(), true, false, false, COOKIE_PRIORITY_DEFAULT));
1617 // Test that malformed attributes fail to set the cookie.
1618 EXPECT_FALSE(SetCookieWithDetails(cm.get(), url_google_foo_, " A", "B",
1619 std::string(), "/foo", base::Time(), false,
1620 false, false, COOKIE_PRIORITY_DEFAULT));
1621 EXPECT_FALSE(SetCookieWithDetails(cm.get(), url_google_foo_, "A;", "B",
1622 std::string(), "/foo", base::Time(), false,
1623 false, false, COOKIE_PRIORITY_DEFAULT));
1624 EXPECT_FALSE(SetCookieWithDetails(cm.get(), url_google_foo_, "A=", "B",
1625 std::string(), "/foo", base::Time(), false,
1626 false, false, COOKIE_PRIORITY_DEFAULT));
1627 EXPECT_FALSE(SetCookieWithDetails(
1628 cm.get(), url_google_foo_, "A", "B", "google.ozzzzzzle", "foo",
1629 base::Time(), false, false, false, COOKIE_PRIORITY_DEFAULT));
1630 EXPECT_FALSE(SetCookieWithDetails(cm.get(), url_google_foo_, "A=", "B",
1631 std::string(), "foo", base::Time(), false,
1632 false, false, COOKIE_PRIORITY_DEFAULT));
1634 CookieList cookies = GetAllCookiesForURL(cm.get(), url_google_foo_);
1635 CookieList::iterator it = cookies.begin();
1637 ASSERT_TRUE(it != cookies.end());
1638 EXPECT_EQ("A", it->Name());
1639 EXPECT_EQ("B", it->Value());
1640 EXPECT_EQ("www.google.izzle", it->Domain());
1641 EXPECT_EQ("/foo", it->Path());
1642 EXPECT_FALSE(it->IsPersistent());
1643 EXPECT_FALSE(it->IsSecure());
1644 EXPECT_FALSE(it->IsHttpOnly());
1646 ASSERT_TRUE(++it == cookies.end());
1648 cookies = GetAllCookiesForURL(cm.get(), url_google_bar_);
1649 it = cookies.begin();
1651 ASSERT_TRUE(it != cookies.end());
1652 EXPECT_EQ("C", it->Name());
1653 EXPECT_EQ("D", it->Value());
1654 EXPECT_EQ(".google.izzle", it->Domain());
1655 EXPECT_EQ("/bar", it->Path());
1656 EXPECT_FALSE(it->IsSecure());
1657 EXPECT_TRUE(it->IsHttpOnly());
1659 ASSERT_TRUE(++it == cookies.end());
1661 cookies = GetAllCookiesForURL(cm.get(), url_google_secure_);
1662 it = cookies.begin();
1664 ASSERT_TRUE(it != cookies.end());
1665 EXPECT_EQ("E", it->Name());
1666 EXPECT_EQ("F", it->Value());
1667 EXPECT_EQ("/", it->Path());
1668 EXPECT_EQ("www.google.izzle", it->Domain());
1669 EXPECT_TRUE(it->IsSecure());
1670 EXPECT_FALSE(it->IsHttpOnly());
1672 ASSERT_TRUE(++it == cookies.end());
1675 TEST_F(CookieMonsterTest, DeleteAllForHost) {
1676 scoped_refptr<CookieMonster> cm(new CookieMonster(NULL, NULL));
1678 // Test probes:
1679 // * Non-secure URL, mid-level (http://w.c.b.a)
1680 // * Secure URL, mid-level (https://w.c.b.a)
1681 // * URL with path, mid-level (https:/w.c.b.a/dir1/xx)
1682 // All three tests should nuke only the midlevel host cookie,
1683 // the http_only cookie, the host secure cookie, and the two host
1684 // path cookies. http_only, secure, and paths are ignored by
1685 // this call, and domain cookies arent touched.
1686 PopulateCmForDeleteAllForHost(cm);
1687 EXPECT_EQ("dom_1=X; dom_2=X; dom_3=X; host_3=X",
1688 GetCookies(cm.get(), GURL(kTopLevelDomainPlus3)));
1689 EXPECT_EQ("dom_1=X; dom_2=X; host_2=X; sec_dom=X; sec_host=X",
1690 GetCookies(cm.get(), GURL(kTopLevelDomainPlus2Secure)));
1691 EXPECT_EQ("dom_1=X; host_1=X",
1692 GetCookies(cm.get(), GURL(kTopLevelDomainPlus1)));
1693 EXPECT_EQ(
1694 "dom_path_2=X; host_path_2=X; dom_path_1=X; host_path_1=X; "
1695 "dom_1=X; dom_2=X; host_2=X; sec_dom=X; sec_host=X",
1696 GetCookies(cm.get(), GURL(kTopLevelDomainPlus2Secure +
1697 std::string("/dir1/dir2/xxx"))));
1699 EXPECT_EQ(6, DeleteAllForHost(cm.get(), GURL(kTopLevelDomainPlus2)));
1700 EXPECT_EQ(8U, GetAllCookies(cm.get()).size());
1702 EXPECT_EQ("dom_1=X; dom_2=X; dom_3=X; host_3=X",
1703 GetCookies(cm.get(), GURL(kTopLevelDomainPlus3)));
1704 EXPECT_EQ("dom_1=X; dom_2=X; sec_dom=X",
1705 GetCookies(cm.get(), GURL(kTopLevelDomainPlus2Secure)));
1706 EXPECT_EQ("dom_1=X; host_1=X",
1707 GetCookies(cm.get(), GURL(kTopLevelDomainPlus1)));
1708 EXPECT_EQ("dom_path_2=X; dom_path_1=X; dom_1=X; dom_2=X; sec_dom=X",
1709 GetCookies(cm.get(), GURL(kTopLevelDomainPlus2Secure +
1710 std::string("/dir1/dir2/xxx"))));
1712 PopulateCmForDeleteAllForHost(cm);
1713 EXPECT_EQ(6, DeleteAllForHost(cm.get(), GURL(kTopLevelDomainPlus2Secure)));
1714 EXPECT_EQ(8U, GetAllCookies(cm.get()).size());
1716 EXPECT_EQ("dom_1=X; dom_2=X; dom_3=X; host_3=X",
1717 GetCookies(cm.get(), GURL(kTopLevelDomainPlus3)));
1718 EXPECT_EQ("dom_1=X; dom_2=X; sec_dom=X",
1719 GetCookies(cm.get(), GURL(kTopLevelDomainPlus2Secure)));
1720 EXPECT_EQ("dom_1=X; host_1=X",
1721 GetCookies(cm.get(), GURL(kTopLevelDomainPlus1)));
1722 EXPECT_EQ("dom_path_2=X; dom_path_1=X; dom_1=X; dom_2=X; sec_dom=X",
1723 GetCookies(cm.get(), GURL(kTopLevelDomainPlus2Secure +
1724 std::string("/dir1/dir2/xxx"))));
1726 PopulateCmForDeleteAllForHost(cm);
1727 EXPECT_EQ(6, DeleteAllForHost(cm.get(), GURL(kTopLevelDomainPlus2Secure +
1728 std::string("/dir1/xxx"))));
1729 EXPECT_EQ(8U, GetAllCookies(cm.get()).size());
1731 EXPECT_EQ("dom_1=X; dom_2=X; dom_3=X; host_3=X",
1732 GetCookies(cm.get(), GURL(kTopLevelDomainPlus3)));
1733 EXPECT_EQ("dom_1=X; dom_2=X; sec_dom=X",
1734 GetCookies(cm.get(), GURL(kTopLevelDomainPlus2Secure)));
1735 EXPECT_EQ("dom_1=X; host_1=X",
1736 GetCookies(cm.get(), GURL(kTopLevelDomainPlus1)));
1737 EXPECT_EQ("dom_path_2=X; dom_path_1=X; dom_1=X; dom_2=X; sec_dom=X",
1738 GetCookies(cm.get(), GURL(kTopLevelDomainPlus2Secure +
1739 std::string("/dir1/dir2/xxx"))));
1742 TEST_F(CookieMonsterTest, UniqueCreationTime) {
1743 scoped_refptr<CookieMonster> cm(new CookieMonster(NULL, NULL));
1744 CookieOptions options;
1746 // Add in three cookies through every public interface to the
1747 // CookieMonster and confirm that none of them have duplicate
1748 // creation times.
1750 // SetCookieWithCreationTime and SetCookieWithCreationTimeAndOptions
1751 // are not included as they aren't going to be public for very much
1752 // longer.
1754 // SetCookie, SetCookieWithOptions, SetCookieWithDetails
1756 SetCookie(cm.get(), url_google_, "SetCookie1=A");
1757 SetCookie(cm.get(), url_google_, "SetCookie2=A");
1758 SetCookie(cm.get(), url_google_, "SetCookie3=A");
1760 SetCookieWithOptions(cm.get(), url_google_, "setCookieWithOptions1=A",
1761 options);
1762 SetCookieWithOptions(cm.get(), url_google_, "setCookieWithOptions2=A",
1763 options);
1764 SetCookieWithOptions(cm.get(), url_google_, "setCookieWithOptions3=A",
1765 options);
1767 SetCookieWithDetails(cm.get(), url_google_, "setCookieWithDetails1", "A",
1768 ".google.com", "/", Time(), false, false, false,
1769 COOKIE_PRIORITY_DEFAULT);
1770 SetCookieWithDetails(cm.get(), url_google_, "setCookieWithDetails2", "A",
1771 ".google.com", "/", Time(), false, false, false,
1772 COOKIE_PRIORITY_DEFAULT);
1773 SetCookieWithDetails(cm.get(), url_google_, "setCookieWithDetails3", "A",
1774 ".google.com", "/", Time(), false, false, false,
1775 COOKIE_PRIORITY_DEFAULT);
1777 // Now we check
1778 CookieList cookie_list(GetAllCookies(cm.get()));
1779 typedef std::map<int64, CanonicalCookie> TimeCookieMap;
1780 TimeCookieMap check_map;
1781 for (CookieList::const_iterator it = cookie_list.begin();
1782 it != cookie_list.end(); it++) {
1783 const int64 creation_date = it->CreationDate().ToInternalValue();
1784 TimeCookieMap::const_iterator existing_cookie_it(
1785 check_map.find(creation_date));
1786 EXPECT_TRUE(existing_cookie_it == check_map.end())
1787 << "Cookie " << it->Name() << " has same creation date ("
1788 << it->CreationDate().ToInternalValue()
1789 << ") as previously entered cookie "
1790 << existing_cookie_it->second.Name();
1792 if (existing_cookie_it == check_map.end()) {
1793 check_map.insert(
1794 TimeCookieMap::value_type(it->CreationDate().ToInternalValue(), *it));
1799 // Mainly a test of GetEffectiveDomain, or more specifically, of the
1800 // expected behavior of GetEffectiveDomain within the CookieMonster.
1801 TEST_F(CookieMonsterTest, GetKey) {
1802 scoped_refptr<CookieMonster> cm(new CookieMonster(NULL, NULL));
1804 // This test is really only interesting if GetKey() actually does something.
1805 EXPECT_EQ("google.com", cm->GetKey("www.google.com"));
1806 EXPECT_EQ("google.izzie", cm->GetKey("www.google.izzie"));
1807 EXPECT_EQ("google.izzie", cm->GetKey(".google.izzie"));
1808 EXPECT_EQ("bbc.co.uk", cm->GetKey("bbc.co.uk"));
1809 EXPECT_EQ("bbc.co.uk", cm->GetKey("a.b.c.d.bbc.co.uk"));
1810 EXPECT_EQ("apple.com", cm->GetKey("a.b.c.d.apple.com"));
1811 EXPECT_EQ("apple.izzie", cm->GetKey("a.b.c.d.apple.izzie"));
1813 // Cases where the effective domain is null, so we use the host
1814 // as the key.
1815 EXPECT_EQ("co.uk", cm->GetKey("co.uk"));
1816 const std::string extension_name("iehocdgbbocmkdidlbnnfbmbinnahbae");
1817 EXPECT_EQ(extension_name, cm->GetKey(extension_name));
1818 EXPECT_EQ("com", cm->GetKey("com"));
1819 EXPECT_EQ("hostalias", cm->GetKey("hostalias"));
1820 EXPECT_EQ("localhost", cm->GetKey("localhost"));
1823 // Test that cookies transfer from/to the backing store correctly.
1824 TEST_F(CookieMonsterTest, BackingStoreCommunication) {
1825 // Store details for cookies transforming through the backing store interface.
1827 base::Time current(base::Time::Now());
1828 scoped_refptr<MockSimplePersistentCookieStore> store(
1829 new MockSimplePersistentCookieStore);
1830 base::Time new_access_time;
1831 base::Time expires(base::Time::Now() + base::TimeDelta::FromSeconds(100));
1833 const CookiesInputInfo input_info[] = {
1834 {GURL("http://a.b.google.com"),
1835 "a",
1836 "1",
1838 "/path/to/cookie",
1839 expires,
1840 false,
1841 false,
1842 false,
1843 COOKIE_PRIORITY_DEFAULT},
1844 {GURL("https://www.google.com"),
1845 "b",
1846 "2",
1847 ".google.com",
1848 "/path/from/cookie",
1849 expires + TimeDelta::FromSeconds(10),
1850 true,
1851 true,
1852 false,
1853 COOKIE_PRIORITY_DEFAULT},
1854 {GURL("https://google.com"),
1855 "c",
1856 "3",
1858 "/another/path/to/cookie",
1859 base::Time::Now() + base::TimeDelta::FromSeconds(100),
1860 true,
1861 false,
1862 true,
1863 COOKIE_PRIORITY_DEFAULT}};
1864 const int INPUT_DELETE = 1;
1866 // Create new cookies and flush them to the store.
1868 scoped_refptr<CookieMonster> cmout(new CookieMonster(store.get(), NULL));
1869 for (const CookiesInputInfo* p = input_info;
1870 p < &input_info[arraysize(input_info)]; p++) {
1871 EXPECT_TRUE(SetCookieWithDetails(cmout.get(), p->url, p->name, p->value,
1872 p->domain, p->path, p->expiration_time,
1873 p->secure, p->http_only,
1874 p->first_party_only, p->priority));
1876 GURL del_url(input_info[INPUT_DELETE]
1877 .url.Resolve(input_info[INPUT_DELETE].path)
1878 .spec());
1879 DeleteCookie(cmout.get(), del_url, input_info[INPUT_DELETE].name);
1882 // Create a new cookie monster and make sure that everything is correct
1884 scoped_refptr<CookieMonster> cmin(new CookieMonster(store.get(), NULL));
1885 CookieList cookies(GetAllCookies(cmin.get()));
1886 ASSERT_EQ(2u, cookies.size());
1887 // Ordering is path length, then creation time. So second cookie
1888 // will come first, and we need to swap them.
1889 std::swap(cookies[0], cookies[1]);
1890 for (int output_index = 0; output_index < 2; output_index++) {
1891 int input_index = output_index * 2;
1892 const CookiesInputInfo* input = &input_info[input_index];
1893 const CanonicalCookie* output = &cookies[output_index];
1895 EXPECT_EQ(input->name, output->Name());
1896 EXPECT_EQ(input->value, output->Value());
1897 EXPECT_EQ(input->url.host(), output->Domain());
1898 EXPECT_EQ(input->path, output->Path());
1899 EXPECT_LE(current.ToInternalValue(),
1900 output->CreationDate().ToInternalValue());
1901 EXPECT_EQ(input->secure, output->IsSecure());
1902 EXPECT_EQ(input->http_only, output->IsHttpOnly());
1903 EXPECT_EQ(input->first_party_only, output->IsFirstPartyOnly());
1904 EXPECT_TRUE(output->IsPersistent());
1905 EXPECT_EQ(input->expiration_time.ToInternalValue(),
1906 output->ExpiryDate().ToInternalValue());
1911 TEST_F(CookieMonsterTest, CookieListOrdering) {
1912 // Put a random set of cookies into a monster and make sure
1913 // they're returned in the right order.
1914 scoped_refptr<CookieMonster> cm(new CookieMonster(NULL, NULL));
1915 EXPECT_TRUE(
1916 SetCookie(cm.get(), GURL("http://d.c.b.a.google.com/aa/x.html"), "c=1"));
1917 EXPECT_TRUE(SetCookie(cm.get(), GURL("http://b.a.google.com/aa/bb/cc/x.html"),
1918 "d=1; domain=b.a.google.com"));
1919 EXPECT_TRUE(SetCookie(cm.get(), GURL("http://b.a.google.com/aa/bb/cc/x.html"),
1920 "a=4; domain=b.a.google.com"));
1921 EXPECT_TRUE(SetCookie(cm.get(),
1922 GURL("http://c.b.a.google.com/aa/bb/cc/x.html"),
1923 "e=1; domain=c.b.a.google.com"));
1924 EXPECT_TRUE(SetCookie(cm.get(),
1925 GURL("http://d.c.b.a.google.com/aa/bb/x.html"), "b=1"));
1926 EXPECT_TRUE(SetCookie(cm.get(), GURL("http://news.bbc.co.uk/midpath/x.html"),
1927 "g=10"));
1929 unsigned int i = 0;
1930 CookieList cookies(GetAllCookiesForURL(
1931 cm.get(), GURL("http://d.c.b.a.google.com/aa/bb/cc/dd")));
1932 ASSERT_EQ(5u, cookies.size());
1933 EXPECT_EQ("d", cookies[i++].Name());
1934 EXPECT_EQ("a", cookies[i++].Name());
1935 EXPECT_EQ("e", cookies[i++].Name());
1936 EXPECT_EQ("b", cookies[i++].Name());
1937 EXPECT_EQ("c", cookies[i++].Name());
1941 unsigned int i = 0;
1942 CookieList cookies(GetAllCookies(cm.get()));
1943 ASSERT_EQ(6u, cookies.size());
1944 EXPECT_EQ("d", cookies[i++].Name());
1945 EXPECT_EQ("a", cookies[i++].Name());
1946 EXPECT_EQ("e", cookies[i++].Name());
1947 EXPECT_EQ("g", cookies[i++].Name());
1948 EXPECT_EQ("b", cookies[i++].Name());
1949 EXPECT_EQ("c", cookies[i++].Name());
1953 // This test and CookieMonstertest.TestGCTimes (in cookie_monster_perftest.cc)
1954 // are somewhat complementary twins. This test is probing for whether
1955 // garbage collection always happens when it should (i.e. that we actually
1956 // get rid of cookies when we should). The perftest is probing for
1957 // whether garbage collection happens when it shouldn't. See comments
1958 // before that test for more details.
1960 // Disabled on Windows, see crbug.com/126095
1961 #if defined(OS_WIN)
1962 #define MAYBE_GarbageCollectionTriggers DISABLED_GarbageCollectionTriggers
1963 #else
1964 #define MAYBE_GarbageCollectionTriggers GarbageCollectionTriggers
1965 #endif
1967 TEST_F(CookieMonsterTest, MAYBE_GarbageCollectionTriggers) {
1968 // First we check to make sure that a whole lot of recent cookies
1969 // doesn't get rid of anything after garbage collection is checked for.
1971 scoped_refptr<CookieMonster> cm(
1972 CreateMonsterForGC(CookieMonster::kMaxCookies * 2));
1973 EXPECT_EQ(CookieMonster::kMaxCookies * 2, GetAllCookies(cm.get()).size());
1974 SetCookie(cm.get(), GURL("http://newdomain.com"), "b=2");
1975 EXPECT_EQ(CookieMonster::kMaxCookies * 2 + 1,
1976 GetAllCookies(cm.get()).size());
1979 // Now we explore a series of relationships between cookie last access
1980 // time and size of store to make sure we only get rid of cookies when
1981 // we really should.
1982 const struct TestCase {
1983 size_t num_cookies;
1984 size_t num_old_cookies;
1985 size_t expected_initial_cookies;
1986 // Indexed by ExpiryAndKeyScheme
1987 size_t expected_cookies_after_set;
1988 } test_cases[] = {
1989 {// A whole lot of recent cookies; gc shouldn't happen.
1990 CookieMonster::kMaxCookies * 2,
1992 CookieMonster::kMaxCookies * 2,
1993 CookieMonster::kMaxCookies * 2 + 1},
1994 {// Some old cookies, but still overflowing max.
1995 CookieMonster::kMaxCookies * 2,
1996 CookieMonster::kMaxCookies / 2,
1997 CookieMonster::kMaxCookies * 2,
1998 CookieMonster::kMaxCookies * 2 - CookieMonster::kMaxCookies / 2 + 1},
1999 {// Old cookies enough to bring us right down to our purge line.
2000 CookieMonster::kMaxCookies * 2,
2001 CookieMonster::kMaxCookies + CookieMonster::kPurgeCookies + 1,
2002 CookieMonster::kMaxCookies * 2,
2003 CookieMonster::kMaxCookies - CookieMonster::kPurgeCookies},
2004 {// Old cookies enough to bring below our purge line (which we
2005 // shouldn't do).
2006 CookieMonster::kMaxCookies * 2,
2007 CookieMonster::kMaxCookies * 3 / 2,
2008 CookieMonster::kMaxCookies * 2,
2009 CookieMonster::kMaxCookies - CookieMonster::kPurgeCookies}};
2011 for (int ci = 0; ci < static_cast<int>(arraysize(test_cases)); ++ci) {
2012 const TestCase* test_case = &test_cases[ci];
2013 scoped_refptr<CookieMonster> cm(CreateMonsterFromStoreForGC(
2014 test_case->num_cookies, test_case->num_old_cookies,
2015 CookieMonster::kSafeFromGlobalPurgeDays * 2));
2016 EXPECT_EQ(test_case->expected_initial_cookies,
2017 GetAllCookies(cm.get()).size())
2018 << "For test case " << ci;
2019 // Will trigger GC
2020 SetCookie(cm.get(), GURL("http://newdomain.com"), "b=2");
2021 EXPECT_EQ(test_case->expected_cookies_after_set,
2022 GetAllCookies(cm.get()).size())
2023 << "For test case " << ci;
2027 // This test checks that keep expired cookies flag is working.
2028 TEST_F(CookieMonsterTest, KeepExpiredCookies) {
2029 scoped_refptr<CookieMonster> cm(new CookieMonster(NULL, NULL));
2030 cm->SetKeepExpiredCookies();
2031 CookieOptions options;
2033 // Set a persistent cookie.
2034 ASSERT_TRUE(SetCookieWithOptions(
2035 cm.get(), url_google_,
2036 std::string(kValidCookieLine) + "; expires=Mon, 18-Apr-22 22:50:13 GMT",
2037 options));
2039 // Get the canonical cookie.
2040 CookieList cookie_list = GetAllCookies(cm.get());
2041 ASSERT_EQ(1U, cookie_list.size());
2043 // Use a past expiry date to delete the cookie.
2044 ASSERT_TRUE(SetCookieWithOptions(
2045 cm.get(), url_google_,
2046 std::string(kValidCookieLine) + "; expires=Mon, 18-Apr-1977 22:50:13 GMT",
2047 options));
2049 // Check that the cookie with the past expiry date is still there.
2050 // GetAllCookies() also triggers garbage collection.
2051 cookie_list = GetAllCookies(cm.get());
2052 ASSERT_EQ(1U, cookie_list.size());
2053 ASSERT_TRUE(cookie_list[0].IsExpired(Time::Now()));
2056 namespace {
2058 // Mock PersistentCookieStore that keeps track of the number of Flush() calls.
2059 class FlushablePersistentStore : public CookieMonster::PersistentCookieStore {
2060 public:
2061 FlushablePersistentStore() : flush_count_(0) {}
2063 void Load(const LoadedCallback& loaded_callback) override {
2064 std::vector<CanonicalCookie*> out_cookies;
2065 base::MessageLoop::current()->PostTask(
2066 FROM_HERE,
2067 base::Bind(&net::LoadedCallbackTask::Run,
2068 new net::LoadedCallbackTask(loaded_callback, out_cookies)));
2071 void LoadCookiesForKey(const std::string& key,
2072 const LoadedCallback& loaded_callback) override {
2073 Load(loaded_callback);
2076 void AddCookie(const CanonicalCookie&) override {}
2077 void UpdateCookieAccessTime(const CanonicalCookie&) override {}
2078 void DeleteCookie(const CanonicalCookie&) override {}
2079 void SetForceKeepSessionState() override {}
2081 void Flush(const base::Closure& callback) override {
2082 ++flush_count_;
2083 if (!callback.is_null())
2084 callback.Run();
2087 int flush_count() { return flush_count_; }
2089 private:
2090 ~FlushablePersistentStore() override {}
2092 volatile int flush_count_;
2095 // Counts the number of times Callback() has been run.
2096 class CallbackCounter : public base::RefCountedThreadSafe<CallbackCounter> {
2097 public:
2098 CallbackCounter() : callback_count_(0) {}
2100 void Callback() { ++callback_count_; }
2102 int callback_count() { return callback_count_; }
2104 private:
2105 friend class base::RefCountedThreadSafe<CallbackCounter>;
2106 ~CallbackCounter() {}
2108 volatile int callback_count_;
2111 } // namespace
2113 // Test that FlushStore() is forwarded to the store and callbacks are posted.
2114 TEST_F(CookieMonsterTest, FlushStore) {
2115 scoped_refptr<CallbackCounter> counter(new CallbackCounter());
2116 scoped_refptr<FlushablePersistentStore> store(new FlushablePersistentStore());
2117 scoped_refptr<CookieMonster> cm(new CookieMonster(store.get(), NULL));
2119 ASSERT_EQ(0, store->flush_count());
2120 ASSERT_EQ(0, counter->callback_count());
2122 // Before initialization, FlushStore() should just run the callback.
2123 cm->FlushStore(base::Bind(&CallbackCounter::Callback, counter.get()));
2124 base::MessageLoop::current()->RunUntilIdle();
2126 ASSERT_EQ(0, store->flush_count());
2127 ASSERT_EQ(1, counter->callback_count());
2129 // NULL callback is safe.
2130 cm->FlushStore(base::Closure());
2131 base::MessageLoop::current()->RunUntilIdle();
2133 ASSERT_EQ(0, store->flush_count());
2134 ASSERT_EQ(1, counter->callback_count());
2136 // After initialization, FlushStore() should delegate to the store.
2137 GetAllCookies(cm.get()); // Force init.
2138 cm->FlushStore(base::Bind(&CallbackCounter::Callback, counter.get()));
2139 base::MessageLoop::current()->RunUntilIdle();
2141 ASSERT_EQ(1, store->flush_count());
2142 ASSERT_EQ(2, counter->callback_count());
2144 // NULL callback is still safe.
2145 cm->FlushStore(base::Closure());
2146 base::MessageLoop::current()->RunUntilIdle();
2148 ASSERT_EQ(2, store->flush_count());
2149 ASSERT_EQ(2, counter->callback_count());
2151 // If there's no backing store, FlushStore() is always a safe no-op.
2152 cm = new CookieMonster(NULL, NULL);
2153 GetAllCookies(cm.get()); // Force init.
2154 cm->FlushStore(base::Closure());
2155 base::MessageLoop::current()->RunUntilIdle();
2157 ASSERT_EQ(2, counter->callback_count());
2159 cm->FlushStore(base::Bind(&CallbackCounter::Callback, counter.get()));
2160 base::MessageLoop::current()->RunUntilIdle();
2162 ASSERT_EQ(3, counter->callback_count());
2165 TEST_F(CookieMonsterTest, SetAllCookies) {
2166 scoped_refptr<FlushablePersistentStore> store(new FlushablePersistentStore());
2167 scoped_refptr<CookieMonster> cm(new CookieMonster(store.get(), NULL));
2168 cm->SetPersistSessionCookies(true);
2170 EXPECT_TRUE(SetCookie(cm.get(), url_google_, "U=V; path=/"));
2171 EXPECT_TRUE(SetCookie(cm.get(), url_google_, "W=X; path=/foo"));
2172 EXPECT_TRUE(SetCookie(cm.get(), url_google_, "Y=Z; path=/"));
2174 CookieList list;
2175 list.push_back(CanonicalCookie(url_google_, "A", "B", url_google_.host(), "/",
2176 base::Time::Now(), base::Time(), base::Time(),
2177 false, false, false, COOKIE_PRIORITY_DEFAULT));
2178 list.push_back(CanonicalCookie(url_google_, "W", "X", url_google_.host(),
2179 "/bar", base::Time::Now(), base::Time(),
2180 base::Time(), false, false, false,
2181 COOKIE_PRIORITY_DEFAULT));
2182 list.push_back(CanonicalCookie(url_google_, "Y", "Z", url_google_.host(), "/",
2183 base::Time::Now(), base::Time(), base::Time(),
2184 false, false, false, COOKIE_PRIORITY_DEFAULT));
2186 // SetAllCookies must not flush.
2187 ASSERT_EQ(0, store->flush_count());
2188 EXPECT_TRUE(SetAllCookies(cm.get(), list));
2189 EXPECT_EQ(0, store->flush_count());
2191 CookieList cookies = GetAllCookies(cm.get());
2192 size_t expected_size = 3; // "A", "W" and "Y". "U" is gone.
2193 EXPECT_EQ(expected_size, cookies.size());
2194 CookieList::iterator it = cookies.begin();
2196 ASSERT_TRUE(it != cookies.end());
2197 EXPECT_EQ("W", it->Name());
2198 EXPECT_EQ("X", it->Value());
2199 EXPECT_EQ("/bar", it->Path()); // The path has been updated.
2201 ASSERT_TRUE(++it != cookies.end());
2202 EXPECT_EQ("A", it->Name());
2203 EXPECT_EQ("B", it->Value());
2205 ASSERT_TRUE(++it != cookies.end());
2206 EXPECT_EQ("Y", it->Name());
2207 EXPECT_EQ("Z", it->Value());
2210 TEST_F(CookieMonsterTest, ComputeCookieDiff) {
2211 scoped_refptr<CookieMonster> cm(new CookieMonster(NULL, NULL));
2213 base::Time now = base::Time::Now();
2214 base::Time creation_time = now - base::TimeDelta::FromSeconds(1);
2216 CanonicalCookie cookie1(url_google_, "A", "B", url_google_.host(), "/",
2217 creation_time, base::Time(), base::Time(), false,
2218 false, false, COOKIE_PRIORITY_DEFAULT);
2219 CanonicalCookie cookie2(url_google_, "C", "D", url_google_.host(), "/",
2220 creation_time, base::Time(), base::Time(), false,
2221 false, false, COOKIE_PRIORITY_DEFAULT);
2222 CanonicalCookie cookie3(url_google_, "E", "F", url_google_.host(), "/",
2223 creation_time, base::Time(), base::Time(), false,
2224 false, false, COOKIE_PRIORITY_DEFAULT);
2225 CanonicalCookie cookie4(url_google_, "G", "H", url_google_.host(), "/",
2226 creation_time, base::Time(), base::Time(), false,
2227 false, false, COOKIE_PRIORITY_DEFAULT);
2228 CanonicalCookie cookie4_with_new_value(
2229 url_google_, "G", "iamnew", url_google_.host(), "/", creation_time,
2230 base::Time(), base::Time(), false, false, false, COOKIE_PRIORITY_DEFAULT);
2231 CanonicalCookie cookie5(url_google_, "I", "J", url_google_.host(), "/",
2232 creation_time, base::Time(), base::Time(), false,
2233 false, false, COOKIE_PRIORITY_DEFAULT);
2234 CanonicalCookie cookie5_with_new_creation_time(
2235 url_google_, "I", "J", url_google_.host(), "/", now, base::Time(),
2236 base::Time(), false, false, false, COOKIE_PRIORITY_DEFAULT);
2237 CanonicalCookie cookie6(url_google_, "K", "L", url_google_.host(), "/foo",
2238 creation_time, base::Time(), base::Time(), false,
2239 false, false, COOKIE_PRIORITY_DEFAULT);
2240 CanonicalCookie cookie6_with_new_path(
2241 url_google_, "K", "L", url_google_.host(), "/bar", creation_time,
2242 base::Time(), base::Time(), false, false, false, COOKIE_PRIORITY_DEFAULT);
2243 CanonicalCookie cookie7(url_google_, "M", "N", url_google_.host(), "/foo",
2244 creation_time, base::Time(), base::Time(), false,
2245 false, false, COOKIE_PRIORITY_DEFAULT);
2246 CanonicalCookie cookie7_with_new_path(
2247 url_google_, "M", "N", url_google_.host(), "/bar", creation_time,
2248 base::Time(), base::Time(), false, false, false, COOKIE_PRIORITY_DEFAULT);
2250 CookieList old_cookies;
2251 old_cookies.push_back(cookie1);
2252 old_cookies.push_back(cookie2);
2253 old_cookies.push_back(cookie4);
2254 old_cookies.push_back(cookie5);
2255 old_cookies.push_back(cookie6);
2256 old_cookies.push_back(cookie7);
2258 CookieList new_cookies;
2259 new_cookies.push_back(cookie1);
2260 new_cookies.push_back(cookie3);
2261 new_cookies.push_back(cookie4_with_new_value);
2262 new_cookies.push_back(cookie5_with_new_creation_time);
2263 new_cookies.push_back(cookie6_with_new_path);
2264 new_cookies.push_back(cookie7);
2265 new_cookies.push_back(cookie7_with_new_path);
2267 CookieList cookies_to_add;
2268 CookieList cookies_to_delete;
2270 cm->ComputeCookieDiff(&old_cookies, &new_cookies, &cookies_to_add,
2271 &cookies_to_delete);
2273 // |cookie1| has not changed.
2274 EXPECT_FALSE(IsCookieInList(cookie1, cookies_to_add));
2275 EXPECT_FALSE(IsCookieInList(cookie1, cookies_to_delete));
2277 // |cookie2| has been deleted.
2278 EXPECT_FALSE(IsCookieInList(cookie2, cookies_to_add));
2279 EXPECT_TRUE(IsCookieInList(cookie2, cookies_to_delete));
2281 // |cookie3| has been added.
2282 EXPECT_TRUE(IsCookieInList(cookie3, cookies_to_add));
2283 EXPECT_FALSE(IsCookieInList(cookie3, cookies_to_delete));
2285 // |cookie4| has a new value: new cookie overrides the old one (which does not
2286 // need to be explicitly removed).
2287 EXPECT_FALSE(IsCookieInList(cookie4, cookies_to_add));
2288 EXPECT_FALSE(IsCookieInList(cookie4, cookies_to_delete));
2289 EXPECT_TRUE(IsCookieInList(cookie4_with_new_value, cookies_to_add));
2290 EXPECT_FALSE(IsCookieInList(cookie4_with_new_value, cookies_to_delete));
2292 // |cookie5| has a new creation time: new cookie overrides the old one (which
2293 // does not need to be explicitly removed).
2294 EXPECT_FALSE(IsCookieInList(cookie5, cookies_to_add));
2295 EXPECT_FALSE(IsCookieInList(cookie5, cookies_to_delete));
2296 EXPECT_TRUE(IsCookieInList(cookie5_with_new_creation_time, cookies_to_add));
2297 EXPECT_FALSE(
2298 IsCookieInList(cookie5_with_new_creation_time, cookies_to_delete));
2300 // |cookie6| has a new path: the new cookie does not overrides the old one,
2301 // which needs to be explicitly removed.
2302 EXPECT_FALSE(IsCookieInList(cookie6, cookies_to_add));
2303 EXPECT_TRUE(IsCookieInList(cookie6, cookies_to_delete));
2304 EXPECT_TRUE(IsCookieInList(cookie6_with_new_path, cookies_to_add));
2305 EXPECT_FALSE(IsCookieInList(cookie6_with_new_path, cookies_to_delete));
2307 // |cookie7| is kept and |cookie7_with_new_path| is added as a new cookie.
2308 EXPECT_FALSE(IsCookieInList(cookie7, cookies_to_add));
2309 EXPECT_FALSE(IsCookieInList(cookie7, cookies_to_delete));
2310 EXPECT_TRUE(IsCookieInList(cookie7_with_new_path, cookies_to_add));
2311 EXPECT_FALSE(IsCookieInList(cookie7_with_new_path, cookies_to_delete));
2314 TEST_F(CookieMonsterTest, HistogramCheck) {
2315 scoped_refptr<CookieMonster> cm(new CookieMonster(NULL, NULL));
2316 // Should match call in InitializeHistograms, but doesn't really matter
2317 // since the histogram should have been initialized by the CM construction
2318 // above.
2319 base::HistogramBase* expired_histogram = base::Histogram::FactoryGet(
2320 "Cookie.ExpirationDurationMinutes", 1, 10 * 365 * 24 * 60, 50,
2321 base::Histogram::kUmaTargetedHistogramFlag);
2323 scoped_ptr<base::HistogramSamples> samples1(
2324 expired_histogram->SnapshotSamples());
2325 ASSERT_TRUE(SetCookieWithDetails(
2326 cm.get(), GURL("http://fake.a.url"), "a", "b", "a.url", "/",
2327 base::Time::Now() + base::TimeDelta::FromMinutes(59), false, false, false,
2328 COOKIE_PRIORITY_DEFAULT));
2330 scoped_ptr<base::HistogramSamples> samples2(
2331 expired_histogram->SnapshotSamples());
2332 EXPECT_EQ(samples1->TotalCount() + 1, samples2->TotalCount());
2334 // kValidCookieLine creates a session cookie.
2335 ASSERT_TRUE(SetCookie(cm.get(), url_google_, kValidCookieLine));
2337 scoped_ptr<base::HistogramSamples> samples3(
2338 expired_histogram->SnapshotSamples());
2339 EXPECT_EQ(samples2->TotalCount(), samples3->TotalCount());
2342 namespace {
2344 class MultiThreadedCookieMonsterTest : public CookieMonsterTest {
2345 public:
2346 MultiThreadedCookieMonsterTest() : other_thread_("CMTthread") {}
2348 // Helper methods for calling the asynchronous CookieMonster methods
2349 // from a different thread.
2351 void GetAllCookiesTask(CookieMonster* cm, GetCookieListCallback* callback) {
2352 cm->GetAllCookiesAsync(
2353 base::Bind(&GetCookieListCallback::Run, base::Unretained(callback)));
2356 void GetAllCookiesForURLTask(CookieMonster* cm,
2357 const GURL& url,
2358 GetCookieListCallback* callback) {
2359 cm->GetAllCookiesForURLAsync(url, base::Bind(&GetCookieListCallback::Run,
2360 base::Unretained(callback)));
2363 void GetAllCookiesForURLWithOptionsTask(CookieMonster* cm,
2364 const GURL& url,
2365 const CookieOptions& options,
2366 GetCookieListCallback* callback) {
2367 cm->GetAllCookiesForURLWithOptionsAsync(
2368 url, options,
2369 base::Bind(&GetCookieListCallback::Run, base::Unretained(callback)));
2372 void SetCookieWithDetailsTask(CookieMonster* cm,
2373 const GURL& url,
2374 ResultSavingCookieCallback<bool>* callback) {
2375 // Define the parameters here instead of in the calling fucntion.
2376 // The maximum number of parameters for Bind function is 6.
2377 std::string name = "A";
2378 std::string value = "B";
2379 std::string domain = std::string();
2380 std::string path = "/foo";
2381 base::Time expiration_time = base::Time();
2382 bool secure = false;
2383 bool http_only = false;
2384 bool first_party_only = false;
2385 CookiePriority priority = COOKIE_PRIORITY_DEFAULT;
2386 cm->SetCookieWithDetailsAsync(
2387 url, name, value, domain, path, expiration_time, secure, http_only,
2388 first_party_only, priority,
2389 base::Bind(&ResultSavingCookieCallback<bool>::Run,
2390 base::Unretained(callback)));
2393 void DeleteAllCreatedBetweenTask(CookieMonster* cm,
2394 const base::Time& delete_begin,
2395 const base::Time& delete_end,
2396 ResultSavingCookieCallback<int>* callback) {
2397 cm->DeleteAllCreatedBetweenAsync(
2398 delete_begin, delete_end,
2399 base::Bind(&ResultSavingCookieCallback<int>::Run,
2400 base::Unretained(callback)));
2403 void DeleteAllForHostTask(CookieMonster* cm,
2404 const GURL& url,
2405 ResultSavingCookieCallback<int>* callback) {
2406 cm->DeleteAllForHostAsync(url,
2407 base::Bind(&ResultSavingCookieCallback<int>::Run,
2408 base::Unretained(callback)));
2411 void DeleteAllCreatedBetweenForHostTask(
2412 CookieMonster* cm,
2413 const base::Time delete_begin,
2414 const base::Time delete_end,
2415 const GURL& url,
2416 ResultSavingCookieCallback<int>* callback) {
2417 cm->DeleteAllCreatedBetweenForHostAsync(
2418 delete_begin, delete_end, url,
2419 base::Bind(&ResultSavingCookieCallback<int>::Run,
2420 base::Unretained(callback)));
2423 void DeleteCanonicalCookieTask(CookieMonster* cm,
2424 const CanonicalCookie& cookie,
2425 ResultSavingCookieCallback<bool>* callback) {
2426 cm->DeleteCanonicalCookieAsync(
2427 cookie, base::Bind(&ResultSavingCookieCallback<bool>::Run,
2428 base::Unretained(callback)));
2431 protected:
2432 void RunOnOtherThread(const base::Closure& task) {
2433 other_thread_.Start();
2434 other_thread_.message_loop()->PostTask(FROM_HERE, task);
2435 RunFor(kTimeout);
2436 other_thread_.Stop();
2439 Thread other_thread_;
2442 } // namespace
2444 TEST_F(MultiThreadedCookieMonsterTest, ThreadCheckGetAllCookies) {
2445 scoped_refptr<CookieMonster> cm(new CookieMonster(NULL, NULL));
2446 EXPECT_TRUE(SetCookie(cm.get(), url_google_, "A=B"));
2447 CookieList cookies = GetAllCookies(cm.get());
2448 CookieList::const_iterator it = cookies.begin();
2449 ASSERT_TRUE(it != cookies.end());
2450 EXPECT_EQ("www.google.izzle", it->Domain());
2451 EXPECT_EQ("A", it->Name());
2452 ASSERT_TRUE(++it == cookies.end());
2453 GetCookieListCallback callback(&other_thread_);
2454 base::Closure task =
2455 base::Bind(&net::MultiThreadedCookieMonsterTest::GetAllCookiesTask,
2456 base::Unretained(this), cm, &callback);
2457 RunOnOtherThread(task);
2458 EXPECT_TRUE(callback.did_run());
2459 it = callback.cookies().begin();
2460 ASSERT_TRUE(it != callback.cookies().end());
2461 EXPECT_EQ("www.google.izzle", it->Domain());
2462 EXPECT_EQ("A", it->Name());
2463 ASSERT_TRUE(++it == callback.cookies().end());
2466 TEST_F(MultiThreadedCookieMonsterTest, ThreadCheckGetAllCookiesForURL) {
2467 scoped_refptr<CookieMonster> cm(new CookieMonster(NULL, NULL));
2468 EXPECT_TRUE(SetCookie(cm.get(), url_google_, "A=B"));
2469 CookieList cookies = GetAllCookiesForURL(cm.get(), url_google_);
2470 CookieList::const_iterator it = cookies.begin();
2471 ASSERT_TRUE(it != cookies.end());
2472 EXPECT_EQ("www.google.izzle", it->Domain());
2473 EXPECT_EQ("A", it->Name());
2474 ASSERT_TRUE(++it == cookies.end());
2475 GetCookieListCallback callback(&other_thread_);
2476 base::Closure task =
2477 base::Bind(&net::MultiThreadedCookieMonsterTest::GetAllCookiesForURLTask,
2478 base::Unretained(this), cm, url_google_, &callback);
2479 RunOnOtherThread(task);
2480 EXPECT_TRUE(callback.did_run());
2481 it = callback.cookies().begin();
2482 ASSERT_TRUE(it != callback.cookies().end());
2483 EXPECT_EQ("www.google.izzle", it->Domain());
2484 EXPECT_EQ("A", it->Name());
2485 ASSERT_TRUE(++it == callback.cookies().end());
2488 TEST_F(MultiThreadedCookieMonsterTest, ThreadCheckGetAllCookiesForURLWithOpt) {
2489 scoped_refptr<CookieMonster> cm(new CookieMonster(NULL, NULL));
2490 EXPECT_TRUE(SetCookie(cm.get(), url_google_, "A=B"));
2491 CookieOptions options;
2492 CookieList cookies =
2493 GetAllCookiesForURLWithOptions(cm.get(), url_google_, options);
2494 CookieList::const_iterator it = cookies.begin();
2495 ASSERT_TRUE(it != cookies.end());
2496 EXPECT_EQ("www.google.izzle", it->Domain());
2497 EXPECT_EQ("A", it->Name());
2498 ASSERT_TRUE(++it == cookies.end());
2499 GetCookieListCallback callback(&other_thread_);
2500 base::Closure task = base::Bind(
2501 &net::MultiThreadedCookieMonsterTest::GetAllCookiesForURLWithOptionsTask,
2502 base::Unretained(this), cm, url_google_, options, &callback);
2503 RunOnOtherThread(task);
2504 EXPECT_TRUE(callback.did_run());
2505 it = callback.cookies().begin();
2506 ASSERT_TRUE(it != callback.cookies().end());
2507 EXPECT_EQ("www.google.izzle", it->Domain());
2508 EXPECT_EQ("A", it->Name());
2509 ASSERT_TRUE(++it == callback.cookies().end());
2512 TEST_F(MultiThreadedCookieMonsterTest, ThreadCheckSetCookieWithDetails) {
2513 scoped_refptr<CookieMonster> cm(new CookieMonster(NULL, NULL));
2514 EXPECT_TRUE(SetCookieWithDetails(cm.get(), url_google_foo_, "A", "B",
2515 std::string(), "/foo", base::Time(), false,
2516 false, false, COOKIE_PRIORITY_DEFAULT));
2517 ResultSavingCookieCallback<bool> callback(&other_thread_);
2518 base::Closure task =
2519 base::Bind(&net::MultiThreadedCookieMonsterTest::SetCookieWithDetailsTask,
2520 base::Unretained(this), cm, url_google_foo_, &callback);
2521 RunOnOtherThread(task);
2522 EXPECT_TRUE(callback.did_run());
2523 EXPECT_TRUE(callback.result());
2526 TEST_F(MultiThreadedCookieMonsterTest, ThreadCheckDeleteAllCreatedBetween) {
2527 scoped_refptr<CookieMonster> cm(new CookieMonster(NULL, NULL));
2528 CookieOptions options;
2529 Time now = Time::Now();
2530 EXPECT_TRUE(SetCookieWithOptions(cm.get(), url_google_, "A=B", options));
2531 EXPECT_EQ(1, DeleteAllCreatedBetween(cm.get(), now - TimeDelta::FromDays(99),
2532 Time()));
2533 EXPECT_TRUE(SetCookieWithOptions(cm.get(), url_google_, "A=B", options));
2534 ResultSavingCookieCallback<int> callback(&other_thread_);
2535 base::Closure task = base::Bind(
2536 &net::MultiThreadedCookieMonsterTest::DeleteAllCreatedBetweenTask,
2537 base::Unretained(this), cm, now - TimeDelta::FromDays(99), Time(),
2538 &callback);
2539 RunOnOtherThread(task);
2540 EXPECT_TRUE(callback.did_run());
2541 EXPECT_EQ(1, callback.result());
2544 TEST_F(MultiThreadedCookieMonsterTest, ThreadCheckDeleteAllForHost) {
2545 scoped_refptr<CookieMonster> cm(new CookieMonster(NULL, NULL));
2546 CookieOptions options;
2547 EXPECT_TRUE(SetCookieWithOptions(cm.get(), url_google_, "A=B", options));
2548 EXPECT_EQ(1, DeleteAllForHost(cm.get(), url_google_));
2549 EXPECT_TRUE(SetCookieWithOptions(cm.get(), url_google_, "A=B", options));
2550 ResultSavingCookieCallback<int> callback(&other_thread_);
2551 base::Closure task =
2552 base::Bind(&net::MultiThreadedCookieMonsterTest::DeleteAllForHostTask,
2553 base::Unretained(this), cm, url_google_, &callback);
2554 RunOnOtherThread(task);
2555 EXPECT_TRUE(callback.did_run());
2556 EXPECT_EQ(1, callback.result());
2559 TEST_F(MultiThreadedCookieMonsterTest,
2560 ThreadCheckDeleteAllCreatedBetweenForHost) {
2561 scoped_refptr<CookieMonster> cm(new CookieMonster(NULL, NULL));
2562 GURL url_not_google("http://www.notgoogle.com");
2564 CookieOptions options;
2565 Time now = Time::Now();
2566 // ago1 < ago2 < ago3 < now.
2567 Time ago1 = now - TimeDelta::FromDays(101);
2568 Time ago2 = now - TimeDelta::FromDays(100);
2569 Time ago3 = now - TimeDelta::FromDays(99);
2571 // These 3 cookies match the first deletion.
2572 EXPECT_TRUE(SetCookieWithOptions(cm.get(), url_google_, "A=B", options));
2573 EXPECT_TRUE(SetCookieWithOptions(cm.get(), url_google_, "C=D", options));
2574 EXPECT_TRUE(SetCookieWithOptions(cm.get(), url_google_, "Y=Z", options));
2576 // This cookie does not match host.
2577 EXPECT_TRUE(SetCookieWithOptions(cm.get(), url_not_google, "E=F", options));
2579 // This cookie does not match time range: [ago3, inf], for first deletion, but
2580 // matches for the second deletion.
2581 EXPECT_TRUE(cm->SetCookieWithCreationTime(url_google_, "G=H", ago2));
2583 // 1. First set of deletions.
2584 EXPECT_EQ(
2585 3, // Deletes A=B, C=D, Y=Z
2586 DeleteAllCreatedBetweenForHost(cm.get(), ago3, Time::Max(), url_google_));
2588 EXPECT_TRUE(SetCookieWithOptions(cm.get(), url_google_, "A=B", options));
2589 ResultSavingCookieCallback<int> callback(&other_thread_);
2591 // 2. Second set of deletions.
2592 base::Closure task = base::Bind(
2593 &net::MultiThreadedCookieMonsterTest::DeleteAllCreatedBetweenForHostTask,
2594 base::Unretained(this), cm, ago1, Time(), url_google_, &callback);
2595 RunOnOtherThread(task);
2596 EXPECT_TRUE(callback.did_run());
2597 EXPECT_EQ(2, callback.result()); // Deletes A=B, G=H.
2600 TEST_F(MultiThreadedCookieMonsterTest, ThreadCheckDeleteCanonicalCookie) {
2601 scoped_refptr<CookieMonster> cm(new CookieMonster(NULL, NULL));
2602 CookieOptions options;
2603 EXPECT_TRUE(SetCookieWithOptions(cm.get(), url_google_, "A=B", options));
2604 CookieList cookies = GetAllCookies(cm.get());
2605 CookieList::iterator it = cookies.begin();
2606 EXPECT_TRUE(DeleteCanonicalCookie(cm.get(), *it));
2608 EXPECT_TRUE(SetCookieWithOptions(cm.get(), url_google_, "A=B", options));
2609 ResultSavingCookieCallback<bool> callback(&other_thread_);
2610 cookies = GetAllCookies(cm.get());
2611 it = cookies.begin();
2612 base::Closure task = base::Bind(
2613 &net::MultiThreadedCookieMonsterTest::DeleteCanonicalCookieTask,
2614 base::Unretained(this), cm, *it, &callback);
2615 RunOnOtherThread(task);
2616 EXPECT_TRUE(callback.did_run());
2617 EXPECT_TRUE(callback.result());
2620 // Ensure that cookies for http, https, ws, and wss all share the same storage
2621 // and policies when GetAllCookiesForURLAsync is used. This test is part of
2622 // MultiThreadedCookieMonsterTest in order to test and use
2623 // GetAllCookiesForURLAsync, but it does not use any additional threads.
2624 TEST_F(MultiThreadedCookieMonsterTest, GetAllCookiesForURLEffectiveDomain) {
2625 std::vector<CanonicalCookie*> cookies;
2626 // This cookie will be freed by the CookieMonster.
2627 cookies.push_back(CanonicalCookie::Create(url_google_, kValidCookieLine,
2628 Time::Now(), CookieOptions()));
2629 CanonicalCookie cookie = *cookies[0];
2630 scoped_refptr<NewMockPersistentCookieStore> store(
2631 new NewMockPersistentCookieStore);
2632 scoped_refptr<CookieMonster> cm(new CookieMonster(store.get(), NULL));
2634 CookieMonster::PersistentCookieStore::LoadedCallback loaded_callback;
2635 ::testing::StrictMock<::testing::MockFunction<void(int)>> checkpoint;
2636 const std::string key =
2637 cookie_util::GetEffectiveDomain(url_google_.scheme(), url_google_.host());
2639 ::testing::InSequence s;
2640 EXPECT_CALL(checkpoint, Call(0));
2641 EXPECT_CALL(*store, Load(::testing::_));
2642 EXPECT_CALL(*store, LoadCookiesForKey(key, ::testing::_))
2643 .WillOnce(::testing::SaveArg<1>(&loaded_callback));
2644 EXPECT_CALL(checkpoint, Call(1));
2645 // LoadCookiesForKey will never be called after checkpoint.Call(1) although
2646 // we will call GetAllCookiesForURLAsync again, because all URLs below share
2647 // the same key.
2648 EXPECT_CALL(*store, LoadCookiesForKey(::testing::_, ::testing::_)).Times(0);
2650 GetCookieListCallback callback;
2651 checkpoint.Call(0);
2652 GetAllCookiesForURLTask(cm.get(), url_google_, &callback);
2653 checkpoint.Call(1);
2654 ASSERT_FALSE(callback.did_run());
2655 // Pass the cookies to the CookieMonster.
2656 loaded_callback.Run(cookies);
2657 // Now GetAllCookiesForURLTask is done.
2658 ASSERT_TRUE(callback.did_run());
2659 // See that the callback was called with the cookies.
2660 ASSERT_EQ(1u, callback.cookies().size());
2661 EXPECT_TRUE(cookie.IsEquivalent(callback.cookies()[0]));
2663 // All urls in |urls| should share the same cookie domain.
2664 const GURL kUrls[] = {
2665 url_google_,
2666 url_google_secure_,
2667 GURL(kUrlGoogleWebSocket),
2668 GURL(kUrlGoogleWebSocketSecure),
2670 for (const GURL& url : kUrls) {
2671 // Call the function with |url| and verify it is done synchronously without
2672 // calling LoadCookiesForKey.
2673 GetCookieListCallback callback;
2674 GetAllCookiesForURLTask(cm.get(), url, &callback);
2675 ASSERT_TRUE(callback.did_run());
2676 ASSERT_EQ(1u, callback.cookies().size());
2677 EXPECT_TRUE(cookie.IsEquivalent(callback.cookies()[0]));
2681 TEST_F(CookieMonsterTest, InvalidExpiryTime) {
2682 std::string cookie_line =
2683 std::string(kValidCookieLine) + "; expires=Blarg arg arg";
2684 scoped_ptr<CanonicalCookie> cookie(CanonicalCookie::Create(
2685 url_google_, cookie_line, Time::Now(), CookieOptions()));
2686 ASSERT_FALSE(cookie->IsPersistent());
2689 // Test that CookieMonster writes session cookies into the underlying
2690 // CookieStore if the "persist session cookies" option is on.
2691 TEST_F(CookieMonsterTest, PersistSessionCookies) {
2692 scoped_refptr<MockPersistentCookieStore> store(new MockPersistentCookieStore);
2693 scoped_refptr<CookieMonster> cm(new CookieMonster(store.get(), NULL));
2694 cm->SetPersistSessionCookies(true);
2696 // All cookies set with SetCookie are session cookies.
2697 EXPECT_TRUE(SetCookie(cm.get(), url_google_, "A=B"));
2698 EXPECT_EQ("A=B", GetCookies(cm.get(), url_google_));
2700 // The cookie was written to the backing store.
2701 EXPECT_EQ(1u, store->commands().size());
2702 EXPECT_EQ(CookieStoreCommand::ADD, store->commands()[0].type);
2703 EXPECT_EQ("A", store->commands()[0].cookie.Name());
2704 EXPECT_EQ("B", store->commands()[0].cookie.Value());
2706 // Modify the cookie.
2707 EXPECT_TRUE(SetCookie(cm.get(), url_google_, "A=C"));
2708 EXPECT_EQ("A=C", GetCookies(cm.get(), url_google_));
2709 EXPECT_EQ(3u, store->commands().size());
2710 EXPECT_EQ(CookieStoreCommand::REMOVE, store->commands()[1].type);
2711 EXPECT_EQ("A", store->commands()[1].cookie.Name());
2712 EXPECT_EQ("B", store->commands()[1].cookie.Value());
2713 EXPECT_EQ(CookieStoreCommand::ADD, store->commands()[2].type);
2714 EXPECT_EQ("A", store->commands()[2].cookie.Name());
2715 EXPECT_EQ("C", store->commands()[2].cookie.Value());
2717 // Delete the cookie.
2718 DeleteCookie(cm.get(), url_google_, "A");
2719 EXPECT_EQ("", GetCookies(cm.get(), url_google_));
2720 EXPECT_EQ(4u, store->commands().size());
2721 EXPECT_EQ(CookieStoreCommand::REMOVE, store->commands()[3].type);
2722 EXPECT_EQ("A", store->commands()[3].cookie.Name());
2723 EXPECT_EQ("C", store->commands()[3].cookie.Value());
2726 // Test the commands sent to the persistent cookie store.
2727 TEST_F(CookieMonsterTest, PersisentCookieStorageTest) {
2728 scoped_refptr<MockPersistentCookieStore> store(new MockPersistentCookieStore);
2729 scoped_refptr<CookieMonster> cm(new CookieMonster(store.get(), NULL));
2731 // Add a cookie.
2732 EXPECT_TRUE(SetCookie(cm.get(), url_google_,
2733 "A=B; expires=Mon, 18-Apr-22 22:50:13 GMT"));
2734 this->MatchCookieLines("A=B", GetCookies(cm.get(), url_google_));
2735 ASSERT_EQ(1u, store->commands().size());
2736 EXPECT_EQ(CookieStoreCommand::ADD, store->commands()[0].type);
2737 // Remove it.
2738 EXPECT_TRUE(SetCookie(cm.get(), url_google_, "A=B; max-age=0"));
2739 this->MatchCookieLines(std::string(), GetCookies(cm.get(), url_google_));
2740 ASSERT_EQ(2u, store->commands().size());
2741 EXPECT_EQ(CookieStoreCommand::REMOVE, store->commands()[1].type);
2743 // Add a cookie.
2744 EXPECT_TRUE(SetCookie(cm.get(), url_google_,
2745 "A=B; expires=Mon, 18-Apr-22 22:50:13 GMT"));
2746 this->MatchCookieLines("A=B", GetCookies(cm.get(), url_google_));
2747 ASSERT_EQ(3u, store->commands().size());
2748 EXPECT_EQ(CookieStoreCommand::ADD, store->commands()[2].type);
2749 // Overwrite it.
2750 EXPECT_TRUE(SetCookie(cm.get(), url_google_,
2751 "A=Foo; expires=Mon, 18-Apr-22 22:50:14 GMT"));
2752 this->MatchCookieLines("A=Foo", GetCookies(cm.get(), url_google_));
2753 ASSERT_EQ(5u, store->commands().size());
2754 EXPECT_EQ(CookieStoreCommand::REMOVE, store->commands()[3].type);
2755 EXPECT_EQ(CookieStoreCommand::ADD, store->commands()[4].type);
2757 // Create some non-persistent cookies and check that they don't go to the
2758 // persistent storage.
2759 EXPECT_TRUE(SetCookie(cm.get(), url_google_, "B=Bar"));
2760 this->MatchCookieLines("A=Foo; B=Bar", GetCookies(cm.get(), url_google_));
2761 EXPECT_EQ(5u, store->commands().size());
2764 // Test to assure that cookies with control characters are purged appropriately.
2765 // See http://crbug.com/238041 for background.
2766 TEST_F(CookieMonsterTest, ControlCharacterPurge) {
2767 const Time now1(Time::Now());
2768 const Time now2(Time::Now() + TimeDelta::FromSeconds(1));
2769 const Time now3(Time::Now() + TimeDelta::FromSeconds(2));
2770 const Time later(now1 + TimeDelta::FromDays(1));
2771 const GURL url("http://host/path");
2772 const std::string domain("host");
2773 const std::string path("/path");
2775 scoped_refptr<MockPersistentCookieStore> store(new MockPersistentCookieStore);
2777 std::vector<CanonicalCookie*> initial_cookies;
2779 AddCookieToList(domain, "foo=bar; path=" + path, now1, &initial_cookies);
2781 // We have to manually build this cookie because it contains a control
2782 // character, and our cookie line parser rejects control characters.
2783 CanonicalCookie* cc =
2784 new CanonicalCookie(url, "baz",
2785 "\x05"
2786 "boo",
2787 domain, path, now2, later, now2, false, false, false,
2788 COOKIE_PRIORITY_DEFAULT);
2789 initial_cookies.push_back(cc);
2791 AddCookieToList(domain, "hello=world; path=" + path, now3, &initial_cookies);
2793 // Inject our initial cookies into the mock PersistentCookieStore.
2794 store->SetLoadExpectation(true, initial_cookies);
2796 scoped_refptr<CookieMonster> cm(new CookieMonster(store.get(), NULL));
2798 EXPECT_EQ("foo=bar; hello=world", GetCookies(cm.get(), url));
2801 class CookieMonsterNotificationTest : public CookieMonsterTest {
2802 public:
2803 CookieMonsterNotificationTest()
2804 : test_url_("http://www.google.com/foo"),
2805 store_(new MockPersistentCookieStore),
2806 monster_(new CookieMonster(store_.get(), NULL)) {}
2808 ~CookieMonsterNotificationTest() override {}
2810 CookieMonster* monster() { return monster_.get(); }
2812 protected:
2813 const GURL test_url_;
2815 private:
2816 scoped_refptr<MockPersistentCookieStore> store_;
2817 scoped_refptr<CookieMonster> monster_;
2820 void RecordCookieChanges(std::vector<net::CanonicalCookie>* out_cookies,
2821 std::vector<bool>* out_removes,
2822 const net::CanonicalCookie& cookie,
2823 bool removed) {
2824 DCHECK(out_cookies);
2825 out_cookies->push_back(cookie);
2826 if (out_removes)
2827 out_removes->push_back(removed);
2830 TEST_F(CookieMonsterNotificationTest, NoNotifyWithNoCookie) {
2831 std::vector<net::CanonicalCookie> cookies;
2832 scoped_ptr<CookieStore::CookieChangedSubscription> sub(
2833 monster()->AddCallbackForCookie(
2834 test_url_, "abc",
2835 base::Bind(&RecordCookieChanges, &cookies, nullptr)));
2836 base::MessageLoop::current()->RunUntilIdle();
2837 EXPECT_EQ(0U, cookies.size());
2840 TEST_F(CookieMonsterNotificationTest, NoNotifyWithInitialCookie) {
2841 std::vector<net::CanonicalCookie> cookies;
2842 SetCookie(monster(), test_url_, "abc=def");
2843 base::MessageLoop::current()->RunUntilIdle();
2844 scoped_ptr<CookieStore::CookieChangedSubscription> sub(
2845 monster()->AddCallbackForCookie(
2846 test_url_, "abc",
2847 base::Bind(&RecordCookieChanges, &cookies, nullptr)));
2848 base::MessageLoop::current()->RunUntilIdle();
2849 EXPECT_EQ(0U, cookies.size());
2852 TEST_F(CookieMonsterNotificationTest, NotifyOnSet) {
2853 std::vector<net::CanonicalCookie> cookies;
2854 std::vector<bool> removes;
2855 scoped_ptr<CookieStore::CookieChangedSubscription> sub(
2856 monster()->AddCallbackForCookie(
2857 test_url_, "abc",
2858 base::Bind(&RecordCookieChanges, &cookies, &removes)));
2859 SetCookie(monster(), test_url_, "abc=def");
2860 base::MessageLoop::current()->RunUntilIdle();
2861 EXPECT_EQ(1U, cookies.size());
2862 EXPECT_EQ(1U, removes.size());
2864 EXPECT_EQ("abc", cookies[0].Name());
2865 EXPECT_EQ("def", cookies[0].Value());
2866 EXPECT_FALSE(removes[0]);
2869 TEST_F(CookieMonsterNotificationTest, NotifyOnDelete) {
2870 std::vector<net::CanonicalCookie> cookies;
2871 std::vector<bool> removes;
2872 scoped_ptr<CookieStore::CookieChangedSubscription> sub(
2873 monster()->AddCallbackForCookie(
2874 test_url_, "abc",
2875 base::Bind(&RecordCookieChanges, &cookies, &removes)));
2876 SetCookie(monster(), test_url_, "abc=def");
2877 base::MessageLoop::current()->RunUntilIdle();
2878 EXPECT_EQ(1U, cookies.size());
2879 EXPECT_EQ(1U, removes.size());
2881 DeleteCookie(monster(), test_url_, "abc");
2882 base::MessageLoop::current()->RunUntilIdle();
2883 EXPECT_EQ(2U, cookies.size());
2884 EXPECT_EQ(2U, removes.size());
2886 EXPECT_EQ("abc", cookies[1].Name());
2887 EXPECT_EQ("def", cookies[1].Value());
2888 EXPECT_TRUE(removes[1]);
2891 TEST_F(CookieMonsterNotificationTest, NotifyOnUpdate) {
2892 std::vector<net::CanonicalCookie> cookies;
2893 std::vector<bool> removes;
2894 scoped_ptr<CookieStore::CookieChangedSubscription> sub(
2895 monster()->AddCallbackForCookie(
2896 test_url_, "abc",
2897 base::Bind(&RecordCookieChanges, &cookies, &removes)));
2898 SetCookie(monster(), test_url_, "abc=def");
2899 base::MessageLoop::current()->RunUntilIdle();
2900 EXPECT_EQ(1U, cookies.size());
2902 // Replacing an existing cookie is actually a two-phase delete + set
2903 // operation, so we get an extra notification.
2904 SetCookie(monster(), test_url_, "abc=ghi");
2905 base::MessageLoop::current()->RunUntilIdle();
2907 EXPECT_EQ(3U, cookies.size());
2908 EXPECT_EQ(3U, removes.size());
2910 EXPECT_EQ("abc", cookies[1].Name());
2911 EXPECT_EQ("def", cookies[1].Value());
2912 EXPECT_TRUE(removes[1]);
2914 EXPECT_EQ("abc", cookies[2].Name());
2915 EXPECT_EQ("ghi", cookies[2].Value());
2916 EXPECT_FALSE(removes[2]);
2919 TEST_F(CookieMonsterNotificationTest, MultipleNotifies) {
2920 std::vector<net::CanonicalCookie> cookies0;
2921 std::vector<net::CanonicalCookie> cookies1;
2922 scoped_ptr<CookieStore::CookieChangedSubscription> sub0(
2923 monster()->AddCallbackForCookie(
2924 test_url_, "abc",
2925 base::Bind(&RecordCookieChanges, &cookies0, nullptr)));
2926 scoped_ptr<CookieStore::CookieChangedSubscription> sub1(
2927 monster()->AddCallbackForCookie(
2928 test_url_, "def",
2929 base::Bind(&RecordCookieChanges, &cookies1, nullptr)));
2930 SetCookie(monster(), test_url_, "abc=def");
2931 base::MessageLoop::current()->RunUntilIdle();
2932 EXPECT_EQ(1U, cookies0.size());
2933 EXPECT_EQ(0U, cookies1.size());
2934 SetCookie(monster(), test_url_, "def=abc");
2935 base::MessageLoop::current()->RunUntilIdle();
2936 EXPECT_EQ(1U, cookies0.size());
2937 EXPECT_EQ(1U, cookies1.size());
2940 TEST_F(CookieMonsterNotificationTest, MultipleSameNotifies) {
2941 std::vector<net::CanonicalCookie> cookies0;
2942 std::vector<net::CanonicalCookie> cookies1;
2943 scoped_ptr<CookieStore::CookieChangedSubscription> sub0(
2944 monster()->AddCallbackForCookie(
2945 test_url_, "abc",
2946 base::Bind(&RecordCookieChanges, &cookies0, nullptr)));
2947 scoped_ptr<CookieStore::CookieChangedSubscription> sub1(
2948 monster()->AddCallbackForCookie(
2949 test_url_, "abc",
2950 base::Bind(&RecordCookieChanges, &cookies1, nullptr)));
2951 SetCookie(monster(), test_url_, "abc=def");
2952 base::MessageLoop::current()->RunUntilIdle();
2953 EXPECT_EQ(1U, cookies0.size());
2954 EXPECT_EQ(1U, cookies0.size());
2957 } // namespace net