| // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #ifndef NET_COOKIES_COOKIE_STORE_UNITTEST_H_ |
| #define NET_COOKIES_COOKIE_STORE_UNITTEST_H_ |
| |
| #include "base/bind.h" |
| #include "base/message_loop.h" |
| #include "base/string_tokenizer.h" |
| #include "base/threading/thread.h" |
| #include "googleurl/src/gurl.h" |
| #include "net/cookies/cookie_monster.h" |
| #include "net/cookies/cookie_store.h" |
| #include "net/cookies/cookie_store_test_callbacks.h" |
| #include "testing/gtest/include/gtest/gtest.h" |
| |
| // This file declares unittest templates that can be used to test common |
| // behavior of any CookieStore implementation. |
| // See cookie_monster_unittest.cc for an example of an implementation. |
| |
| namespace net { |
| |
| using base::Thread; |
| |
| const int kTimeout = 1000; |
| |
| const char kUrlFtp[] = "ftp://ftp.google.izzle/"; |
| const char kUrlGoogle[] = "http://www.google.izzle"; |
| const char kUrlGoogleFoo[] = "http://www.google.izzle/foo"; |
| const char kUrlGoogleBar[] = "http://www.google.izzle/bar"; |
| const char kUrlGoogleSecure[] = "https://www.google.izzle"; |
| const char kValidCookieLine[] = "A=B; path=/"; |
| const char kValidDomainCookieLine[] = "A=B; path=/; domain=google.izzle"; |
| |
| // The CookieStoreTestTraits must have the following members: |
| // struct CookieStoreTestTraits { |
| // // Factory function. |
| // static scoped_refptr<CookieStore> Create(); |
| // |
| // // The cookie store is a CookieMonster. Only used to test |
| // // GetCookieMonster(). |
| // static const bool is_cookie_monster; |
| // |
| // // The cookie store supports cookies with the exclude_httponly() option. |
| // static const bool supports_http_only; |
| // |
| // // The cookie store supports the GetCookiesWithInfoAsync() method. |
| // static const bool supports_cookies_with_info; |
| // |
| // // The cookie store is able to make the difference between the ".com" |
| // // and the "com" domains. |
| // static const bool supports_non_dotted_domains; |
| // |
| // // The cookie store handles the domains with trailing dots (such as "com.") |
| // // correctly. |
| // static const bool supports_trailing_dots; |
| // |
| // // The cookie store rejects cookies for invalid schemes such as ftp. |
| // static const bool filters_schemes; |
| // |
| // // The cookie store has a bug happening when a path is a substring of |
| // // another. |
| // static const bool has_path_prefix_bug; |
| // |
| // // Time to wait between two cookie insertions to ensure that cookies have |
| // // different creation times. |
| // static const int creation_time_granularity_in_ms; |
| // }; |
| |
| template <class CookieStoreTestTraits> |
| class CookieStoreTest : public testing::Test { |
| protected: |
| CookieStoreTest() |
| : url_google_(kUrlGoogle), |
| url_google_secure_(kUrlGoogleSecure), |
| url_google_foo_(kUrlGoogleFoo), |
| url_google_bar_(kUrlGoogleBar) { |
| // This test may be used outside of the net test suite, and thus may not |
| // have a message loop. |
| if (!MessageLoop::current()) |
| message_loop_.reset(new MessageLoop); |
| weak_factory_.reset( |
| new base::WeakPtrFactory<MessageLoop>(MessageLoop::current())); |
| } |
| |
| // Helper methods for the asynchronous Cookie Store API that call the |
| // asynchronous method and then pump the loop until the callback is invoked, |
| // finally returning the value. |
| |
| std::string GetCookies(CookieStore* cs, const GURL& url) { |
| DCHECK(cs); |
| CookieOptions options; |
| if (!CookieStoreTestTraits::supports_http_only) |
| options.set_include_httponly(); |
| GetCookieStringCallback callback; |
| cs->GetCookiesWithOptionsAsync( |
| url, options, |
| base::Bind(&GetCookieStringCallback::Run, base::Unretained(&callback))); |
| RunFor(kTimeout); |
| EXPECT_TRUE(callback.did_run()); |
| return callback.cookie(); |
| } |
| |
| std::string GetCookiesWithOptions(CookieStore* cs, |
| const GURL& url, |
| const CookieOptions& options) { |
| DCHECK(cs); |
| GetCookieStringCallback callback; |
| cs->GetCookiesWithOptionsAsync( |
| url, options, base::Bind(&GetCookieStringCallback::Run, |
| base::Unretained(&callback))); |
| RunFor(kTimeout); |
| EXPECT_TRUE(callback.did_run()); |
| return callback.cookie(); |
| } |
| |
| void GetCookiesWithInfo(CookieStore* cs, |
| const GURL& url, |
| const CookieOptions& options, |
| std::string* cookie_line, |
| std::vector<CookieStore::CookieInfo>* cookie_info) { |
| DCHECK(cs); |
| DCHECK(cookie_line); |
| DCHECK(cookie_info); |
| GetCookiesWithInfoCallback callback; |
| cs->GetCookiesWithInfoAsync( |
| url, options, base::Bind(&GetCookiesWithInfoCallback::Run, |
| base::Unretained(&callback))); |
| RunFor(kTimeout); |
| EXPECT_TRUE(callback.did_run()); |
| *cookie_line = callback.cookie_line(); |
| *cookie_info = callback.cookie_info(); |
| } |
| |
| bool SetCookieWithOptions(CookieStore* cs, |
| const GURL& url, |
| const std::string& cookie_line, |
| const CookieOptions& options) { |
| DCHECK(cs); |
| SetCookieCallback callback; |
| cs->SetCookieWithOptionsAsync( |
| url, cookie_line, options, |
| base::Bind(&SetCookieCallback::Run, base::Unretained(&callback))); |
| RunFor(kTimeout); |
| EXPECT_TRUE(callback.did_run()); |
| return callback.result(); |
| } |
| |
| bool SetCookieWithServerTime(CookieStore* cs, |
| const GURL& url, |
| const std::string& cookie_line, |
| const base::Time& server_time) { |
| CookieOptions options; |
| if (!CookieStoreTestTraits::supports_http_only) |
| options.set_include_httponly(); |
| options.set_server_time(server_time); |
| return SetCookieWithOptions(cs, url, cookie_line, options); |
| } |
| |
| bool SetCookie(CookieStore* cs, |
| const GURL& url, |
| const std::string& cookie_line) { |
| CookieOptions options; |
| if (!CookieStoreTestTraits::supports_http_only) |
| options.set_include_httponly(); |
| return SetCookieWithOptions(cs, url, cookie_line, options); |
| } |
| |
| void DeleteCookie(CookieStore* cs, |
| const GURL& url, |
| const std::string& cookie_name) { |
| DCHECK(cs); |
| DeleteCookieCallback callback; |
| cs->DeleteCookieAsync( |
| url, cookie_name, |
| base::Bind(&DeleteCookieCallback::Run, base::Unretained(&callback))); |
| RunFor(kTimeout); |
| EXPECT_TRUE(callback.did_run()); |
| } |
| |
| int DeleteCreatedBetween(CookieStore* cs, |
| const base::Time& delete_begin, |
| const base::Time& delete_end) { |
| DCHECK(cs); |
| DeleteCallback callback; |
| cs->DeleteAllCreatedBetweenAsync( |
| delete_begin, delete_end, |
| base::Bind(&DeleteCallback::Run, base::Unretained(&callback))); |
| RunFor(kTimeout); |
| EXPECT_TRUE(callback.did_run()); |
| return callback.num_deleted(); |
| } |
| |
| int DeleteSessionCookies(CookieStore* cs) { |
| DCHECK(cs); |
| DeleteCallback callback; |
| cs->DeleteSessionCookiesAsync( |
| base::Bind(&DeleteCallback::Run, base::Unretained(&callback))); |
| RunFor(kTimeout); |
| EXPECT_TRUE(callback.did_run()); |
| return callback.num_deleted(); |
| } |
| |
| void RunFor(int ms) { |
| // Runs the test thread message loop for up to |ms| milliseconds. |
| MessageLoop::current()->PostDelayedTask( |
| FROM_HERE, base::Bind(&MessageLoop::Quit, weak_factory_->GetWeakPtr()), |
| base::TimeDelta::FromMilliseconds(ms)); |
| MessageLoop::current()->Run(); |
| weak_factory_->InvalidateWeakPtrs(); |
| } |
| |
| scoped_refptr<CookieStore> GetCookieStore() { |
| return CookieStoreTestTraits::Create(); |
| } |
| |
| // Compares two cookie lines. |
| void MatchCookieLines(const std::string& line1, const std::string& line2) { |
| EXPECT_EQ(TokenizeCookieLine(line1), TokenizeCookieLine(line2)); |
| } |
| |
| // Check the cookie line by polling until equality or a timeout is reached. |
| void MatchCookieLineWithTimeout(CookieStore* cs, |
| const GURL& url, |
| const std::string& line) { |
| std::string cookies = GetCookies(cs, url); |
| bool matched = (TokenizeCookieLine(line) == TokenizeCookieLine(cookies)); |
| base::Time polling_end_date = base::Time::Now() + |
| base::TimeDelta::FromMilliseconds( |
| CookieStoreTestTraits::creation_time_granularity_in_ms); |
| |
| while (!matched && base::Time::Now() <= polling_end_date) { |
| base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(10)); |
| cookies = GetCookies(cs, url); |
| matched = (TokenizeCookieLine(line) == TokenizeCookieLine(cookies)); |
| } |
| |
| EXPECT_TRUE(matched) << "\"" << cookies |
| << "\" does not match \"" << line << "\""; |
| } |
| |
| GURL url_google_; |
| GURL url_google_secure_; |
| GURL url_google_foo_; |
| GURL url_google_bar_; |
| |
| scoped_ptr<base::WeakPtrFactory<MessageLoop> > weak_factory_; |
| scoped_ptr<MessageLoop> message_loop_; |
| |
| private: |
| // Returns a set of strings of type "name=value". Fails in case of duplicate. |
| std::set<std::string> TokenizeCookieLine(const std::string& line) { |
| std::set<std::string> tokens; |
| StringTokenizer tokenizer(line, " ;"); |
| while (tokenizer.GetNext()) |
| EXPECT_TRUE(tokens.insert(tokenizer.token()).second); |
| return tokens; |
| } |
| }; |
| |
| TYPED_TEST_CASE_P(CookieStoreTest); |
| |
| TYPED_TEST_P(CookieStoreTest, TypeTest) { |
| scoped_refptr<CookieStore> cs(this->GetCookieStore()); |
| EXPECT_EQ(cs->GetCookieMonster(), |
| (TypeParam::is_cookie_monster) ? |
| static_cast<CookieMonster*>(cs.get()) : NULL); |
| } |
| |
| TYPED_TEST_P(CookieStoreTest, DomainTest) { |
| scoped_refptr<CookieStore> cs(this->GetCookieStore()); |
| EXPECT_TRUE(this->SetCookie(cs, this->url_google_, "A=B")); |
| this->MatchCookieLines("A=B", this->GetCookies(cs, this->url_google_)); |
| EXPECT_TRUE(this->SetCookie(cs, this->url_google_, |
| "C=D; domain=.google.izzle")); |
| this->MatchCookieLines("A=B; C=D", this->GetCookies(cs, this->url_google_)); |
| |
| // Verify that A=B was set as a host cookie rather than a domain |
| // cookie -- should not be accessible from a sub sub-domain. |
| this->MatchCookieLines("C=D", |
| this->GetCookies(cs, GURL("http://foo.www.google.izzle"))); |
| |
| // Test and make sure we find domain cookies on the same domain. |
| EXPECT_TRUE(this->SetCookie(cs, this->url_google_, |
| "E=F; domain=.www.google.izzle")); |
| this->MatchCookieLines("A=B; C=D; E=F", |
| this->GetCookies(cs, this->url_google_)); |
| |
| // Test setting a domain= that doesn't start w/ a dot, should |
| // treat it as a domain cookie, as if there was a pre-pended dot. |
| EXPECT_TRUE(this->SetCookie(cs, this->url_google_, |
| "G=H; domain=www.google.izzle")); |
| this->MatchCookieLines("A=B; C=D; E=F; G=H", |
| this->GetCookies(cs, this->url_google_)); |
| |
| // Test domain enforcement, should fail on a sub-domain or something too deep. |
| EXPECT_FALSE(this->SetCookie(cs, this->url_google_, "I=J; domain=.izzle")); |
| this->MatchCookieLines("", this->GetCookies(cs, GURL("http://a.izzle"))); |
| EXPECT_FALSE(this->SetCookie(cs, this->url_google_, |
| "K=L; domain=.bla.www.google.izzle")); |
| this->MatchCookieLines("C=D; E=F; G=H", |
| this->GetCookies(cs, GURL("http://bla.www.google.izzle"))); |
| this->MatchCookieLines("A=B; C=D; E=F; G=H", |
| this->GetCookies(cs, this->url_google_)); |
| } |
| |
| // FireFox recognizes domains containing trailing periods as valid. |
| // IE and Safari do not. Assert the expected policy here. |
| TYPED_TEST_P(CookieStoreTest, DomainWithTrailingDotTest) { |
| scoped_refptr<CookieStore> cs(this->GetCookieStore()); |
| EXPECT_FALSE(this->SetCookie(cs, this->url_google_, |
| "a=1; domain=.www.google.com.")); |
| EXPECT_FALSE(this->SetCookie(cs, this->url_google_, |
| "b=2; domain=.www.google.com..")); |
| this->MatchCookieLines("", this->GetCookies(cs, this->url_google_)); |
| } |
| |
| // Test that cookies can bet set on higher level domains. |
| // http://b/issue?id=896491 |
| TYPED_TEST_P(CookieStoreTest, ValidSubdomainTest) { |
| scoped_refptr<CookieStore> cs(this->GetCookieStore()); |
| GURL url_abcd("http://a.b.c.d.com"); |
| GURL url_bcd("http://b.c.d.com"); |
| GURL url_cd("http://c.d.com"); |
| GURL url_d("http://d.com"); |
| |
| EXPECT_TRUE(this->SetCookie(cs, url_abcd, "a=1; domain=.a.b.c.d.com")); |
| EXPECT_TRUE(this->SetCookie(cs, url_abcd, "b=2; domain=.b.c.d.com")); |
| EXPECT_TRUE(this->SetCookie(cs, url_abcd, "c=3; domain=.c.d.com")); |
| EXPECT_TRUE(this->SetCookie(cs, url_abcd, "d=4; domain=.d.com")); |
| |
| this->MatchCookieLines("a=1; b=2; c=3; d=4", this->GetCookies(cs, url_abcd)); |
| this->MatchCookieLines("b=2; c=3; d=4", this->GetCookies(cs, url_bcd)); |
| this->MatchCookieLines("c=3; d=4", this->GetCookies(cs, url_cd)); |
| this->MatchCookieLines("d=4", this->GetCookies(cs, url_d)); |
| |
| // Check that the same cookie can exist on different sub-domains. |
| EXPECT_TRUE(this->SetCookie(cs, url_bcd, "X=bcd; domain=.b.c.d.com")); |
| EXPECT_TRUE(this->SetCookie(cs, url_bcd, "X=cd; domain=.c.d.com")); |
| this->MatchCookieLines("b=2; c=3; d=4; X=bcd; X=cd", |
| this->GetCookies(cs, url_bcd)); |
| this->MatchCookieLines("c=3; d=4; X=cd", this->GetCookies(cs, url_cd)); |
| } |
| |
| // Test that setting a cookie which specifies an invalid domain has |
| // no side-effect. An invalid domain in this context is one which does |
| // not match the originating domain. |
| // http://b/issue?id=896472 |
| TYPED_TEST_P(CookieStoreTest, InvalidDomainTest) { |
| { |
| scoped_refptr<CookieStore> cs(this->GetCookieStore()); |
| GURL url_foobar("http://foo.bar.com"); |
| |
| // More specific sub-domain than allowed. |
| EXPECT_FALSE(this->SetCookie(cs, url_foobar, |
| "a=1; domain=.yo.foo.bar.com")); |
| |
| EXPECT_FALSE(this->SetCookie(cs, url_foobar, "b=2; domain=.foo.com")); |
| EXPECT_FALSE(this->SetCookie(cs, url_foobar, "c=3; domain=.bar.foo.com")); |
| |
| // Different TLD, but the rest is a substring. |
| EXPECT_FALSE(this->SetCookie(cs, url_foobar, |
| "d=4; domain=.foo.bar.com.net")); |
| |
| // A substring that isn't really a parent domain. |
| EXPECT_FALSE(this->SetCookie(cs, url_foobar, "e=5; domain=ar.com")); |
| |
| // Completely invalid domains: |
| EXPECT_FALSE(this->SetCookie(cs, url_foobar, "f=6; domain=.")); |
| EXPECT_FALSE(this->SetCookie(cs, url_foobar, "g=7; domain=/")); |
| EXPECT_FALSE(this->SetCookie(cs, url_foobar, |
| "h=8; domain=http://foo.bar.com")); |
| EXPECT_FALSE(this->SetCookie(cs, url_foobar, "i=9; domain=..foo.bar.com")); |
| EXPECT_FALSE(this->SetCookie(cs, url_foobar, "j=10; domain=..bar.com")); |
| |
| // Make sure there isn't something quirky in the domain canonicalization |
| // that supports full URL semantics. |
| EXPECT_FALSE(this->SetCookie(cs, url_foobar, |
| "k=11; domain=.foo.bar.com?blah")); |
| EXPECT_FALSE(this->SetCookie(cs, url_foobar, |
| "l=12; domain=.foo.bar.com/blah")); |
| EXPECT_FALSE(this->SetCookie(cs, url_foobar, |
| "m=13; domain=.foo.bar.com:80")); |
| EXPECT_FALSE(this->SetCookie(cs, url_foobar, |
| "n=14; domain=.foo.bar.com:")); |
| EXPECT_FALSE(this->SetCookie(cs, url_foobar, |
| "o=15; domain=.foo.bar.com#sup")); |
| |
| this->MatchCookieLines("", this->GetCookies(cs, url_foobar)); |
| } |
| |
| { |
| // Make sure the cookie code hasn't gotten its subdomain string handling |
| // reversed, missed a suffix check, etc. It's important here that the two |
| // hosts below have the same domain + registry. |
| scoped_refptr<CookieStore> cs(this->GetCookieStore()); |
| GURL url_foocom("http://foo.com.com"); |
| EXPECT_FALSE(this->SetCookie(cs, url_foocom, |
| "a=1; domain=.foo.com.com.com")); |
| this->MatchCookieLines("", this->GetCookies(cs, url_foocom)); |
| } |
| } |
| |
| // Test the behavior of omitting dot prefix from domain, should |
| // function the same as FireFox. |
| // http://b/issue?id=889898 |
| TYPED_TEST_P(CookieStoreTest, DomainWithoutLeadingDotTest) { |
| { // The omission of dot results in setting a domain cookie. |
| scoped_refptr<CookieStore> cs(this->GetCookieStore()); |
| GURL url_hosted("http://manage.hosted.filefront.com"); |
| GURL url_filefront("http://www.filefront.com"); |
| EXPECT_TRUE(this->SetCookie(cs, url_hosted, |
| "sawAd=1; domain=filefront.com")); |
| this->MatchCookieLines("sawAd=1", this->GetCookies(cs, url_hosted)); |
| this->MatchCookieLines("sawAd=1", this->GetCookies(cs, url_filefront)); |
| } |
| |
| { // Even when the domains match exactly, don't consider it host cookie. |
| scoped_refptr<CookieStore> cs(this->GetCookieStore()); |
| GURL url("http://www.google.com"); |
| EXPECT_TRUE(this->SetCookie(cs, url, "a=1; domain=www.google.com")); |
| this->MatchCookieLines("a=1", this->GetCookies(cs, url)); |
| this->MatchCookieLines("a=1", |
| this->GetCookies(cs, GURL("http://sub.www.google.com"))); |
| this->MatchCookieLines("", |
| this->GetCookies(cs, GURL("http://something-else.com"))); |
| } |
| } |
| |
| // Test that the domain specified in cookie string is treated case-insensitive |
| // http://b/issue?id=896475. |
| TYPED_TEST_P(CookieStoreTest, CaseInsensitiveDomainTest) { |
| scoped_refptr<CookieStore> cs(this->GetCookieStore()); |
| GURL url("http://www.google.com"); |
| EXPECT_TRUE(this->SetCookie(cs, url, "a=1; domain=.GOOGLE.COM")); |
| EXPECT_TRUE(this->SetCookie(cs, url, "b=2; domain=.wWw.gOOgLE.coM")); |
| this->MatchCookieLines("a=1; b=2", this->GetCookies(cs, url)); |
| } |
| |
| TYPED_TEST_P(CookieStoreTest, TestIpAddress) { |
| GURL url_ip("http://1.2.3.4/weee"); |
| { |
| scoped_refptr<CookieStore> cs(this->GetCookieStore()); |
| EXPECT_TRUE(this->SetCookie(cs, url_ip, kValidCookieLine)); |
| this->MatchCookieLines("A=B", this->GetCookies(cs, url_ip)); |
| } |
| |
| { // IP addresses should not be able to set domain cookies. |
| scoped_refptr<CookieStore> cs(this->GetCookieStore()); |
| EXPECT_FALSE(this->SetCookie(cs, url_ip, "b=2; domain=.1.2.3.4")); |
| EXPECT_FALSE(this->SetCookie(cs, url_ip, "c=3; domain=.3.4")); |
| this->MatchCookieLines("", this->GetCookies(cs, url_ip)); |
| // It should be allowed to set a cookie if domain= matches the IP address |
| // exactly. This matches IE/Firefox, even though it seems a bit wrong. |
| EXPECT_FALSE(this->SetCookie(cs, url_ip, "b=2; domain=1.2.3.3")); |
| this->MatchCookieLines("", this->GetCookies(cs, url_ip)); |
| EXPECT_TRUE(this->SetCookie(cs, url_ip, "b=2; domain=1.2.3.4")); |
| this->MatchCookieLines("b=2", this->GetCookies(cs, url_ip)); |
| } |
| } |
| |
| // Test host cookies, and setting of cookies on TLD. |
| TYPED_TEST_P(CookieStoreTest, TestNonDottedAndTLD) { |
| { |
| scoped_refptr<CookieStore> cs(this->GetCookieStore()); |
| GURL url("http://com/"); |
| // Allow setting on "com", (but only as a host cookie). |
| EXPECT_TRUE(this->SetCookie(cs, url, "a=1")); |
| EXPECT_FALSE(this->SetCookie(cs, url, "b=2; domain=.com")); |
| EXPECT_FALSE(this->SetCookie(cs, url, "c=3; domain=com")); |
| this->MatchCookieLines("a=1", this->GetCookies(cs, url)); |
| // Make sure it doesn't show up for a normal .com, it should be a host |
| // not a domain cookie. |
| this->MatchCookieLines("", |
| this->GetCookies(cs, GURL("http://hopefully-no-cookies.com/"))); |
| if (TypeParam::supports_non_dotted_domains) { |
| this->MatchCookieLines("", this->GetCookies(cs, GURL("http://.com/"))); |
| } |
| } |
| |
| { |
| // http://com. should be treated the same as http://com. |
| scoped_refptr<CookieStore> cs(this->GetCookieStore()); |
| GURL url("http://com./index.html"); |
| if (TypeParam::supports_trailing_dots) { |
| EXPECT_TRUE(this->SetCookie(cs, url, "a=1")); |
| this->MatchCookieLines("a=1", this->GetCookies(cs, url)); |
| this->MatchCookieLines("", |
| this->GetCookies(cs, GURL("http://hopefully-no-cookies.com./"))); |
| } else { |
| EXPECT_FALSE(this->SetCookie(cs, url, "a=1")); |
| } |
| } |
| |
| { // Should not be able to set host cookie from a subdomain. |
| scoped_refptr<CookieStore> cs(this->GetCookieStore()); |
| GURL url("http://a.b"); |
| EXPECT_FALSE(this->SetCookie(cs, url, "a=1; domain=.b")); |
| EXPECT_FALSE(this->SetCookie(cs, url, "b=2; domain=b")); |
| this->MatchCookieLines("", this->GetCookies(cs, url)); |
| } |
| |
| { // Same test as above, but explicitly on a known TLD (com). |
| scoped_refptr<CookieStore> cs(this->GetCookieStore()); |
| GURL url("http://google.com"); |
| EXPECT_FALSE(this->SetCookie(cs, url, "a=1; domain=.com")); |
| EXPECT_FALSE(this->SetCookie(cs, url, "b=2; domain=com")); |
| this->MatchCookieLines("", this->GetCookies(cs, url)); |
| } |
| |
| { // Make sure can't set cookie on TLD which is dotted. |
| scoped_refptr<CookieStore> cs(this->GetCookieStore()); |
| GURL url("http://google.co.uk"); |
| EXPECT_FALSE(this->SetCookie(cs, url, "a=1; domain=.co.uk")); |
| EXPECT_FALSE(this->SetCookie(cs, url, "b=2; domain=.uk")); |
| this->MatchCookieLines("", this->GetCookies(cs, url)); |
| this->MatchCookieLines("", |
| this->GetCookies(cs, GURL("http://something-else.co.uk"))); |
| this->MatchCookieLines("", |
| this->GetCookies(cs, GURL("http://something-else.uk"))); |
| } |
| |
| { // Intranet URLs should only be able to set host cookies. |
| scoped_refptr<CookieStore> cs(this->GetCookieStore()); |
| GURL url("http://b"); |
| EXPECT_TRUE(this->SetCookie(cs, url, "a=1")); |
| EXPECT_FALSE(this->SetCookie(cs, url, "b=2; domain=.b")); |
| EXPECT_FALSE(this->SetCookie(cs, url, "c=3; domain=b")); |
| this->MatchCookieLines("a=1", this->GetCookies(cs, url)); |
| } |
| } |
| |
| // Test reading/writing cookies when the domain ends with a period, |
| // as in "www.google.com." |
| TYPED_TEST_P(CookieStoreTest, TestHostEndsWithDot) { |
| scoped_refptr<CookieStore> cs(this->GetCookieStore()); |
| GURL url("http://www.google.com"); |
| GURL url_with_dot("http://www.google.com."); |
| EXPECT_TRUE(this->SetCookie(cs, url, "a=1")); |
| this->MatchCookieLines("a=1", this->GetCookies(cs, url)); |
| |
| if (TypeParam::supports_trailing_dots) { |
| // Do not share cookie space with the dot version of domain. |
| // Note: this is not what FireFox does, but it _is_ what IE+Safari do. |
| EXPECT_FALSE(this->SetCookie(cs, url, "b=2; domain=.www.google.com.")); |
| this->MatchCookieLines("a=1", this->GetCookies(cs, url)); |
| |
| EXPECT_TRUE(this->SetCookie(cs, url_with_dot, "b=2; domain=.google.com.")); |
| this->MatchCookieLines("b=2", this->GetCookies(cs, url_with_dot)); |
| } else { |
| EXPECT_TRUE(this->SetCookie(cs, url, "b=2; domain=.www.google.com.")); |
| EXPECT_FALSE(this->SetCookie(cs, url_with_dot, "b=2; domain=.google.com.")); |
| } |
| |
| // Make sure there weren't any side effects. |
| this->MatchCookieLines("", |
| this->GetCookies(cs, GURL("http://hopefully-no-cookies.com/"))); |
| this->MatchCookieLines("", this->GetCookies(cs, GURL("http://.com/"))); |
| } |
| |
| TYPED_TEST_P(CookieStoreTest, InvalidScheme) { |
| if (!TypeParam::filters_schemes) |
| return; |
| |
| scoped_refptr<CookieStore> cs(this->GetCookieStore()); |
| EXPECT_FALSE(this->SetCookie(cs, GURL(kUrlFtp), kValidCookieLine)); |
| } |
| |
| TYPED_TEST_P(CookieStoreTest, InvalidScheme_Read) { |
| if (!TypeParam::filters_schemes) |
| return; |
| |
| scoped_refptr<CookieStore> cs(this->GetCookieStore()); |
| EXPECT_TRUE(this->SetCookie(cs, GURL(kUrlGoogle), kValidDomainCookieLine)); |
| this->MatchCookieLines("", this->GetCookies(cs, GURL(kUrlFtp))); |
| } |
| |
| TYPED_TEST_P(CookieStoreTest, PathTest) { |
| scoped_refptr<CookieStore> cs(this->GetCookieStore()); |
| std::string url("http://www.google.izzle"); |
| EXPECT_TRUE(this->SetCookie(cs, GURL(url), "A=B; path=/wee")); |
| this->MatchCookieLines("A=B", this->GetCookies(cs, GURL(url + "/wee"))); |
| this->MatchCookieLines("A=B", this->GetCookies(cs, GURL(url + "/wee/"))); |
| this->MatchCookieLines("A=B", this->GetCookies(cs, GURL(url + "/wee/war"))); |
| this->MatchCookieLines("A=B", |
| this->GetCookies(cs, GURL(url + "/wee/war/more/more"))); |
| if (!TypeParam::has_path_prefix_bug) |
| this->MatchCookieLines("", this->GetCookies(cs, GURL(url + "/weehee"))); |
| this->MatchCookieLines("", this->GetCookies(cs, GURL(url + "/"))); |
| |
| // If we add a 0 length path, it should default to / |
| EXPECT_TRUE(this->SetCookie(cs, GURL(url), "A=C; path=")); |
| this->MatchCookieLines("A=B; A=C", this->GetCookies(cs, GURL(url + "/wee"))); |
| this->MatchCookieLines("A=C", this->GetCookies(cs, GURL(url + "/"))); |
| } |
| |
| TYPED_TEST_P(CookieStoreTest, HttpOnlyTest) { |
| if (!TypeParam::supports_http_only) |
| return; |
| |
| scoped_refptr<CookieStore> cs(this->GetCookieStore()); |
| CookieOptions options; |
| options.set_include_httponly(); |
| |
| // Create a httponly cookie. |
| EXPECT_TRUE(this->SetCookieWithOptions(cs, this->url_google_, "A=B; httponly", |
| options)); |
| |
| // Check httponly read protection. |
| this->MatchCookieLines("", this->GetCookies(cs, this->url_google_)); |
| this->MatchCookieLines("A=B", |
| this->GetCookiesWithOptions(cs, this->url_google_, options)); |
| |
| // Check httponly overwrite protection. |
| EXPECT_FALSE(this->SetCookie(cs, this->url_google_, "A=C")); |
| this->MatchCookieLines("", this->GetCookies(cs, this->url_google_)); |
| this->MatchCookieLines("A=B", |
| this->GetCookiesWithOptions(cs, this->url_google_, options)); |
| EXPECT_TRUE(this->SetCookieWithOptions(cs, this->url_google_, "A=C", |
| options)); |
| this->MatchCookieLines("A=C", this->GetCookies(cs, this->url_google_)); |
| |
| // Check httponly create protection. |
| EXPECT_FALSE(this->SetCookie(cs, this->url_google_, "B=A; httponly")); |
| this->MatchCookieLines("A=C", |
| this->GetCookiesWithOptions(cs, this->url_google_, options)); |
| EXPECT_TRUE(this->SetCookieWithOptions(cs, this->url_google_, "B=A; httponly", |
| options)); |
| this->MatchCookieLines("A=C; B=A", |
| this->GetCookiesWithOptions(cs, this->url_google_, options)); |
| this->MatchCookieLines("A=C", this->GetCookies(cs, this->url_google_)); |
| } |
| |
| TYPED_TEST_P(CookieStoreTest, TestGetCookiesWithInfo) { |
| if (!TypeParam::supports_cookies_with_info) |
| return; |
| |
| scoped_refptr<CookieStore> cs(this->GetCookieStore()); |
| CookieOptions options; |
| |
| EXPECT_TRUE(this->SetCookieWithOptions(cs, this->url_google_, "A=B", |
| options)); |
| EXPECT_TRUE(this->SetCookieWithOptions(cs, this->url_google_, |
| "C=D; Mac-Key=390jfn0awf3; Mac-Algorithm=hmac-sha-1", options)); |
| |
| this->MatchCookieLines("A=B; C=D", |
| this->GetCookiesWithOptions(cs, this->url_google_, options)); |
| |
| std::string cookie_line; |
| std::vector<CookieStore::CookieInfo> cookie_infos; |
| |
| this->GetCookiesWithInfo(cs, this->url_google_, options, &cookie_line, |
| &cookie_infos); |
| |
| EXPECT_EQ("A=B; C=D", cookie_line); |
| |
| EXPECT_EQ(2U, cookie_infos.size()); |
| |
| EXPECT_EQ("A", cookie_infos[0].name); |
| EXPECT_EQ("", cookie_infos[0].mac_key); |
| EXPECT_EQ("", cookie_infos[0].mac_algorithm); |
| |
| EXPECT_EQ("C", cookie_infos[1].name); |
| EXPECT_EQ("390jfn0awf3", cookie_infos[1].mac_key); |
| EXPECT_EQ("hmac-sha-1", cookie_infos[1].mac_algorithm); |
| } |
| |
| TYPED_TEST_P(CookieStoreTest, TestCookieDeletion) { |
| scoped_refptr<CookieStore> cs(this->GetCookieStore()); |
| |
| // Create a session cookie. |
| EXPECT_TRUE(this->SetCookie(cs, this->url_google_, kValidCookieLine)); |
| this->MatchCookieLines("A=B", this->GetCookies(cs, this->url_google_)); |
| // Delete it via Max-Age. |
| EXPECT_TRUE(this->SetCookie(cs, this->url_google_, |
| std::string(kValidCookieLine) + "; max-age=0")); |
| this->MatchCookieLineWithTimeout(cs, this->url_google_, ""); |
| |
| // Create a session cookie. |
| EXPECT_TRUE(this->SetCookie(cs, this->url_google_, kValidCookieLine)); |
| this->MatchCookieLines("A=B", this->GetCookies(cs, this->url_google_)); |
| // Delete it via Expires. |
| EXPECT_TRUE(this->SetCookie(cs, this->url_google_, |
| std::string(kValidCookieLine) + |
| "; expires=Mon, 18-Apr-1977 22:50:13 GMT")); |
| this->MatchCookieLines("", this->GetCookies(cs, this->url_google_)); |
| |
| // Create a persistent cookie. |
| EXPECT_TRUE(this->SetCookie(cs, this->url_google_, |
| std::string(kValidCookieLine) + |
| "; expires=Mon, 18-Apr-22 22:50:13 GMT")); |
| |
| this->MatchCookieLines("A=B", this->GetCookies(cs, this->url_google_)); |
| // Delete it via Max-Age. |
| EXPECT_TRUE(this->SetCookie(cs, this->url_google_, |
| std::string(kValidCookieLine) + "; max-age=0")); |
| this->MatchCookieLineWithTimeout(cs, this->url_google_, ""); |
| |
| // Create a persistent cookie. |
| EXPECT_TRUE(this->SetCookie(cs, this->url_google_, |
| std::string(kValidCookieLine) + |
| "; expires=Mon, 18-Apr-22 22:50:13 GMT")); |
| this->MatchCookieLines("A=B", this->GetCookies(cs, this->url_google_)); |
| // Delete it via Expires. |
| EXPECT_TRUE(this->SetCookie(cs, this->url_google_, |
| std::string(kValidCookieLine) + |
| "; expires=Mon, 18-Apr-1977 22:50:13 GMT")); |
| this->MatchCookieLines("", this->GetCookies(cs, this->url_google_)); |
| |
| // Create a persistent cookie. |
| EXPECT_TRUE(this->SetCookie(cs, this->url_google_, |
| std::string(kValidCookieLine) + |
| "; expires=Mon, 18-Apr-22 22:50:13 GMT")); |
| this->MatchCookieLines("A=B", this->GetCookies(cs, this->url_google_)); |
| // Check that it is not deleted with significant enough clock skew. |
| base::Time server_time; |
| EXPECT_TRUE(base::Time::FromString("Sun, 17-Apr-1977 22:50:13 GMT", |
| &server_time)); |
| EXPECT_TRUE(this->SetCookieWithServerTime( |
| cs, this->url_google_, |
| std::string(kValidCookieLine) + |
| "; expires=Mon, 18-Apr-1977 22:50:13 GMT", |
| server_time)); |
| this->MatchCookieLines("A=B", this->GetCookies(cs, this->url_google_)); |
| |
| // Create a persistent cookie. |
| EXPECT_TRUE(this->SetCookie(cs, this->url_google_, |
| std::string(kValidCookieLine) + |
| "; expires=Mon, 18-Apr-22 22:50:13 GMT")); |
| this->MatchCookieLines("A=B", this->GetCookies(cs, this->url_google_)); |
| // Delete it via Expires, with a unix epoch of 0. |
| EXPECT_TRUE(this->SetCookie(cs, this->url_google_, |
| std::string(kValidCookieLine) + |
| "; expires=Thu, 1-Jan-1970 00:00:00 GMT")); |
| this->MatchCookieLines("", this->GetCookies(cs, this->url_google_)); |
| } |
| |
| TYPED_TEST_P(CookieStoreTest, TestDeleteAllCreatedBetween) { |
| scoped_refptr<CookieStore> cs(this->GetCookieStore()); |
| const base::Time last_month = base::Time::Now() - |
| base::TimeDelta::FromDays(30); |
| const base::Time last_minute = base::Time::Now() - |
| base::TimeDelta::FromMinutes(1); |
| const base::Time next_minute = base::Time::Now() + |
| base::TimeDelta::FromMinutes(1); |
| const base::Time next_month = base::Time::Now() + |
| base::TimeDelta::FromDays(30); |
| |
| // Add a cookie. |
| EXPECT_TRUE(this->SetCookie(cs, this->url_google_, "A=B")); |
| // Check that the cookie is in the store. |
| this->MatchCookieLines("A=B", this->GetCookies(cs, this->url_google_)); |
| |
| // Remove cookies in empty intervals. |
| EXPECT_EQ(0, this->DeleteCreatedBetween(cs, last_month, last_minute)); |
| EXPECT_EQ(0, this->DeleteCreatedBetween(cs, next_minute, next_month)); |
| // Check that the cookie is still there. |
| this->MatchCookieLines("A=B", this->GetCookies(cs, this->url_google_)); |
| |
| // Remove the cookie with an interval defined by two dates. |
| EXPECT_EQ(1, this->DeleteCreatedBetween(cs, last_minute, next_minute)); |
| // Check that the cookie disappeared. |
| this->MatchCookieLines("", this->GetCookies(cs, this->url_google_)); |
| |
| // Add another cookie. |
| EXPECT_TRUE(this->SetCookie(cs, this->url_google_, "C=D")); |
| // Check that the cookie is in the store. |
| this->MatchCookieLines("C=D", this->GetCookies(cs, this->url_google_)); |
| |
| // Remove the cookie with a null ending time. |
| EXPECT_EQ(1, this->DeleteCreatedBetween(cs, last_minute, base::Time())); |
| // Check that the cookie disappeared. |
| this->MatchCookieLines("", this->GetCookies(cs, this->url_google_)); |
| } |
| |
| TYPED_TEST_P(CookieStoreTest, TestSecure) { |
| scoped_refptr<CookieStore> cs(this->GetCookieStore()); |
| |
| EXPECT_TRUE(this->SetCookie(cs, this->url_google_, "A=B")); |
| this->MatchCookieLines("A=B", this->GetCookies(cs, this->url_google_)); |
| this->MatchCookieLines("A=B", this->GetCookies(cs, this->url_google_secure_)); |
| |
| EXPECT_TRUE(this->SetCookie(cs, this->url_google_secure_, "A=B; secure")); |
| // The secure should overwrite the non-secure. |
| this->MatchCookieLines("", this->GetCookies(cs, this->url_google_)); |
| this->MatchCookieLines("A=B", this->GetCookies(cs, this->url_google_secure_)); |
| |
| EXPECT_TRUE(this->SetCookie(cs, this->url_google_secure_, "D=E; secure")); |
| this->MatchCookieLines("", this->GetCookies(cs, this->url_google_)); |
| this->MatchCookieLines("A=B; D=E", |
| this->GetCookies(cs, this->url_google_secure_)); |
| |
| EXPECT_TRUE(this->SetCookie(cs, this->url_google_secure_, "A=B")); |
| // The non-secure should overwrite the secure. |
| this->MatchCookieLines("A=B", this->GetCookies(cs, this->url_google_)); |
| this->MatchCookieLines("D=E; A=B", |
| this->GetCookies(cs, this->url_google_secure_)); |
| } |
| |
| static const int kLastAccessThresholdMilliseconds = 200; |
| |
| // Formerly NetUtilTest.CookieTest back when we used wininet's cookie handling. |
| TYPED_TEST_P(CookieStoreTest, NetUtilCookieTest) { |
| const GURL test_url("http://mojo.jojo.google.izzle/"); |
| |
| scoped_refptr<CookieStore> cs(this->GetCookieStore()); |
| |
| EXPECT_TRUE(this->SetCookie(cs, test_url, "foo=bar")); |
| std::string value = this->GetCookies(cs, test_url); |
| this->MatchCookieLines("foo=bar", value); |
| |
| // test that we can retrieve all cookies: |
| EXPECT_TRUE(this->SetCookie(cs, test_url, "x=1")); |
| EXPECT_TRUE(this->SetCookie(cs, test_url, "y=2")); |
| |
| std::string result = this->GetCookies(cs, test_url); |
| EXPECT_FALSE(result.empty()); |
| EXPECT_NE(result.find("x=1"), std::string::npos) << result; |
| EXPECT_NE(result.find("y=2"), std::string::npos) << result; |
| } |
| |
| TYPED_TEST_P(CookieStoreTest, OverwritePersistentCookie) { |
| GURL url_google("http://www.google.com/"); |
| GURL url_chromium("http://chromium.org"); |
| scoped_refptr<CookieStore> cs(this->GetCookieStore()); |
| |
| // Insert a cookie "a" for path "/path1" |
| EXPECT_TRUE( |
| this->SetCookie(cs, url_google, "a=val1; path=/path1; " |
| "expires=Mon, 18-Apr-22 22:50:13 GMT")); |
| |
| // Insert a cookie "b" for path "/path1" |
| EXPECT_TRUE( |
| this->SetCookie(cs, url_google, "b=val1; path=/path1; " |
| "expires=Mon, 18-Apr-22 22:50:14 GMT")); |
| |
| // Insert a cookie "b" for path "/path1", that is httponly. This should |
| // overwrite the non-http-only version. |
| CookieOptions allow_httponly; |
| allow_httponly.set_include_httponly(); |
| EXPECT_TRUE( |
| this->SetCookieWithOptions(cs, url_google, |
| "b=val2; path=/path1; httponly; " |
| "expires=Mon, 18-Apr-22 22:50:14 GMT", |
| allow_httponly)); |
| |
| // Insert a cookie "a" for path "/path1". This should overwrite. |
| EXPECT_TRUE(this->SetCookie(cs, url_google, |
| "a=val33; path=/path1; " |
| "expires=Mon, 18-Apr-22 22:50:14 GMT")); |
| |
| // Insert a cookie "a" for path "/path2". This should NOT overwrite |
| // cookie "a", since the path is different. |
| EXPECT_TRUE(this->SetCookie(cs, url_google, |
| "a=val9; path=/path2; " |
| "expires=Mon, 18-Apr-22 22:50:14 GMT")); |
| |
| // Insert a cookie "a" for path "/path1", but this time for "chromium.org". |
| // Although the name and path match, the hostnames do not, so shouldn't |
| // overwrite. |
| EXPECT_TRUE(this->SetCookie(cs, url_chromium, |
| "a=val99; path=/path1; " |
| "expires=Mon, 18-Apr-22 22:50:14 GMT")); |
| |
| if (TypeParam::supports_http_only) { |
| this->MatchCookieLines("a=val33", |
| this->GetCookies(cs, GURL("http://www.google.com/path1"))); |
| } else { |
| this->MatchCookieLines("a=val33; b=val2", |
| this->GetCookies(cs, GURL("http://www.google.com/path1"))); |
| } |
| this->MatchCookieLines("a=val9", |
| this->GetCookies(cs, GURL("http://www.google.com/path2"))); |
| this->MatchCookieLines("a=val99", |
| this->GetCookies(cs, GURL("http://chromium.org/path1"))); |
| } |
| |
| TYPED_TEST_P(CookieStoreTest, CookieOrdering) { |
| // Put a random set of cookies into a store and make sure they're returned in |
| // the right order. |
| // Cookies should be sorted by path length and creation time, as per RFC6265. |
| scoped_refptr<CookieStore> cs(this->GetCookieStore()); |
| EXPECT_TRUE(this->SetCookie(cs, GURL("http://d.c.b.a.google.com/aa/x.html"), |
| "c=1")); |
| EXPECT_TRUE(this->SetCookie(cs, GURL("http://b.a.google.com/aa/bb/cc/x.html"), |
| "d=1; domain=b.a.google.com")); |
| base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds( |
| TypeParam::creation_time_granularity_in_ms)); |
| EXPECT_TRUE(this->SetCookie(cs, GURL("http://b.a.google.com/aa/bb/cc/x.html"), |
| "a=4; domain=b.a.google.com")); |
| base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds( |
| TypeParam::creation_time_granularity_in_ms)); |
| EXPECT_TRUE(this->SetCookie(cs, |
| GURL("http://c.b.a.google.com/aa/bb/cc/x.html"), |
| "e=1; domain=c.b.a.google.com")); |
| EXPECT_TRUE(this->SetCookie(cs, |
| GURL("http://d.c.b.a.google.com/aa/bb/x.html"), |
| "b=1")); |
| EXPECT_TRUE(this->SetCookie(cs, GURL("http://news.bbc.co.uk/midpath/x.html"), |
| "g=10")); |
| EXPECT_EQ("d=1; a=4; e=1; b=1; c=1", |
| this->GetCookies(cs, GURL("http://d.c.b.a.google.com/aa/bb/cc/dd"))); |
| } |
| |
| REGISTER_TYPED_TEST_CASE_P(CookieStoreTest, |
| TypeTest, DomainTest, DomainWithTrailingDotTest, ValidSubdomainTest, |
| InvalidDomainTest, DomainWithoutLeadingDotTest, CaseInsensitiveDomainTest, |
| TestIpAddress, TestNonDottedAndTLD, TestHostEndsWithDot, InvalidScheme, |
| InvalidScheme_Read, PathTest, HttpOnlyTest, TestGetCookiesWithInfo, |
| TestCookieDeletion, TestDeleteAllCreatedBetween, TestSecure, |
| NetUtilCookieTest, OverwritePersistentCookie, CookieOrdering); |
| |
| template<class CookieStoreTestTraits> |
| class MultiThreadedCookieStoreTest : |
| public CookieStoreTest<CookieStoreTestTraits> { |
| public: |
| MultiThreadedCookieStoreTest() : other_thread_("CMTthread") {} |
| |
| // Helper methods for calling the asynchronous CookieStore methods |
| // from a different thread. |
| |
| void GetCookiesTask(CookieStore* cs, |
| const GURL& url, |
| GetCookieStringCallback* callback) { |
| CookieOptions options; |
| if (!CookieStoreTestTraits::supports_http_only) |
| options.set_include_httponly(); |
| cs->GetCookiesWithOptionsAsync( |
| url, options, |
| base::Bind(&GetCookieStringCallback::Run, base::Unretained(callback))); |
| } |
| |
| void GetCookiesWithOptionsTask(CookieStore* cs, |
| const GURL& url, |
| const CookieOptions& options, |
| GetCookieStringCallback* callback) { |
| cs->GetCookiesWithOptionsAsync( |
| url, options, |
| base::Bind(&GetCookieStringCallback::Run, base::Unretained(callback))); |
| } |
| |
| void GetCookiesWithInfoTask(CookieStore* cs, |
| const GURL& url, |
| const CookieOptions& options, |
| GetCookiesWithInfoCallback* callback) { |
| cs->GetCookiesWithInfoAsync( |
| url, options, |
| base::Bind(&GetCookiesWithInfoCallback::Run, |
| base::Unretained(callback))); |
| } |
| |
| void SetCookieWithOptionsTask(CookieStore* cs, |
| const GURL& url, |
| const std::string& cookie_line, |
| const CookieOptions& options, |
| SetCookieCallback* callback) { |
| cs->SetCookieWithOptionsAsync( |
| url, cookie_line, options, |
| base::Bind(&SetCookieCallback::Run, base::Unretained(callback))); |
| } |
| |
| void DeleteCookieTask(CookieStore* cs, |
| const GURL& url, |
| const std::string& cookie_name, |
| DeleteCookieCallback* callback) { |
| cs->DeleteCookieAsync( |
| url, cookie_name, |
| base::Bind(&DeleteCookieCallback::Run, base::Unretained(callback))); |
| } |
| |
| void DeleteSessionCookiesTask(CookieStore* cs, DeleteCallback* callback) { |
| cs->DeleteSessionCookiesAsync( |
| base::Bind(&DeleteCallback::Run, base::Unretained(callback))); |
| } |
| |
| protected: |
| void RunOnOtherThread(const base::Closure& task) { |
| other_thread_.Start(); |
| other_thread_.message_loop()->PostTask(FROM_HERE, task); |
| CookieStoreTest<CookieStoreTestTraits>::RunFor(kTimeout); |
| other_thread_.Stop(); |
| } |
| |
| Thread other_thread_; |
| }; |
| |
| TYPED_TEST_CASE_P(MultiThreadedCookieStoreTest); |
| |
| // TODO(ycxiao): Eventually, we will need to create a separate thread, create |
| // the cookie store on that thread (or at least its store, i.e., the DB |
| // thread). |
| TYPED_TEST_P(MultiThreadedCookieStoreTest, ThreadCheckGetCookies) { |
| scoped_refptr<CookieStore> cs(this->GetCookieStore()); |
| EXPECT_TRUE(this->SetCookie(cs, this->url_google_, "A=B")); |
| this->MatchCookieLines("A=B", this->GetCookies(cs, this->url_google_)); |
| GetCookieStringCallback callback(&this->other_thread_); |
| base::Closure task = base::Bind( |
| &net::MultiThreadedCookieStoreTest<TypeParam>::GetCookiesTask, |
| base::Unretained(this), |
| cs, this->url_google_, &callback); |
| this->RunOnOtherThread(task); |
| EXPECT_TRUE(callback.did_run()); |
| EXPECT_EQ("A=B", callback.cookie()); |
| } |
| |
| TYPED_TEST_P(MultiThreadedCookieStoreTest, ThreadCheckGetCookiesWithOptions) { |
| scoped_refptr<CookieStore> cs(this->GetCookieStore()); |
| CookieOptions options; |
| if (!TypeParam::supports_http_only) |
| options.set_include_httponly(); |
| EXPECT_TRUE(this->SetCookie(cs, this->url_google_, "A=B")); |
| this->MatchCookieLines("A=B", |
| this->GetCookiesWithOptions(cs, this->url_google_, options)); |
| GetCookieStringCallback callback(&this->other_thread_); |
| base::Closure task = base::Bind( |
| &net::MultiThreadedCookieStoreTest<TypeParam>::GetCookiesWithOptionsTask, |
| base::Unretained(this), |
| cs, this->url_google_, options, &callback); |
| this->RunOnOtherThread(task); |
| EXPECT_TRUE(callback.did_run()); |
| EXPECT_EQ("A=B", callback.cookie()); |
| } |
| |
| TYPED_TEST_P(MultiThreadedCookieStoreTest, ThreadCheckGetCookiesWithInfo) { |
| if (!TypeParam::supports_cookies_with_info) |
| return; |
| scoped_refptr<CookieStore> cs(this->GetCookieStore()); |
| CookieOptions options; |
| std::string cookie_line; |
| std::vector<CookieStore::CookieInfo> cookie_infos; |
| EXPECT_TRUE(this->SetCookie(cs, this->url_google_, "A=B")); |
| this->GetCookiesWithInfo(cs, this->url_google_, options, &cookie_line, |
| &cookie_infos); |
| this->MatchCookieLines("A=B", cookie_line); |
| EXPECT_EQ(1U, cookie_infos.size()); |
| EXPECT_EQ("A", cookie_infos[0].name); |
| EXPECT_EQ("", cookie_infos[0].mac_key); |
| EXPECT_EQ("", cookie_infos[0].mac_algorithm); |
| GetCookiesWithInfoCallback callback(&this->other_thread_); |
| base::Closure task = base::Bind( |
| &net::MultiThreadedCookieStoreTest<TypeParam>::GetCookiesWithInfoTask, |
| base::Unretained(this), cs, this->url_google_, options, &callback); |
| this->RunOnOtherThread(task); |
| EXPECT_TRUE(callback.did_run()); |
| this->MatchCookieLines("A=B", callback.cookie_line()); |
| EXPECT_EQ(1U, callback.cookie_info().size()); |
| EXPECT_EQ("A", callback.cookie_info()[0].name); |
| EXPECT_EQ("", callback.cookie_info()[0].mac_key); |
| EXPECT_EQ("", callback.cookie_info()[0].mac_algorithm); |
| } |
| |
| TYPED_TEST_P(MultiThreadedCookieStoreTest, ThreadCheckSetCookieWithOptions) { |
| scoped_refptr<CookieStore> cs(this->GetCookieStore()); |
| CookieOptions options; |
| if (!TypeParam::supports_http_only) |
| options.set_include_httponly(); |
| EXPECT_TRUE(this->SetCookieWithOptions(cs, this->url_google_, "A=B", |
| options)); |
| SetCookieCallback callback(&this->other_thread_); |
| base::Closure task = base::Bind( |
| &net::MultiThreadedCookieStoreTest<TypeParam>::SetCookieWithOptionsTask, |
| base::Unretained(this), |
| cs, this->url_google_, "A=B", options, &callback); |
| this->RunOnOtherThread(task); |
| EXPECT_TRUE(callback.did_run()); |
| EXPECT_TRUE(callback.result()); |
| } |
| |
| TYPED_TEST_P(MultiThreadedCookieStoreTest, ThreadCheckDeleteCookie) { |
| scoped_refptr<CookieStore> cs(this->GetCookieStore()); |
| CookieOptions options; |
| if (!TypeParam::supports_http_only) |
| options.set_include_httponly(); |
| EXPECT_TRUE(this->SetCookieWithOptions(cs, this->url_google_, "A=B", |
| options)); |
| this->DeleteCookie(cs, this->url_google_, "A"); |
| EXPECT_TRUE(this->SetCookieWithOptions(cs, this->url_google_, "A=B", |
| options)); |
| DeleteCookieCallback callback(&this->other_thread_); |
| base::Closure task = base::Bind( |
| &net::MultiThreadedCookieStoreTest<TypeParam>::DeleteCookieTask, |
| base::Unretained(this), |
| cs, this->url_google_, "A", &callback); |
| this->RunOnOtherThread(task); |
| EXPECT_TRUE(callback.did_run()); |
| } |
| |
| TYPED_TEST_P(MultiThreadedCookieStoreTest, ThreadCheckDeleteSessionCookies) { |
| scoped_refptr<CookieStore> cs(this->GetCookieStore()); |
| CookieOptions options; |
| if (!TypeParam::supports_http_only) |
| options.set_include_httponly(); |
| EXPECT_TRUE(this->SetCookieWithOptions(cs, this->url_google_, |
| "A=B", options)); |
| EXPECT_TRUE(this->SetCookieWithOptions(cs, this->url_google_, |
| "B=C; expires=Mon, 18-Apr-22 22:50:13 GMT", options)); |
| EXPECT_EQ(1, this->DeleteSessionCookies(cs)); |
| EXPECT_EQ(0, this->DeleteSessionCookies(cs)); |
| EXPECT_TRUE(this->SetCookieWithOptions(cs, this->url_google_, |
| "A=B", options)); |
| DeleteCallback callback(&this->other_thread_); |
| base::Closure task = base::Bind( |
| &net::MultiThreadedCookieStoreTest<TypeParam>::DeleteSessionCookiesTask, |
| base::Unretained(this), |
| cs, &callback); |
| this->RunOnOtherThread(task); |
| EXPECT_TRUE(callback.did_run()); |
| EXPECT_EQ(1, callback.num_deleted()); |
| } |
| |
| REGISTER_TYPED_TEST_CASE_P(MultiThreadedCookieStoreTest, |
| ThreadCheckGetCookies, ThreadCheckGetCookiesWithOptions, |
| ThreadCheckGetCookiesWithInfo, ThreadCheckSetCookieWithOptions, |
| ThreadCheckDeleteCookie, ThreadCheckDeleteSessionCookies); |
| |
| } // namespace net |
| |
| #endif // NET_COOKIES_COOKIE_STORE_UNITTEST_H_ |