diff options
author | Andras Becsi <andras.becsi@digia.com> | 2013-12-11 21:33:03 +0100 |
---|---|---|
committer | Andras Becsi <andras.becsi@digia.com> | 2013-12-13 12:34:07 +0100 |
commit | f2a33ff9cbc6d19943f1c7fbddd1f23d23975577 (patch) | |
tree | 0586a32aa390ade8557dfd6b4897f43a07449578 /chromium/net/cookies | |
parent | 5362912cdb5eea702b68ebe23702468d17c3017a (diff) | |
download | qtwebengine-chromium-f2a33ff9cbc6d19943f1c7fbddd1f23d23975577.tar.gz |
Update Chromium to branch 1650 (31.0.1650.63)
Change-Id: I57d8c832eaec1eb2364e0a8e7352a6dd354db99f
Reviewed-by: Jocelyn Turcotte <jocelyn.turcotte@digia.com>
Diffstat (limited to 'chromium/net/cookies')
-rw-r--r-- | chromium/net/cookies/cookie_monster.cc | 45 | ||||
-rw-r--r-- | chromium/net/cookies/cookie_monster.h | 16 | ||||
-rw-r--r-- | chromium/net/cookies/cookie_monster_perftest.cc | 28 | ||||
-rw-r--r-- | chromium/net/cookies/cookie_monster_unittest.cc | 41 | ||||
-rw-r--r-- | chromium/net/cookies/parsed_cookie.cc | 59 | ||||
-rw-r--r-- | chromium/net/cookies/parsed_cookie_unittest.cc | 71 |
6 files changed, 194 insertions, 66 deletions
diff --git a/chromium/net/cookies/cookie_monster.cc b/chromium/net/cookies/cookie_monster.cc index f24637735fd..65723ff20a6 100644 --- a/chromium/net/cookies/cookie_monster.cc +++ b/chromium/net/cookies/cookie_monster.cc @@ -112,6 +112,15 @@ const int CookieMonster::kSafeFromGlobalPurgeDays = 30; namespace { +bool ContainsControlCharacter(const std::string& s) { + for (std::string::const_iterator i = s.begin(); i != s.end(); ++i) { + if ((*i >= 0) && (*i <= 31)) + return true; + } + + return false; +} + typedef std::vector<CanonicalCookie*> CanonicalCookieVector; // Default minimum delay after updating a cookie's LastAccessDate before we @@ -286,6 +295,8 @@ ChangeCausePair ChangeCauseMapping[] = { { CookieMonster::Delegate::CHANGE_COOKIE_EVICTED, true }, // DELETE_COOKIE_EXPIRED_OVERWRITE { CookieMonster::Delegate::CHANGE_COOKIE_EXPIRED_OVERWRITE, true }, + // DELETE_COOKIE_CONTROL_CHAR + { CookieMonster::Delegate::CHANGE_COOKIE_EVICTED, true}, // DELETE_COOKIE_LAST_ENTRY { CookieMonster::Delegate::CHANGE_COOKIE_EXPLICIT, false } }; @@ -1477,16 +1488,24 @@ void CookieMonster::StoreLoadedCookies( // and sync'd. base::AutoLock autolock(lock_); + CookieItVector cookies_with_control_chars; + for (std::vector<CanonicalCookie*>::const_iterator it = cookies.begin(); it != cookies.end(); ++it) { int64 cookie_creation_time = (*it)->CreationDate().ToInternalValue(); if (creation_times_.insert(cookie_creation_time).second) { - InternalInsertCookie(GetKey((*it)->Domain()), *it, false); + CookieMap::iterator inserted = + InternalInsertCookie(GetKey((*it)->Domain()), *it, false); const Time cookie_access_time((*it)->LastAccessDate()); if (earliest_access_time_.is_null() || cookie_access_time < earliest_access_time_) earliest_access_time_ = cookie_access_time; + + if (ContainsControlCharacter((*it)->Name()) || + ContainsControlCharacter((*it)->Value())) { + cookies_with_control_chars.push_back(inserted); + } } else { LOG(ERROR) << base::StringPrintf("Found cookies with duplicate creation " "times in backing store: " @@ -1500,6 +1519,16 @@ void CookieMonster::StoreLoadedCookies( } } + // Any cookies that contain control characters that we have loaded from the + // persistent store should be deleted. See http://crbug.com/238041. + for (CookieItVector::iterator it = cookies_with_control_chars.begin(); + it != cookies_with_control_chars.end();) { + CookieItVector::iterator curit = it; + ++it; + + InternalDeleteCookie(*curit, true, DELETE_COOKIE_CONTROL_CHAR); + } + // After importing cookies from the PersistentCookieStore, verify that // none of our other constraints are violated. // In particular, the backing store might have given us duplicate cookies. @@ -1733,19 +1762,23 @@ bool CookieMonster::DeleteAnyEquivalentCookie(const std::string& key, return skipped_httponly; } -void CookieMonster::InternalInsertCookie(const std::string& key, - CanonicalCookie* cc, - bool sync_to_store) { +CookieMonster::CookieMap::iterator CookieMonster::InternalInsertCookie( + const std::string& key, + CanonicalCookie* cc, + bool sync_to_store) { lock_.AssertAcquired(); if ((cc->IsPersistent() || persist_session_cookies_) && store_.get() && sync_to_store) store_->AddCookie(*cc); - cookies_.insert(CookieMap::value_type(key, cc)); + CookieMap::iterator inserted = + cookies_.insert(CookieMap::value_type(key, cc)); if (delegate_.get()) { delegate_->OnCookieChanged( *cc, false, CookieMonster::Delegate::CHANGE_COOKIE_EXPLICIT); } + + return inserted; } bool CookieMonster::SetCookieWithCreationTimeAndOptions( @@ -1831,6 +1864,8 @@ void CookieMonster::InternalUpdateCookieAccessTime(CanonicalCookie* cc, store_->UpdateCookieAccessTime(*cc); } +// InternalDeleteCookies must not invalidate iterators other than the one being +// deleted. void CookieMonster::InternalDeleteCookie(CookieMap::iterator it, bool sync_to_store, DeletionCause deletion_cause) { diff --git a/chromium/net/cookies/cookie_monster.h b/chromium/net/cookies/cookie_monster.h index eaf89d33810..1df616cd6d9 100644 --- a/chromium/net/cookies/cookie_monster.h +++ b/chromium/net/cookies/cookie_monster.h @@ -379,6 +379,11 @@ class NET_EXPORT CookieMonster : public CookieStore { // already-expired expiration date. This captures that case. DELETE_COOKIE_EXPIRED_OVERWRITE, + // Cookies are not allowed to contain control characters in the name or + // value. However, we used to allow them, so we are now evicting any such + // cookies as we load them. See http://crbug.com/238041. + DELETE_COOKIE_CONTROL_CHAR, + DELETE_COOKIE_LAST_ENTRY }; @@ -517,10 +522,11 @@ class NET_EXPORT CookieMonster : public CookieStore { bool skip_httponly, bool already_expired); - // Takes ownership of *cc. - void InternalInsertCookie(const std::string& key, - CanonicalCookie* cc, - bool sync_to_store); + // Takes ownership of *cc. Returns an iterator that points to the inserted + // cookie in cookies_. Guarantee: all iterators to cookies_ remain valid. + CookieMap::iterator InternalInsertCookie(const std::string& key, + CanonicalCookie* cc, + bool sync_to_store); // Helper function that sets cookies with more control. // Not exposed as we don't want callers to have the ability @@ -541,6 +547,8 @@ class NET_EXPORT CookieMonster : public CookieStore { // |deletion_cause| argument is used for collecting statistics and choosing // the correct Delegate::ChangeCause for OnCookieChanged notifications. + // Guarantee: All iterators to cookies_ except to the deleted entry remain + // vaild. void InternalDeleteCookie(CookieMap::iterator it, bool sync_to_store, DeletionCause deletion_cause); diff --git a/chromium/net/cookies/cookie_monster_perftest.cc b/chromium/net/cookies/cookie_monster_perftest.cc index c70516f70eb..2bc0be8480c 100644 --- a/chromium/net/cookies/cookie_monster_perftest.cc +++ b/chromium/net/cookies/cookie_monster_perftest.cc @@ -6,9 +6,9 @@ #include "base/bind.h" #include "base/message_loop/message_loop.h" -#include "base/perftimer.h" #include "base/strings/string_util.h" #include "base/strings/stringprintf.h" +#include "base/test/perf_time_logger.h" #include "net/cookies/canonical_cookie.h" #include "net/cookies/cookie_monster.h" #include "net/cookies/cookie_monster_store_test.h" @@ -97,7 +97,7 @@ class GetCookiesCallback : public BaseCallback { TEST(ParsedCookieTest, TestParseCookies) { std::string cookie(kCookieLine); - PerfTimeLogger timer("Parsed_cookie_parse_cookies"); + base::PerfTimeLogger timer("Parsed_cookie_parse_cookies"); for (int i = 0; i < kNumCookies; ++i) { ParsedCookie pc(cookie); EXPECT_TRUE(pc.IsValid()); @@ -108,7 +108,7 @@ TEST(ParsedCookieTest, TestParseCookies) { TEST(ParsedCookieTest, TestParseBigCookies) { std::string cookie(3800, 'z'); cookie += kCookieLine; - PerfTimeLogger timer("Parsed_cookie_parse_big_cookies"); + base::PerfTimeLogger timer("Parsed_cookie_parse_big_cookies"); for (int i = 0; i < kNumCookies; ++i) { ParsedCookie pc(cookie); EXPECT_TRUE(pc.IsValid()); @@ -126,7 +126,7 @@ TEST_F(CookieMonsterTest, TestAddCookiesOnSingleHost) { SetCookieCallback setCookieCallback; // Add a bunch of cookies on a single host - PerfTimeLogger timer("Cookie_monster_add_single_host"); + base::PerfTimeLogger timer("Cookie_monster_add_single_host"); for (std::vector<std::string>::const_iterator it = cookies.begin(); it != cookies.end(); ++it) { @@ -136,14 +136,14 @@ TEST_F(CookieMonsterTest, TestAddCookiesOnSingleHost) { GetCookiesCallback getCookiesCallback; - PerfTimeLogger timer2("Cookie_monster_query_single_host"); + base::PerfTimeLogger timer2("Cookie_monster_query_single_host"); for (std::vector<std::string>::const_iterator it = cookies.begin(); it != cookies.end(); ++it) { getCookiesCallback.GetCookies(cm.get(), GURL(kGoogleURL)); } timer2.Done(); - PerfTimeLogger timer3("Cookie_monster_deleteall_single_host"); + base::PerfTimeLogger timer3("Cookie_monster_deleteall_single_host"); cm->DeleteAllAsync(CookieMonster::DeleteCallback()); base::MessageLoop::current()->RunUntilIdle(); timer3.Done(); @@ -160,7 +160,7 @@ TEST_F(CookieMonsterTest, TestAddCookieOnManyHosts) { SetCookieCallback setCookieCallback; // Add a cookie on a bunch of host - PerfTimeLogger timer("Cookie_monster_add_many_hosts"); + base::PerfTimeLogger timer("Cookie_monster_add_many_hosts"); for (std::vector<GURL>::const_iterator it = gurls.begin(); it != gurls.end(); ++it) { setCookieCallback.SetCookie(cm.get(), *it, cookie); @@ -169,14 +169,14 @@ TEST_F(CookieMonsterTest, TestAddCookieOnManyHosts) { GetCookiesCallback getCookiesCallback; - PerfTimeLogger timer2("Cookie_monster_query_many_hosts"); + base::PerfTimeLogger timer2("Cookie_monster_query_many_hosts"); for (std::vector<GURL>::const_iterator it = gurls.begin(); it != gurls.end(); ++it) { getCookiesCallback.GetCookies(cm.get(), *it); } timer2.Done(); - PerfTimeLogger timer3("Cookie_monster_deleteall_many_hosts"); + base::PerfTimeLogger timer3("Cookie_monster_deleteall_many_hosts"); cm->DeleteAllAsync(CookieMonster::DeleteCallback()); base::MessageLoop::current()->RunUntilIdle(); timer3.Done(); @@ -229,7 +229,7 @@ TEST_F(CookieMonsterTest, TestDomainTree) { std::string cookie_line = getCookiesCallback.GetCookies(cm.get(), probe_gurl); EXPECT_EQ(5, CountInString(cookie_line, '=')) << "Cookie line: " << cookie_line; - PerfTimeLogger timer("Cookie_monster_query_domain_tree"); + base::PerfTimeLogger timer("Cookie_monster_query_domain_tree"); for (int i = 0; i < kNumCookies; i++) { getCookiesCallback.GetCookies(cm.get(), probe_gurl); } @@ -269,7 +269,7 @@ TEST_F(CookieMonsterTest, TestDomainLine) { cookie_line = getCookiesCallback.GetCookies(cm.get(), probe_gurl); EXPECT_EQ(32, CountInString(cookie_line, '=')); - PerfTimeLogger timer2("Cookie_monster_query_domain_line"); + base::PerfTimeLogger timer2("Cookie_monster_query_domain_line"); for (int i = 0; i < kNumCookies; i++) { getCookiesCallback.GetCookies(cm.get(), probe_gurl); } @@ -304,7 +304,7 @@ TEST_F(CookieMonsterTest, TestImport) { // Import will happen on first access. GURL gurl("www.google.com"); CookieOptions options; - PerfTimeLogger timer("Cookie_monster_import_from_store"); + base::PerfTimeLogger timer("Cookie_monster_import_from_store"); getCookiesCallback.GetCookies(cm.get(), gurl); timer.Done(); @@ -314,7 +314,7 @@ TEST_F(CookieMonsterTest, TestImport) { TEST_F(CookieMonsterTest, TestGetKey) { scoped_refptr<CookieMonster> cm(new CookieMonster(NULL, NULL)); - PerfTimeLogger timer("Cookie_monster_get_key"); + base::PerfTimeLogger timer("Cookie_monster_get_key"); for (int i = 0; i < kNumCookies; i++) cm->GetKey("www.google.com"); timer.Done(); @@ -375,7 +375,7 @@ TEST_F(CookieMonsterTest, TestGCTimes) { // Trigger the Garbage collection we're allowed. setCookieCallback.SetCookie(cm.get(), gurl, cookie_line); - PerfTimeLogger timer((std::string("GC_") + test_case.name).c_str()); + base::PerfTimeLogger timer((std::string("GC_") + test_case.name).c_str()); for (int i = 0; i < kNumCookies; i++) setCookieCallback.SetCookie(cm.get(), gurl, cookie_line); timer.Done(); diff --git a/chromium/net/cookies/cookie_monster_unittest.cc b/chromium/net/cookies/cookie_monster_unittest.cc index d1ce04f3885..2bfe9ee9978 100644 --- a/chromium/net/cookies/cookie_monster_unittest.cc +++ b/chromium/net/cookies/cookie_monster_unittest.cc @@ -2685,4 +2685,45 @@ TEST_F(CookieMonsterTest, PersisentCookieStorageTest) { EXPECT_EQ(5u, store->commands().size()); } +// Test to assure that cookies with control characters are purged appropriately. +// See http://crbug.com/238041 for background. +TEST_F(CookieMonsterTest, ControlCharacterPurge) { + const Time now1(Time::Now()); + const Time now2(Time::Now() + TimeDelta::FromSeconds(1)); + const Time now3(Time::Now() + TimeDelta::FromSeconds(2)); + const Time later(now1 + TimeDelta::FromDays(1)); + const GURL url("http://host/path"); + const std::string domain("host"); + const std::string path("/path"); + + scoped_refptr<MockPersistentCookieStore> store( + new MockPersistentCookieStore); + + std::vector<CanonicalCookie*> initial_cookies; + + AddCookieToList(domain, + "foo=bar; path=" + path, + now1, + &initial_cookies); + + // We have to manually build this cookie because it contains a control + // character, and our cookie line parser rejects control characters. + CanonicalCookie *cc = new CanonicalCookie(url, "baz", "\x05" "boo", domain, + path, now2, later, now2, false, + false, COOKIE_PRIORITY_DEFAULT); + initial_cookies.push_back(cc); + + AddCookieToList(domain, + "hello=world; path=" + path, + now3, + &initial_cookies); + + // Inject our initial cookies into the mock PersistentCookieStore. + store->SetLoadExpectation(true, initial_cookies); + + scoped_refptr<CookieMonster> cm(new CookieMonster(store.get(), NULL)); + + EXPECT_EQ("foo=bar; hello=world", GetCookies(cm.get(), url)); +} + } // namespace net diff --git a/chromium/net/cookies/parsed_cookie.cc b/chromium/net/cookies/parsed_cookie.cc index 125d3d998b9..60e0bbb6618 100644 --- a/chromium/net/cookies/parsed_cookie.cc +++ b/chromium/net/cookies/parsed_cookie.cc @@ -45,20 +45,8 @@ #include "net/cookies/parsed_cookie.h" #include "base/logging.h" -#include "base/metrics/histogram.h" #include "base/strings/string_util.h" -// TODO(jww): We are collecting several UMA statistics in this file, and they -// relate to http://crbug.com/238041. We are measuring stats related to control -// characters in cookies because, currently, we allow control characters in a -// variety of scenarios where various RFCs theoretically disallow them. These -// control characters have the potential to cause problems with certain web -// servers that reject HTTP requests that contain cookies with control -// characters. We are measuring whether disallowing such cookies would have a -// notable impact on our users. We want to collect these stats through 1 stable -// release, so these UMA stats should remain at least through the M29 -// branch-point. - namespace { const char kPathTokenName[] = "path"; @@ -148,11 +136,15 @@ bool IsValidCookieValue(const std::string& value) { return true; } +bool IsControlCharacter(unsigned char c) { + return (c >= 0) && (c <= 31); +} + bool IsValidCookieAttributeValue(const std::string& value) { // The greatest common denominator of cookie attribute values is // <any CHAR except CTLs or ";"> according to RFC 6265. for (std::string::const_iterator i = value.begin(); i != value.end(); ++i) { - if ((*i >= 0 && *i <= 31) || *i == ';') + if (IsControlCharacter(*i) || *i == ';') return false; } return true; @@ -194,9 +186,7 @@ CookiePriority ParsedCookie::Priority() const { } bool ParsedCookie::SetName(const std::string& name) { - bool valid_token = IsValidToken(name); - UMA_HISTOGRAM_BOOLEAN("Cookie.SetNameVaildity", valid_token); - if (!valid_token) + if (!IsValidToken(name)) return false; if (pairs_.empty()) pairs_.push_back(std::make_pair("", "")); @@ -205,10 +195,7 @@ bool ParsedCookie::SetName(const std::string& name) { } bool ParsedCookie::SetValue(const std::string& value) { - bool valid_cookie_value = IsValidCookieValue(value); - UMA_HISTOGRAM_BOOLEAN("Cookie.SetValueCookieValueValidity", - valid_cookie_value); - if (!valid_cookie_value) + if (!IsValidCookieValue(value)) return false; if (pairs_.empty()) pairs_.push_back(std::make_pair("", "")); @@ -354,15 +341,6 @@ std::string ParsedCookie::ParseValueString(const std::string& value) { // Parse all token/value pairs and populate pairs_. void ParsedCookie::ParseTokenValuePairs(const std::string& cookie_line) { - enum ParsedCookieStatus { - PARSED_COOKIE_STATUS_NOTHING = 0x0, - PARSED_COOKIE_STATUS_CONTROL_CHAR = 0x1, - PARSED_COOKIE_STATUS_INVALID = 0x2, - PARSED_COOKIE_STATUS_BOTH = - PARSED_COOKIE_STATUS_CONTROL_CHAR | PARSED_COOKIE_STATUS_INVALID - }; - int parsed_cookie_status = PARSED_COOKIE_STATUS_NOTHING; - pairs_.clear(); // Ok, here we go. We should be expecting to be starting somewhere @@ -407,17 +385,21 @@ void ParsedCookie::ParseTokenValuePairs(const std::string& cookie_line) { // OK, now try to parse a value. std::string::const_iterator value_start, value_end; ParseValue(&it, end, &value_start, &value_end); + // OK, we're finished with a Token/Value. pair.second = std::string(value_start, value_end); - if (!IsValidCookieAttributeValue(pair.second)) - parsed_cookie_status |= PARSED_COOKIE_STATUS_CONTROL_CHAR; - if (!IsValidToken(pair.second)) - parsed_cookie_status |= PARSED_COOKIE_STATUS_INVALID; - // From RFC2109: "Attributes (names) (attr) are case-insensitive." if (pair_num != 0) StringToLowerASCII(&pair.first); + // Ignore Set-Cookie directives contaning control characters. See + // http://crbug.com/238041. + if (!IsValidCookieAttributeValue(pair.first) || + !IsValidCookieAttributeValue(pair.second)) { + pairs_.clear(); + break; + } + pairs_.push_back(pair); // We've processed a token/value pair, we're either at the end of @@ -425,9 +407,6 @@ void ParsedCookie::ParseTokenValuePairs(const std::string& cookie_line) { if (it != end) ++it; } - - UMA_HISTOGRAM_ENUMERATION("Cookie.ParsedCookieStatus", parsed_cookie_status, - PARSED_COOKIE_STATUS_BOTH + 1); } void ParsedCookie::SetupAttributes() { @@ -478,11 +457,7 @@ bool ParsedCookie::SetBool(size_t* index, bool ParsedCookie::SetAttributePair(size_t* index, const std::string& key, const std::string& value) { - bool valid_attribute_pair = IsValidToken(key) && - IsValidCookieAttributeValue(value); - UMA_HISTOGRAM_BOOLEAN("Cookie.SetAttributePairCharsValidity", - valid_attribute_pair); - if (!valid_attribute_pair) + if (!(IsValidToken(key) && IsValidCookieAttributeValue(value))) return false; if (!IsValid()) return false; diff --git a/chromium/net/cookies/parsed_cookie_unittest.cc b/chromium/net/cookies/parsed_cookie_unittest.cc index ad4aba65d79..23e3768afe6 100644 --- a/chromium/net/cookies/parsed_cookie_unittest.cc +++ b/chromium/net/cookies/parsed_cookie_unittest.cc @@ -422,4 +422,73 @@ TEST(ParsedCookieTest, SetPriority) { EXPECT_EQ(COOKIE_PRIORITY_DEFAULT, pc.Priority()); } -} // namespace net +TEST(ParsedCookieTest, InvalidNonAlphanumericChars) { + ParsedCookie pc1("name=\x05"); + ParsedCookie pc2("name=foo" "\x1c" "bar"); + ParsedCookie pc3("name=foobar" "\x11"); + ParsedCookie pc4("name=\x02" "foobar"); + + ParsedCookie pc5("\x05=value"); + ParsedCookie pc6("foo" "\x05" "bar=value"); + ParsedCookie pc7("foobar" "\x05" "=value"); + ParsedCookie pc8("\x05" "foobar" "=value"); + + ParsedCookie pc9("foo" "\x05" "bar" "=foo" "\x05" "bar"); + + ParsedCookie pc10("foo=bar;ba" "\x05" "z=boo"); + ParsedCookie pc11("foo=bar;baz=bo" "\x05" "o"); + ParsedCookie pc12("foo=bar;ba" "\05" "z=bo" "\x05" "o"); + + EXPECT_FALSE(pc1.IsValid()); + EXPECT_FALSE(pc2.IsValid()); + EXPECT_FALSE(pc3.IsValid()); + EXPECT_FALSE(pc4.IsValid()); + EXPECT_FALSE(pc5.IsValid()); + EXPECT_FALSE(pc6.IsValid()); + EXPECT_FALSE(pc7.IsValid()); + EXPECT_FALSE(pc8.IsValid()); + EXPECT_FALSE(pc9.IsValid()); + EXPECT_FALSE(pc10.IsValid()); + EXPECT_FALSE(pc11.IsValid()); + EXPECT_FALSE(pc12.IsValid()); +} + +TEST(ParsedCookieTest, ValidNonAlphanumericChars) { + // Note that some of these words are pasted backwords thanks to poor vim bidi + // support. This should not affect the tests, however. + const char* pc1_literal = "name=العربية"; + const char* pc2_literal = "name=普通話"; + const char* pc3_literal = "name=ภาษาไทย"; + const char* pc4_literal = "name=עִבְרִית"; + const char* pc5_literal = "العربية=value"; + const char* pc6_literal = "普通話=value"; + const char* pc7_literal = "ภาษาไทย=value"; + const char* pc8_literal = "עִבְרִית=value"; + ParsedCookie pc1(pc1_literal); + ParsedCookie pc2(pc2_literal); + ParsedCookie pc3(pc3_literal); + ParsedCookie pc4(pc4_literal); + ParsedCookie pc5(pc5_literal); + ParsedCookie pc6(pc6_literal); + ParsedCookie pc7(pc7_literal); + ParsedCookie pc8(pc8_literal); + + EXPECT_TRUE(pc1.IsValid()); + EXPECT_EQ(pc1_literal, pc1.ToCookieLine()); + EXPECT_TRUE(pc2.IsValid()); + EXPECT_EQ(pc2_literal, pc2.ToCookieLine()); + EXPECT_TRUE(pc3.IsValid()); + EXPECT_EQ(pc3_literal, pc3.ToCookieLine()); + EXPECT_TRUE(pc4.IsValid()); + EXPECT_EQ(pc4_literal, pc4.ToCookieLine()); + EXPECT_TRUE(pc5.IsValid()); + EXPECT_EQ(pc5_literal, pc5.ToCookieLine()); + EXPECT_TRUE(pc6.IsValid()); + EXPECT_EQ(pc6_literal, pc6.ToCookieLine()); + EXPECT_TRUE(pc7.IsValid()); + EXPECT_EQ(pc7_literal, pc7.ToCookieLine()); + EXPECT_TRUE(pc8.IsValid()); + EXPECT_EQ(pc8_literal, pc8.ToCookieLine()); +} + +} |