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