Back out all cookie changes due to bug 602746. a=omgeverythingisbroken

This commit is contained in:
Dan Witte 2010-10-07 19:02:30 -07:00
Родитель 618e0a4c10
Коммит 4dca9a23a7
6 изменённых файлов: 154 добавлений и 276 удалений

Просмотреть файл

@ -75,27 +75,26 @@ StrBlockCopy(const nsACString &aSource1,
* creation helper
******************************************************************************/
// This is a counter that keeps track of the last used creation time, each time
// we create a new nsCookie. This is nominally the time (in microseconds) the
// cookie was created, but is guaranteed to be monotonically increasing for
// cookies added at runtime after the database has been read in. This is
// necessary to enforce ordering among cookies whose creation times would
// otherwise overlap, since it's possible two cookies may be created at the same
// time, or that the system clock isn't monotonic.
static PRInt64 gLastCreationTime;
// This is a counter that keeps track of the last used creation id, each time we
// create a new nsCookie. The creation id is nominally the time (in microseconds)
// the cookie was created. This id also corresponds to the row id used in the
// sqlite database, which must be unique. However, since it's possible two cookies
// may be created at the same time, or the system clock isn't monotonic, we must
// check each id to enforce monotonicity.
static PRInt64 gLastCreationID;
PRInt64
nsCookie::GenerateUniqueCreationTime(PRInt64 aCreationTime)
nsCookie::GenerateCreationID(PRInt64 aCreationTime)
{
// Check if the creation time given to us is greater than the running maximum
// (it should always be monotonically increasing).
if (aCreationTime > gLastCreationTime) {
gLastCreationTime = aCreationTime;
if (aCreationTime > gLastCreationID) {
gLastCreationID = aCreationTime;
return aCreationTime;
}
// Make up our own.
return ++gLastCreationTime;
return ++gLastCreationID;
}
nsCookie *
@ -105,7 +104,7 @@ nsCookie::Create(const nsACString &aName,
const nsACString &aPath,
PRInt64 aExpiry,
PRInt64 aLastAccessed,
PRInt64 aCreationTime,
PRInt64 aCreationID,
PRBool aIsSession,
PRBool aIsSecure,
PRBool aIsHttpOnly)
@ -126,14 +125,13 @@ nsCookie::Create(const nsACString &aName,
StrBlockCopy(aName, aValue, aHost, aPath,
name, value, host, path, end);
// If the creationTime given to us is higher than the running maximum, update
// our maximum.
if (aCreationTime > gLastCreationTime)
gLastCreationTime = aCreationTime;
// If the creationID given to us is higher than the running maximum, update it.
if (aCreationID > gLastCreationID)
gLastCreationID = aCreationID;
// construct the cookie. placement new, oh yeah!
return new (place) nsCookie(name, value, host, path, end,
aExpiry, aLastAccessed, aCreationTime,
aExpiry, aLastAccessed, aCreationID,
aIsSession, aIsSecure, aIsHttpOnly);
}
@ -155,7 +153,7 @@ NS_IMETHODIMP nsCookie::GetIsSecure(PRBool *aIsSecure) { *aIsSecure = IsSecu
NS_IMETHODIMP nsCookie::GetIsHttpOnly(PRBool *aHttpOnly) { *aHttpOnly = IsHttpOnly(); return NS_OK; }
NS_IMETHODIMP nsCookie::GetStatus(nsCookieStatus *aStatus) { *aStatus = 0; return NS_OK; }
NS_IMETHODIMP nsCookie::GetPolicy(nsCookiePolicy *aPolicy) { *aPolicy = 0; return NS_OK; }
NS_IMETHODIMP nsCookie::GetCreationTime(PRInt64 *aCreation){ *aCreation = CreationTime(); return NS_OK; }
NS_IMETHODIMP nsCookie::GetCreationTime(PRInt64 *aCreation){ *aCreation = CreationID(); return NS_OK; }
NS_IMETHODIMP nsCookie::GetLastAccessed(PRInt64 *aTime) { *aTime = LastAccessed(); return NS_OK; }
// compatibility method, for use with the legacy nsICookie interface.

Просмотреть файл

@ -71,7 +71,7 @@ class nsCookie : public nsICookie2
const char *aEnd,
PRInt64 aExpiry,
PRInt64 aLastAccessed,
PRInt64 aCreationTime,
PRInt64 aCreationID,
PRBool aIsSession,
PRBool aIsSecure,
PRBool aIsHttpOnly)
@ -82,7 +82,7 @@ class nsCookie : public nsICookie2
, mEnd(aEnd)
, mExpiry(aExpiry)
, mLastAccessed(aLastAccessed)
, mCreationTime(aCreationTime)
, mCreationID(aCreationID)
, mIsSession(aIsSession != PR_FALSE)
, mIsSecure(aIsSecure != PR_FALSE)
, mIsHttpOnly(aIsHttpOnly != PR_FALSE)
@ -90,9 +90,10 @@ class nsCookie : public nsICookie2
}
public:
// Generate a unique and monotonically increasing creation time. See comment
// in nsCookie.cpp.
static PRInt64 GenerateUniqueCreationTime(PRInt64 aCreationTime);
// Generate a unique creationID. This will usually be the same as the
// creation time, but with a guarantee of monotonicity such that it can
// be used as a sqlite rowid.
static PRInt64 GenerateCreationID(PRInt64 aCreationTime);
// public helper to create an nsCookie object. use |operator delete|
// to destroy an object created by this method.
@ -102,7 +103,7 @@ class nsCookie : public nsICookie2
const nsACString &aPath,
PRInt64 aExpiry,
PRInt64 aLastAccessed,
PRInt64 aCreationTime,
PRInt64 aCreationID,
PRBool aIsSession,
PRBool aIsSecure,
PRBool aIsHttpOnly);
@ -117,7 +118,7 @@ class nsCookie : public nsICookie2
inline const nsDependentCString Path() const { return nsDependentCString(mPath, mEnd); }
inline PRInt64 Expiry() const { return mExpiry; } // in seconds
inline PRInt64 LastAccessed() const { return mLastAccessed; } // in microseconds
inline PRInt64 CreationTime() const { return mCreationTime; } // in microseconds
inline PRInt64 CreationID() const { return mCreationID; } // in microseconds
inline PRBool IsSession() const { return mIsSession; }
inline PRBool IsDomain() const { return *mHost == '.'; }
inline PRBool IsSecure() const { return mIsSecure; }
@ -127,9 +128,9 @@ class nsCookie : public nsICookie2
inline void SetExpiry(PRInt64 aExpiry) { mExpiry = aExpiry; }
inline void SetLastAccessed(PRInt64 aTime) { mLastAccessed = aTime; }
inline void SetIsSession(PRBool aIsSession) { mIsSession = (PRPackedBool) aIsSession; }
// Set the creation time manually, overriding the monotonicity checks in
// Create(). Use with caution!
inline void SetCreationTime(PRInt64 aTime) { mCreationTime = aTime; }
// set the creation id manually, overriding the monotonicity checks in Create().
// use with caution!
inline void SetCreationID(PRInt64 aID) { mCreationID = aID; }
protected:
// member variables
@ -144,7 +145,9 @@ class nsCookie : public nsICookie2
const char *mEnd;
PRInt64 mExpiry;
PRInt64 mLastAccessed;
PRInt64 mCreationTime;
// creation id is unique for each cookie and approximately represents the cookie
// creation time, in microseconds.
PRInt64 mCreationID;
PRPackedBool mIsSession;
PRPackedBool mIsSecure;
PRPackedBool mIsHttpOnly;

Просмотреть файл

@ -100,7 +100,7 @@ static nsCookieService *gCookieService;
static const char kHttpOnlyPrefix[] = "#HttpOnly_";
static const char kCookieFileName[] = "cookies.sqlite";
#define COOKIES_SCHEMA_VERSION 4
#define COOKIES_SCHEMA_VERSION 3
static const PRInt64 kCookieStaleThreshold = 60 * PR_USEC_PER_SEC; // 1 minute in microseconds
static const PRInt64 kCookiePurgeAge = 30 * 24 * 60 * 60 * PR_USEC_PER_SEC; // 30 days in microseconds
@ -284,9 +284,10 @@ LogCookie(nsCookie *aCookie)
PR_LOG(sCookieLog, PR_LOG_DEBUG,
("expires: %s%s", timeString, aCookie->IsSession() ? " (at end of session)" : ""));
PR_ExplodeTime(aCookie->CreationTime(), PR_GMTParameters, &explodedTime);
PR_ExplodeTime(aCookie->CreationID(), PR_GMTParameters, &explodedTime);
PR_FormatTimeUSEnglish(timeString, 40, "%c GMT", &explodedTime);
PR_LOG(sCookieLog, PR_LOG_DEBUG,("created: %s", timeString));
PR_LOG(sCookieLog, PR_LOG_DEBUG,
("created: %s (id %lld)", timeString, aCookie->CreationID()));
PR_LOG(sCookieLog, PR_LOG_DEBUG,("is secure: %s\n", aCookie->IsSecure() ? "true" : "false"));
PR_LOG(sCookieLog, PR_LOG_DEBUG,("is httpOnly: %s\n", aCookie->IsHttpOnly() ? "true" : "false"));
@ -729,10 +730,9 @@ nsCookieService::TryInitDB(PRBool aDeleteExistingDB)
}
// open a connection to the cookie database, and only cache our connection
// and statements upon success. The connection is opened unshared to eliminate
// cache contention between the main and background threads.
rv = mStorageService->OpenUnsharedDatabase(cookieFile,
getter_AddRefs(mDBState->dbConn));
// and statements upon success. The connection is opened shared such that
// the main and background threads can operate on the db concurrently.
rv = mStorageService->OpenDatabase(cookieFile, getter_AddRefs(mDBState->dbConn));
NS_ENSURE_SUCCESS(rv, rv);
// Grow cookie db in 512KB increments
@ -750,9 +750,6 @@ nsCookieService::TryInitDB(PRBool aDeleteExistingDB)
rv = mDBState->dbConn->GetSchemaVersion(&dbSchemaVersion);
NS_ENSURE_SUCCESS(rv, rv);
// Start a transaction for the whole migration block.
mozStorageTransaction transaction(mDBState->dbConn, PR_TRUE);
switch (dbSchemaVersion) {
// upgrading.
// every time you increment the database schema, you need to implement
@ -768,6 +765,8 @@ nsCookieService::TryInitDB(PRBool aDeleteExistingDB)
case 2:
{
mozStorageTransaction transaction(mDBState->dbConn, PR_TRUE);
// Add the baseDomain column and index to the table.
rv = mDBState->dbConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
"ALTER TABLE moz_cookies ADD baseDomain TEXT"));
@ -783,7 +782,7 @@ nsCookieService::TryInitDB(PRBool aDeleteExistingDB)
nsCOMPtr<mozIStorageStatement> update;
rv = mDBState->dbConn->CreateStatement(NS_LITERAL_CSTRING(
"UPDATE moz_cookies SET baseDomain = :baseDomain WHERE id = :id"),
"UPDATE moz_cookies SET baseDomain = ?1 WHERE id = ?2"),
getter_AddRefs(update));
NS_ENSURE_SUCCESS(rv, rv);
@ -805,11 +804,9 @@ nsCookieService::TryInitDB(PRBool aDeleteExistingDB)
mozStorageStatementScoper scoper(update);
rv = update->BindUTF8StringByName(NS_LITERAL_CSTRING("baseDomain"),
baseDomain);
rv = update->BindUTF8StringByIndex(0, baseDomain);
NS_ASSERT_SUCCESS(rv);
rv = update->BindInt64ByName(NS_LITERAL_CSTRING("id"),
id);
rv = update->BindInt64ByIndex(1, id);
NS_ASSERT_SUCCESS(rv);
rv = update->ExecuteStep(&hasResult);
@ -820,59 +817,13 @@ nsCookieService::TryInitDB(PRBool aDeleteExistingDB)
rv = mDBState->dbConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
"CREATE INDEX moz_basedomain ON moz_cookies (baseDomain)"));
NS_ENSURE_SUCCESS(rv, rv);
}
// Fall through to the next upgrade.
case 3:
{
// Add the creationTime column to the table.
rv = mDBState->dbConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
"ALTER TABLE moz_cookies ADD creationTime INTEGER"));
NS_ENSURE_SUCCESS(rv, rv);
// Read in the rowids from the database...
nsCOMPtr<mozIStorageStatement> select;
rv = mDBState->dbConn->CreateStatement(NS_LITERAL_CSTRING(
"SELECT id FROM moz_cookies"), getter_AddRefs(select));
NS_ENSURE_SUCCESS(rv, rv);
// ... and use them to generate the creationTime.
nsCOMPtr<mozIStorageStatement> update;
rv = mDBState->dbConn->CreateStatement(NS_LITERAL_CSTRING(
"UPDATE moz_cookies SET creationTime = :id WHERE id = :id"),
getter_AddRefs(update));
NS_ENSURE_SUCCESS(rv, rv);
PRBool hasResult;
while (1) {
rv = select->ExecuteStep(&hasResult);
NS_ENSURE_SUCCESS(rv, rv);
if (!hasResult)
break;
mozStorageStatementScoper scoper(update);
PRInt64 id = select->AsInt64(0);
rv = update->BindInt64ByName(NS_LITERAL_CSTRING("id"), id);
NS_ASSERT_SUCCESS(rv);
rv = update->ExecuteStep(&hasResult);
NS_ENSURE_SUCCESS(rv, rv);
}
// Create a unique index on (name, host, path) to allow fast lookup.
rv = mDBState->dbConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
"CREATE UNIQUE INDEX moz_uniqueid "
"ON moz_cookies (name, host, path)"));
// Update the schema version.
rv = mDBState->dbConn->SetSchemaVersion(COOKIES_SCHEMA_VERSION);
NS_ENSURE_SUCCESS(rv, rv);
}
// Fall through to the next upgrade.
// No more upgrades. Update the schema version.
rv = mDBState->dbConn->SetSchemaVersion(COOKIES_SCHEMA_VERSION);
NS_ENSURE_SUCCESS(rv, rv);
case COOKIES_SCHEMA_VERSION:
break;
@ -910,7 +861,6 @@ nsCookieService::TryInitDB(PRBool aDeleteExistingDB)
"path, "
"expiry, "
"lastAccessed, "
"creationTime, "
"isSecure, "
"isHttpOnly "
"FROM moz_cookies"), getter_AddRefs(stmt));
@ -931,12 +881,13 @@ nsCookieService::TryInitDB(PRBool aDeleteExistingDB)
// make operations on the table asynchronous, for performance
mDBState->dbConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING("PRAGMA synchronous = OFF"));
// Use write-ahead-logging for performance.
mDBState->dbConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING("PRAGMA journal_mode = WAL"));
// open in exclusive mode for performance
mDBState->dbConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING("PRAGMA locking_mode = EXCLUSIVE"));
// cache frequently used statements (for insertion, deletion, and updating)
rv = mDBState->dbConn->CreateStatement(NS_LITERAL_CSTRING(
"INSERT INTO moz_cookies ("
"id, "
"baseDomain, "
"name, "
"value, "
@ -944,33 +895,19 @@ nsCookieService::TryInitDB(PRBool aDeleteExistingDB)
"path, "
"expiry, "
"lastAccessed, "
"creationTime, "
"isSecure, "
"isHttpOnly"
") VALUES ("
":baseDomain, "
":name, "
":value, "
":host, "
":path, "
":expiry, "
":lastAccessed, "
":creationTime, "
":isSecure, "
":isHttpOnly"
")"),
") VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8, ?9, ?10)"),
getter_AddRefs(mDBState->stmtInsert));
NS_ENSURE_SUCCESS(rv, rv);
rv = mDBState->dbConn->CreateStatement(NS_LITERAL_CSTRING(
"DELETE FROM moz_cookies "
"WHERE name = :name AND host = :host AND path = :path"),
"DELETE FROM moz_cookies WHERE id = ?1"),
getter_AddRefs(mDBState->stmtDelete));
NS_ENSURE_SUCCESS(rv, rv);
rv = mDBState->dbConn->CreateStatement(NS_LITERAL_CSTRING(
"UPDATE moz_cookies SET lastAccessed = :lastAccessed "
"WHERE name = :name AND host = :host AND path = :path"),
"UPDATE moz_cookies SET lastAccessed = ?1 WHERE id = ?2"),
getter_AddRefs(mDBState->stmtUpdate));
NS_ENSURE_SUCCESS(rv, rv);
@ -1019,10 +956,8 @@ nsCookieService::CreateTable()
"path TEXT, "
"expiry INTEGER, "
"lastAccessed INTEGER, "
"creationTime INTEGER, "
"isSecure INTEGER, "
"isHttpOnly INTEGER, "
"CONSTRAINT moz_uniqueid UNIQUE (name, host, path)"
"isHttpOnly INTEGER"
")"));
if (NS_FAILED(rv)) return rv;
@ -1415,7 +1350,7 @@ nsCookieService::Add(const nsACString &aHost,
nsCookie::Create(aName, aValue, host, aPath,
aExpiry,
currentTimeInUsec,
nsCookie::GenerateUniqueCreationTime(currentTimeInUsec),
nsCookie::GenerateCreationID(currentTimeInUsec),
aIsSession,
aIsSecure,
aIsHttpOnly);
@ -1447,7 +1382,8 @@ nsCookieService::Remove(const nsACString &aHost,
host,
PromiseFlatCString(aName),
PromiseFlatCString(aPath),
matchIter)) {
matchIter,
PR_Now() / PR_USEC_PER_SEC)) {
nsRefPtr<nsCookie> cookie = matchIter.Cookie();
RemoveCookieFromList(matchIter);
NotifyChanged(cookie, NS_LITERAL_STRING("deleted").get());
@ -1479,23 +1415,21 @@ nsCookieService::Remove(const nsACString &aHost,
nsresult
nsCookieService::Read()
{
// Let the reading begin! Note that our query specifies that 'baseDomain'
// not be NULL -- see below for why.
// Let the reading begin!
nsCOMPtr<mozIStorageStatement> stmt;
nsresult rv = mDefaultDBState.dbConn->CreateStatement(NS_LITERAL_CSTRING(
"SELECT "
"id, "
"name, "
"value, "
"host, "
"path, "
"expiry, "
"lastAccessed, "
"creationTime, "
"isSecure, "
"isHttpOnly, "
"baseDomain "
"FROM moz_cookies "
"WHERE baseDomain NOTNULL"), getter_AddRefs(stmt));
"FROM moz_cookies"), getter_AddRefs(stmt));
NS_ENSURE_SUCCESS(rv, rv);
nsRefPtr<ReadCookieDBListener> readListener = new ReadCookieDBListener;
@ -1507,18 +1441,6 @@ nsCookieService::Read()
if (!mDefaultDBState.readSet.IsInitialized())
mDefaultDBState.readSet.Init();
// Queue up an operation to delete any rows with a NULL 'baseDomain'
// column. This takes care of any cookies set by browsers that don't
// understand the 'baseDomain' column, where the database schema version
// is from one that does. (This would occur when downgrading.)
rv = mDefaultDBState.dbConn->CreateStatement(NS_LITERAL_CSTRING(
"DELETE FROM moz_cookies WHERE baseDomain ISNULL"), getter_AddRefs(stmt));
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<mozIStoragePendingStatement> handle;
rv = stmt->ExecuteAsync(mRemoveListener, getter_AddRefs(handle));
NS_ASSERT_SUCCESS(rv);
return NS_OK;
}
@ -1528,27 +1450,29 @@ template<class T> nsCookie*
nsCookieService::GetCookieFromRow(T &aRow)
{
// Skip reading 'baseDomain' -- up to the caller.
PRInt64 creationID = aRow->AsInt64(0);
nsCString name, value, host, path;
nsresult rv = aRow->GetUTF8String(0, name);
nsresult rv = aRow->GetUTF8String(1, name);
NS_ASSERT_SUCCESS(rv);
rv = aRow->GetUTF8String(1, value);
rv = aRow->GetUTF8String(2, value);
NS_ASSERT_SUCCESS(rv);
rv = aRow->GetUTF8String(2, host);
rv = aRow->GetUTF8String(3, host);
NS_ASSERT_SUCCESS(rv);
rv = aRow->GetUTF8String(3, path);
rv = aRow->GetUTF8String(4, path);
NS_ASSERT_SUCCESS(rv);
PRInt64 expiry = aRow->AsInt64(4);
PRInt64 lastAccessed = aRow->AsInt64(5);
PRInt64 creationTime = aRow->AsInt64(6);
PRInt64 expiry = aRow->AsInt64(5);
PRInt64 lastAccessed = aRow->AsInt64(6);
PRBool isSecure = 0 != aRow->AsInt32(7);
PRBool isHttpOnly = 0 != aRow->AsInt32(8);
// Create a new nsCookie and assign the data.
// Create a new nsCookie and assign the data. We are guaranteed that the
// creationID is unique, since we're reading it from the db itself.
return nsCookie::Create(name, value, host, path,
expiry,
lastAccessed,
creationTime,
creationID,
PR_FALSE,
isSecure,
isHttpOnly);
@ -1557,11 +1481,9 @@ nsCookieService::GetCookieFromRow(T &aRow)
void
nsCookieService::AsyncReadComplete()
{
// We may be in the private browsing DB state, with a pending read on the
// default DB state. (This would occur if we started up in private browsing
// mode.) As long as we do all our operations on the default state, we're OK.
NS_ASSERTION(mDefaultDBState.pendingRead, "no pending read");
NS_ASSERTION(mDefaultDBState.readListener, "no read listener");
NS_ASSERTION(mDBState == &mDefaultDBState, "not in default db state");
NS_ASSERTION(mDBState->pendingRead, "no pending read");
NS_ASSERTION(mDBState->readListener, "no read listener");
// Merge the data read on the background thread with the data synchronously
// read on the main thread. Note that transactions on the cookie table may
@ -1575,8 +1497,7 @@ nsCookieService::AsyncReadComplete()
if (mDefaultDBState.readSet.GetEntry(tuple.baseDomain))
continue;
AddCookieToList(tuple.baseDomain, tuple.cookie, &mDefaultDBState, NULL,
PR_FALSE);
AddCookieToList(tuple.baseDomain, tuple.cookie, NULL, PR_FALSE);
}
mDefaultDBState.stmtReadDomain = nsnull;
@ -1595,11 +1516,9 @@ nsCookieService::AsyncReadComplete()
void
nsCookieService::CancelAsyncRead(PRBool aPurgeReadSet)
{
// We may be in the private browsing DB state, with a pending read on the
// default DB state. (This would occur if we started up in private browsing
// mode.) As long as we do all our operations on the default state, we're OK.
NS_ASSERTION(mDefaultDBState.pendingRead, "no pending read");
NS_ASSERTION(mDefaultDBState.readListener, "no read listener");
NS_ASSERTION(mDBState == &mDefaultDBState, "not in default db state");
NS_ASSERTION(mDBState->pendingRead, "no pending read");
NS_ASSERTION(mDBState->readListener, "no read listener");
// Cancel the pending read, kill the read listener, and empty the array
// of data already read in on the background thread.
@ -1629,14 +1548,9 @@ nsCookieService::GetSyncDBConn()
mDefaultDBState.dbConn->GetDatabaseFile(getter_AddRefs(cookieFile));
NS_ASSERTION(cookieFile, "no cookie file on connection");
mStorageService->OpenUnsharedDatabase(cookieFile,
mStorageService->OpenDatabase(cookieFile,
getter_AddRefs(mDefaultDBState.syncConn));
if (!mDefaultDBState.syncConn) {
NS_ERROR("can't open sync db connection");
COOKIE_LOGSTRING(PR_LOG_DEBUG,
("GetSyncDBConn(): can't open sync db connection"));
}
NS_ASSERTION(mDefaultDBState.syncConn, "can't open sync db connection");
return mDefaultDBState.syncConn;
}
@ -1663,13 +1577,13 @@ nsCookieService::EnsureReadDomain(const nsCString &aBaseDomain)
// Cache the statement, since it's likely to be used again.
rv = mDefaultDBState.syncConn->CreateStatement(NS_LITERAL_CSTRING(
"SELECT "
"id, "
"name, "
"value, "
"host, "
"path, "
"expiry, "
"lastAccessed, "
"creationTime, "
"isSecure, "
"isHttpOnly "
"FROM moz_cookies "
@ -1699,7 +1613,7 @@ nsCookieService::EnsureReadDomain(const nsCString &aBaseDomain)
break;
nsCookie* newCookie = GetCookieFromRow(mDefaultDBState.stmtReadDomain);
AddCookieToList(aBaseDomain, newCookie, &mDefaultDBState, NULL, PR_FALSE);
AddCookieToList(aBaseDomain, newCookie, NULL, PR_FALSE);
++readCount;
}
@ -1731,13 +1645,13 @@ nsCookieService::EnsureReadComplete()
nsCOMPtr<mozIStorageStatement> stmt;
nsresult rv = mDefaultDBState.syncConn->CreateStatement(NS_LITERAL_CSTRING(
"SELECT "
"id, "
"name, "
"value, "
"host, "
"path, "
"expiry, "
"lastAccessed, "
"creationTime, "
"isSecure, "
"isHttpOnly, "
"baseDomain "
@ -1763,7 +1677,7 @@ nsCookieService::EnsureReadComplete()
continue;
nsCookie* newCookie = GetCookieFromRow(stmt);
AddCookieToList(baseDomain, newCookie, &mDefaultDBState, NULL, PR_FALSE);
AddCookieToList(baseDomain, newCookie, NULL, PR_FALSE);
++readCount;
}
@ -1779,13 +1693,6 @@ nsCookieService::EnsureReadComplete()
NS_IMETHODIMP
nsCookieService::ImportCookies(nsIFile *aCookieFile)
{
// Make sure we're in the default DB state. We don't want people importing
// cookies into a private browsing session!
if (mDBState != &mDefaultDBState) {
NS_WARNING("Trying to import cookies in a private browsing session!");
return NS_ERROR_NOT_AVAILABLE;
}
nsresult rv;
nsCOMPtr<nsIInputStream> fileInputStream;
rv = NS_NewLocalFileInputStream(getter_AddRefs(fileInputStream), aCookieFile);
@ -1803,7 +1710,7 @@ nsCookieService::ImportCookies(nsIFile *aCookieFile)
PRInt32 numInts;
PRInt64 expires;
PRBool isDomain, isHttpOnly = PR_FALSE;
PRUint32 originalCookieCount = mDefaultDBState.cookieCount;
PRUint32 originalCookieCount = mDBState->cookieCount;
PRInt64 currentTimeInUsec = PR_Now();
PRInt64 currentTime = currentTimeInUsec / PR_USEC_PER_SEC;
@ -1840,8 +1747,8 @@ nsCookieService::ImportCookies(nsIFile *aCookieFile)
// We will likely be adding a bunch of cookies to the DB, so we use async
// batching with storage to make this super fast.
nsCOMPtr<mozIStorageBindingParamsArray> paramsArray;
if (originalCookieCount == 0 && mDefaultDBState.dbConn) {
mDefaultDBState.stmtInsert->NewBindingParamsArray(getter_AddRefs(paramsArray));
if (originalCookieCount == 0 && mDBState->dbConn) {
mDBState->stmtInsert->NewBindingParamsArray(getter_AddRefs(paramsArray));
}
while (isMore && NS_SUCCEEDED(lineInputStream->ReadLine(buffer, &isMore))) {
@ -1891,8 +1798,9 @@ nsCookieService::ImportCookies(nsIFile *aCookieFile)
if (NS_FAILED(rv))
continue;
// Create a new nsCookie and assign the data. We don't know the cookie
// creation time, so just use the current time to generate a unique one.
// Create a new nsCookie and assign the data.
// We don't know the cookie creation time, so just use the current time
// to generate a unique creationID.
nsRefPtr<nsCookie> newCookie =
nsCookie::Create(Substring(buffer, nameIndex, cookieIndex - nameIndex - 1),
Substring(buffer, cookieIndex, buffer.Length() - cookieIndex),
@ -1900,7 +1808,7 @@ nsCookieService::ImportCookies(nsIFile *aCookieFile)
Substring(buffer, pathIndex, secureIndex - pathIndex - 1),
expires,
lastAccessedCounter,
nsCookie::GenerateUniqueCreationTime(currentTimeInUsec),
nsCookie::GenerateCreationID(currentTimeInUsec),
PR_FALSE,
Substring(buffer, secureIndex, expiresIndex - secureIndex - 1).EqualsLiteral(kTrue),
isHttpOnly);
@ -1913,7 +1821,7 @@ nsCookieService::ImportCookies(nsIFile *aCookieFile)
lastAccessedCounter--;
if (originalCookieCount == 0) {
AddCookieToList(baseDomain, newCookie, &mDefaultDBState, paramsArray);
AddCookieToList(baseDomain, newCookie, paramsArray);
}
else {
AddInternal(baseDomain, newCookie, currentTimeInUsec, NULL, NULL, PR_TRUE);
@ -1925,18 +1833,17 @@ nsCookieService::ImportCookies(nsIFile *aCookieFile)
PRUint32 length;
paramsArray->GetLength(&length);
if (length) {
rv = mDefaultDBState.stmtInsert->BindParameters(paramsArray);
rv = mDBState->stmtInsert->BindParameters(paramsArray);
NS_ASSERT_SUCCESS(rv);
nsCOMPtr<mozIStoragePendingStatement> handle;
rv = mDefaultDBState.stmtInsert->ExecuteAsync(mInsertListener,
rv = mDBState->stmtInsert->ExecuteAsync(mInsertListener,
getter_AddRefs(handle));
NS_ASSERT_SUCCESS(rv);
}
}
COOKIE_LOGSTRING(PR_LOG_DEBUG, ("ImportCookies(): %ld cookies imported",
mDefaultDBState.cookieCount));
COOKIE_LOGSTRING(PR_LOG_DEBUG, ("ImportCookies(): %ld cookies imported", mDBState->cookieCount));
return NS_OK;
}
@ -1955,8 +1862,8 @@ class CompareCookiesForSending
public:
PRBool Equals(const nsCookie* aCookie1, const nsCookie* aCookie2) const
{
return aCookie1->CreationTime() == aCookie2->CreationTime() &&
aCookie2->Path().Length() == aCookie1->Path().Length();
// CreationID is unique, so two id's can never be equal.
return PR_FALSE;
}
PRBool LessThan(const nsCookie* aCookie1, const nsCookie* aCookie2) const
@ -1970,7 +1877,8 @@ public:
// required for backwards compatibility since some websites erroneously
// depend on receiving cookies in the order in which they were sent to the
// browser! see bug 236772.
return aCookie1->CreationTime() < aCookie2->CreationTime();
// note: CreationID is unique, so two id's can never be equal.
return aCookie1->CreationID() < aCookie2->CreationID();
}
};
@ -2223,7 +2131,7 @@ nsCookieService::SetCookieInternal(nsIURI *aHostURI,
cookieAttributes.path,
cookieAttributes.expiryTime,
currentTimeInUsec,
nsCookie::GenerateUniqueCreationTime(currentTimeInUsec),
nsCookie::GenerateCreationID(currentTimeInUsec),
cookieAttributes.isSession,
cookieAttributes.isSecure,
cookieAttributes.isHttpOnly);
@ -2284,35 +2192,30 @@ nsCookieService::AddInternal(const nsCString &aBaseDomain,
nsListIter matchIter;
PRBool foundCookie = FindCookie(aBaseDomain, aCookie->Host(),
aCookie->Name(), aCookie->Path(), matchIter);
aCookie->Name(), aCookie->Path(), matchIter, currentTime);
nsRefPtr<nsCookie> oldCookie;
if (foundCookie) {
oldCookie = matchIter.Cookie();
// If the old cookie is httponly, make sure we're not coming from script --
// but, if the old cookie has already expired, pretend like it didn't exist.
if (!aFromHttp && oldCookie->IsHttpOnly() &&
oldCookie->Expiry() > currentTime) {
// if the old cookie is httponly, make sure we're not coming from script
if (!aFromHttp && oldCookie->IsHttpOnly()) {
COOKIE_LOGFAILURE(SET_COOKIE, aHostURI, aCookieHeader, "previously stored cookie is httponly; coming from script");
return;
}
// Remove the old cookie, regardless of whether it's expired or not, and
// notify.
RemoveCookieFromList(matchIter);
COOKIE_LOGFAILURE(SET_COOKIE, aHostURI, aCookieHeader, "previously stored cookie was deleted");
NotifyChanged(oldCookie, NS_LITERAL_STRING("deleted").get());
// If the new cookie has expired -- i.e. the intent was simply to delete
// the old cookie -- then we're done.
if (aCookie->Expiry() <= currentTime)
// check if the cookie has expired
if (aCookie->Expiry() <= currentTime) {
COOKIE_LOGFAILURE(SET_COOKIE, aHostURI, aCookieHeader, "previously stored cookie was deleted");
NotifyChanged(oldCookie, NS_LITERAL_STRING("deleted").get());
return;
}
// Preserve creation time of cookie for ordering purposes.
// preserve creation time of cookie
if (oldCookie)
aCookie->SetCreationTime(oldCookie->CreationTime());
aCookie->SetCreationID(oldCookie->CreationID());
} else {
// check if cookie has already expired
@ -2348,7 +2251,7 @@ nsCookieService::AddInternal(const nsCString &aBaseDomain,
// Add the cookie to the db. We do not supply a params array for batching
// because this might result in removals and additions being out of order.
AddCookieToList(aBaseDomain, aCookie, mDBState, NULL);
AddCookieToList(aBaseDomain, aCookie, NULL);
NotifyChanged(aCookie, foundCookie ? NS_LITERAL_STRING("changed").get()
: NS_LITERAL_STRING("added").get());
@ -3002,18 +2905,18 @@ class CompareCookiesByAge {
public:
PRBool Equals(const nsListIter &a, const nsListIter &b) const
{
return a.Cookie()->LastAccessed() == b.Cookie()->LastAccessed() &&
a.Cookie()->CreationTime() == b.Cookie()->CreationTime();
// CreationID is unique, so two id's can never be equal.
return PR_FALSE;
}
PRBool LessThan(const nsListIter &a, const nsListIter &b) const
{
// compare by lastAccessed time, and tiebreak by creationTime.
// compare by LastAccessed time, and tiebreak by CreationID.
PRInt64 result = a.Cookie()->LastAccessed() - b.Cookie()->LastAccessed();
if (result != 0)
return result < 0;
return a.Cookie()->CreationTime() < b.Cookie()->CreationTime();
return a.Cookie()->CreationID() < b.Cookie()->CreationID();
}
};
@ -3079,7 +2982,7 @@ nsCookieService::PurgeCookies(PRInt64 aCurrentTimeInUsec)
#ifdef PR_LOGGING
PRUint32 initialCookieCount = mDBState->cookieCount;
COOKIE_LOGSTRING(PR_LOG_DEBUG,
("PurgeCookies(): beginning purge with %ld cookies and %lld oldest age",
("PurgeCookies(): beginning purge with %ld cookies and %lld age",
mDBState->cookieCount, aCurrentTimeInUsec - mDBState->cookieOldestTime));
#endif
@ -3127,7 +3030,7 @@ nsCookieService::PurgeCookies(PRInt64 aCurrentTimeInUsec)
for (nsPurgeData::ArrayType::index_type i = purgeList.Length(); i--; ) {
nsCookie *cookie = purgeList[i].Cookie();
removedList->AppendElement(cookie, PR_FALSE);
COOKIE_LOGEVICTED(cookie, "Cookie too old");
COOKIE_LOGEVICTED(cookie, "Cookie expired or too old");
RemoveCookieFromList(purgeList[i], paramsArray);
}
@ -3154,7 +3057,7 @@ nsCookieService::PurgeCookies(PRInt64 aCurrentTimeInUsec)
COOKIE_LOGSTRING(PR_LOG_DEBUG,
("PurgeCookies(): %ld expired; %ld purged; %ld remain; %lld oldest age",
initialCookieCount - postExpiryCookieCount,
postExpiryCookieCount - mDBState->cookieCount,
mDBState->cookieCount - postExpiryCookieCount,
mDBState->cookieCount,
aCurrentTimeInUsec - mDBState->cookieOldestTime));
}
@ -3180,7 +3083,8 @@ nsCookieService::CookieExists(nsICookie2 *aCookie,
NS_ENSURE_SUCCESS(rv, rv);
nsListIter iter;
*aFoundCookie = FindCookie(baseDomain, host, name, path, iter);
*aFoundCookie = FindCookie(baseDomain, host, name, path, iter,
PR_Now() / PR_USEC_PER_SEC);
return NS_OK;
}
@ -3279,7 +3183,8 @@ nsCookieService::FindCookie(const nsCString &aBaseDomain,
const nsAFlatCString &aHost,
const nsAFlatCString &aName,
const nsAFlatCString &aPath,
nsListIter &aIter)
nsListIter &aIter,
PRInt64 aCurrentTime)
{
EnsureReadDomain(aBaseDomain);
@ -3291,7 +3196,8 @@ nsCookieService::FindCookie(const nsCString &aBaseDomain,
for (nsCookieEntry::IndexType i = 0; i < cookies.Length(); ++i) {
nsCookie *cookie = cookies[i];
if (aHost.Equals(cookie->Host()) &&
if (cookie->Expiry() > aCurrentTime &&
aHost.Equals(cookie->Host()) &&
aPath.Equals(cookie->Path()) &&
aName.Equals(cookie->Name())) {
aIter = nsListIter(entry, i);
@ -3320,16 +3226,7 @@ nsCookieService::RemoveCookieFromList(const nsListIter &aIter,
nsCOMPtr<mozIStorageBindingParams> params;
paramsArray->NewBindingParams(getter_AddRefs(params));
nsresult rv = params->BindUTF8StringByName(NS_LITERAL_CSTRING("name"),
aIter.Cookie()->Name());
NS_ASSERT_SUCCESS(rv);
rv = params->BindUTF8StringByName(NS_LITERAL_CSTRING("host"),
aIter.Cookie()->Host());
NS_ASSERT_SUCCESS(rv);
rv = params->BindUTF8StringByName(NS_LITERAL_CSTRING("path"),
aIter.Cookie()->Path());
nsresult rv = params->BindInt64ByIndex(0, aIter.Cookie()->CreationID());
NS_ASSERT_SUCCESS(rv);
rv = paramsArray->AddParams(params);
@ -3375,44 +3272,34 @@ bindCookieParameters(mozIStorageBindingParamsArray *aParamsArray,
NS_ASSERT_SUCCESS(rv);
// Bind our values to params
rv = params->BindUTF8StringByName(NS_LITERAL_CSTRING("baseDomain"),
aBaseDomain);
rv = params->BindInt64ByIndex(0, aCookie->CreationID());
NS_ASSERT_SUCCESS(rv);
rv = params->BindUTF8StringByName(NS_LITERAL_CSTRING("name"),
aCookie->Name());
rv = params->BindUTF8StringByIndex(1, aBaseDomain);
NS_ASSERT_SUCCESS(rv);
rv = params->BindUTF8StringByName(NS_LITERAL_CSTRING("value"),
aCookie->Value());
rv = params->BindUTF8StringByIndex(2, aCookie->Name());
NS_ASSERT_SUCCESS(rv);
rv = params->BindUTF8StringByName(NS_LITERAL_CSTRING("host"),
aCookie->Host());
rv = params->BindUTF8StringByIndex(3, aCookie->Value());
NS_ASSERT_SUCCESS(rv);
rv = params->BindUTF8StringByName(NS_LITERAL_CSTRING("path"),
aCookie->Path());
rv = params->BindUTF8StringByIndex(4, aCookie->Host());
NS_ASSERT_SUCCESS(rv);
rv = params->BindInt64ByName(NS_LITERAL_CSTRING("expiry"),
aCookie->Expiry());
rv = params->BindUTF8StringByIndex(5, aCookie->Path());
NS_ASSERT_SUCCESS(rv);
rv = params->BindInt64ByName(NS_LITERAL_CSTRING("lastAccessed"),
aCookie->LastAccessed());
rv = params->BindInt64ByIndex(6, aCookie->Expiry());
NS_ASSERT_SUCCESS(rv);
rv = params->BindInt64ByName(NS_LITERAL_CSTRING("creationTime"),
aCookie->CreationTime());
rv = params->BindInt64ByIndex(7, aCookie->LastAccessed());
NS_ASSERT_SUCCESS(rv);
rv = params->BindInt32ByName(NS_LITERAL_CSTRING("isSecure"),
aCookie->IsSecure());
rv = params->BindInt32ByIndex(8, aCookie->IsSecure());
NS_ASSERT_SUCCESS(rv);
rv = params->BindInt32ByName(NS_LITERAL_CSTRING("isHttpOnly"),
aCookie->IsHttpOnly());
rv = params->BindInt32ByIndex(9, aCookie->IsHttpOnly());
NS_ASSERT_SUCCESS(rv);
// Bind the params to the array.
@ -3423,28 +3310,27 @@ bindCookieParameters(mozIStorageBindingParamsArray *aParamsArray,
void
nsCookieService::AddCookieToList(const nsCString &aBaseDomain,
nsCookie *aCookie,
DBState *aDBState,
mozIStorageBindingParamsArray *aParamsArray,
PRBool aWriteToDB)
{
NS_ASSERTION(!(aDBState->dbConn && !aWriteToDB && aParamsArray),
NS_ASSERTION(!(mDBState->dbConn && !aWriteToDB && aParamsArray),
"Not writing to the DB but have a params array?");
NS_ASSERTION(!(!aDBState->dbConn && aParamsArray),
NS_ASSERTION(!(!mDBState->dbConn && aParamsArray),
"Do not have a DB connection but have a params array?");
nsCookieEntry *entry = aDBState->hostTable.PutEntry(aBaseDomain);
nsCookieEntry *entry = mDBState->hostTable.PutEntry(aBaseDomain);
NS_ASSERTION(entry, "can't insert element into a null entry!");
entry->GetCookies().AppendElement(aCookie);
++aDBState->cookieCount;
++mDBState->cookieCount;
// keep track of the oldest cookie, for when it comes time to purge
if (aCookie->LastAccessed() < aDBState->cookieOldestTime)
aDBState->cookieOldestTime = aCookie->LastAccessed();
if (aCookie->LastAccessed() < mDBState->cookieOldestTime)
mDBState->cookieOldestTime = aCookie->LastAccessed();
// if it's a non-session cookie and hasn't just been read from the db, write it out.
if (aWriteToDB && !aCookie->IsSession() && aDBState->dbConn) {
mozIStorageStatement *stmt = aDBState->stmtInsert;
if (aWriteToDB && !aCookie->IsSession() && mDBState->dbConn) {
mozIStorageStatement *stmt = mDBState->stmtInsert;
nsCOMPtr<mozIStorageBindingParamsArray> paramsArray(aParamsArray);
if (!paramsArray) {
stmt->NewBindingParamsArray(getter_AddRefs(paramsArray));
@ -3480,20 +3366,9 @@ nsCookieService::UpdateCookieInList(nsCookie *aCookie,
aParamsArray->NewBindingParams(getter_AddRefs(params));
// Bind our parameters.
nsresult rv = params->BindInt64ByName(NS_LITERAL_CSTRING("lastAccessed"),
aLastAccessed);
nsresult rv = params->BindInt64ByIndex(0, aLastAccessed);
NS_ASSERT_SUCCESS(rv);
rv = params->BindUTF8StringByName(NS_LITERAL_CSTRING("name"),
aCookie->Name());
NS_ASSERT_SUCCESS(rv);
rv = params->BindUTF8StringByName(NS_LITERAL_CSTRING("host"),
aCookie->Host());
NS_ASSERT_SUCCESS(rv);
rv = params->BindUTF8StringByName(NS_LITERAL_CSTRING("path"),
aCookie->Path());
rv = params->BindInt64ByIndex(1, aCookie->CreationID());
NS_ASSERT_SUCCESS(rv);
// Add our bound parameters to the array.

Просмотреть файл

@ -235,7 +235,7 @@ class nsCookieService : public nsICookieService
PRBool SetCookieInternal(nsIURI *aHostURI, const nsCString& aBaseDomain, PRBool aRequireHostMatch, CookieStatus aStatus, nsDependentCString &aCookieHeader, PRInt64 aServerTime, PRBool aFromHttp);
void AddInternal(const nsCString& aBaseDomain, nsCookie *aCookie, PRInt64 aCurrentTimeInUsec, nsIURI *aHostURI, const char *aCookieHeader, PRBool aFromHttp);
void RemoveCookieFromList(const nsListIter &aIter, mozIStorageBindingParamsArray *aParamsArray = NULL);
void AddCookieToList(const nsCString& aBaseDomain, nsCookie *aCookie, DBState *aDBState, mozIStorageBindingParamsArray *aParamsArray, PRBool aWriteToDB = PR_TRUE);
void AddCookieToList(const nsCString& aBaseDomain, nsCookie *aCookie, mozIStorageBindingParamsArray *aParamsArray, PRBool aWriteToDB = PR_TRUE);
void UpdateCookieInList(nsCookie *aCookie, PRInt64 aLastAccessed, mozIStorageBindingParamsArray *aParamsArray);
static PRBool GetTokenValue(nsASingleFragmentCString::const_char_iterator &aIter, nsASingleFragmentCString::const_char_iterator &aEndIter, nsDependentCSubstring &aTokenString, nsDependentCSubstring &aTokenValue, PRBool &aEqualsFound);
static PRBool ParseAttributes(nsDependentCString &aCookieHeader, nsCookieAttributes &aCookie);
@ -247,7 +247,7 @@ class nsCookieService : public nsICookieService
static PRBool GetExpiry(nsCookieAttributes &aCookie, PRInt64 aServerTime, PRInt64 aCurrentTime);
void RemoveAllFromMemory();
void PurgeCookies(PRInt64 aCurrentTimeInUsec);
PRBool FindCookie(const nsCString& aBaseDomain, const nsAFlatCString &aHost, const nsAFlatCString &aName, const nsAFlatCString &aPath, nsListIter &aIter);
PRBool FindCookie(const nsCString& aBaseDomain, const nsAFlatCString &aHost, const nsAFlatCString &aName, const nsAFlatCString &aPath, nsListIter &aIter, PRInt64 aCurrentTime);
PRUint32 CountCookiesFromHostInternal(const nsCString &aBaseDomain, nsEnumerationData &aData);
void NotifyRejected(nsIURI *aHostURI);
void NotifyChanged(nsISupports *aSubject, const PRUnichar *aData);

Просмотреть файл

@ -738,11 +738,10 @@ main(PRInt32 argc, char *argv[])
rv[13] = NS_SUCCEEDED(cookieMgr2->CookieExists(newDomainCookie, &found)) && !found;
// sleep four seconds, to make sure the second cookie has expired
PR_Sleep(4 * PR_TicksPerSecond());
// check CountCookiesFromHost() doesn't count the expired cookie...
// check CountCookiesFromHost() and CookieExists() don't count the expired cookie
rv[14] = NS_SUCCEEDED(cookieMgr2->CountCookiesFromHost(NS_LITERAL_CSTRING("cookiemgr.test"), &hostCookies)) &&
hostCookies == 1;
// ... but that it's still there using CookieExists()
rv[15] = NS_SUCCEEDED(cookieMgr2->CookieExists(expiredCookie, &found)) && found;
rv[15] = NS_SUCCEEDED(cookieMgr2->CookieExists(expiredCookie, &found)) && !found;
// double-check RemoveAll() using the enumerator
rv[16] = NS_SUCCEEDED(cookieMgr->RemoveAll());
rv[17] = NS_SUCCEEDED(cookieMgr->GetEnumerator(getter_AddRefs(enumerator))) &&

Просмотреть файл

@ -111,9 +111,12 @@ interface mozIStorageService : nsISupports {
* Each connection uses its own sqlite cache, which is inefficient, so you
* should use openDatabase instead of this method unless you need a feature
* of SQLite that is incompatible with a shared cache, like virtual table
* and full text indexing support. If cache contention is expected, for
* instance when operating on a database from multiple threads, using
* unshared connections may be a performance win.
* and full text indexing support.
*
* Consumers should check mozIStorageConnection::connectionReady to ensure
* that they can use the database. If this value is false, it is strongly
* recommended that the database be backed up with
* mozIStorageConnection::backupDB so user data is not lost.
*
* ==========
* DANGER
@ -128,7 +131,7 @@ interface mozIStorageService : nsISupports {
* use it only from the thread you created it from.
*
* @param aDatabaseFile
* A nsIFile that represents the database that is to be opened.
* A nsIFile that represents the database that is to be opened..
*
* @returns a mozIStorageConnection for the requested database file.
*