[Android] Implement 3-way sensor fallback for Device Orientation.
[chromium-blink-merge.git] / net / cookies / cookie_monster_unittest.cc
blobea9b13cf4c1c9a3dd81c9b10aa0c21a58af0d5ae
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/location.h"
14 #include "base/memory/ref_counted.h"
15 #include "base/memory/scoped_ptr.h"
16 #include "base/memory/scoped_vector.h"
17 #include "base/message_loop/message_loop.h"
18 #include "base/metrics/histogram.h"
19 #include "base/metrics/histogram_samples.h"
20 #include "base/single_thread_task_runner.h"
21 #include "base/strings/string_number_conversions.h"
22 #include "base/strings/string_piece.h"
23 #include "base/strings/string_split.h"
24 #include "base/strings/string_tokenizer.h"
25 #include "base/strings/stringprintf.h"
26 #include "base/test/histogram_tester.h"
27 #include "base/thread_task_runner_handle.h"
28 #include "base/threading/thread.h"
29 #include "base/time/time.h"
30 #include "net/cookies/canonical_cookie.h"
31 #include "net/cookies/cookie_constants.h"
32 #include "net/cookies/cookie_monster.h"
33 #include "net/cookies/cookie_monster_store_test.h" // For CookieStore mock
34 #include "net/cookies/cookie_util.h"
35 #include "net/cookies/parsed_cookie.h"
36 #include "testing/gmock/include/gmock/gmock.h"
37 #include "testing/gtest/include/gtest/gtest.h"
38 #include "url/gurl.h"
40 namespace net {
42 using base::Time;
43 using base::TimeDelta;
45 namespace {
47 // TODO(erikwright): Replace the pre-existing MockPersistentCookieStore (and
48 // brethren) with this one, and remove the 'New' prefix.
49 class NewMockPersistentCookieStore
50 : public CookieMonster::PersistentCookieStore {
51 public:
52 MOCK_METHOD1(Load, void(const LoadedCallback& loaded_callback));
53 MOCK_METHOD2(LoadCookiesForKey,
54 void(const std::string& key,
55 const LoadedCallback& loaded_callback));
56 MOCK_METHOD1(AddCookie, void(const CanonicalCookie& cc));
57 MOCK_METHOD1(UpdateCookieAccessTime, void(const CanonicalCookie& cc));
58 MOCK_METHOD1(DeleteCookie, void(const CanonicalCookie& cc));
59 virtual void Flush(const base::Closure& callback) {
60 if (!callback.is_null())
61 base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, callback);
63 MOCK_METHOD0(SetForceKeepSessionState, void());
65 private:
66 virtual ~NewMockPersistentCookieStore() {}
69 const char kTopLevelDomainPlus1[] = "http://www.harvard.edu";
70 const char kTopLevelDomainPlus2[] = "http://www.math.harvard.edu";
71 const char kTopLevelDomainPlus2Secure[] = "https://www.math.harvard.edu";
72 const char kTopLevelDomainPlus3[] = "http://www.bourbaki.math.harvard.edu";
73 const char kOtherDomain[] = "http://www.mit.edu";
74 const char kUrlGoogleSpecific[] = "http://www.gmail.google.izzle";
76 class GetCookieListCallback : public CookieCallback {
77 public:
78 GetCookieListCallback() {}
79 explicit GetCookieListCallback(Thread* run_in_thread)
80 : CookieCallback(run_in_thread) {}
82 void Run(const CookieList& cookies) {
83 cookies_ = cookies;
84 CallbackEpilogue();
87 const CookieList& cookies() { return cookies_; }
89 private:
90 CookieList cookies_;
93 struct CookieMonsterTestTraits {
94 static scoped_refptr<CookieStore> Create() {
95 return new CookieMonster(NULL, NULL);
98 static const bool is_cookie_monster = true;
99 static const bool supports_http_only = true;
100 static const bool supports_non_dotted_domains = true;
101 static const bool supports_trailing_dots = true;
102 static const bool filters_schemes = true;
103 static const bool has_path_prefix_bug = false;
104 static const int creation_time_granularity_in_ms = 0;
107 INSTANTIATE_TYPED_TEST_CASE_P(CookieMonster,
108 CookieStoreTest,
109 CookieMonsterTestTraits);
111 INSTANTIATE_TYPED_TEST_CASE_P(CookieMonster,
112 MultiThreadedCookieStoreTest,
113 CookieMonsterTestTraits);
115 class CookieMonsterTest : public CookieStoreTest<CookieMonsterTestTraits> {
116 protected:
117 CookieList GetAllCookies(CookieMonster* cm) {
118 DCHECK(cm);
119 GetCookieListCallback callback;
120 cm->GetAllCookiesAsync(
121 base::Bind(&GetCookieListCallback::Run, base::Unretained(&callback)));
122 RunFor(kTimeout);
123 EXPECT_TRUE(callback.did_run());
124 return callback.cookies();
127 CookieList GetAllCookiesForURL(CookieMonster* cm, const GURL& url) {
128 DCHECK(cm);
129 GetCookieListCallback callback;
130 cm->GetAllCookiesForURLAsync(url, base::Bind(&GetCookieListCallback::Run,
131 base::Unretained(&callback)));
132 RunFor(kTimeout);
133 EXPECT_TRUE(callback.did_run());
134 return callback.cookies();
137 CookieList GetAllCookiesForURLWithOptions(CookieMonster* cm,
138 const GURL& url,
139 const CookieOptions& options) {
140 DCHECK(cm);
141 GetCookieListCallback callback;
142 cm->GetAllCookiesForURLWithOptionsAsync(
143 url, options,
144 base::Bind(&GetCookieListCallback::Run, base::Unretained(&callback)));
145 RunFor(kTimeout);
146 EXPECT_TRUE(callback.did_run());
147 return callback.cookies();
150 bool SetCookieWithDetails(CookieMonster* cm,
151 const GURL& url,
152 const std::string& name,
153 const std::string& value,
154 const std::string& domain,
155 const std::string& path,
156 const base::Time& expiration_time,
157 bool secure,
158 bool http_only,
159 bool first_party_only,
160 CookiePriority priority) {
161 DCHECK(cm);
162 ResultSavingCookieCallback<bool> callback;
163 cm->SetCookieWithDetailsAsync(
164 url, name, value, domain, path, expiration_time, secure, http_only,
165 first_party_only, priority,
166 base::Bind(&ResultSavingCookieCallback<bool>::Run,
167 base::Unretained(&callback)));
168 RunFor(kTimeout);
169 EXPECT_TRUE(callback.did_run());
170 return callback.result();
173 bool SetAllCookies(CookieMonster* cm, const CookieList& list) {
174 DCHECK(cm);
175 ResultSavingCookieCallback<bool> callback;
176 cm->SetAllCookiesAsync(list,
177 base::Bind(&ResultSavingCookieCallback<bool>::Run,
178 base::Unretained(&callback)));
179 RunFor(kTimeout);
180 EXPECT_TRUE(callback.did_run());
181 return callback.result();
184 int DeleteAll(CookieMonster* cm) {
185 DCHECK(cm);
186 ResultSavingCookieCallback<int> callback;
187 cm->DeleteAllAsync(base::Bind(&ResultSavingCookieCallback<int>::Run,
188 base::Unretained(&callback)));
189 RunFor(kTimeout);
190 EXPECT_TRUE(callback.did_run());
191 return callback.result();
194 int DeleteAllCreatedBetween(CookieMonster* cm,
195 const base::Time& delete_begin,
196 const base::Time& delete_end) {
197 DCHECK(cm);
198 ResultSavingCookieCallback<int> callback;
199 cm->DeleteAllCreatedBetweenAsync(
200 delete_begin, delete_end,
201 base::Bind(&ResultSavingCookieCallback<int>::Run,
202 base::Unretained(&callback)));
203 RunFor(kTimeout);
204 EXPECT_TRUE(callback.did_run());
205 return callback.result();
208 int DeleteAllCreatedBetweenForHost(CookieMonster* cm,
209 const base::Time delete_begin,
210 const base::Time delete_end,
211 const GURL& url) {
212 DCHECK(cm);
213 ResultSavingCookieCallback<int> callback;
214 cm->DeleteAllCreatedBetweenForHostAsync(
215 delete_begin, delete_end, url,
216 base::Bind(&ResultSavingCookieCallback<int>::Run,
217 base::Unretained(&callback)));
218 RunFor(kTimeout);
219 EXPECT_TRUE(callback.did_run());
220 return callback.result();
223 int DeleteAllForHost(CookieMonster* cm, const GURL& url) {
224 DCHECK(cm);
225 ResultSavingCookieCallback<int> callback;
226 cm->DeleteAllForHostAsync(url,
227 base::Bind(&ResultSavingCookieCallback<int>::Run,
228 base::Unretained(&callback)));
229 RunFor(kTimeout);
230 EXPECT_TRUE(callback.did_run());
231 return callback.result();
234 bool DeleteCanonicalCookie(CookieMonster* cm, const CanonicalCookie& cookie) {
235 DCHECK(cm);
236 ResultSavingCookieCallback<bool> callback;
237 cm->DeleteCanonicalCookieAsync(
238 cookie, base::Bind(&ResultSavingCookieCallback<bool>::Run,
239 base::Unretained(&callback)));
240 RunFor(kTimeout);
241 EXPECT_TRUE(callback.did_run());
242 return callback.result();
245 // Helper for DeleteAllForHost test; repopulates CM with same layout
246 // each time.
247 void PopulateCmForDeleteAllForHost(scoped_refptr<CookieMonster> cm) {
248 GURL url_top_level_domain_plus_1(kTopLevelDomainPlus1);
249 GURL url_top_level_domain_plus_2(kTopLevelDomainPlus2);
250 GURL url_top_level_domain_plus_2_secure(kTopLevelDomainPlus2Secure);
251 GURL url_top_level_domain_plus_3(kTopLevelDomainPlus3);
252 GURL url_other(kOtherDomain);
254 DeleteAll(cm.get());
256 // Static population for probe:
257 // * Three levels of domain cookie (.b.a, .c.b.a, .d.c.b.a)
258 // * Three levels of host cookie (w.b.a, w.c.b.a, w.d.c.b.a)
259 // * http_only cookie (w.c.b.a)
260 // * first-party cookie (w.c.b.a)
261 // * Two secure cookies (.c.b.a, w.c.b.a)
262 // * Two domain path cookies (.c.b.a/dir1, .c.b.a/dir1/dir2)
263 // * Two host path cookies (w.c.b.a/dir1, w.c.b.a/dir1/dir2)
265 // Domain cookies
266 EXPECT_TRUE(this->SetCookieWithDetails(
267 cm.get(), url_top_level_domain_plus_1, "dom_1", "X", ".harvard.edu",
268 "/", base::Time(), false, false, false, COOKIE_PRIORITY_DEFAULT));
269 EXPECT_TRUE(this->SetCookieWithDetails(
270 cm.get(), url_top_level_domain_plus_2, "dom_2", "X",
271 ".math.harvard.edu", "/", base::Time(), false, false, false,
272 COOKIE_PRIORITY_DEFAULT));
273 EXPECT_TRUE(this->SetCookieWithDetails(
274 cm.get(), url_top_level_domain_plus_3, "dom_3", "X",
275 ".bourbaki.math.harvard.edu", "/", base::Time(), false, false, false,
276 COOKIE_PRIORITY_DEFAULT));
278 // Host cookies
279 EXPECT_TRUE(this->SetCookieWithDetails(
280 cm.get(), url_top_level_domain_plus_1, "host_1", "X", std::string(),
281 "/", base::Time(), false, false, false, COOKIE_PRIORITY_DEFAULT));
282 EXPECT_TRUE(this->SetCookieWithDetails(
283 cm.get(), url_top_level_domain_plus_2, "host_2", "X", std::string(),
284 "/", base::Time(), false, false, false, COOKIE_PRIORITY_DEFAULT));
285 EXPECT_TRUE(this->SetCookieWithDetails(
286 cm.get(), url_top_level_domain_plus_3, "host_3", "X", std::string(),
287 "/", base::Time(), false, false, false, COOKIE_PRIORITY_DEFAULT));
289 // http_only cookie
290 EXPECT_TRUE(this->SetCookieWithDetails(
291 cm.get(), url_top_level_domain_plus_2, "httpo_check", "x",
292 std::string(), "/", base::Time(), false, true, false,
293 COOKIE_PRIORITY_DEFAULT));
295 // first-party cookie
296 EXPECT_TRUE(this->SetCookieWithDetails(
297 cm.get(), url_top_level_domain_plus_2, "firstp_check", "x",
298 std::string(), "/", base::Time(), false, false, true,
299 COOKIE_PRIORITY_DEFAULT));
301 // Secure cookies
302 EXPECT_TRUE(this->SetCookieWithDetails(
303 cm.get(), url_top_level_domain_plus_2_secure, "sec_dom", "X",
304 ".math.harvard.edu", "/", base::Time(), true, false, false,
305 COOKIE_PRIORITY_DEFAULT));
306 EXPECT_TRUE(this->SetCookieWithDetails(
307 cm.get(), url_top_level_domain_plus_2_secure, "sec_host", "X",
308 std::string(), "/", base::Time(), true, false, false,
309 COOKIE_PRIORITY_DEFAULT));
311 // Domain path cookies
312 EXPECT_TRUE(this->SetCookieWithDetails(
313 cm.get(), url_top_level_domain_plus_2, "dom_path_1", "X",
314 ".math.harvard.edu", "/dir1", base::Time(), false, false, false,
315 COOKIE_PRIORITY_DEFAULT));
316 EXPECT_TRUE(this->SetCookieWithDetails(
317 cm.get(), url_top_level_domain_plus_2, "dom_path_2", "X",
318 ".math.harvard.edu", "/dir1/dir2", base::Time(), false, false, false,
319 COOKIE_PRIORITY_DEFAULT));
321 // Host path cookies
322 EXPECT_TRUE(this->SetCookieWithDetails(
323 cm.get(), url_top_level_domain_plus_2, "host_path_1", "X",
324 std::string(), "/dir1", base::Time(), false, false, false,
325 COOKIE_PRIORITY_DEFAULT));
326 EXPECT_TRUE(this->SetCookieWithDetails(
327 cm.get(), url_top_level_domain_plus_2, "host_path_2", "X",
328 std::string(), "/dir1/dir2", base::Time(), false, false, false,
329 COOKIE_PRIORITY_DEFAULT));
331 EXPECT_EQ(14U, this->GetAllCookies(cm.get()).size());
334 Time GetFirstCookieAccessDate(CookieMonster* cm) {
335 const CookieList all_cookies(this->GetAllCookies(cm));
336 return all_cookies.front().LastAccessDate();
339 bool FindAndDeleteCookie(CookieMonster* cm,
340 const std::string& domain,
341 const std::string& name) {
342 CookieList cookies = this->GetAllCookies(cm);
343 for (CookieList::iterator it = cookies.begin(); it != cookies.end(); ++it)
344 if (it->Domain() == domain && it->Name() == name)
345 return this->DeleteCanonicalCookie(cm, *it);
346 return false;
349 int CountInString(const std::string& str, char c) {
350 return std::count(str.begin(), str.end(), c);
353 void TestHostGarbageCollectHelper() {
354 int domain_max_cookies = CookieMonster::kDomainMaxCookies;
355 int domain_purge_cookies = CookieMonster::kDomainPurgeCookies;
356 const int more_than_enough_cookies =
357 (domain_max_cookies + domain_purge_cookies) * 2;
358 // Add a bunch of cookies on a single host, should purge them.
360 scoped_refptr<CookieMonster> cm(new CookieMonster(NULL, NULL));
361 for (int i = 0; i < more_than_enough_cookies; ++i) {
362 std::string cookie = base::StringPrintf("a%03d=b", i);
363 EXPECT_TRUE(SetCookie(cm.get(), url_google_, cookie));
364 std::string cookies = this->GetCookies(cm.get(), url_google_);
365 // Make sure we find it in the cookies.
366 EXPECT_NE(cookies.find(cookie), std::string::npos);
367 // Count the number of cookies.
368 EXPECT_LE(CountInString(cookies, '='), domain_max_cookies);
372 // Add a bunch of cookies on multiple hosts within a single eTLD.
373 // Should keep at least kDomainMaxCookies - kDomainPurgeCookies
374 // between them. We shouldn't go above kDomainMaxCookies for both together.
375 GURL url_google_specific(kUrlGoogleSpecific);
377 scoped_refptr<CookieMonster> cm(new CookieMonster(NULL, NULL));
378 for (int i = 0; i < more_than_enough_cookies; ++i) {
379 std::string cookie_general = base::StringPrintf("a%03d=b", i);
380 EXPECT_TRUE(SetCookie(cm.get(), url_google_, cookie_general));
381 std::string cookie_specific = base::StringPrintf("c%03d=b", i);
382 EXPECT_TRUE(SetCookie(cm.get(), url_google_specific, cookie_specific));
383 std::string cookies_general = this->GetCookies(cm.get(), url_google_);
384 EXPECT_NE(cookies_general.find(cookie_general), std::string::npos);
385 std::string cookies_specific =
386 this->GetCookies(cm.get(), url_google_specific);
387 EXPECT_NE(cookies_specific.find(cookie_specific), std::string::npos);
388 EXPECT_LE((CountInString(cookies_general, '=') +
389 CountInString(cookies_specific, '=')),
390 domain_max_cookies);
392 // After all this, there should be at least
393 // kDomainMaxCookies - kDomainPurgeCookies for both URLs.
394 std::string cookies_general = this->GetCookies(cm.get(), url_google_);
395 std::string cookies_specific =
396 this->GetCookies(cm.get(), url_google_specific);
397 int total_cookies = (CountInString(cookies_general, '=') +
398 CountInString(cookies_specific, '='));
399 EXPECT_GE(total_cookies, domain_max_cookies - domain_purge_cookies);
400 EXPECT_LE(total_cookies, domain_max_cookies);
404 CookiePriority CharToPriority(char ch) {
405 switch (ch) {
406 case 'L':
407 return COOKIE_PRIORITY_LOW;
408 case 'M':
409 return COOKIE_PRIORITY_MEDIUM;
410 case 'H':
411 return COOKIE_PRIORITY_HIGH;
413 NOTREACHED();
414 return COOKIE_PRIORITY_DEFAULT;
417 // Instantiates a CookieMonster, adds multiple cookies (to url_google_) with
418 // priorities specified by |coded_priority_str|, and tests priority-aware
419 // domain cookie eviction.
420 // |coded_priority_str| specifies a run-length-encoded string of priorities.
421 // Example: "2M 3L M 4H" means "MMLLLMHHHH", and speicifies sequential (i.e.,
422 // from least- to most-recently accessed) insertion of 2 medium-priority
423 // cookies, 3 low-priority cookies, 1 medium-priority cookie, and 4
424 // high-priority cookies.
425 // Within each priority, only the least-accessed cookies should be evicted.
426 // Thus, to describe expected suriving cookies, it suffices to specify the
427 // expected population of surviving cookies per priority, i.e.,
428 // |expected_low_count|, |expected_medium_count|, and |expected_high_count|.
429 void TestPriorityCookieCase(CookieMonster* cm,
430 const std::string& coded_priority_str,
431 size_t expected_low_count,
432 size_t expected_medium_count,
433 size_t expected_high_count) {
434 DeleteAll(cm);
435 int next_cookie_id = 0;
436 std::vector<CookiePriority> priority_list;
437 std::vector<int> id_list[3]; // Indexed by CookiePriority.
439 // Parse |coded_priority_str| and add cookies.
440 for (const std::string& token :
441 base::SplitString(coded_priority_str, " ", base::TRIM_WHITESPACE,
442 base::SPLIT_WANT_ALL)) {
443 DCHECK(!token.empty());
444 // Take last character as priority.
445 CookiePriority priority = CharToPriority(token[token.length() - 1]);
446 std::string priority_str = CookiePriorityToString(priority);
447 // The rest of the string (possibly empty) specifies repetition.
448 int rep = 1;
449 if (!token.empty()) {
450 bool result = base::StringToInt(
451 base::StringPiece(token.begin(), token.end() - 1), &rep);
452 DCHECK(result);
454 for (; rep > 0; --rep, ++next_cookie_id) {
455 std::string cookie = base::StringPrintf(
456 "a%d=b;priority=%s", next_cookie_id, priority_str.c_str());
457 EXPECT_TRUE(SetCookie(cm, url_google_, cookie));
458 priority_list.push_back(priority);
459 id_list[priority].push_back(next_cookie_id);
463 int num_cookies = static_cast<int>(priority_list.size());
464 std::vector<int> surviving_id_list[3]; // Indexed by CookiePriority.
466 // Parse the list of cookies
467 std::string cookie_str = this->GetCookies(cm, url_google_);
468 for (const std::string& token : base::SplitString(
469 cookie_str, ";", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL)) {
470 // Assuming *it is "a#=b", so extract and parse "#" portion.
471 int id = -1;
472 bool result = base::StringToInt(
473 base::StringPiece(token.begin() + 1, token.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::ThreadTaskRunnerHandle::Get()->PostTask(
641 FROM_HERE, 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::ThreadTaskRunnerHandle::Get()->PostTask(
2066 FROM_HERE,
2067 base::Bind(&LoadedCallbackTask::Run,
2068 new 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 // Check that DeleteAll does flush (as a sanity check that flush_count()
2315 // works).
2316 TEST_F(CookieMonsterTest, DeleteAll) {
2317 scoped_refptr<FlushablePersistentStore> store(new FlushablePersistentStore());
2318 scoped_refptr<CookieMonster> cm(new CookieMonster(store.get(), NULL));
2319 cm->SetPersistSessionCookies(true);
2321 EXPECT_TRUE(SetCookie(cm.get(), url_google_, "X=Y; path=/"));
2323 ASSERT_EQ(0, store->flush_count());
2324 EXPECT_EQ(1, DeleteAll(cm.get()));
2325 EXPECT_EQ(1, store->flush_count());
2328 TEST_F(CookieMonsterTest, HistogramCheck) {
2329 scoped_refptr<CookieMonster> cm(new CookieMonster(NULL, NULL));
2330 // Should match call in InitializeHistograms, but doesn't really matter
2331 // since the histogram should have been initialized by the CM construction
2332 // above.
2333 base::HistogramBase* expired_histogram = base::Histogram::FactoryGet(
2334 "Cookie.ExpirationDurationMinutes", 1, 10 * 365 * 24 * 60, 50,
2335 base::Histogram::kUmaTargetedHistogramFlag);
2337 scoped_ptr<base::HistogramSamples> samples1(
2338 expired_histogram->SnapshotSamples());
2339 ASSERT_TRUE(SetCookieWithDetails(
2340 cm.get(), GURL("http://fake.a.url"), "a", "b", "a.url", "/",
2341 base::Time::Now() + base::TimeDelta::FromMinutes(59), false, false, false,
2342 COOKIE_PRIORITY_DEFAULT));
2344 scoped_ptr<base::HistogramSamples> samples2(
2345 expired_histogram->SnapshotSamples());
2346 EXPECT_EQ(samples1->TotalCount() + 1, samples2->TotalCount());
2348 // kValidCookieLine creates a session cookie.
2349 ASSERT_TRUE(SetCookie(cm.get(), url_google_, kValidCookieLine));
2351 scoped_ptr<base::HistogramSamples> samples3(
2352 expired_histogram->SnapshotSamples());
2353 EXPECT_EQ(samples2->TotalCount(), samples3->TotalCount());
2356 namespace {
2358 class MultiThreadedCookieMonsterTest : public CookieMonsterTest {
2359 public:
2360 MultiThreadedCookieMonsterTest() : other_thread_("CMTthread") {}
2362 // Helper methods for calling the asynchronous CookieMonster methods
2363 // from a different thread.
2365 void GetAllCookiesTask(CookieMonster* cm, GetCookieListCallback* callback) {
2366 cm->GetAllCookiesAsync(
2367 base::Bind(&GetCookieListCallback::Run, base::Unretained(callback)));
2370 void GetAllCookiesForURLTask(CookieMonster* cm,
2371 const GURL& url,
2372 GetCookieListCallback* callback) {
2373 cm->GetAllCookiesForURLAsync(url, base::Bind(&GetCookieListCallback::Run,
2374 base::Unretained(callback)));
2377 void GetAllCookiesForURLWithOptionsTask(CookieMonster* cm,
2378 const GURL& url,
2379 const CookieOptions& options,
2380 GetCookieListCallback* callback) {
2381 cm->GetAllCookiesForURLWithOptionsAsync(
2382 url, options,
2383 base::Bind(&GetCookieListCallback::Run, base::Unretained(callback)));
2386 void SetCookieWithDetailsTask(CookieMonster* cm,
2387 const GURL& url,
2388 ResultSavingCookieCallback<bool>* callback) {
2389 // Define the parameters here instead of in the calling fucntion.
2390 // The maximum number of parameters for Bind function is 6.
2391 std::string name = "A";
2392 std::string value = "B";
2393 std::string domain = std::string();
2394 std::string path = "/foo";
2395 base::Time expiration_time = base::Time();
2396 bool secure = false;
2397 bool http_only = false;
2398 bool first_party_only = false;
2399 CookiePriority priority = COOKIE_PRIORITY_DEFAULT;
2400 cm->SetCookieWithDetailsAsync(
2401 url, name, value, domain, path, expiration_time, secure, http_only,
2402 first_party_only, priority,
2403 base::Bind(&ResultSavingCookieCallback<bool>::Run,
2404 base::Unretained(callback)));
2407 void DeleteAllCreatedBetweenTask(CookieMonster* cm,
2408 const base::Time& delete_begin,
2409 const base::Time& delete_end,
2410 ResultSavingCookieCallback<int>* callback) {
2411 cm->DeleteAllCreatedBetweenAsync(
2412 delete_begin, delete_end,
2413 base::Bind(&ResultSavingCookieCallback<int>::Run,
2414 base::Unretained(callback)));
2417 void DeleteAllForHostTask(CookieMonster* cm,
2418 const GURL& url,
2419 ResultSavingCookieCallback<int>* callback) {
2420 cm->DeleteAllForHostAsync(url,
2421 base::Bind(&ResultSavingCookieCallback<int>::Run,
2422 base::Unretained(callback)));
2425 void DeleteAllCreatedBetweenForHostTask(
2426 CookieMonster* cm,
2427 const base::Time delete_begin,
2428 const base::Time delete_end,
2429 const GURL& url,
2430 ResultSavingCookieCallback<int>* callback) {
2431 cm->DeleteAllCreatedBetweenForHostAsync(
2432 delete_begin, delete_end, url,
2433 base::Bind(&ResultSavingCookieCallback<int>::Run,
2434 base::Unretained(callback)));
2437 void DeleteCanonicalCookieTask(CookieMonster* cm,
2438 const CanonicalCookie& cookie,
2439 ResultSavingCookieCallback<bool>* callback) {
2440 cm->DeleteCanonicalCookieAsync(
2441 cookie, base::Bind(&ResultSavingCookieCallback<bool>::Run,
2442 base::Unretained(callback)));
2445 protected:
2446 void RunOnOtherThread(const base::Closure& task) {
2447 other_thread_.Start();
2448 other_thread_.task_runner()->PostTask(FROM_HERE, task);
2449 RunFor(kTimeout);
2450 other_thread_.Stop();
2453 Thread other_thread_;
2456 } // namespace
2458 TEST_F(MultiThreadedCookieMonsterTest, ThreadCheckGetAllCookies) {
2459 scoped_refptr<CookieMonster> cm(new CookieMonster(NULL, NULL));
2460 EXPECT_TRUE(SetCookie(cm.get(), url_google_, "A=B"));
2461 CookieList cookies = GetAllCookies(cm.get());
2462 CookieList::const_iterator it = cookies.begin();
2463 ASSERT_TRUE(it != cookies.end());
2464 EXPECT_EQ("www.google.izzle", it->Domain());
2465 EXPECT_EQ("A", it->Name());
2466 ASSERT_TRUE(++it == cookies.end());
2467 GetCookieListCallback callback(&other_thread_);
2468 base::Closure task =
2469 base::Bind(&MultiThreadedCookieMonsterTest::GetAllCookiesTask,
2470 base::Unretained(this), cm, &callback);
2471 RunOnOtherThread(task);
2472 EXPECT_TRUE(callback.did_run());
2473 it = callback.cookies().begin();
2474 ASSERT_TRUE(it != callback.cookies().end());
2475 EXPECT_EQ("www.google.izzle", it->Domain());
2476 EXPECT_EQ("A", it->Name());
2477 ASSERT_TRUE(++it == callback.cookies().end());
2480 TEST_F(MultiThreadedCookieMonsterTest, ThreadCheckGetAllCookiesForURL) {
2481 scoped_refptr<CookieMonster> cm(new CookieMonster(NULL, NULL));
2482 EXPECT_TRUE(SetCookie(cm.get(), url_google_, "A=B"));
2483 CookieList cookies = GetAllCookiesForURL(cm.get(), url_google_);
2484 CookieList::const_iterator it = cookies.begin();
2485 ASSERT_TRUE(it != cookies.end());
2486 EXPECT_EQ("www.google.izzle", it->Domain());
2487 EXPECT_EQ("A", it->Name());
2488 ASSERT_TRUE(++it == cookies.end());
2489 GetCookieListCallback callback(&other_thread_);
2490 base::Closure task =
2491 base::Bind(&MultiThreadedCookieMonsterTest::GetAllCookiesForURLTask,
2492 base::Unretained(this), cm, url_google_, &callback);
2493 RunOnOtherThread(task);
2494 EXPECT_TRUE(callback.did_run());
2495 it = callback.cookies().begin();
2496 ASSERT_TRUE(it != callback.cookies().end());
2497 EXPECT_EQ("www.google.izzle", it->Domain());
2498 EXPECT_EQ("A", it->Name());
2499 ASSERT_TRUE(++it == callback.cookies().end());
2502 TEST_F(MultiThreadedCookieMonsterTest, ThreadCheckGetAllCookiesForURLWithOpt) {
2503 scoped_refptr<CookieMonster> cm(new CookieMonster(NULL, NULL));
2504 EXPECT_TRUE(SetCookie(cm.get(), url_google_, "A=B"));
2505 CookieOptions options;
2506 CookieList cookies =
2507 GetAllCookiesForURLWithOptions(cm.get(), url_google_, options);
2508 CookieList::const_iterator it = cookies.begin();
2509 ASSERT_TRUE(it != cookies.end());
2510 EXPECT_EQ("www.google.izzle", it->Domain());
2511 EXPECT_EQ("A", it->Name());
2512 ASSERT_TRUE(++it == cookies.end());
2513 GetCookieListCallback callback(&other_thread_);
2514 base::Closure task = base::Bind(
2515 &MultiThreadedCookieMonsterTest::GetAllCookiesForURLWithOptionsTask,
2516 base::Unretained(this), cm, url_google_, options, &callback);
2517 RunOnOtherThread(task);
2518 EXPECT_TRUE(callback.did_run());
2519 it = callback.cookies().begin();
2520 ASSERT_TRUE(it != callback.cookies().end());
2521 EXPECT_EQ("www.google.izzle", it->Domain());
2522 EXPECT_EQ("A", it->Name());
2523 ASSERT_TRUE(++it == callback.cookies().end());
2526 TEST_F(MultiThreadedCookieMonsterTest, ThreadCheckSetCookieWithDetails) {
2527 scoped_refptr<CookieMonster> cm(new CookieMonster(NULL, NULL));
2528 EXPECT_TRUE(SetCookieWithDetails(cm.get(), url_google_foo_, "A", "B",
2529 std::string(), "/foo", base::Time(), false,
2530 false, false, COOKIE_PRIORITY_DEFAULT));
2531 ResultSavingCookieCallback<bool> callback(&other_thread_);
2532 base::Closure task =
2533 base::Bind(&MultiThreadedCookieMonsterTest::SetCookieWithDetailsTask,
2534 base::Unretained(this), cm, url_google_foo_, &callback);
2535 RunOnOtherThread(task);
2536 EXPECT_TRUE(callback.did_run());
2537 EXPECT_TRUE(callback.result());
2540 TEST_F(MultiThreadedCookieMonsterTest, ThreadCheckDeleteAllCreatedBetween) {
2541 scoped_refptr<CookieMonster> cm(new CookieMonster(NULL, NULL));
2542 CookieOptions options;
2543 Time now = Time::Now();
2544 EXPECT_TRUE(SetCookieWithOptions(cm.get(), url_google_, "A=B", options));
2545 EXPECT_EQ(1, DeleteAllCreatedBetween(cm.get(), now - TimeDelta::FromDays(99),
2546 Time()));
2547 EXPECT_TRUE(SetCookieWithOptions(cm.get(), url_google_, "A=B", options));
2548 ResultSavingCookieCallback<int> callback(&other_thread_);
2549 base::Closure task =
2550 base::Bind(&MultiThreadedCookieMonsterTest::DeleteAllCreatedBetweenTask,
2551 base::Unretained(this), cm, now - TimeDelta::FromDays(99),
2552 Time(), &callback);
2553 RunOnOtherThread(task);
2554 EXPECT_TRUE(callback.did_run());
2555 EXPECT_EQ(1, callback.result());
2558 TEST_F(MultiThreadedCookieMonsterTest, ThreadCheckDeleteAllForHost) {
2559 scoped_refptr<CookieMonster> cm(new CookieMonster(NULL, NULL));
2560 CookieOptions options;
2561 EXPECT_TRUE(SetCookieWithOptions(cm.get(), url_google_, "A=B", options));
2562 EXPECT_EQ(1, DeleteAllForHost(cm.get(), url_google_));
2563 EXPECT_TRUE(SetCookieWithOptions(cm.get(), url_google_, "A=B", options));
2564 ResultSavingCookieCallback<int> callback(&other_thread_);
2565 base::Closure task =
2566 base::Bind(&MultiThreadedCookieMonsterTest::DeleteAllForHostTask,
2567 base::Unretained(this), cm, url_google_, &callback);
2568 RunOnOtherThread(task);
2569 EXPECT_TRUE(callback.did_run());
2570 EXPECT_EQ(1, callback.result());
2573 TEST_F(MultiThreadedCookieMonsterTest,
2574 ThreadCheckDeleteAllCreatedBetweenForHost) {
2575 scoped_refptr<CookieMonster> cm(new CookieMonster(NULL, NULL));
2576 GURL url_not_google("http://www.notgoogle.com");
2578 CookieOptions options;
2579 Time now = Time::Now();
2580 // ago1 < ago2 < ago3 < now.
2581 Time ago1 = now - TimeDelta::FromDays(101);
2582 Time ago2 = now - TimeDelta::FromDays(100);
2583 Time ago3 = now - TimeDelta::FromDays(99);
2585 // These 3 cookies match the first deletion.
2586 EXPECT_TRUE(SetCookieWithOptions(cm.get(), url_google_, "A=B", options));
2587 EXPECT_TRUE(SetCookieWithOptions(cm.get(), url_google_, "C=D", options));
2588 EXPECT_TRUE(SetCookieWithOptions(cm.get(), url_google_, "Y=Z", options));
2590 // This cookie does not match host.
2591 EXPECT_TRUE(SetCookieWithOptions(cm.get(), url_not_google, "E=F", options));
2593 // This cookie does not match time range: [ago3, inf], for first deletion, but
2594 // matches for the second deletion.
2595 EXPECT_TRUE(cm->SetCookieWithCreationTime(url_google_, "G=H", ago2));
2597 // 1. First set of deletions.
2598 EXPECT_EQ(
2599 3, // Deletes A=B, C=D, Y=Z
2600 DeleteAllCreatedBetweenForHost(cm.get(), ago3, Time::Max(), url_google_));
2602 EXPECT_TRUE(SetCookieWithOptions(cm.get(), url_google_, "A=B", options));
2603 ResultSavingCookieCallback<int> callback(&other_thread_);
2605 // 2. Second set of deletions.
2606 base::Closure task = base::Bind(
2607 &MultiThreadedCookieMonsterTest::DeleteAllCreatedBetweenForHostTask,
2608 base::Unretained(this), cm, ago1, Time(), url_google_, &callback);
2609 RunOnOtherThread(task);
2610 EXPECT_TRUE(callback.did_run());
2611 EXPECT_EQ(2, callback.result()); // Deletes A=B, G=H.
2614 TEST_F(MultiThreadedCookieMonsterTest, ThreadCheckDeleteCanonicalCookie) {
2615 scoped_refptr<CookieMonster> cm(new CookieMonster(NULL, NULL));
2616 CookieOptions options;
2617 EXPECT_TRUE(SetCookieWithOptions(cm.get(), url_google_, "A=B", options));
2618 CookieList cookies = GetAllCookies(cm.get());
2619 CookieList::iterator it = cookies.begin();
2620 EXPECT_TRUE(DeleteCanonicalCookie(cm.get(), *it));
2622 EXPECT_TRUE(SetCookieWithOptions(cm.get(), url_google_, "A=B", options));
2623 ResultSavingCookieCallback<bool> callback(&other_thread_);
2624 cookies = GetAllCookies(cm.get());
2625 it = cookies.begin();
2626 base::Closure task =
2627 base::Bind(&MultiThreadedCookieMonsterTest::DeleteCanonicalCookieTask,
2628 base::Unretained(this), cm, *it, &callback);
2629 RunOnOtherThread(task);
2630 EXPECT_TRUE(callback.did_run());
2631 EXPECT_TRUE(callback.result());
2634 // Ensure that cookies for http, https, ws, and wss all share the same storage
2635 // and policies when GetAllCookiesForURLAsync is used. This test is part of
2636 // MultiThreadedCookieMonsterTest in order to test and use
2637 // GetAllCookiesForURLAsync, but it does not use any additional threads.
2638 TEST_F(MultiThreadedCookieMonsterTest, GetAllCookiesForURLEffectiveDomain) {
2639 std::vector<CanonicalCookie*> cookies;
2640 // This cookie will be freed by the CookieMonster.
2641 cookies.push_back(CanonicalCookie::Create(url_google_, kValidCookieLine,
2642 Time::Now(), CookieOptions()));
2643 CanonicalCookie cookie = *cookies[0];
2644 scoped_refptr<NewMockPersistentCookieStore> store(
2645 new NewMockPersistentCookieStore);
2646 scoped_refptr<CookieMonster> cm(new CookieMonster(store.get(), NULL));
2648 CookieMonster::PersistentCookieStore::LoadedCallback loaded_callback;
2649 ::testing::StrictMock<::testing::MockFunction<void(int)>> checkpoint;
2650 const std::string key =
2651 cookie_util::GetEffectiveDomain(url_google_.scheme(), url_google_.host());
2653 ::testing::InSequence s;
2654 EXPECT_CALL(checkpoint, Call(0));
2655 EXPECT_CALL(*store, Load(::testing::_));
2656 EXPECT_CALL(*store, LoadCookiesForKey(key, ::testing::_))
2657 .WillOnce(::testing::SaveArg<1>(&loaded_callback));
2658 EXPECT_CALL(checkpoint, Call(1));
2659 // LoadCookiesForKey will never be called after checkpoint.Call(1) although
2660 // we will call GetAllCookiesForURLAsync again, because all URLs below share
2661 // the same key.
2662 EXPECT_CALL(*store, LoadCookiesForKey(::testing::_, ::testing::_)).Times(0);
2664 GetCookieListCallback callback;
2665 checkpoint.Call(0);
2666 GetAllCookiesForURLTask(cm.get(), url_google_, &callback);
2667 checkpoint.Call(1);
2668 ASSERT_FALSE(callback.did_run());
2669 // Pass the cookies to the CookieMonster.
2670 loaded_callback.Run(cookies);
2671 // Now GetAllCookiesForURLTask is done.
2672 ASSERT_TRUE(callback.did_run());
2673 // See that the callback was called with the cookies.
2674 ASSERT_EQ(1u, callback.cookies().size());
2675 EXPECT_TRUE(cookie.IsEquivalent(callback.cookies()[0]));
2677 // All urls in |urls| should share the same cookie domain.
2678 const GURL kUrls[] = {
2679 url_google_,
2680 url_google_secure_,
2681 GURL(kUrlGoogleWebSocket),
2682 GURL(kUrlGoogleWebSocketSecure),
2684 for (const GURL& url : kUrls) {
2685 // Call the function with |url| and verify it is done synchronously without
2686 // calling LoadCookiesForKey.
2687 GetCookieListCallback callback;
2688 GetAllCookiesForURLTask(cm.get(), url, &callback);
2689 ASSERT_TRUE(callback.did_run());
2690 ASSERT_EQ(1u, callback.cookies().size());
2691 EXPECT_TRUE(cookie.IsEquivalent(callback.cookies()[0]));
2695 TEST_F(CookieMonsterTest, InvalidExpiryTime) {
2696 std::string cookie_line =
2697 std::string(kValidCookieLine) + "; expires=Blarg arg arg";
2698 scoped_ptr<CanonicalCookie> cookie(CanonicalCookie::Create(
2699 url_google_, cookie_line, Time::Now(), CookieOptions()));
2700 ASSERT_FALSE(cookie->IsPersistent());
2703 // Test that CookieMonster writes session cookies into the underlying
2704 // CookieStore if the "persist session cookies" option is on.
2705 TEST_F(CookieMonsterTest, PersistSessionCookies) {
2706 scoped_refptr<MockPersistentCookieStore> store(new MockPersistentCookieStore);
2707 scoped_refptr<CookieMonster> cm(new CookieMonster(store.get(), NULL));
2708 cm->SetPersistSessionCookies(true);
2710 // All cookies set with SetCookie are session cookies.
2711 EXPECT_TRUE(SetCookie(cm.get(), url_google_, "A=B"));
2712 EXPECT_EQ("A=B", GetCookies(cm.get(), url_google_));
2714 // The cookie was written to the backing store.
2715 EXPECT_EQ(1u, store->commands().size());
2716 EXPECT_EQ(CookieStoreCommand::ADD, store->commands()[0].type);
2717 EXPECT_EQ("A", store->commands()[0].cookie.Name());
2718 EXPECT_EQ("B", store->commands()[0].cookie.Value());
2720 // Modify the cookie.
2721 EXPECT_TRUE(SetCookie(cm.get(), url_google_, "A=C"));
2722 EXPECT_EQ("A=C", GetCookies(cm.get(), url_google_));
2723 EXPECT_EQ(3u, store->commands().size());
2724 EXPECT_EQ(CookieStoreCommand::REMOVE, store->commands()[1].type);
2725 EXPECT_EQ("A", store->commands()[1].cookie.Name());
2726 EXPECT_EQ("B", store->commands()[1].cookie.Value());
2727 EXPECT_EQ(CookieStoreCommand::ADD, store->commands()[2].type);
2728 EXPECT_EQ("A", store->commands()[2].cookie.Name());
2729 EXPECT_EQ("C", store->commands()[2].cookie.Value());
2731 // Delete the cookie.
2732 DeleteCookie(cm.get(), url_google_, "A");
2733 EXPECT_EQ("", GetCookies(cm.get(), url_google_));
2734 EXPECT_EQ(4u, store->commands().size());
2735 EXPECT_EQ(CookieStoreCommand::REMOVE, store->commands()[3].type);
2736 EXPECT_EQ("A", store->commands()[3].cookie.Name());
2737 EXPECT_EQ("C", store->commands()[3].cookie.Value());
2740 // Test the commands sent to the persistent cookie store.
2741 TEST_F(CookieMonsterTest, PersisentCookieStorageTest) {
2742 scoped_refptr<MockPersistentCookieStore> store(new MockPersistentCookieStore);
2743 scoped_refptr<CookieMonster> cm(new CookieMonster(store.get(), NULL));
2745 // Add a cookie.
2746 EXPECT_TRUE(SetCookie(cm.get(), url_google_,
2747 "A=B; expires=Mon, 18-Apr-22 22:50:13 GMT"));
2748 this->MatchCookieLines("A=B", GetCookies(cm.get(), url_google_));
2749 ASSERT_EQ(1u, store->commands().size());
2750 EXPECT_EQ(CookieStoreCommand::ADD, store->commands()[0].type);
2751 // Remove it.
2752 EXPECT_TRUE(SetCookie(cm.get(), url_google_, "A=B; max-age=0"));
2753 this->MatchCookieLines(std::string(), GetCookies(cm.get(), url_google_));
2754 ASSERT_EQ(2u, store->commands().size());
2755 EXPECT_EQ(CookieStoreCommand::REMOVE, store->commands()[1].type);
2757 // Add a cookie.
2758 EXPECT_TRUE(SetCookie(cm.get(), url_google_,
2759 "A=B; expires=Mon, 18-Apr-22 22:50:13 GMT"));
2760 this->MatchCookieLines("A=B", GetCookies(cm.get(), url_google_));
2761 ASSERT_EQ(3u, store->commands().size());
2762 EXPECT_EQ(CookieStoreCommand::ADD, store->commands()[2].type);
2763 // Overwrite it.
2764 EXPECT_TRUE(SetCookie(cm.get(), url_google_,
2765 "A=Foo; expires=Mon, 18-Apr-22 22:50:14 GMT"));
2766 this->MatchCookieLines("A=Foo", GetCookies(cm.get(), url_google_));
2767 ASSERT_EQ(5u, store->commands().size());
2768 EXPECT_EQ(CookieStoreCommand::REMOVE, store->commands()[3].type);
2769 EXPECT_EQ(CookieStoreCommand::ADD, store->commands()[4].type);
2771 // Create some non-persistent cookies and check that they don't go to the
2772 // persistent storage.
2773 EXPECT_TRUE(SetCookie(cm.get(), url_google_, "B=Bar"));
2774 this->MatchCookieLines("A=Foo; B=Bar", GetCookies(cm.get(), url_google_));
2775 EXPECT_EQ(5u, store->commands().size());
2778 // Test to assure that cookies with control characters are purged appropriately.
2779 // See http://crbug.com/238041 for background.
2780 TEST_F(CookieMonsterTest, ControlCharacterPurge) {
2781 const Time now1(Time::Now());
2782 const Time now2(Time::Now() + TimeDelta::FromSeconds(1));
2783 const Time now3(Time::Now() + TimeDelta::FromSeconds(2));
2784 const Time later(now1 + TimeDelta::FromDays(1));
2785 const GURL url("http://host/path");
2786 const std::string domain("host");
2787 const std::string path("/path");
2789 scoped_refptr<MockPersistentCookieStore> store(new MockPersistentCookieStore);
2791 std::vector<CanonicalCookie*> initial_cookies;
2793 AddCookieToList(domain, "foo=bar; path=" + path, now1, &initial_cookies);
2795 // We have to manually build this cookie because it contains a control
2796 // character, and our cookie line parser rejects control characters.
2797 CanonicalCookie* cc =
2798 new CanonicalCookie(url, "baz",
2799 "\x05"
2800 "boo",
2801 domain, path, now2, later, now2, false, false, false,
2802 COOKIE_PRIORITY_DEFAULT);
2803 initial_cookies.push_back(cc);
2805 AddCookieToList(domain, "hello=world; path=" + path, now3, &initial_cookies);
2807 // Inject our initial cookies into the mock PersistentCookieStore.
2808 store->SetLoadExpectation(true, initial_cookies);
2810 scoped_refptr<CookieMonster> cm(new CookieMonster(store.get(), NULL));
2812 EXPECT_EQ("foo=bar; hello=world", GetCookies(cm.get(), url));
2815 // Test that cookie source schemes are histogrammed correctly.
2816 TEST_F(CookieMonsterTest, CookieSourceHistogram) {
2817 base::HistogramTester histograms;
2818 const std::string cookie_source_histogram = "Cookie.CookieSourceScheme";
2820 scoped_refptr<MockPersistentCookieStore> store(new MockPersistentCookieStore);
2821 scoped_refptr<CookieMonster> cm(new CookieMonster(store.get(), NULL));
2823 histograms.ExpectTotalCount(cookie_source_histogram, 0);
2825 // Set a Secure cookie on a cryptographic scheme.
2826 EXPECT_TRUE(SetCookie(cm.get(), url_google_secure_, "A=B; path=/; Secure"));
2827 histograms.ExpectTotalCount(cookie_source_histogram, 1);
2828 histograms.ExpectBucketCount(
2829 cookie_source_histogram,
2830 CookieMonster::COOKIE_SOURCE_SECURE_COOKIE_CRYPTOGRAPHIC_SCHEME, 1);
2832 // Set a non-Secure cookie on a cryptographic scheme.
2833 EXPECT_TRUE(SetCookie(cm.get(), url_google_secure_, "C=D; path=/;"));
2834 histograms.ExpectTotalCount(cookie_source_histogram, 2);
2835 histograms.ExpectBucketCount(
2836 cookie_source_histogram,
2837 CookieMonster::COOKIE_SOURCE_NONSECURE_COOKIE_CRYPTOGRAPHIC_SCHEME, 1);
2839 // Set a Secure cookie on a non-cryptographic scheme.
2840 EXPECT_TRUE(SetCookie(cm.get(), url_google_, "D=E; path=/; Secure"));
2841 histograms.ExpectTotalCount(cookie_source_histogram, 3);
2842 histograms.ExpectBucketCount(
2843 cookie_source_histogram,
2844 CookieMonster::COOKIE_SOURCE_SECURE_COOKIE_NONCRYPTOGRAPHIC_SCHEME, 1);
2846 // Overwrite a Secure cookie (set by a cryptographic scheme) on a
2847 // non-cryptographic scheme.
2848 EXPECT_TRUE(SetCookie(cm.get(), url_google_, "A=B; path=/; Secure"));
2849 histograms.ExpectTotalCount(cookie_source_histogram, 4);
2850 histograms.ExpectBucketCount(
2851 cookie_source_histogram,
2852 CookieMonster::COOKIE_SOURCE_SECURE_COOKIE_CRYPTOGRAPHIC_SCHEME, 1);
2853 histograms.ExpectBucketCount(
2854 cookie_source_histogram,
2855 CookieMonster::COOKIE_SOURCE_SECURE_COOKIE_NONCRYPTOGRAPHIC_SCHEME, 2);
2857 // Test that clearing a Secure cookie on a http:// URL does not get
2858 // counted.
2859 EXPECT_TRUE(SetCookie(cm.get(), url_google_secure_, "F=G; path=/; Secure"));
2860 histograms.ExpectTotalCount(cookie_source_histogram, 5);
2861 std::string cookies1 = GetCookies(cm.get(), url_google_secure_);
2862 EXPECT_NE(std::string::npos, cookies1.find("F=G"));
2863 EXPECT_TRUE(SetCookie(cm.get(), url_google_,
2864 "F=G; path=/; Expires=Thu, 01-Jan-1970 00:00:01 GMT"));
2865 std::string cookies2 = GetCookies(cm.get(), url_google_secure_);
2866 EXPECT_EQ(std::string::npos, cookies2.find("F=G"));
2867 histograms.ExpectTotalCount(cookie_source_histogram, 5);
2869 // Set a non-Secure cookie on a non-cryptographic scheme.
2870 EXPECT_TRUE(SetCookie(cm.get(), url_google_, "H=I; path=/"));
2871 histograms.ExpectTotalCount(cookie_source_histogram, 6);
2872 histograms.ExpectBucketCount(
2873 cookie_source_histogram,
2874 CookieMonster::COOKIE_SOURCE_NONSECURE_COOKIE_NONCRYPTOGRAPHIC_SCHEME, 1);
2877 class CookieMonsterNotificationTest : public CookieMonsterTest {
2878 public:
2879 CookieMonsterNotificationTest()
2880 : test_url_("http://www.google.com/foo"),
2881 store_(new MockPersistentCookieStore),
2882 monster_(new CookieMonster(store_.get(), NULL)) {}
2884 ~CookieMonsterNotificationTest() override {}
2886 CookieMonster* monster() { return monster_.get(); }
2888 protected:
2889 const GURL test_url_;
2891 private:
2892 scoped_refptr<MockPersistentCookieStore> store_;
2893 scoped_refptr<CookieMonster> monster_;
2896 void RecordCookieChanges(std::vector<CanonicalCookie>* out_cookies,
2897 std::vector<bool>* out_removes,
2898 const CanonicalCookie& cookie,
2899 bool removed) {
2900 DCHECK(out_cookies);
2901 out_cookies->push_back(cookie);
2902 if (out_removes)
2903 out_removes->push_back(removed);
2906 TEST_F(CookieMonsterNotificationTest, NoNotifyWithNoCookie) {
2907 std::vector<CanonicalCookie> cookies;
2908 scoped_ptr<CookieStore::CookieChangedSubscription> sub(
2909 monster()->AddCallbackForCookie(
2910 test_url_, "abc",
2911 base::Bind(&RecordCookieChanges, &cookies, nullptr)));
2912 base::MessageLoop::current()->RunUntilIdle();
2913 EXPECT_EQ(0U, cookies.size());
2916 TEST_F(CookieMonsterNotificationTest, NoNotifyWithInitialCookie) {
2917 std::vector<CanonicalCookie> cookies;
2918 SetCookie(monster(), test_url_, "abc=def");
2919 base::MessageLoop::current()->RunUntilIdle();
2920 scoped_ptr<CookieStore::CookieChangedSubscription> sub(
2921 monster()->AddCallbackForCookie(
2922 test_url_, "abc",
2923 base::Bind(&RecordCookieChanges, &cookies, nullptr)));
2924 base::MessageLoop::current()->RunUntilIdle();
2925 EXPECT_EQ(0U, cookies.size());
2928 TEST_F(CookieMonsterNotificationTest, NotifyOnSet) {
2929 std::vector<CanonicalCookie> cookies;
2930 std::vector<bool> removes;
2931 scoped_ptr<CookieStore::CookieChangedSubscription> sub(
2932 monster()->AddCallbackForCookie(
2933 test_url_, "abc",
2934 base::Bind(&RecordCookieChanges, &cookies, &removes)));
2935 SetCookie(monster(), test_url_, "abc=def");
2936 base::MessageLoop::current()->RunUntilIdle();
2937 EXPECT_EQ(1U, cookies.size());
2938 EXPECT_EQ(1U, removes.size());
2940 EXPECT_EQ("abc", cookies[0].Name());
2941 EXPECT_EQ("def", cookies[0].Value());
2942 EXPECT_FALSE(removes[0]);
2945 TEST_F(CookieMonsterNotificationTest, NotifyOnDelete) {
2946 std::vector<CanonicalCookie> cookies;
2947 std::vector<bool> removes;
2948 scoped_ptr<CookieStore::CookieChangedSubscription> sub(
2949 monster()->AddCallbackForCookie(
2950 test_url_, "abc",
2951 base::Bind(&RecordCookieChanges, &cookies, &removes)));
2952 SetCookie(monster(), test_url_, "abc=def");
2953 base::MessageLoop::current()->RunUntilIdle();
2954 EXPECT_EQ(1U, cookies.size());
2955 EXPECT_EQ(1U, removes.size());
2957 DeleteCookie(monster(), test_url_, "abc");
2958 base::MessageLoop::current()->RunUntilIdle();
2959 EXPECT_EQ(2U, cookies.size());
2960 EXPECT_EQ(2U, removes.size());
2962 EXPECT_EQ("abc", cookies[1].Name());
2963 EXPECT_EQ("def", cookies[1].Value());
2964 EXPECT_TRUE(removes[1]);
2967 TEST_F(CookieMonsterNotificationTest, NotifyOnUpdate) {
2968 std::vector<CanonicalCookie> cookies;
2969 std::vector<bool> removes;
2970 scoped_ptr<CookieStore::CookieChangedSubscription> sub(
2971 monster()->AddCallbackForCookie(
2972 test_url_, "abc",
2973 base::Bind(&RecordCookieChanges, &cookies, &removes)));
2974 SetCookie(monster(), test_url_, "abc=def");
2975 base::MessageLoop::current()->RunUntilIdle();
2976 EXPECT_EQ(1U, cookies.size());
2978 // Replacing an existing cookie is actually a two-phase delete + set
2979 // operation, so we get an extra notification.
2980 SetCookie(monster(), test_url_, "abc=ghi");
2981 base::MessageLoop::current()->RunUntilIdle();
2983 EXPECT_EQ(3U, cookies.size());
2984 EXPECT_EQ(3U, removes.size());
2986 EXPECT_EQ("abc", cookies[1].Name());
2987 EXPECT_EQ("def", cookies[1].Value());
2988 EXPECT_TRUE(removes[1]);
2990 EXPECT_EQ("abc", cookies[2].Name());
2991 EXPECT_EQ("ghi", cookies[2].Value());
2992 EXPECT_FALSE(removes[2]);
2995 TEST_F(CookieMonsterNotificationTest, MultipleNotifies) {
2996 std::vector<CanonicalCookie> cookies0;
2997 std::vector<CanonicalCookie> cookies1;
2998 scoped_ptr<CookieStore::CookieChangedSubscription> sub0(
2999 monster()->AddCallbackForCookie(
3000 test_url_, "abc",
3001 base::Bind(&RecordCookieChanges, &cookies0, nullptr)));
3002 scoped_ptr<CookieStore::CookieChangedSubscription> sub1(
3003 monster()->AddCallbackForCookie(
3004 test_url_, "def",
3005 base::Bind(&RecordCookieChanges, &cookies1, nullptr)));
3006 SetCookie(monster(), test_url_, "abc=def");
3007 base::MessageLoop::current()->RunUntilIdle();
3008 EXPECT_EQ(1U, cookies0.size());
3009 EXPECT_EQ(0U, cookies1.size());
3010 SetCookie(monster(), test_url_, "def=abc");
3011 base::MessageLoop::current()->RunUntilIdle();
3012 EXPECT_EQ(1U, cookies0.size());
3013 EXPECT_EQ(1U, cookies1.size());
3016 TEST_F(CookieMonsterNotificationTest, MultipleSameNotifies) {
3017 std::vector<CanonicalCookie> cookies0;
3018 std::vector<CanonicalCookie> cookies1;
3019 scoped_ptr<CookieStore::CookieChangedSubscription> sub0(
3020 monster()->AddCallbackForCookie(
3021 test_url_, "abc",
3022 base::Bind(&RecordCookieChanges, &cookies0, nullptr)));
3023 scoped_ptr<CookieStore::CookieChangedSubscription> sub1(
3024 monster()->AddCallbackForCookie(
3025 test_url_, "abc",
3026 base::Bind(&RecordCookieChanges, &cookies1, nullptr)));
3027 SetCookie(monster(), test_url_, "abc=def");
3028 base::MessageLoop::current()->RunUntilIdle();
3029 EXPECT_EQ(1U, cookies0.size());
3030 EXPECT_EQ(1U, cookies0.size());
3033 } // namespace net