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