--- a/extensions/cookie/test/unit/head_cookies.js
+++ b/extensions/cookie/test/unit/head_cookies.js
@@ -12,62 +12,54 @@ const Cr = Components.results;
XPCOMUtils.defineLazyServiceGetter(Services, "cookies",
"@mozilla.org/cookieService;1",
"nsICookieService");
XPCOMUtils.defineLazyServiceGetter(Services, "cookiemgr",
"@mozilla.org/cookiemanager;1",
"nsICookieManager2");
-function _observer(generator, service, topic) {
- Services.obs.addObserver(this, topic, false);
+// Close and reload the cookie database.
+function do_reload_profile(generator, profile, cleanse) {
+ function _observer(generator, service, topic) {
+ Services.obs.addObserver(this, topic, false);
- this.service = service;
- this.generator = generator;
- this.topic = topic;
-}
+ this.service = service;
+ this.generator = generator;
+ this.topic = topic;
+ }
-_observer.prototype = {
- observe: function (subject, topic, data) {
- do_check_eq(this.topic, topic);
+ _observer.prototype = {
+ observe: function (subject, topic, data) {
+ do_check_eq(this.topic, topic);
- Services.obs.removeObserver(this, this.topic);
+ Services.obs.removeObserver(this, this.topic);
- // Continue executing the generator function.
- if (this.generator)
+ // Fire the notification to reload the database, and continue executing
+ // the generator function.
+ this.service.observe(null, "profile-do-change", "");
this.generator.next();
- this.generator = null;
- this.service = null;
- this.topic = null;
+ this.generator = null;
+ this.service = null;
+ this.topic = null;
+ }
}
-}
-// Close the cookie database. If a generator is supplied, it will be invoked
-// once the close is complete.
-function do_close_profile(generator, cleanse) {
+ let dbfile = profile.QueryInterface(Ci.nsILocalFile).clone();
+ dbfile.append("cookies.sqlite");
+
// Register an observer for db close.
let service = Services.cookies.QueryInterface(Ci.nsIObserver);
let obs = new _observer(generator, service, "cookie-db-closed");
// Close the db.
service.observe(null, "profile-before-change", cleanse ? cleanse : "");
}
-// Load the cookie database. If a generator is supplied, it will be invoked
-// once the load is complete.
-function do_load_profile(generator) {
- // Register an observer for read completion.
- let service = Services.cookies.QueryInterface(Ci.nsIObserver);
- let obs = new _observer(generator, service, "cookie-db-read");
-
- // Load the profile.
- service.observe(null, "profile-do-change", "");
-}
-
// Set four cookies; with & without channel, http and non-http; and test
// the cookie count against 'expected' after each set.
function do_set_cookies(uri, channel, session, expected) {
let suffix = session ? "" : "; max-age=1000";
// without channel
Services.cookies.setCookieString(uri, null, "oh=hai" + suffix, null);
do_check_eq(Services.cookiemgr.countCookiesFromHost(uri.host), expected[0]);
@@ -76,22 +68,8 @@ function do_set_cookies(uri, channel, se
do_check_eq(Services.cookiemgr.countCookiesFromHost(uri.host), expected[1]);
// without channel, from http
Services.cookies.setCookieStringFromHttp(uri, null, null, "cheez=burger" + suffix, null, null);
do_check_eq(Services.cookiemgr.countCookiesFromHost(uri.host), expected[2]);
// with channel, from http
Services.cookies.setCookieStringFromHttp(uri, null, null, "hot=dog" + suffix, null, channel);
do_check_eq(Services.cookiemgr.countCookiesFromHost(uri.host), expected[3]);
}
-
-function do_count_enumerator(enumerator) {
- let i = 0;
- while (enumerator.hasMoreElements()) {
- enumerator.getNext();
- ++i;
- }
- return i;
-}
-
-function do_count_cookies() {
- return do_count_enumerator(Services.cookiemgr.enumerator);
-}
-
--- a/extensions/cookie/test/unit/test_cookies_persistence.js
+++ b/extensions/cookie/test/unit/test_cookies_persistence.js
@@ -42,44 +42,33 @@ function do_run_test() {
// test with cookies enabled, and third party cookies persistent.
Services.prefs.setIntPref("network.cookie.cookieBehavior", 0);
Services.prefs.setBoolPref("network.cookie.thirdparty.sessionOnly", false);
do_set_cookies(uri1, channel1, false, [1, 2, 3, 4]);
do_set_cookies(uri2, channel2, true, [1, 2, 3, 4]);
// fake a profile change
- do_close_profile(test_generator);
+ do_reload_profile(test_generator, profile);
yield;
- do_load_profile();
- do_check_eq(Services.cookies.countCookiesFromHost(uri1.host), 4);
- do_check_eq(Services.cookies.countCookiesFromHost(uri2.host), 0);
-
- // Again, but don't wait for the async close to complete. This should always
- // work, since we blocked on close above and haven't kicked off any writes
- // since then.
- do_close_profile();
- do_load_profile();
do_check_eq(Services.cookies.countCookiesFromHost(uri1.host), 4);
do_check_eq(Services.cookies.countCookiesFromHost(uri2.host), 0);
// cleanse them
- do_close_profile(test_generator, "shutdown-cleanse");
+ do_reload_profile(test_generator, profile, "shutdown-cleanse");
yield;
- do_load_profile();
do_check_eq(Services.cookies.countCookiesFromHost(uri1.host), 0);
do_check_eq(Services.cookies.countCookiesFromHost(uri2.host), 0);
// test with cookies set to session-only
Services.prefs.setIntPref("network.cookie.lifetimePolicy", 2);
do_set_cookies(uri1, channel1, false, [1, 2, 3, 4]);
do_set_cookies(uri2, channel2, true, [1, 2, 3, 4]);
// fake a profile change
- do_close_profile(test_generator);
+ do_reload_profile(test_generator, profile);
yield;
- do_load_profile();
do_check_eq(Services.cookies.countCookiesFromHost(uri1.host), 0);
do_check_eq(Services.cookies.countCookiesFromHost(uri2.host), 0);
finish_test();
}
deleted file mode 100644
--- a/extensions/cookie/test/unit/test_cookies_read.js
+++ /dev/null
@@ -1,67 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
- * http://creativecommons.org/publicdomain/zero/1.0/
- */
-
-// test cookie database asynchronous read operation.
-
-let test_generator = do_run_test();
-
-function run_test() {
- do_test_pending();
- test_generator.next();
-}
-
-function finish_test() {
- do_execute_soon(function() {
- test_generator.close();
- do_test_finished();
- });
-}
-
-function do_run_test() {
- // Set up a profile.
- let profile = do_get_profile();
-
- for (let i = 0; i < 3000; ++i) {
- let uri = NetUtil.newURI("http://" + i + ".com/");
- Services.cookies.setCookieString(uri, null, "oh=hai; max-age=1000", null);
- }
-
- do_check_eq(do_count_cookies(), 3000);
-
- // fake a profile change
- do_close_profile(test_generator);
- yield;
- do_load_profile();
-
- // test a few random cookies
- do_check_eq(Services.cookiemgr.countCookiesFromHost("2000.com"), 1);
- do_check_eq(Services.cookiemgr.countCookiesFromHost("abc.com"), 0);
- do_check_eq(Services.cookiemgr.countCookiesFromHost("100.com"), 1);
- do_check_eq(Services.cookiemgr.countCookiesFromHost("1400.com"), 1);
- do_check_eq(Services.cookiemgr.countCookiesFromHost("xyz.com"), 0);
-
- // force synchronous load of everything
- do_check_eq(do_count_cookies(), 3000);
-
- // check that everything's precisely correct
- for (let i = 0; i < 3000; ++i) {
- let host = i.toString() + ".com";
- do_check_eq(Services.cookiemgr.countCookiesFromHost(host), 1);
- }
-
- // reload again, but wait for async read completion
- do_close_profile(test_generator);
- yield;
- do_load_profile(test_generator);
- yield;
-
- // check that everything's precisely correct
- for (let i = 0; i < 3000; ++i) {
- let host = i.toString() + ".com";
- do_check_eq(Services.cookiemgr.countCookiesFromHost(host), 1);
- }
-
- finish_test();
-}
-
--- a/extensions/cookie/test/unit/test_cookies_thirdparty_session.js
+++ b/extensions/cookie/test/unit/test_cookies_thirdparty_session.js
@@ -42,36 +42,33 @@ function do_run_test() {
// test with cookies enabled, and third party cookies persistent.
Services.prefs.setIntPref("network.cookie.cookieBehavior", 0);
Services.prefs.setBoolPref("network.cookie.thirdparty.sessionOnly", false);
do_set_cookies(uri1, channel2, false, [1, 2, 3, 4]);
do_set_cookies(uri2, channel1, true, [1, 2, 3, 4]);
// fake a profile change
- do_close_profile(test_generator);
+ do_reload_profile(test_generator, profile);
yield;
- do_load_profile();
do_check_eq(Services.cookies.countCookiesFromHost(uri1.host), 4);
do_check_eq(Services.cookies.countCookiesFromHost(uri2.host), 0);
// cleanse them
- do_close_profile(test_generator, "shutdown-cleanse");
+ do_reload_profile(test_generator, profile, "shutdown-cleanse");
yield;
- do_load_profile();
do_check_eq(Services.cookies.countCookiesFromHost(uri1.host), 0);
do_check_eq(Services.cookies.countCookiesFromHost(uri2.host), 0);
// test with third party cookies for session only.
Services.prefs.setBoolPref("network.cookie.thirdparty.sessionOnly", true);
do_set_cookies(uri1, channel2, false, [1, 2, 3, 4]);
do_set_cookies(uri2, channel1, true, [1, 2, 3, 4]);
// fake a profile change
- do_close_profile(test_generator);
+ do_reload_profile(test_generator, profile);
yield;
- do_load_profile();
do_check_eq(Services.cookies.countCookiesFromHost(uri1.host), 0);
do_check_eq(Services.cookies.countCookiesFromHost(uri2.host), 0);
finish_test();
}
--- a/netwerk/cookie/nsCookieService.cpp
+++ b/netwerk/cookie/nsCookieService.cpp
@@ -82,18 +82,16 @@
using namespace mozilla::net;
/******************************************************************************
* nsCookieService impl:
* useful types & constants
******************************************************************************/
-static nsCookieService *gCookieService;
-
// XXX_hack. See bug 178993.
// This is a hack to hide HttpOnly cookies from older browsers
static const char kHttpOnlyPrefix[] = "#HttpOnly_";
static const char kCookieFileName[] = "cookies.sqlite";
#define COOKIES_SCHEMA_VERSION 3
static const PRInt64 kCookieStaleThreshold = 60 * PR_USEC_PER_SEC; // 1 minute in microseconds
@@ -354,50 +352,51 @@ LogSuccess(PRBool aSetCookie, nsIURI *aH
NS_ASSERTION(NS_SUCCEEDED(__rv), msg); \
PR_smprintf_free(msg); \
} \
PR_END_MACRO
#else
#define NS_ASSERT_SUCCESS(res) PR_BEGIN_MACRO /* nothing */ PR_END_MACRO
#endif
+namespace {
/******************************************************************************
- * DBListenerErrorHandler impl:
+ * DBListenerErrorHandler imp:
* Parent class for our async storage listeners that handles the logging of
* errors.
******************************************************************************/
class DBListenerErrorHandler : public mozIStorageStatementCallback
{
protected:
virtual const char *GetOpType() = 0;
public:
NS_DECL_ISUPPORTS
NS_IMETHOD HandleError(mozIStorageError* aError)
{
- // XXX Ignore corruption handling for now. See bug 547031.
#ifdef PR_LOGGING
PRInt32 result = -1;
aError->GetResult(&result);
nsCAutoString message;
aError->GetMessage(message);
COOKIE_LOGSTRING(PR_LOG_WARNING,
("Error %d occurred while performing a %s operation. Message: `%s`\n",
result, GetOpType(), message.get()));
#endif
return NS_OK;
}
};
NS_IMPL_ISUPPORTS1(DBListenerErrorHandler, mozIStorageStatementCallback)
/******************************************************************************
- * InsertCookieDBListener impl:
- * mozIStorageStatementCallback used to track asynchronous insertion operations.
+ * InsertCookieDBListener imp:
+ * Static mozIStorageStatementCallback used to track asynchronous insertion
+ * operations.
******************************************************************************/
class InsertCookieDBListener : public DBListenerErrorHandler
{
protected:
virtual const char *GetOpType() { return "INSERT"; }
public:
NS_IMETHOD HandleResult(mozIStorageResultSet*)
@@ -407,18 +406,19 @@ public:
}
NS_IMETHOD HandleCompletion(PRUint16 aReason)
{
return NS_OK;
}
};
/******************************************************************************
- * UpdateCookieDBListener impl:
- * mozIStorageStatementCallback used to track asynchronous update operations.
+ * UpdateCookieDBListener imp:
+ * Static mozIStorageStatementCallback used to track asynchronous update
+ * operations.
******************************************************************************/
class UpdateCookieDBListener : public DBListenerErrorHandler
{
protected:
virtual const char *GetOpType() { return "UPDATE"; }
public:
NS_IMETHOD HandleResult(mozIStorageResultSet*)
@@ -428,18 +428,19 @@ public:
}
NS_IMETHOD HandleCompletion(PRUint16 aReason)
{
return NS_OK;
}
};
/******************************************************************************
- * RemoveCookieDBListener impl:
- * mozIStorageStatementCallback used to track asynchronous removal operations.
+ * RemoveCookieDBListener imp:
+ * Static mozIStorageStatementCallback used to track asynchronous removal
+ * operations.
******************************************************************************/
class RemoveCookieDBListener : public DBListenerErrorHandler
{
protected:
virtual const char *GetOpType() { return "REMOVE"; }
public:
NS_IMETHOD HandleResult(mozIStorageResultSet*)
@@ -449,88 +450,16 @@ public:
}
NS_IMETHOD HandleCompletion(PRUint16 aReason)
{
return NS_OK;
}
};
/******************************************************************************
- * ReadCookieDBListener impl:
- * mozIStorageStatementCallback used to track asynchronous removal operations.
- ******************************************************************************/
-class ReadCookieDBListener : public DBListenerErrorHandler
-{
-protected:
- virtual const char *GetOpType() { return "READ"; }
- bool mCanceled;
-
-public:
- ReadCookieDBListener() : mCanceled(false) { }
-
- void Cancel() { mCanceled = true; }
-
- NS_IMETHOD HandleResult(mozIStorageResultSet *aResult)
- {
- nsresult rv;
- nsCOMPtr<mozIStorageRow> row;
- nsTArray<CookieDomainTuple> &cookieArray =
- gCookieService->mDefaultDBState.hostArray;
-
- while (1) {
- rv = aResult->GetNextRow(getter_AddRefs(row));
- NS_ASSERT_SUCCESS(rv);
-
- if (!row)
- break;
-
- CookieDomainTuple *tuple = cookieArray.AppendElement();
- row->GetUTF8String(9, tuple->baseDomain);
- tuple->cookie = gCookieService->GetCookieFromRow(row);
- }
-
- return NS_OK;
- }
- NS_IMETHOD HandleCompletion(PRUint16 aReason)
- {
- // Process the completion of the read operation. If we have been canceled,
- // we cannot assume that the cookieservice still has an open connection
- // or that it even refers to the same database, so we must return early.
- // Conversely, the cookieservice guarantees that if we have not been
- // canceled, the database connection is still alive and we can safely
- // operate on it.
-
- if (mCanceled) {
- // We may receive a REASON_FINISHED after being canceled;
- // tweak the reason accordingly.
- aReason = mozIStorageStatementCallback::REASON_CANCELED;
- }
-
- switch (aReason) {
- case mozIStorageStatementCallback::REASON_FINISHED:
- gCookieService->AsyncReadComplete();
- break;
- case mozIStorageStatementCallback::REASON_CANCELED:
- // Nothing more to do here. The partially read data has already been
- // thrown away.
- COOKIE_LOGSTRING(PR_LOG_DEBUG, ("Read canceled"));
- break;
- case mozIStorageStatementCallback::REASON_ERROR:
- // Nothing more to do here. DBListenerErrorHandler::HandleError()
- // can take handle it.
- COOKIE_LOGSTRING(PR_LOG_DEBUG, ("Read error"));
- break;
- default:
- NS_NOTREACHED("invalid reason");
- }
- return NS_OK;
- }
-};
-
-/******************************************************************************
* CloseCookieDBListener imp:
* Static mozIStorageCompletionCallback used to notify when the database is
* successfully closed.
******************************************************************************/
class CloseCookieDBListener : public mozIStorageCompletionCallback
{
public:
NS_DECL_ISUPPORTS
@@ -544,21 +473,25 @@ public:
obs->NotifyObservers(nsnull, "cookie-db-closed", nsnull);
return NS_OK;
}
};
NS_IMPL_ISUPPORTS1(CloseCookieDBListener, mozIStorageCompletionCallback)
+} // anonymous namespace
+
/******************************************************************************
* nsCookieService impl:
* singleton instance ctor/dtor methods
******************************************************************************/
+static nsCookieService *gCookieService;
+
nsICookieService*
nsCookieService::GetXPCOMSingleton()
{
#ifdef MOZ_IPC
if (IsNeckoChild())
return CookieServiceChild::GetSingleton();
#endif
@@ -638,19 +571,16 @@ nsCookieService::Init()
prefBranch->AddObserver(kPrefCookieBehavior, this, PR_TRUE);
prefBranch->AddObserver(kPrefMaxNumberOfCookies, this, PR_TRUE);
prefBranch->AddObserver(kPrefMaxCookiesPerHost, this, PR_TRUE);
prefBranch->AddObserver(kPrefCookiePurgeAge, this, PR_TRUE);
prefBranch->AddObserver(kPrefThirdPartySession, this, PR_TRUE);
PrefChanged(prefBranch);
}
- mStorageService = do_GetService("@mozilla.org/storage/service;1", &rv);
- NS_ENSURE_SUCCESS(rv, rv);
-
// failure here is non-fatal (we can run fine without
// persistent storage - e.g. if there's no profile)
rv = InitDB();
if (NS_FAILED(rv))
COOKIE_LOGSTRING(PR_LOG_WARNING, ("Init(): InitDB() gave error %x", rv));
mObserverService = mozilla::services::GetObserverService();
if (mObserverService) {
@@ -719,20 +649,23 @@ nsCookieService::TryInitDB(PRBool aDelet
cookieFile->AppendNative(NS_LITERAL_CSTRING(kCookieFileName));
// remove an existing db, if we've been told to (i.e. it's corrupt)
if (aDeleteExistingDB) {
rv = cookieFile->Remove(PR_FALSE);
NS_ENSURE_SUCCESS(rv, rv);
}
+ nsCOMPtr<mozIStorageService> storage = do_GetService("@mozilla.org/storage/service;1");
+ if (!storage)
+ return NS_ERROR_UNEXPECTED;
+
// open a connection to the cookie database, and only cache our connection
- // 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));
+ // and statements upon success.
+ rv = storage->OpenUnsharedDatabase(cookieFile, getter_AddRefs(mDBState->dbConn));
NS_ENSURE_SUCCESS(rv, rv);
PRBool tableExists = PR_FALSE;
mDBState->dbConn->TableExists(NS_LITERAL_CSTRING("moz_cookies"), &tableExists);
if (!tableExists) {
rv = CreateTable();
NS_ENSURE_SUCCESS(rv, rv);
@@ -963,23 +896,16 @@ nsCookieService::CloseDB()
NS_ASSERTION(!mPrivateDBState.dbConn, "private DB connection should always be null");
// finalize our statements and close the db connection for the default state.
// since we own these objects, nulling the pointers is sufficient here.
mDefaultDBState.stmtInsert = nsnull;
mDefaultDBState.stmtDelete = nsnull;
mDefaultDBState.stmtUpdate = nsnull;
if (mDefaultDBState.dbConn) {
- // Cancel any pending read. No further results will be received by our
- // read listener.
- if (mDefaultDBState.pendingRead) {
- CancelAsyncRead(PR_TRUE);
- mDefaultDBState.syncConn = nsnull;
- }
-
mDefaultDBState.dbConn->AsyncClose(mCloseListener);
mDefaultDBState.dbConn = nsnull;
}
}
nsCookieService::~nsCookieService()
{
CloseDB();
@@ -996,17 +922,19 @@ nsCookieService::Observe(nsISupports
if (!strcmp(aTopic, "profile-before-change")) {
// The profile is about to change,
// or is going away because the application is shutting down.
RemoveAllFromMemory();
if (mDBState->dbConn) {
if (!nsCRT::strcmp(aData, NS_LITERAL_STRING("shutdown-cleanse").get())) {
// clear the cookie file
- RemoveAll();
+ nsresult rv = mDBState->dbConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING("DELETE FROM moz_cookies"));
+ if (NS_FAILED(rv))
+ NS_WARNING("db delete failed");
}
// Close the DB connection before changing
CloseDB();
}
} else if (!strcmp(aTopic, "profile-do-change")) {
// the profile has already changed; init the db from the new location.
@@ -1249,25 +1177,26 @@ NS_IMETHODIMP
nsCookieService::RemoveAll()
{
RemoveAllFromMemory();
// clear the cookie file
if (mDBState->dbConn) {
NS_ASSERTION(mDBState == &mDefaultDBState, "not in default DB state");
- // XXX Ignore corruption for now. See bug 547031.
- nsCOMPtr<mozIStorageStatement> stmt;
- nsresult rv = mDefaultDBState.dbConn->CreateStatement(NS_LITERAL_CSTRING(
- "DELETE FROM moz_cookies"), getter_AddRefs(stmt));
- NS_ENSURE_SUCCESS(rv, rv);
-
- nsCOMPtr<mozIStoragePendingStatement> handle;
- rv = stmt->ExecuteAsync(mRemoveListener, getter_AddRefs(handle));
- NS_ASSERT_SUCCESS(rv);
+ nsresult rv = mDBState->dbConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING("DELETE FROM moz_cookies"));
+ if (NS_FAILED(rv)) {
+ // Database must be corrupted, so remove it completely.
+ nsCOMPtr<nsIFile> dbFile;
+ mDBState->dbConn->GetDatabaseFile(getter_AddRefs(dbFile));
+ CloseDB();
+ dbFile->Remove(PR_FALSE);
+
+ InitDB();
+ }
}
NotifyChanged(nsnull, NS_LITERAL_STRING("cleared").get());
return NS_OK;
}
// helper struct for passing arguments into hash enumeration callback.
struct nsGetEnumeratorData
@@ -1298,18 +1227,16 @@ COMArrayCallback(nsCookieEntry *aEntry,
}
NS_IMETHODIMP
nsCookieService::GetEnumerator(nsISimpleEnumerator **aEnumerator)
{
nsCOMArray<nsICookie> cookieList(mDBState->cookieCount);
nsGetEnumeratorData data(&cookieList, PR_Now() / PR_USEC_PER_SEC);
- EnsureReadComplete();
-
mDBState->hostTable.EnumerateEntries(COMArrayCallback, &data);
return NS_NewArrayEnumerator(aEnumerator, cookieList);
}
NS_IMETHODIMP
nsCookieService::Add(const nsACString &aHost,
const nsACString &aPath,
@@ -1397,288 +1324,95 @@ nsCookieService::Remove(const nsACString
/******************************************************************************
* nsCookieService impl:
* private file I/O functions
******************************************************************************/
nsresult
nsCookieService::Read()
{
- // Let the reading begin!
+ nsresult rv;
+
+ // delete expired cookies, before we read in the db
+ {
+ // scope the deletion, so the write lock is released when finished
+ nsCOMPtr<mozIStorageStatement> stmtDeleteExpired;
+ rv = mDBState->dbConn->CreateStatement(NS_LITERAL_CSTRING(
+ "DELETE FROM moz_cookies WHERE expiry <= ?1"),
+ getter_AddRefs(stmtDeleteExpired));
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ rv = stmtDeleteExpired->BindInt64ByIndex(0, PR_Now() / PR_USEC_PER_SEC);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ PRBool hasResult;
+ rv = stmtDeleteExpired->ExecuteStep(&hasResult);
+ NS_ENSURE_SUCCESS(rv, rv);
+ }
+
+ // let the reading begin!
nsCOMPtr<mozIStorageStatement> stmt;
- nsresult rv = mDefaultDBState.dbConn->CreateStatement(NS_LITERAL_CSTRING(
+ rv = mDBState->dbConn->CreateStatement(NS_LITERAL_CSTRING(
"SELECT "
"id, "
"name, "
"value, "
"host, "
"path, "
"expiry, "
"lastAccessed, "
"isSecure, "
"isHttpOnly, "
"baseDomain "
"FROM moz_cookies"), getter_AddRefs(stmt));
NS_ENSURE_SUCCESS(rv, rv);
- nsRefPtr<ReadCookieDBListener> readListener = new ReadCookieDBListener;
- rv = stmt->ExecuteAsync(readListener,
- getter_AddRefs(mDefaultDBState.pendingRead));
- NS_ASSERT_SUCCESS(rv);
-
- mDefaultDBState.readListener = readListener;
- if (!mDefaultDBState.readSet.IsInitialized())
- mDefaultDBState.readSet.Init();
-
- return NS_OK;
-}
-
-// Extract data from a single result row and create an nsCookie.
-// This is templated since 'T' is different for sync vs async results.
-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(1, name);
- NS_ASSERT_SUCCESS(rv);
- rv = aRow->GetUTF8String(2, value);
- NS_ASSERT_SUCCESS(rv);
- rv = aRow->GetUTF8String(3, host);
- NS_ASSERT_SUCCESS(rv);
- rv = aRow->GetUTF8String(4, path);
- NS_ASSERT_SUCCESS(rv);
-
- 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.
- return nsCookie::Create(name, value, host, path,
- expiry,
- lastAccessed,
- creationID,
- PR_FALSE,
- isSecure,
- isHttpOnly);
-}
-
-void
-nsCookieService::AsyncReadComplete()
-{
- 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
- // have occurred on the main thread since, making the background data stale.
- for (PRUint32 i = 0; i < mDefaultDBState.hostArray.Length(); ++i) {
- const CookieDomainTuple &tuple = mDefaultDBState.hostArray[i];
-
- // Tiebreak: if the given base domain has already been read in, ignore
- // the background data. Note that readSet may contain domains that were
- // queried but found not to be in the db -- that's harmless.
- if (mDefaultDBState.readSet.GetEntry(tuple.baseDomain))
- continue;
-
- AddCookieToList(tuple.baseDomain, tuple.cookie, NULL, PR_FALSE);
+ nsCAutoString baseDomain, name, value, host, path;
+ PRBool hasResult;
+ while (NS_SUCCEEDED(rv = stmt->ExecuteStep(&hasResult)) && hasResult) {
+ PRInt64 creationID = stmt->AsInt64(0);
+
+ stmt->GetUTF8String(1, name);
+ stmt->GetUTF8String(2, value);
+ stmt->GetUTF8String(3, host);
+ stmt->GetUTF8String(4, path);
+
+ PRInt64 expiry = stmt->AsInt64(5);
+ PRInt64 lastAccessed = stmt->AsInt64(6);
+ PRBool isSecure = 0 != stmt->AsInt32(7);
+ PRBool isHttpOnly = 0 != stmt->AsInt32(8);
+
+ stmt->GetUTF8String(9, baseDomain);
+
+ // create a new nsCookie and assign the data.
+ nsCookie* newCookie =
+ nsCookie::Create(name, value, host, path,
+ expiry,
+ lastAccessed,
+ creationID,
+ PR_FALSE,
+ isSecure,
+ isHttpOnly);
+ if (!newCookie)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ if (!AddCookieToList(baseDomain, newCookie, NULL, PR_FALSE))
+ // It is purpose that created us; purpose that connects us;
+ // purpose that pulls us; that guides us; that drives us.
+ // It is purpose that defines us; purpose that binds us.
+ // When a cookie no longer has purpose, it has a choice:
+ // it can return to the source to be deleted, or it can go
+ // into exile, and stay hidden inside the Matrix.
+ // Let's choose deletion.
+ delete newCookie;
}
- mDefaultDBState.stmtReadDomain = nsnull;
- mDefaultDBState.pendingRead = nsnull;
- mDefaultDBState.readListener = nsnull;
- mDefaultDBState.syncConn = nsnull;
- mDefaultDBState.hostArray.Clear();
- mDefaultDBState.readSet.Clear();
-
- mObserverService->NotifyObservers(nsnull, "cookie-db-read", nsnull);
-
- COOKIE_LOGSTRING(PR_LOG_DEBUG, ("Read(): %ld cookies read",
- mDefaultDBState.cookieCount));
-}
-
-void
-nsCookieService::CancelAsyncRead(PRBool aPurgeReadSet)
-{
- 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.
- mDefaultDBState.readListener->Cancel();
- nsresult rv = mDefaultDBState.pendingRead->Cancel();
- NS_ASSERT_SUCCESS(rv);
-
- mDefaultDBState.stmtReadDomain = nsnull;
- mDefaultDBState.pendingRead = nsnull;
- mDefaultDBState.readListener = nsnull;
- mDefaultDBState.hostArray.Clear();
-
- // Only clear the 'readSet' table if we no longer need to know what set of
- // data is already accounted for.
- if (aPurgeReadSet)
- mDefaultDBState.readSet.Clear();
-}
-
-mozIStorageConnection*
-nsCookieService::GetSyncDBConn()
-{
- NS_ASSERTION(!mDefaultDBState.syncConn, "already have sync db connection");
-
- // Start a new connection for sync reads to reduce contention with the
- // background thread.
- nsCOMPtr<nsIFile> cookieFile;
- mDefaultDBState.dbConn->GetDatabaseFile(getter_AddRefs(cookieFile));
- NS_ASSERTION(cookieFile, "no cookie file on connection");
-
- mStorageService->OpenDatabase(cookieFile,
- getter_AddRefs(mDefaultDBState.syncConn));
- NS_ASSERTION(mDefaultDBState.syncConn, "can't open sync db connection");
- return mDefaultDBState.syncConn;
-}
-
-void
-nsCookieService::EnsureReadDomain(const nsCString &aBaseDomain)
-{
- NS_ASSERTION(!mDBState->dbConn || mDBState == &mDefaultDBState,
- "not in default db state");
-
- // Fast path 1: nothing to read, or we've already finished reading.
- if (NS_LIKELY(!mDBState->dbConn || !mDefaultDBState.pendingRead))
- return;
-
- // Fast path 2: already read in this particular domain.
- if (NS_LIKELY(mDefaultDBState.readSet.GetEntry(aBaseDomain)))
- return;
-
- // Read in the data synchronously.
- nsresult rv;
- if (!mDefaultDBState.stmtReadDomain) {
- if (!GetSyncDBConn())
- return;
-
- // 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, "
- "isSecure, "
- "isHttpOnly "
- "FROM moz_cookies "
- "WHERE baseDomain = ?1"),
- getter_AddRefs(mDefaultDBState.stmtReadDomain));
-
- // XXX Ignore corruption for now. See bug 547031.
- if (NS_FAILED(rv)) return;
- }
-
- NS_ASSERTION(mDefaultDBState.syncConn, "should have a sync db connection");
-
- mozStorageStatementScoper scoper(mDefaultDBState.stmtReadDomain);
-
- rv = mDefaultDBState.stmtReadDomain->BindUTF8StringByIndex(0, aBaseDomain);
- NS_ASSERT_SUCCESS(rv);
-
- PRBool hasResult;
- PRUint32 readCount = 0;
- nsCString name, value, host, path;
- while (1) {
- rv = mDefaultDBState.stmtReadDomain->ExecuteStep(&hasResult);
- // XXX Ignore corruption for now. See bug 547031.
- if (NS_FAILED(rv)) return;
-
- if (!hasResult)
- break;
-
- nsCookie* newCookie = GetCookieFromRow(mDefaultDBState.stmtReadDomain);
- AddCookieToList(aBaseDomain, newCookie, NULL, PR_FALSE);
- ++readCount;
- }
-
- // Add it to the hashset of read entries, so we don't read it again.
- mDefaultDBState.readSet.PutEntry(aBaseDomain);
-
- COOKIE_LOGSTRING(PR_LOG_DEBUG,
- ("EnsureReadDomain(): %ld cookies read for base domain %s",
- readCount, aBaseDomain.get()));
-}
-
-void
-nsCookieService::EnsureReadComplete()
-{
- NS_ASSERTION(!mDBState->dbConn || mDBState == &mDefaultDBState,
- "not in default db state");
-
- // Fast path 1: nothing to read, or we've already finished reading.
- if (NS_LIKELY(!mDBState->dbConn || !mDefaultDBState.pendingRead))
- return;
-
- // Cancel the pending read, so we don't get any more results.
- CancelAsyncRead(PR_FALSE);
-
- if (!mDefaultDBState.syncConn && !GetSyncDBConn())
- return;
-
- // Read in the data synchronously.
- nsCOMPtr<mozIStorageStatement> stmt;
- nsresult rv = mDefaultDBState.syncConn->CreateStatement(NS_LITERAL_CSTRING(
- "SELECT "
- "id, "
- "name, "
- "value, "
- "host, "
- "path, "
- "expiry, "
- "lastAccessed, "
- "isSecure, "
- "isHttpOnly, "
- "baseDomain "
- "FROM moz_cookies"), getter_AddRefs(stmt));
-
- // XXX Ignore corruption for now. See bug 547031.
- if (NS_FAILED(rv)) return;
-
- nsCString baseDomain, name, value, host, path;
- PRBool hasResult;
- PRUint32 readCount = 0;
- while (1) {
- rv = stmt->ExecuteStep(&hasResult);
- // XXX Ignore corruption for now. See bug 547031.
- if (NS_FAILED(rv)) return;
-
- if (!hasResult)
- break;
-
- // Make sure we haven't already read the data.
- stmt->GetUTF8String(9, baseDomain);
- if (mDefaultDBState.readSet.GetEntry(baseDomain))
- continue;
-
- nsCookie* newCookie = GetCookieFromRow(stmt);
- AddCookieToList(baseDomain, newCookie, NULL, PR_FALSE);
- ++readCount;
- }
-
- mDefaultDBState.syncConn = nsnull;
- mDefaultDBState.readSet.Clear();
-
- mObserverService->NotifyObservers(nsnull, "cookie-db-read", nsnull);
-
- COOKIE_LOGSTRING(PR_LOG_DEBUG,
- ("EnsureReadComplete(): %ld cookies read", readCount));
+ COOKIE_LOGSTRING(PR_LOG_DEBUG, ("Read(): %ld cookies read", mDBState->cookieCount));
+
+ return rv;
}
NS_IMETHODIMP
nsCookieService::ImportCookies(nsIFile *aCookieFile)
{
nsresult rv;
nsCOMPtr<nsIInputStream> fileInputStream;
rv = NS_NewLocalFileInputStream(getter_AddRefs(fileInputStream), aCookieFile);
@@ -1722,19 +1456,16 @@ nsCookieService::ImportCookies(nsIFile *
* in a comment, so they don't expose HttpOnly cookies to JS.
*
* The format for HttpOnly cookies is
*
* #HttpOnly_host \t isDomain \t path \t secure \t expires \t name \t cookie
*
*/
- // First, ensure we've read in everything from the database, if we have one.
- EnsureReadComplete();
-
// 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 && mDBState->dbConn) {
mDBState->stmtInsert->NewBindingParamsArray(getter_AddRefs(paramsArray));
}
while (isMore && NS_SUCCEEDED(lineInputStream->ReadLine(buffer, &isMore))) {
@@ -1921,18 +1652,16 @@ nsCookieService::GetCookieInternal(nsIUR
}
nsCookie *cookie;
nsAutoTArray<nsCookie*, 8> foundCookieList;
PRInt64 currentTimeInUsec = PR_Now();
PRInt64 currentTime = currentTimeInUsec / PR_USEC_PER_SEC;
PRBool stale = PR_FALSE;
- EnsureReadDomain(baseDomain);
-
// perform the hash lookup
nsCookieEntry *entry = mDBState->hostTable.GetEntry(baseDomain);
if (!entry)
return;
// iterate the cookies!
const nsCookieEntry::ArrayType &cookies = entry->GetCookies();
for (nsCookieEntry::IndexType i = 0; i < cookies.Length(); ++i) {
@@ -2982,18 +2711,16 @@ nsCookieService::PurgeCookies(PRInt64 aC
// Create a params array to batch the removals. This is OK here because
// all the removals are in order, and there are no interleaved additions.
mozIStorageStatement *stmt = mDBState->stmtDelete;
nsCOMPtr<mozIStorageBindingParamsArray> paramsArray;
if (mDBState->dbConn) {
stmt->NewBindingParamsArray(getter_AddRefs(paramsArray));
}
- EnsureReadComplete();
-
nsPurgeData data(aCurrentTimeInUsec / PR_USEC_PER_SEC,
aCurrentTimeInUsec - mCookiePurgeAge, purgeList, removedList, paramsArray);
mDBState->hostTable.EnumerateEntries(purgeCookiesCallback, &data);
#ifdef PR_LOGGING
PRUint32 postExpiryCookieCount = mDBState->cookieCount;
#endif
@@ -3076,18 +2803,16 @@ nsCookieService::CookieExists(nsICookie2
}
// count the number of cookies in a base domain, and simultaneously find the
// oldest cookie in that domain.
PRUint32
nsCookieService::CountCookiesFromHostInternal(const nsCString &aBaseDomain,
nsEnumerationData &aData)
{
- EnsureReadDomain(aBaseDomain);
-
nsCookieEntry *entry = mDBState->hostTable.GetEntry(aBaseDomain);
if (!entry)
return 0;
PRUint32 countFromHost = 0;
const nsCookieEntry::ArrayType &cookies = entry->GetCookies();
for (nsCookieEntry::IndexType i = 0; i < cookies.Length(); ++i) {
nsCookie *cookie = cookies[i];
@@ -3141,18 +2866,16 @@ nsCookieService::GetCookiesFromHost(cons
nsCAutoString baseDomain;
rv = GetBaseDomainFromHost(host, baseDomain);
NS_ENSURE_SUCCESS(rv, rv);
nsCOMArray<nsICookie> cookieList(mMaxCookiesPerHost);
PRInt64 currentTime = PR_Now() / PR_USEC_PER_SEC;
- EnsureReadDomain(baseDomain);
-
nsCookieEntry *entry = mDBState->hostTable.GetEntry(baseDomain);
if (!entry)
return NS_NewEmptyEnumerator(aEnumerator);
const nsCookieEntry::ArrayType &cookies = entry->GetCookies();
for (nsCookieEntry::IndexType i = 0; i < cookies.Length(); ++i) {
nsCookie *cookie = cookies[i];
@@ -3168,18 +2891,16 @@ nsCookieService::GetCookiesFromHost(cons
PRBool
nsCookieService::FindCookie(const nsCString &aBaseDomain,
const nsAFlatCString &aHost,
const nsAFlatCString &aName,
const nsAFlatCString &aPath,
nsListIter &aIter,
PRInt64 aCurrentTime)
{
- EnsureReadDomain(aBaseDomain);
-
nsCookieEntry *entry = mDBState->hostTable.GetEntry(aBaseDomain);
if (!entry)
return PR_FALSE;
const nsCookieEntry::ArrayType &cookies = entry->GetCookies();
for (nsCookieEntry::IndexType i = 0; i < cookies.Length(); ++i) {
nsCookie *cookie = cookies[i];
@@ -3289,29 +3010,32 @@ bindCookieParameters(mozIStorageBindingP
rv = params->BindInt32ByIndex(9, aCookie->IsHttpOnly());
NS_ASSERT_SUCCESS(rv);
// Bind the params to the array.
rv = aParamsArray->AddParams(params);
NS_ASSERT_SUCCESS(rv);
}
-void
+PRBool
nsCookieService::AddCookieToList(const nsCString &aBaseDomain,
nsCookie *aCookie,
mozIStorageBindingParamsArray *aParamsArray,
PRBool aWriteToDB)
{
NS_ASSERTION(!(mDBState->dbConn && !aWriteToDB && aParamsArray),
"Not writing to the DB but have a params array?");
NS_ASSERTION(!(!mDBState->dbConn && aParamsArray),
"Do not have a DB connection but have a params array?");
nsCookieEntry *entry = mDBState->hostTable.PutEntry(aBaseDomain);
- NS_ASSERTION(entry, "can't insert element into a null entry!");
+ if (!entry) {
+ NS_ERROR("can't insert element into a null entry!");
+ return PR_FALSE;
+ }
entry->GetCookies().AppendElement(aCookie);
++mDBState->cookieCount;
// keep track of the oldest cookie, for when it comes time to purge
if (aCookie->LastAccessed() < mDBState->cookieOldestTime)
mDBState->cookieOldestTime = aCookie->LastAccessed();
@@ -3329,16 +3053,18 @@ nsCookieService::AddCookieToList(const n
if (!aParamsArray) {
nsresult rv = stmt->BindParameters(paramsArray);
NS_ASSERT_SUCCESS(rv);
nsCOMPtr<mozIStoragePendingStatement> handle;
rv = stmt->ExecuteAsync(mInsertListener, getter_AddRefs(handle));
NS_ASSERT_SUCCESS(rv);
}
}
+
+ return PR_TRUE;
}
void
nsCookieService::UpdateCookieInList(nsCookie *aCookie,
PRInt64 aLastAccessed,
mozIStorageBindingParamsArray *aParamsArray)
{
NS_ASSERTION(aCookie, "Passing a null cookie to UpdateCookieInList!");
--- a/netwerk/cookie/nsCookieService.h
+++ b/netwerk/cookie/nsCookieService.h
@@ -49,31 +49,28 @@
#include "nsWeakReference.h"
#include "nsCookie.h"
#include "nsString.h"
#include "nsAutoPtr.h"
#include "nsHashKeys.h"
#include "nsTHashtable.h"
#include "mozIStorageStatement.h"
-#include "mozIStoragePendingStatement.h"
#include "mozIStorageConnection.h"
-#include "mozIStorageRow.h"
class nsICookiePermission;
class nsIEffectiveTLDService;
class nsIIDNService;
class nsIPrefBranch;
class nsIObserverService;
class nsIURI;
class nsIChannel;
-class mozIStorageService;
+class DBListenerErrorHandler;
class mozIStorageStatementCallback;
class mozIStorageCompletionCallback;
-class ReadCookieDBListener;
struct nsCookieAttributes;
struct nsListIter;
struct nsEnumerationData;
namespace mozilla {
namespace net {
#ifdef MOZ_IPC
@@ -133,52 +130,29 @@ class nsCookieEntry : public PLDHashEntr
inline ArrayType& GetCookies() { return mCookies; }
private:
nsCString mBaseDomain;
ArrayType mCookies;
};
-// encapsulates a (baseDomain, nsCookie) tuple for temporary storage purposes.
-struct CookieDomainTuple
-{
- nsCString baseDomain;
- nsRefPtr<nsCookie> cookie;
-};
-
// encapsulates in-memory and on-disk DB states, so we can
// conveniently switch state when entering or exiting private browsing.
struct DBState
{
DBState() : cookieCount(0), cookieOldestTime(LL_MAXINT) { }
nsTHashtable<nsCookieEntry> hostTable;
PRUint32 cookieCount;
PRInt64 cookieOldestTime;
nsCOMPtr<mozIStorageConnection> dbConn;
nsCOMPtr<mozIStorageStatement> stmtInsert;
nsCOMPtr<mozIStorageStatement> stmtDelete;
nsCOMPtr<mozIStorageStatement> stmtUpdate;
-
- // Various parts representing asynchronous read state. These are useful
- // while the background read is taking place.
- nsCOMPtr<mozIStorageConnection> syncConn;
- nsCOMPtr<mozIStorageStatement> stmtReadDomain;
- nsCOMPtr<mozIStoragePendingStatement> pendingRead;
- // The asynchronous read listener. This is a weak ref (storage has ownership)
- // since it may need to outlive the DBState's database connection.
- ReadCookieDBListener* readListener;
- // An array of (baseDomain, cookie) tuples representing data read in
- // asynchronously. This is merged into hostTable once read is complete.
- nsTArray<CookieDomainTuple> hostArray;
- // A hashset of baseDomains read in synchronously, while the async read is
- // in flight. This is used to keep track of which data in hostArray is stale
- // when the time comes to merge.
- nsTHashtable<nsCStringHashKey> readSet;
};
// these constants represent a decision about a cookie based on user prefs.
enum CookieStatus
{
STATUS_ACCEPTED,
STATUS_ACCEPT_SESSION,
STATUS_REJECTED,
@@ -214,31 +188,25 @@ class nsCookieService : public nsICookie
protected:
void PrefChanged(nsIPrefBranch *aPrefBranch);
nsresult InitDB();
nsresult TryInitDB(PRBool aDeleteExistingDB);
nsresult CreateTable();
void CloseDB();
nsresult Read();
- template<class T> nsCookie* GetCookieFromRow(T &aRow);
- void AsyncReadComplete();
- void CancelAsyncRead(PRBool aPurgeReadSet);
- mozIStorageConnection* GetSyncDBConn();
- void EnsureReadDomain(const nsCString &aBaseDomain);
- void EnsureReadComplete();
nsresult NormalizeHost(nsCString &aHost);
nsresult GetBaseDomain(nsIURI *aHostURI, nsCString &aBaseDomain, PRBool &aRequireHostMatch);
nsresult GetBaseDomainFromHost(const nsACString &aHost, nsCString &aBaseDomain);
void GetCookieInternal(nsIURI *aHostURI, nsIURI *aOriginatingURI, PRBool aHttpBound, nsCString &aCookie);
void SetCookieStringInternal(nsIURI *aHostURI, nsIURI *aOriginatingURI, const nsCString &aCookieHeader, const nsCString &aServerTime, PRBool aFromHttp);
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, mozIStorageBindingParamsArray *aParamsArray, PRBool aWriteToDB = PR_TRUE);
+ PRBool 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);
PRBool IsForeign(const nsCString &aBaseDomain, PRBool aRequireHostMatch, nsIURI *aFirstURI);
void GetOriginatingURI(nsIChannel *aChannel, nsIURI **aURI);
CookieStatus CheckPrefs(nsIURI *aHostURI, nsIURI *aOriginatingURI, const nsCString &aBaseDomain, PRBool aRequireHostMatch, const char *aCookieHeader);
PRBool CheckDomain(nsCookieAttributes &aCookie, nsIURI *aHostURI, const nsCString &aBaseDomain, PRBool aRequireHostMatch);
static PRBool CheckPath(nsCookieAttributes &aCookie, nsIURI *aHostURI);
@@ -251,17 +219,16 @@ class nsCookieService : public nsICookie
void NotifyChanged(nsISupports *aSubject, const PRUnichar *aData);
protected:
// cached members.
nsCOMPtr<nsIObserverService> mObserverService;
nsCOMPtr<nsICookiePermission> mPermissionService;
nsCOMPtr<nsIEffectiveTLDService> mTLDService;
nsCOMPtr<nsIIDNService> mIDNService;
- nsCOMPtr<mozIStorageService> mStorageService;
// we have two separate DB states: one for normal browsing and one for
// private browsing, switching between them as appropriate. this state
// encapsulates both the in-memory table and the on-disk DB.
// note that the private states' dbConn should always be null - we never
// want to be dealing with the on-disk DB when in private browsing.
DBState *mDBState;
DBState mDefaultDBState;
@@ -275,19 +242,18 @@ class nsCookieService : public nsICookie
// cached prefs
PRUint8 mCookieBehavior; // BEHAVIOR_{ACCEPT, REJECTFOREIGN, REJECT}
PRBool mThirdPartySession;
PRUint16 mMaxNumberOfCookies;
PRUint16 mMaxCookiesPerHost;
PRInt64 mCookiePurgeAge;
- // friends!
+ // this callback needs access to member functions
friend PLDHashOperator purgeCookiesCallback(nsCookieEntry *aEntry, void *aArg);
- friend class ReadCookieDBListener;
static nsCookieService* GetSingleton();
#ifdef MOZ_IPC
friend class mozilla::net::CookieServiceParent;
#endif
};
#endif // nsCookieService_h__
--- a/storage/src/mozStorageStatement.cpp
+++ b/storage/src/mozStorageStatement.cpp
@@ -778,17 +778,17 @@ NS_IMETHODIMP
Statement::GetUTF8String(PRUint32 aIndex,
nsACString &_value)
{
// Get type of Index will check aIndex for us, so we don't have to.
PRInt32 type;
nsresult rv = GetTypeOfIndex(aIndex, &type);
NS_ENSURE_SUCCESS(rv, rv);
if (type == mozIStorageStatement::VALUE_TYPE_NULL) {
- // NULL columns should have IsVoid set to distinguish them from the empty
+ // NULL columns should have IsVod set to distinguis them from an empty
// string.
_value.Truncate(0);
_value.SetIsVoid(PR_TRUE);
}
else {
const char *value =
reinterpret_cast<const char *>(::sqlite3_column_text(mDBStatement,
aIndex));
@@ -801,17 +801,17 @@ NS_IMETHODIMP
Statement::GetString(PRUint32 aIndex,
nsAString &_value)
{
// Get type of Index will check aIndex for us, so we don't have to.
PRInt32 type;
nsresult rv = GetTypeOfIndex(aIndex, &type);
NS_ENSURE_SUCCESS(rv, rv);
if (type == mozIStorageStatement::VALUE_TYPE_NULL) {
- // NULL columns should have IsVoid set to distinguish them from the empty
+ // NULL columns should have IsVod set to distinguis them from an empty
// string.
_value.Truncate(0);
_value.SetIsVoid(PR_TRUE);
} else {
const PRUnichar *value =
static_cast<const PRUnichar *>(::sqlite3_column_text16(mDBStatement,
aIndex));
_value.Assign(value, ::sqlite3_column_bytes16(mDBStatement, aIndex) / 2);