Home | History | Annotate | Download | only in base
      1 // Copyright (c) 2006-2008 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 <time.h>
      6 
      7 #include <string>
      8 
      9 #include "base/basictypes.h"
     10 #include "base/platform_thread.h"
     11 #include "base/ref_counted.h"
     12 #include "base/string_util.h"
     13 #include "base/time.h"
     14 #include "googleurl/src/gurl.h"
     15 #include "net/base/cookie_monster.h"
     16 #include "testing/gtest/include/gtest/gtest.h"
     17 
     18 using base::Time;
     19 using base::TimeDelta;
     20 
     21 namespace {
     22   class ParsedCookieTest : public testing::Test { };
     23   class CookieMonsterTest : public testing::Test { };
     24 }
     25 
     26 
     27 TEST(ParsedCookieTest, TestBasic) {
     28   net::CookieMonster::ParsedCookie pc("a=b");
     29   EXPECT_TRUE(pc.IsValid());
     30   EXPECT_FALSE(pc.IsSecure());
     31   EXPECT_EQ("a", pc.Name());
     32   EXPECT_EQ("b", pc.Value());
     33 }
     34 
     35 TEST(ParsedCookieTest, TestQuoted) {
     36   // These are some quoting cases which the major browsers all
     37   // handle differently.  I've tested Internet Explorer 6, Opera 9.6,
     38   // Firefox 3, and Safari Windows 3.2.1.  We originally tried to match
     39   // Firefox closely, however we now match Internet Explorer and Safari.
     40   const char* values[] = {
     41     // Trailing whitespace after a quoted value.  The whitespace after
     42     // the quote is stripped in all browsers.
     43     "\"zzz \"  ",              "\"zzz \"",
     44     // Handling a quoted value with a ';', like FOO="zz;pp"  ;
     45     // IE and Safari: "zz;
     46     // Firefox and Opera: "zz;pp"
     47     "\"zz;pp\" ;",             "\"zz",
     48     // Handling a value with multiple quoted parts, like FOO="zzz "   "ppp" ;
     49     // IE and Safari: "zzz "   "ppp";
     50     // Firefox: "zzz ";
     51     // Opera: <rejects cookie>
     52     "\"zzz \"   \"ppp\" ",     "\"zzz \"   \"ppp\"",
     53     // A quote in a value that didn't start quoted.  like FOO=A"B ;
     54     // IE, Safari, and Firefox: A"B;
     55     // Opera: <rejects cookie>
     56     "A\"B",                    "A\"B",
     57   };
     58 
     59   for (size_t i = 0; i < arraysize(values); i += 2) {
     60     std::string input(values[i]);
     61     std::string expected(values[i + 1]);
     62 
     63     net::CookieMonster::ParsedCookie pc(
     64         "aBc=" + input + " ; path=\"/\"  ; httponly ");
     65     EXPECT_TRUE(pc.IsValid());
     66     EXPECT_FALSE(pc.IsSecure());
     67     EXPECT_TRUE(pc.IsHttpOnly());
     68     EXPECT_TRUE(pc.HasPath());
     69     EXPECT_EQ("aBc", pc.Name());
     70     EXPECT_EQ(expected, pc.Value());
     71 
     72     // If a path was quoted, the path attribute keeps the quotes.  This will
     73     // make the cookie effectively useless, but path parameters aren't supposed
     74     // to be quoted.  Bug 1261605.
     75     EXPECT_EQ("\"/\"", pc.Path());
     76   }
     77 }
     78 
     79 TEST(ParsedCookieTest, TestNameless) {
     80   net::CookieMonster::ParsedCookie pc("BLAHHH; path=/; secure;");
     81   EXPECT_TRUE(pc.IsValid());
     82   EXPECT_TRUE(pc.IsSecure());
     83   EXPECT_TRUE(pc.HasPath());
     84   EXPECT_EQ("/", pc.Path());
     85   EXPECT_EQ("", pc.Name());
     86   EXPECT_EQ("BLAHHH", pc.Value());
     87 }
     88 
     89 TEST(ParsedCookieTest, TestAttributeCase) {
     90   net::CookieMonster::ParsedCookie pc("BLAHHH; Path=/; sECuRe; httpONLY");
     91   EXPECT_TRUE(pc.IsValid());
     92   EXPECT_TRUE(pc.IsSecure());
     93   EXPECT_TRUE(pc.IsHttpOnly());
     94   EXPECT_TRUE(pc.HasPath());
     95   EXPECT_EQ("/", pc.Path());
     96   EXPECT_EQ("", pc.Name());
     97   EXPECT_EQ("BLAHHH", pc.Value());
     98   EXPECT_EQ(3U, pc.NumberOfAttributes());
     99 }
    100 
    101 TEST(ParsedCookieTest, TestDoubleQuotedNameless) {
    102   net::CookieMonster::ParsedCookie pc("\"BLA\\\"HHH\"; path=/; secure;");
    103   EXPECT_TRUE(pc.IsValid());
    104   EXPECT_TRUE(pc.IsSecure());
    105   EXPECT_TRUE(pc.HasPath());
    106   EXPECT_EQ("/", pc.Path());
    107   EXPECT_EQ("", pc.Name());
    108   EXPECT_EQ("\"BLA\\\"HHH\"", pc.Value());
    109   EXPECT_EQ(2U, pc.NumberOfAttributes());
    110 }
    111 
    112 TEST(ParsedCookieTest, QuoteOffTheEnd) {
    113   net::CookieMonster::ParsedCookie pc("a=\"B");
    114   EXPECT_TRUE(pc.IsValid());
    115   EXPECT_EQ("a", pc.Name());
    116   EXPECT_EQ("\"B", pc.Value());
    117   EXPECT_EQ(0U, pc.NumberOfAttributes());
    118 }
    119 
    120 TEST(ParsedCookieTest, MissingName) {
    121   net::CookieMonster::ParsedCookie pc("=ABC");
    122   EXPECT_TRUE(pc.IsValid());
    123   EXPECT_EQ("", pc.Name());
    124   EXPECT_EQ("ABC", pc.Value());
    125   EXPECT_EQ(0U, pc.NumberOfAttributes());
    126 }
    127 
    128 TEST(ParsedCookieTest, MissingValue) {
    129   net::CookieMonster::ParsedCookie pc("ABC=;  path = /wee");
    130   EXPECT_TRUE(pc.IsValid());
    131   EXPECT_EQ("ABC", pc.Name());
    132   EXPECT_EQ("", pc.Value());
    133   EXPECT_TRUE(pc.HasPath());
    134   EXPECT_EQ("/wee", pc.Path());
    135   EXPECT_EQ(1U, pc.NumberOfAttributes());
    136 }
    137 
    138 TEST(ParsedCookieTest, Whitespace) {
    139   net::CookieMonster::ParsedCookie pc("  A  = BC  ;secure;;;   httponly");
    140   EXPECT_TRUE(pc.IsValid());
    141   EXPECT_EQ("A", pc.Name());
    142   EXPECT_EQ("BC", pc.Value());
    143   EXPECT_FALSE(pc.HasPath());
    144   EXPECT_FALSE(pc.HasDomain());
    145   EXPECT_TRUE(pc.IsSecure());
    146   EXPECT_TRUE(pc.IsHttpOnly());
    147   // We parse anything between ; as attributes, so we end up with two
    148   // attributes with an empty string name and value.
    149   EXPECT_EQ(4U, pc.NumberOfAttributes());
    150 }
    151 TEST(ParsedCookieTest, MultipleEquals) {
    152   net::CookieMonster::ParsedCookie pc("  A=== BC  ;secure;;;   httponly");
    153   EXPECT_TRUE(pc.IsValid());
    154   EXPECT_EQ("A", pc.Name());
    155   EXPECT_EQ("== BC", pc.Value());
    156   EXPECT_FALSE(pc.HasPath());
    157   EXPECT_FALSE(pc.HasDomain());
    158   EXPECT_TRUE(pc.IsSecure());
    159   EXPECT_TRUE(pc.IsHttpOnly());
    160   EXPECT_EQ(4U, pc.NumberOfAttributes());
    161 }
    162 
    163 TEST(ParsedCookieTest, QuotedTrailingWhitespace) {
    164   net::CookieMonster::ParsedCookie pc("ANCUUID=\"zohNumRKgI0oxyhSsV3Z7D\"  ; "
    165                                       "expires=Sun, 18-Apr-2027 21:06:29 GMT ; "
    166                                       "path=/  ;  ");
    167   EXPECT_TRUE(pc.IsValid());
    168   EXPECT_EQ("ANCUUID", pc.Name());
    169   // Stripping whitespace after the quotes matches all other major browsers.
    170   EXPECT_EQ("\"zohNumRKgI0oxyhSsV3Z7D\"", pc.Value());
    171   EXPECT_TRUE(pc.HasExpires());
    172   EXPECT_TRUE(pc.HasPath());
    173   EXPECT_EQ("/", pc.Path());
    174   EXPECT_EQ(2U, pc.NumberOfAttributes());
    175 }
    176 
    177 TEST(ParsedCookieTest, TrailingWhitespace) {
    178   net::CookieMonster::ParsedCookie pc("ANCUUID=zohNumRKgI0oxyhSsV3Z7D  ; "
    179                                       "expires=Sun, 18-Apr-2027 21:06:29 GMT ; "
    180                                       "path=/  ;  ");
    181   EXPECT_TRUE(pc.IsValid());
    182   EXPECT_EQ("ANCUUID", pc.Name());
    183   EXPECT_EQ("zohNumRKgI0oxyhSsV3Z7D", pc.Value());
    184   EXPECT_TRUE(pc.HasExpires());
    185   EXPECT_TRUE(pc.HasPath());
    186   EXPECT_EQ("/", pc.Path());
    187   EXPECT_EQ(2U, pc.NumberOfAttributes());
    188 }
    189 
    190 TEST(ParsedCookieTest, TooManyPairs) {
    191   std::string blankpairs;
    192   blankpairs.resize(net::CookieMonster::ParsedCookie::kMaxPairs - 1, ';');
    193 
    194   net::CookieMonster::ParsedCookie pc1(blankpairs + "secure");
    195   EXPECT_TRUE(pc1.IsValid());
    196   EXPECT_TRUE(pc1.IsSecure());
    197 
    198   net::CookieMonster::ParsedCookie pc2(blankpairs + ";secure");
    199   EXPECT_TRUE(pc2.IsValid());
    200   EXPECT_FALSE(pc2.IsSecure());
    201 }
    202 
    203 // TODO some better test cases for invalid cookies.
    204 TEST(ParsedCookieTest, InvalidWhitespace) {
    205   net::CookieMonster::ParsedCookie pc("    ");
    206   EXPECT_FALSE(pc.IsValid());
    207 }
    208 
    209 TEST(ParsedCookieTest, InvalidTooLong) {
    210   std::string maxstr;
    211   maxstr.resize(net::CookieMonster::ParsedCookie::kMaxCookieSize, 'a');
    212 
    213   net::CookieMonster::ParsedCookie pc1(maxstr);
    214   EXPECT_TRUE(pc1.IsValid());
    215 
    216   net::CookieMonster::ParsedCookie pc2(maxstr + "A");
    217   EXPECT_FALSE(pc2.IsValid());
    218 }
    219 
    220 TEST(ParsedCookieTest, InvalidEmpty) {
    221   net::CookieMonster::ParsedCookie pc("");
    222   EXPECT_FALSE(pc.IsValid());
    223 }
    224 
    225 TEST(ParsedCookieTest, EmbeddedTerminator) {
    226   net::CookieMonster::ParsedCookie pc1("AAA=BB\0ZYX");
    227   net::CookieMonster::ParsedCookie pc2("AAA=BB\rZYX");
    228   net::CookieMonster::ParsedCookie pc3("AAA=BB\nZYX");
    229   EXPECT_TRUE(pc1.IsValid());
    230   EXPECT_EQ("AAA", pc1.Name());
    231   EXPECT_EQ("BB", pc1.Value());
    232   EXPECT_TRUE(pc2.IsValid());
    233   EXPECT_EQ("AAA", pc2.Name());
    234   EXPECT_EQ("BB", pc2.Value());
    235   EXPECT_TRUE(pc3.IsValid());
    236   EXPECT_EQ("AAA", pc3.Name());
    237   EXPECT_EQ("BB", pc3.Value());
    238 }
    239 
    240 static const char kUrlGoogle[] = "http://www.google.izzle";
    241 static const char kUrlGoogleSecure[] = "https://www.google.izzle";
    242 static const char kUrlFtp[] = "ftp://ftp.google.izzle/";
    243 static const char kValidCookieLine[] = "A=B; path=/";
    244 static const char kValidDomainCookieLine[] = "A=B; path=/; domain=google.izzle";
    245 
    246 TEST(CookieMonsterTest, DomainTest) {
    247   GURL url_google(kUrlGoogle);
    248 
    249   scoped_refptr<net::CookieMonster> cm(new net::CookieMonster);
    250   EXPECT_TRUE(cm->SetCookie(url_google, "A=B"));
    251   EXPECT_EQ("A=B", cm->GetCookies(url_google));
    252   EXPECT_TRUE(cm->SetCookie(url_google, "C=D; domain=.google.izzle"));
    253   EXPECT_EQ("A=B; C=D", cm->GetCookies(url_google));
    254 
    255   // Verify that A=B was set as a host cookie rather than a domain
    256   // cookie -- should not be accessible from a sub sub-domain.
    257   EXPECT_EQ("C=D", cm->GetCookies(GURL("http://foo.www.google.izzle")));
    258 
    259   // Test and make sure we find domain cookies on the same domain.
    260   EXPECT_TRUE(cm->SetCookie(url_google, "E=F; domain=.www.google.izzle"));
    261   EXPECT_EQ("A=B; C=D; E=F", cm->GetCookies(url_google));
    262 
    263   // Test setting a domain= that doesn't start w/ a dot, should
    264   // treat it as a domain cookie, as if there was a pre-pended dot.
    265   EXPECT_TRUE(cm->SetCookie(url_google, "G=H; domain=www.google.izzle"));
    266   EXPECT_EQ("A=B; C=D; E=F; G=H", cm->GetCookies(url_google));
    267 
    268   // Test domain enforcement, should fail on a sub-domain or something too deep.
    269   EXPECT_FALSE(cm->SetCookie(url_google, "I=J; domain=.izzle"));
    270   EXPECT_EQ("", cm->GetCookies(GURL("http://a.izzle")));
    271   EXPECT_FALSE(cm->SetCookie(url_google, "K=L; domain=.bla.www.google.izzle"));
    272   EXPECT_EQ("C=D; E=F; G=H",
    273             cm->GetCookies(GURL("http://bla.www.google.izzle")));
    274   EXPECT_EQ("A=B; C=D; E=F; G=H", cm->GetCookies(url_google));
    275 }
    276 
    277 // FireFox recognizes domains containing trailing periods as valid.
    278 // IE and Safari do not. Assert the expected policy here.
    279 TEST(CookieMonsterTest, DomainWithTrailingDotTest) {
    280   scoped_refptr<net::CookieMonster> cm(new net::CookieMonster);
    281   GURL url_google("http://www.google.com");
    282 
    283   EXPECT_FALSE(cm->SetCookie(url_google, "a=1; domain=.www.google.com."));
    284   EXPECT_FALSE(cm->SetCookie(url_google, "b=2; domain=.www.google.com.."));
    285   EXPECT_EQ("", cm->GetCookies(url_google));
    286 }
    287 
    288 // Test that cookies can bet set on higher level domains.
    289 // http://b/issue?id=896491
    290 TEST(CookieMonsterTest, ValidSubdomainTest) {
    291   scoped_refptr<net::CookieMonster> cm(new net::CookieMonster);
    292   GURL url_abcd("http://a.b.c.d.com");
    293   GURL url_bcd("http://b.c.d.com");
    294   GURL url_cd("http://c.d.com");
    295   GURL url_d("http://d.com");
    296 
    297   EXPECT_TRUE(cm->SetCookie(url_abcd, "a=1; domain=.a.b.c.d.com"));
    298   EXPECT_TRUE(cm->SetCookie(url_abcd, "b=2; domain=.b.c.d.com"));
    299   EXPECT_TRUE(cm->SetCookie(url_abcd, "c=3; domain=.c.d.com"));
    300   EXPECT_TRUE(cm->SetCookie(url_abcd, "d=4; domain=.d.com"));
    301 
    302   EXPECT_EQ("a=1; b=2; c=3; d=4", cm->GetCookies(url_abcd));
    303   EXPECT_EQ("b=2; c=3; d=4", cm->GetCookies(url_bcd));
    304   EXPECT_EQ("c=3; d=4", cm->GetCookies(url_cd));
    305   EXPECT_EQ("d=4", cm->GetCookies(url_d));
    306 
    307   // Check that the same cookie can exist on different sub-domains.
    308   EXPECT_TRUE(cm->SetCookie(url_bcd, "X=bcd; domain=.b.c.d.com"));
    309   EXPECT_TRUE(cm->SetCookie(url_bcd, "X=cd; domain=.c.d.com"));
    310   EXPECT_EQ("b=2; c=3; d=4; X=bcd; X=cd", cm->GetCookies(url_bcd));
    311   EXPECT_EQ("c=3; d=4; X=cd", cm->GetCookies(url_cd));
    312 }
    313 
    314 // Test that setting a cookie which specifies an invalid domain has
    315 // no side-effect. An invalid domain in this context is one which does
    316 // not match the originating domain.
    317 // http://b/issue?id=896472
    318 TEST(CookieMonsterTest, InvalidDomainTest) {
    319   {
    320     scoped_refptr<net::CookieMonster> cm(new net::CookieMonster);
    321     GURL url_foobar("http://foo.bar.com");
    322 
    323     // More specific sub-domain than allowed.
    324     EXPECT_FALSE(cm->SetCookie(url_foobar, "a=1; domain=.yo.foo.bar.com"));
    325 
    326     EXPECT_FALSE(cm->SetCookie(url_foobar, "b=2; domain=.foo.com"));
    327     EXPECT_FALSE(cm->SetCookie(url_foobar, "c=3; domain=.bar.foo.com"));
    328 
    329     // Different TLD, but the rest is a substring.
    330     EXPECT_FALSE(cm->SetCookie(url_foobar, "d=4; domain=.foo.bar.com.net"));
    331 
    332     // A substring that isn't really a parent domain.
    333     EXPECT_FALSE(cm->SetCookie(url_foobar, "e=5; domain=ar.com"));
    334 
    335     // Completely invalid domains:
    336     EXPECT_FALSE(cm->SetCookie(url_foobar, "f=6; domain=."));
    337     EXPECT_FALSE(cm->SetCookie(url_foobar, "g=7; domain=/"));
    338     EXPECT_FALSE(cm->SetCookie(url_foobar, "h=8; domain=http://foo.bar.com"));
    339     EXPECT_FALSE(cm->SetCookie(url_foobar, "i=9; domain=..foo.bar.com"));
    340     EXPECT_FALSE(cm->SetCookie(url_foobar, "j=10; domain=..bar.com"));
    341 
    342     // Make sure there isn't something quirky in the domain canonicalization
    343     // that supports full URL semantics.
    344     EXPECT_FALSE(cm->SetCookie(url_foobar, "k=11; domain=.foo.bar.com?blah"));
    345     EXPECT_FALSE(cm->SetCookie(url_foobar, "l=12; domain=.foo.bar.com/blah"));
    346     EXPECT_FALSE(cm->SetCookie(url_foobar, "m=13; domain=.foo.bar.com:80"));
    347     EXPECT_FALSE(cm->SetCookie(url_foobar, "n=14; domain=.foo.bar.com:"));
    348     EXPECT_FALSE(cm->SetCookie(url_foobar, "o=15; domain=.foo.bar.com#sup"));
    349 
    350     EXPECT_EQ("", cm->GetCookies(url_foobar));
    351   }
    352 
    353   {
    354     // Make sure the cookie code hasn't gotten its subdomain string handling
    355     // reversed, missed a suffix check, etc.  It's important here that the two
    356     // hosts below have the same domain + registry.
    357     scoped_refptr<net::CookieMonster> cm(new net::CookieMonster);
    358     GURL url_foocom("http://foo.com.com");
    359     EXPECT_FALSE(cm->SetCookie(url_foocom, "a=1; domain=.foo.com.com.com"));
    360     EXPECT_EQ("", cm->GetCookies(url_foocom));
    361   }
    362 }
    363 
    364 // Test the behavior of omitting dot prefix from domain, should
    365 // function the same as FireFox.
    366 // http://b/issue?id=889898
    367 TEST(CookieMonsterTest, DomainWithoutLeadingDotTest) {
    368   {  // The omission of dot results in setting a domain cookie.
    369     scoped_refptr<net::CookieMonster> cm(new net::CookieMonster);
    370     GURL url_hosted("http://manage.hosted.filefront.com");
    371     GURL url_filefront("http://www.filefront.com");
    372     EXPECT_TRUE(cm->SetCookie(url_hosted, "sawAd=1; domain=filefront.com"));
    373     EXPECT_EQ("sawAd=1", cm->GetCookies(url_hosted));
    374     EXPECT_EQ("sawAd=1", cm->GetCookies(url_filefront));
    375   }
    376 
    377   {  // Even when the domains match exactly, don't consider it host cookie.
    378     scoped_refptr<net::CookieMonster> cm(new net::CookieMonster);
    379     GURL url("http://www.google.com");
    380     EXPECT_TRUE(cm->SetCookie(url, "a=1; domain=www.google.com"));
    381     EXPECT_EQ("a=1", cm->GetCookies(url));
    382     EXPECT_EQ("a=1", cm->GetCookies(GURL("http://sub.www.google.com")));
    383     EXPECT_EQ("", cm->GetCookies(GURL("http://something-else.com")));
    384   }
    385 }
    386 
    387 // Test that the domain specified in cookie string is treated case-insensitive
    388 // http://b/issue?id=896475.
    389 TEST(CookieMonsterTest, CaseInsensitiveDomainTest) {
    390   scoped_refptr<net::CookieMonster> cm(new net::CookieMonster);
    391   GURL url_google("http://www.google.com");
    392   EXPECT_TRUE(cm->SetCookie(url_google, "a=1; domain=.GOOGLE.COM"));
    393   EXPECT_TRUE(cm->SetCookie(url_google, "b=2; domain=.wWw.gOOgLE.coM"));
    394   EXPECT_EQ("a=1; b=2", cm->GetCookies(url_google));
    395 }
    396 
    397 TEST(CookieMonsterTest, TestIpAddress) {
    398   GURL url_ip("http://1.2.3.4/weee");
    399   {
    400     scoped_refptr<net::CookieMonster> cm(new net::CookieMonster);
    401     EXPECT_TRUE(cm->SetCookie(url_ip, kValidCookieLine));
    402     EXPECT_EQ("A=B", cm->GetCookies(url_ip));
    403   }
    404 
    405   {  // IP addresses should not be able to set domain cookies.
    406     scoped_refptr<net::CookieMonster> cm(new net::CookieMonster);
    407     EXPECT_FALSE(cm->SetCookie(url_ip, "b=2; domain=.1.2.3.4"));
    408     EXPECT_FALSE(cm->SetCookie(url_ip, "c=3; domain=.3.4"));
    409     EXPECT_EQ("", cm->GetCookies(url_ip));
    410     // It should be allowed to set a cookie if domain= matches the IP address
    411     // exactly.  This matches IE/Firefox, even though it seems a bit wrong.
    412     EXPECT_FALSE(cm->SetCookie(url_ip, "b=2; domain=1.2.3.3"));
    413     EXPECT_EQ("", cm->GetCookies(url_ip));
    414     EXPECT_TRUE(cm->SetCookie(url_ip, "b=2; domain=1.2.3.4"));
    415     EXPECT_EQ("b=2", cm->GetCookies(url_ip));
    416   }
    417 }
    418 
    419 // Test host cookies, and setting of cookies on TLD.
    420 TEST(CookieMonsterTest, TestNonDottedAndTLD) {
    421   {
    422     scoped_refptr<net::CookieMonster> cm(new net::CookieMonster);
    423     GURL url("http://com/");
    424     // Allow setting on "com", (but only as a host cookie).
    425     EXPECT_TRUE(cm->SetCookie(url, "a=1"));
    426     EXPECT_FALSE(cm->SetCookie(url, "b=2; domain=.com"));
    427     EXPECT_FALSE(cm->SetCookie(url, "c=3; domain=com"));
    428     EXPECT_EQ("a=1", cm->GetCookies(url));
    429     // Make sure it doesn't show up for a normal .com, it should be a host
    430     // not a domain cookie.
    431     EXPECT_EQ("", cm->GetCookies(GURL("http://hopefully-no-cookies.com/")));
    432     EXPECT_EQ("", cm->GetCookies(GURL("http://.com/")));
    433   }
    434 
    435   {  // http://com. should be treated the same as http://com.
    436     scoped_refptr<net::CookieMonster> cm(new net::CookieMonster);
    437     GURL url("http://com./index.html");
    438     EXPECT_TRUE(cm->SetCookie(url, "a=1"));
    439     EXPECT_EQ("a=1", cm->GetCookies(url));
    440     EXPECT_EQ("", cm->GetCookies(GURL("http://hopefully-no-cookies.com./")));
    441   }
    442 
    443   {  // Should not be able to set host cookie from a subdomain.
    444     scoped_refptr<net::CookieMonster> cm(new net::CookieMonster);
    445     GURL url("http://a.b");
    446     EXPECT_FALSE(cm->SetCookie(url, "a=1; domain=.b"));
    447     EXPECT_FALSE(cm->SetCookie(url, "b=2; domain=b"));
    448     EXPECT_EQ("", cm->GetCookies(url));
    449   }
    450 
    451   {  // Same test as above, but explicitly on a known TLD (com).
    452     scoped_refptr<net::CookieMonster> cm(new net::CookieMonster);
    453     GURL url("http://google.com");
    454     EXPECT_FALSE(cm->SetCookie(url, "a=1; domain=.com"));
    455     EXPECT_FALSE(cm->SetCookie(url, "b=2; domain=com"));
    456     EXPECT_EQ("", cm->GetCookies(url));
    457   }
    458 
    459   {  // Make sure can't set cookie on TLD which is dotted.
    460     scoped_refptr<net::CookieMonster> cm(new net::CookieMonster);
    461     GURL url("http://google.co.uk");
    462     EXPECT_FALSE(cm->SetCookie(url, "a=1; domain=.co.uk"));
    463     EXPECT_FALSE(cm->SetCookie(url, "b=2; domain=.uk"));
    464     EXPECT_EQ("", cm->GetCookies(url));
    465     EXPECT_EQ("", cm->GetCookies(GURL("http://something-else.co.uk")));
    466     EXPECT_EQ("", cm->GetCookies(GURL("http://something-else.uk")));
    467   }
    468 
    469   {  // Intranet URLs should only be able to set host cookies.
    470     scoped_refptr<net::CookieMonster> cm(new net::CookieMonster);
    471     GURL url("http://b");
    472     EXPECT_TRUE(cm->SetCookie(url, "a=1"));
    473     EXPECT_FALSE(cm->SetCookie(url, "b=2; domain=.b"));
    474     EXPECT_FALSE(cm->SetCookie(url, "c=3; domain=b"));
    475     EXPECT_EQ("a=1", cm->GetCookies(url));
    476   }
    477 }
    478 
    479 // Test reading/writing cookies when the domain ends with a period,
    480 // as in "www.google.com."
    481 TEST(CookieMonsterTest, TestHostEndsWithDot) {
    482   scoped_refptr<net::CookieMonster> cm(new net::CookieMonster);
    483   GURL url("http://www.google.com");
    484   GURL url_with_dot("http://www.google.com.");
    485   EXPECT_TRUE(cm->SetCookie(url, "a=1"));
    486   EXPECT_EQ("a=1", cm->GetCookies(url));
    487 
    488   // Do not share cookie space with the dot version of domain.
    489   // Note: this is not what FireFox does, but it _is_ what IE+Safari do.
    490   EXPECT_FALSE(cm->SetCookie(url, "b=2; domain=.www.google.com."));
    491   EXPECT_EQ("a=1", cm->GetCookies(url));
    492 
    493   EXPECT_TRUE(cm->SetCookie(url_with_dot, "b=2; domain=.google.com."));
    494   EXPECT_EQ("b=2", cm->GetCookies(url_with_dot));
    495 
    496   // Make sure there weren't any side effects.
    497   EXPECT_EQ(cm->GetCookies(GURL("http://hopefully-no-cookies.com/")), "");
    498   EXPECT_EQ("", cm->GetCookies(GURL("http://.com/")));
    499 }
    500 
    501 TEST(CookieMonsterTest, InvalidScheme) {
    502   scoped_refptr<net::CookieMonster> cm(new net::CookieMonster);
    503   EXPECT_FALSE(cm->SetCookie(GURL(kUrlFtp), kValidCookieLine));
    504 }
    505 
    506 TEST(CookieMonsterTest, InvalidScheme_Read) {
    507   scoped_refptr<net::CookieMonster> cm(new net::CookieMonster);
    508   EXPECT_TRUE(cm->SetCookie(GURL(kUrlGoogle), kValidDomainCookieLine));
    509   EXPECT_EQ("", cm->GetCookies(GURL(kUrlFtp)));
    510 }
    511 
    512 TEST(CookieMonsterTest, PathTest) {
    513   std::string url("http://www.google.izzle");
    514   scoped_refptr<net::CookieMonster> cm(new net::CookieMonster);
    515   EXPECT_TRUE(cm->SetCookie(GURL(url), "A=B; path=/wee"));
    516   EXPECT_EQ("A=B", cm->GetCookies(GURL(url + "/wee")));
    517   EXPECT_EQ("A=B", cm->GetCookies(GURL(url + "/wee/")));
    518   EXPECT_EQ("A=B", cm->GetCookies(GURL(url + "/wee/war")));
    519   EXPECT_EQ("A=B", cm->GetCookies(GURL(url + "/wee/war/more/more")));
    520   EXPECT_EQ("", cm->GetCookies(GURL(url + "/weehee")));
    521   EXPECT_EQ("", cm->GetCookies(GURL(url + "/")));
    522 
    523   // If we add a 0 length path, it should default to /
    524   EXPECT_TRUE(cm->SetCookie(GURL(url), "A=C; path="));
    525   EXPECT_EQ("A=B; A=C", cm->GetCookies(GURL(url + "/wee")));
    526   EXPECT_EQ("A=C", cm->GetCookies(GURL(url + "/")));
    527 }
    528 
    529 TEST(CookieMonsterTest, HttpOnlyTest) {
    530   GURL url_google(kUrlGoogle);
    531   scoped_refptr<net::CookieMonster> cm(new net::CookieMonster);
    532   net::CookieOptions options;
    533   options.set_include_httponly();
    534 
    535   // Create a httponly cookie.
    536   EXPECT_TRUE(cm->SetCookieWithOptions(url_google, "A=B; httponly", options));
    537 
    538   // Check httponly read protection.
    539   EXPECT_EQ("", cm->GetCookies(url_google));
    540   EXPECT_EQ("A=B", cm->GetCookiesWithOptions(url_google, options));
    541 
    542   // Check httponly overwrite protection.
    543   EXPECT_FALSE(cm->SetCookie(url_google, "A=C"));
    544   EXPECT_EQ("", cm->GetCookies(url_google));
    545   EXPECT_EQ("A=B", cm->GetCookiesWithOptions(url_google, options));
    546   EXPECT_TRUE(cm->SetCookieWithOptions(url_google, "A=C", options));
    547   EXPECT_EQ("A=C", cm->GetCookies(url_google));
    548 
    549   // Check httponly create protection.
    550   EXPECT_FALSE(cm->SetCookie(url_google, "B=A; httponly"));
    551   EXPECT_EQ("A=C", cm->GetCookiesWithOptions(url_google, options));
    552   EXPECT_TRUE(cm->SetCookieWithOptions(url_google, "B=A; httponly", options));
    553   EXPECT_EQ("A=C; B=A", cm->GetCookiesWithOptions(url_google, options));
    554   EXPECT_EQ("A=C", cm->GetCookies(url_google));
    555 }
    556 
    557 namespace {
    558 
    559 struct CookieDateParsingCase {
    560   const char* str;
    561   const bool valid;
    562   const time_t epoch;
    563 };
    564 
    565 }  // namespace
    566 
    567 TEST(CookieMonsterTest, TestCookieDateParsing) {
    568   const CookieDateParsingCase tests[] = {
    569     { "Sat, 15-Apr-17 21:01:22 GMT",           true, 1492290082 },
    570     { "Thu, 19-Apr-2007 16:00:00 GMT",         true, 1176998400 },
    571     { "Wed, 25 Apr 2007 21:02:13 GMT",         true, 1177534933 },
    572     { "Thu, 19/Apr\\2007 16:00:00 GMT",        true, 1176998400 },
    573     { "Fri, 1 Jan 2010 01:01:50 GMT",          true, 1262307710 },
    574     { "Wednesday, 1-Jan-2003 00:00:00 GMT",    true, 1041379200 },
    575     { ", 1-Jan-2003 00:00:00 GMT",             true, 1041379200 },
    576     { " 1-Jan-2003 00:00:00 GMT",              true, 1041379200 },
    577     { "1-Jan-2003 00:00:00 GMT",               true, 1041379200 },
    578     { "Wed,18-Apr-07 22:50:12 GMT",            true, 1176936612 },
    579     { "WillyWonka  , 18-Apr-07 22:50:12 GMT",  true, 1176936612 },
    580     { "WillyWonka  , 18-Apr-07 22:50:12",      true, 1176936612 },
    581     { "WillyWonka  ,  18-apr-07   22:50:12",   true, 1176936612 },
    582     { "Mon, 18-Apr-1977 22:50:13 GMT",         true, 230251813 },
    583     { "Mon, 18-Apr-77 22:50:13 GMT",           true, 230251813 },
    584     // If the cookie came in with the expiration quoted (which in terms of
    585     // the RFC you shouldn't do), we will get string quoted.  Bug 1261605.
    586     { "\"Sat, 15-Apr-17\\\"21:01:22\\\"GMT\"", true, 1492290082 },
    587     // Test with full month names and partial names.
    588     { "Partyday, 18- April-07 22:50:12",       true, 1176936612 },
    589     { "Partyday, 18 - Apri-07 22:50:12",       true, 1176936612 },
    590     { "Wednes, 1-Januar-2003 00:00:00 GMT",    true, 1041379200 },
    591     // Test that we always take GMT even with other time zones or bogus
    592     // values.  The RFC says everything should be GMT, and in the worst case
    593     // we are 24 hours off because of zone issues.
    594     { "Sat, 15-Apr-17 21:01:22",               true, 1492290082 },
    595     { "Sat, 15-Apr-17 21:01:22 GMT-2",         true, 1492290082 },
    596     { "Sat, 15-Apr-17 21:01:22 GMT BLAH",      true, 1492290082 },
    597     { "Sat, 15-Apr-17 21:01:22 GMT-0400",      true, 1492290082 },
    598     { "Sat, 15-Apr-17 21:01:22 GMT-0400 (EDT)",true, 1492290082 },
    599     { "Sat, 15-Apr-17 21:01:22 DST",           true, 1492290082 },
    600     { "Sat, 15-Apr-17 21:01:22 -0400",         true, 1492290082 },
    601     { "Sat, 15-Apr-17 21:01:22 (hello there)", true, 1492290082 },
    602     // Test that if we encounter multiple : fields, that we take the first
    603     // that correctly parses.
    604     { "Sat, 15-Apr-17 21:01:22 11:22:33",      true, 1492290082 },
    605     { "Sat, 15-Apr-17 ::00 21:01:22",          true, 1492290082 },
    606     { "Sat, 15-Apr-17 boink:z 21:01:22",       true, 1492290082 },
    607     // We take the first, which in this case is invalid.
    608     { "Sat, 15-Apr-17 91:22:33 21:01:22",      false, 0 },
    609     // amazon.com formats their cookie expiration like this.
    610     { "Thu Apr 18 22:50:12 2007 GMT",          true, 1176936612 },
    611     // Test that hh:mm:ss can occur anywhere.
    612     { "22:50:12 Thu Apr 18 2007 GMT",          true, 1176936612 },
    613     { "Thu 22:50:12 Apr 18 2007 GMT",          true, 1176936612 },
    614     { "Thu Apr 22:50:12 18 2007 GMT",          true, 1176936612 },
    615     { "Thu Apr 18 22:50:12 2007 GMT",          true, 1176936612 },
    616     { "Thu Apr 18 2007 22:50:12 GMT",          true, 1176936612 },
    617     { "Thu Apr 18 2007 GMT 22:50:12",          true, 1176936612 },
    618     // Test that the day and year can be anywhere if they are unambigious.
    619     { "Sat, 15-Apr-17 21:01:22 GMT",           true, 1492290082 },
    620     { "15-Sat, Apr-17 21:01:22 GMT",           true, 1492290082 },
    621     { "15-Sat, Apr 21:01:22 GMT 17",           true, 1492290082 },
    622     { "15-Sat, Apr 21:01:22 GMT 2017",         true, 1492290082 },
    623     { "15 Apr 21:01:22 2017",                  true, 1492290082 },
    624     { "15 17 Apr 21:01:22",                    true, 1492290082 },
    625     { "Apr 15 17 21:01:22",                    true, 1492290082 },
    626     { "Apr 15 21:01:22 17",                    true, 1492290082 },
    627     { "2017 April 15 21:01:22",                true, 1492290082 },
    628     { "15 April 2017 21:01:22",                true, 1492290082 },
    629     // Some invalid dates
    630     { "98 April 17 21:01:22",                    false, 0 },
    631     { "Thu, 012-Aug-2008 20:49:07 GMT",          false, 0 },
    632     { "Thu, 12-Aug-31841 20:49:07 GMT",          false, 0 },
    633     { "Thu, 12-Aug-9999999999 20:49:07 GMT",     false, 0 },
    634     { "Thu, 999999999999-Aug-2007 20:49:07 GMT", false, 0 },
    635     { "Thu, 12-Aug-2007 20:61:99999999999 GMT",  false, 0 },
    636     { "IAintNoDateFool",                         false, 0 },
    637   };
    638 
    639   Time parsed_time;
    640   for (size_t i = 0; i < arraysize(tests); ++i) {
    641     parsed_time = net::CookieMonster::ParseCookieTime(tests[i].str);
    642     if (!tests[i].valid) {
    643       EXPECT_FALSE(!parsed_time.is_null()) << tests[i].str;
    644       continue;
    645     }
    646     EXPECT_TRUE(!parsed_time.is_null()) << tests[i].str;
    647     EXPECT_EQ(tests[i].epoch, parsed_time.ToTimeT()) << tests[i].str;
    648   }
    649 }
    650 
    651 TEST(CookieMonsterTest, TestCookieDeletion) {
    652   GURL url_google(kUrlGoogle);
    653   scoped_refptr<net::CookieMonster> cm(new net::CookieMonster);
    654 
    655   // Create a session cookie.
    656   EXPECT_TRUE(cm->SetCookie(url_google, kValidCookieLine));
    657   EXPECT_EQ("A=B", cm->GetCookies(url_google));
    658   // Delete it via Max-Age.
    659   EXPECT_TRUE(cm->SetCookie(url_google,
    660                            std::string(kValidCookieLine) + "; max-age=0"));
    661   EXPECT_EQ("", cm->GetCookies(url_google));
    662 
    663   // Create a session cookie.
    664   EXPECT_TRUE(cm->SetCookie(url_google, kValidCookieLine));
    665   EXPECT_EQ("A=B", cm->GetCookies(url_google));
    666   // Delete it via Expires.
    667   EXPECT_TRUE(cm->SetCookie(url_google,
    668                            std::string(kValidCookieLine) +
    669                            "; expires=Mon, 18-Apr-1977 22:50:13 GMT"));
    670   EXPECT_EQ("", cm->GetCookies(url_google));
    671 
    672   // Create a persistent cookie.
    673   EXPECT_TRUE(cm->SetCookie(url_google,
    674                            std::string(kValidCookieLine) +
    675                            "; expires=Mon, 18-Apr-22 22:50:13 GMT"));
    676   EXPECT_EQ("A=B", cm->GetCookies(url_google));
    677   // Delete it via Max-Age.
    678   EXPECT_TRUE(cm->SetCookie(url_google,
    679                            std::string(kValidCookieLine) + "; max-age=0"));
    680   EXPECT_EQ("", cm->GetCookies(url_google));
    681 
    682   // Create a persistent cookie.
    683   EXPECT_TRUE(cm->SetCookie(url_google,
    684                            std::string(kValidCookieLine) +
    685                            "; expires=Mon, 18-Apr-22 22:50:13 GMT"));
    686   EXPECT_EQ("A=B", cm->GetCookies(url_google));
    687   // Delete it via Expires.
    688   EXPECT_TRUE(cm->SetCookie(url_google,
    689                            std::string(kValidCookieLine) +
    690                            "; expires=Mon, 18-Apr-1977 22:50:13 GMT"));
    691   EXPECT_EQ("", cm->GetCookies(url_google));
    692 
    693   // Create a persistent cookie.
    694   EXPECT_TRUE(cm->SetCookie(url_google,
    695                            std::string(kValidCookieLine) +
    696                            "; expires=Mon, 18-Apr-22 22:50:13 GMT"));
    697   EXPECT_EQ("A=B", cm->GetCookies(url_google));
    698   // Delete it via Expires, with a unix epoch of 0.
    699   EXPECT_TRUE(cm->SetCookie(url_google,
    700                            std::string(kValidCookieLine) +
    701                            "; expires=Thu, 1-Jan-1970 00:00:00 GMT"));
    702   EXPECT_EQ("", cm->GetCookies(url_google));
    703 }
    704 
    705 TEST(CookieMonsterTest, TestCookieDeleteAll) {
    706   GURL url_google(kUrlGoogle);
    707   scoped_refptr<net::CookieMonster> cm(new net::CookieMonster);
    708   net::CookieOptions options;
    709   options.set_include_httponly();
    710 
    711   EXPECT_TRUE(cm->SetCookie(url_google, kValidCookieLine));
    712   EXPECT_EQ("A=B", cm->GetCookies(url_google));
    713 
    714   EXPECT_TRUE(cm->SetCookieWithOptions(url_google, "C=D; httponly", options));
    715   EXPECT_EQ("A=B; C=D", cm->GetCookiesWithOptions(url_google, options));
    716 
    717   EXPECT_EQ(2, cm->DeleteAll(false));
    718   EXPECT_EQ("", cm->GetCookiesWithOptions(url_google, options));
    719 }
    720 
    721 TEST(CookieMonsterTest, TestCookieDeleteAllCreatedAfterTimestamp) {
    722   GURL url_google(kUrlGoogle);
    723   scoped_refptr<net::CookieMonster> cm(new net::CookieMonster);
    724   Time now = Time::Now();
    725 
    726   // Nothing has been added so nothing should be deleted.
    727   EXPECT_EQ(0, cm->DeleteAllCreatedAfter(now - TimeDelta::FromDays(99), false));
    728 
    729   // Create 3 cookies with creation date of today, yesterday and the day before.
    730   EXPECT_TRUE(cm->SetCookieWithCreationTime(url_google, "T-0=Now", now));
    731   EXPECT_TRUE(cm->SetCookieWithCreationTime(url_google, "T-1=Yesterday",
    732                                            now - TimeDelta::FromDays(1)));
    733   EXPECT_TRUE(cm->SetCookieWithCreationTime(url_google, "T-2=DayBefore",
    734                                            now - TimeDelta::FromDays(2)));
    735 
    736   // Try to delete everything from now onwards.
    737   EXPECT_EQ(1, cm->DeleteAllCreatedAfter(now, false));
    738   // Now delete the one cookie created in the last day.
    739   EXPECT_EQ(1, cm->DeleteAllCreatedAfter(now - TimeDelta::FromDays(1), false));
    740   // Now effectively delete all cookies just created (1 is remaining).
    741   EXPECT_EQ(1, cm->DeleteAllCreatedAfter(now - TimeDelta::FromDays(99), false));
    742 
    743   // Make sure everything is gone.
    744   EXPECT_EQ(0, cm->DeleteAllCreatedAfter(Time(), false));
    745   // Really make sure everything is gone.
    746   EXPECT_EQ(0, cm->DeleteAll(false));
    747 }
    748 
    749 TEST(CookieMonsterTest, TestCookieDeleteAllCreatedBetweenTimestamps) {
    750   GURL url_google(kUrlGoogle);
    751   scoped_refptr<net::CookieMonster> cm(new net::CookieMonster);
    752   Time now = Time::Now();
    753 
    754   // Nothing has been added so nothing should be deleted.
    755   EXPECT_EQ(0, cm->DeleteAllCreatedAfter(now - TimeDelta::FromDays(99), false));
    756 
    757   // Create 3 cookies with creation date of today, yesterday and the day before.
    758   EXPECT_TRUE(cm->SetCookieWithCreationTime(url_google, "T-0=Now", now));
    759   EXPECT_TRUE(cm->SetCookieWithCreationTime(url_google, "T-1=Yesterday",
    760                                            now - TimeDelta::FromDays(1)));
    761   EXPECT_TRUE(cm->SetCookieWithCreationTime(url_google, "T-2=DayBefore",
    762                                            now - TimeDelta::FromDays(2)));
    763   EXPECT_TRUE(cm->SetCookieWithCreationTime(url_google, "T-3=ThreeDays",
    764                                            now - TimeDelta::FromDays(3)));
    765   EXPECT_TRUE(cm->SetCookieWithCreationTime(url_google, "T-7=LastWeek",
    766                                            now - TimeDelta::FromDays(7)));
    767 
    768   // Try to delete threedays and the daybefore.
    769   EXPECT_EQ(2, cm->DeleteAllCreatedBetween(now - TimeDelta::FromDays(3),
    770                                           now - TimeDelta::FromDays(1),
    771                                           false));
    772 
    773   // Try to delete yesterday, also make sure that delete_end is not
    774   // inclusive.
    775   EXPECT_EQ(1, cm->DeleteAllCreatedBetween(now - TimeDelta::FromDays(2),
    776                                           now,
    777                                           false));
    778 
    779   // Make sure the delete_begin is inclusive.
    780   EXPECT_EQ(1, cm->DeleteAllCreatedBetween(now - TimeDelta::FromDays(7),
    781                                           now,
    782                                           false));
    783 
    784   // Delete the last (now) item.
    785   EXPECT_EQ(1, cm->DeleteAllCreatedAfter(Time(), false));
    786 
    787   // Really make sure everything is gone.
    788   EXPECT_EQ(0, cm->DeleteAll(false));
    789 }
    790 
    791 TEST(CookieMonsterTest, TestSecure) {
    792   GURL url_google(kUrlGoogle);
    793   GURL url_google_secure(kUrlGoogleSecure);
    794   scoped_refptr<net::CookieMonster> cm(new net::CookieMonster);
    795 
    796   EXPECT_TRUE(cm->SetCookie(url_google, "A=B"));
    797   EXPECT_EQ("A=B", cm->GetCookies(url_google));
    798   EXPECT_EQ("A=B", cm->GetCookies(url_google_secure));
    799 
    800   EXPECT_TRUE(cm->SetCookie(url_google_secure, "A=B; secure"));
    801   // The secure should overwrite the non-secure.
    802   EXPECT_EQ("", cm->GetCookies(url_google));
    803   EXPECT_EQ("A=B", cm->GetCookies(url_google_secure));
    804 
    805   EXPECT_TRUE(cm->SetCookie(url_google_secure, "D=E; secure"));
    806   EXPECT_EQ("", cm->GetCookies(url_google));
    807   EXPECT_EQ("A=B; D=E", cm->GetCookies(url_google_secure));
    808 
    809   EXPECT_TRUE(cm->SetCookie(url_google_secure, "A=B"));
    810   // The non-secure should overwrite the secure.
    811   EXPECT_EQ("A=B", cm->GetCookies(url_google));
    812   EXPECT_EQ("D=E; A=B", cm->GetCookies(url_google_secure));
    813 }
    814 
    815 static Time GetFirstCookieAccessDate(net::CookieMonster* cm) {
    816   const net::CookieMonster::CookieList all_cookies(cm->GetAllCookies());
    817   return all_cookies.front().second.LastAccessDate();
    818 }
    819 
    820 static const int kLastAccessThresholdMilliseconds = 200;
    821 
    822 TEST(CookieMonsterTest, TestLastAccess) {
    823   GURL url_google(kUrlGoogle);
    824   scoped_refptr<net::CookieMonster> cm(
    825       new net::CookieMonster(kLastAccessThresholdMilliseconds));
    826 
    827   EXPECT_TRUE(cm->SetCookie(url_google, "A=B"));
    828   const Time last_access_date(GetFirstCookieAccessDate(cm));
    829 
    830   // Reading the cookie again immediately shouldn't update the access date,
    831   // since we're inside the threshold.
    832   EXPECT_EQ("A=B", cm->GetCookies(url_google));
    833   EXPECT_TRUE(last_access_date == GetFirstCookieAccessDate(cm));
    834 
    835   // Reading after a short wait should update the access date.
    836   PlatformThread::Sleep(kLastAccessThresholdMilliseconds + 20);
    837   EXPECT_EQ("A=B", cm->GetCookies(url_google));
    838   EXPECT_FALSE(last_access_date == GetFirstCookieAccessDate(cm));
    839 }
    840 
    841 static int CountInString(const std::string& str, char c) {
    842   int count = 0;
    843   for (std::string::const_iterator it = str.begin();
    844        it != str.end(); ++it) {
    845     if (*it == c)
    846       ++count;
    847   }
    848   return count;
    849 }
    850 
    851 TEST(CookieMonsterTest, TestHostGarbageCollection) {
    852   GURL url_google(kUrlGoogle);
    853   scoped_refptr<net::CookieMonster> cm(new net::CookieMonster);
    854   // Add a bunch of cookies on a single host, should purge them.
    855   for (int i = 0; i < 101; i++) {
    856     std::string cookie = StringPrintf("a%03d=b", i);
    857     EXPECT_TRUE(cm->SetCookie(url_google, cookie));
    858     std::string cookies = cm->GetCookies(url_google);
    859     // Make sure we find it in the cookies.
    860     EXPECT_TRUE(cookies.find(cookie) != std::string::npos);
    861     // Count the number of cookies.
    862     EXPECT_LE(CountInString(cookies, '='), 70);
    863   }
    864 }
    865 
    866 TEST(CookieMonsterTest, TestTotalGarbageCollection) {
    867   scoped_refptr<net::CookieMonster> cm(
    868       new net::CookieMonster(kLastAccessThresholdMilliseconds));
    869 
    870   // Add a bunch of cookies on a bunch of host, some should get purged.
    871   const GURL sticky_cookie("http://a0000.izzle");
    872   for (int i = 0; i < 4000; ++i) {
    873     GURL url(StringPrintf("http://a%04d.izzle", i));
    874     EXPECT_TRUE(cm->SetCookie(url, "a=b"));
    875     EXPECT_EQ("a=b", cm->GetCookies(url));
    876 
    877     // Keep touching the first cookie to ensure it's not purged (since it will
    878     // always have the most recent access time).
    879     if (!(i % 500)) {
    880       // Ensure the timestamps will be different enough to update.
    881       PlatformThread::Sleep(kLastAccessThresholdMilliseconds + 20);
    882       EXPECT_EQ("a=b", cm->GetCookies(sticky_cookie));
    883     }
    884   }
    885 
    886   // Check that cookies that still exist.
    887   for (int i = 0; i < 4000; ++i) {
    888     GURL url(StringPrintf("http://a%04d.izzle", i));
    889     if ((i == 0) || (i > 1001)) {
    890       // Cookies should still be around.
    891       EXPECT_FALSE(cm->GetCookies(url).empty());
    892     } else if (i < 701) {
    893       // Cookies should have gotten purged.
    894       EXPECT_TRUE(cm->GetCookies(url).empty());
    895     }
    896   }
    897 }
    898 
    899 // Formerly NetUtilTest.CookieTest back when we used wininet's cookie handling.
    900 TEST(CookieMonsterTest, NetUtilCookieTest) {
    901   const GURL test_url("http://mojo.jojo.google.izzle/");
    902 
    903   scoped_refptr<net::CookieMonster> cm(new net::CookieMonster);
    904 
    905   EXPECT_TRUE(cm->SetCookie(test_url, "foo=bar"));
    906   std::string value = cm->GetCookies(test_url);
    907   EXPECT_EQ("foo=bar", value);
    908 
    909   // test that we can retrieve all cookies:
    910   EXPECT_TRUE(cm->SetCookie(test_url, "x=1"));
    911   EXPECT_TRUE(cm->SetCookie(test_url, "y=2"));
    912 
    913   std::string result = cm->GetCookies(test_url);
    914   EXPECT_FALSE(result.empty());
    915   EXPECT_NE(result.find("x=1"), std::string::npos) << result;
    916   EXPECT_NE(result.find("y=2"), std::string::npos) << result;
    917 }
    918 
    919 static bool FindAndDeleteCookie(net::CookieMonster* cm,
    920                                 const std::string& domain,
    921                                 const std::string& name) {
    922   net::CookieMonster::CookieList cookies = cm->GetAllCookies();
    923   for (net::CookieMonster::CookieList::iterator it = cookies.begin();
    924        it != cookies.end(); ++it)
    925     if (it->first == domain && it->second.Name() == name)
    926       return cm->DeleteCookie(domain, it->second, false);
    927   return false;
    928 }
    929 
    930 TEST(CookieMonsterTest, TestDeleteSingleCookie) {
    931   GURL url_google(kUrlGoogle);
    932 
    933   scoped_refptr<net::CookieMonster> cm(new net::CookieMonster);
    934 
    935   EXPECT_TRUE(cm->SetCookie(url_google, "A=B"));
    936   EXPECT_TRUE(cm->SetCookie(url_google, "C=D"));
    937   EXPECT_TRUE(cm->SetCookie(url_google, "E=F"));
    938   EXPECT_EQ("A=B; C=D; E=F", cm->GetCookies(url_google));
    939 
    940   EXPECT_TRUE(FindAndDeleteCookie(cm, url_google.host(), "C"));
    941   EXPECT_EQ("A=B; E=F", cm->GetCookies(url_google));
    942 
    943   EXPECT_FALSE(FindAndDeleteCookie(cm, "random.host", "E"));
    944   EXPECT_EQ("A=B; E=F", cm->GetCookies(url_google));
    945 }
    946 
    947 TEST(CookieMonsterTest, SetCookieableSchemes) {
    948   scoped_refptr<net::CookieMonster> cm(new net::CookieMonster);
    949   scoped_refptr<net::CookieMonster> cm_foo(new net::CookieMonster);
    950 
    951   // Only cm_foo should allow foo:// cookies.
    952   const char* kSchemes[] = {"foo"};
    953   cm_foo->SetCookieableSchemes(kSchemes, 1);
    954 
    955   GURL foo_url("foo://host/path");
    956   GURL http_url("http://host/path");
    957 
    958   EXPECT_TRUE(cm->SetCookie(http_url, "x=1"));
    959   EXPECT_FALSE(cm->SetCookie(foo_url, "x=1"));
    960   EXPECT_TRUE(cm_foo->SetCookie(foo_url, "x=1"));
    961   EXPECT_FALSE(cm_foo->SetCookie(http_url, "x=1"));
    962 }
    963 
    964 TEST(CookieMonsterTest, GetAllCookiesForURL) {
    965 
    966   GURL url_google(kUrlGoogle);
    967   GURL url_google_secure(kUrlGoogleSecure);
    968 
    969   scoped_refptr<net::CookieMonster> cm(
    970       new net::CookieMonster(kLastAccessThresholdMilliseconds));
    971 
    972   // Create an httponly cookie.
    973   net::CookieOptions options;
    974   options.set_include_httponly();
    975 
    976   EXPECT_TRUE(cm->SetCookieWithOptions(url_google, "A=B; httponly", options));
    977   EXPECT_TRUE(cm->SetCookieWithOptions(url_google,
    978                                        "C=D; domain=.google.izzle",
    979                                        options));
    980   EXPECT_TRUE(cm->SetCookieWithOptions(url_google_secure,
    981                                        "E=F; domain=.google.izzle; secure",
    982                                        options));
    983   const Time last_access_date(GetFirstCookieAccessDate(cm));
    984 
    985   PlatformThread::Sleep(kLastAccessThresholdMilliseconds + 20);
    986 
    987   // Check raw cookies.
    988   net::CookieMonster::CookieList raw_cookies =
    989       cm->GetAllCookiesForURL(url_google);
    990   net::CookieMonster::CookieList::iterator it = raw_cookies.begin();
    991 
    992   ASSERT_TRUE(it != raw_cookies.end());
    993   EXPECT_EQ("www.google.izzle", it->first);
    994   EXPECT_EQ("A", it->second.Name());
    995 
    996   ASSERT_TRUE(++it != raw_cookies.end());
    997   EXPECT_EQ(".google.izzle", it->first);
    998   EXPECT_EQ("C", it->second.Name());
    999 
   1000   ASSERT_TRUE(++it == raw_cookies.end());
   1001 
   1002   // Test secure cookies.
   1003   raw_cookies = cm->GetAllCookiesForURL(url_google_secure);
   1004   it = raw_cookies.begin();
   1005 
   1006   ASSERT_TRUE(it != raw_cookies.end());
   1007   EXPECT_EQ("www.google.izzle", it->first);
   1008   EXPECT_EQ("A", it->second.Name());
   1009 
   1010   ASSERT_TRUE(++it != raw_cookies.end());
   1011   EXPECT_EQ(".google.izzle", it->first);
   1012   EXPECT_EQ("C", it->second.Name());
   1013 
   1014   ASSERT_TRUE(++it != raw_cookies.end());
   1015   EXPECT_EQ(".google.izzle", it->first);
   1016   EXPECT_EQ("E", it->second.Name());
   1017 
   1018   ASSERT_TRUE(++it == raw_cookies.end());
   1019 
   1020   // Reading after a short wait should not update the access date.
   1021   EXPECT_TRUE (last_access_date == GetFirstCookieAccessDate(cm));
   1022 }
   1023 
   1024 TEST(CookieMonsterTest, DeleteCookieByName) {
   1025   scoped_refptr<net::CookieMonster> cm(new net::CookieMonster);
   1026   GURL url_google(kUrlGoogle);
   1027 
   1028   EXPECT_TRUE(cm->SetCookie(url_google, "A=A1; path=/"));
   1029   EXPECT_TRUE(cm->SetCookie(url_google, "A=A2; path=/foo"));
   1030   EXPECT_TRUE(cm->SetCookie(url_google, "A=A3; path=/bar"));
   1031   EXPECT_TRUE(cm->SetCookie(url_google, "B=B1; path=/"));
   1032   EXPECT_TRUE(cm->SetCookie(url_google, "B=B2; path=/foo"));
   1033   EXPECT_TRUE(cm->SetCookie(url_google, "B=B3; path=/bar"));
   1034 
   1035   cm->DeleteCookie(GURL(std::string(kUrlGoogle) + "/foo/bar"), "A");
   1036 
   1037   net::CookieMonster::CookieList cookies = cm->GetAllCookies();
   1038   size_t expected_size = 4;
   1039   EXPECT_EQ(expected_size, cookies.size());
   1040   for (net::CookieMonster::CookieList::iterator it = cookies.begin();
   1041        it != cookies.end(); ++it) {
   1042     EXPECT_NE("A1", it->second.Value());
   1043     EXPECT_NE("A2", it->second.Value());
   1044   }
   1045 }
   1046 
   1047 // TODO test overwrite cookie
   1048