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