Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / net / cookies / cookie_store_unittest.h
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_