зеркало из https://github.com/mozilla/pjs.git
relanding bug 403372.
This commit is contained in:
Родитель
88e77df876
Коммит
15e51ab5b5
|
@ -89,6 +89,7 @@ nsCookie::Create(const nsACString &aName,
|
||||||
const nsACString &aHost,
|
const nsACString &aHost,
|
||||||
const nsACString &aPath,
|
const nsACString &aPath,
|
||||||
PRInt64 aExpiry,
|
PRInt64 aExpiry,
|
||||||
|
PRInt64 aLastAccessed,
|
||||||
PRInt64 aCreationID,
|
PRInt64 aCreationID,
|
||||||
PRBool aIsSession,
|
PRBool aIsSession,
|
||||||
PRBool aIsSecure,
|
PRBool aIsSecure,
|
||||||
|
@ -119,7 +120,7 @@ nsCookie::Create(const nsACString &aName,
|
||||||
|
|
||||||
// construct the cookie. placement new, oh yeah!
|
// construct the cookie. placement new, oh yeah!
|
||||||
return new (place) nsCookie(name, value, host, path, end,
|
return new (place) nsCookie(name, value, host, path, end,
|
||||||
aExpiry, aCreationID,
|
aExpiry, aLastAccessed, aCreationID,
|
||||||
aIsSession, aIsSecure, aIsHttpOnly);
|
aIsSession, aIsSecure, aIsHttpOnly);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -70,6 +70,7 @@ class nsCookie : public nsICookie2
|
||||||
const char *aPath,
|
const char *aPath,
|
||||||
const char *aEnd,
|
const char *aEnd,
|
||||||
PRInt64 aExpiry,
|
PRInt64 aExpiry,
|
||||||
|
PRInt64 aLastAccessed,
|
||||||
PRInt64 aCreationID,
|
PRInt64 aCreationID,
|
||||||
PRBool aIsSession,
|
PRBool aIsSession,
|
||||||
PRBool aIsSecure,
|
PRBool aIsSecure,
|
||||||
|
@ -81,6 +82,7 @@ class nsCookie : public nsICookie2
|
||||||
, mPath(aPath)
|
, mPath(aPath)
|
||||||
, mEnd(aEnd)
|
, mEnd(aEnd)
|
||||||
, mExpiry(aExpiry)
|
, mExpiry(aExpiry)
|
||||||
|
, mLastAccessed(aLastAccessed)
|
||||||
, mCreationID(aCreationID)
|
, mCreationID(aCreationID)
|
||||||
, mIsSession(aIsSession != PR_FALSE)
|
, mIsSession(aIsSession != PR_FALSE)
|
||||||
, mIsSecure(aIsSecure != PR_FALSE)
|
, mIsSecure(aIsSecure != PR_FALSE)
|
||||||
|
@ -96,6 +98,7 @@ class nsCookie : public nsICookie2
|
||||||
const nsACString &aHost,
|
const nsACString &aHost,
|
||||||
const nsACString &aPath,
|
const nsACString &aPath,
|
||||||
PRInt64 aExpiry,
|
PRInt64 aExpiry,
|
||||||
|
PRInt64 aLastAccessed,
|
||||||
PRInt64 aCreationID,
|
PRInt64 aCreationID,
|
||||||
PRBool aIsSession,
|
PRBool aIsSession,
|
||||||
PRBool aIsSecure,
|
PRBool aIsSecure,
|
||||||
|
@ -109,10 +112,9 @@ class nsCookie : public nsICookie2
|
||||||
inline const nsDependentCString Host() const { return nsDependentCString(mHost, mPath - 1); }
|
inline const nsDependentCString Host() const { return nsDependentCString(mHost, mPath - 1); }
|
||||||
inline const nsDependentCString RawHost() const { return nsDependentCString(IsDomain() ? mHost + 1 : mHost, mPath - 1); }
|
inline const nsDependentCString RawHost() const { return nsDependentCString(IsDomain() ? mHost + 1 : mHost, mPath - 1); }
|
||||||
inline const nsDependentCString Path() const { return nsDependentCString(mPath, mEnd); }
|
inline const nsDependentCString Path() const { return nsDependentCString(mPath, mEnd); }
|
||||||
inline PRInt64 Expiry() const { return mExpiry; }
|
inline PRInt64 Expiry() const { return mExpiry; } // in seconds
|
||||||
inline PRInt64 CreationID() const { return mCreationID; }
|
inline PRInt64 LastAccessed() const { return mLastAccessed; } // in microseconds
|
||||||
// cookie creation time, in seconds
|
inline PRInt64 CreationID() const { return mCreationID; } // in microseconds
|
||||||
inline PRInt64 CreationTime() const { return mCreationID / PR_USEC_PER_SEC; }
|
|
||||||
inline PRBool IsSession() const { return mIsSession; }
|
inline PRBool IsSession() const { return mIsSession; }
|
||||||
inline PRBool IsDomain() const { return *mHost == '.'; }
|
inline PRBool IsDomain() const { return *mHost == '.'; }
|
||||||
inline PRBool IsSecure() const { return mIsSecure; }
|
inline PRBool IsSecure() const { return mIsSecure; }
|
||||||
|
@ -120,6 +122,7 @@ class nsCookie : public nsICookie2
|
||||||
|
|
||||||
// setters
|
// setters
|
||||||
inline void SetExpiry(PRInt64 aExpiry) { mExpiry = aExpiry; }
|
inline void SetExpiry(PRInt64 aExpiry) { mExpiry = aExpiry; }
|
||||||
|
inline void SetLastAccessed(PRInt64 aTime) { mLastAccessed = aTime; }
|
||||||
inline void SetIsSession(PRBool aIsSession) { mIsSession = aIsSession; }
|
inline void SetIsSession(PRBool aIsSession) { mIsSession = aIsSession; }
|
||||||
// set the creation id manually, overriding the monotonicity checks in Create().
|
// set the creation id manually, overriding the monotonicity checks in Create().
|
||||||
// use with caution!
|
// use with caution!
|
||||||
|
@ -142,6 +145,7 @@ class nsCookie : public nsICookie2
|
||||||
const char *mPath;
|
const char *mPath;
|
||||||
const char *mEnd;
|
const char *mEnd;
|
||||||
PRInt64 mExpiry;
|
PRInt64 mExpiry;
|
||||||
|
PRInt64 mLastAccessed;
|
||||||
// creation id is unique for each cookie and approximately represents the cookie
|
// creation id is unique for each cookie and approximately represents the cookie
|
||||||
// creation time, in microseconds.
|
// creation time, in microseconds.
|
||||||
PRInt64 mCreationID;
|
PRInt64 mCreationID;
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
// vim:ts=2:sw=2:et:
|
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
|
||||||
/* ***** BEGIN LICENSE BLOCK *****
|
/* ***** BEGIN LICENSE BLOCK *****
|
||||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||||
*
|
*
|
||||||
|
@ -83,7 +82,9 @@
|
||||||
static const char kHttpOnlyPrefix[] = "#HttpOnly_";
|
static const char kHttpOnlyPrefix[] = "#HttpOnly_";
|
||||||
|
|
||||||
static const char kCookieFileName[] = "cookies.sqlite";
|
static const char kCookieFileName[] = "cookies.sqlite";
|
||||||
#define COOKIES_SCHEMA_VERSION 1
|
#define COOKIES_SCHEMA_VERSION 2
|
||||||
|
|
||||||
|
static const PRInt64 kCookieStaleThreshold = 60 * PR_USEC_PER_SEC; // 1 minute in microseconds
|
||||||
|
|
||||||
static const char kOldCookieFileName[] = "cookies.txt";
|
static const char kOldCookieFileName[] = "cookies.txt";
|
||||||
|
|
||||||
|
@ -126,7 +127,6 @@ struct nsCookieAttributes
|
||||||
nsCAutoString expires;
|
nsCAutoString expires;
|
||||||
nsCAutoString maxage;
|
nsCAutoString maxage;
|
||||||
PRInt64 expiryTime;
|
PRInt64 expiryTime;
|
||||||
PRInt64 creationID;
|
|
||||||
PRBool isSession;
|
PRBool isSession;
|
||||||
PRBool isSecure;
|
PRBool isSecure;
|
||||||
PRBool isHttpOnly;
|
PRBool isHttpOnly;
|
||||||
|
@ -162,17 +162,17 @@ struct nsListIter
|
||||||
struct nsEnumerationData
|
struct nsEnumerationData
|
||||||
{
|
{
|
||||||
nsEnumerationData(PRInt64 aCurrentTime,
|
nsEnumerationData(PRInt64 aCurrentTime,
|
||||||
PRInt64 aOldestID)
|
PRInt64 aOldestTime)
|
||||||
: currentTime(aCurrentTime)
|
: currentTime(aCurrentTime)
|
||||||
, oldestID(aOldestID)
|
, oldestTime(aOldestTime)
|
||||||
, iter(nsnull, nsnull, nsnull) {}
|
, iter(nsnull, nsnull, nsnull) {}
|
||||||
|
|
||||||
// the current time
|
// the current time, in seconds
|
||||||
PRInt64 currentTime;
|
PRInt64 currentTime;
|
||||||
|
|
||||||
// oldest creation id in the cookie list. use aOldestID = LL_MAXINT
|
// oldest lastAccessed time in the cookie list. use aOldestTime = LL_MAXINT
|
||||||
// to enable this search, LL_MININT to disable it.
|
// to enable this search, LL_MININT to disable it.
|
||||||
PRInt64 oldestID;
|
PRInt64 oldestTime;
|
||||||
|
|
||||||
// an iterator object that points to the desired cookie
|
// an iterator object that points to the desired cookie
|
||||||
nsListIter iter;
|
nsListIter iter;
|
||||||
|
@ -482,59 +482,65 @@ nsCookieService::InitDB()
|
||||||
PRInt32 dbSchemaVersion;
|
PRInt32 dbSchemaVersion;
|
||||||
rv = mDBConn->GetSchemaVersion(&dbSchemaVersion);
|
rv = mDBConn->GetSchemaVersion(&dbSchemaVersion);
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
||||||
if (dbSchemaVersion == 0) {
|
|
||||||
NS_WARNING("couldn't get schema version!");
|
|
||||||
|
|
||||||
// the table may be usable; someone might've just clobbered the schema
|
|
||||||
// version. we can treat this case like a downgrade using the codepath
|
|
||||||
// below, by verifying the columns we care about are all there. for now,
|
|
||||||
// re-set the schema version in the db, in case the checks succeed (if
|
|
||||||
// they don't, we're dropping the table anyway).
|
|
||||||
rv = mDBConn->SetSchemaVersion(COOKIES_SCHEMA_VERSION);
|
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
|
||||||
|
|
||||||
// set this to a large number, to force the downgrade codepath
|
switch (dbSchemaVersion) {
|
||||||
dbSchemaVersion = PR_INT32_MAX;
|
// upgrading.
|
||||||
}
|
// every time you increment the database schema, you need to implement
|
||||||
|
// the upgrading code from the previous version to the new one.
|
||||||
|
case 1:
|
||||||
|
{
|
||||||
|
// add the lastAccessed column to the table
|
||||||
|
rv = mDBConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
|
||||||
|
"ALTER TABLE moz_cookies ADD lastAccessed INTEGER"));
|
||||||
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
||||||
if (dbSchemaVersion != COOKIES_SCHEMA_VERSION) {
|
// update the schema version
|
||||||
// migration how-to:
|
rv = mDBConn->SetSchemaVersion(COOKIES_SCHEMA_VERSION);
|
||||||
//
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
// 1. increment COOKIES_SCHEMA_VERSION.
|
}
|
||||||
// 2. implement a method that performs up/sidegrade to your version
|
// fall through to the next upgrade
|
||||||
// from the current version.
|
|
||||||
|
|
||||||
if (dbSchemaVersion > COOKIES_SCHEMA_VERSION) {
|
case COOKIES_SCHEMA_VERSION:
|
||||||
// downgrading.
|
break;
|
||||||
// if columns have been added to the table, we can still use the ones we
|
|
||||||
// understand safely. if columns have been deleted or altered, just
|
case 0:
|
||||||
// blow away the table and start from scratch! if you change the way
|
{
|
||||||
// a column is interpreted, make sure you also change its name so this
|
NS_WARNING("couldn't get schema version!");
|
||||||
// check will catch it.
|
|
||||||
|
// the table may be usable; someone might've just clobbered the schema
|
||||||
// NOTE: if you change the code below, make sure the db schema version
|
// version. we can treat this case like a downgrade using the codepath
|
||||||
// getter above still falls through to this codepath on failure!
|
// below, by verifying the columns we care about are all there. for now,
|
||||||
|
// re-set the schema version in the db, in case the checks succeed (if
|
||||||
|
// they don't, we're dropping the table anyway).
|
||||||
|
rv = mDBConn->SetSchemaVersion(COOKIES_SCHEMA_VERSION);
|
||||||
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
}
|
||||||
|
// fall through to downgrade check
|
||||||
|
|
||||||
|
// downgrading.
|
||||||
|
// if columns have been added to the table, we can still use the ones we
|
||||||
|
// understand safely. if columns have been deleted or altered, just
|
||||||
|
// blow away the table and start from scratch! if you change the way
|
||||||
|
// a column is interpreted, make sure you also change its name so this
|
||||||
|
// check will catch it.
|
||||||
|
default:
|
||||||
|
{
|
||||||
// check if all the expected columns exist
|
// check if all the expected columns exist
|
||||||
nsCOMPtr<mozIStorageStatement> stmt;
|
nsCOMPtr<mozIStorageStatement> stmt;
|
||||||
rv = mDBConn->CreateStatement(NS_LITERAL_CSTRING(
|
rv = mDBConn->CreateStatement(NS_LITERAL_CSTRING(
|
||||||
"SELECT id, name, value, host, path, expiry, isSecure, isHttpOnly "
|
"SELECT id, name, value, host, path, expiry, isSecure, isHttpOnly "
|
||||||
"FROM moz_cookies"), getter_AddRefs(stmt));
|
"FROM moz_cookies"), getter_AddRefs(stmt));
|
||||||
if (NS_SUCCEEDED(rv)) {
|
if (NS_SUCCEEDED(rv))
|
||||||
PRBool hasResult;
|
break;
|
||||||
rv = stmt->ExecuteStep(&hasResult);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (NS_FAILED(rv)) {
|
|
||||||
// our columns aren't there - drop the table!
|
|
||||||
rv = mDBConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING("DROP TABLE moz_cookies"));
|
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
|
||||||
|
|
||||||
rv = CreateTable();
|
// our columns aren't there - drop the table!
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
rv = mDBConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING("DROP TABLE moz_cookies"));
|
||||||
}
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
||||||
|
rv = CreateTable();
|
||||||
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -544,14 +550,18 @@ nsCookieService::InitDB()
|
||||||
// cache frequently used statements (for insertion, deletion, and updating)
|
// cache frequently used statements (for insertion, deletion, and updating)
|
||||||
rv = mDBConn->CreateStatement(NS_LITERAL_CSTRING(
|
rv = mDBConn->CreateStatement(NS_LITERAL_CSTRING(
|
||||||
"INSERT INTO moz_cookies "
|
"INSERT INTO moz_cookies "
|
||||||
"(id, name, value, host, path, expiry, isSecure, isHttpOnly) "
|
"(id, name, value, host, path, expiry, lastAccessed, isSecure, isHttpOnly) "
|
||||||
"VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8)"), getter_AddRefs(mStmtInsert));
|
"VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8, ?9)"), getter_AddRefs(mStmtInsert));
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
||||||
rv = mDBConn->CreateStatement(NS_LITERAL_CSTRING(
|
rv = mDBConn->CreateStatement(NS_LITERAL_CSTRING(
|
||||||
"DELETE FROM moz_cookies WHERE id = ?1"), getter_AddRefs(mStmtDelete));
|
"DELETE FROM moz_cookies WHERE id = ?1"), getter_AddRefs(mStmtDelete));
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
||||||
|
rv = mDBConn->CreateStatement(NS_LITERAL_CSTRING(
|
||||||
|
"UPDATE moz_cookies SET lastAccessed = ?1 WHERE id = ?2"), getter_AddRefs(mStmtUpdate));
|
||||||
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
||||||
// check whether to import or just read in the db
|
// check whether to import or just read in the db
|
||||||
if (tableExists)
|
if (tableExists)
|
||||||
return Read();
|
return Read();
|
||||||
|
@ -580,7 +590,7 @@ nsCookieService::CreateTable()
|
||||||
return mDBConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
|
return mDBConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
|
||||||
"CREATE TABLE moz_cookies ("
|
"CREATE TABLE moz_cookies ("
|
||||||
"id INTEGER PRIMARY KEY, name TEXT, value TEXT, host TEXT, path TEXT,"
|
"id INTEGER PRIMARY KEY, name TEXT, value TEXT, host TEXT, path TEXT,"
|
||||||
"expiry INTEGER, isSecure INTEGER, isHttpOnly INTEGER)"));
|
"expiry INTEGER, lastAccessed INTEGER, isSecure INTEGER, isHttpOnly INTEGER)"));
|
||||||
}
|
}
|
||||||
|
|
||||||
nsCookieService::~nsCookieService()
|
nsCookieService::~nsCookieService()
|
||||||
|
@ -599,13 +609,14 @@ nsCookieService::Observe(nsISupports *aSubject,
|
||||||
// or is going away because the application is shutting down.
|
// or is going away because the application is shutting down.
|
||||||
RemoveAllFromMemory();
|
RemoveAllFromMemory();
|
||||||
|
|
||||||
if (!nsCRT::strcmp(aData, NS_LITERAL_STRING("shutdown-cleanse").get()) && mDBConn)
|
if (!nsCRT::strcmp(aData, NS_LITERAL_STRING("shutdown-cleanse").get()) && mDBConn) {
|
||||||
// clear the cookie file
|
// clear the cookie file
|
||||||
if (mDBConn) {
|
if (mDBConn) {
|
||||||
nsresult rv = mDBConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING("DELETE FROM moz_cookies"));
|
nsresult rv = mDBConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING("DELETE FROM moz_cookies"));
|
||||||
if (NS_FAILED(rv))
|
if (NS_FAILED(rv))
|
||||||
NS_WARNING("db delete failed");
|
NS_WARNING("db delete failed");
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
} else if (!strcmp(aTopic, "profile-do-change")) {
|
} else if (!strcmp(aTopic, "profile-do-change")) {
|
||||||
// the profile has already changed; init the db from the new location
|
// the profile has already changed; init the db from the new location
|
||||||
|
@ -825,6 +836,7 @@ nsCookieService::Add(const nsACString &aDomain,
|
||||||
nsCookie::Create(aName, aValue, aDomain, aPath,
|
nsCookie::Create(aName, aValue, aDomain, aPath,
|
||||||
aExpiry,
|
aExpiry,
|
||||||
currentTimeInUsec,
|
currentTimeInUsec,
|
||||||
|
currentTimeInUsec,
|
||||||
aIsSession,
|
aIsSession,
|
||||||
aIsSecure,
|
aIsSecure,
|
||||||
aIsHttpOnly);
|
aIsHttpOnly);
|
||||||
|
@ -893,7 +905,7 @@ nsCookieService::Read()
|
||||||
// let the reading begin!
|
// let the reading begin!
|
||||||
nsCOMPtr<mozIStorageStatement> stmt;
|
nsCOMPtr<mozIStorageStatement> stmt;
|
||||||
rv = mDBConn->CreateStatement(NS_LITERAL_CSTRING(
|
rv = mDBConn->CreateStatement(NS_LITERAL_CSTRING(
|
||||||
"SELECT id, name, value, host, path, expiry, isSecure, isHttpOnly "
|
"SELECT id, name, value, host, path, expiry, lastAccessed, isSecure, isHttpOnly "
|
||||||
"FROM moz_cookies"), getter_AddRefs(stmt));
|
"FROM moz_cookies"), getter_AddRefs(stmt));
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
||||||
|
@ -908,13 +920,15 @@ nsCookieService::Read()
|
||||||
stmt->GetUTF8String(4, path);
|
stmt->GetUTF8String(4, path);
|
||||||
|
|
||||||
PRInt64 expiry = stmt->AsInt64(5);
|
PRInt64 expiry = stmt->AsInt64(5);
|
||||||
PRBool isSecure = stmt->AsInt32(6);
|
PRInt64 lastAccessed = stmt->AsInt64(6);
|
||||||
PRBool isHttpOnly = stmt->AsInt32(7);
|
PRBool isSecure = stmt->AsInt32(7);
|
||||||
|
PRBool isHttpOnly = stmt->AsInt32(8);
|
||||||
|
|
||||||
// create a new nsCookie and assign the data.
|
// create a new nsCookie and assign the data.
|
||||||
nsCookie* newCookie =
|
nsCookie* newCookie =
|
||||||
nsCookie::Create(name, value, host, path,
|
nsCookie::Create(name, value, host, path,
|
||||||
expiry,
|
expiry,
|
||||||
|
lastAccessed,
|
||||||
creationID,
|
creationID,
|
||||||
PR_FALSE,
|
PR_FALSE,
|
||||||
isSecure,
|
isSecure,
|
||||||
|
@ -964,12 +978,11 @@ nsCookieService::ImportCookies(nsIFile *aCookieFile)
|
||||||
PRBool isDomain, isHttpOnly = PR_FALSE;
|
PRBool isDomain, isHttpOnly = PR_FALSE;
|
||||||
PRUint32 originalCookieCount = mCookieCount;
|
PRUint32 originalCookieCount = mCookieCount;
|
||||||
|
|
||||||
// generate a creation id for all the cookies we're going to read in, by
|
PRInt64 currentTimeInUsec = PR_Now();
|
||||||
// using the current time and successively decrementing it, to keep
|
PRInt64 currentTime = currentTimeInUsec / PR_USEC_PER_SEC;
|
||||||
// the most-recently-used cookie ordering. the actual creation time is
|
// we use lastAccessedCounter to keep cookies in recently-used order,
|
||||||
// unknown, so this is the best we can do.
|
// so we start by initializing to currentTime (somewhat arbitrary)
|
||||||
PRInt64 creationIDCounter = PR_Now();
|
PRInt64 lastAccessedCounter = currentTimeInUsec;
|
||||||
PRInt64 currentTime = creationIDCounter / PR_USEC_PER_SEC;
|
|
||||||
|
|
||||||
/* file format is:
|
/* file format is:
|
||||||
*
|
*
|
||||||
|
@ -979,7 +992,9 @@ nsCookieService::ImportCookies(nsIFile *aCookieFile)
|
||||||
* isDomain is "TRUE" or "FALSE" (default to "FALSE")
|
* isDomain is "TRUE" or "FALSE" (default to "FALSE")
|
||||||
* isSecure is "TRUE" or "FALSE" (default to "TRUE")
|
* isSecure is "TRUE" or "FALSE" (default to "TRUE")
|
||||||
* expires is a PRInt64 integer
|
* expires is a PRInt64 integer
|
||||||
* note: cookie can contain tabs.
|
* note 1: cookie can contain tabs.
|
||||||
|
* note 2: cookies will be stored in order of lastAccessed time:
|
||||||
|
* most-recently used come first; least-recently-used come last.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -1035,13 +1050,17 @@ nsCookieService::ImportCookies(nsIFile *aCookieFile)
|
||||||
}
|
}
|
||||||
|
|
||||||
// create a new nsCookie and assign the data.
|
// create a new nsCookie and assign the data.
|
||||||
|
// we don't know the cookie creation time, so just use the current time;
|
||||||
|
// this is okay, since nsCookie::Create() will make sure the creation id
|
||||||
|
// ends up monotonically increasing.
|
||||||
nsRefPtr<nsCookie> newCookie =
|
nsRefPtr<nsCookie> newCookie =
|
||||||
nsCookie::Create(Substring(buffer, nameIndex, cookieIndex - nameIndex - 1),
|
nsCookie::Create(Substring(buffer, nameIndex, cookieIndex - nameIndex - 1),
|
||||||
Substring(buffer, cookieIndex, buffer.Length() - cookieIndex),
|
Substring(buffer, cookieIndex, buffer.Length() - cookieIndex),
|
||||||
host,
|
host,
|
||||||
Substring(buffer, pathIndex, secureIndex - pathIndex - 1),
|
Substring(buffer, pathIndex, secureIndex - pathIndex - 1),
|
||||||
expires,
|
expires,
|
||||||
creationIDCounter,
|
lastAccessedCounter,
|
||||||
|
currentTimeInUsec,
|
||||||
PR_FALSE,
|
PR_FALSE,
|
||||||
Substring(buffer, secureIndex, expiresIndex - secureIndex - 1).EqualsLiteral(kTrue),
|
Substring(buffer, secureIndex, expiresIndex - secureIndex - 1).EqualsLiteral(kTrue),
|
||||||
isHttpOnly);
|
isHttpOnly);
|
||||||
|
@ -1049,10 +1068,9 @@ nsCookieService::ImportCookies(nsIFile *aCookieFile)
|
||||||
return NS_ERROR_OUT_OF_MEMORY;
|
return NS_ERROR_OUT_OF_MEMORY;
|
||||||
}
|
}
|
||||||
|
|
||||||
// manually set the creation id. this is okay, since nsCookie::Create() will keep
|
// trick: preserve the most-recently-used cookie ordering,
|
||||||
// track of the largest id we've used, and we're setting it to a smaller
|
// by successively decrementing the lastAccessed time
|
||||||
// known unique one here.
|
lastAccessedCounter--;
|
||||||
newCookie->SetCreationID(--creationIDCounter);
|
|
||||||
|
|
||||||
if (originalCookieCount == 0)
|
if (originalCookieCount == 0)
|
||||||
AddCookieToList(newCookie);
|
AddCookieToList(newCookie);
|
||||||
|
@ -1122,9 +1140,11 @@ nsCookieService::GetCookieInternal(nsIURI *aHostURI,
|
||||||
|
|
||||||
nsCookie *cookie;
|
nsCookie *cookie;
|
||||||
nsAutoVoidArray foundCookieList;
|
nsAutoVoidArray foundCookieList;
|
||||||
PRInt64 currentTime = PR_Now() / PR_USEC_PER_SEC;
|
PRInt64 currentTimeInUsec = PR_Now();
|
||||||
|
PRInt64 currentTime = currentTimeInUsec / PR_USEC_PER_SEC;
|
||||||
const char *currentDot = hostFromURI.get();
|
const char *currentDot = hostFromURI.get();
|
||||||
const char *nextDot = currentDot + 1;
|
const char *nextDot = currentDot + 1;
|
||||||
|
PRBool stale = PR_FALSE;
|
||||||
|
|
||||||
// begin hash lookup, walking up the subdomain levels.
|
// begin hash lookup, walking up the subdomain levels.
|
||||||
// we use nextDot to force a lookup of the original host (without leading dot).
|
// we use nextDot to force a lookup of the original host (without leading dot).
|
||||||
|
@ -1172,8 +1192,10 @@ nsCookieService::GetCookieInternal(nsIURI *aHostURI,
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// all checks passed - add to list
|
// all checks passed - add to list and check if lastAccessed stamp needs updating
|
||||||
foundCookieList.AppendElement(cookie);
|
foundCookieList.AppendElement(cookie);
|
||||||
|
if (currentTimeInUsec - cookie->LastAccessed() > kCookieStaleThreshold)
|
||||||
|
stale = PR_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
currentDot = nextDot;
|
currentDot = nextDot;
|
||||||
|
@ -1182,13 +1204,31 @@ nsCookieService::GetCookieInternal(nsIURI *aHostURI,
|
||||||
|
|
||||||
} while (currentDot);
|
} while (currentDot);
|
||||||
|
|
||||||
|
PRInt32 count = foundCookieList.Count();
|
||||||
|
if (count == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// update lastAccessed timestamps. we only do this if the timestamp is stale
|
||||||
|
// by a certain amount, to avoid thrashing the db during pageload.
|
||||||
|
if (stale) {
|
||||||
|
// start a transaction on the storage db, to optimize updates.
|
||||||
|
// transaction will automically commit on completion.
|
||||||
|
mozStorageTransaction transaction(mDBConn, PR_TRUE);
|
||||||
|
|
||||||
|
for (PRInt32 i = 0; i < count; ++i) {
|
||||||
|
cookie = static_cast<nsCookie*>(foundCookieList.ElementAt(i));
|
||||||
|
|
||||||
|
if (currentTimeInUsec - cookie->LastAccessed() > kCookieStaleThreshold)
|
||||||
|
UpdateCookieInList(cookie, currentTime);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// return cookies in order of path length; longest to shortest.
|
// return cookies in order of path length; longest to shortest.
|
||||||
// this is required per RFC2109. if cookies match in length,
|
// this is required per RFC2109. if cookies match in length,
|
||||||
// then sort by creation time (see bug 236772).
|
// then sort by creation time (see bug 236772).
|
||||||
foundCookieList.Sort(compareCookiesForSending, nsnull);
|
foundCookieList.Sort(compareCookiesForSending, nsnull);
|
||||||
|
|
||||||
nsCAutoString cookieData;
|
nsCAutoString cookieData;
|
||||||
PRInt32 count = foundCookieList.Count();
|
|
||||||
for (PRInt32 i = 0; i < count; ++i) {
|
for (PRInt32 i = 0; i < count; ++i) {
|
||||||
cookie = static_cast<nsCookie*>(foundCookieList.ElementAt(i));
|
cookie = static_cast<nsCookie*>(foundCookieList.ElementAt(i));
|
||||||
|
|
||||||
|
@ -1242,9 +1282,7 @@ nsCookieService::SetCookieInternal(nsIURI *aHostURI,
|
||||||
// so we can handle them separately.
|
// so we can handle them separately.
|
||||||
PRBool newCookie = ParseAttributes(aCookieHeader, cookieAttributes);
|
PRBool newCookie = ParseAttributes(aCookieHeader, cookieAttributes);
|
||||||
|
|
||||||
// generate a creation id for the cookie
|
|
||||||
PRInt64 currentTimeInUsec = PR_Now();
|
PRInt64 currentTimeInUsec = PR_Now();
|
||||||
cookieAttributes.creationID = currentTimeInUsec;
|
|
||||||
|
|
||||||
// calculate expiry time of cookie.
|
// calculate expiry time of cookie.
|
||||||
cookieAttributes.isSession = GetExpiry(cookieAttributes, aServerTime,
|
cookieAttributes.isSession = GetExpiry(cookieAttributes, aServerTime,
|
||||||
|
@ -1278,7 +1316,8 @@ nsCookieService::SetCookieInternal(nsIURI *aHostURI,
|
||||||
cookieAttributes.host,
|
cookieAttributes.host,
|
||||||
cookieAttributes.path,
|
cookieAttributes.path,
|
||||||
cookieAttributes.expiryTime,
|
cookieAttributes.expiryTime,
|
||||||
cookieAttributes.creationID,
|
currentTimeInUsec,
|
||||||
|
currentTimeInUsec,
|
||||||
cookieAttributes.isSession,
|
cookieAttributes.isSession,
|
||||||
cookieAttributes.isSecure,
|
cookieAttributes.isSecure,
|
||||||
cookieAttributes.isHttpOnly);
|
cookieAttributes.isHttpOnly);
|
||||||
|
@ -1360,6 +1399,10 @@ nsCookieService::AddInternal(nsCookie *aCookie,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// preserve creation time of cookie
|
||||||
|
if (oldCookie)
|
||||||
|
aCookie->SetCreationID(oldCookie->CreationID());
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
// check if cookie has already expired
|
// check if cookie has already expired
|
||||||
if (aCookie->Expiry() <= aCurrentTime) {
|
if (aCookie->Expiry() <= aCurrentTime) {
|
||||||
|
@ -1381,7 +1424,7 @@ nsCookieService::AddInternal(nsCookie *aCookie,
|
||||||
// check if we still have to get rid of something
|
// check if we still have to get rid of something
|
||||||
if (mCookieCount >= mMaxNumberOfCookies) {
|
if (mCookieCount >= mMaxNumberOfCookies) {
|
||||||
// find the position of the oldest cookie, and remove it
|
// find the position of the oldest cookie, and remove it
|
||||||
data.oldestID = LL_MAXINT;
|
data.oldestTime = LL_MAXINT;
|
||||||
FindOldestCookie(data);
|
FindOldestCookie(data);
|
||||||
oldCookie = data.iter.current;
|
oldCookie = data.iter.current;
|
||||||
RemoveCookieFromList(data.iter);
|
RemoveCookieFromList(data.iter);
|
||||||
|
@ -2091,8 +2134,8 @@ nsCookieService::CountCookiesFromHostInternal(const nsACString &aHost,
|
||||||
++countFromHost;
|
++countFromHost;
|
||||||
|
|
||||||
// check if we've found the oldest cookie so far
|
// check if we've found the oldest cookie so far
|
||||||
if (aData.oldestID > iter.current->CreationID()) {
|
if (aData.oldestTime > iter.current->LastAccessed()) {
|
||||||
aData.oldestID = iter.current->CreationID();
|
aData.oldestTime = iter.current->LastAccessed();
|
||||||
aData.iter = iter;
|
aData.iter = iter;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2205,10 +2248,13 @@ bindCookieParameters(mozIStorageStatement* aStmt, const nsCookie* aCookie)
|
||||||
rv = aStmt->BindInt64Parameter(5, aCookie->Expiry());
|
rv = aStmt->BindInt64Parameter(5, aCookie->Expiry());
|
||||||
if (NS_FAILED(rv)) return rv;
|
if (NS_FAILED(rv)) return rv;
|
||||||
|
|
||||||
rv = aStmt->BindInt32Parameter(6, aCookie->IsSecure());
|
rv = aStmt->BindInt64Parameter(6, aCookie->LastAccessed());
|
||||||
if (NS_FAILED(rv)) return rv;
|
if (NS_FAILED(rv)) return rv;
|
||||||
|
|
||||||
rv = aStmt->BindInt32Parameter(7, aCookie->IsHttpOnly());
|
rv = aStmt->BindInt32Parameter(7, aCookie->IsSecure());
|
||||||
|
if (NS_FAILED(rv)) return rv;
|
||||||
|
|
||||||
|
rv = aStmt->BindInt32Parameter(8, aCookie->IsHttpOnly());
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2248,6 +2294,33 @@ nsCookieService::AddCookieToList(nsCookie *aCookie, PRBool aWriteToDB)
|
||||||
return PR_TRUE;
|
return PR_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
nsCookieService::UpdateCookieInList(nsCookie *aCookie, PRInt64 aLastAccessed)
|
||||||
|
{
|
||||||
|
// update the lastAccessed timestamp
|
||||||
|
aCookie->SetLastAccessed(aLastAccessed);
|
||||||
|
|
||||||
|
// if it's a non-session cookie, update it in the db too
|
||||||
|
if (!aCookie->IsSession() && mStmtUpdate) {
|
||||||
|
// use our cached sqlite "update" statement
|
||||||
|
mozStorageStatementScoper scoper(mStmtUpdate);
|
||||||
|
|
||||||
|
nsresult rv = mStmtUpdate->BindInt64Parameter(0, aLastAccessed);
|
||||||
|
if (NS_SUCCEEDED(rv)) {
|
||||||
|
rv = mStmtUpdate->BindInt64Parameter(1, aCookie->CreationID());
|
||||||
|
if (NS_SUCCEEDED(rv)) {
|
||||||
|
PRBool hasResult;
|
||||||
|
rv = mStmtUpdate->ExecuteStep(&hasResult);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (NS_FAILED(rv)) {
|
||||||
|
NS_WARNING("db update failed!");
|
||||||
|
COOKIE_LOGSTRING(PR_LOG_WARNING, ("UpdateCookieInList(): updating db gave error %x", rv));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
PR_STATIC_CALLBACK(PLDHashOperator)
|
PR_STATIC_CALLBACK(PLDHashOperator)
|
||||||
findOldestCallback(nsCookieEntry *aEntry,
|
findOldestCallback(nsCookieEntry *aEntry,
|
||||||
void *aArg)
|
void *aArg)
|
||||||
|
@ -2255,8 +2328,8 @@ findOldestCallback(nsCookieEntry *aEntry,
|
||||||
nsEnumerationData *data = static_cast<nsEnumerationData*>(aArg);
|
nsEnumerationData *data = static_cast<nsEnumerationData*>(aArg);
|
||||||
for (nsListIter iter(aEntry, nsnull, aEntry->Head()); iter.current; ++iter) {
|
for (nsListIter iter(aEntry, nsnull, aEntry->Head()); iter.current; ++iter) {
|
||||||
// check if we've found the oldest cookie so far
|
// check if we've found the oldest cookie so far
|
||||||
if (data->oldestID > iter.current->CreationID()) {
|
if (data->oldestTime > iter.current->LastAccessed()) {
|
||||||
data->oldestID = iter.current->CreationID();
|
data->oldestTime = iter.current->LastAccessed();
|
||||||
data->iter = iter;
|
data->iter = iter;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2268,3 +2341,4 @@ nsCookieService::FindOldestCookie(nsEnumerationData &aData)
|
||||||
{
|
{
|
||||||
mHostTable.EnumerateEntries(findOldestCallback, &aData);
|
mHostTable.EnumerateEntries(findOldestCallback, &aData);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -173,6 +173,7 @@ class nsCookieService : public nsICookieService
|
||||||
void AddInternal(nsCookie *aCookie, PRInt64 aCurrentTime, nsIURI *aHostURI, const char *aCookieHeader, PRBool aFromHttp);
|
void AddInternal(nsCookie *aCookie, PRInt64 aCurrentTime, nsIURI *aHostURI, const char *aCookieHeader, PRBool aFromHttp);
|
||||||
void RemoveCookieFromList(nsListIter &aIter);
|
void RemoveCookieFromList(nsListIter &aIter);
|
||||||
PRBool AddCookieToList(nsCookie *aCookie, PRBool aWriteToDB = PR_TRUE);
|
PRBool AddCookieToList(nsCookie *aCookie, PRBool aWriteToDB = PR_TRUE);
|
||||||
|
void UpdateCookieInList(nsCookie *aCookie, PRInt64 aLastAccessed);
|
||||||
static PRBool GetTokenValue(nsASingleFragmentCString::const_char_iterator &aIter, nsASingleFragmentCString::const_char_iterator &aEndIter, nsDependentCSubstring &aTokenString, nsDependentCSubstring &aTokenValue, PRBool &aEqualsFound);
|
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);
|
static PRBool ParseAttributes(nsDependentCString &aCookieHeader, nsCookieAttributes &aCookie);
|
||||||
static PRBool IsIPAddress(const nsAFlatCString &aHost);
|
static PRBool IsIPAddress(const nsAFlatCString &aHost);
|
||||||
|
@ -195,6 +196,7 @@ class nsCookieService : public nsICookieService
|
||||||
nsCOMPtr<mozIStorageConnection> mDBConn;
|
nsCOMPtr<mozIStorageConnection> mDBConn;
|
||||||
nsCOMPtr<mozIStorageStatement> mStmtInsert;
|
nsCOMPtr<mozIStorageStatement> mStmtInsert;
|
||||||
nsCOMPtr<mozIStorageStatement> mStmtDelete;
|
nsCOMPtr<mozIStorageStatement> mStmtDelete;
|
||||||
|
nsCOMPtr<mozIStorageStatement> mStmtUpdate;
|
||||||
nsCOMPtr<nsIObserverService> mObserverService;
|
nsCOMPtr<nsIObserverService> mObserverService;
|
||||||
nsCOMPtr<nsICookiePermission> mPermissionService;
|
nsCOMPtr<nsICookiePermission> mPermissionService;
|
||||||
|
|
||||||
|
|
|
@ -786,7 +786,7 @@ main(PRInt32 argc, char *argv[])
|
||||||
|
|
||||||
// test that cookies are
|
// test that cookies are
|
||||||
// a) returned by order of creation time (oldest first, newest last)
|
// a) returned by order of creation time (oldest first, newest last)
|
||||||
// b) evicted by order of creation time, if the limit on cookies per host (50) is reached
|
// b) evicted by order of lastAccessed time, if the limit on cookies per host (50) is reached
|
||||||
nsCAutoString name;
|
nsCAutoString name;
|
||||||
nsCAutoString expected;
|
nsCAutoString expected;
|
||||||
for (PRInt32 i = 0; i < 60; ++i) {
|
for (PRInt32 i = 0; i < 60; ++i) {
|
||||||
|
@ -804,7 +804,7 @@ main(PRInt32 argc, char *argv[])
|
||||||
GetACookie(cookieService, "http://creation.ordering.tests/", nsnull, getter_Copies(cookie));
|
GetACookie(cookieService, "http://creation.ordering.tests/", nsnull, getter_Copies(cookie));
|
||||||
rv[0] = CheckResult(cookie.get(), MUST_EQUAL, expected.get());
|
rv[0] = CheckResult(cookie.get(), MUST_EQUAL, expected.get());
|
||||||
|
|
||||||
// test that cookies are evicted by order of creation time, if the limit on total cookies
|
// test that cookies are evicted by order of lastAccessed time, if the limit on total cookies
|
||||||
// (1000) is reached
|
// (1000) is reached
|
||||||
nsCAutoString host;
|
nsCAutoString host;
|
||||||
for (PRInt32 i = 0; i < 1010; ++i) {
|
for (PRInt32 i = 0; i < 1010; ++i) {
|
||||||
|
|
Загрузка…
Ссылка в новой задаче