diff options
author | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2017-03-08 10:28:10 +0100 |
---|---|---|
committer | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2017-03-20 13:40:30 +0000 |
commit | e733310db58160074f574c429d48f8308c0afe17 (patch) | |
tree | f8aef4b7e62a69928dbcf880620eece20f98c6df /chromium/net/cookies | |
parent | 2f583e4aec1ae3a86fa047829c96b310dc12ecdf (diff) | |
download | qtwebengine-chromium-e733310db58160074f574c429d48f8308c0afe17.tar.gz |
BASELINE: Update Chromium to 56.0.2924.122
Change-Id: I4e04de8f47e47e501c46ed934c76a431c6337ced
Reviewed-by: Michael BrĂ¼ning <michael.bruning@qt.io>
Diffstat (limited to 'chromium/net/cookies')
-rw-r--r-- | chromium/net/cookies/canonical_cookie.cc | 3 | ||||
-rw-r--r-- | chromium/net/cookies/canonical_cookie.h | 2 | ||||
-rw-r--r-- | chromium/net/cookies/cookie_monster.cc | 101 | ||||
-rw-r--r-- | chromium/net/cookies/cookie_monster.h | 33 | ||||
-rw-r--r-- | chromium/net/cookies/cookie_monster_perftest.cc | 4 | ||||
-rw-r--r-- | chromium/net/cookies/cookie_monster_store_test.cc | 53 | ||||
-rw-r--r-- | chromium/net/cookies/cookie_monster_store_test.h | 29 | ||||
-rw-r--r-- | chromium/net/cookies/cookie_monster_unittest.cc | 47 | ||||
-rw-r--r-- | chromium/net/cookies/cookie_util.cc | 85 | ||||
-rw-r--r-- | chromium/net/cookies/cookie_util.h | 9 | ||||
-rw-r--r-- | chromium/net/cookies/cookie_util_unittest.cc | 186 |
11 files changed, 321 insertions, 231 deletions
diff --git a/chromium/net/cookies/canonical_cookie.cc b/chromium/net/cookies/canonical_cookie.cc index bbabbb771a4..de2fbbe6c65 100644 --- a/chromium/net/cookies/canonical_cookie.cc +++ b/chromium/net/cookies/canonical_cookie.cc @@ -157,7 +157,8 @@ Time CanonicalCookie::CanonExpiration(const ParsedCookie& pc, // Try the Expires attribute. if (pc.HasExpires() && !pc.Expires().empty()) { // Adjust for clock skew between server and host. - base::Time parsed_expiry = cookie_util::ParseCookieTime(pc.Expires()); + base::Time parsed_expiry = + cookie_util::ParseCookieExpirationTime(pc.Expires()); if (!parsed_expiry.is_null()) return parsed_expiry + (current - server_time); } diff --git a/chromium/net/cookies/canonical_cookie.h b/chromium/net/cookies/canonical_cookie.h index 4102299e425..2ef9131e1a6 100644 --- a/chromium/net/cookies/canonical_cookie.h +++ b/chromium/net/cookies/canonical_cookie.h @@ -139,6 +139,8 @@ class NET_EXPORT CanonicalCookie { std::string DebugString() const; static std::string CanonPath(const GURL& url, const ParsedCookie& pc); + + // Returns a "null" time if expiration was unspecified or invalid. static base::Time CanonExpiration(const ParsedCookie& pc, const base::Time& current, const base::Time& server_time); diff --git a/chromium/net/cookies/cookie_monster.cc b/chromium/net/cookies/cookie_monster.cc index 9925dbc1b97..b656d83e6c0 100644 --- a/chromium/net/cookies/cookie_monster.cc +++ b/chromium/net/cookies/cookie_monster.cc @@ -1006,7 +1006,7 @@ CookieMonster::AddCallbackForCookie(const GURL& gurl, std::pair<GURL, std::string> key(gurl, name); if (hook_map_.count(key) == 0) - hook_map_[key] = make_linked_ptr(new CookieChangedCallbackList()); + hook_map_[key] = base::MakeUnique<CookieChangedCallbackList>(); return hook_map_[key]->Add( base::Bind(&RunAsync, base::ThreadTaskRunnerHandle::Get(), callback)); } @@ -1094,15 +1094,14 @@ CookieList CookieMonster::GetAllCookies() { // sorter as elsewhere, then copy the result out. std::vector<CanonicalCookie*> cookie_ptrs; cookie_ptrs.reserve(cookies_.size()); - for (CookieMap::iterator it = cookies_.begin(); it != cookies_.end(); ++it) - cookie_ptrs.push_back(it->second); + for (const auto& cookie : cookies_) + cookie_ptrs.push_back(cookie.second.get()); std::sort(cookie_ptrs.begin(), cookie_ptrs.end(), CookieSorter); CookieList cookie_list; cookie_list.reserve(cookie_ptrs.size()); - for (std::vector<CanonicalCookie*>::const_iterator it = cookie_ptrs.begin(); - it != cookie_ptrs.end(); ++it) - cookie_list.push_back(**it); + for (const auto& cookie_ptr : cookie_ptrs) + cookie_list.push_back(*cookie_ptr); return cookie_list; } @@ -1135,7 +1134,7 @@ int CookieMonster::DeleteAllCreatedBetween(const Time& delete_begin, int num_deleted = 0; for (CookieMap::iterator it = cookies_.begin(); it != cookies_.end();) { CookieMap::iterator curit = it; - CanonicalCookie* cc = curit->second; + CanonicalCookie* cc = curit->second.get(); ++it; if (cc->CreationDate() >= delete_begin && @@ -1156,7 +1155,7 @@ int CookieMonster::DeleteAllCreatedBetweenWithPredicate( int num_deleted = 0; for (CookieMap::iterator it = cookies_.begin(); it != cookies_.end();) { CookieMap::iterator curit = it; - CanonicalCookie* cc = curit->second; + CanonicalCookie* cc = curit->second.get(); ++it; if (cc->CreationDate() >= delete_begin && @@ -1230,7 +1229,7 @@ void CookieMonster::DeleteCookie(const GURL& url, for (CookieMap::iterator it = cookies_.begin(); it != cookies_.end();) { CookieMap::iterator curit = it; ++it; - if (matching_cookies.find(curit->second) != matching_cookies.end()) { + if (matching_cookies.find(curit->second.get()) != matching_cookies.end()) { InternalDeleteCookie(curit, true, DELETE_COOKIE_EXPLICIT); } } @@ -1274,7 +1273,7 @@ int CookieMonster::DeleteSessionCookies() { int num_deleted = 0; for (CookieMap::iterator it = cookies_.begin(); it != cookies_.end();) { CookieMap::iterator curit = it; - CanonicalCookie* cc = curit->second; + CanonicalCookie* cc = curit->second.get(); ++it; if (!cc->IsPersistent()) { @@ -1332,21 +1331,23 @@ bool CookieMonster::ShouldFetchAllCookiesWhenFetchingAnyCookie() { return fetch_strategy_ == kAlwaysFetch; } -void CookieMonster::OnLoaded(TimeTicks beginning_time, - const std::vector<CanonicalCookie*>& cookies) { +void CookieMonster::OnLoaded( + TimeTicks beginning_time, + std::vector<std::unique_ptr<CanonicalCookie>> cookies) { DCHECK(thread_checker_.CalledOnValidThread()); - StoreLoadedCookies(cookies); + StoreLoadedCookies(std::move(cookies)); histogram_time_blocked_on_load_->AddTime(TimeTicks::Now() - beginning_time); // Invoke the task queue of cookie request. InvokeQueue(); } -void CookieMonster::OnKeyLoaded(const std::string& key, - const std::vector<CanonicalCookie*>& cookies) { +void CookieMonster::OnKeyLoaded( + const std::string& key, + std::vector<std::unique_ptr<CanonicalCookie>> cookies) { DCHECK(thread_checker_.CalledOnValidThread()); - StoreLoadedCookies(cookies); + StoreLoadedCookies(std::move(cookies)); auto tasks_pending_for_key = tasks_pending_for_key_.find(key); @@ -1372,7 +1373,7 @@ void CookieMonster::OnKeyLoaded(const std::string& key, } void CookieMonster::StoreLoadedCookies( - const std::vector<CanonicalCookie*>& cookies) { + std::vector<std::unique_ptr<CanonicalCookie>> cookies) { DCHECK(thread_checker_.CalledOnValidThread()); // TODO(erikwright): Remove ScopedTracker below once crbug.com/457528 is @@ -1385,20 +1386,20 @@ void CookieMonster::StoreLoadedCookies( // removed, and sync'd. CookieItVector cookies_with_control_chars; - for (std::vector<CanonicalCookie*>::const_iterator it = cookies.begin(); - it != cookies.end(); ++it) { - int64_t cookie_creation_time = (*it)->CreationDate().ToInternalValue(); + for (auto& cookie : cookies) { + int64_t cookie_creation_time = cookie->CreationDate().ToInternalValue(); if (creation_times_.insert(cookie_creation_time).second) { - CookieMap::iterator inserted = - InternalInsertCookie(GetKey((*it)->Domain()), *it, GURL(), false); - const Time cookie_access_time((*it)->LastAccessDate()); + CanonicalCookie* cookie_ptr = cookie.get(); + CookieMap::iterator inserted = InternalInsertCookie( + GetKey(cookie_ptr->Domain()), std::move(cookie), GURL(), false); + const Time cookie_access_time(cookie_ptr->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())) { + if (ContainsControlCharacter(cookie_ptr->Name()) || + ContainsControlCharacter(cookie_ptr->Value())) { cookies_with_control_chars.push_back(inserted); } } else { @@ -1406,11 +1407,8 @@ void CookieMonster::StoreLoadedCookies( "Found cookies with duplicate creation " "times in backing store: " "{name='%s', domain='%s', path='%s'}", - (*it)->Name().c_str(), (*it)->Domain().c_str(), - (*it)->Path().c_str()); - // We've been given ownership of the cookie and are throwing it - // away; reclaim the space. - delete (*it); + cookie->Name().c_str(), cookie->Domain().c_str(), + cookie->Path().c_str()); } } @@ -1498,7 +1496,7 @@ void CookieMonster::TrimDuplicateCookiesForKey(const std::string& key, // the equivalence map. for (CookieMap::iterator it = begin; it != end; ++it) { DCHECK_EQ(key, it->first); - CanonicalCookie* cookie = it->second; + CanonicalCookie* cookie = it->second.get(); CookieSignature signature(cookie->Name(), cookie->Domain(), cookie->Path()); CookieSet& set = equivalent_cookies[signature]; @@ -1582,7 +1580,7 @@ void CookieMonster::FindCookiesForKey(const std::string& key, for (CookieMapItPair its = cookies_.equal_range(key); its.first != its.second;) { CookieMap::iterator curit = its.first; - CanonicalCookie* cc = curit->second; + CanonicalCookie* cc = curit->second.get(); ++its.first; // If the cookie is expired, delete it. @@ -1623,7 +1621,7 @@ bool CookieMonster::DeleteAnyEquivalentCookie(const std::string& key, for (CookieMapItPair its = cookies_.equal_range(key); its.first != its.second;) { CookieMap::iterator curit = its.first; - CanonicalCookie* cc = curit->second; + CanonicalCookie* cc = curit->second.get(); ++its.first; // If strict secure cookies is being enforced, then the equivalency @@ -1674,25 +1672,28 @@ bool CookieMonster::DeleteAnyEquivalentCookie(const std::string& key, CookieMonster::CookieMap::iterator CookieMonster::InternalInsertCookie( const std::string& key, - CanonicalCookie* cc, + std::unique_ptr<CanonicalCookie> cc, const GURL& source_url, bool sync_to_store) { DCHECK(thread_checker_.CalledOnValidThread()); + CanonicalCookie* cc_ptr = cc.get(); - if ((cc->IsPersistent() || persist_session_cookies_) && store_.get() && + if ((cc_ptr->IsPersistent() || persist_session_cookies_) && store_.get() && sync_to_store) - store_->AddCookie(*cc); + store_->AddCookie(*cc_ptr); CookieMap::iterator inserted = - cookies_.insert(CookieMap::value_type(key, cc)); - if (delegate_.get()) - delegate_->OnCookieChanged(*cc, false, CookieStore::ChangeCause::INSERTED); + cookies_.insert(CookieMap::value_type(key, std::move(cc))); + if (delegate_.get()) { + delegate_->OnCookieChanged(*cc_ptr, false, + CookieStore::ChangeCause::INSERTED); + } // See InitializeHistograms() for details. - int32_t type_sample = cc->SameSite() != CookieSameSite::NO_RESTRICTION + int32_t type_sample = cc_ptr->SameSite() != CookieSameSite::NO_RESTRICTION ? 1 << COOKIE_TYPE_SAME_SITE : 0; - type_sample |= cc->IsHttpOnly() ? 1 << COOKIE_TYPE_HTTPONLY : 0; - type_sample |= cc->IsSecure() ? 1 << COOKIE_TYPE_SECURE : 0; + type_sample |= cc_ptr->IsHttpOnly() ? 1 << COOKIE_TYPE_HTTPONLY : 0; + type_sample |= cc_ptr->IsSecure() ? 1 << COOKIE_TYPE_SECURE : 0; histogram_cookie_type_->Add(type_sample); // Histogram the type of scheme used on URLs that set cookies. This @@ -1704,18 +1705,19 @@ CookieMonster::CookieMap::iterator CookieMonster::InternalInsertCookie( CookieSource cookie_source_sample; if (source_url.SchemeIsCryptographic()) { cookie_source_sample = - cc->IsSecure() ? COOKIE_SOURCE_SECURE_COOKIE_CRYPTOGRAPHIC_SCHEME - : COOKIE_SOURCE_NONSECURE_COOKIE_CRYPTOGRAPHIC_SCHEME; + cc_ptr->IsSecure() + ? COOKIE_SOURCE_SECURE_COOKIE_CRYPTOGRAPHIC_SCHEME + : COOKIE_SOURCE_NONSECURE_COOKIE_CRYPTOGRAPHIC_SCHEME; } else { cookie_source_sample = - cc->IsSecure() + cc_ptr->IsSecure() ? COOKIE_SOURCE_SECURE_COOKIE_NONCRYPTOGRAPHIC_SCHEME : COOKIE_SOURCE_NONSECURE_COOKIE_NONCRYPTOGRAPHIC_SCHEME; } histogram_cookie_source_scheme_->Add(cookie_source_sample); } - RunCookieChangedCallbacks(*cc, CookieStore::ChangeCause::INSERTED); + RunCookieChangedCallbacks(*cc_ptr, CookieStore::ChangeCause::INSERTED); return inserted; } @@ -1782,7 +1784,7 @@ bool CookieMonster::SetCanonicalCookie(std::unique_ptr<CanonicalCookie> cc, (cc->ExpiryDate() - creation_time).InMinutes()); } - InternalInsertCookie(key, cc.release(), source_url, true); + InternalInsertCookie(key, std::move(cc), source_url, true); } else { VLOG(kVlogSetCookies) << "SetCookie() not storing already expired cookie."; } @@ -1847,7 +1849,7 @@ void CookieMonster::InternalDeleteCookie(CookieMap::iterator it, if (deletion_cause != DELETE_COOKIE_DONT_RECORD) histogram_cookie_deletion_cause_->Add(deletion_cause); - CanonicalCookie* cc = it->second; + CanonicalCookie* cc = it->second.get(); VLOG(kVlogSetCookies) << "InternalDeleteCookie()" << ", cause:" << deletion_cause << ", cc: " << cc->DebugString(); @@ -1860,7 +1862,6 @@ void CookieMonster::InternalDeleteCookie(CookieMap::iterator it, delegate_->OnCookieChanged(*cc, true, mapping.cause); RunCookieChangedCallbacks(*cc, mapping.cause); cookies_.erase(it); - delete cc; } // Domain expiry behavior is unchanged by key/expiry scheme (the @@ -2045,7 +2046,7 @@ size_t CookieMonster::PurgeLeastRecentMatches(CookieItVector* cookies, size_t current = 0u; while ((removed < purge_goal && current < cookies->size()) && cookies_count_possibly_to_be_deleted > 0) { - const CanonicalCookie* current_cookie = cookies->at(current)->second; + const CanonicalCookie* current_cookie = cookies->at(current)->second.get(); // Only delete the current cookie if the priority is equal to // the current level. if (IsCookieEligibleForEviction(priority, protect_secure_cookies, diff --git a/chromium/net/cookies/cookie_monster.h b/chromium/net/cookies/cookie_monster.h index 087099c92b3..8dea3d32903 100644 --- a/chromium/net/cookies/cookie_monster.h +++ b/chromium/net/cookies/cookie_monster.h @@ -50,7 +50,7 @@ class CookieMonsterDelegate; // backing store. Otherwise, callbacks may be invoked immediately. // // A cookie task is either pending loading of the entire cookie store, or -// loading of cookies for a specfic domain key(eTLD+1). In the former case, the +// loading of cookies for a specific domain key(eTLD+1). In the former case, the // cookie task will be queued in tasks_pending_ while PersistentCookieStore // chain loads the cookie store on DB thread. In the latter case, the cookie // task will be queued in tasks_pending_for_key_ while PermanentCookieStore @@ -97,10 +97,11 @@ class NET_EXPORT CookieMonster : public CookieStore { // for the hashing might not overcome the O(log(1000)) for querying // a multimap. Also, multimap is standard, another reason to use it. // TODO(rdsmith): This benchmark should be re-done now that we're allowing - // subtantially more entries in the map. - typedef std::multimap<std::string, CanonicalCookie*> CookieMap; - typedef std::pair<CookieMap::iterator, CookieMap::iterator> CookieMapItPair; - typedef std::vector<CookieMap::iterator> CookieItVector; + // substantially more entries in the map. + using CookieMap = + std::multimap<std::string, std::unique_ptr<CanonicalCookie>>; + using CookieMapItPair = std::pair<CookieMap::iterator, CookieMap::iterator>; + using CookieItVector = std::vector<CookieMap::iterator>; // Cookie garbage collection thresholds. Based off of the Mozilla defaults. // When the number of cookies gets to k{Domain,}MaxCookies @@ -243,7 +244,7 @@ class NET_EXPORT CookieMonster : public CookieStore { CookieMonsterTest, TestCookieDeleteAllCreatedBetweenTimestampsWithPredicate); - // For gargage collection constants. + // For garbage collection constants. FRIEND_TEST_ALL_PREFIXES(CookieMonsterTest, TestHostGarbageCollection); FRIEND_TEST_ALL_PREFIXES(CookieMonsterTest, TestTotalGarbageCollection); FRIEND_TEST_ALL_PREFIXES(CookieMonsterTest, GarbageCollectionTriggers); @@ -451,7 +452,7 @@ class NET_EXPORT CookieMonster : public CookieStore { // was invoked and is used for reporting histogram_time_blocked_on_load_. // See PersistentCookieStore::Load for details on the contents of cookies. void OnLoaded(base::TimeTicks beginning_time, - const std::vector<CanonicalCookie*>& cookies); + std::vector<std::unique_ptr<CanonicalCookie>> cookies); // Stores cookies loaded from the backing store and invokes the deferred // task(s) pending loading of cookies associated with the domain key @@ -459,10 +460,11 @@ class NET_EXPORT CookieMonster : public CookieStore { // loaded from DB. See PersistentCookieStore::Load for details on the contents // of cookies. void OnKeyLoaded(const std::string& key, - const std::vector<CanonicalCookie*>& cookies); + std::vector<std::unique_ptr<CanonicalCookie>> cookies); // Stores the loaded cookies. - void StoreLoadedCookies(const std::vector<CanonicalCookie*>& cookies); + void StoreLoadedCookies( + std::vector<std::unique_ptr<CanonicalCookie>> cookies); // Invokes deferred calls. void InvokeQueue(); @@ -505,10 +507,10 @@ class NET_EXPORT CookieMonster : public CookieStore { bool already_expired, bool enforce_strict_secure); - // Takes ownership of *cc. Returns an iterator that points to the inserted + // Inserts |cc| into cookies_. 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, + std::unique_ptr<CanonicalCookie> cc, const GURL& source_url, bool sync_to_store); @@ -536,7 +538,7 @@ class NET_EXPORT CookieMonster : public CookieStore { // |deletion_cause| argument is used for collecting statistics and choosing // the correct CookieStore::ChangeCause for OnCookieChanged // notifications. Guarantee: All iterators to cookies_ except to the - // deleted entry remain vaild. + // deleted entry remain valid. void InternalDeleteCookie(CookieMap::iterator it, bool sync_to_store, DeletionCause deletion_cause); @@ -714,8 +716,9 @@ class NET_EXPORT CookieMonster : public CookieStore { bool persist_session_cookies_; - typedef std::map<std::pair<GURL, std::string>, - linked_ptr<CookieChangedCallbackList>> CookieChangedHookMap; + using CookieChangedHookMap = + std::map<std::pair<GURL, std::string>, + std::unique_ptr<CookieChangedCallbackList>>; CookieChangedHookMap hook_map_; base::ThreadChecker thread_checker_; @@ -754,7 +757,7 @@ typedef base::RefCountedThreadSafe<CookieMonster::PersistentCookieStore> class NET_EXPORT CookieMonster::PersistentCookieStore : public RefcountedPersistentCookieStore { public: - typedef base::Callback<void(const std::vector<CanonicalCookie*>&)> + typedef base::Callback<void(std::vector<std::unique_ptr<CanonicalCookie>>)> LoadedCallback; // TODO(erikchen): Depending on the results of the cookie monster Finch diff --git a/chromium/net/cookies/cookie_monster_perftest.cc b/chromium/net/cookies/cookie_monster_perftest.cc index 983f5ee2e54..eb9ce7b9435 100644 --- a/chromium/net/cookies/cookie_monster_perftest.cc +++ b/chromium/net/cookies/cookie_monster_perftest.cc @@ -282,7 +282,7 @@ TEST_F(CookieMonsterTest, TestDomainLine) { TEST_F(CookieMonsterTest, TestImport) { scoped_refptr<MockPersistentCookieStore> store(new MockPersistentCookieStore); - std::vector<CanonicalCookie*> initial_cookies; + std::vector<std::unique_ptr<CanonicalCookie>> initial_cookies; GetCookiesCallback getCookiesCallback; // We want to setup a fairly large backing store, with 300 domains of 50 @@ -300,7 +300,7 @@ TEST_F(CookieMonsterTest, TestImport) { } } - store->SetLoadExpectation(true, initial_cookies); + store->SetLoadExpectation(true, std::move(initial_cookies)); std::unique_ptr<CookieMonster> cm(new CookieMonster(store.get(), nullptr)); diff --git a/chromium/net/cookies/cookie_monster_store_test.cc b/chromium/net/cookies/cookie_monster_store_test.cc index 7a8af87c47e..1375134a16c 100644 --- a/chromium/net/cookies/cookie_monster_store_test.cc +++ b/chromium/net/cookies/cookie_monster_store_test.cc @@ -19,14 +19,6 @@ namespace net { -LoadedCallbackTask::LoadedCallbackTask(LoadedCallback loaded_callback, - std::vector<CanonicalCookie*> cookies) - : loaded_callback_(loaded_callback), cookies_(cookies) { -} - -LoadedCallbackTask::~LoadedCallbackTask() { -} - CookieStoreCommand::CookieStoreCommand( Type type, const CookieMonster::PersistentCookieStore::LoadedCallback& loaded_callback, @@ -46,9 +38,9 @@ MockPersistentCookieStore::MockPersistentCookieStore() void MockPersistentCookieStore::SetLoadExpectation( bool return_value, - const std::vector<CanonicalCookie*>& result) { + std::vector<std::unique_ptr<CanonicalCookie>> result) { load_return_value_ = return_value; - load_result_ = result; + load_result_.swap(result); } void MockPersistentCookieStore::Load(const LoadedCallback& loaded_callback) { @@ -57,15 +49,13 @@ void MockPersistentCookieStore::Load(const LoadedCallback& loaded_callback) { CookieStoreCommand(CookieStoreCommand::LOAD, loaded_callback, "")); return; } - std::vector<CanonicalCookie*> out_cookies; + std::vector<std::unique_ptr<CanonicalCookie>> out_cookies; if (load_return_value_) { - out_cookies = load_result_; + out_cookies.swap(load_result_); loaded_ = true; } base::ThreadTaskRunnerHandle::Get()->PostTask( - FROM_HERE, - base::Bind(&LoadedCallbackTask::Run, - new LoadedCallbackTask(loaded_callback, out_cookies))); + FROM_HERE, base::Bind(loaded_callback, base::Passed(&out_cookies))); } void MockPersistentCookieStore::LoadCookiesForKey( @@ -79,11 +69,9 @@ void MockPersistentCookieStore::LoadCookiesForKey( if (!loaded_) { Load(loaded_callback); } else { + std::vector<std::unique_ptr<CanonicalCookie>> empty_cookies; base::ThreadTaskRunnerHandle::Get()->PostTask( - FROM_HERE, - base::Bind(&LoadedCallbackTask::Run, - new LoadedCallbackTask(loaded_callback, - std::vector<CanonicalCookie*>()))); + FROM_HERE, base::Bind(loaded_callback, base::Passed(&empty_cookies))); } } @@ -137,9 +125,9 @@ std::unique_ptr<CanonicalCookie> BuildCanonicalCookie( // functions. Would be nice to export them, and re-use here. EXPECT_FALSE(pc.HasMaxAge()); EXPECT_TRUE(pc.HasPath()); - base::Time cookie_expires = pc.HasExpires() - ? cookie_util::ParseCookieTime(pc.Expires()) - : base::Time(); + base::Time cookie_expires = + pc.HasExpires() ? cookie_util::ParseCookieExpirationTime(pc.Expires()) + : base::Time(); std::string cookie_path = pc.Path(); return CanonicalCookie::Create(url, pc.Name(), pc.Value(), url.host(), @@ -151,11 +139,11 @@ std::unique_ptr<CanonicalCookie> BuildCanonicalCookie( void AddCookieToList(const GURL& url, const std::string& cookie_line, const base::Time& creation_time, - std::vector<CanonicalCookie*>* out_list) { + std::vector<std::unique_ptr<CanonicalCookie>>* out_list) { std::unique_ptr<CanonicalCookie> cookie( BuildCanonicalCookie(url, cookie_line, creation_time)); - out_list->push_back(cookie.release()); + out_list->push_back(std::move(cookie)); } MockSimplePersistentCookieStore::MockSimplePersistentCookieStore() @@ -164,16 +152,13 @@ MockSimplePersistentCookieStore::MockSimplePersistentCookieStore() void MockSimplePersistentCookieStore::Load( const LoadedCallback& loaded_callback) { - std::vector<CanonicalCookie*> out_cookies; + std::vector<std::unique_ptr<CanonicalCookie>> out_cookies; - for (CanonicalCookieMap::const_iterator it = cookies_.begin(); - it != cookies_.end(); it++) - out_cookies.push_back(new CanonicalCookie(it->second)); + for (auto it = cookies_.begin(); it != cookies_.end(); it++) + out_cookies.push_back(base::MakeUnique<CanonicalCookie>(it->second)); base::ThreadTaskRunnerHandle::Get()->PostTask( - FROM_HERE, - base::Bind(&LoadedCallbackTask::Run, - new LoadedCallbackTask(loaded_callback, out_cookies))); + FROM_HERE, base::Bind(loaded_callback, base::Passed(&out_cookies))); loaded_ = true; } @@ -183,11 +168,9 @@ void MockSimplePersistentCookieStore::LoadCookiesForKey( if (!loaded_) { Load(loaded_callback); } else { + std::vector<std::unique_ptr<CanonicalCookie>> empty_cookies; base::ThreadTaskRunnerHandle::Get()->PostTask( - FROM_HERE, - base::Bind(&LoadedCallbackTask::Run, - new LoadedCallbackTask(loaded_callback, - std::vector<CanonicalCookie*>()))); + FROM_HERE, base::Bind(loaded_callback, base::Passed(&empty_cookies))); } } diff --git a/chromium/net/cookies/cookie_monster_store_test.h b/chromium/net/cookies/cookie_monster_store_test.h index 835ec6d0520..29b063fd1aa 100644 --- a/chromium/net/cookies/cookie_monster_store_test.h +++ b/chromium/net/cookies/cookie_monster_store_test.h @@ -30,29 +30,6 @@ class Time; namespace net { -// Wrapper class for posting a loaded callback. Since the Callback class is not -// reference counted, we cannot post a callback to the message loop directly, -// instead we post a LoadedCallbackTask. -class LoadedCallbackTask - : public base::RefCountedThreadSafe<LoadedCallbackTask> { - public: - typedef CookieMonster::PersistentCookieStore::LoadedCallback LoadedCallback; - - LoadedCallbackTask(LoadedCallback loaded_callback, - std::vector<CanonicalCookie*> cookies); - - void Run() { loaded_callback_.Run(cookies_); } - - private: - friend class base::RefCountedThreadSafe<LoadedCallbackTask>; - ~LoadedCallbackTask(); - - LoadedCallback loaded_callback_; - std::vector<CanonicalCookie*> cookies_; - - DISALLOW_COPY_AND_ASSIGN(LoadedCallbackTask); -}; // Wrapper class LoadedCallbackTask - // Describes a call to one of the 5 functions of PersistentCookieStore. struct CookieStoreCommand { enum Type { @@ -107,7 +84,7 @@ class MockPersistentCookieStore : public CookieMonster::PersistentCookieStore { } void SetLoadExpectation(bool return_value, - const std::vector<CanonicalCookie*>& result); + std::vector<std::unique_ptr<CanonicalCookie>> result); const CommandList& commands() const { return commands_; } @@ -136,7 +113,7 @@ class MockPersistentCookieStore : public CookieMonster::PersistentCookieStore { // Deferred result to use when Load() is called. bool load_return_value_; - std::vector<CanonicalCookie*> load_result_; + std::vector<std::unique_ptr<CanonicalCookie>> load_result_; // Indicates if the store has been fully loaded to avoid returning duplicate // cookies. bool loaded_; @@ -177,7 +154,7 @@ std::unique_ptr<CanonicalCookie> BuildCanonicalCookie( void AddCookieToList(const GURL& url, const std::string& cookie_line, const base::Time& creation_time, - std::vector<CanonicalCookie*>* out_list); + std::vector<std::unique_ptr<CanonicalCookie>>* out_list); // Just act like a backing database. Keep cookie information from // Add/Update/Delete and regurgitate it when Load is called. diff --git a/chromium/net/cookies/cookie_monster_unittest.cc b/chromium/net/cookies/cookie_monster_unittest.cc index 9414fe11d4c..2c5ae97212b 100644 --- a/chromium/net/cookies/cookie_monster_unittest.cc +++ b/chromium/net/cookies/cookie_monster_unittest.cc @@ -974,11 +974,11 @@ class DeferredCookieTaskTest : public CookieMonsterTest { // and PersistentCookieStore::Load completion callback. void CompleteLoading() { while (!loaded_for_key_callbacks_.empty()) { - loaded_for_key_callbacks_.front().Run(loaded_cookies_); + loaded_for_key_callbacks_.front().Run(std::move(loaded_cookies_)); loaded_cookies_.clear(); loaded_for_key_callbacks_.pop(); } - loaded_callback_.Run(loaded_cookies_); + loaded_callback_.Run(std::move(loaded_cookies_)); } // Performs the provided action, expecting it to cause a call to @@ -1027,7 +1027,7 @@ class DeferredCookieTaskTest : public CookieMonsterTest { testing::InSequence in_sequence_; // Holds cookies to be returned from PersistentCookieStore::Load or // PersistentCookieStore::LoadCookiesForKey. - std::vector<CanonicalCookie*> loaded_cookies_; + std::vector<std::unique_ptr<CanonicalCookie>> loaded_cookies_; // Stores the callback passed from the CookieMonster to the // PersistentCookieStore::Load CookieMonster::PersistentCookieStore::LoadedCallback loaded_callback_; @@ -1310,7 +1310,7 @@ TEST_F(DeferredCookieTaskTest, } TEST_F(DeferredCookieTaskTest, DeferredDeleteCanonicalCookie) { - std::vector<CanonicalCookie*> cookies; + std::vector<std::unique_ptr<CanonicalCookie>> cookies; std::unique_ptr<CanonicalCookie> cookie = BuildCanonicalCookie( http_www_google_.url(), "X=1; path=/", base::Time::Now()); @@ -1789,7 +1789,7 @@ TEST_F(CookieMonsterTest, DontImportDuplicateCookies) { // be careful not to have any duplicate creation times at all (as it's a // violation of a CookieMonster invariant) even if Time::Now() doesn't // move between calls. - std::vector<CanonicalCookie*> initial_cookies; + std::vector<std::unique_ptr<CanonicalCookie>> initial_cookies; // Insert 4 cookies with name "X" on path "/", with varying creation // dates. We expect only the most recent one to be preserved following @@ -1830,7 +1830,7 @@ TEST_F(CookieMonsterTest, DontImportDuplicateCookies) { Time::Now() + TimeDelta::FromDays(10), &initial_cookies); // Inject our initial cookies into the mock PersistentCookieStore. - store->SetLoadExpectation(true, initial_cookies); + store->SetLoadExpectation(true, std::move(initial_cookies)); std::unique_ptr<CookieMonster> cm(new CookieMonster(store.get(), nullptr)); @@ -1866,7 +1866,7 @@ TEST_F(CookieMonsterTest, DontImportDuplicateCreationTimes) { // four with the earlier time as creation times. We should only get // two cookies remaining, but which two (other than that there should // be one from each set) will be random. - std::vector<CanonicalCookie*> initial_cookies; + std::vector<std::unique_ptr<CanonicalCookie>> initial_cookies; AddCookieToList(GURL("http://www.google.com"), "X=1; path=/", now, &initial_cookies); AddCookieToList(GURL("http://www.google.com"), "X=2; path=/", now, @@ -1886,7 +1886,7 @@ TEST_F(CookieMonsterTest, DontImportDuplicateCreationTimes) { &initial_cookies); // Inject our initial cookies into the mock PersistentCookieStore. - store->SetLoadExpectation(true, initial_cookies); + store->SetLoadExpectation(true, std::move(initial_cookies)); std::unique_ptr<CookieMonster> cm(new CookieMonster(store.get(), nullptr)); @@ -2301,7 +2301,8 @@ TEST_F(CookieMonsterTest, WhileLoadingLoadCompletesBeforeKeyLoadCompletes) { store->commands()[1].type); // The main load completes first (With no cookies). - store->commands()[0].loaded_callback.Run(std::vector<CanonicalCookie*>()); + store->commands()[0].loaded_callback.Run( + std::vector<std::unique_ptr<CanonicalCookie>>()); // The tasks should run in order, and the get should see the cookies. @@ -2313,7 +2314,8 @@ TEST_F(CookieMonsterTest, WhileLoadingLoadCompletesBeforeKeyLoadCompletes) { // The loaded for key event completes late, with not cookies (Since they // were already loaded). - store->commands()[1].loaded_callback.Run(std::vector<CanonicalCookie*>()); + store->commands()[1].loaded_callback.Run( + std::vector<std::unique_ptr<CanonicalCookie>>()); // The just set cookie should still be in the store. GetCookieListCallback get_cookie_list_callback2; @@ -2348,14 +2350,13 @@ TEST_F(CookieMonsterTest, WhileLoadingDeleteAllGetForURL) { ASSERT_EQ(1u, store->commands().size()); ASSERT_EQ(CookieStoreCommand::LOAD, store->commands()[0].type); - std::vector<CanonicalCookie*> cookies; + std::vector<std::unique_ptr<CanonicalCookie>> cookies; // When passed to the CookieMonster, it takes ownership of the pointed to // cookies. cookies.push_back( - CanonicalCookie::Create(kUrl, "a=b", base::Time(), CookieOptions()) - .release()); + CanonicalCookie::Create(kUrl, "a=b", base::Time(), CookieOptions())); ASSERT_TRUE(cookies[0]); - store->commands()[0].loaded_callback.Run(cookies); + store->commands()[0].loaded_callback.Run(std::move(cookies)); delete_callback.WaitUntilDone(); EXPECT_EQ(1, delete_callback.result()); @@ -2396,7 +2397,8 @@ TEST_F(CookieMonsterTest, WhileLoadingGetAllSetGetAll) { ASSERT_EQ(CookieStoreCommand::LOAD, store->commands()[0].type); // The load completes (With no cookies). - store->commands()[0].loaded_callback.Run(std::vector<CanonicalCookie*>()); + store->commands()[0].loaded_callback.Run( + std::vector<std::unique_ptr<CanonicalCookie>>()); get_cookie_list_callback1.WaitUntilDone(); EXPECT_EQ(0u, get_cookie_list_callback1.cookies().size()); @@ -2448,7 +2450,8 @@ TEST_F(CookieMonsterTest, CheckOrderOfCookieTaskQueueWhenLoadingCompletes) { ASSERT_EQ(CookieStoreCommand::LOAD, store->commands()[0].type); // The load completes. - store->commands()[0].loaded_callback.Run(std::vector<CanonicalCookie*>()); + store->commands()[0].loaded_callback.Run( + std::vector<std::unique_ptr<CanonicalCookie>>()); // The get cookies call should see no cookies set. get_cookie_list_callback1.WaitUntilDone(); @@ -2474,11 +2477,9 @@ class FlushablePersistentStore : public CookieMonster::PersistentCookieStore { FlushablePersistentStore() : flush_count_(0) {} void Load(const LoadedCallback& loaded_callback) override { - std::vector<CanonicalCookie*> out_cookies; + std::vector<std::unique_ptr<CanonicalCookie>> out_cookies; base::ThreadTaskRunnerHandle::Get()->PostTask( - FROM_HERE, - base::Bind(&LoadedCallbackTask::Run, - new LoadedCallbackTask(loaded_callback, out_cookies))); + FROM_HERE, base::Bind(loaded_callback, base::Passed(&out_cookies))); } void LoadCookiesForKey(const std::string& key, @@ -2881,7 +2882,7 @@ TEST_F(CookieMonsterTest, ControlCharacterPurge) { scoped_refptr<MockPersistentCookieStore> store(new MockPersistentCookieStore); - std::vector<CanonicalCookie*> initial_cookies; + std::vector<std::unique_ptr<CanonicalCookie>> initial_cookies; AddCookieToList(url, "foo=bar; path=" + path, now1, &initial_cookies); @@ -2893,12 +2894,12 @@ TEST_F(CookieMonsterTest, ControlCharacterPurge) { "boo", domain, path, now2, later, false, false, CookieSameSite::DEFAULT_MODE, false, COOKIE_PRIORITY_DEFAULT); - initial_cookies.push_back(cc.release()); + initial_cookies.push_back(std::move(cc)); AddCookieToList(url, "hello=world; path=" + path, now3, &initial_cookies); // Inject our initial cookies into the mock PersistentCookieStore. - store->SetLoadExpectation(true, initial_cookies); + store->SetLoadExpectation(true, std::move(initial_cookies)); std::unique_ptr<CookieMonster> cm(new CookieMonster(store.get(), nullptr)); diff --git a/chromium/net/cookies/cookie_util.cc b/chromium/net/cookies/cookie_util.cc index 210b8d479af..a1b274b39b0 100644 --- a/chromium/net/cookies/cookie_util.cc +++ b/chromium/net/cookies/cookie_util.cc @@ -18,6 +18,77 @@ namespace net { namespace cookie_util { +namespace { + +base::Time MinNonNullTime() { + return base::Time::FromInternalValue(1); +} + +// Tries to assemble a base::Time given a base::Time::Exploded representing a +// UTC calendar date. +// +// If the date falls outside of the range supported internally by +// FromUTCExploded() on the current platform, then the result is: +// +// * Time(1) if it's below the range FromUTCExploded() supports. +// * Time::Max() if it's above the range FromUTCExploded() supports. +bool SaturatedTimeFromUTCExploded(const base::Time::Exploded& exploded, + base::Time* out) { + // Try to calculate the base::Time in the normal fashion. + if (base::Time::FromUTCExploded(exploded, out)) { + // Don't return Time(0) on success. + if (out->is_null()) + *out = MinNonNullTime(); + return true; + } + + // base::Time::FromUTCExploded() has platform-specific limits: + // + // * Windows: Years 1601 - 30827 + // * 32-bit POSIX: Years 1970 - 2038 + // + // Work around this by returning min/max valid times for times outside those + // ranges when imploding the time is doomed to fail. + // + // Note that the following implementation is NOT perfect. It will accept + // some invalid calendar dates in the out-of-range case. + if (!exploded.HasValidValues()) + return false; +#if defined(OS_POSIX) && !defined(OS_MACOSX) + // Allow dates prior to unix epoch (which fail on non-Mac/iOS POSIX). + if (exploded.year < 1970) { + *out = MinNonNullTime(); + return true; + } + + // On 32-bit non-Mac/iOS POSIX systems, the time_t value that FromExploded() + // returns overflows in the middle of year 2038. In that case, return + // Time::Max(). + if (sizeof(time_t) == 4u && exploded.year >= 2038) { + *out = base::Time::Max(); + return true; + } +#endif // defined(OS_POSIX) && !defined(OS_MACOSX) + +#if defined(OS_WIN) + // Allow dates prior to Windows epoch. + if (exploded.year < 1601) { + *out = MinNonNullTime(); + return true; + } + + // Allow dates after the Windows epoch. + if (exploded.year >= 30827) { + *out = base::Time::Max(); + return true; + } +#endif // defined(OS_WIN) + + return false; +} + +} // namespace + bool DomainIsHostOnly(const std::string& domain_string) { return (domain_string.empty() || domain_string[0] != '.'); } @@ -103,7 +174,7 @@ bool GetCookieDomainWithString(const GURL& url, // - The time must be of the format hh:mm:ss. // An average cookie expiration will look something like this: // Sat, 15-Apr-17 21:01:22 GMT -base::Time ParseCookieTime(const std::string& time_string) { +base::Time ParseCookieExpirationTime(const std::string& time_string) { static const char* const kMonths[] = { "jan", "feb", "mar", "apr", "may", "jun", "jul", "aug", "sep", "oct", "nov", "dec" }; @@ -200,13 +271,11 @@ base::Time ParseCookieTime(const std::string& time_string) { if (exploded.year >= 0 && exploded.year <= 68) exploded.year += 2000; - // If our values are within their correct ranges, we got our time. - if (exploded.day_of_month >= 1 && exploded.day_of_month <= 31 && - exploded.month >= 1 && exploded.month <= 12 && - exploded.year >= 1601 && exploded.year <= 30827 && - exploded.hour <= 23 && exploded.minute <= 59 && exploded.second <= 59) { - return base::Time::FromUTCExploded(exploded); - } + // Note that clipping the date if it is outside of a platform-specific range + // is permitted by: https://tools.ietf.org/html/rfc6265#section-5.2.1 + base::Time result; + if (SaturatedTimeFromUTCExploded(exploded, &result)) + return result; // One of our values was out of expected range. For well-formed input, // the following check would be reasonable: diff --git a/chromium/net/cookies/cookie_util.h b/chromium/net/cookies/cookie_util.h index 0bf1452af86..60e5f661cd4 100644 --- a/chromium/net/cookies/cookie_util.h +++ b/chromium/net/cookies/cookie_util.h @@ -37,8 +37,13 @@ NET_EXPORT bool GetCookieDomainWithString(const GURL& url, // i.e. it doesn't begin with a leading '.' character. NET_EXPORT bool DomainIsHostOnly(const std::string& domain_string); -// Parses the string with the cookie time (very forgivingly). -NET_EXPORT base::Time ParseCookieTime(const std::string& time_string); +// Parses the string with the cookie expiration time (very forgivingly). +// Returns the "null" time on failure. +// +// If the expiration date is below or above the platform-specific range +// supported by Time::FromUTCExplodeded(), then this will return Time(1) or +// Time::Max(), respectively. +NET_EXPORT base::Time ParseCookieExpirationTime(const std::string& time_string); // Convenience for converting a cookie origin (domain and https pair) to a URL. NET_EXPORT GURL CookieOriginToURL(const std::string& domain, bool is_https); diff --git a/chromium/net/cookies/cookie_util_unittest.cc b/chromium/net/cookies/cookie_util_unittest.cc index 5414be1e4dd..8ca3acafe43 100644 --- a/chromium/net/cookies/cookie_util_unittest.cc +++ b/chromium/net/cookies/cookie_util_unittest.cc @@ -63,79 +63,81 @@ TEST(CookieUtilTest, TestCookieDateParsing) { const bool valid; const time_t epoch; } tests[] = { - { "Sat, 15-Apr-17 21:01:22 GMT", true, 1492290082 }, - { "Thu, 19-Apr-2007 16:00:00 GMT", true, 1176998400 }, - { "Wed, 25 Apr 2007 21:02:13 GMT", true, 1177534933 }, - { "Thu, 19/Apr\\2007 16:00:00 GMT", true, 1176998400 }, - { "Fri, 1 Jan 2010 01:01:50 GMT", true, 1262307710 }, - { "Wednesday, 1-Jan-2003 00:00:00 GMT", true, 1041379200 }, - { ", 1-Jan-2003 00:00:00 GMT", true, 1041379200 }, - { " 1-Jan-2003 00:00:00 GMT", true, 1041379200 }, - { "1-Jan-2003 00:00:00 GMT", true, 1041379200 }, - { "Wed,18-Apr-07 22:50:12 GMT", true, 1176936612 }, - { "WillyWonka , 18-Apr-07 22:50:12 GMT", true, 1176936612 }, - { "WillyWonka , 18-Apr-07 22:50:12", true, 1176936612 }, - { "WillyWonka , 18-apr-07 22:50:12", true, 1176936612 }, - { "Mon, 18-Apr-1977 22:50:13 GMT", true, 230251813 }, - { "Mon, 18-Apr-77 22:50:13 GMT", true, 230251813 }, - // If the cookie came in with the expiration quoted (which in terms of - // the RFC you shouldn't do), we will get string quoted. Bug 1261605. - { "\"Sat, 15-Apr-17\\\"21:01:22\\\"GMT\"", true, 1492290082 }, - // Test with full month names and partial names. - { "Partyday, 18- April-07 22:50:12", true, 1176936612 }, - { "Partyday, 18 - Apri-07 22:50:12", true, 1176936612 }, - { "Wednes, 1-Januar-2003 00:00:00 GMT", true, 1041379200 }, - // Test that we always take GMT even with other time zones or bogus - // values. The RFC says everything should be GMT, and in the worst case - // we are 24 hours off because of zone issues. - { "Sat, 15-Apr-17 21:01:22", true, 1492290082 }, - { "Sat, 15-Apr-17 21:01:22 GMT-2", true, 1492290082 }, - { "Sat, 15-Apr-17 21:01:22 GMT BLAH", true, 1492290082 }, - { "Sat, 15-Apr-17 21:01:22 GMT-0400", true, 1492290082 }, - { "Sat, 15-Apr-17 21:01:22 GMT-0400 (EDT)",true, 1492290082 }, - { "Sat, 15-Apr-17 21:01:22 DST", true, 1492290082 }, - { "Sat, 15-Apr-17 21:01:22 -0400", true, 1492290082 }, - { "Sat, 15-Apr-17 21:01:22 (hello there)", true, 1492290082 }, - // Test that if we encounter multiple : fields, that we take the first - // that correctly parses. - { "Sat, 15-Apr-17 21:01:22 11:22:33", true, 1492290082 }, - { "Sat, 15-Apr-17 ::00 21:01:22", true, 1492290082 }, - { "Sat, 15-Apr-17 boink:z 21:01:22", true, 1492290082 }, - // We take the first, which in this case is invalid. - { "Sat, 15-Apr-17 91:22:33 21:01:22", false, 0 }, - // amazon.com formats their cookie expiration like this. - { "Thu Apr 18 22:50:12 2007 GMT", true, 1176936612 }, - // Test that hh:mm:ss can occur anywhere. - { "22:50:12 Thu Apr 18 2007 GMT", true, 1176936612 }, - { "Thu 22:50:12 Apr 18 2007 GMT", true, 1176936612 }, - { "Thu Apr 22:50:12 18 2007 GMT", true, 1176936612 }, - { "Thu Apr 18 22:50:12 2007 GMT", true, 1176936612 }, - { "Thu Apr 18 2007 22:50:12 GMT", true, 1176936612 }, - { "Thu Apr 18 2007 GMT 22:50:12", true, 1176936612 }, - // Test that the day and year can be anywhere if they are unambigious. - { "Sat, 15-Apr-17 21:01:22 GMT", true, 1492290082 }, - { "15-Sat, Apr-17 21:01:22 GMT", true, 1492290082 }, - { "15-Sat, Apr 21:01:22 GMT 17", true, 1492290082 }, - { "15-Sat, Apr 21:01:22 GMT 2017", true, 1492290082 }, - { "15 Apr 21:01:22 2017", true, 1492290082 }, - { "15 17 Apr 21:01:22", true, 1492290082 }, - { "Apr 15 17 21:01:22", true, 1492290082 }, - { "Apr 15 21:01:22 17", true, 1492290082 }, - { "2017 April 15 21:01:22", true, 1492290082 }, - { "15 April 2017 21:01:22", true, 1492290082 }, - // Some invalid dates - { "98 April 17 21:01:22", false, 0 }, - { "Thu, 012-Aug-2008 20:49:07 GMT", false, 0 }, - { "Thu, 12-Aug-31841 20:49:07 GMT", false, 0 }, - { "Thu, 12-Aug-9999999999 20:49:07 GMT", false, 0 }, - { "Thu, 999999999999-Aug-2007 20:49:07 GMT", false, 0 }, - { "Thu, 12-Aug-2007 20:61:99999999999 GMT", false, 0 }, - { "IAintNoDateFool", false, 0 }, + {"Sat, 15-Apr-17 21:01:22 GMT", true, 1492290082}, + {"Thu, 19-Apr-2007 16:00:00 GMT", true, 1176998400}, + {"Wed, 25 Apr 2007 21:02:13 GMT", true, 1177534933}, + {"Thu, 19/Apr\\2007 16:00:00 GMT", true, 1176998400}, + {"Fri, 1 Jan 2010 01:01:50 GMT", true, 1262307710}, + {"Wednesday, 1-Jan-2003 00:00:00 GMT", true, 1041379200}, + {", 1-Jan-2003 00:00:00 GMT", true, 1041379200}, + {" 1-Jan-2003 00:00:00 GMT", true, 1041379200}, + {"1-Jan-2003 00:00:00 GMT", true, 1041379200}, + {"Wed,18-Apr-07 22:50:12 GMT", true, 1176936612}, + {"WillyWonka , 18-Apr-07 22:50:12 GMT", true, 1176936612}, + {"WillyWonka , 18-Apr-07 22:50:12", true, 1176936612}, + {"WillyWonka , 18-apr-07 22:50:12", true, 1176936612}, + {"Mon, 18-Apr-1977 22:50:13 GMT", true, 230251813}, + {"Mon, 18-Apr-77 22:50:13 GMT", true, 230251813}, + // If the cookie came in with the expiration quoted (which in terms of + // the RFC you shouldn't do), we will get string quoted. Bug 1261605. + {"\"Sat, 15-Apr-17\\\"21:01:22\\\"GMT\"", true, 1492290082}, + // Test with full month names and partial names. + {"Partyday, 18- April-07 22:50:12", true, 1176936612}, + {"Partyday, 18 - Apri-07 22:50:12", true, 1176936612}, + {"Wednes, 1-Januar-2003 00:00:00 GMT", true, 1041379200}, + // Test that we always take GMT even with other time zones or bogus + // values. The RFC says everything should be GMT, and in the worst case + // we are 24 hours off because of zone issues. + {"Sat, 15-Apr-17 21:01:22", true, 1492290082}, + {"Sat, 15-Apr-17 21:01:22 GMT-2", true, 1492290082}, + {"Sat, 15-Apr-17 21:01:22 GMT BLAH", true, 1492290082}, + {"Sat, 15-Apr-17 21:01:22 GMT-0400", true, 1492290082}, + {"Sat, 15-Apr-17 21:01:22 GMT-0400 (EDT)", true, 1492290082}, + {"Sat, 15-Apr-17 21:01:22 DST", true, 1492290082}, + {"Sat, 15-Apr-17 21:01:22 -0400", true, 1492290082}, + {"Sat, 15-Apr-17 21:01:22 (hello there)", true, 1492290082}, + // Test that if we encounter multiple : fields, that we take the first + // that correctly parses. + {"Sat, 15-Apr-17 21:01:22 11:22:33", true, 1492290082}, + {"Sat, 15-Apr-17 ::00 21:01:22", true, 1492290082}, + {"Sat, 15-Apr-17 boink:z 21:01:22", true, 1492290082}, + // We take the first, which in this case is invalid. + {"Sat, 15-Apr-17 91:22:33 21:01:22", false, 0}, + // amazon.com formats their cookie expiration like this. + {"Thu Apr 18 22:50:12 2007 GMT", true, 1176936612}, + // Test that hh:mm:ss can occur anywhere. + {"22:50:12 Thu Apr 18 2007 GMT", true, 1176936612}, + {"Thu 22:50:12 Apr 18 2007 GMT", true, 1176936612}, + {"Thu Apr 22:50:12 18 2007 GMT", true, 1176936612}, + {"Thu Apr 18 22:50:12 2007 GMT", true, 1176936612}, + {"Thu Apr 18 2007 22:50:12 GMT", true, 1176936612}, + {"Thu Apr 18 2007 GMT 22:50:12", true, 1176936612}, + // Test that the day and year can be anywhere if they are unambigious. + {"Sat, 15-Apr-17 21:01:22 GMT", true, 1492290082}, + {"15-Sat, Apr-17 21:01:22 GMT", true, 1492290082}, + {"15-Sat, Apr 21:01:22 GMT 17", true, 1492290082}, + {"15-Sat, Apr 21:01:22 GMT 2017", true, 1492290082}, + {"15 Apr 21:01:22 2017", true, 1492290082}, + {"15 17 Apr 21:01:22", true, 1492290082}, + {"Apr 15 17 21:01:22", true, 1492290082}, + {"Apr 15 21:01:22 17", true, 1492290082}, + {"2017 April 15 21:01:22", true, 1492290082}, + {"15 April 2017 21:01:22", true, 1492290082}, + // Some invalid dates + {"98 April 17 21:01:22", false, 0}, + {"Thu, 012-Aug-2008 20:49:07 GMT", false, 0}, + {"Thu, 12-Aug-9999999999 20:49:07 GMT", false, 0}, + {"Thu, 999999999999-Aug-2007 20:49:07 GMT", false, 0}, + {"Thu, 12-Aug-2007 20:61:99999999999 GMT", false, 0}, + {"IAintNoDateFool", false, 0}, + {"1600 April 33 21:01:22", false, 0}, + {"1970 April 33 21:01:22", false, 0}, + {"Thu, 33-Aug-31841 20:49:07 GMT", false, 0}, }; base::Time parsed_time; for (size_t i = 0; i < arraysize(tests); ++i) { - parsed_time = cookie_util::ParseCookieTime(tests[i].str); + parsed_time = cookie_util::ParseCookieExpirationTime(tests[i].str); if (!tests[i].valid) { EXPECT_TRUE(parsed_time.is_null()) << tests[i].str; continue; @@ -145,6 +147,52 @@ TEST(CookieUtilTest, TestCookieDateParsing) { } } +// Tests parsing dates that are beyond 2038. 32-bit (non-Mac) POSIX systems are +// incapable of doing this, however the expectation is for cookie parsing to +// succeed anyway (and return the minimum value Time::FromUTCExploded() can +// parse on the current platform). Also checks a date outside the limit on +// Windows, which is year 30827. +TEST(CookieUtilTest, ParseCookieExpirationTimeBeyond2038) { + const char* kTests[] = { + "Thu, 12-Aug-31841 20:49:07 GMT", "2039 April 15 21:01:22", + "2039 April 15 21:01:22", "2038 April 15 21:01:22", + }; + + for (const auto& test : kTests) { + base::Time parsed_time = cookie_util::ParseCookieExpirationTime(test); + EXPECT_FALSE(parsed_time.is_null()); + + // It should either have an exact value, or be base::Time::Max(). For + // simplicity just check that it is greater than an arbitray date. + base::Time almost_jan_2038 = + base::Time::UnixEpoch() + base::TimeDelta::FromDays(365 * 68); + EXPECT_LT(almost_jan_2038, parsed_time); + } +} + +// Tests parsing dates that are prior to (or around) 1970. Non-Mac POSIX systems +// are incapable of doing this, however the expectation is for cookie parsing to +// succeed anyway (and return a minimal base::Time). +TEST(CookieUtilTest, ParseCookieExpirationTimeBefore1970) { + const char* kTests[] = { + // The unix epoch. + "1970 Jan 1 00:00:00", + // The windows epoch. + "1601 Jan 1 00:00:00", + // Other dates. + "1969 March 3 21:01:22", "1600 April 15 21:01:22", + }; + + for (const auto& test : kTests) { + base::Time parsed_time = cookie_util::ParseCookieExpirationTime(test); + EXPECT_FALSE(parsed_time.is_null()); + + // It should either have an exact value, or should be base::Time(1) + // For simplicity just check that it is less than the unix epoch. + EXPECT_LE(parsed_time, base::Time::UnixEpoch()); + } +} + TEST(CookieUtilTest, TestRequestCookieParsing) { std::vector<RequestCookieParsingTest> tests; |