Bug 756648 - Implement "cookie jars" for apps. r=biesi,smaug
This commit is contained in:
@@ -18,6 +18,11 @@ SerializedLoadContext::SerializedLoadContext(nsILoadContext* aLoadContext)
|
|||||||
|
|
||||||
SerializedLoadContext::SerializedLoadContext(nsIChannel* aChannel)
|
SerializedLoadContext::SerializedLoadContext(nsIChannel* aChannel)
|
||||||
{
|
{
|
||||||
|
if (!aChannel) {
|
||||||
|
Init(nullptr);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
nsCOMPtr<nsILoadContext> loadContext;
|
nsCOMPtr<nsILoadContext> loadContext;
|
||||||
NS_QueryNotificationCallbacks(aChannel, loadContext);
|
NS_QueryNotificationCallbacks(aChannel, loadContext);
|
||||||
Init(loadContext);
|
Init(loadContext);
|
||||||
@@ -40,7 +45,9 @@ SerializedLoadContext::SerializedLoadContext(nsIChannel* aChannel)
|
|||||||
SerializedLoadContext::SerializedLoadContext(nsIWebSocketChannel* aChannel)
|
SerializedLoadContext::SerializedLoadContext(nsIWebSocketChannel* aChannel)
|
||||||
{
|
{
|
||||||
nsCOMPtr<nsILoadContext> loadContext;
|
nsCOMPtr<nsILoadContext> loadContext;
|
||||||
|
if (aChannel) {
|
||||||
NS_QueryNotificationCallbacks(aChannel, loadContext);
|
NS_QueryNotificationCallbacks(aChannel, loadContext);
|
||||||
|
}
|
||||||
Init(loadContext);
|
Init(loadContext);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -18,6 +18,8 @@
|
|||||||
// c) Schema 3: the 'creationTime' column already exists; or the
|
// c) Schema 3: the 'creationTime' column already exists; or the
|
||||||
// 'moz_uniqueid' index already exists.
|
// 'moz_uniqueid' index already exists.
|
||||||
|
|
||||||
|
let COOKIE_DATABASE_SCHEMA_CURRENT = 5;
|
||||||
|
|
||||||
let test_generator = do_run_test();
|
let test_generator = do_run_test();
|
||||||
|
|
||||||
function run_test() {
|
function run_test() {
|
||||||
@@ -62,6 +64,10 @@ function do_run_test() {
|
|||||||
sub_generator.next();
|
sub_generator.next();
|
||||||
yield;
|
yield;
|
||||||
|
|
||||||
|
this.sub_generator = run_test_3(test_generator, COOKIE_DATABASE_SCHEMA_CURRENT);
|
||||||
|
sub_generator.next();
|
||||||
|
yield;
|
||||||
|
|
||||||
this.sub_generator = run_test_3(test_generator, 4);
|
this.sub_generator = run_test_3(test_generator, 4);
|
||||||
sub_generator.next();
|
sub_generator.next();
|
||||||
yield;
|
yield;
|
||||||
@@ -206,7 +212,7 @@ function run_test_3(generator, schema)
|
|||||||
|
|
||||||
// Check that the schema version has been reset.
|
// Check that the schema version has been reset.
|
||||||
let db = Services.storage.openDatabase(cookieFile);
|
let db = Services.storage.openDatabase(cookieFile);
|
||||||
do_check_eq(db.schemaVersion, 4);
|
do_check_eq(db.schemaVersion, COOKIE_DATABASE_SCHEMA_CURRENT);
|
||||||
db.close();
|
db.close();
|
||||||
|
|
||||||
// Clean up.
|
// Clean up.
|
||||||
@@ -233,7 +239,7 @@ function run_test_4_exists(generator, schema, stmt)
|
|||||||
|
|
||||||
// Check that the schema version has been reset and the backup file exists.
|
// Check that the schema version has been reset and the backup file exists.
|
||||||
db = Services.storage.openDatabase(cookieFile);
|
db = Services.storage.openDatabase(cookieFile);
|
||||||
do_check_eq(db.schemaVersion, 4);
|
do_check_eq(db.schemaVersion, COOKIE_DATABASE_SCHEMA_CURRENT);
|
||||||
db.close();
|
db.close();
|
||||||
do_check_true(backupFile.exists());
|
do_check_true(backupFile.exists());
|
||||||
|
|
||||||
@@ -264,7 +270,7 @@ function run_test_4_baseDomain(generator)
|
|||||||
|
|
||||||
// Check that the schema version has been reset and the backup file exists.
|
// Check that the schema version has been reset and the backup file exists.
|
||||||
db = Services.storage.openDatabase(cookieFile);
|
db = Services.storage.openDatabase(cookieFile);
|
||||||
do_check_eq(db.schemaVersion, 4);
|
do_check_eq(db.schemaVersion, COOKIE_DATABASE_SCHEMA_CURRENT);
|
||||||
db.close();
|
db.close();
|
||||||
do_check_true(backupFile.exists());
|
do_check_true(backupFile.exists());
|
||||||
|
|
||||||
|
|||||||
@@ -1339,6 +1339,12 @@ NS_UsePrivateBrowsing(nsIChannel *channel)
|
|||||||
return loadContext && loadContext->UsePrivateBrowsing();
|
return loadContext && loadContext->UsePrivateBrowsing();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Constants duplicated from nsIScriptSecurityManager so we avoid having necko
|
||||||
|
// know about script security manager.
|
||||||
|
#define NECKO_NO_APP_ID 0
|
||||||
|
// Note: UNKNOWN also equals PR_UINT32_MAX
|
||||||
|
#define NECKO_UNKNOWN_APP_ID 4294967295
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets AppId and isInBrowserElement from channel's nsILoadContext.
|
* Gets AppId and isInBrowserElement from channel's nsILoadContext.
|
||||||
* Returns false if error or channel's callbacks don't implement nsILoadContext.
|
* Returns false if error or channel's callbacks don't implement nsILoadContext.
|
||||||
|
|||||||
@@ -117,7 +117,8 @@ CookieServiceChild::GetCookieStringInternal(nsIURI *aHostURI,
|
|||||||
|
|
||||||
// Synchronously call the parent.
|
// Synchronously call the parent.
|
||||||
nsAutoCString result;
|
nsAutoCString result;
|
||||||
SendGetCookieString(uriParams, !!isForeign, aFromHttp, &result);
|
SendGetCookieString(uriParams, !!isForeign, aFromHttp,
|
||||||
|
IPC::SerializedLoadContext(aChannel), &result);
|
||||||
if (!result.IsEmpty())
|
if (!result.IsEmpty())
|
||||||
*aCookieString = ToNewCString(result);
|
*aCookieString = ToNewCString(result);
|
||||||
|
|
||||||
@@ -149,7 +150,7 @@ CookieServiceChild::SetCookieStringInternal(nsIURI *aHostURI,
|
|||||||
|
|
||||||
// Synchronously call the parent.
|
// Synchronously call the parent.
|
||||||
SendSetCookieString(uriParams, !!isForeign, cookieString, serverTime,
|
SendSetCookieString(uriParams, !!isForeign, cookieString, serverTime,
|
||||||
aFromHttp);
|
aFromHttp, IPC::SerializedLoadContext(aChannel));
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -34,6 +34,8 @@ bool
|
|||||||
CookieServiceParent::RecvGetCookieString(const URIParams& aHost,
|
CookieServiceParent::RecvGetCookieString(const URIParams& aHost,
|
||||||
const bool& aIsForeign,
|
const bool& aIsForeign,
|
||||||
const bool& aFromHttp,
|
const bool& aFromHttp,
|
||||||
|
const IPC::SerializedLoadContext&
|
||||||
|
aLoadContext,
|
||||||
nsCString* aResult)
|
nsCString* aResult)
|
||||||
{
|
{
|
||||||
if (!mCookieService)
|
if (!mCookieService)
|
||||||
@@ -45,8 +47,12 @@ CookieServiceParent::RecvGetCookieString(const URIParams& aHost,
|
|||||||
if (!hostURI)
|
if (!hostURI)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
mCookieService->GetCookieStringInternal(hostURI, aIsForeign,
|
uint32_t appId;
|
||||||
aFromHttp, *aResult);
|
bool isInBrowserElement;
|
||||||
|
GetAppInfoFromLoadContext(aLoadContext, appId, isInBrowserElement);
|
||||||
|
|
||||||
|
mCookieService->GetCookieStringInternal(hostURI, aIsForeign, aFromHttp, appId,
|
||||||
|
isInBrowserElement, *aResult);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -55,7 +61,9 @@ CookieServiceParent::RecvSetCookieString(const URIParams& aHost,
|
|||||||
const bool& aIsForeign,
|
const bool& aIsForeign,
|
||||||
const nsCString& aCookieString,
|
const nsCString& aCookieString,
|
||||||
const nsCString& aServerTime,
|
const nsCString& aServerTime,
|
||||||
const bool& aFromHttp)
|
const bool& aFromHttp,
|
||||||
|
const IPC::SerializedLoadContext&
|
||||||
|
aLoadContext)
|
||||||
{
|
{
|
||||||
if (!mCookieService)
|
if (!mCookieService)
|
||||||
return true;
|
return true;
|
||||||
@@ -66,13 +74,34 @@ CookieServiceParent::RecvSetCookieString(const URIParams& aHost,
|
|||||||
if (!hostURI)
|
if (!hostURI)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
uint32_t appId;
|
||||||
|
bool isInBrowserElement;
|
||||||
|
GetAppInfoFromLoadContext(aLoadContext, appId, isInBrowserElement);
|
||||||
|
|
||||||
nsDependentCString cookieString(aCookieString, 0);
|
nsDependentCString cookieString(aCookieString, 0);
|
||||||
mCookieService->SetCookieStringInternal(hostURI, aIsForeign,
|
mCookieService->SetCookieStringInternal(hostURI, aIsForeign, cookieString,
|
||||||
cookieString, aServerTime,
|
aServerTime, aFromHttp, appId,
|
||||||
aFromHttp);
|
isInBrowserElement);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
CookieServiceParent::GetAppInfoFromLoadContext(
|
||||||
|
const IPC::SerializedLoadContext &aLoadContext,
|
||||||
|
uint32_t& aAppId,
|
||||||
|
bool& aIsInBrowserElement)
|
||||||
|
{
|
||||||
|
// TODO: bug 782542: what to do when we get null loadContext? For now assume
|
||||||
|
// NECKO_NO_APP_ID.
|
||||||
|
aAppId = NECKO_NO_APP_ID;
|
||||||
|
aIsInBrowserElement = false;
|
||||||
|
|
||||||
|
if (aLoadContext.IsNotNull()) {
|
||||||
|
aAppId = aLoadContext.mAppId;
|
||||||
|
aIsInBrowserElement = aLoadContext.mIsInBrowserElement;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -7,6 +7,7 @@
|
|||||||
#define mozilla_net_CookieServiceParent_h
|
#define mozilla_net_CookieServiceParent_h
|
||||||
|
|
||||||
#include "mozilla/net/PCookieServiceParent.h"
|
#include "mozilla/net/PCookieServiceParent.h"
|
||||||
|
#include "SerializedLoadContext.h"
|
||||||
|
|
||||||
class nsCookieService;
|
class nsCookieService;
|
||||||
class nsIIOService;
|
class nsIIOService;
|
||||||
@@ -24,13 +25,20 @@ protected:
|
|||||||
virtual bool RecvGetCookieString(const URIParams& aHost,
|
virtual bool RecvGetCookieString(const URIParams& aHost,
|
||||||
const bool& aIsForeign,
|
const bool& aIsForeign,
|
||||||
const bool& aFromHttp,
|
const bool& aFromHttp,
|
||||||
|
const IPC::SerializedLoadContext&
|
||||||
|
loadContext,
|
||||||
nsCString* aResult);
|
nsCString* aResult);
|
||||||
|
|
||||||
virtual bool RecvSetCookieString(const URIParams& aHost,
|
virtual bool RecvSetCookieString(const URIParams& aHost,
|
||||||
const bool& aIsForeign,
|
const bool& aIsForeign,
|
||||||
const nsCString& aCookieString,
|
const nsCString& aCookieString,
|
||||||
const nsCString& aServerTime,
|
const nsCString& aServerTime,
|
||||||
const bool& aFromHttp);
|
const bool& aFromHttp,
|
||||||
|
const IPC::SerializedLoadContext&
|
||||||
|
loadContext);
|
||||||
|
|
||||||
|
void GetAppInfoFromLoadContext(const IPC::SerializedLoadContext& aLoadContext,
|
||||||
|
uint32_t& aAppId, bool& aIsInBrowserElement);
|
||||||
|
|
||||||
nsRefPtr<nsCookieService> mCookieService;
|
nsRefPtr<nsCookieService> mCookieService;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -8,6 +8,10 @@
|
|||||||
include protocol PNecko;
|
include protocol PNecko;
|
||||||
include URIParams;
|
include URIParams;
|
||||||
|
|
||||||
|
include "SerializedLoadContext.h";
|
||||||
|
|
||||||
|
using IPC::SerializedLoadContext;
|
||||||
|
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
namespace net {
|
namespace net {
|
||||||
|
|
||||||
@@ -47,6 +51,9 @@ parent:
|
|||||||
* Whether the result is for an HTTP request header. This should be
|
* Whether the result is for an HTTP request header. This should be
|
||||||
* true for nsICookieService.getCookieStringFromHttp calls, false
|
* true for nsICookieService.getCookieStringFromHttp calls, false
|
||||||
* otherwise.
|
* otherwise.
|
||||||
|
* @param loadContext
|
||||||
|
* The loadContext from the HTTP channel or document that the cookie is
|
||||||
|
* being set on.
|
||||||
*
|
*
|
||||||
* @see nsICookieService.getCookieString
|
* @see nsICookieService.getCookieString
|
||||||
* @see nsICookieService.getCookieStringFromHttp
|
* @see nsICookieService.getCookieStringFromHttp
|
||||||
@@ -56,7 +63,8 @@ parent:
|
|||||||
*/
|
*/
|
||||||
sync GetCookieString(URIParams host,
|
sync GetCookieString(URIParams host,
|
||||||
bool isForeign,
|
bool isForeign,
|
||||||
bool fromHttp)
|
bool fromHttp,
|
||||||
|
SerializedLoadContext loadContext)
|
||||||
returns (nsCString result);
|
returns (nsCString result);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -80,6 +88,9 @@ parent:
|
|||||||
* Whether the result is for an HTTP request header. This should be
|
* Whether the result is for an HTTP request header. This should be
|
||||||
* true for nsICookieService.setCookieStringFromHttp calls, false
|
* true for nsICookieService.setCookieStringFromHttp calls, false
|
||||||
* otherwise.
|
* otherwise.
|
||||||
|
* @param loadContext
|
||||||
|
* The loadContext from the HTTP channel or document that the cookie is
|
||||||
|
* being set on.
|
||||||
*
|
*
|
||||||
* @see nsICookieService.setCookieString
|
* @see nsICookieService.setCookieString
|
||||||
* @see nsICookieService.setCookieStringFromHttp
|
* @see nsICookieService.setCookieStringFromHttp
|
||||||
@@ -89,7 +100,8 @@ parent:
|
|||||||
bool isForeign,
|
bool isForeign,
|
||||||
nsCString cookieString,
|
nsCString cookieString,
|
||||||
nsCString serverTime,
|
nsCString serverTime,
|
||||||
bool fromHttp);
|
bool fromHttp,
|
||||||
|
SerializedLoadContext loadContext);
|
||||||
|
|
||||||
__delete__();
|
__delete__();
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||||
|
/* vim: set sw=2 ts=8 et tw=80 : */
|
||||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
@@ -52,6 +53,13 @@
|
|||||||
using namespace mozilla;
|
using namespace mozilla;
|
||||||
using namespace mozilla::net;
|
using namespace mozilla::net;
|
||||||
|
|
||||||
|
// Create key from baseDomain that will access the default cookie namespace.
|
||||||
|
// TODO: When we figure out what the API will look like for nsICookieManager{2}
|
||||||
|
// on content processes (see bug 777620), change to use the appropriate app
|
||||||
|
// namespace. For now those IDLs aren't supported on child processes.
|
||||||
|
#define DEFAULT_APP_KEY(baseDomain) \
|
||||||
|
nsCookieKey(baseDomain, NECKO_NO_APP_ID, false)
|
||||||
|
|
||||||
/******************************************************************************
|
/******************************************************************************
|
||||||
* nsCookieService impl:
|
* nsCookieService impl:
|
||||||
* useful types & constants
|
* useful types & constants
|
||||||
@@ -64,7 +72,7 @@ static nsCookieService *gCookieService;
|
|||||||
static const char kHttpOnlyPrefix[] = "#HttpOnly_";
|
static const char kHttpOnlyPrefix[] = "#HttpOnly_";
|
||||||
|
|
||||||
#define COOKIES_FILE "cookies.sqlite"
|
#define COOKIES_FILE "cookies.sqlite"
|
||||||
#define COOKIES_SCHEMA_VERSION 4
|
#define COOKIES_SCHEMA_VERSION 5
|
||||||
|
|
||||||
static const int64_t kCookieStaleThreshold = 60 * PR_USEC_PER_SEC; // 1 minute in microseconds
|
static const int64_t kCookieStaleThreshold = 60 * PR_USEC_PER_SEC; // 1 minute in microseconds
|
||||||
static const int64_t kCookiePurgeAge =
|
static const int64_t kCookiePurgeAge =
|
||||||
@@ -99,7 +107,7 @@ static const char kPrefThirdPartySession[] = "network.cookie.thirdparty.session
|
|||||||
|
|
||||||
static void
|
static void
|
||||||
bindCookieParameters(mozIStorageBindingParamsArray *aParamsArray,
|
bindCookieParameters(mozIStorageBindingParamsArray *aParamsArray,
|
||||||
const nsCString &aBaseDomain,
|
const nsCookieKey &aKey,
|
||||||
const nsCookie *aCookie);
|
const nsCookie *aCookie);
|
||||||
|
|
||||||
// struct for temporarily storing cookie attributes during header parsing
|
// struct for temporarily storing cookie attributes during header parsing
|
||||||
@@ -467,7 +475,9 @@ public:
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
CookieDomainTuple *tuple = mDBState->hostArray.AppendElement();
|
CookieDomainTuple *tuple = mDBState->hostArray.AppendElement();
|
||||||
row->GetUTF8String(9, tuple->baseDomain);
|
row->GetUTF8String(9, tuple->key.mBaseDomain);
|
||||||
|
tuple->key.mAppId = static_cast<uint32_t>(row->AsInt32(10));
|
||||||
|
tuple->key.mInBrowserElement = static_cast<bool>(row->AsInt32(11));
|
||||||
tuple->cookie = gCookieService->GetCookieFromRow(row);
|
tuple->cookie = gCookieService->GetCookieFromRow(row);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -930,6 +940,52 @@ nsCookieService::TryInitDB(bool aRecreateDB)
|
|||||||
}
|
}
|
||||||
// Fall through to the next upgrade.
|
// Fall through to the next upgrade.
|
||||||
|
|
||||||
|
case 4:
|
||||||
|
{
|
||||||
|
// We need to add appId/inBrowserElement, plus change a constraint on
|
||||||
|
// the table (unique entries now include appId/inBrowserElement):
|
||||||
|
// this requires creating a new table and copying the data to it. We
|
||||||
|
// then rename the new table to the old name.
|
||||||
|
//
|
||||||
|
// Why we made this change: appId/inBrowserElement allow "cookie jars"
|
||||||
|
// for Firefox OS. We create a separate cookie namespace per {appId,
|
||||||
|
// inBrowserElement}. When upgrading, we convert existing cookies
|
||||||
|
// (which imply we're on desktop/mobile) to use {0, false}, as that is
|
||||||
|
// the only namespace used by a non-Firefox-OS implementation.
|
||||||
|
|
||||||
|
// Rename existing table
|
||||||
|
rv = mDefaultDBState->dbConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
|
||||||
|
"ALTER TABLE moz_cookies RENAME TO moz_cookies_old"));
|
||||||
|
NS_ENSURE_SUCCESS(rv, RESULT_RETRY);
|
||||||
|
|
||||||
|
// Drop existing index (CreateTable will create new one for new table)
|
||||||
|
rv = mDefaultDBState->dbConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
|
||||||
|
"DROP INDEX moz_basedomain"));
|
||||||
|
NS_ENSURE_SUCCESS(rv, RESULT_RETRY);
|
||||||
|
|
||||||
|
// Create new table (with new fields and new unique constraint)
|
||||||
|
rv = CreateTable();
|
||||||
|
NS_ENSURE_SUCCESS(rv, RESULT_RETRY);
|
||||||
|
|
||||||
|
// Copy data from old table, using appId/inBrowser=0 for existing rows
|
||||||
|
rv = mDefaultDBState->dbConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
|
||||||
|
"INSERT INTO moz_cookies "
|
||||||
|
"(baseDomain, appId, inBrowserElement, name, value, host, path, expiry,"
|
||||||
|
" lastAccessed, creationTime, isSecure, isHttpOnly) "
|
||||||
|
"SELECT baseDomain, 0, 0, name, value, host, path, expiry,"
|
||||||
|
" lastAccessed, creationTime, isSecure, isHttpOnly "
|
||||||
|
"FROM moz_cookies_old"));
|
||||||
|
NS_ENSURE_SUCCESS(rv, RESULT_RETRY);
|
||||||
|
|
||||||
|
// Drop old table
|
||||||
|
rv = mDefaultDBState->dbConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
|
||||||
|
"DROP TABLE moz_cookies_old"));
|
||||||
|
NS_ENSURE_SUCCESS(rv, RESULT_RETRY);
|
||||||
|
|
||||||
|
COOKIE_LOGSTRING(PR_LOG_DEBUG,
|
||||||
|
("Upgraded database to schema version 5"));
|
||||||
|
}
|
||||||
|
|
||||||
// No more upgrades. Update the schema version.
|
// No more upgrades. Update the schema version.
|
||||||
rv = mDefaultDBState->dbConn->SetSchemaVersion(COOKIES_SCHEMA_VERSION);
|
rv = mDefaultDBState->dbConn->SetSchemaVersion(COOKIES_SCHEMA_VERSION);
|
||||||
NS_ENSURE_SUCCESS(rv, RESULT_RETRY);
|
NS_ENSURE_SUCCESS(rv, RESULT_RETRY);
|
||||||
@@ -965,6 +1021,8 @@ nsCookieService::TryInitDB(bool aRecreateDB)
|
|||||||
"SELECT "
|
"SELECT "
|
||||||
"id, "
|
"id, "
|
||||||
"baseDomain, "
|
"baseDomain, "
|
||||||
|
"appId, "
|
||||||
|
"inBrowserElement, "
|
||||||
"name, "
|
"name, "
|
||||||
"value, "
|
"value, "
|
||||||
"host, "
|
"host, "
|
||||||
@@ -1005,6 +1063,8 @@ nsCookieService::TryInitDB(bool aRecreateDB)
|
|||||||
rv = mDefaultDBState->dbConn->CreateAsyncStatement(NS_LITERAL_CSTRING(
|
rv = mDefaultDBState->dbConn->CreateAsyncStatement(NS_LITERAL_CSTRING(
|
||||||
"INSERT INTO moz_cookies ("
|
"INSERT INTO moz_cookies ("
|
||||||
"baseDomain, "
|
"baseDomain, "
|
||||||
|
"appId, "
|
||||||
|
"inBrowserElement, "
|
||||||
"name, "
|
"name, "
|
||||||
"value, "
|
"value, "
|
||||||
"host, "
|
"host, "
|
||||||
@@ -1016,6 +1076,8 @@ nsCookieService::TryInitDB(bool aRecreateDB)
|
|||||||
"isHttpOnly"
|
"isHttpOnly"
|
||||||
") VALUES ("
|
") VALUES ("
|
||||||
":baseDomain, "
|
":baseDomain, "
|
||||||
|
":appId, "
|
||||||
|
":inBrowserElement, "
|
||||||
":name, "
|
":name, "
|
||||||
":value, "
|
":value, "
|
||||||
":host, "
|
":host, "
|
||||||
@@ -1076,11 +1138,15 @@ nsCookieService::CreateTable()
|
|||||||
COOKIES_SCHEMA_VERSION);
|
COOKIES_SCHEMA_VERSION);
|
||||||
if (NS_FAILED(rv)) return rv;
|
if (NS_FAILED(rv)) return rv;
|
||||||
|
|
||||||
// Create the table.
|
// Create the table. We default appId/inBrowserElement to 0: this is so if
|
||||||
|
// users revert to an older Firefox version that doesn't know about these
|
||||||
|
// fields, any cookies set will still work once they upgrade back.
|
||||||
rv = mDefaultDBState->dbConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
|
rv = mDefaultDBState->dbConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
|
||||||
"CREATE TABLE moz_cookies ("
|
"CREATE TABLE moz_cookies ("
|
||||||
"id INTEGER PRIMARY KEY, "
|
"id INTEGER PRIMARY KEY, "
|
||||||
"baseDomain TEXT, "
|
"baseDomain TEXT, "
|
||||||
|
"appId INTEGER DEFAULT 0, "
|
||||||
|
"inBrowserElement INTEGER DEFAULT 0, "
|
||||||
"name TEXT, "
|
"name TEXT, "
|
||||||
"value TEXT, "
|
"value TEXT, "
|
||||||
"host TEXT, "
|
"host TEXT, "
|
||||||
@@ -1090,13 +1156,15 @@ nsCookieService::CreateTable()
|
|||||||
"creationTime INTEGER, "
|
"creationTime INTEGER, "
|
||||||
"isSecure INTEGER, "
|
"isSecure INTEGER, "
|
||||||
"isHttpOnly INTEGER, "
|
"isHttpOnly INTEGER, "
|
||||||
"CONSTRAINT moz_uniqueid UNIQUE (name, host, path)"
|
"CONSTRAINT moz_uniqueid UNIQUE (name, host, path, appId, inBrowserElement)"
|
||||||
")"));
|
")"));
|
||||||
if (NS_FAILED(rv)) return rv;
|
if (NS_FAILED(rv)) return rv;
|
||||||
|
|
||||||
// Create an index on baseDomain.
|
// Create an index on baseDomain.
|
||||||
return mDefaultDBState->dbConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
|
return mDefaultDBState->dbConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
|
||||||
"CREATE INDEX moz_basedomain ON moz_cookies (baseDomain)"));
|
"CREATE INDEX moz_basedomain ON moz_cookies (baseDomain, "
|
||||||
|
"appId, "
|
||||||
|
"inBrowserElement)"));
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@@ -1254,7 +1322,7 @@ RebuildDBCallback(nsCookieEntry *aEntry,
|
|||||||
nsCookie* cookie = cookies[i];
|
nsCookie* cookie = cookies[i];
|
||||||
|
|
||||||
if (!cookie->IsSession()) {
|
if (!cookie->IsSession()) {
|
||||||
bindCookieParameters(paramsArray, aEntry->GetKey(), cookie);
|
bindCookieParameters(paramsArray, aEntry, cookie);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1422,8 +1490,16 @@ nsCookieService::GetCookieStringCommon(nsIURI *aHostURI,
|
|||||||
bool isForeign = true;
|
bool isForeign = true;
|
||||||
mThirdPartyUtil->IsThirdPartyChannel(aChannel, aHostURI, &isForeign);
|
mThirdPartyUtil->IsThirdPartyChannel(aChannel, aHostURI, &isForeign);
|
||||||
|
|
||||||
|
// Get app info, if channel is present. Else assume default namespace.
|
||||||
|
uint32_t appId = NECKO_NO_APP_ID;
|
||||||
|
bool inBrowserElement = false;
|
||||||
|
if (aChannel) {
|
||||||
|
NS_GetAppInfo(aChannel, &appId, &inBrowserElement);
|
||||||
|
}
|
||||||
|
|
||||||
nsAutoCString result;
|
nsAutoCString result;
|
||||||
GetCookieStringInternal(aHostURI, isForeign, aHttpBound, result);
|
GetCookieStringInternal(aHostURI, isForeign, aHttpBound, appId,
|
||||||
|
inBrowserElement, result);
|
||||||
*aCookie = result.IsEmpty() ? nullptr : ToNewCString(result);
|
*aCookie = result.IsEmpty() ? nullptr : ToNewCString(result);
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
@@ -1463,10 +1539,17 @@ nsCookieService::SetCookieStringCommon(nsIURI *aHostURI,
|
|||||||
bool isForeign = true;
|
bool isForeign = true;
|
||||||
mThirdPartyUtil->IsThirdPartyChannel(aChannel, aHostURI, &isForeign);
|
mThirdPartyUtil->IsThirdPartyChannel(aChannel, aHostURI, &isForeign);
|
||||||
|
|
||||||
|
// Get app info, if channel is present. Else assume default namespace.
|
||||||
|
uint32_t appId = NECKO_NO_APP_ID;
|
||||||
|
bool inBrowserElement = false;
|
||||||
|
if (aChannel) {
|
||||||
|
NS_GetAppInfo(aChannel, &appId, &inBrowserElement);
|
||||||
|
}
|
||||||
|
|
||||||
nsDependentCString cookieString(aCookieHeader);
|
nsDependentCString cookieString(aCookieHeader);
|
||||||
nsDependentCString serverTime(aServerTime ? aServerTime : "");
|
nsDependentCString serverTime(aServerTime ? aServerTime : "");
|
||||||
SetCookieStringInternal(aHostURI, isForeign, cookieString,
|
SetCookieStringInternal(aHostURI, isForeign, cookieString,
|
||||||
serverTime, aFromHttp);
|
serverTime, aFromHttp, appId, inBrowserElement);
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1475,7 +1558,9 @@ nsCookieService::SetCookieStringInternal(nsIURI *aHostURI,
|
|||||||
bool aIsForeign,
|
bool aIsForeign,
|
||||||
nsDependentCString &aCookieHeader,
|
nsDependentCString &aCookieHeader,
|
||||||
const nsCString &aServerTime,
|
const nsCString &aServerTime,
|
||||||
bool aFromHttp)
|
bool aFromHttp,
|
||||||
|
uint32_t aAppId,
|
||||||
|
bool aInBrowserElement)
|
||||||
{
|
{
|
||||||
NS_ASSERTION(aHostURI, "null host!");
|
NS_ASSERTION(aHostURI, "null host!");
|
||||||
|
|
||||||
@@ -1498,9 +1583,11 @@ nsCookieService::SetCookieStringInternal(nsIURI *aHostURI,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
nsCookieKey key(baseDomain, aAppId, aInBrowserElement);
|
||||||
|
|
||||||
// check default prefs
|
// check default prefs
|
||||||
CookieStatus cookieStatus = CheckPrefs(aHostURI, aIsForeign, baseDomain,
|
CookieStatus cookieStatus = CheckPrefs(aHostURI, aIsForeign, requireHostMatch,
|
||||||
requireHostMatch, aCookieHeader.get());
|
aCookieHeader.get());
|
||||||
// fire a notification if cookie was rejected (but not if there was an error)
|
// fire a notification if cookie was rejected (but not if there was an error)
|
||||||
switch (cookieStatus) {
|
switch (cookieStatus) {
|
||||||
case STATUS_REJECTED:
|
case STATUS_REJECTED:
|
||||||
@@ -1528,7 +1615,7 @@ nsCookieService::SetCookieStringInternal(nsIURI *aHostURI,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// process each cookie in the header
|
// process each cookie in the header
|
||||||
while (SetCookieInternal(aHostURI, baseDomain, requireHostMatch, cookieStatus,
|
while (SetCookieInternal(aHostURI, key, requireHostMatch, cookieStatus,
|
||||||
aCookieHeader, serverTime, aFromHttp)) {
|
aCookieHeader, serverTime, aFromHttp)) {
|
||||||
// document.cookie can only set one cookie at a time
|
// document.cookie can only set one cookie at a time
|
||||||
if (!aFromHttp)
|
if (!aFromHttp)
|
||||||
@@ -1712,7 +1799,7 @@ nsCookieService::Add(const nsACString &aHost,
|
|||||||
return NS_ERROR_OUT_OF_MEMORY;
|
return NS_ERROR_OUT_OF_MEMORY;
|
||||||
}
|
}
|
||||||
|
|
||||||
AddInternal(baseDomain, cookie, currentTimeInUsec, nullptr, nullptr, true);
|
AddInternal(DEFAULT_APP_KEY(baseDomain), cookie, currentTimeInUsec, nullptr, nullptr, true);
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1738,7 +1825,7 @@ nsCookieService::Remove(const nsACString &aHost,
|
|||||||
|
|
||||||
nsListIter matchIter;
|
nsListIter matchIter;
|
||||||
nsRefPtr<nsCookie> cookie;
|
nsRefPtr<nsCookie> cookie;
|
||||||
if (FindCookie(baseDomain,
|
if (FindCookie(DEFAULT_APP_KEY(baseDomain),
|
||||||
host,
|
host,
|
||||||
PromiseFlatCString(aName),
|
PromiseFlatCString(aName),
|
||||||
PromiseFlatCString(aPath),
|
PromiseFlatCString(aPath),
|
||||||
@@ -1793,7 +1880,9 @@ nsCookieService::Read()
|
|||||||
"creationTime, "
|
"creationTime, "
|
||||||
"isSecure, "
|
"isSecure, "
|
||||||
"isHttpOnly, "
|
"isHttpOnly, "
|
||||||
"baseDomain "
|
"baseDomain, "
|
||||||
|
"appId, "
|
||||||
|
"inBrowserElement "
|
||||||
"FROM moz_cookies "
|
"FROM moz_cookies "
|
||||||
"WHERE baseDomain NOTNULL"), getter_AddRefs(stmtRead));
|
"WHERE baseDomain NOTNULL"), getter_AddRefs(stmtRead));
|
||||||
NS_ENSURE_SUCCESS(rv, RESULT_RETRY);
|
NS_ENSURE_SUCCESS(rv, RESULT_RETRY);
|
||||||
@@ -1885,11 +1974,10 @@ nsCookieService::AsyncReadComplete()
|
|||||||
// Tiebreak: if the given base domain has already been read in, ignore
|
// Tiebreak: if the given base domain has already been read in, ignore
|
||||||
// the background data. Note that readSet may contain domains that were
|
// the background data. Note that readSet may contain domains that were
|
||||||
// queried but found not to be in the db -- that's harmless.
|
// queried but found not to be in the db -- that's harmless.
|
||||||
if (mDefaultDBState->readSet.GetEntry(tuple.baseDomain))
|
if (mDefaultDBState->readSet.GetEntry(tuple.key))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
AddCookieToList(tuple.baseDomain, tuple.cookie, mDefaultDBState, NULL,
|
AddCookieToList(tuple.key, tuple.cookie, mDefaultDBState, NULL, false);
|
||||||
false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
mDefaultDBState->stmtReadDomain = nullptr;
|
mDefaultDBState->stmtReadDomain = nullptr;
|
||||||
@@ -1933,7 +2021,7 @@ nsCookieService::CancelAsyncRead(bool aPurgeReadSet)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
nsCookieService::EnsureReadDomain(const nsCString &aBaseDomain)
|
nsCookieService::EnsureReadDomain(const nsCookieKey &aKey)
|
||||||
{
|
{
|
||||||
NS_ASSERTION(!mDBState->dbConn || mDBState == mDefaultDBState,
|
NS_ASSERTION(!mDBState->dbConn || mDBState == mDefaultDBState,
|
||||||
"not in default db state");
|
"not in default db state");
|
||||||
@@ -1943,7 +2031,7 @@ nsCookieService::EnsureReadDomain(const nsCString &aBaseDomain)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
// Fast path 2: already read in this particular domain.
|
// Fast path 2: already read in this particular domain.
|
||||||
if (NS_LIKELY(mDefaultDBState->readSet.GetEntry(aBaseDomain)))
|
if (NS_LIKELY(mDefaultDBState->readSet.GetEntry(aKey)))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// Read in the data synchronously.
|
// Read in the data synchronously.
|
||||||
@@ -1962,7 +2050,9 @@ nsCookieService::EnsureReadDomain(const nsCString &aBaseDomain)
|
|||||||
"isSecure, "
|
"isSecure, "
|
||||||
"isHttpOnly "
|
"isHttpOnly "
|
||||||
"FROM moz_cookies "
|
"FROM moz_cookies "
|
||||||
"WHERE baseDomain = :baseDomain"),
|
"WHERE baseDomain = :baseDomain "
|
||||||
|
" AND appId = :appId "
|
||||||
|
" AND inBrowserElement = :inBrowserElement"),
|
||||||
getter_AddRefs(mDefaultDBState->stmtReadDomain));
|
getter_AddRefs(mDefaultDBState->stmtReadDomain));
|
||||||
|
|
||||||
if (NS_FAILED(rv)) {
|
if (NS_FAILED(rv)) {
|
||||||
@@ -1980,8 +2070,15 @@ nsCookieService::EnsureReadDomain(const nsCString &aBaseDomain)
|
|||||||
mozStorageStatementScoper scoper(mDefaultDBState->stmtReadDomain);
|
mozStorageStatementScoper scoper(mDefaultDBState->stmtReadDomain);
|
||||||
|
|
||||||
rv = mDefaultDBState->stmtReadDomain->BindUTF8StringByName(
|
rv = mDefaultDBState->stmtReadDomain->BindUTF8StringByName(
|
||||||
NS_LITERAL_CSTRING("baseDomain"), aBaseDomain);
|
NS_LITERAL_CSTRING("baseDomain"), aKey.mBaseDomain);
|
||||||
NS_ASSERT_SUCCESS(rv);
|
NS_ASSERT_SUCCESS(rv);
|
||||||
|
rv = mDefaultDBState->stmtReadDomain->BindInt32ByName(
|
||||||
|
NS_LITERAL_CSTRING("appId"), aKey.mAppId);
|
||||||
|
NS_ASSERT_SUCCESS(rv);
|
||||||
|
rv = mDefaultDBState->stmtReadDomain->BindInt32ByName(
|
||||||
|
NS_LITERAL_CSTRING("inBrowserElement"), aKey.mInBrowserElement ? 1 : 0);
|
||||||
|
NS_ASSERT_SUCCESS(rv);
|
||||||
|
|
||||||
|
|
||||||
bool hasResult;
|
bool hasResult;
|
||||||
nsCString name, value, host, path;
|
nsCString name, value, host, path;
|
||||||
@@ -2006,15 +2103,16 @@ nsCookieService::EnsureReadDomain(const nsCString &aBaseDomain)
|
|||||||
// Add the cookies to the table in a single operation. This makes sure that
|
// Add the cookies to the table in a single operation. This makes sure that
|
||||||
// either all the cookies get added, or in the case of corruption, none.
|
// either all the cookies get added, or in the case of corruption, none.
|
||||||
for (uint32_t i = 0; i < array.Length(); ++i) {
|
for (uint32_t i = 0; i < array.Length(); ++i) {
|
||||||
AddCookieToList(aBaseDomain, array[i], mDefaultDBState, NULL, false);
|
AddCookieToList(aKey, array[i], mDefaultDBState, NULL, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add it to the hashset of read entries, so we don't read it again.
|
// Add it to the hashset of read entries, so we don't read it again.
|
||||||
mDefaultDBState->readSet.PutEntry(aBaseDomain);
|
mDefaultDBState->readSet.PutEntry(aKey);
|
||||||
|
|
||||||
COOKIE_LOGSTRING(PR_LOG_DEBUG,
|
COOKIE_LOGSTRING(PR_LOG_DEBUG,
|
||||||
("EnsureReadDomain(): %ld cookies read for base domain %s",
|
("EnsureReadDomain(): %ld cookies read for base domain %s, "
|
||||||
array.Length(), aBaseDomain.get()));
|
" appId=%u, inBrowser=%d", array.Length(), aKey.mBaseDomain.get(),
|
||||||
|
(unsigned)aKey.mAppId, (int)aKey.mInBrowserElement));
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@@ -2043,7 +2141,9 @@ nsCookieService::EnsureReadComplete()
|
|||||||
"creationTime, "
|
"creationTime, "
|
||||||
"isSecure, "
|
"isSecure, "
|
||||||
"isHttpOnly, "
|
"isHttpOnly, "
|
||||||
"baseDomain "
|
"baseDomain, "
|
||||||
|
"appId, "
|
||||||
|
"inBrowserElement "
|
||||||
"FROM moz_cookies "
|
"FROM moz_cookies "
|
||||||
"WHERE baseDomain NOTNULL"), getter_AddRefs(stmt));
|
"WHERE baseDomain NOTNULL"), getter_AddRefs(stmt));
|
||||||
|
|
||||||
@@ -2057,7 +2157,8 @@ nsCookieService::EnsureReadComplete()
|
|||||||
}
|
}
|
||||||
|
|
||||||
nsCString baseDomain, name, value, host, path;
|
nsCString baseDomain, name, value, host, path;
|
||||||
bool hasResult;
|
uint32_t appId;
|
||||||
|
bool inBrowserElement, hasResult;
|
||||||
nsAutoTArray<CookieDomainTuple, kMaxNumberOfCookies> array;
|
nsAutoTArray<CookieDomainTuple, kMaxNumberOfCookies> array;
|
||||||
while (1) {
|
while (1) {
|
||||||
rv = stmt->ExecuteStep(&hasResult);
|
rv = stmt->ExecuteStep(&hasResult);
|
||||||
@@ -2075,11 +2176,14 @@ nsCookieService::EnsureReadComplete()
|
|||||||
|
|
||||||
// Make sure we haven't already read the data.
|
// Make sure we haven't already read the data.
|
||||||
stmt->GetUTF8String(9, baseDomain);
|
stmt->GetUTF8String(9, baseDomain);
|
||||||
if (mDefaultDBState->readSet.GetEntry(baseDomain))
|
appId = static_cast<uint32_t>(stmt->AsInt32(10));
|
||||||
|
inBrowserElement = static_cast<bool>(stmt->AsInt32(11));
|
||||||
|
nsCookieKey key(baseDomain, appId, inBrowserElement);
|
||||||
|
if (mDefaultDBState->readSet.GetEntry(key))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
CookieDomainTuple* tuple = array.AppendElement();
|
CookieDomainTuple* tuple = array.AppendElement();
|
||||||
tuple->baseDomain = baseDomain;
|
tuple->key = key;
|
||||||
tuple->cookie = GetCookieFromRow(stmt);
|
tuple->cookie = GetCookieFromRow(stmt);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2087,7 +2191,7 @@ nsCookieService::EnsureReadComplete()
|
|||||||
// either all the cookies get added, or in the case of corruption, none.
|
// either all the cookies get added, or in the case of corruption, none.
|
||||||
for (uint32_t i = 0; i < array.Length(); ++i) {
|
for (uint32_t i = 0; i < array.Length(); ++i) {
|
||||||
CookieDomainTuple& tuple = array[i];
|
CookieDomainTuple& tuple = array[i];
|
||||||
AddCookieToList(tuple.baseDomain, tuple.cookie, mDefaultDBState, NULL,
|
AddCookieToList(tuple.key, tuple.cookie, mDefaultDBState, NULL,
|
||||||
false);
|
false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2218,6 +2322,9 @@ nsCookieService::ImportCookies(nsIFile *aCookieFile)
|
|||||||
if (NS_FAILED(rv))
|
if (NS_FAILED(rv))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
// pre-existing cookies have appId=0, inBrowser=false
|
||||||
|
nsCookieKey key = DEFAULT_APP_KEY(baseDomain);
|
||||||
|
|
||||||
// Create a new nsCookie and assign the data. We don't know the cookie
|
// 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.
|
// creation time, so just use the current time to generate a unique one.
|
||||||
nsRefPtr<nsCookie> newCookie =
|
nsRefPtr<nsCookie> newCookie =
|
||||||
@@ -2240,10 +2347,11 @@ nsCookieService::ImportCookies(nsIFile *aCookieFile)
|
|||||||
lastAccessedCounter--;
|
lastAccessedCounter--;
|
||||||
|
|
||||||
if (originalCookieCount == 0) {
|
if (originalCookieCount == 0) {
|
||||||
AddCookieToList(baseDomain, newCookie, mDefaultDBState, paramsArray);
|
AddCookieToList(key, newCookie, mDefaultDBState, paramsArray);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
AddInternal(baseDomain, newCookie, currentTimeInUsec, NULL, NULL, true);
|
AddInternal(key, newCookie, currentTimeInUsec,
|
||||||
|
NULL, NULL, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2305,6 +2413,8 @@ void
|
|||||||
nsCookieService::GetCookieStringInternal(nsIURI *aHostURI,
|
nsCookieService::GetCookieStringInternal(nsIURI *aHostURI,
|
||||||
bool aIsForeign,
|
bool aIsForeign,
|
||||||
bool aHttpBound,
|
bool aHttpBound,
|
||||||
|
uint32_t aAppId,
|
||||||
|
bool aInBrowserElement,
|
||||||
nsCString &aCookieString)
|
nsCString &aCookieString)
|
||||||
{
|
{
|
||||||
NS_ASSERTION(aHostURI, "null host!");
|
NS_ASSERTION(aHostURI, "null host!");
|
||||||
@@ -2332,8 +2442,8 @@ nsCookieService::GetCookieStringInternal(nsIURI *aHostURI,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// check default prefs
|
// check default prefs
|
||||||
CookieStatus cookieStatus = CheckPrefs(aHostURI, aIsForeign, baseDomain,
|
CookieStatus cookieStatus = CheckPrefs(aHostURI, aIsForeign, requireHostMatch,
|
||||||
requireHostMatch, nullptr);
|
nullptr);
|
||||||
// for GetCookie(), we don't fire rejection notifications.
|
// for GetCookie(), we don't fire rejection notifications.
|
||||||
switch (cookieStatus) {
|
switch (cookieStatus) {
|
||||||
case STATUS_REJECTED:
|
case STATUS_REJECTED:
|
||||||
@@ -2357,10 +2467,11 @@ nsCookieService::GetCookieStringInternal(nsIURI *aHostURI,
|
|||||||
int64_t currentTime = currentTimeInUsec / PR_USEC_PER_SEC;
|
int64_t currentTime = currentTimeInUsec / PR_USEC_PER_SEC;
|
||||||
bool stale = false;
|
bool stale = false;
|
||||||
|
|
||||||
EnsureReadDomain(baseDomain);
|
nsCookieKey key(baseDomain, aAppId, aInBrowserElement);
|
||||||
|
EnsureReadDomain(key);
|
||||||
|
|
||||||
// perform the hash lookup
|
// perform the hash lookup
|
||||||
nsCookieEntry *entry = mDBState->hostTable.GetEntry(baseDomain);
|
nsCookieEntry *entry = mDBState->hostTable.GetEntry(key);
|
||||||
if (!entry)
|
if (!entry)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@@ -2489,7 +2600,7 @@ nsCookieService::GetCookieStringInternal(nsIURI *aHostURI,
|
|||||||
// to be processed
|
// to be processed
|
||||||
bool
|
bool
|
||||||
nsCookieService::SetCookieInternal(nsIURI *aHostURI,
|
nsCookieService::SetCookieInternal(nsIURI *aHostURI,
|
||||||
const nsCString &aBaseDomain,
|
const nsCookieKey &aKey,
|
||||||
bool aRequireHostMatch,
|
bool aRequireHostMatch,
|
||||||
CookieStatus aStatus,
|
CookieStatus aStatus,
|
||||||
nsDependentCString &aCookieHeader,
|
nsDependentCString &aCookieHeader,
|
||||||
@@ -2536,7 +2647,7 @@ nsCookieService::SetCookieInternal(nsIURI *aHostURI,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// domain & path checks
|
// domain & path checks
|
||||||
if (!CheckDomain(cookieAttributes, aHostURI, aBaseDomain, aRequireHostMatch)) {
|
if (!CheckDomain(cookieAttributes, aHostURI, aKey.mBaseDomain, aRequireHostMatch)) {
|
||||||
COOKIE_LOGFAILURE(SET_COOKIE, aHostURI, savedCookieHeader, "failed the domain tests");
|
COOKIE_LOGFAILURE(SET_COOKIE, aHostURI, savedCookieHeader, "failed the domain tests");
|
||||||
return newCookie;
|
return newCookie;
|
||||||
}
|
}
|
||||||
@@ -2586,7 +2697,7 @@ nsCookieService::SetCookieInternal(nsIURI *aHostURI,
|
|||||||
|
|
||||||
// add the cookie to the list. AddInternal() takes care of logging.
|
// add the cookie to the list. AddInternal() takes care of logging.
|
||||||
// we get the current time again here, since it may have changed during prompting
|
// we get the current time again here, since it may have changed during prompting
|
||||||
AddInternal(aBaseDomain, cookie, PR_Now(), aHostURI, savedCookieHeader.get(),
|
AddInternal(aKey, cookie, PR_Now(), aHostURI, savedCookieHeader.get(),
|
||||||
aFromHttp);
|
aFromHttp);
|
||||||
return newCookie;
|
return newCookie;
|
||||||
}
|
}
|
||||||
@@ -2597,7 +2708,7 @@ nsCookieService::SetCookieInternal(nsIURI *aHostURI,
|
|||||||
// and deletes a cookie (if maximum number of cookies has been
|
// and deletes a cookie (if maximum number of cookies has been
|
||||||
// reached). also performs list maintenance by removing expired cookies.
|
// reached). also performs list maintenance by removing expired cookies.
|
||||||
void
|
void
|
||||||
nsCookieService::AddInternal(const nsCString &aBaseDomain,
|
nsCookieService::AddInternal(const nsCookieKey &aKey,
|
||||||
nsCookie *aCookie,
|
nsCookie *aCookie,
|
||||||
int64_t aCurrentTimeInUsec,
|
int64_t aCurrentTimeInUsec,
|
||||||
nsIURI *aHostURI,
|
nsIURI *aHostURI,
|
||||||
@@ -2614,7 +2725,7 @@ nsCookieService::AddInternal(const nsCString &aBaseDomain,
|
|||||||
}
|
}
|
||||||
|
|
||||||
nsListIter matchIter;
|
nsListIter matchIter;
|
||||||
bool foundCookie = FindCookie(aBaseDomain, aCookie->Host(),
|
bool foundCookie = FindCookie(aKey, aCookie->Host(),
|
||||||
aCookie->Name(), aCookie->Path(), matchIter);
|
aCookie->Name(), aCookie->Path(), matchIter);
|
||||||
|
|
||||||
nsRefPtr<nsCookie> oldCookie;
|
nsRefPtr<nsCookie> oldCookie;
|
||||||
@@ -2679,7 +2790,7 @@ nsCookieService::AddInternal(const nsCString &aBaseDomain,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// check if we have to delete an old cookie.
|
// check if we have to delete an old cookie.
|
||||||
nsCookieEntry *entry = mDBState->hostTable.GetEntry(aBaseDomain);
|
nsCookieEntry *entry = mDBState->hostTable.GetEntry(aKey);
|
||||||
if (entry && entry->GetCookies().Length() >= mMaxCookiesPerHost) {
|
if (entry && entry->GetCookies().Length() >= mMaxCookiesPerHost) {
|
||||||
nsListIter iter;
|
nsListIter iter;
|
||||||
FindStaleCookie(entry, currentTime, iter);
|
FindStaleCookie(entry, currentTime, iter);
|
||||||
@@ -2707,7 +2818,7 @@ nsCookieService::AddInternal(const nsCString &aBaseDomain,
|
|||||||
|
|
||||||
// Add the cookie to the db. We do not supply a params array for batching
|
// 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.
|
// because this might result in removals and additions being out of order.
|
||||||
AddCookieToList(aBaseDomain, aCookie, mDBState, NULL);
|
AddCookieToList(aKey, aCookie, mDBState, NULL);
|
||||||
COOKIE_LOGSUCCESS(SET_COOKIE, aHostURI, aCookieHeader, aCookie, foundCookie);
|
COOKIE_LOGSUCCESS(SET_COOKIE, aHostURI, aCookieHeader, aCookie, foundCookie);
|
||||||
|
|
||||||
// Now that list mutations are complete, notify observers. We do it here
|
// Now that list mutations are complete, notify observers. We do it here
|
||||||
@@ -3053,7 +3164,6 @@ static inline bool IsSubdomainOf(const nsCString &a, const nsCString &b)
|
|||||||
CookieStatus
|
CookieStatus
|
||||||
nsCookieService::CheckPrefs(nsIURI *aHostURI,
|
nsCookieService::CheckPrefs(nsIURI *aHostURI,
|
||||||
bool aIsForeign,
|
bool aIsForeign,
|
||||||
const nsCString &aBaseDomain,
|
|
||||||
bool aRequireHostMatch,
|
bool aRequireHostMatch,
|
||||||
const char *aCookieHeader)
|
const char *aCookieHeader)
|
||||||
{
|
{
|
||||||
@@ -3511,7 +3621,7 @@ nsCookieService::CookieExists(nsICookie2 *aCookie,
|
|||||||
NS_ENSURE_SUCCESS(rv, rv);
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
||||||
nsListIter iter;
|
nsListIter iter;
|
||||||
*aFoundCookie = FindCookie(baseDomain, host, name, path, iter);
|
*aFoundCookie = FindCookie(DEFAULT_APP_KEY(baseDomain), host, name, path, iter);
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3565,10 +3675,11 @@ nsCookieService::CountCookiesFromHost(const nsACString &aHost,
|
|||||||
rv = GetBaseDomainFromHost(host, baseDomain);
|
rv = GetBaseDomainFromHost(host, baseDomain);
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
||||||
EnsureReadDomain(baseDomain);
|
nsCookieKey key = DEFAULT_APP_KEY(baseDomain);
|
||||||
|
EnsureReadDomain(key);
|
||||||
|
|
||||||
// Return a count of all cookies, including expired.
|
// Return a count of all cookies, including expired.
|
||||||
nsCookieEntry *entry = mDBState->hostTable.GetEntry(baseDomain);
|
nsCookieEntry *entry = mDBState->hostTable.GetEntry(key);
|
||||||
*aCountFromHost = entry ? entry->GetCookies().Length() : 0;
|
*aCountFromHost = entry ? entry->GetCookies().Length() : 0;
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
@@ -3593,9 +3704,10 @@ nsCookieService::GetCookiesFromHost(const nsACString &aHost,
|
|||||||
rv = GetBaseDomainFromHost(host, baseDomain);
|
rv = GetBaseDomainFromHost(host, baseDomain);
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
||||||
EnsureReadDomain(baseDomain);
|
nsCookieKey key = DEFAULT_APP_KEY(baseDomain);
|
||||||
|
EnsureReadDomain(key);
|
||||||
|
|
||||||
nsCookieEntry *entry = mDBState->hostTable.GetEntry(baseDomain);
|
nsCookieEntry *entry = mDBState->hostTable.GetEntry(key);
|
||||||
if (!entry)
|
if (!entry)
|
||||||
return NS_NewEmptyEnumerator(aEnumerator);
|
return NS_NewEmptyEnumerator(aEnumerator);
|
||||||
|
|
||||||
@@ -3610,15 +3722,15 @@ nsCookieService::GetCookiesFromHost(const nsACString &aHost,
|
|||||||
|
|
||||||
// find an exact cookie specified by host, name, and path that hasn't expired.
|
// find an exact cookie specified by host, name, and path that hasn't expired.
|
||||||
bool
|
bool
|
||||||
nsCookieService::FindCookie(const nsCString &aBaseDomain,
|
nsCookieService::FindCookie(const nsCookieKey &aKey,
|
||||||
const nsAFlatCString &aHost,
|
const nsAFlatCString &aHost,
|
||||||
const nsAFlatCString &aName,
|
const nsAFlatCString &aName,
|
||||||
const nsAFlatCString &aPath,
|
const nsAFlatCString &aPath,
|
||||||
nsListIter &aIter)
|
nsListIter &aIter)
|
||||||
{
|
{
|
||||||
EnsureReadDomain(aBaseDomain);
|
EnsureReadDomain(aKey);
|
||||||
|
|
||||||
nsCookieEntry *entry = mDBState->hostTable.GetEntry(aBaseDomain);
|
nsCookieEntry *entry = mDBState->hostTable.GetEntry(aKey);
|
||||||
if (!entry)
|
if (!entry)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
@@ -3697,7 +3809,7 @@ nsCookieService::RemoveCookieFromList(const nsListIter &aIter,
|
|||||||
|
|
||||||
void
|
void
|
||||||
bindCookieParameters(mozIStorageBindingParamsArray *aParamsArray,
|
bindCookieParameters(mozIStorageBindingParamsArray *aParamsArray,
|
||||||
const nsCString &aBaseDomain,
|
const nsCookieKey &aKey,
|
||||||
const nsCookie *aCookie)
|
const nsCookie *aCookie)
|
||||||
{
|
{
|
||||||
NS_ASSERTION(aParamsArray, "Null params array passed to bindCookieParameters!");
|
NS_ASSERTION(aParamsArray, "Null params array passed to bindCookieParameters!");
|
||||||
@@ -3712,7 +3824,15 @@ bindCookieParameters(mozIStorageBindingParamsArray *aParamsArray,
|
|||||||
|
|
||||||
// Bind our values to params
|
// Bind our values to params
|
||||||
rv = params->BindUTF8StringByName(NS_LITERAL_CSTRING("baseDomain"),
|
rv = params->BindUTF8StringByName(NS_LITERAL_CSTRING("baseDomain"),
|
||||||
aBaseDomain);
|
aKey.mBaseDomain);
|
||||||
|
NS_ASSERT_SUCCESS(rv);
|
||||||
|
|
||||||
|
rv = params->BindInt32ByName(NS_LITERAL_CSTRING("appId"),
|
||||||
|
aKey.mAppId);
|
||||||
|
NS_ASSERT_SUCCESS(rv);
|
||||||
|
|
||||||
|
rv = params->BindInt32ByName(NS_LITERAL_CSTRING("inBrowserElement"),
|
||||||
|
aKey.mInBrowserElement ? 1 : 0);
|
||||||
NS_ASSERT_SUCCESS(rv);
|
NS_ASSERT_SUCCESS(rv);
|
||||||
|
|
||||||
rv = params->BindUTF8StringByName(NS_LITERAL_CSTRING("name"),
|
rv = params->BindUTF8StringByName(NS_LITERAL_CSTRING("name"),
|
||||||
@@ -3757,7 +3877,7 @@ bindCookieParameters(mozIStorageBindingParamsArray *aParamsArray,
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
nsCookieService::AddCookieToList(const nsCString &aBaseDomain,
|
nsCookieService::AddCookieToList(const nsCookieKey &aKey,
|
||||||
nsCookie *aCookie,
|
nsCookie *aCookie,
|
||||||
DBState *aDBState,
|
DBState *aDBState,
|
||||||
mozIStorageBindingParamsArray *aParamsArray,
|
mozIStorageBindingParamsArray *aParamsArray,
|
||||||
@@ -3768,7 +3888,7 @@ nsCookieService::AddCookieToList(const nsCString &aBaseDomain,
|
|||||||
NS_ASSERTION(!(!aDBState->dbConn && aParamsArray),
|
NS_ASSERTION(!(!aDBState->dbConn && aParamsArray),
|
||||||
"Do not have a DB connection but have a params array?");
|
"Do not have a DB connection but have a params array?");
|
||||||
|
|
||||||
nsCookieEntry *entry = aDBState->hostTable.PutEntry(aBaseDomain);
|
nsCookieEntry *entry = aDBState->hostTable.PutEntry(aKey);
|
||||||
NS_ASSERTION(entry, "can't insert element into a null entry!");
|
NS_ASSERTION(entry, "can't insert element into a null entry!");
|
||||||
|
|
||||||
entry->GetCookies().AppendElement(aCookie);
|
entry->GetCookies().AppendElement(aCookie);
|
||||||
@@ -3785,7 +3905,7 @@ nsCookieService::AddCookieToList(const nsCString &aBaseDomain,
|
|||||||
if (!paramsArray) {
|
if (!paramsArray) {
|
||||||
stmt->NewBindingParamsArray(getter_AddRefs(paramsArray));
|
stmt->NewBindingParamsArray(getter_AddRefs(paramsArray));
|
||||||
}
|
}
|
||||||
bindCookieParameters(paramsArray, aBaseDomain, aCookie);
|
bindCookieParameters(paramsArray, aKey, aCookie);
|
||||||
|
|
||||||
// If we were supplied an array to store parameters, we shouldn't call
|
// If we were supplied an array to store parameters, we shouldn't call
|
||||||
// executeAsync - someone up the stack will do this for us.
|
// executeAsync - someone up the stack will do this for us.
|
||||||
|
|||||||
@@ -47,41 +47,42 @@ class CookieServiceParent;
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// hash entry class
|
// hash key class
|
||||||
class nsCookieEntry : public PLDHashEntryHdr
|
class nsCookieKey : public PLDHashEntryHdr
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
// Hash methods
|
typedef const nsCookieKey& KeyType;
|
||||||
typedef const nsCString& KeyType;
|
typedef const nsCookieKey* KeyTypePointer;
|
||||||
typedef const nsCString* KeyTypePointer;
|
|
||||||
typedef nsTArray< nsRefPtr<nsCookie> > ArrayType;
|
|
||||||
typedef ArrayType::index_type IndexType;
|
|
||||||
|
|
||||||
explicit
|
nsCookieKey()
|
||||||
nsCookieEntry(KeyTypePointer aBaseDomain)
|
{}
|
||||||
: mBaseDomain(*aBaseDomain)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
nsCookieEntry(const nsCookieEntry& toCopy)
|
nsCookieKey(const nsCString &baseDomain, uint32_t appId, bool inBrowser)
|
||||||
{
|
: mBaseDomain(baseDomain)
|
||||||
// if we end up here, things will break. nsTHashtable shouldn't
|
, mAppId(appId)
|
||||||
// allow this, since we set ALLOW_MEMMOVE to true.
|
, mInBrowserElement(inBrowser)
|
||||||
NS_NOTREACHED("nsCookieEntry copy constructor is forbidden!");
|
{}
|
||||||
}
|
|
||||||
|
|
||||||
~nsCookieEntry()
|
nsCookieKey(const KeyTypePointer other)
|
||||||
{
|
: mBaseDomain(other->mBaseDomain)
|
||||||
}
|
, mAppId(other->mAppId)
|
||||||
|
, mInBrowserElement(other->mInBrowserElement)
|
||||||
|
{}
|
||||||
|
|
||||||
KeyType GetKey() const
|
nsCookieKey(const KeyType &other)
|
||||||
{
|
: mBaseDomain(other.mBaseDomain)
|
||||||
return mBaseDomain;
|
, mAppId(other.mAppId)
|
||||||
}
|
, mInBrowserElement(other.mInBrowserElement)
|
||||||
|
{}
|
||||||
|
|
||||||
bool KeyEquals(KeyTypePointer aKey) const
|
~nsCookieKey()
|
||||||
|
{}
|
||||||
|
|
||||||
|
bool KeyEquals(KeyTypePointer other) const
|
||||||
{
|
{
|
||||||
return mBaseDomain == *aKey;
|
return mBaseDomain == other->mBaseDomain &&
|
||||||
|
mAppId == other->mAppId &&
|
||||||
|
mInBrowserElement == other->mInBrowserElement;
|
||||||
}
|
}
|
||||||
|
|
||||||
static KeyTypePointer KeyToPointer(KeyType aKey)
|
static KeyTypePointer KeyToPointer(KeyType aKey)
|
||||||
@@ -91,22 +92,55 @@ class nsCookieEntry : public PLDHashEntryHdr
|
|||||||
|
|
||||||
static PLDHashNumber HashKey(KeyTypePointer aKey)
|
static PLDHashNumber HashKey(KeyTypePointer aKey)
|
||||||
{
|
{
|
||||||
return mozilla::HashString(*aKey);
|
// TODO: more efficient way to generate hash?
|
||||||
|
nsAutoCString temp(aKey->mBaseDomain);
|
||||||
|
temp.Append("#");
|
||||||
|
temp.Append(aKey->mAppId);
|
||||||
|
temp.Append("#");
|
||||||
|
temp.Append(aKey->mInBrowserElement ? 1 : 0);
|
||||||
|
return mozilla::HashString(temp);
|
||||||
}
|
}
|
||||||
|
|
||||||
enum { ALLOW_MEMMOVE = true };
|
enum { ALLOW_MEMMOVE = true };
|
||||||
|
|
||||||
|
nsCString mBaseDomain;
|
||||||
|
uint32_t mAppId;
|
||||||
|
bool mInBrowserElement;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Inherit from nsCookieKey so this can be stored in nsTHashTable
|
||||||
|
// TODO: why aren't we using nsClassHashTable<nsCookieKey, ArrayType>?
|
||||||
|
class nsCookieEntry : public nsCookieKey
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
// Hash methods
|
||||||
|
typedef nsTArray< nsRefPtr<nsCookie> > ArrayType;
|
||||||
|
typedef ArrayType::index_type IndexType;
|
||||||
|
|
||||||
|
nsCookieEntry(KeyTypePointer aKey)
|
||||||
|
: nsCookieKey(aKey)
|
||||||
|
{}
|
||||||
|
|
||||||
|
nsCookieEntry(const nsCookieEntry& toCopy)
|
||||||
|
{
|
||||||
|
// if we end up here, things will break. nsTHashtable shouldn't
|
||||||
|
// allow this, since we set ALLOW_MEMMOVE to true.
|
||||||
|
NS_NOTREACHED("nsCookieEntry copy constructor is forbidden!");
|
||||||
|
}
|
||||||
|
|
||||||
|
~nsCookieEntry()
|
||||||
|
{}
|
||||||
|
|
||||||
inline ArrayType& GetCookies() { return mCookies; }
|
inline ArrayType& GetCookies() { return mCookies; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
nsCString mBaseDomain;
|
|
||||||
ArrayType mCookies;
|
ArrayType mCookies;
|
||||||
};
|
};
|
||||||
|
|
||||||
// encapsulates a (baseDomain, nsCookie) tuple for temporary storage purposes.
|
// encapsulates a (key, nsCookie) tuple for temporary storage purposes.
|
||||||
struct CookieDomainTuple
|
struct CookieDomainTuple
|
||||||
{
|
{
|
||||||
nsCString baseDomain;
|
nsCookieKey key;
|
||||||
nsRefPtr<nsCookie> cookie;
|
nsRefPtr<nsCookie> cookie;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -152,7 +186,7 @@ struct DBState
|
|||||||
// A hashset of baseDomains read in synchronously, while the async read is
|
// 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
|
// in flight. This is used to keep track of which data in hostArray is stale
|
||||||
// when the time comes to merge.
|
// when the time comes to merge.
|
||||||
nsTHashtable<nsCStringHashKey> readSet;
|
nsTHashtable<nsCookieKey> readSet;
|
||||||
|
|
||||||
// DB completion handlers.
|
// DB completion handlers.
|
||||||
nsCOMPtr<mozIStorageStatementCallback> insertListener;
|
nsCOMPtr<mozIStorageStatementCallback> insertListener;
|
||||||
@@ -219,29 +253,30 @@ class nsCookieService : public nsICookieService
|
|||||||
template<class T> nsCookie* GetCookieFromRow(T &aRow);
|
template<class T> nsCookie* GetCookieFromRow(T &aRow);
|
||||||
void AsyncReadComplete();
|
void AsyncReadComplete();
|
||||||
void CancelAsyncRead(bool aPurgeReadSet);
|
void CancelAsyncRead(bool aPurgeReadSet);
|
||||||
void EnsureReadDomain(const nsCString &aBaseDomain);
|
void EnsureReadDomain(const nsCookieKey &aKey);
|
||||||
void EnsureReadComplete();
|
void EnsureReadComplete();
|
||||||
nsresult NormalizeHost(nsCString &aHost);
|
nsresult NormalizeHost(nsCString &aHost);
|
||||||
nsresult GetBaseDomain(nsIURI *aHostURI, nsCString &aBaseDomain, bool &aRequireHostMatch);
|
nsresult GetBaseDomain(nsIURI *aHostURI, nsCString &aBaseDomain, bool &aRequireHostMatch);
|
||||||
nsresult GetBaseDomainFromHost(const nsACString &aHost, nsCString &aBaseDomain);
|
nsresult GetBaseDomainFromHost(const nsACString &aHost, nsCString &aBaseDomain);
|
||||||
nsresult GetCookieStringCommon(nsIURI *aHostURI, nsIChannel *aChannel, bool aHttpBound, char** aCookie);
|
nsresult GetCookieStringCommon(nsIURI *aHostURI, nsIChannel *aChannel, bool aHttpBound, char** aCookie);
|
||||||
void GetCookieStringInternal(nsIURI *aHostURI, bool aIsForeign, bool aHttpBound, nsCString &aCookie);
|
void GetCookieStringInternal(nsIURI *aHostURI, bool aIsForeign, bool aHttpBound, uint32_t aAppId, bool aInBrowserElement, nsCString &aCookie);
|
||||||
nsresult SetCookieStringCommon(nsIURI *aHostURI, const char *aCookieHeader, const char *aServerTime, nsIChannel *aChannel, bool aFromHttp);
|
nsresult SetCookieStringCommon(nsIURI *aHostURI, const char *aCookieHeader, const char *aServerTime, nsIChannel *aChannel, bool aFromHttp);
|
||||||
void SetCookieStringInternal(nsIURI *aHostURI, bool aIsForeign, nsDependentCString &aCookieHeader, const nsCString &aServerTime, bool aFromHttp);
|
void SetCookieStringInternal(nsIURI *aHostURI, bool aIsForeign, nsDependentCString &aCookieHeader, const nsCString &aServerTime, bool aFromHttp, uint32_t aAppId, bool aInBrowserElement);
|
||||||
bool SetCookieInternal(nsIURI *aHostURI, const nsCString& aBaseDomain, bool aRequireHostMatch, CookieStatus aStatus, nsDependentCString &aCookieHeader, int64_t aServerTime, bool aFromHttp);
|
bool SetCookieInternal(nsIURI *aHostURI, const nsCookieKey& aKey, bool aRequireHostMatch, CookieStatus aStatus, nsDependentCString &aCookieHeader, int64_t aServerTime, bool aFromHttp);
|
||||||
void AddInternal(const nsCString& aBaseDomain, nsCookie *aCookie, int64_t aCurrentTimeInUsec, nsIURI *aHostURI, const char *aCookieHeader, bool aFromHttp);
|
void AddInternal(const nsCookieKey& aKey, nsCookie *aCookie, int64_t aCurrentTimeInUsec, nsIURI *aHostURI, const char *aCookieHeader, bool aFromHttp);
|
||||||
void RemoveCookieFromList(const nsListIter &aIter, mozIStorageBindingParamsArray *aParamsArray = NULL);
|
void RemoveCookieFromList(const nsListIter &aIter, mozIStorageBindingParamsArray *aParamsArray = NULL);
|
||||||
void AddCookieToList(const nsCString& aBaseDomain, nsCookie *aCookie, DBState *aDBState, mozIStorageBindingParamsArray *aParamsArray, bool aWriteToDB = true);
|
void AddCookieToList(const nsCookieKey& aKey, nsCookie *aCookie, DBState *aDBState, mozIStorageBindingParamsArray *aParamsArray, bool aWriteToDB = true);
|
||||||
void UpdateCookieInList(nsCookie *aCookie, int64_t aLastAccessed, mozIStorageBindingParamsArray *aParamsArray);
|
void UpdateCookieInList(nsCookie *aCookie, int64_t aLastAccessed, mozIStorageBindingParamsArray *aParamsArray);
|
||||||
static bool GetTokenValue(nsASingleFragmentCString::const_char_iterator &aIter, nsASingleFragmentCString::const_char_iterator &aEndIter, nsDependentCSubstring &aTokenString, nsDependentCSubstring &aTokenValue, bool &aEqualsFound);
|
static bool GetTokenValue(nsASingleFragmentCString::const_char_iterator &aIter, nsASingleFragmentCString::const_char_iterator &aEndIter, nsDependentCSubstring &aTokenString, nsDependentCSubstring &aTokenValue, bool &aEqualsFound);
|
||||||
static bool ParseAttributes(nsDependentCString &aCookieHeader, nsCookieAttributes &aCookie);
|
static bool ParseAttributes(nsDependentCString &aCookieHeader, nsCookieAttributes &aCookie);
|
||||||
CookieStatus CheckPrefs(nsIURI *aHostURI, bool aIsForeign, const nsCString &aBaseDomain, bool aRequireHostMatch, const char *aCookieHeader);
|
bool RequireThirdPartyCheck();
|
||||||
|
CookieStatus CheckPrefs(nsIURI *aHostURI, bool aIsForeign, bool aRequireHostMatch, const char *aCookieHeader);
|
||||||
bool CheckDomain(nsCookieAttributes &aCookie, nsIURI *aHostURI, const nsCString &aBaseDomain, bool aRequireHostMatch);
|
bool CheckDomain(nsCookieAttributes &aCookie, nsIURI *aHostURI, const nsCString &aBaseDomain, bool aRequireHostMatch);
|
||||||
static bool CheckPath(nsCookieAttributes &aCookie, nsIURI *aHostURI);
|
static bool CheckPath(nsCookieAttributes &aCookie, nsIURI *aHostURI);
|
||||||
static bool GetExpiry(nsCookieAttributes &aCookie, int64_t aServerTime, int64_t aCurrentTime);
|
static bool GetExpiry(nsCookieAttributes &aCookie, int64_t aServerTime, int64_t aCurrentTime);
|
||||||
void RemoveAllFromMemory();
|
void RemoveAllFromMemory();
|
||||||
already_AddRefed<nsIArray> PurgeCookies(int64_t aCurrentTimeInUsec);
|
already_AddRefed<nsIArray> PurgeCookies(int64_t aCurrentTimeInUsec);
|
||||||
bool FindCookie(const nsCString& aBaseDomain, const nsAFlatCString &aHost, const nsAFlatCString &aName, const nsAFlatCString &aPath, nsListIter &aIter);
|
bool FindCookie(const nsCookieKey& aKey, const nsAFlatCString &aHost, const nsAFlatCString &aName, const nsAFlatCString &aPath, nsListIter &aIter);
|
||||||
static void FindStaleCookie(nsCookieEntry *aEntry, int64_t aCurrentTime, nsListIter &aIter);
|
static void FindStaleCookie(nsCookieEntry *aEntry, int64_t aCurrentTime, nsListIter &aIter);
|
||||||
void NotifyRejected(nsIURI *aHostURI);
|
void NotifyRejected(nsIURI *aHostURI);
|
||||||
void NotifyChanged(nsISupports *aSubject, const PRUnichar *aData);
|
void NotifyChanged(nsISupports *aSubject, const PRUnichar *aData);
|
||||||
|
|||||||
@@ -184,3 +184,37 @@ ChannelEventSink.prototype = {
|
|||||||
callback.onRedirectVerifyCallback(Cr.NS_OK);
|
callback.onRedirectVerifyCallback(Cr.NS_OK);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class that implements nsILoadContext. Use it as callbacks for channel when
|
||||||
|
* test needs it.
|
||||||
|
*/
|
||||||
|
function LoadContextCallback(appId, inBrowserElement, isPrivate, isContent) {
|
||||||
|
this.appId = appId;
|
||||||
|
this.isInBrowserElement = inBrowserElement;
|
||||||
|
this.usePrivateBrowsing = isPrivate;
|
||||||
|
this.isContent = isContent;
|
||||||
|
}
|
||||||
|
|
||||||
|
LoadContextCallback.prototype = {
|
||||||
|
associatedWindow: null,
|
||||||
|
topWindow : null,
|
||||||
|
isAppOfType: function(appType) {
|
||||||
|
throw Cr.NS_ERROR_NOT_IMPLEMENTED;
|
||||||
|
},
|
||||||
|
QueryInterface: function(iid) {
|
||||||
|
if (iid == Ci.nsILoadContext ||
|
||||||
|
Ci.nsIInterfaceRequestor ||
|
||||||
|
Ci.nsISupports) {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
throw Cr.NS_ERROR_NO_INTERFACE;
|
||||||
|
},
|
||||||
|
getInterface: function(iid) {
|
||||||
|
if (iid.equals(Ci.nsILoadContext))
|
||||||
|
return this;
|
||||||
|
throw Cr.NS_ERROR_NO_INTERFACE;
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
139
netwerk/test/unit/test_cookiejars.js
Normal file
139
netwerk/test/unit/test_cookiejars.js
Normal file
@@ -0,0 +1,139 @@
|
|||||||
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Test that channels with different
|
||||||
|
* AppIds/inBrowserElements/usePrivateBrowsing (from nsILoadContext callback)
|
||||||
|
* are stored in separate namespaces ("cookie jars")
|
||||||
|
*/
|
||||||
|
|
||||||
|
const Cc = Components.classes;
|
||||||
|
const Ci = Components.interfaces;
|
||||||
|
const Cu = Components.utils;
|
||||||
|
const Cr = Components.results;
|
||||||
|
|
||||||
|
Cu.import("resource://testing-common/httpd.js");
|
||||||
|
var httpserver = new HttpServer();
|
||||||
|
|
||||||
|
var cookieSetPath = "/setcookie";
|
||||||
|
var cookieCheckPath = "/checkcookie";
|
||||||
|
|
||||||
|
// Test array:
|
||||||
|
// - element 0: name for cookie, used both to set and later to check
|
||||||
|
// - element 1: loadContext (determines cookie namespace)
|
||||||
|
//
|
||||||
|
// TODO: bug 722850: make private browsing work per-app, and add tests. For now
|
||||||
|
// all values are 'false' for PB.
|
||||||
|
|
||||||
|
var tests = [
|
||||||
|
{ cookieName: 'LCC_App0_BrowF_PrivF',
|
||||||
|
loadContext: new LoadContextCallback(0, false, false, 1) },
|
||||||
|
{ cookieName: 'LCC_App0_BrowT_PrivF',
|
||||||
|
loadContext: new LoadContextCallback(0, true, false, 1) },
|
||||||
|
{ cookieName: 'LCC_App1_BrowF_PrivF',
|
||||||
|
loadContext: new LoadContextCallback(1, false, false, 1) },
|
||||||
|
{ cookieName: 'LCC_App1_BrowT_PrivF',
|
||||||
|
loadContext: new LoadContextCallback(1, true, false, 1) },
|
||||||
|
];
|
||||||
|
|
||||||
|
// test number: index into 'tests' array
|
||||||
|
var i = 0;
|
||||||
|
|
||||||
|
function setupChannel(path)
|
||||||
|
{
|
||||||
|
var ios = Cc["@mozilla.org/network/io-service;1"].getService(Ci.nsIIOService);
|
||||||
|
var chan = ios.newChannel("http://localhost:4444" + path, "", null);
|
||||||
|
chan.notificationCallbacks = tests[i].loadContext;
|
||||||
|
chan.QueryInterface(Ci.nsIHttpChannel);
|
||||||
|
return chan;
|
||||||
|
}
|
||||||
|
|
||||||
|
function setCookie() {
|
||||||
|
var channel = setupChannel(cookieSetPath);
|
||||||
|
channel.setRequestHeader("foo-set-cookie", tests[i].cookieName, false);
|
||||||
|
channel.asyncOpen(new ChannelListener(setNextCookie, null), null);
|
||||||
|
}
|
||||||
|
|
||||||
|
function setNextCookie(request, data, context)
|
||||||
|
{
|
||||||
|
if (++i == tests.length) {
|
||||||
|
// all cookies set: switch to checking them
|
||||||
|
i = 0;
|
||||||
|
checkCookie();
|
||||||
|
} else {
|
||||||
|
do_print("setNextCookie:i=" + i);
|
||||||
|
setCookie();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Open channel that should send one and only one correct Cookie: header to
|
||||||
|
// server, corresponding to it's namespace
|
||||||
|
function checkCookie()
|
||||||
|
{
|
||||||
|
var channel = setupChannel(cookieCheckPath);
|
||||||
|
channel.asyncOpen(new ChannelListener(completeCheckCookie, null), null);
|
||||||
|
}
|
||||||
|
|
||||||
|
function completeCheckCookie(request, data, context) {
|
||||||
|
// Look for all cookies in what the server saw: fail if we see any besides the
|
||||||
|
// one expected cookie for each namespace;
|
||||||
|
var expectedCookie = tests[i].cookieName;
|
||||||
|
request.QueryInterface(Ci.nsIHttpChannel);
|
||||||
|
var cookiesSeen = request.getResponseHeader("foo-saw-cookies");
|
||||||
|
|
||||||
|
var j;
|
||||||
|
for (j = 0; j < tests.length; j++) {
|
||||||
|
var cookieToCheck = tests[j].cookieName;
|
||||||
|
found = (cookiesSeen.indexOf(cookieToCheck) != -1);
|
||||||
|
if (found && expectedCookie != cookieToCheck) {
|
||||||
|
do_throw("test index " + i + ": found unexpected cookie '"
|
||||||
|
+ cookieToCheck + "': in '" + cookiesSeen + "'");
|
||||||
|
} else if (!found && expectedCookie == cookieToCheck) {
|
||||||
|
do_throw("test index " + i + ": missing expected cookie '"
|
||||||
|
+ expectedCookie + "': in '" + cookiesSeen + "'");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// If we get here we're good.
|
||||||
|
do_print("Saw only correct cookie '" + expectedCookie + "'");
|
||||||
|
do_check_true(true);
|
||||||
|
|
||||||
|
|
||||||
|
if (++i == tests.length) {
|
||||||
|
// end of tests
|
||||||
|
httpserver.stop(do_test_finished);
|
||||||
|
} else {
|
||||||
|
checkCookie();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function run_test()
|
||||||
|
{
|
||||||
|
httpserver.registerPathHandler(cookieSetPath, cookieSetHandler);
|
||||||
|
httpserver.registerPathHandler(cookieCheckPath, cookieCheckHandler);
|
||||||
|
httpserver.start(4444);
|
||||||
|
|
||||||
|
setCookie();
|
||||||
|
do_test_pending();
|
||||||
|
}
|
||||||
|
|
||||||
|
function cookieSetHandler(metadata, response)
|
||||||
|
{
|
||||||
|
var cookieName = metadata.getHeader("foo-set-cookie");
|
||||||
|
|
||||||
|
response.setStatusLine(metadata.httpVersion, 200, "Ok");
|
||||||
|
response.setHeader("Set-Cookie", cookieName + "=1; Path=/", false);
|
||||||
|
response.setHeader("Content-Type", "text/plain");
|
||||||
|
response.bodyOutputStream.write("Ok", "Ok".length);
|
||||||
|
}
|
||||||
|
|
||||||
|
function cookieCheckHandler(metadata, response)
|
||||||
|
{
|
||||||
|
var cookies = metadata.getHeader("Cookie");
|
||||||
|
|
||||||
|
response.setStatusLine(metadata.httpVersion, 200, "Ok");
|
||||||
|
response.setHeader("foo-saw-cookies", cookies, false);
|
||||||
|
response.setHeader("Content-Type", "text/plain");
|
||||||
|
response.bodyOutputStream.write("Ok", "Ok".length);
|
||||||
|
}
|
||||||
|
|
||||||
@@ -95,6 +95,7 @@ fail-if = os == "android"
|
|||||||
[test_content_encoding_gzip.js]
|
[test_content_encoding_gzip.js]
|
||||||
[test_content_sniffer.js]
|
[test_content_sniffer.js]
|
||||||
[test_cookie_header.js]
|
[test_cookie_header.js]
|
||||||
|
[test_cookiejars.js]
|
||||||
[test_data_protocol.js]
|
[test_data_protocol.js]
|
||||||
[test_dns_service.js]
|
[test_dns_service.js]
|
||||||
[test_dns_localredirect.js]
|
[test_dns_localredirect.js]
|
||||||
|
|||||||
3
netwerk/test/unit_ipc/test_cookiejars_wrap.js
Normal file
3
netwerk/test/unit_ipc/test_cookiejars_wrap.js
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
function run_test() {
|
||||||
|
run_test_in_child("../unit/test_cookiejars.js");
|
||||||
|
}
|
||||||
@@ -4,7 +4,8 @@ tail =
|
|||||||
|
|
||||||
[test_cacheflags_wrap.js]
|
[test_cacheflags_wrap.js]
|
||||||
[test_channel_close_wrap.js]
|
[test_channel_close_wrap.js]
|
||||||
[test_cookie_wrap.js]
|
[test_cookie_header_wrap.js]
|
||||||
|
[test_cookiejars_wrap.js]
|
||||||
[test_duplicate_headers_wrap.js]
|
[test_duplicate_headers_wrap.js]
|
||||||
[test_event_sink_wrap.js]
|
[test_event_sink_wrap.js]
|
||||||
[test_head_wrap.js]
|
[test_head_wrap.js]
|
||||||
|
|||||||
Reference in New Issue
Block a user