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 #include "chrome/browser/browsing_data/browsing_data_cookie_helper.h" 6 7 #include "base/bind.h" 8 #include "base/run_loop.h" 9 #include "chrome/test/base/testing_profile.h" 10 #include "content/public/test/test_browser_thread_bundle.h" 11 #include "net/cookies/canonical_cookie.h" 12 #include "net/cookies/parsed_cookie.h" 13 #include "net/url_request/url_request_context_getter.h" 14 #include "testing/gtest/include/gtest/gtest.h" 15 16 namespace { 17 18 class BrowsingDataCookieHelperTest : public testing::Test { 19 public: 20 BrowsingDataCookieHelperTest() 21 : testing_profile_(new TestingProfile()) { 22 } 23 24 void CreateCookiesForTest() { 25 scoped_refptr<net::CookieMonster> cookie_monster = 26 testing_profile_->GetCookieMonster(); 27 cookie_monster->SetCookieWithOptionsAsync( 28 GURL("http://www.google.com"), "A=1", net::CookieOptions(), 29 net::CookieMonster::SetCookiesCallback()); 30 cookie_monster->SetCookieWithOptionsAsync( 31 GURL("http://www.gmail.google.com"), "B=1", net::CookieOptions(), 32 net::CookieMonster::SetCookiesCallback()); 33 } 34 35 void CreateCookiesForDomainCookieTest() { 36 scoped_refptr<net::CookieMonster> cookie_monster = 37 testing_profile_->GetCookieMonster(); 38 cookie_monster->SetCookieWithOptionsAsync( 39 GURL("http://www.google.com"), "A=1", net::CookieOptions(), 40 net::CookieMonster::SetCookiesCallback()); 41 cookie_monster->SetCookieWithOptionsAsync( 42 GURL("http://www.google.com"), "A=2; Domain=.www.google.com ", 43 net::CookieOptions(), net::CookieMonster::SetCookiesCallback()); 44 } 45 46 void FetchCallback(const net::CookieList& cookies) { 47 ASSERT_EQ(2UL, cookies.size()); 48 cookie_list_ = cookies; 49 net::CookieList::const_iterator it = cookies.begin(); 50 51 // Correct because fetching cookies will get a sorted cookie list. 52 ASSERT_TRUE(it != cookies.end()); 53 EXPECT_EQ("www.google.com", it->Domain()); 54 EXPECT_EQ("A", it->Name()); 55 56 ASSERT_TRUE(++it != cookies.end()); 57 EXPECT_EQ("www.gmail.google.com", it->Domain()); 58 EXPECT_EQ("B", it->Name()); 59 60 ASSERT_TRUE(++it == cookies.end()); 61 } 62 63 void DomainCookieCallback(const net::CookieList& cookies) { 64 ASSERT_EQ(2UL, cookies.size()); 65 cookie_list_ = cookies; 66 net::CookieList::const_iterator it = cookies.begin(); 67 68 // Correct because fetching cookies will get a sorted cookie list. 69 ASSERT_TRUE(it != cookies.end()); 70 EXPECT_EQ("www.google.com", it->Domain()); 71 EXPECT_EQ("A", it->Name()); 72 EXPECT_EQ("1", it->Value()); 73 74 ASSERT_TRUE(++it != cookies.end()); 75 EXPECT_EQ(".www.google.com", it->Domain()); 76 EXPECT_EQ("A", it->Name()); 77 EXPECT_EQ("2", it->Value()); 78 79 ASSERT_TRUE(++it == cookies.end()); 80 } 81 82 void DeleteCallback(const net::CookieList& cookies) { 83 ASSERT_EQ(1UL, cookies.size()); 84 net::CookieList::const_iterator it = cookies.begin(); 85 86 ASSERT_TRUE(it != cookies.end()); 87 EXPECT_EQ("www.gmail.google.com", it->Domain()); 88 EXPECT_EQ("B", it->Name()); 89 90 ASSERT_TRUE(++it == cookies.end()); 91 } 92 93 void CannedUniqueCallback(const net::CookieList& cookies) { 94 EXPECT_EQ(1UL, cookies.size()); 95 cookie_list_ = cookies; 96 net::CookieList::const_iterator it = cookies.begin(); 97 98 ASSERT_TRUE(it != cookies.end()); 99 EXPECT_EQ("http://www.google.com/", it->Source()); 100 EXPECT_EQ("www.google.com", it->Domain()); 101 EXPECT_EQ("/", it->Path()); 102 EXPECT_EQ("A", it->Name()); 103 104 ASSERT_TRUE(++it == cookies.end()); 105 } 106 107 void CannedReplaceCookieCallback(const net::CookieList& cookies) { 108 EXPECT_EQ(5UL, cookies.size()); 109 cookie_list_ = cookies; 110 net::CookieList::const_iterator it = cookies.begin(); 111 112 ASSERT_TRUE(it != cookies.end()); 113 EXPECT_EQ("http://www.google.com/", it->Source()); 114 EXPECT_EQ("www.google.com", it->Domain()); 115 EXPECT_EQ("/", it->Path()); 116 EXPECT_EQ("A", it->Name()); 117 EXPECT_EQ("2", it->Value()); 118 119 ASSERT_TRUE(++it != cookies.end()); 120 EXPECT_EQ("http://www.google.com/", it->Source()); 121 EXPECT_EQ("www.google.com", it->Domain()); 122 EXPECT_EQ("/example/0", it->Path()); 123 EXPECT_EQ("A", it->Name()); 124 EXPECT_EQ("4", it->Value()); 125 126 ASSERT_TRUE(++it != cookies.end()); 127 EXPECT_EQ("http://www.google.com/", it->Source()); 128 EXPECT_EQ(".google.com", it->Domain()); 129 EXPECT_EQ("/", it->Path()); 130 EXPECT_EQ("A", it->Name()); 131 EXPECT_EQ("6", it->Value()); 132 133 ASSERT_TRUE(++it != cookies.end()); 134 EXPECT_EQ("http://www.google.com/", it->Source()); 135 EXPECT_EQ(".google.com", it->Domain()); 136 EXPECT_EQ("/example/1", it->Path()); 137 EXPECT_EQ("A", it->Name()); 138 EXPECT_EQ("8", it->Value()); 139 140 ASSERT_TRUE(++it != cookies.end()); 141 EXPECT_EQ("http://www.google.com/", it->Source()); 142 EXPECT_EQ(".www.google.com", it->Domain()); 143 EXPECT_EQ("/", it->Path()); 144 EXPECT_EQ("A", it->Name()); 145 EXPECT_EQ("10", it->Value()); 146 147 ASSERT_TRUE(++it == cookies.end()); 148 } 149 150 void CannedDomainCookieCallback(const net::CookieList& cookies) { 151 ASSERT_EQ(2UL, cookies.size()); 152 cookie_list_ = cookies; 153 net::CookieList::const_iterator it = cookies.begin(); 154 155 ASSERT_TRUE(it != cookies.end()); 156 EXPECT_EQ("http://www.google.com/", it->Source()); 157 EXPECT_EQ("A", it->Name()); 158 EXPECT_EQ("www.google.com", it->Domain()); 159 160 ASSERT_TRUE(++it != cookies.end()); 161 EXPECT_EQ("http://www.google.com/", it->Source()); 162 EXPECT_EQ("A", it->Name()); 163 EXPECT_EQ(".www.google.com", it->Domain()); 164 165 ASSERT_TRUE(++it == cookies.end()); 166 } 167 168 void CannedDifferentFramesCallback(const net::CookieList& cookie_list) { 169 ASSERT_EQ(3U, cookie_list.size()); 170 } 171 172 protected: 173 content::TestBrowserThreadBundle thread_bundle_; 174 scoped_ptr<TestingProfile> testing_profile_; 175 176 net::CookieList cookie_list_; 177 }; 178 179 TEST_F(BrowsingDataCookieHelperTest, FetchData) { 180 CreateCookiesForTest(); 181 scoped_refptr<BrowsingDataCookieHelper> cookie_helper( 182 new BrowsingDataCookieHelper(testing_profile_->GetRequestContext())); 183 184 cookie_helper->StartFetching( 185 base::Bind(&BrowsingDataCookieHelperTest::FetchCallback, 186 base::Unretained(this))); 187 base::RunLoop().RunUntilIdle(); 188 } 189 190 TEST_F(BrowsingDataCookieHelperTest, DomainCookie) { 191 CreateCookiesForDomainCookieTest(); 192 scoped_refptr<BrowsingDataCookieHelper> cookie_helper( 193 new BrowsingDataCookieHelper(testing_profile_->GetRequestContext())); 194 195 cookie_helper->StartFetching( 196 base::Bind(&BrowsingDataCookieHelperTest::DomainCookieCallback, 197 base::Unretained(this))); 198 base::RunLoop().RunUntilIdle(); 199 } 200 201 TEST_F(BrowsingDataCookieHelperTest, DeleteCookie) { 202 CreateCookiesForTest(); 203 scoped_refptr<BrowsingDataCookieHelper> cookie_helper( 204 new BrowsingDataCookieHelper(testing_profile_->GetRequestContext())); 205 206 cookie_helper->StartFetching( 207 base::Bind(&BrowsingDataCookieHelperTest::FetchCallback, 208 base::Unretained(this))); 209 base::RunLoop().RunUntilIdle(); 210 211 net::CanonicalCookie cookie = cookie_list_[0]; 212 cookie_helper->DeleteCookie(cookie); 213 214 cookie_helper->StartFetching( 215 base::Bind(&BrowsingDataCookieHelperTest::DeleteCallback, 216 base::Unretained(this))); 217 base::RunLoop().RunUntilIdle(); 218 } 219 220 TEST_F(BrowsingDataCookieHelperTest, CannedDomainCookie) { 221 const GURL origin("http://www.google.com"); 222 net::CookieList cookie; 223 224 scoped_refptr<CannedBrowsingDataCookieHelper> helper( 225 new CannedBrowsingDataCookieHelper( 226 testing_profile_->GetRequestContext())); 227 228 ASSERT_TRUE(helper->empty()); 229 helper->AddChangedCookie(origin, origin, "A=1", net::CookieOptions()); 230 helper->AddChangedCookie(origin, origin, "A=1; Domain=.www.google.com", 231 net::CookieOptions()); 232 // Try adding invalid cookies that will be ignored. 233 helper->AddChangedCookie(origin, origin, std::string(), net::CookieOptions()); 234 helper->AddChangedCookie(origin, 235 origin, 236 "C=bad guy; Domain=wrongdomain.com", 237 net::CookieOptions()); 238 239 helper->StartFetching( 240 base::Bind(&BrowsingDataCookieHelperTest::CannedDomainCookieCallback, 241 base::Unretained(this))); 242 cookie = cookie_list_; 243 244 helper->Reset(); 245 ASSERT_TRUE(helper->empty()); 246 247 helper->AddReadCookies(origin, origin, cookie); 248 helper->StartFetching( 249 base::Bind(&BrowsingDataCookieHelperTest::CannedDomainCookieCallback, 250 base::Unretained(this))); 251 } 252 253 TEST_F(BrowsingDataCookieHelperTest, CannedUnique) { 254 const GURL origin("http://www.google.com"); 255 net::CookieList cookie; 256 257 scoped_refptr<CannedBrowsingDataCookieHelper> helper( 258 new CannedBrowsingDataCookieHelper( 259 testing_profile_->GetRequestContext())); 260 261 ASSERT_TRUE(helper->empty()); 262 helper->AddChangedCookie(origin, origin, "A=1", net::CookieOptions()); 263 helper->AddChangedCookie(origin, origin, "A=1", net::CookieOptions()); 264 helper->StartFetching( 265 base::Bind(&BrowsingDataCookieHelperTest::CannedUniqueCallback, 266 base::Unretained(this))); 267 268 cookie = cookie_list_; 269 helper->Reset(); 270 ASSERT_TRUE(helper->empty()); 271 272 helper->AddReadCookies(origin, origin, cookie); 273 helper->AddReadCookies(origin, origin, cookie); 274 helper->StartFetching( 275 base::Bind(&BrowsingDataCookieHelperTest::CannedUniqueCallback, 276 base::Unretained(this))); 277 } 278 279 TEST_F(BrowsingDataCookieHelperTest, CannedReplaceCookie) { 280 const GURL origin("http://www.google.com"); 281 net::CookieList cookie; 282 283 scoped_refptr<CannedBrowsingDataCookieHelper> helper( 284 new CannedBrowsingDataCookieHelper( 285 testing_profile_->GetRequestContext())); 286 287 ASSERT_TRUE(helper->empty()); 288 helper->AddChangedCookie(origin, origin, "A=1", net::CookieOptions()); 289 helper->AddChangedCookie(origin, origin, "A=2", net::CookieOptions()); 290 helper->AddChangedCookie(origin, origin, "A=3; Path=/example/0", 291 net::CookieOptions()); 292 helper->AddChangedCookie(origin, origin, "A=4; Path=/example/0", 293 net::CookieOptions()); 294 helper->AddChangedCookie(origin, origin, "A=5; Domain=google.com", 295 net::CookieOptions()); 296 helper->AddChangedCookie(origin, origin, "A=6; Domain=google.com", 297 net::CookieOptions()); 298 helper->AddChangedCookie(origin, origin, 299 "A=7; Domain=google.com; Path=/example/1", 300 net::CookieOptions()); 301 helper->AddChangedCookie(origin, origin, 302 "A=8; Domain=google.com; Path=/example/1", 303 net::CookieOptions()); 304 305 helper->AddChangedCookie(origin, origin, 306 "A=9; Domain=www.google.com", 307 net::CookieOptions()); 308 helper->AddChangedCookie(origin, origin, 309 "A=10; Domain=www.google.com", 310 net::CookieOptions()); 311 312 helper->StartFetching( 313 base::Bind(&BrowsingDataCookieHelperTest::CannedReplaceCookieCallback, 314 base::Unretained(this))); 315 316 cookie = cookie_list_; 317 helper->Reset(); 318 ASSERT_TRUE(helper->empty()); 319 320 helper->AddReadCookies(origin, origin, cookie); 321 helper->AddReadCookies(origin, origin, cookie); 322 helper->StartFetching( 323 base::Bind(&BrowsingDataCookieHelperTest::CannedReplaceCookieCallback, 324 base::Unretained(this))); 325 } 326 327 TEST_F(BrowsingDataCookieHelperTest, CannedEmpty) { 328 const GURL url_google("http://www.google.com"); 329 330 scoped_refptr<CannedBrowsingDataCookieHelper> helper( 331 new CannedBrowsingDataCookieHelper( 332 testing_profile_->GetRequestContext())); 333 334 ASSERT_TRUE(helper->empty()); 335 helper->AddChangedCookie(url_google, url_google, "a=1", 336 net::CookieOptions()); 337 ASSERT_FALSE(helper->empty()); 338 helper->Reset(); 339 ASSERT_TRUE(helper->empty()); 340 341 net::CookieList cookies; 342 net::ParsedCookie pc("a=1"); 343 scoped_ptr<net::CanonicalCookie> cookie( 344 new net::CanonicalCookie(url_google, pc)); 345 cookies.push_back(*cookie); 346 347 helper->AddReadCookies(url_google, url_google, cookies); 348 ASSERT_FALSE(helper->empty()); 349 helper->Reset(); 350 ASSERT_TRUE(helper->empty()); 351 } 352 353 TEST_F(BrowsingDataCookieHelperTest, CannedDifferentFrames) { 354 GURL frame1_url("http://www.google.com"); 355 GURL frame2_url("http://www.google.de"); 356 GURL request_url("http://www.google.com"); 357 358 scoped_refptr<CannedBrowsingDataCookieHelper> helper( 359 new CannedBrowsingDataCookieHelper( 360 testing_profile_->GetRequestContext())); 361 362 ASSERT_TRUE(helper->empty()); 363 helper->AddChangedCookie(frame1_url, request_url, "a=1", 364 net::CookieOptions()); 365 helper->AddChangedCookie(frame1_url, request_url, "b=1", 366 net::CookieOptions()); 367 helper->AddChangedCookie(frame2_url, request_url, "c=1", 368 net::CookieOptions()); 369 370 helper->StartFetching( 371 base::Bind(&BrowsingDataCookieHelperTest::CannedDifferentFramesCallback, 372 base::Unretained(this))); 373 } 374 375 TEST_F(BrowsingDataCookieHelperTest, CannedGetCookieCount) { 376 // The URL in the omnibox is a frame URL. This is not necessarily the request 377 // URL, since websites usually include other resources. 378 GURL frame1_url("http://www.google.com"); 379 GURL frame2_url("http://www.google.de"); 380 // The request URL used for all cookies that are added to the |helper|. 381 GURL request1_url("http://static.google.com/foo/res1.html"); 382 GURL request2_url("http://static.google.com/bar/res2.html"); 383 std::string cookie_domain(".www.google.com"); 384 std::string cookie_pair1("A=1"); 385 std::string cookie_pair2("B=1"); 386 // The cookie pair used for adding a cookie that overrides the cookie created 387 // with |cookie_pair1|. The cookie-name of |cookie_pair3| must match the 388 // cookie-name of |cookie-pair1|. 389 std::string cookie_pair3("A=2"); 390 // The cookie pair used for adding a non host-only cookie. The cookie-name 391 // must match the cookie-name of |cookie_pair1| in order to add a host-only 392 // and a non host-only cookie with the same name below. 393 std::string cookie_pair4("A=3"); 394 395 scoped_refptr<CannedBrowsingDataCookieHelper> helper( 396 new CannedBrowsingDataCookieHelper( 397 testing_profile_->GetRequestContext())); 398 399 // Add two different cookies (distinguished by the tuple [cookie-name, 400 // domain-value, path-value]) for a HTTP request to |frame1_url| and verify 401 // that the cookie count is increased to two. The set-cookie-string consists 402 // only of the cookie-pair. This means that the host and the default-path of 403 // the |request_url| are used as domain-value and path-value for the added 404 // cookies. 405 EXPECT_EQ(0U, helper->GetCookieCount()); 406 helper->AddChangedCookie(frame1_url, frame1_url, cookie_pair1, 407 net::CookieOptions()); 408 EXPECT_EQ(1U, helper->GetCookieCount()); 409 helper->AddChangedCookie(frame1_url, frame1_url, cookie_pair2, 410 net::CookieOptions()); 411 EXPECT_EQ(2U, helper->GetCookieCount()); 412 413 // Use a different frame URL for adding another cookie that will replace one 414 // of the previously added cookies. This could happen during an automatic 415 // redirect e.g. |frame1_url| redirects to |frame2_url| and a cookie set by a 416 // request to |frame1_url| is updated. 417 helper->AddChangedCookie(frame2_url, frame1_url, cookie_pair3, 418 net::CookieOptions()); 419 EXPECT_EQ(2U, helper->GetCookieCount()); 420 421 // Add two more cookies that are set while loading resources. The two cookies 422 // below have a differnt path-value since the request URLs have different 423 // paths. 424 helper->AddChangedCookie(frame2_url, request1_url, cookie_pair3, 425 net::CookieOptions()); 426 EXPECT_EQ(3U, helper->GetCookieCount()); 427 helper->AddChangedCookie(frame2_url, request2_url, cookie_pair3, 428 net::CookieOptions()); 429 EXPECT_EQ(4U, helper->GetCookieCount()); 430 431 // Host-only and domain cookies are treated as seperate items. This means that 432 // the following two cookie-strings are stored as two separate cookies, even 433 // though they have the same name and are send with the same request: 434 // "A=1; 435 // "A=3; Domain=www.google.com" 436 // Add a domain cookie and check if it increases the cookie count. 437 helper->AddChangedCookie(frame2_url, frame1_url, 438 cookie_pair4 + "; Domain=" + cookie_domain, 439 net::CookieOptions()); 440 EXPECT_EQ(5U, helper->GetCookieCount()); 441 } 442 443 } // namespace 444