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