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