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