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