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 #ifndef NET_COOKIES_COOKIE_STORE_UNITTEST_H_
      6 #define NET_COOKIES_COOKIE_STORE_UNITTEST_H_
      7 
      8 #include "base/bind.h"
      9 #include "base/message_loop/message_loop.h"
     10 #include "base/strings/string_tokenizer.h"
     11 #include "base/threading/thread.h"
     12 #include "net/cookies/cookie_monster.h"
     13 #include "net/cookies/cookie_store.h"
     14 #include "net/cookies/cookie_store_test_callbacks.h"
     15 #include "testing/gtest/include/gtest/gtest.h"
     16 #include "url/gurl.h"
     17 
     18 // This file declares unittest templates that can be used to test common
     19 // behavior of any CookieStore implementation.
     20 // See cookie_monster_unittest.cc for an example of an implementation.
     21 
     22 namespace net {
     23 
     24 using base::Thread;
     25 
     26 const int kTimeout = 1000;
     27 
     28 const char kUrlFtp[] = "ftp://ftp.google.izzle/";
     29 const char kUrlGoogle[] = "http://www.google.izzle";
     30 const char kUrlGoogleFoo[] = "http://www.google.izzle/foo";
     31 const char kUrlGoogleBar[] = "http://www.google.izzle/bar";
     32 const char kUrlGoogleSecure[] = "https://www.google.izzle";
     33 const char kValidCookieLine[] = "A=B; path=/";
     34 const char kValidDomainCookieLine[] = "A=B; path=/; domain=google.izzle";
     35 
     36 // The CookieStoreTestTraits must have the following members:
     37 // struct CookieStoreTestTraits {
     38 //   // Factory function.
     39 //   static scoped_refptr<CookieStore> Create();
     40 //
     41 //   // The cookie store is a CookieMonster. Only used to test
     42 //   // GetCookieMonster().
     43 //   static const bool is_cookie_monster;
     44 //
     45 //   // The cookie store supports cookies with the exclude_httponly() option.
     46 //   static const bool supports_http_only;
     47 //
     48 //   // The cookie store is able to make the difference between the ".com"
     49 //   // and the "com" domains.
     50 //   static const bool supports_non_dotted_domains;
     51 //
     52 //   // The cookie store handles the domains with trailing dots (such as "com.")
     53 //   // correctly.
     54 //   static const bool supports_trailing_dots;
     55 //
     56 //   // The cookie store rejects cookies for invalid schemes such as ftp.
     57 //   static const bool filters_schemes;
     58 //
     59 //   // The cookie store has a bug happening when a path is a substring of
     60 //   // another.
     61 //   static const bool has_path_prefix_bug;
     62 //
     63 //   // Time to wait between two cookie insertions to ensure that cookies have
     64 //   // different creation times.
     65 //   static const int creation_time_granularity_in_ms;
     66 // };
     67 
     68 template <class CookieStoreTestTraits>
     69 class CookieStoreTest : public testing::Test {
     70  protected:
     71   CookieStoreTest()
     72       : url_google_(kUrlGoogle),
     73         url_google_secure_(kUrlGoogleSecure),
     74         url_google_foo_(kUrlGoogleFoo),
     75         url_google_bar_(kUrlGoogleBar) {
     76     // This test may be used outside of the net test suite, and thus may not
     77     // have a message loop.
     78     if (!base::MessageLoop::current())
     79       message_loop_.reset(new base::MessageLoop);
     80     weak_factory_.reset(new base::WeakPtrFactory<base::MessageLoop>(
     81         base::MessageLoop::current()));
     82   }
     83 
     84   // Helper methods for the asynchronous Cookie Store API that call the
     85   // asynchronous method and then pump the loop until the callback is invoked,
     86   // finally returning the value.
     87 
     88   std::string GetCookies(CookieStore* cs, const GURL& url) {
     89     DCHECK(cs);
     90     CookieOptions options;
     91     if (!CookieStoreTestTraits::supports_http_only)
     92       options.set_include_httponly();
     93     StringResultCookieCallback callback;
     94     cs->GetCookiesWithOptionsAsync(
     95         url, options,
     96         base::Bind(&StringResultCookieCallback::Run,
     97                    base::Unretained(&callback)));
     98     RunFor(kTimeout);
     99     EXPECT_TRUE(callback.did_run());
    100     return callback.result();
    101   }
    102 
    103   std::string GetCookiesWithOptions(CookieStore* cs,
    104                                     const GURL& url,
    105                                     const CookieOptions& options) {
    106     DCHECK(cs);
    107     StringResultCookieCallback callback;
    108     cs->GetCookiesWithOptionsAsync(
    109         url, options, base::Bind(&StringResultCookieCallback::Run,
    110                                  base::Unretained(&callback)));
    111     RunFor(kTimeout);
    112     EXPECT_TRUE(callback.did_run());
    113     return callback.result();
    114   }
    115 
    116   bool SetCookieWithOptions(CookieStore* cs,
    117                             const GURL& url,
    118                             const std::string& cookie_line,
    119                             const CookieOptions& options) {
    120     DCHECK(cs);
    121     ResultSavingCookieCallback<bool> callback;
    122     cs->SetCookieWithOptionsAsync(
    123         url, cookie_line, options,
    124         base::Bind(
    125             &ResultSavingCookieCallback<bool>::Run,
    126             base::Unretained(&callback)));
    127     RunFor(kTimeout);
    128     EXPECT_TRUE(callback.did_run());
    129     return callback.result();
    130   }
    131 
    132   bool SetCookieWithServerTime(CookieStore* cs,
    133                                const GURL& url,
    134                                const std::string& cookie_line,
    135                                const base::Time& server_time) {
    136     CookieOptions options;
    137     if (!CookieStoreTestTraits::supports_http_only)
    138       options.set_include_httponly();
    139     options.set_server_time(server_time);
    140     return SetCookieWithOptions(cs, url, cookie_line, options);
    141   }
    142 
    143   bool SetCookie(CookieStore* cs,
    144                  const GURL& url,
    145                  const std::string& cookie_line) {
    146     CookieOptions options;
    147     if (!CookieStoreTestTraits::supports_http_only)
    148       options.set_include_httponly();
    149     return SetCookieWithOptions(cs, url, cookie_line, options);
    150   }
    151 
    152   void DeleteCookie(CookieStore* cs,
    153                     const GURL& url,
    154                     const std::string& cookie_name) {
    155     DCHECK(cs);
    156     NoResultCookieCallback callback;
    157     cs->DeleteCookieAsync(
    158         url, cookie_name,
    159         base::Bind(&NoResultCookieCallback::Run, base::Unretained(&callback)));
    160     RunFor(kTimeout);
    161     EXPECT_TRUE(callback.did_run());
    162   }
    163 
    164   int DeleteCreatedBetween(CookieStore* cs,
    165                             const base::Time& delete_begin,
    166                             const base::Time& delete_end) {
    167     DCHECK(cs);
    168     ResultSavingCookieCallback<int> callback;
    169     cs->DeleteAllCreatedBetweenAsync(
    170         delete_begin, delete_end,
    171         base::Bind(
    172             &ResultSavingCookieCallback<int>::Run,
    173             base::Unretained(&callback)));
    174     RunFor(kTimeout);
    175     EXPECT_TRUE(callback.did_run());
    176     return callback.result();
    177   }
    178 
    179   int DeleteAllCreatedBetweenForHost(CookieStore* cs,
    180                                      const base::Time delete_begin,
    181                                      const base::Time delete_end,
    182                                      const GURL& url) {
    183     DCHECK(cs);
    184     ResultSavingCookieCallback<int> callback;
    185     cs->DeleteAllCreatedBetweenForHostAsync(
    186         delete_begin, delete_end, url,
    187         base::Bind(
    188             &ResultSavingCookieCallback<int>::Run,
    189             base::Unretained(&callback)));
    190     RunFor(kTimeout);
    191     EXPECT_TRUE(callback.did_run());
    192     return callback.result();
    193   }
    194 
    195   int DeleteSessionCookies(CookieStore* cs) {
    196     DCHECK(cs);
    197     ResultSavingCookieCallback<int> callback;
    198     cs->DeleteSessionCookiesAsync(
    199         base::Bind(
    200             &ResultSavingCookieCallback<int>::Run,
    201             base::Unretained(&callback)));
    202     RunFor(kTimeout);
    203     EXPECT_TRUE(callback.did_run());
    204     return callback.result();
    205   }
    206 
    207   void RunFor(int ms) {
    208     // Runs the test thread message loop for up to |ms| milliseconds.
    209     base::MessageLoop::current()->PostDelayedTask(
    210         FROM_HERE,
    211         base::Bind(&base::MessageLoop::Quit, weak_factory_->GetWeakPtr()),
    212         base::TimeDelta::FromMilliseconds(ms));
    213     base::MessageLoop::current()->Run();
    214     weak_factory_->InvalidateWeakPtrs();
    215   }
    216 
    217   scoped_refptr<CookieStore> GetCookieStore() {
    218     return CookieStoreTestTraits::Create();
    219   }
    220 
    221   // Compares two cookie lines.
    222   void MatchCookieLines(const std::string& line1, const std::string& line2) {
    223     EXPECT_EQ(TokenizeCookieLine(line1), TokenizeCookieLine(line2));
    224   }
    225 
    226   // Check the cookie line by polling until equality or a timeout is reached.
    227   void MatchCookieLineWithTimeout(CookieStore* cs,
    228                                   const GURL& url,
    229                                   const std::string& line) {
    230     std::string cookies = GetCookies(cs, url);
    231     bool matched = (TokenizeCookieLine(line) == TokenizeCookieLine(cookies));
    232     base::Time polling_end_date = base::Time::Now() +
    233         base::TimeDelta::FromMilliseconds(
    234             CookieStoreTestTraits::creation_time_granularity_in_ms);
    235 
    236     while (!matched &&  base::Time::Now() <= polling_end_date) {
    237       base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(10));
    238       cookies = GetCookies(cs, url);
    239       matched = (TokenizeCookieLine(line) == TokenizeCookieLine(cookies));
    240     }
    241 
    242     EXPECT_TRUE(matched) << "\"" << cookies
    243                          << "\" does not match \"" << line << "\"";
    244   }
    245 
    246   GURL url_google_;
    247   GURL url_google_secure_;
    248   GURL url_google_foo_;
    249   GURL url_google_bar_;
    250 
    251   scoped_ptr<base::WeakPtrFactory<base::MessageLoop> > weak_factory_;
    252   scoped_ptr<base::MessageLoop> message_loop_;
    253 
    254  private:
    255   // Returns a set of strings of type "name=value". Fails in case of duplicate.
    256   std::set<std::string> TokenizeCookieLine(const std::string& line) {
    257     std::set<std::string> tokens;
    258     base::StringTokenizer tokenizer(line, " ;");
    259     while (tokenizer.GetNext())
    260       EXPECT_TRUE(tokens.insert(tokenizer.token()).second);
    261     return tokens;
    262   }
    263 };
    264 
    265 TYPED_TEST_CASE_P(CookieStoreTest);
    266 
    267 TYPED_TEST_P(CookieStoreTest, TypeTest) {
    268   scoped_refptr<CookieStore> cs(this->GetCookieStore());
    269   EXPECT_EQ(cs->GetCookieMonster(),
    270             (TypeParam::is_cookie_monster) ?
    271                 static_cast<CookieMonster*>(cs.get()) : NULL);
    272 }
    273 
    274 TYPED_TEST_P(CookieStoreTest, DomainTest) {
    275   scoped_refptr<CookieStore> cs(this->GetCookieStore());
    276   EXPECT_TRUE(this->SetCookie(cs.get(), this->url_google_, "A=B"));
    277   this->MatchCookieLines("A=B", this->GetCookies(cs.get(), this->url_google_));
    278   EXPECT_TRUE(this->SetCookie(
    279       cs.get(), this->url_google_, "C=D; domain=.google.izzle"));
    280   this->MatchCookieLines("A=B; C=D",
    281                          this->GetCookies(cs.get(), this->url_google_));
    282 
    283   // Verify that A=B was set as a host cookie rather than a domain
    284   // cookie -- should not be accessible from a sub sub-domain.
    285   this->MatchCookieLines(
    286       "C=D", this->GetCookies(cs.get(), GURL("http://foo.www.google.izzle")));
    287 
    288   // Test and make sure we find domain cookies on the same domain.
    289   EXPECT_TRUE(this->SetCookie(
    290       cs.get(), this->url_google_, "E=F; domain=.www.google.izzle"));
    291   this->MatchCookieLines("A=B; C=D; E=F",
    292                          this->GetCookies(cs.get(), this->url_google_));
    293 
    294   // Test setting a domain= that doesn't start w/ a dot, should
    295   // treat it as a domain cookie, as if there was a pre-pended dot.
    296   EXPECT_TRUE(this->SetCookie(
    297       cs.get(), this->url_google_, "G=H; domain=www.google.izzle"));
    298   this->MatchCookieLines("A=B; C=D; E=F; G=H",
    299                          this->GetCookies(cs.get(), this->url_google_));
    300 
    301   // Test domain enforcement, should fail on a sub-domain or something too deep.
    302   EXPECT_FALSE(
    303       this->SetCookie(cs.get(), this->url_google_, "I=J; domain=.izzle"));
    304   this->MatchCookieLines(std::string(),
    305                          this->GetCookies(cs.get(), GURL("http://a.izzle")));
    306   EXPECT_FALSE(this->SetCookie(
    307       cs.get(), this->url_google_, "K=L; domain=.bla.www.google.izzle"));
    308   this->MatchCookieLines(
    309       "C=D; E=F; G=H",
    310       this->GetCookies(cs.get(), GURL("http://bla.www.google.izzle")));
    311   this->MatchCookieLines("A=B; C=D; E=F; G=H",
    312                          this->GetCookies(cs.get(), this->url_google_));
    313 }
    314 
    315 // FireFox recognizes domains containing trailing periods as valid.
    316 // IE and Safari do not. Assert the expected policy here.
    317 TYPED_TEST_P(CookieStoreTest, DomainWithTrailingDotTest) {
    318   scoped_refptr<CookieStore> cs(this->GetCookieStore());
    319   EXPECT_FALSE(this->SetCookie(
    320       cs.get(), this->url_google_, "a=1; domain=.www.google.com."));
    321   EXPECT_FALSE(this->SetCookie(
    322       cs.get(), this->url_google_, "b=2; domain=.www.google.com.."));
    323   this->MatchCookieLines(std::string(),
    324                          this->GetCookies(cs.get(), this->url_google_));
    325 }
    326 
    327 // Test that cookies can bet set on higher level domains.
    328 // http://b/issue?id=896491
    329 TYPED_TEST_P(CookieStoreTest, ValidSubdomainTest) {
    330   scoped_refptr<CookieStore> cs(this->GetCookieStore());
    331   GURL url_abcd("http://a.b.c.d.com");
    332   GURL url_bcd("http://b.c.d.com");
    333   GURL url_cd("http://c.d.com");
    334   GURL url_d("http://d.com");
    335 
    336   EXPECT_TRUE(this->SetCookie(cs.get(), url_abcd, "a=1; domain=.a.b.c.d.com"));
    337   EXPECT_TRUE(this->SetCookie(cs.get(), url_abcd, "b=2; domain=.b.c.d.com"));
    338   EXPECT_TRUE(this->SetCookie(cs.get(), url_abcd, "c=3; domain=.c.d.com"));
    339   EXPECT_TRUE(this->SetCookie(cs.get(), url_abcd, "d=4; domain=.d.com"));
    340 
    341   this->MatchCookieLines("a=1; b=2; c=3; d=4",
    342                          this->GetCookies(cs.get(), url_abcd));
    343   this->MatchCookieLines("b=2; c=3; d=4", this->GetCookies(cs.get(), url_bcd));
    344   this->MatchCookieLines("c=3; d=4", this->GetCookies(cs.get(), url_cd));
    345   this->MatchCookieLines("d=4", this->GetCookies(cs.get(), url_d));
    346 
    347   // Check that the same cookie can exist on different sub-domains.
    348   EXPECT_TRUE(this->SetCookie(cs.get(), url_bcd, "X=bcd; domain=.b.c.d.com"));
    349   EXPECT_TRUE(this->SetCookie(cs.get(), url_bcd, "X=cd; domain=.c.d.com"));
    350   this->MatchCookieLines("b=2; c=3; d=4; X=bcd; X=cd",
    351                          this->GetCookies(cs.get(), url_bcd));
    352   this->MatchCookieLines("c=3; d=4; X=cd", this->GetCookies(cs.get(), url_cd));
    353 }
    354 
    355 // Test that setting a cookie which specifies an invalid domain has
    356 // no side-effect. An invalid domain in this context is one which does
    357 // not match the originating domain.
    358 // http://b/issue?id=896472
    359 TYPED_TEST_P(CookieStoreTest, InvalidDomainTest) {
    360   {
    361     scoped_refptr<CookieStore> cs(this->GetCookieStore());
    362     GURL url_foobar("http://foo.bar.com");
    363 
    364     // More specific sub-domain than allowed.
    365     EXPECT_FALSE(
    366         this->SetCookie(cs.get(), url_foobar, "a=1; domain=.yo.foo.bar.com"));
    367 
    368     EXPECT_FALSE(this->SetCookie(cs.get(), url_foobar, "b=2; domain=.foo.com"));
    369     EXPECT_FALSE(
    370         this->SetCookie(cs.get(), url_foobar, "c=3; domain=.bar.foo.com"));
    371 
    372     // Different TLD, but the rest is a substring.
    373     EXPECT_FALSE(
    374         this->SetCookie(cs.get(), url_foobar, "d=4; domain=.foo.bar.com.net"));
    375 
    376     // A substring that isn't really a parent domain.
    377     EXPECT_FALSE(this->SetCookie(cs.get(), url_foobar, "e=5; domain=ar.com"));
    378 
    379     // Completely invalid domains:
    380     EXPECT_FALSE(this->SetCookie(cs.get(), url_foobar, "f=6; domain=."));
    381     EXPECT_FALSE(this->SetCookie(cs.get(), url_foobar, "g=7; domain=/"));
    382     EXPECT_FALSE(this->SetCookie(
    383         cs.get(), url_foobar, "h=8; domain=http://foo.bar.com"));
    384     EXPECT_FALSE(
    385         this->SetCookie(cs.get(), url_foobar, "i=9; domain=..foo.bar.com"));
    386     EXPECT_FALSE(
    387         this->SetCookie(cs.get(), url_foobar, "j=10; domain=..bar.com"));
    388 
    389     // Make sure there isn't something quirky in the domain canonicalization
    390     // that supports full URL semantics.
    391     EXPECT_FALSE(this->SetCookie(
    392         cs.get(), url_foobar, "k=11; domain=.foo.bar.com?blah"));
    393     EXPECT_FALSE(this->SetCookie(
    394         cs.get(), url_foobar, "l=12; domain=.foo.bar.com/blah"));
    395     EXPECT_FALSE(
    396         this->SetCookie(cs.get(), url_foobar, "m=13; domain=.foo.bar.com:80"));
    397     EXPECT_FALSE(
    398         this->SetCookie(cs.get(), url_foobar, "n=14; domain=.foo.bar.com:"));
    399     EXPECT_FALSE(
    400         this->SetCookie(cs.get(), url_foobar, "o=15; domain=.foo.bar.com#sup"));
    401 
    402     this->MatchCookieLines(std::string(),
    403                            this->GetCookies(cs.get(), url_foobar));
    404   }
    405 
    406   {
    407     // Make sure the cookie code hasn't gotten its subdomain string handling
    408     // reversed, missed a suffix check, etc.  It's important here that the two
    409     // hosts below have the same domain + registry.
    410     scoped_refptr<CookieStore> cs(this->GetCookieStore());
    411     GURL url_foocom("http://foo.com.com");
    412     EXPECT_FALSE(
    413         this->SetCookie(cs.get(), url_foocom, "a=1; domain=.foo.com.com.com"));
    414     this->MatchCookieLines(std::string(),
    415                            this->GetCookies(cs.get(), url_foocom));
    416   }
    417 }
    418 
    419 // Test the behavior of omitting dot prefix from domain, should
    420 // function the same as FireFox.
    421 // http://b/issue?id=889898
    422 TYPED_TEST_P(CookieStoreTest, DomainWithoutLeadingDotTest) {
    423   {  // The omission of dot results in setting a domain cookie.
    424     scoped_refptr<CookieStore> cs(this->GetCookieStore());
    425     GURL url_hosted("http://manage.hosted.filefront.com");
    426     GURL url_filefront("http://www.filefront.com");
    427     EXPECT_TRUE(
    428         this->SetCookie(cs.get(), url_hosted, "sawAd=1; domain=filefront.com"));
    429     this->MatchCookieLines("sawAd=1", this->GetCookies(cs.get(), url_hosted));
    430     this->MatchCookieLines("sawAd=1",
    431                            this->GetCookies(cs.get(), url_filefront));
    432   }
    433 
    434   {  // Even when the domains match exactly, don't consider it host cookie.
    435     scoped_refptr<CookieStore> cs(this->GetCookieStore());
    436     GURL url("http://www.google.com");
    437     EXPECT_TRUE(this->SetCookie(cs.get(), url, "a=1; domain=www.google.com"));
    438     this->MatchCookieLines("a=1", this->GetCookies(cs.get(), url));
    439     this->MatchCookieLines(
    440         "a=1", this->GetCookies(cs.get(), GURL("http://sub.www.google.com")));
    441     this->MatchCookieLines(
    442         std::string(),
    443         this->GetCookies(cs.get(), GURL("http://something-else.com")));
    444   }
    445 }
    446 
    447 // Test that the domain specified in cookie string is treated case-insensitive
    448 // http://b/issue?id=896475.
    449 TYPED_TEST_P(CookieStoreTest, CaseInsensitiveDomainTest) {
    450     scoped_refptr<CookieStore> cs(this->GetCookieStore());
    451   GURL url("http://www.google.com");
    452   EXPECT_TRUE(this->SetCookie(cs.get(), url, "a=1; domain=.GOOGLE.COM"));
    453   EXPECT_TRUE(this->SetCookie(cs.get(), url, "b=2; domain=.wWw.gOOgLE.coM"));
    454   this->MatchCookieLines("a=1; b=2", this->GetCookies(cs.get(), url));
    455 }
    456 
    457 TYPED_TEST_P(CookieStoreTest, TestIpAddress) {
    458   GURL url_ip("http://1.2.3.4/weee");
    459   {
    460     scoped_refptr<CookieStore> cs(this->GetCookieStore());
    461     EXPECT_TRUE(this->SetCookie(cs.get(), url_ip, kValidCookieLine));
    462     this->MatchCookieLines("A=B", this->GetCookies(cs.get(), url_ip));
    463   }
    464 
    465   {  // IP addresses should not be able to set domain cookies.
    466     scoped_refptr<CookieStore> cs(this->GetCookieStore());
    467     EXPECT_FALSE(this->SetCookie(cs.get(), url_ip, "b=2; domain=.1.2.3.4"));
    468     EXPECT_FALSE(this->SetCookie(cs.get(), url_ip, "c=3; domain=.3.4"));
    469     this->MatchCookieLines(std::string(), this->GetCookies(cs.get(), url_ip));
    470     // It should be allowed to set a cookie if domain= matches the IP address
    471     // exactly.  This matches IE/Firefox, even though it seems a bit wrong.
    472     EXPECT_FALSE(this->SetCookie(cs.get(), url_ip, "b=2; domain=1.2.3.3"));
    473     this->MatchCookieLines(std::string(), this->GetCookies(cs.get(), url_ip));
    474     EXPECT_TRUE(this->SetCookie(cs.get(), url_ip, "b=2; domain=1.2.3.4"));
    475     this->MatchCookieLines("b=2", this->GetCookies(cs.get(), url_ip));
    476   }
    477 }
    478 
    479 // Test host cookies, and setting of cookies on TLD.
    480 TYPED_TEST_P(CookieStoreTest, TestNonDottedAndTLD) {
    481   {
    482     scoped_refptr<CookieStore> cs(this->GetCookieStore());
    483     GURL url("http://com/");
    484     // Allow setting on "com", (but only as a host cookie).
    485     EXPECT_TRUE(this->SetCookie(cs.get(), url, "a=1"));
    486     EXPECT_FALSE(this->SetCookie(cs.get(), url, "b=2; domain=.com"));
    487     EXPECT_FALSE(this->SetCookie(cs.get(), url, "c=3; domain=com"));
    488     this->MatchCookieLines("a=1", this->GetCookies(cs.get(), url));
    489     // Make sure it doesn't show up for a normal .com, it should be a host
    490     // not a domain cookie.
    491     this->MatchCookieLines(
    492         std::string(),
    493         this->GetCookies(cs.get(), GURL("http://hopefully-no-cookies.com/")));
    494     if (TypeParam::supports_non_dotted_domains) {
    495       this->MatchCookieLines(std::string(),
    496                              this->GetCookies(cs.get(), GURL("http://.com/")));
    497     }
    498   }
    499 
    500   {
    501     // http://com. should be treated the same as http://com.
    502     scoped_refptr<CookieStore> cs(this->GetCookieStore());
    503     GURL url("http://com./index.html");
    504     if (TypeParam::supports_trailing_dots) {
    505       EXPECT_TRUE(this->SetCookie(cs.get(), url, "a=1"));
    506       this->MatchCookieLines("a=1", this->GetCookies(cs.get(), url));
    507       this->MatchCookieLines(
    508           std::string(),
    509           this->GetCookies(cs.get(),
    510                            GURL("http://hopefully-no-cookies.com./")));
    511     } else {
    512       EXPECT_FALSE(this->SetCookie(cs.get(), url, "a=1"));
    513     }
    514   }
    515 
    516   {  // Should not be able to set host cookie from a subdomain.
    517     scoped_refptr<CookieStore> cs(this->GetCookieStore());
    518     GURL url("http://a.b");
    519     EXPECT_FALSE(this->SetCookie(cs.get(), url, "a=1; domain=.b"));
    520     EXPECT_FALSE(this->SetCookie(cs.get(), url, "b=2; domain=b"));
    521     this->MatchCookieLines(std::string(), this->GetCookies(cs.get(), url));
    522   }
    523 
    524   {  // Same test as above, but explicitly on a known TLD (com).
    525     scoped_refptr<CookieStore> cs(this->GetCookieStore());
    526     GURL url("http://google.com");
    527     EXPECT_FALSE(this->SetCookie(cs.get(), url, "a=1; domain=.com"));
    528     EXPECT_FALSE(this->SetCookie(cs.get(), url, "b=2; domain=com"));
    529     this->MatchCookieLines(std::string(), this->GetCookies(cs.get(), url));
    530   }
    531 
    532   {  // Make sure can't set cookie on TLD which is dotted.
    533     scoped_refptr<CookieStore> cs(this->GetCookieStore());
    534     GURL url("http://google.co.uk");
    535     EXPECT_FALSE(this->SetCookie(cs.get(), url, "a=1; domain=.co.uk"));
    536     EXPECT_FALSE(this->SetCookie(cs.get(), url, "b=2; domain=.uk"));
    537     this->MatchCookieLines(std::string(), this->GetCookies(cs.get(), url));
    538     this->MatchCookieLines(
    539         std::string(),
    540         this->GetCookies(cs.get(), GURL("http://something-else.co.uk")));
    541     this->MatchCookieLines(
    542         std::string(),
    543         this->GetCookies(cs.get(), GURL("http://something-else.uk")));
    544   }
    545 
    546   {  // Intranet URLs should only be able to set host cookies.
    547     scoped_refptr<CookieStore> cs(this->GetCookieStore());
    548     GURL url("http://b");
    549     EXPECT_TRUE(this->SetCookie(cs.get(), url, "a=1"));
    550     EXPECT_FALSE(this->SetCookie(cs.get(), url, "b=2; domain=.b"));
    551     EXPECT_FALSE(this->SetCookie(cs.get(), url, "c=3; domain=b"));
    552     this->MatchCookieLines("a=1", this->GetCookies(cs.get(), url));
    553   }
    554 }
    555 
    556 // Test reading/writing cookies when the domain ends with a period,
    557 // as in "www.google.com."
    558 TYPED_TEST_P(CookieStoreTest, TestHostEndsWithDot) {
    559   scoped_refptr<CookieStore> cs(this->GetCookieStore());
    560   GURL url("http://www.google.com");
    561   GURL url_with_dot("http://www.google.com.");
    562   EXPECT_TRUE(this->SetCookie(cs.get(), url, "a=1"));
    563   this->MatchCookieLines("a=1", this->GetCookies(cs.get(), url));
    564 
    565   if (TypeParam::supports_trailing_dots) {
    566     // Do not share cookie space with the dot version of domain.
    567     // Note: this is not what FireFox does, but it _is_ what IE+Safari do.
    568     EXPECT_FALSE(
    569         this->SetCookie(cs.get(), url, "b=2; domain=.www.google.com."));
    570     this->MatchCookieLines("a=1", this->GetCookies(cs.get(), url));
    571 
    572     EXPECT_TRUE(
    573         this->SetCookie(cs.get(), url_with_dot, "b=2; domain=.google.com."));
    574     this->MatchCookieLines("b=2", this->GetCookies(cs.get(), url_with_dot));
    575   } else {
    576     EXPECT_TRUE(this->SetCookie(cs.get(), url, "b=2; domain=.www.google.com."));
    577     EXPECT_FALSE(
    578         this->SetCookie(cs.get(), url_with_dot, "b=2; domain=.google.com."));
    579   }
    580 
    581   // Make sure there weren't any side effects.
    582   this->MatchCookieLines(
    583       std::string(),
    584       this->GetCookies(cs.get(), GURL("http://hopefully-no-cookies.com/")));
    585   this->MatchCookieLines(std::string(),
    586                          this->GetCookies(cs.get(), GURL("http://.com/")));
    587 }
    588 
    589 TYPED_TEST_P(CookieStoreTest, InvalidScheme) {
    590   if (!TypeParam::filters_schemes)
    591     return;
    592 
    593   scoped_refptr<CookieStore> cs(this->GetCookieStore());
    594   EXPECT_FALSE(this->SetCookie(cs.get(), GURL(kUrlFtp), kValidCookieLine));
    595 }
    596 
    597 TYPED_TEST_P(CookieStoreTest, InvalidScheme_Read) {
    598   if (!TypeParam::filters_schemes)
    599     return;
    600 
    601   scoped_refptr<CookieStore> cs(this->GetCookieStore());
    602   EXPECT_TRUE(
    603       this->SetCookie(cs.get(), GURL(kUrlGoogle), kValidDomainCookieLine));
    604   this->MatchCookieLines(std::string(),
    605                          this->GetCookies(cs.get(), GURL(kUrlFtp)));
    606 }
    607 
    608 TYPED_TEST_P(CookieStoreTest, PathTest) {
    609   scoped_refptr<CookieStore> cs(this->GetCookieStore());
    610   std::string url("http://www.google.izzle");
    611   EXPECT_TRUE(this->SetCookie(cs.get(), GURL(url), "A=B; path=/wee"));
    612   this->MatchCookieLines("A=B", this->GetCookies(cs.get(), GURL(url + "/wee")));
    613   this->MatchCookieLines("A=B",
    614                          this->GetCookies(cs.get(), GURL(url + "/wee/")));
    615   this->MatchCookieLines("A=B",
    616                          this->GetCookies(cs.get(), GURL(url + "/wee/war")));
    617   this->MatchCookieLines(
    618       "A=B", this->GetCookies(cs.get(), GURL(url + "/wee/war/more/more")));
    619   if (!TypeParam::has_path_prefix_bug)
    620     this->MatchCookieLines(std::string(),
    621                            this->GetCookies(cs.get(), GURL(url + "/weehee")));
    622   this->MatchCookieLines(std::string(),
    623                          this->GetCookies(cs.get(), GURL(url + "/")));
    624 
    625   // If we add a 0 length path, it should default to /
    626   EXPECT_TRUE(this->SetCookie(cs.get(), GURL(url), "A=C; path="));
    627   this->MatchCookieLines("A=B; A=C",
    628                          this->GetCookies(cs.get(), GURL(url + "/wee")));
    629   this->MatchCookieLines("A=C", this->GetCookies(cs.get(), GURL(url + "/")));
    630 }
    631 
    632 TYPED_TEST_P(CookieStoreTest, EmptyExpires) {
    633   scoped_refptr<CookieStore> cs(this->GetCookieStore());
    634   CookieOptions options;
    635   if (!TypeParam::supports_http_only)
    636     options.set_include_httponly();
    637   GURL url("http://www7.ipdl.inpit.go.jp/Tokujitu/tjkta.ipdl?N0000=108");
    638   std::string set_cookie_line =
    639       "ACSTM=20130308043820420042; path=/; domain=ipdl.inpit.go.jp; Expires=";
    640   std::string cookie_line = "ACSTM=20130308043820420042";
    641 
    642   this->SetCookieWithOptions(cs.get(), url, set_cookie_line, options);
    643   this->MatchCookieLines(cookie_line,
    644                          this->GetCookiesWithOptions(cs.get(), url, options));
    645 
    646   options.set_server_time(base::Time::Now() - base::TimeDelta::FromHours(1));
    647   this->SetCookieWithOptions(cs.get(), url, set_cookie_line, options);
    648   this->MatchCookieLines(cookie_line,
    649                          this->GetCookiesWithOptions(cs.get(), url, options));
    650 
    651   options.set_server_time(base::Time::Now() + base::TimeDelta::FromHours(1));
    652   this->SetCookieWithOptions(cs.get(), url, set_cookie_line, options);
    653   this->MatchCookieLines(cookie_line,
    654                          this->GetCookiesWithOptions(cs.get(), url, options));
    655 }
    656 
    657 TYPED_TEST_P(CookieStoreTest, HttpOnlyTest) {
    658   if (!TypeParam::supports_http_only)
    659     return;
    660 
    661   scoped_refptr<CookieStore> cs(this->GetCookieStore());
    662   CookieOptions options;
    663   options.set_include_httponly();
    664 
    665   // Create a httponly cookie.
    666   EXPECT_TRUE(this->SetCookieWithOptions(
    667       cs.get(), this->url_google_, "A=B; httponly", options));
    668 
    669   // Check httponly read protection.
    670   this->MatchCookieLines(std::string(),
    671                          this->GetCookies(cs.get(), this->url_google_));
    672   this->MatchCookieLines(
    673       "A=B", this->GetCookiesWithOptions(cs.get(), this->url_google_, options));
    674 
    675   // Check httponly overwrite protection.
    676   EXPECT_FALSE(this->SetCookie(cs.get(), this->url_google_, "A=C"));
    677   this->MatchCookieLines(std::string(),
    678                          this->GetCookies(cs.get(), this->url_google_));
    679   this->MatchCookieLines(
    680       "A=B", this->GetCookiesWithOptions(cs.get(), this->url_google_, options));
    681   EXPECT_TRUE(
    682       this->SetCookieWithOptions(cs.get(), this->url_google_, "A=C", options));
    683   this->MatchCookieLines("A=C", this->GetCookies(cs.get(), this->url_google_));
    684 
    685   // Check httponly create protection.
    686   EXPECT_FALSE(this->SetCookie(cs.get(), this->url_google_, "B=A; httponly"));
    687   this->MatchCookieLines(
    688       "A=C", this->GetCookiesWithOptions(cs.get(), this->url_google_, options));
    689   EXPECT_TRUE(this->SetCookieWithOptions(
    690       cs.get(), this->url_google_, "B=A; httponly", options));
    691   this->MatchCookieLines(
    692       "A=C; B=A",
    693       this->GetCookiesWithOptions(cs.get(), this->url_google_, options));
    694   this->MatchCookieLines("A=C", this->GetCookies(cs.get(), this->url_google_));
    695 }
    696 
    697 TYPED_TEST_P(CookieStoreTest, TestCookieDeletion) {
    698   scoped_refptr<CookieStore> cs(this->GetCookieStore());
    699 
    700   // Create a session cookie.
    701   EXPECT_TRUE(this->SetCookie(cs.get(), this->url_google_, kValidCookieLine));
    702   this->MatchCookieLines("A=B", this->GetCookies(cs.get(), this->url_google_));
    703   // Delete it via Max-Age.
    704   EXPECT_TRUE(this->SetCookie(cs.get(),
    705                               this->url_google_,
    706                               std::string(kValidCookieLine) + "; max-age=0"));
    707   this->MatchCookieLineWithTimeout(cs.get(), this->url_google_, std::string());
    708 
    709   // Create a session cookie.
    710   EXPECT_TRUE(this->SetCookie(cs.get(), this->url_google_, kValidCookieLine));
    711   this->MatchCookieLines("A=B", this->GetCookies(cs.get(), this->url_google_));
    712   // Delete it via Expires.
    713   EXPECT_TRUE(this->SetCookie(cs.get(),
    714                               this->url_google_,
    715                               std::string(kValidCookieLine) +
    716                                   "; expires=Mon, 18-Apr-1977 22:50:13 GMT"));
    717   this->MatchCookieLines(std::string(),
    718                          this->GetCookies(cs.get(), this->url_google_));
    719 
    720   // Create a persistent cookie.
    721   EXPECT_TRUE(this->SetCookie(
    722       cs.get(),
    723       this->url_google_,
    724       std::string(kValidCookieLine) + "; expires=Mon, 18-Apr-22 22:50:13 GMT"));
    725 
    726   this->MatchCookieLines("A=B", this->GetCookies(cs.get(), this->url_google_));
    727   // Delete it via Max-Age.
    728   EXPECT_TRUE(this->SetCookie(cs.get(),
    729                               this->url_google_,
    730                               std::string(kValidCookieLine) + "; max-age=0"));
    731   this->MatchCookieLineWithTimeout(cs.get(), this->url_google_, std::string());
    732 
    733   // Create a persistent cookie.
    734   EXPECT_TRUE(this->SetCookie(
    735       cs.get(),
    736       this->url_google_,
    737       std::string(kValidCookieLine) + "; expires=Mon, 18-Apr-22 22:50:13 GMT"));
    738   this->MatchCookieLines("A=B", this->GetCookies(cs.get(), this->url_google_));
    739   // Delete it via Expires.
    740   EXPECT_TRUE(this->SetCookie(cs.get(),
    741                               this->url_google_,
    742                               std::string(kValidCookieLine) +
    743                                   "; expires=Mon, 18-Apr-1977 22:50:13 GMT"));
    744   this->MatchCookieLines(std::string(),
    745                          this->GetCookies(cs.get(), this->url_google_));
    746 
    747   // Create a persistent cookie.
    748   EXPECT_TRUE(this->SetCookie(
    749       cs.get(),
    750       this->url_google_,
    751       std::string(kValidCookieLine) + "; expires=Mon, 18-Apr-22 22:50:13 GMT"));
    752   this->MatchCookieLines("A=B", this->GetCookies(cs.get(), this->url_google_));
    753   // Check that it is not deleted with significant enough clock skew.
    754   base::Time server_time;
    755   EXPECT_TRUE(base::Time::FromString("Sun, 17-Apr-1977 22:50:13 GMT",
    756                                      &server_time));
    757   EXPECT_TRUE(this->SetCookieWithServerTime(
    758       cs.get(),
    759       this->url_google_,
    760       std::string(kValidCookieLine) + "; expires=Mon, 18-Apr-1977 22:50:13 GMT",
    761       server_time));
    762   this->MatchCookieLines("A=B", this->GetCookies(cs.get(), this->url_google_));
    763 
    764   // Create a persistent cookie.
    765   EXPECT_TRUE(this->SetCookie(
    766       cs.get(),
    767       this->url_google_,
    768       std::string(kValidCookieLine) + "; expires=Mon, 18-Apr-22 22:50:13 GMT"));
    769   this->MatchCookieLines("A=B", this->GetCookies(cs.get(), this->url_google_));
    770   // Delete it via Expires, with a unix epoch of 0.
    771   EXPECT_TRUE(this->SetCookie(cs.get(),
    772                               this->url_google_,
    773                               std::string(kValidCookieLine) +
    774                                   "; expires=Thu, 1-Jan-1970 00:00:00 GMT"));
    775   this->MatchCookieLines(std::string(),
    776                          this->GetCookies(cs.get(), this->url_google_));
    777 }
    778 
    779 TYPED_TEST_P(CookieStoreTest, TestDeleteAllCreatedBetween) {
    780   scoped_refptr<CookieStore> cs(this->GetCookieStore());
    781   const base::Time last_month = base::Time::Now() -
    782                                 base::TimeDelta::FromDays(30);
    783   const base::Time last_minute = base::Time::Now() -
    784                                  base::TimeDelta::FromMinutes(1);
    785   const base::Time next_minute = base::Time::Now() +
    786                                  base::TimeDelta::FromMinutes(1);
    787   const base::Time next_month = base::Time::Now() +
    788                                 base::TimeDelta::FromDays(30);
    789 
    790   // Add a cookie.
    791   EXPECT_TRUE(this->SetCookie(cs.get(), this->url_google_, "A=B"));
    792   // Check that the cookie is in the store.
    793   this->MatchCookieLines("A=B", this->GetCookies(cs.get(), this->url_google_));
    794 
    795   // Remove cookies in empty intervals.
    796   EXPECT_EQ(0, this->DeleteCreatedBetween(cs.get(), last_month, last_minute));
    797   EXPECT_EQ(0, this->DeleteCreatedBetween(cs.get(), next_minute, next_month));
    798   // Check that the cookie is still there.
    799   this->MatchCookieLines("A=B", this->GetCookies(cs.get(), this->url_google_));
    800 
    801   // Remove the cookie with an interval defined by two dates.
    802   EXPECT_EQ(1, this->DeleteCreatedBetween(cs.get(), last_minute, next_minute));
    803   // Check that the cookie disappeared.
    804   this->MatchCookieLines(std::string(),
    805                          this->GetCookies(cs.get(), this->url_google_));
    806 
    807   // Add another cookie.
    808   EXPECT_TRUE(this->SetCookie(cs.get(), this->url_google_, "C=D"));
    809   // Check that the cookie is in the store.
    810   this->MatchCookieLines("C=D", this->GetCookies(cs.get(), this->url_google_));
    811 
    812   // Remove the cookie with a null ending time.
    813   EXPECT_EQ(1, this->DeleteCreatedBetween(cs.get(), last_minute, base::Time()));
    814   // Check that the cookie disappeared.
    815   this->MatchCookieLines(std::string(),
    816                          this->GetCookies(cs.get(), this->url_google_));
    817 }
    818 
    819 TYPED_TEST_P(CookieStoreTest, TestDeleteAllCreatedBetweenForHost) {
    820   scoped_refptr<CookieStore> cs(this->GetCookieStore());
    821   GURL url_not_google("http://www.notgoogle.com");
    822   base::Time now = base::Time::Now();
    823 
    824   // These 3 cookies match the time range and host.
    825   EXPECT_TRUE(this->SetCookie(cs.get(), this->url_google_, "A=B"));
    826   EXPECT_TRUE(this->SetCookie(cs.get(), this->url_google_, "C=D"));
    827   EXPECT_TRUE(this->SetCookie(cs.get(), this->url_google_, "Y=Z"));
    828 
    829   // This cookie does not match host.
    830   EXPECT_TRUE(this->SetCookie(cs.get(), url_not_google, "E=F"));
    831 
    832   // Delete cookies.
    833   EXPECT_EQ(
    834       3,  // Deletes A=B, C=D, Y=Z
    835       this->DeleteAllCreatedBetweenForHost(
    836           cs.get(), now, base::Time::Max(), this->url_google_));
    837 }
    838 
    839 TYPED_TEST_P(CookieStoreTest, TestSecure) {
    840     scoped_refptr<CookieStore> cs(this->GetCookieStore());
    841 
    842     EXPECT_TRUE(this->SetCookie(cs.get(), this->url_google_, "A=B"));
    843     this->MatchCookieLines("A=B",
    844                            this->GetCookies(cs.get(), this->url_google_));
    845     this->MatchCookieLines(
    846         "A=B", this->GetCookies(cs.get(), this->url_google_secure_));
    847 
    848   EXPECT_TRUE(
    849       this->SetCookie(cs.get(), this->url_google_secure_, "A=B; secure"));
    850   // The secure should overwrite the non-secure.
    851   this->MatchCookieLines(std::string(),
    852                          this->GetCookies(cs.get(), this->url_google_));
    853   this->MatchCookieLines("A=B",
    854                          this->GetCookies(cs.get(), this->url_google_secure_));
    855 
    856   EXPECT_TRUE(
    857       this->SetCookie(cs.get(), this->url_google_secure_, "D=E; secure"));
    858   this->MatchCookieLines(std::string(),
    859                          this->GetCookies(cs.get(), this->url_google_));
    860   this->MatchCookieLines("A=B; D=E",
    861                          this->GetCookies(cs.get(), this->url_google_secure_));
    862 
    863   EXPECT_TRUE(this->SetCookie(cs.get(), this->url_google_secure_, "A=B"));
    864   // The non-secure should overwrite the secure.
    865   this->MatchCookieLines("A=B", this->GetCookies(cs.get(), this->url_google_));
    866   this->MatchCookieLines("D=E; A=B",
    867                          this->GetCookies(cs.get(), this->url_google_secure_));
    868 }
    869 
    870 static const int kLastAccessThresholdMilliseconds = 200;
    871 
    872 // Formerly NetUtilTest.CookieTest back when we used wininet's cookie handling.
    873 TYPED_TEST_P(CookieStoreTest, NetUtilCookieTest) {
    874   const GURL test_url("http://mojo.jojo.google.izzle/");
    875 
    876   scoped_refptr<CookieStore> cs(this->GetCookieStore());
    877 
    878   EXPECT_TRUE(this->SetCookie(cs.get(), test_url, "foo=bar"));
    879   std::string value = this->GetCookies(cs.get(), test_url);
    880   this->MatchCookieLines("foo=bar", value);
    881 
    882   // test that we can retrieve all cookies:
    883   EXPECT_TRUE(this->SetCookie(cs.get(), test_url, "x=1"));
    884   EXPECT_TRUE(this->SetCookie(cs.get(), test_url, "y=2"));
    885 
    886   std::string result = this->GetCookies(cs.get(), test_url);
    887   EXPECT_FALSE(result.empty());
    888   EXPECT_NE(result.find("x=1"), std::string::npos) << result;
    889   EXPECT_NE(result.find("y=2"), std::string::npos) << result;
    890 }
    891 
    892 TYPED_TEST_P(CookieStoreTest, OverwritePersistentCookie) {
    893   GURL url_google("http://www.google.com/");
    894   GURL url_chromium("http://chromium.org");
    895   scoped_refptr<CookieStore> cs(this->GetCookieStore());
    896 
    897   // Insert a cookie "a" for path "/path1"
    898   EXPECT_TRUE(this->SetCookie(cs.get(),
    899                               url_google,
    900                               "a=val1; path=/path1; "
    901                               "expires=Mon, 18-Apr-22 22:50:13 GMT"));
    902 
    903   // Insert a cookie "b" for path "/path1"
    904   EXPECT_TRUE(this->SetCookie(cs.get(),
    905                               url_google,
    906                               "b=val1; path=/path1; "
    907                               "expires=Mon, 18-Apr-22 22:50:14 GMT"));
    908 
    909   // Insert a cookie "b" for path "/path1", that is httponly. This should
    910   // overwrite the non-http-only version.
    911   CookieOptions allow_httponly;
    912   allow_httponly.set_include_httponly();
    913   EXPECT_TRUE(this->SetCookieWithOptions(cs.get(),
    914                                          url_google,
    915                                          "b=val2; path=/path1; httponly; "
    916                                          "expires=Mon, 18-Apr-22 22:50:14 GMT",
    917                                          allow_httponly));
    918 
    919   // Insert a cookie "a" for path "/path1". This should overwrite.
    920   EXPECT_TRUE(this->SetCookie(cs.get(),
    921                               url_google,
    922                               "a=val33; path=/path1; "
    923                               "expires=Mon, 18-Apr-22 22:50:14 GMT"));
    924 
    925   // Insert a cookie "a" for path "/path2". This should NOT overwrite
    926   // cookie "a", since the path is different.
    927   EXPECT_TRUE(this->SetCookie(cs.get(),
    928                               url_google,
    929                               "a=val9; path=/path2; "
    930                               "expires=Mon, 18-Apr-22 22:50:14 GMT"));
    931 
    932   // Insert a cookie "a" for path "/path1", but this time for "chromium.org".
    933   // Although the name and path match, the hostnames do not, so shouldn't
    934   // overwrite.
    935   EXPECT_TRUE(this->SetCookie(cs.get(),
    936                               url_chromium,
    937                               "a=val99; path=/path1; "
    938                               "expires=Mon, 18-Apr-22 22:50:14 GMT"));
    939 
    940   if (TypeParam::supports_http_only) {
    941     this->MatchCookieLines(
    942         "a=val33",
    943         this->GetCookies(cs.get(), GURL("http://www.google.com/path1")));
    944   } else {
    945     this->MatchCookieLines(
    946         "a=val33; b=val2",
    947         this->GetCookies(cs.get(), GURL("http://www.google.com/path1")));
    948   }
    949   this->MatchCookieLines(
    950       "a=val9",
    951       this->GetCookies(cs.get(), GURL("http://www.google.com/path2")));
    952   this->MatchCookieLines(
    953       "a=val99", this->GetCookies(cs.get(), GURL("http://chromium.org/path1")));
    954 }
    955 
    956 TYPED_TEST_P(CookieStoreTest, CookieOrdering) {
    957   // Put a random set of cookies into a store and make sure they're returned in
    958   // the right order.
    959   // Cookies should be sorted by path length and creation time, as per RFC6265.
    960   scoped_refptr<CookieStore> cs(this->GetCookieStore());
    961   EXPECT_TRUE(this->SetCookie(
    962       cs.get(), GURL("http://d.c.b.a.google.com/aa/x.html"), "c=1"));
    963   EXPECT_TRUE(this->SetCookie(cs.get(),
    964                               GURL("http://b.a.google.com/aa/bb/cc/x.html"),
    965                               "d=1; domain=b.a.google.com"));
    966   base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(
    967       TypeParam::creation_time_granularity_in_ms));
    968   EXPECT_TRUE(this->SetCookie(cs.get(),
    969                               GURL("http://b.a.google.com/aa/bb/cc/x.html"),
    970                               "a=4; domain=b.a.google.com"));
    971   base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(
    972       TypeParam::creation_time_granularity_in_ms));
    973   EXPECT_TRUE(this->SetCookie(cs.get(),
    974                               GURL("http://c.b.a.google.com/aa/bb/cc/x.html"),
    975                               "e=1; domain=c.b.a.google.com"));
    976   EXPECT_TRUE(this->SetCookie(
    977       cs.get(), GURL("http://d.c.b.a.google.com/aa/bb/x.html"), "b=1"));
    978   EXPECT_TRUE(this->SetCookie(
    979       cs.get(), GURL("http://news.bbc.co.uk/midpath/x.html"), "g=10"));
    980   EXPECT_EQ("d=1; a=4; e=1; b=1; c=1",
    981             this->GetCookies(cs.get(),
    982                              GURL("http://d.c.b.a.google.com/aa/bb/cc/dd")));
    983 }
    984 
    985 TYPED_TEST_P(CookieStoreTest, DeleteSessionCookie) {
    986   scoped_refptr<CookieStore> cs(this->GetCookieStore());
    987   // Create a session cookie and a persistent cookie.
    988   EXPECT_TRUE(this->SetCookie(
    989       cs.get(), this->url_google_, std::string(kValidCookieLine)));
    990   EXPECT_TRUE(this->SetCookie(cs.get(),
    991                               this->url_google_,
    992                               "C=D; path=/; domain=google.izzle;"
    993                               "expires=Mon, 18-Apr-22 22:50:13 GMT"));
    994   this->MatchCookieLines("A=B; C=D",
    995                          this->GetCookies(cs.get(), this->url_google_));
    996   // Delete the session cookie.
    997   this->DeleteSessionCookies(cs.get());
    998   // Check that the session cookie has been deleted but not the persistent one.
    999   EXPECT_EQ("C=D", this->GetCookies(cs.get(), this->url_google_));
   1000 }
   1001 
   1002 REGISTER_TYPED_TEST_CASE_P(CookieStoreTest,
   1003                            TypeTest,
   1004                            DomainTest,
   1005                            DomainWithTrailingDotTest,
   1006                            ValidSubdomainTest,
   1007                            InvalidDomainTest,
   1008                            DomainWithoutLeadingDotTest,
   1009                            CaseInsensitiveDomainTest,
   1010                            TestIpAddress,
   1011                            TestNonDottedAndTLD,
   1012                            TestHostEndsWithDot,
   1013                            InvalidScheme,
   1014                            InvalidScheme_Read,
   1015                            PathTest,
   1016                            EmptyExpires,
   1017                            HttpOnlyTest,
   1018                            TestCookieDeletion,
   1019                            TestDeleteAllCreatedBetween,
   1020                            TestDeleteAllCreatedBetweenForHost,
   1021                            TestSecure,
   1022                            NetUtilCookieTest,
   1023                            OverwritePersistentCookie,
   1024                            CookieOrdering,
   1025                            DeleteSessionCookie);
   1026 
   1027 template<class CookieStoreTestTraits>
   1028 class MultiThreadedCookieStoreTest :
   1029     public CookieStoreTest<CookieStoreTestTraits> {
   1030  public:
   1031   MultiThreadedCookieStoreTest() : other_thread_("CMTthread") {}
   1032 
   1033   // Helper methods for calling the asynchronous CookieStore methods
   1034   // from a different thread.
   1035 
   1036   void GetCookiesTask(CookieStore* cs,
   1037                       const GURL& url,
   1038                       StringResultCookieCallback* callback) {
   1039     CookieOptions options;
   1040     if (!CookieStoreTestTraits::supports_http_only)
   1041       options.set_include_httponly();
   1042     cs->GetCookiesWithOptionsAsync(
   1043         url, options,
   1044         base::Bind(&StringResultCookieCallback::Run,
   1045                    base::Unretained(callback)));
   1046   }
   1047 
   1048   void GetCookiesWithOptionsTask(CookieStore* cs,
   1049                                  const GURL& url,
   1050                                  const CookieOptions& options,
   1051                                  StringResultCookieCallback* callback) {
   1052     cs->GetCookiesWithOptionsAsync(
   1053         url, options,
   1054         base::Bind(&StringResultCookieCallback::Run,
   1055                    base::Unretained(callback)));
   1056   }
   1057 
   1058   void SetCookieWithOptionsTask(CookieStore* cs,
   1059                                 const GURL& url,
   1060                                 const std::string& cookie_line,
   1061                                 const CookieOptions& options,
   1062                                 ResultSavingCookieCallback<bool>* callback) {
   1063     cs->SetCookieWithOptionsAsync(
   1064         url, cookie_line, options,
   1065         base::Bind(
   1066             &ResultSavingCookieCallback<bool>::Run,
   1067             base::Unretained(callback)));
   1068   }
   1069 
   1070   void DeleteCookieTask(CookieStore* cs,
   1071                         const GURL& url,
   1072                         const std::string& cookie_name,
   1073                         NoResultCookieCallback* callback) {
   1074     cs->DeleteCookieAsync(
   1075         url, cookie_name,
   1076         base::Bind(&NoResultCookieCallback::Run, base::Unretained(callback)));
   1077   }
   1078 
   1079     void DeleteSessionCookiesTask(CookieStore* cs,
   1080                                   ResultSavingCookieCallback<int>* callback) {
   1081     cs->DeleteSessionCookiesAsync(
   1082         base::Bind(
   1083             &ResultSavingCookieCallback<int>::Run,
   1084             base::Unretained(callback)));
   1085   }
   1086 
   1087  protected:
   1088   void RunOnOtherThread(const base::Closure& task) {
   1089     other_thread_.Start();
   1090     other_thread_.message_loop()->PostTask(FROM_HERE, task);
   1091     CookieStoreTest<CookieStoreTestTraits>::RunFor(kTimeout);
   1092     other_thread_.Stop();
   1093   }
   1094 
   1095   Thread other_thread_;
   1096 };
   1097 
   1098 TYPED_TEST_CASE_P(MultiThreadedCookieStoreTest);
   1099 
   1100 // TODO(ycxiao): Eventually, we will need to create a separate thread, create
   1101 // the cookie store on that thread (or at least its store, i.e., the DB
   1102 // thread).
   1103 TYPED_TEST_P(MultiThreadedCookieStoreTest, ThreadCheckGetCookies) {
   1104   scoped_refptr<CookieStore> cs(this->GetCookieStore());
   1105   EXPECT_TRUE(this->SetCookie(cs.get(), this->url_google_, "A=B"));
   1106   this->MatchCookieLines("A=B", this->GetCookies(cs.get(), this->url_google_));
   1107   StringResultCookieCallback callback(&this->other_thread_);
   1108   base::Closure task = base::Bind(
   1109       &net::MultiThreadedCookieStoreTest<TypeParam>::GetCookiesTask,
   1110       base::Unretained(this),
   1111       cs, this->url_google_, &callback);
   1112   this->RunOnOtherThread(task);
   1113   EXPECT_TRUE(callback.did_run());
   1114   EXPECT_EQ("A=B", callback.result());
   1115 }
   1116 
   1117 TYPED_TEST_P(MultiThreadedCookieStoreTest, ThreadCheckGetCookiesWithOptions) {
   1118   scoped_refptr<CookieStore> cs(this->GetCookieStore());
   1119   CookieOptions options;
   1120   if (!TypeParam::supports_http_only)
   1121     options.set_include_httponly();
   1122   EXPECT_TRUE(this->SetCookie(cs.get(), this->url_google_, "A=B"));
   1123   this->MatchCookieLines(
   1124       "A=B", this->GetCookiesWithOptions(cs.get(), this->url_google_, options));
   1125   StringResultCookieCallback callback(&this->other_thread_);
   1126   base::Closure task = base::Bind(
   1127       &net::MultiThreadedCookieStoreTest<TypeParam>::GetCookiesWithOptionsTask,
   1128       base::Unretained(this),
   1129       cs, this->url_google_, options, &callback);
   1130   this->RunOnOtherThread(task);
   1131   EXPECT_TRUE(callback.did_run());
   1132   EXPECT_EQ("A=B", callback.result());
   1133 }
   1134 
   1135 TYPED_TEST_P(MultiThreadedCookieStoreTest, ThreadCheckSetCookieWithOptions) {
   1136   scoped_refptr<CookieStore> cs(this->GetCookieStore());
   1137   CookieOptions options;
   1138   if (!TypeParam::supports_http_only)
   1139     options.set_include_httponly();
   1140   EXPECT_TRUE(
   1141       this->SetCookieWithOptions(cs.get(), this->url_google_, "A=B", options));
   1142   ResultSavingCookieCallback<bool> callback(&this->other_thread_);
   1143   base::Closure task = base::Bind(
   1144       &net::MultiThreadedCookieStoreTest<TypeParam>::SetCookieWithOptionsTask,
   1145       base::Unretained(this),
   1146       cs, this->url_google_, "A=B", options, &callback);
   1147   this->RunOnOtherThread(task);
   1148   EXPECT_TRUE(callback.did_run());
   1149   EXPECT_TRUE(callback.result());
   1150 }
   1151 
   1152 TYPED_TEST_P(MultiThreadedCookieStoreTest, ThreadCheckDeleteCookie) {
   1153   scoped_refptr<CookieStore> cs(this->GetCookieStore());
   1154   CookieOptions options;
   1155   if (!TypeParam::supports_http_only)
   1156     options.set_include_httponly();
   1157   EXPECT_TRUE(
   1158       this->SetCookieWithOptions(cs.get(), this->url_google_, "A=B", options));
   1159   this->DeleteCookie(cs.get(), this->url_google_, "A");
   1160   EXPECT_TRUE(
   1161       this->SetCookieWithOptions(cs.get(), this->url_google_, "A=B", options));
   1162   NoResultCookieCallback callback(&this->other_thread_);
   1163   base::Closure task = base::Bind(
   1164       &net::MultiThreadedCookieStoreTest<TypeParam>::DeleteCookieTask,
   1165       base::Unretained(this),
   1166       cs, this->url_google_, "A", &callback);
   1167   this->RunOnOtherThread(task);
   1168   EXPECT_TRUE(callback.did_run());
   1169 }
   1170 
   1171 TYPED_TEST_P(MultiThreadedCookieStoreTest, ThreadCheckDeleteSessionCookies) {
   1172   scoped_refptr<CookieStore> cs(this->GetCookieStore());
   1173   CookieOptions options;
   1174   if (!TypeParam::supports_http_only)
   1175     options.set_include_httponly();
   1176   EXPECT_TRUE(
   1177       this->SetCookieWithOptions(cs.get(), this->url_google_, "A=B", options));
   1178   EXPECT_TRUE(
   1179       this->SetCookieWithOptions(cs.get(),
   1180                                  this->url_google_,
   1181                                  "B=C; expires=Mon, 18-Apr-22 22:50:13 GMT",
   1182                                  options));
   1183   EXPECT_EQ(1, this->DeleteSessionCookies(cs.get()));
   1184   EXPECT_EQ(0, this->DeleteSessionCookies(cs.get()));
   1185   EXPECT_TRUE(
   1186       this->SetCookieWithOptions(cs.get(), this->url_google_, "A=B", options));
   1187   ResultSavingCookieCallback<int> callback(&this->other_thread_);
   1188   base::Closure task = base::Bind(
   1189       &net::MultiThreadedCookieStoreTest<TypeParam>::DeleteSessionCookiesTask,
   1190       base::Unretained(this),
   1191       cs, &callback);
   1192   this->RunOnOtherThread(task);
   1193   EXPECT_TRUE(callback.did_run());
   1194   EXPECT_EQ(1, callback.result());
   1195 }
   1196 
   1197 REGISTER_TYPED_TEST_CASE_P(MultiThreadedCookieStoreTest,
   1198                            ThreadCheckGetCookies,
   1199                            ThreadCheckGetCookiesWithOptions,
   1200                            ThreadCheckSetCookieWithOptions,
   1201                            ThreadCheckDeleteCookie,
   1202                            ThreadCheckDeleteSessionCookies);
   1203 
   1204 }  // namespace net
   1205 
   1206 #endif  // NET_COOKIES_COOKIE_STORE_UNITTEST_H_
   1207