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