Index: net/base/cookie_monster.cc |
diff --git a/net/base/cookie_monster.cc b/net/base/cookie_monster.cc |
index 4c460148195cd8ab993ba27e0b8f9bb95195785d..795d3ea8f65dc3fb3672a5d2a7a9ffa177fa2b23 100644 |
--- a/net/base/cookie_monster.cc |
+++ b/net/base/cookie_monster.cc |
@@ -185,13 +185,29 @@ void CookieMonster::InitStore() { |
// This prevents multiple vector growth / copies as we append cookies. |
cookies.reserve(kNumCookiesTotal); |
store_->Load(&cookies); |
+ |
+ // Avoid ever letting cookies with duplicate creation times into the store; |
+ // that way we don't have to worry about what sections of code are safe |
+ // to call while it's in that state. |
+ std::set<int64> creation_times; |
for (std::vector<KeyedCanonicalCookie>::const_iterator it = cookies.begin(); |
it != cookies.end(); ++it) { |
- InternalInsertCookie(it->first, it->second, false); |
+ int64 cookie_creation_time = it->second->CreationDate().ToInternalValue(); |
+ |
+ if (creation_times.insert(cookie_creation_time).second) { |
+ InternalInsertCookie(it->first, it->second, false); |
+ } else { |
+ LOG(ERROR) << StringPrintf("Found cookies with duplicate creation " |
+ "times in backing store: " |
+ "{name='%s', domain='%s', path='%s'}", |
+ it->second->Name().c_str(), |
+ it->first.c_str(), |
+ it->second->Path().c_str()); |
+ } |
} |
// After importing cookies from the PersistentCookieStore, verify that |
- // none of our constraints are violated. |
+ // none of our other constraints are violated. |
// |
// In particular, the backing store might have given us duplicate cookies. |
EnsureCookiesMapIsValid(); |
@@ -218,9 +234,6 @@ void CookieMonster::EnsureCookiesMapIsValid() { |
// Record how many duplicates were found in the database. |
// See InitializeHistograms() for details. |
histogram_cookie_deletion_cause_->Add(num_duplicates_trimmed); |
- |
- // TODO(eroman): Should also verify that there are no cookies with the same |
- // creation time, since that is assumed to be unique by the rest of the code. |
} |
// Our strategy to find duplicates is: |
@@ -294,13 +307,18 @@ int CookieMonster::TrimDuplicateCookiesForHost( |
// We save the iterator into |cookies_| rather than the actual cookie |
// pointer, since we may need to delete it later. |
- list.insert(it); |
+ bool insert_success = list.insert(it).second; |
+ DCHECK(insert_success) << |
+ "Duplicate creation times found in duplicate cookie name scan."; |
} |
// If there were no duplicates, we are done! |
if (num_duplicates == 0) |
return 0; |
+ // Make sure we find everything below that we did above. |
+ int num_duplicates_found = 0; |
+ |
// Otherwise, delete all the duplicate cookies, both from our in-memory store |
// and from the backing store. |
for (EquivalenceMap::iterator it = equivalent_cookies.begin(); |
@@ -311,6 +329,7 @@ int CookieMonster::TrimDuplicateCookiesForHost( |
if (dupes.size() <= 1) |
continue; // This cookiename/path has no duplicates. |
+ num_duplicates_found += dupes.size() - 1; |
// Since |dups| is sorted by creation time (descending), the first cookie |
// is the most recent one, so we will keep it. The rest are duplicates. |
@@ -334,6 +353,7 @@ int CookieMonster::TrimDuplicateCookiesForHost( |
DELETE_COOKIE_DUPLICATE_IN_BACKING_STORE); |
} |
} |
+ DCHECK_EQ(num_duplicates, num_duplicates_found); |
return num_duplicates; |
} |
@@ -654,13 +674,7 @@ bool CookieMonster::SetCookieWithCreationTimeAndOptions( |
const std::string& cookie_line, |
const Time& creation_time_or_null, |
const CookieOptions& options) { |
- AutoLock autolock(lock_); |
- |
- if (!HasCookieableScheme(url)) { |
- return false; |
- } |
- |
- InitIfNecessary(); |
+ lock_.AssertAcquired(); |
COOKIE_DLOG(INFO) << "SetCookie() line: " << cookie_line; |
@@ -706,6 +720,20 @@ bool CookieMonster::SetCookieWithCreationTimeAndOptions( |
return SetCanonicalCookie(&cc, creation_time, options); |
} |
+bool CookieMonster::SetCookieWithCreationTime(const GURL& url, |
+ const std::string& cookie_line, |
+ const base::Time& creation_time) { |
+ AutoLock autolock(lock_); |
+ |
+ if (!HasCookieableScheme(url)) { |
+ return false; |
+ } |
+ |
+ InitIfNecessary(); |
+ return SetCookieWithCreationTimeAndOptions(url, cookie_line, creation_time, |
+ CookieOptions()); |
+} |
+ |
bool CookieMonster::SetCookieWithDetails( |
const GURL& url, const std::string& name, const std::string& value, |
const std::string& domain, const std::string& path, |
@@ -1030,6 +1058,14 @@ static bool CookieSorter(CookieMonster::CanonicalCookie* cc1, |
bool CookieMonster::SetCookieWithOptions(const GURL& url, |
const std::string& cookie_line, |
const CookieOptions& options) { |
+ AutoLock autolock(lock_); |
ahendrickson
2010/07/27 19:15:37
I'm curious about why you moved this section (and
Randy Smith (Not in Mondays)
2010/07/27 20:11:47
Historically, all of the functions that took the C
|
+ |
+ if (!HasCookieableScheme(url)) { |
+ return false; |
+ } |
+ |
+ InitIfNecessary(); |
+ |
return SetCookieWithCreationTimeAndOptions(url, cookie_line, Time(), options); |
} |