Bug 1165267 - Part 1: Replace appId and inBrowser by originAttributes v2. r=honzab

This commit is contained in:
Ethan Tseng 2015-09-03 18:22:51 +08:00
parent 583b7001e7
commit bb095c04f4
6 changed files with 269 additions and 142 deletions

View File

@ -18,7 +18,7 @@
// c) Schema 3: the 'creationTime' column already exists; or the
// 'moz_uniqueid' index already exists.
var COOKIE_DATABASE_SCHEMA_CURRENT = 5;
var COOKIE_DATABASE_SCHEMA_CURRENT = 6;
var test_generator = do_run_test();

View File

@ -27,15 +27,13 @@ namespace {
// Ignore failures from this function, as they only affect whether we do or
// don't show a dialog box in private browsing mode if the user sets a pref.
void
CreateDummyChannel(nsIURI* aHostURI, uint32_t aAppId, bool aInMozBrowser,
bool aIsPrivate, nsIChannel **aChannel)
CreateDummyChannel(nsIURI* aHostURI, OriginAttributes &aAttrs, bool aIsPrivate,
nsIChannel **aChannel)
{
MOZ_ASSERT(aAppId != nsIScriptSecurityManager::UNKNOWN_APP_ID);
MOZ_ASSERT(aAttrs.mAppId != nsIScriptSecurityManager::UNKNOWN_APP_ID);
// TODO: Bug 1165267 - Use OriginAttributes for nsCookieService
OriginAttributes attrs(aAppId, aInMozBrowser);
nsCOMPtr<nsIPrincipal> principal =
BasePrincipal::CreateCodebasePrincipal(aHostURI, attrs);
BasePrincipal::CreateCodebasePrincipal(aHostURI, aAttrs);
if (!principal) {
return;
}
@ -66,28 +64,22 @@ namespace net {
MOZ_WARN_UNUSED_RESULT
bool
CookieServiceParent::GetAppInfoFromParams(const IPC::SerializedLoadContext &aLoadContext,
uint32_t& aAppId,
bool& aIsInBrowserElement,
CookieServiceParent::GetOriginAttributesFromParams(const IPC::SerializedLoadContext &aLoadContext,
OriginAttributes& aAttrs,
bool& aIsPrivate)
{
aAppId = NECKO_NO_APP_ID;
aIsInBrowserElement = false;
aIsPrivate = false;
OriginAttributes attrs;
const char* error = NeckoParent::GetValidatedAppInfo(aLoadContext,
Manager()->Manager(),
attrs);
aAttrs);
if (error) {
NS_WARNING(nsPrintfCString("CookieServiceParent: GetAppInfoFromParams: "
NS_WARNING(nsPrintfCString("CookieServiceParent: GetOriginAttributesFromParams: "
"FATAL error: %s: KILLING CHILD PROCESS\n",
error).get());
return false;
}
aAppId = attrs.mAppId;
aIsInBrowserElement = attrs.mInBrowser;
if (aLoadContext.IsPrivateBitValid()) {
aIsPrivate = aLoadContext.mUsePrivateBrowsing;
}
@ -133,16 +125,15 @@ CookieServiceParent::RecvGetCookieString(const URIParams& aHost,
if (!hostURI)
return false;
uint32_t appId;
bool isInBrowserElement, isPrivate;
bool valid = GetAppInfoFromParams(aLoadContext, appId,
isInBrowserElement, isPrivate);
OriginAttributes attrs;
bool isPrivate;
bool valid = GetOriginAttributesFromParams(aLoadContext, attrs, isPrivate);
if (!valid) {
return false;
}
mCookieService->GetCookieStringInternal(hostURI, aIsForeign, aFromHttp, appId,
isInBrowserElement, isPrivate, *aResult);
mCookieService->GetCookieStringInternal(hostURI, aIsForeign, aFromHttp, attrs,
isPrivate, *aResult);
return true;
}
@ -164,10 +155,9 @@ CookieServiceParent::RecvSetCookieString(const URIParams& aHost,
if (!hostURI)
return false;
uint32_t appId;
bool isInBrowserElement, isPrivate;
bool valid = GetAppInfoFromParams(aLoadContext, appId,
isInBrowserElement, isPrivate);
OriginAttributes attrs;
bool isPrivate;
bool valid = GetOriginAttributesFromParams(aLoadContext, attrs, isPrivate);
if (!valid) {
return false;
}
@ -180,14 +170,13 @@ CookieServiceParent::RecvSetCookieString(const URIParams& aHost,
// with aIsForeign before we have to worry about nsCookiePermission trying
// to use the channel to inspect it.
nsCOMPtr<nsIChannel> dummyChannel;
CreateDummyChannel(hostURI, appId, isInBrowserElement,
isPrivate, getter_AddRefs(dummyChannel));
CreateDummyChannel(hostURI, attrs, isPrivate, getter_AddRefs(dummyChannel));
// NB: dummyChannel could be null if something failed in CreateDummyChannel.
nsDependentCString cookieString(aCookieString, 0);
mCookieService->SetCookieStringInternal(hostURI, aIsForeign, cookieString,
aServerTime, aFromHttp, appId,
isInBrowserElement, isPrivate, dummyChannel);
aServerTime, aFromHttp, attrs,
isPrivate, dummyChannel);
return true;
}

View File

@ -10,6 +10,7 @@
#include "SerializedLoadContext.h"
class nsCookieService;
namespace mozilla { class OriginAttributes; }
namespace mozilla {
namespace net {
@ -22,9 +23,8 @@ public:
protected:
MOZ_WARN_UNUSED_RESULT bool
GetAppInfoFromParams(const IPC::SerializedLoadContext &aLoadContext,
uint32_t& aAppId,
bool& aIsInBrowserElement,
GetOriginAttributesFromParams(const IPC::SerializedLoadContext &aLoadContext,
OriginAttributes& aAttrs,
bool& aIsPrivate);
virtual void ActorDestroy(ActorDestroyReason aWhy) override;

View File

@ -60,7 +60,7 @@ using namespace mozilla::net;
// 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)
nsCookieKey(baseDomain, OriginAttributes())
/******************************************************************************
* nsCookieService impl:
@ -74,7 +74,7 @@ static nsCookieService *gCookieService;
#define HTTP_ONLY_PREFIX "#HttpOnly_"
#define COOKIES_FILE "cookies.sqlite"
#define COOKIES_SCHEMA_VERSION 5
#define COOKIES_SCHEMA_VERSION 6
// parameter indexes; see EnsureReadDomain, EnsureReadComplete and
// ReadCookieDBListener::HandleResult
@ -88,8 +88,7 @@ static nsCookieService *gCookieService;
#define IDX_SECURE 7
#define IDX_HTTPONLY 8
#define IDX_BASE_DOMAIN 9
#define IDX_APP_ID 10
#define IDX_BROWSER_ELEM 11
#define IDX_ORIGIN_ATTRIBUTES 10
static const int64_t kCookiePurgeAge =
int64_t(30 * 24 * 60 * 60) * PR_USEC_PER_SEC; // 30 days in microseconds
@ -493,8 +492,11 @@ public:
CookieDomainTuple *tuple = mDBState->hostArray.AppendElement();
row->GetUTF8String(IDX_BASE_DOMAIN, tuple->key.mBaseDomain);
tuple->key.mAppId = static_cast<uint32_t>(row->AsInt32(IDX_APP_ID));
tuple->key.mInBrowserElement = static_cast<bool>(row->AsInt32(IDX_BROWSER_ELEM));
nsAutoCString suffix;
row->GetUTF8String(IDX_ORIGIN_ATTRIBUTES, suffix);
tuple->key.mOriginAttributes.PopulateFromSuffix(suffix);
tuple->cookie = gCookieService->GetCookieFromRow(row);
}
@ -572,20 +574,21 @@ public:
// nsIObserver implementation.
NS_IMETHODIMP
Observe(nsISupports *aSubject, const char *aTopic, const char16_t *data) override
Observe(nsISupports *aSubject, const char *aTopic, const char16_t *aData) override
{
MOZ_ASSERT(!nsCRT::strcmp(aTopic, TOPIC_WEB_APP_CLEAR_DATA));
MOZ_ASSERT(!nsCRT::strcmp(aTopic, TOPIC_CLEAR_ORIGIN_DATA));
uint32_t appId = NECKO_UNKNOWN_APP_ID;
bool browserOnly = false;
nsresult rv = NS_GetAppInfoFromClearDataNotification(aSubject, &appId,
&browserOnly);
NS_ENSURE_SUCCESS(rv, rv);
MOZ_ASSERT(XRE_IsParentProcess());
OriginAttributes attrs;
MOZ_ALWAYS_TRUE(attrs.Init(nsDependentString(aData)));
nsCOMPtr<nsICookieManager2> cookieManager
= do_GetService(NS_COOKIEMANAGER_CONTRACTID);
MOZ_ASSERT(cookieManager);
return cookieManager->RemoveCookiesForApp(appId, browserOnly);
// TODO: We should add a new interface RemoveCookiesForOriginAttributes in
// nsICookieManager2 and use it instead of RemoveCookiesForApp.
return cookieManager->RemoveCookiesForApp(attrs.mAppId, attrs.mInBrowser);
}
};
@ -685,7 +688,7 @@ nsCookieService::AppClearDataObserverInit()
{
nsCOMPtr<nsIObserverService> observerService = services::GetObserverService();
nsCOMPtr<nsIObserver> obs = new AppClearDataObserver();
observerService->AddObserver(obs, TOPIC_WEB_APP_CLEAR_DATA,
observerService->AddObserver(obs, TOPIC_CLEAR_ORIGIN_DATA,
/* holdsWeak= */ false);
}
@ -810,6 +813,49 @@ nsCookieService::InitDBStates()
}
}
namespace {
class ConvertAppIdToOriginAttrsSQLFunction final : public mozIStorageFunction
{
~ConvertAppIdToOriginAttrsSQLFunction() {}
NS_DECL_ISUPPORTS
NS_DECL_MOZISTORAGEFUNCTION
};
NS_IMPL_ISUPPORTS(ConvertAppIdToOriginAttrsSQLFunction, mozIStorageFunction);
NS_IMETHODIMP
ConvertAppIdToOriginAttrsSQLFunction::OnFunctionCall(
mozIStorageValueArray* aFunctionArguments, nsIVariant** aResult)
{
nsresult rv;
int32_t appId, inBrowser;
rv = aFunctionArguments->GetInt32(0, &appId);
NS_ENSURE_SUCCESS(rv, rv);
rv = aFunctionArguments->GetInt32(1, &inBrowser);
NS_ENSURE_SUCCESS(rv, rv);
// Create an originAttributes object by appId and inBrowserElemnt.
// Then create the originSuffix string from this object.
OriginAttributes attrs(appId, (inBrowser ? 1 : 0));
nsAutoCString suffix;
attrs.CreateSuffix(suffix);
nsCOMPtr<nsIWritableVariant> outVar(do_CreateInstance(
NS_VARIANT_CONTRACTID, &rv));
NS_ENSURE_SUCCESS(rv, rv);
rv = outVar->SetAsAUTF8String(suffix);
NS_ENSURE_SUCCESS(rv, rv);
outVar.forget(aResult);
return NS_OK;
}
} // namespace
/* Attempt to open and read the database. If 'aRecreateDB' is true, try to
* move the existing database file out of the way and create a new one.
*
@ -1075,7 +1121,7 @@ nsCookieService::TryInitDB(bool aRecreateDB)
NS_ENSURE_SUCCESS(rv, RESULT_RETRY);
// Create new table (with new fields and new unique constraint)
rv = CreateTable();
rv = CreateTableForSchemaVersion5();
NS_ENSURE_SUCCESS(rv, RESULT_RETRY);
// Copy data from old table, using appId/inBrowser=0 for existing rows
@ -1096,6 +1142,67 @@ nsCookieService::TryInitDB(bool aRecreateDB)
COOKIE_LOGSTRING(LogLevel::Debug,
("Upgraded database to schema version 5"));
}
// Fall through to the next upgrade.
case 5:
{
// Change in the version: Replace the columns |appId| and
// |isBrowserElement| by a single column |originAttributes|.
//
// Why we made this change: FxOS new security model (NSec) encapsulates
// "appId/inBrowser" in nsIPrincipal::originAttributes to make it easier
// to modify the contents of this structure in the future.
//
// We do the migration in several steps:
// 1. Rename the old table.
// 2. Create a new table.
// 3. Copy data from the old table to the new table; convert appId and
// inBrowserElement to originAttributes in the meantime.
// 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 without the two deprecated columns appId and
// inBrowserElement.
nsCOMPtr<mozIStorageFunction>
convertToOriginAttrs(new ConvertAppIdToOriginAttrsSQLFunction());
NS_ENSURE_TRUE(convertToOriginAttrs, RESULT_RETRY);
rv = mDefaultDBState->dbConn->CreateFunction(
NS_LITERAL_CSTRING("CONVERT_TO_ORIGIN_ATTRIBUTES"), 2,
convertToOriginAttrs);
NS_ENSURE_SUCCESS(rv, RESULT_RETRY);
rv = mDefaultDBState->dbConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
"INSERT INTO moz_cookies "
"(baseDomain, originAttributes, name, value, host, path, expiry,"
" lastAccessed, creationTime, isSecure, isHttpOnly) "
"SELECT baseDomain, "
" CONVERT_TO_ORIGIN_ATTRIBUTES(appId, inBrowserElement),"
" 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(LogLevel::Debug,
("Upgraded database to schema version 6"));
}
// No more upgrades. Update the schema version.
rv = mDefaultDBState->dbConn->SetSchemaVersion(COOKIES_SCHEMA_VERSION);
@ -1132,8 +1239,7 @@ nsCookieService::TryInitDB(bool aRecreateDB)
"SELECT "
"id, "
"baseDomain, "
"appId, "
"inBrowserElement, "
"originAttributes, "
"name, "
"value, "
"host, "
@ -1174,8 +1280,7 @@ nsCookieService::TryInitDB(bool aRecreateDB)
rv = mDefaultDBState->dbConn->CreateAsyncStatement(NS_LITERAL_CSTRING(
"INSERT INTO moz_cookies ("
"baseDomain, "
"appId, "
"inBrowserElement, "
"originAttributes, "
"name, "
"value, "
"host, "
@ -1187,8 +1292,7 @@ nsCookieService::TryInitDB(bool aRecreateDB)
"isHttpOnly"
") VALUES ("
":baseDomain, "
":appId, "
":inBrowserElement, "
":originAttributes, "
":name, "
":value, "
":host, "
@ -1249,6 +1353,42 @@ nsCookieService::CreateTable()
COOKIES_SCHEMA_VERSION);
if (NS_FAILED(rv)) return rv;
// Create the table.
// We default originAttributes to empty string: this is so if users revert to
// an older Firefox version that doesn't know about this field, any cookies
// set will still work once they upgrade back.
rv = mDefaultDBState->dbConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
"CREATE TABLE moz_cookies ("
"id INTEGER PRIMARY KEY, "
"baseDomain TEXT, "
"originAttributes TEXT NOT NULL DEFAULT '', "
"name TEXT, "
"value TEXT, "
"host TEXT, "
"path TEXT, "
"expiry INTEGER, "
"lastAccessed INTEGER, "
"creationTime INTEGER, "
"isSecure INTEGER, "
"isHttpOnly INTEGER, "
"CONSTRAINT moz_uniqueid UNIQUE (name, host, path, originAttributes)"
")"));
if (NS_FAILED(rv)) return rv;
// Create an index on baseDomain.
return mDefaultDBState->dbConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
"CREATE INDEX moz_basedomain ON moz_cookies (baseDomain, "
"originAttributes)"));
}
// Sets the schema version and creates the moz_cookies table.
nsresult
nsCookieService::CreateTableForSchemaVersion5()
{
// Set the schema version, before creating the table.
nsresult rv = mDefaultDBState->dbConn->SetSchemaVersion(5);
if (NS_FAILED(rv)) return rv;
// 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.
@ -1603,18 +1743,17 @@ nsCookieService::GetCookieStringCommon(nsIURI *aHostURI,
bool isForeign = true;
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;
// Get originAttributes.
OriginAttributes attrs;
if (aChannel) {
NS_GetAppInfo(aChannel, &appId, &inBrowserElement);
NS_GetOriginAttributes(aChannel, attrs);
}
bool isPrivate = aChannel && NS_UsePrivateBrowsing(aChannel);
nsAutoCString result;
GetCookieStringInternal(aHostURI, isForeign, aHttpBound, appId,
inBrowserElement, isPrivate, result);
GetCookieStringInternal(aHostURI, isForeign, aHttpBound, attrs,
isPrivate, result);
*aCookie = result.IsEmpty() ? nullptr : ToNewCString(result);
return NS_OK;
}
@ -1677,11 +1816,10 @@ nsCookieService::SetCookieStringCommon(nsIURI *aHostURI,
bool isForeign = true;
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;
// Get originAttributes.
OriginAttributes attrs;
if (aChannel) {
NS_GetAppInfo(aChannel, &appId, &inBrowserElement);
NS_GetOriginAttributes(aChannel, attrs);
}
bool isPrivate = aChannel && NS_UsePrivateBrowsing(aChannel);
@ -1689,7 +1827,7 @@ nsCookieService::SetCookieStringCommon(nsIURI *aHostURI,
nsDependentCString cookieString(aCookieHeader);
nsDependentCString serverTime(aServerTime ? aServerTime : "");
SetCookieStringInternal(aHostURI, isForeign, cookieString,
serverTime, aFromHttp, appId, inBrowserElement,
serverTime, aFromHttp, attrs,
isPrivate, aChannel);
return NS_OK;
}
@ -1700,8 +1838,7 @@ nsCookieService::SetCookieStringInternal(nsIURI *aHostURI,
nsDependentCString &aCookieHeader,
const nsCString &aServerTime,
bool aFromHttp,
uint32_t aAppId,
bool aInBrowserElement,
const OriginAttributes &aOriginAttrs,
bool aIsPrivate,
nsIChannel *aChannel)
{
@ -1729,7 +1866,7 @@ nsCookieService::SetCookieStringInternal(nsIURI *aHostURI,
return;
}
nsCookieKey key(baseDomain, aAppId, aInBrowserElement);
nsCookieKey key(baseDomain, aOriginAttrs);
// check default prefs
CookieStatus cookieStatus = CheckPrefs(aHostURI, aIsForeign, requireHostMatch,
@ -2012,9 +2149,9 @@ nsCookieService::Add(const nsACString &aHost,
nsresult
nsCookieService::Remove(const nsACString& aHost, uint32_t aAppId,
bool aInBrowserElement, const nsACString& aName,
const nsACString& aPath, bool aBlocked)
nsCookieService::Remove(const nsACString& aHost, const OriginAttributes& aAttrs,
const nsACString& aName, const nsACString& aPath,
bool aBlocked)
{
if (!mDBState) {
NS_WARNING("No DBState! Profile already closed?");
@ -2032,7 +2169,7 @@ nsCookieService::Remove(const nsACString& aHost, uint32_t aAppId,
nsListIter matchIter;
nsRefPtr<nsCookie> cookie;
if (FindCookie(nsCookieKey(baseDomain, aAppId, aInBrowserElement),
if (FindCookie(nsCookieKey(baseDomain, aAttrs),
host,
PromiseFlatCString(aName),
PromiseFlatCString(aPath),
@ -2070,7 +2207,8 @@ nsCookieService::Remove(const nsACString &aHost,
const nsACString &aPath,
bool aBlocked)
{
return Remove(aHost, NECKO_NO_APP_ID, false, aName, aPath, aBlocked);
OriginAttributes attrs;
return Remove(aHost, attrs, aName, aPath, aBlocked);
}
/******************************************************************************
@ -2097,8 +2235,7 @@ nsCookieService::Read()
"isSecure, "
"isHttpOnly, "
"baseDomain, "
"appId, "
"inBrowserElement "
"originAttributes "
"FROM moz_cookies "
"WHERE baseDomain NOTNULL"), getter_AddRefs(stmtRead));
NS_ENSURE_SUCCESS(rv, RESULT_RETRY);
@ -2270,8 +2407,7 @@ nsCookieService::EnsureReadDomain(const nsCookieKey &aKey)
"isHttpOnly "
"FROM moz_cookies "
"WHERE baseDomain = :baseDomain "
" AND appId = :appId "
" AND inBrowserElement = :inBrowserElement"),
" AND originAttributes = :originAttributes"),
getter_AddRefs(mDefaultDBState->stmtReadDomain));
if (NS_FAILED(rv)) {
@ -2291,13 +2427,12 @@ nsCookieService::EnsureReadDomain(const nsCookieKey &aKey)
rv = mDefaultDBState->stmtReadDomain->BindUTF8StringByName(
NS_LITERAL_CSTRING("baseDomain"), aKey.mBaseDomain);
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);
nsAutoCString suffix;
aKey.mOriginAttributes.CreateSuffix(suffix);
rv = mDefaultDBState->stmtReadDomain->BindUTF8StringByName(
NS_LITERAL_CSTRING("originAttributes"), suffix);
NS_ASSERT_SUCCESS(rv);
bool hasResult;
nsCString name, value, host, path;
@ -2330,8 +2465,8 @@ nsCookieService::EnsureReadDomain(const nsCookieKey &aKey)
COOKIE_LOGSTRING(LogLevel::Debug,
("EnsureReadDomain(): %ld cookies read for base domain %s, "
" appId=%u, inBrowser=%d", array.Length(), aKey.mBaseDomain.get(),
(unsigned)aKey.mAppId, (int)aKey.mInBrowserElement));
" originAttributes = %s", array.Length(), aKey.mBaseDomain.get(),
suffix.get()));
}
void
@ -2362,8 +2497,7 @@ nsCookieService::EnsureReadComplete()
"isSecure, "
"isHttpOnly, "
"baseDomain, "
"appId, "
"inBrowserElement "
"originAttributes "
"FROM moz_cookies "
"WHERE baseDomain NOTNULL"), getter_AddRefs(stmt));
@ -2377,8 +2511,7 @@ nsCookieService::EnsureReadComplete()
}
nsCString baseDomain, name, value, host, path;
uint32_t appId;
bool inBrowserElement, hasResult;
bool hasResult;
nsAutoTArray<CookieDomainTuple, kMaxNumberOfCookies> array;
while (1) {
rv = stmt->ExecuteStep(&hasResult);
@ -2396,9 +2529,13 @@ nsCookieService::EnsureReadComplete()
// Make sure we haven't already read the data.
stmt->GetUTF8String(IDX_BASE_DOMAIN, baseDomain);
appId = static_cast<uint32_t>(stmt->AsInt32(IDX_APP_ID));
inBrowserElement = static_cast<bool>(stmt->AsInt32(IDX_BROWSER_ELEM));
nsCookieKey key(baseDomain, appId, inBrowserElement);
nsAutoCString suffix;
OriginAttributes attrs;
stmt->GetUTF8String(IDX_ORIGIN_ATTRIBUTES, suffix);
attrs.PopulateFromSuffix(suffix);
nsCookieKey key(baseDomain, attrs);
if (mDefaultDBState->readSet.GetEntry(key))
continue;
@ -2542,7 +2679,8 @@ nsCookieService::ImportCookies(nsIFile *aCookieFile)
if (NS_FAILED(rv))
continue;
// pre-existing cookies have appId=0, inBrowser=false
// pre-existing cookies have appId=0, inBrowser=false set by default
// constructor of OriginAttributes().
nsCookieKey key = DEFAULT_APP_KEY(baseDomain);
// Create a new nsCookie and assign the data. We don't know the cookie
@ -2633,8 +2771,7 @@ void
nsCookieService::GetCookieStringInternal(nsIURI *aHostURI,
bool aIsForeign,
bool aHttpBound,
uint32_t aAppId,
bool aInBrowserElement,
const OriginAttributes aOriginAttrs,
bool aIsPrivate,
nsCString &aCookieString)
{
@ -2691,7 +2828,7 @@ nsCookieService::GetCookieStringInternal(nsIURI *aHostURI,
int64_t currentTime = currentTimeInUsec / PR_USEC_PER_SEC;
bool stale = false;
nsCookieKey key(baseDomain, aAppId, aInBrowserElement);
nsCookieKey key(baseDomain, aOriginAttrs);
EnsureReadDomain(key);
// perform the hash lookup
@ -3989,8 +4126,8 @@ nsCookieService::GetCookiesForApp(uint32_t aAppId, bool aOnlyBrowserElement,
for (auto iter = mDBState->hostTable.Iter(); !iter.Done(); iter.Next()) {
nsCookieEntry* entry = iter.Get();
if (entry->mAppId != aAppId ||
(aOnlyBrowserElement && !entry->mInBrowserElement)) {
if (entry->mOriginAttributes.mAppId != aAppId ||
(aOnlyBrowserElement && !entry->mOriginAttributes.mInBrowser)) {
continue;
}
@ -4042,9 +4179,11 @@ nsCookieService::RemoveCookiesForApp(uint32_t aAppId, bool aOnlyBrowserElement)
//
// NOTE: we could make this better by getting nsCookieEntry objects instead
// of plain nsICookie.
Remove(host, aAppId, true, name, path, false);
OriginAttributes attrs(aAppId, true);
Remove(host, attrs, name, path, false);
if (!aOnlyBrowserElement) {
Remove(host, aAppId, false, name, path, false);
attrs.mInBrowser = false;
Remove(host, attrs, name, path, false);
}
}
@ -4158,12 +4297,10 @@ bindCookieParameters(mozIStorageBindingParamsArray *aParamsArray,
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);
nsAutoCString suffix;
aKey.mOriginAttributes.CreateSuffix(suffix);
rv = params->BindUTF8StringByName(NS_LITERAL_CSTRING("originAttributes"),
suffix);
NS_ASSERT_SUCCESS(rv);
rv = params->BindUTF8StringByName(NS_LITERAL_CSTRING("name"),

View File

@ -25,10 +25,15 @@
#include "mozIStorageRow.h"
#include "mozIStorageCompletionCallback.h"
#include "mozIStorageStatementCallback.h"
#include "mozIStorageFunction.h"
#include "nsIVariant.h"
#include "nsIFile.h"
#include "mozilla/BasePrincipal.h"
#include "mozilla/MemoryReporting.h"
using mozilla::OriginAttributes;
class nsICookiePermission;
class nsIEffectiveTLDService;
class nsIIDNService;
@ -60,22 +65,19 @@ public:
nsCookieKey()
{}
nsCookieKey(const nsCString &baseDomain, uint32_t appId, bool inBrowser)
nsCookieKey(const nsCString &baseDomain, const OriginAttributes &attrs)
: mBaseDomain(baseDomain)
, mAppId(appId)
, mInBrowserElement(inBrowser)
, mOriginAttributes(attrs)
{}
explicit nsCookieKey(KeyTypePointer other)
: mBaseDomain(other->mBaseDomain)
, mAppId(other->mAppId)
, mInBrowserElement(other->mInBrowserElement)
, mOriginAttributes(other->mOriginAttributes)
{}
nsCookieKey(KeyType other)
: mBaseDomain(other.mBaseDomain)
, mAppId(other.mAppId)
, mInBrowserElement(other.mInBrowserElement)
, mOriginAttributes(other.mOriginAttributes)
{}
~nsCookieKey()
@ -84,8 +86,7 @@ public:
bool KeyEquals(KeyTypePointer other) const
{
return mBaseDomain == other->mBaseDomain &&
mAppId == other->mAppId &&
mInBrowserElement == other->mInBrowserElement;
mOriginAttributes == other->mOriginAttributes;
}
static KeyTypePointer KeyToPointer(KeyType aKey)
@ -98,9 +99,9 @@ public:
// 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);
nsAutoCString suffix;
aKey->mOriginAttributes.CreateSuffix(suffix);
temp.Append(suffix);
return mozilla::HashString(temp);
}
@ -109,8 +110,7 @@ public:
enum { ALLOW_MEMMOVE = true };
nsCString mBaseDomain;
uint32_t mAppId;
bool mInBrowserElement;
OriginAttributes mOriginAttributes;
};
// Inherit from nsCookieKey so this can be stored in nsTHashTable
@ -274,6 +274,7 @@ class nsCookieService final : public nsICookieService
void InitDBStates();
OpenDBResult TryInitDB(bool aDeleteExistingDB);
nsresult CreateTable();
nsresult CreateTableForSchemaVersion5();
void CloseDBStates();
void CleanupCachedStatements();
void CleanupDefaultDBConnection();
@ -290,9 +291,9 @@ class nsCookieService final : public nsICookieService
nsresult GetBaseDomain(nsIURI *aHostURI, nsCString &aBaseDomain, bool &aRequireHostMatch);
nsresult GetBaseDomainFromHost(const nsACString &aHost, nsCString &aBaseDomain);
nsresult GetCookieStringCommon(nsIURI *aHostURI, nsIChannel *aChannel, bool aHttpBound, char** aCookie);
void GetCookieStringInternal(nsIURI *aHostURI, bool aIsForeign, bool aHttpBound, uint32_t aAppId, bool aInBrowserElement, bool aIsPrivate, nsCString &aCookie);
void GetCookieStringInternal(nsIURI *aHostURI, bool aIsForeign, bool aHttpBound, const OriginAttributes aOriginAttrs, bool aIsPrivate, nsCString &aCookie);
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, uint32_t aAppId, bool aInBrowserElement, bool aIsPrivate, nsIChannel* aChannel);
void SetCookieStringInternal(nsIURI *aHostURI, bool aIsForeign, nsDependentCString &aCookieHeader, const nsCString &aServerTime, bool aFromHttp, const OriginAttributes &aOriginAttrs, bool aIsPrivate, nsIChannel* aChannel);
bool SetCookieInternal(nsIURI *aHostURI, const nsCookieKey& aKey, bool aRequireHostMatch, CookieStatus aStatus, nsDependentCString &aCookieHeader, int64_t aServerTime, bool aFromHttp, nsIChannel* aChannel);
void AddInternal(const nsCookieKey& aKey, nsCookie *aCookie, int64_t aCurrentTimeInUsec, nsIURI *aHostURI, const char *aCookieHeader, bool aFromHttp);
void RemoveCookieFromList(const nsListIter &aIter, mozIStorageBindingParamsArray *aParamsArray = nullptr);
@ -318,12 +319,12 @@ class nsCookieService final : public nsICookieService
/**
* This method is a helper that allows calling nsICookieManager::Remove()
* with appId/inBrowserElement parameters.
* with OriginAttributes parameter.
* NOTE: this could be added to a public interface if we happen to need it.
*/
nsresult Remove(const nsACString& aHost, uint32_t aAppId,
bool aInBrowserElement, const nsACString& aName,
const nsACString& aPath, bool aBlocked);
nsresult Remove(const nsACString& aHost, const OriginAttributes& aAttrs,
const nsACString& aName, const nsACString& aPath,
bool aBlocked);
protected:
// cached members.