forked from mirrors/gecko-dev
Bug 1286858 - Data storage and interface changes for SameSite cookies. r=valentin
This commit is contained in:
parent
89ab2c1423
commit
e30f2f6227
11 changed files with 160 additions and 30 deletions
|
|
@ -18,7 +18,7 @@
|
||||||
// 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.
|
||||||
|
|
||||||
var COOKIE_DATABASE_SCHEMA_CURRENT = 8;
|
var COOKIE_DATABASE_SCHEMA_CURRENT = 9;
|
||||||
|
|
||||||
var test_generator = do_run_test();
|
var test_generator = do_run_test();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -178,7 +178,8 @@ CookieServiceChild::RecvAddCookie(const CookieStruct &aCookie,
|
||||||
aCookie.isSession(),
|
aCookie.isSession(),
|
||||||
aCookie.isSecure(),
|
aCookie.isSecure(),
|
||||||
false,
|
false,
|
||||||
aAttrs);
|
aAttrs,
|
||||||
|
aCookie.sameSite());
|
||||||
RecordDocumentCookie(cookie, aAttrs);
|
RecordDocumentCookie(cookie, aAttrs);
|
||||||
return IPC_OK();
|
return IPC_OK();
|
||||||
}
|
}
|
||||||
|
|
@ -210,7 +211,8 @@ CookieServiceChild::RecvTrackCookiesLoad(nsTArray<CookieStruct>&& aCookiesList,
|
||||||
aCookiesList[i].isSession(),
|
aCookiesList[i].isSession(),
|
||||||
aCookiesList[i].isSecure(),
|
aCookiesList[i].isSecure(),
|
||||||
false,
|
false,
|
||||||
aAttrs);
|
aAttrs,
|
||||||
|
aCookiesList[i].sameSite());
|
||||||
RecordDocumentCookie(cookie, aAttrs);
|
RecordDocumentCookie(cookie, aAttrs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -365,7 +367,8 @@ CookieServiceChild::SetCookieInternal(nsCookieAttributes &aCookieAt
|
||||||
aCookieAttributes.isSession,
|
aCookieAttributes.isSession,
|
||||||
aCookieAttributes.isSecure,
|
aCookieAttributes.isSecure,
|
||||||
aCookieAttributes.isHttpOnly,
|
aCookieAttributes.isHttpOnly,
|
||||||
aAttrs);
|
aAttrs,
|
||||||
|
aCookieAttributes.sameSite);
|
||||||
|
|
||||||
RecordDocumentCookie(cookie, aAttrs);
|
RecordDocumentCookie(cookie, aAttrs);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -91,6 +91,7 @@ GetInfoFromCookie(nsCookie *aCookie,
|
||||||
aCookieStruct.creationTime() = aCookie->CreationTime();
|
aCookieStruct.creationTime() = aCookie->CreationTime();
|
||||||
aCookieStruct.isSession() = aCookie->IsSession();
|
aCookieStruct.isSession() = aCookie->IsSession();
|
||||||
aCookieStruct.isSecure() = aCookie->IsSecure();
|
aCookieStruct.isSecure() = aCookie->IsSecure();
|
||||||
|
aCookieStruct.sameSite() = aCookie->SameSite();
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
@ -186,6 +187,7 @@ CookieServiceParent::SerialializeCookieList(const nsTArray<nsCookie*> &aFoundCoo
|
||||||
cookieStruct->creationTime() = cookie->CreationTime();
|
cookieStruct->creationTime() = cookie->CreationTime();
|
||||||
cookieStruct->isSession() = cookie->IsSession();
|
cookieStruct->isSession() = cookie->IsSession();
|
||||||
cookieStruct->isSecure() = cookie->IsSecure();
|
cookieStruct->isSecure() = cookie->IsSecure();
|
||||||
|
cookieStruct->sameSite() = cookie->SameSite();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -79,7 +79,8 @@ nsCookie::Create(const nsACString &aName,
|
||||||
bool aIsSession,
|
bool aIsSession,
|
||||||
bool aIsSecure,
|
bool aIsSecure,
|
||||||
bool aIsHttpOnly,
|
bool aIsHttpOnly,
|
||||||
const OriginAttributes& aOriginAttributes)
|
const OriginAttributes& aOriginAttributes,
|
||||||
|
int32_t aSameSite)
|
||||||
{
|
{
|
||||||
// Ensure mValue contains a valid UTF-8 sequence. Otherwise XPConnect will
|
// Ensure mValue contains a valid UTF-8 sequence. Otherwise XPConnect will
|
||||||
// truncate the string after the first invalid octet.
|
// truncate the string after the first invalid octet.
|
||||||
|
|
@ -108,11 +109,16 @@ nsCookie::Create(const nsACString &aName,
|
||||||
if (aCreationTime > gLastCreationTime)
|
if (aCreationTime > gLastCreationTime)
|
||||||
gLastCreationTime = aCreationTime;
|
gLastCreationTime = aCreationTime;
|
||||||
|
|
||||||
|
// If aSameSite is not a sensible value, assume strict
|
||||||
|
if (aSameSite < 0 || aSameSite > nsICookie2::SAMESITE_STRICT) {
|
||||||
|
aSameSite = nsICookie2::SAMESITE_STRICT;
|
||||||
|
}
|
||||||
|
|
||||||
// construct the cookie. placement new, oh yeah!
|
// construct the cookie. placement new, oh yeah!
|
||||||
return new (place) nsCookie(name, value, host, path, end,
|
return new (place) nsCookie(name, value, host, path, end,
|
||||||
aExpiry, aLastAccessed, aCreationTime,
|
aExpiry, aLastAccessed, aCreationTime,
|
||||||
aIsSession, aIsSecure, aIsHttpOnly,
|
aIsSession, aIsSecure, aIsHttpOnly,
|
||||||
aOriginAttributes);
|
aOriginAttributes, aSameSite);
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t
|
size_t
|
||||||
|
|
@ -151,6 +157,7 @@ NS_IMETHODIMP nsCookie::GetStatus(nsCookieStatus *aStatus) { *aStatus = 0;
|
||||||
NS_IMETHODIMP nsCookie::GetPolicy(nsCookiePolicy *aPolicy) { *aPolicy = 0; return NS_OK; }
|
NS_IMETHODIMP nsCookie::GetPolicy(nsCookiePolicy *aPolicy) { *aPolicy = 0; return NS_OK; }
|
||||||
NS_IMETHODIMP nsCookie::GetCreationTime(int64_t *aCreation){ *aCreation = CreationTime(); return NS_OK; }
|
NS_IMETHODIMP nsCookie::GetCreationTime(int64_t *aCreation){ *aCreation = CreationTime(); return NS_OK; }
|
||||||
NS_IMETHODIMP nsCookie::GetLastAccessed(int64_t *aTime) { *aTime = LastAccessed(); return NS_OK; }
|
NS_IMETHODIMP nsCookie::GetLastAccessed(int64_t *aTime) { *aTime = LastAccessed(); return NS_OK; }
|
||||||
|
NS_IMETHODIMP nsCookie::GetSameSite(int32_t *aSameSite) { *aSameSite = SameSite(); return NS_OK; }
|
||||||
|
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
nsCookie::GetOriginAttributes(JSContext *aCx, JS::MutableHandle<JS::Value> aVal)
|
nsCookie::GetOriginAttributes(JSContext *aCx, JS::MutableHandle<JS::Value> aVal)
|
||||||
|
|
|
||||||
|
|
@ -48,7 +48,8 @@ class nsCookie : public nsICookie2
|
||||||
bool aIsSession,
|
bool aIsSession,
|
||||||
bool aIsSecure,
|
bool aIsSecure,
|
||||||
bool aIsHttpOnly,
|
bool aIsHttpOnly,
|
||||||
const OriginAttributes& aOriginAttributes)
|
const OriginAttributes& aOriginAttributes,
|
||||||
|
int32_t aSameSite)
|
||||||
: mName(aName)
|
: mName(aName)
|
||||||
, mValue(aValue)
|
, mValue(aValue)
|
||||||
, mHost(aHost)
|
, mHost(aHost)
|
||||||
|
|
@ -61,6 +62,7 @@ class nsCookie : public nsICookie2
|
||||||
, mIsSecure(aIsSecure)
|
, mIsSecure(aIsSecure)
|
||||||
, mIsHttpOnly(aIsHttpOnly)
|
, mIsHttpOnly(aIsHttpOnly)
|
||||||
, mOriginAttributes(aOriginAttributes)
|
, mOriginAttributes(aOriginAttributes)
|
||||||
|
, mSameSite(aSameSite)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -92,7 +94,8 @@ class nsCookie : public nsICookie2
|
||||||
bool aIsSession,
|
bool aIsSession,
|
||||||
bool aIsSecure,
|
bool aIsSecure,
|
||||||
bool aIsHttpOnly,
|
bool aIsHttpOnly,
|
||||||
const OriginAttributes& aOriginAttributes);
|
const OriginAttributes& aOriginAttributes,
|
||||||
|
int32_t aSameSite);
|
||||||
|
|
||||||
size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const;
|
size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const;
|
||||||
|
|
||||||
|
|
@ -110,6 +113,7 @@ class nsCookie : public nsICookie2
|
||||||
inline bool IsSecure() const { return mIsSecure; }
|
inline bool IsSecure() const { return mIsSecure; }
|
||||||
inline bool IsHttpOnly() const { return mIsHttpOnly; }
|
inline bool IsHttpOnly() const { return mIsHttpOnly; }
|
||||||
inline const OriginAttributes& OriginAttributesRef() const { return mOriginAttributes; }
|
inline const OriginAttributes& OriginAttributesRef() const { return mOriginAttributes; }
|
||||||
|
inline int32_t SameSite() const { return mSameSite; }
|
||||||
|
|
||||||
// setters
|
// setters
|
||||||
inline void SetExpiry(int64_t aExpiry) { mExpiry = aExpiry; }
|
inline void SetExpiry(int64_t aExpiry) { mExpiry = aExpiry; }
|
||||||
|
|
@ -144,6 +148,7 @@ class nsCookie : public nsICookie2
|
||||||
bool mIsSecure;
|
bool mIsSecure;
|
||||||
bool mIsHttpOnly;
|
bool mIsHttpOnly;
|
||||||
mozilla::OriginAttributes mOriginAttributes;
|
mozilla::OriginAttributes mOriginAttributes;
|
||||||
|
int32_t mSameSite;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Comparator class for sorting cookies before sending to a server.
|
// Comparator class for sorting cookies before sending to a server.
|
||||||
|
|
|
||||||
|
|
@ -80,7 +80,7 @@ static StaticRefPtr<nsCookieService> gCookieService;
|
||||||
#define HTTP_ONLY_PREFIX "#HttpOnly_"
|
#define HTTP_ONLY_PREFIX "#HttpOnly_"
|
||||||
|
|
||||||
#define COOKIES_FILE "cookies.sqlite"
|
#define COOKIES_FILE "cookies.sqlite"
|
||||||
#define COOKIES_SCHEMA_VERSION 8
|
#define COOKIES_SCHEMA_VERSION 9
|
||||||
|
|
||||||
// parameter indexes; see EnsureReadDomain, EnsureReadComplete and
|
// parameter indexes; see EnsureReadDomain, EnsureReadComplete and
|
||||||
// ReadCookieDBListener::HandleResult
|
// ReadCookieDBListener::HandleResult
|
||||||
|
|
@ -95,6 +95,7 @@ static StaticRefPtr<nsCookieService> gCookieService;
|
||||||
#define IDX_HTTPONLY 8
|
#define IDX_HTTPONLY 8
|
||||||
#define IDX_BASE_DOMAIN 9
|
#define IDX_BASE_DOMAIN 9
|
||||||
#define IDX_ORIGIN_ATTRIBUTES 10
|
#define IDX_ORIGIN_ATTRIBUTES 10
|
||||||
|
#define IDX_SAME_SITE 11
|
||||||
|
|
||||||
#define TOPIC_CLEAR_ORIGIN_DATA "clear-origin-attributes-data"
|
#define TOPIC_CLEAR_ORIGIN_DATA "clear-origin-attributes-data"
|
||||||
|
|
||||||
|
|
@ -1391,6 +1392,16 @@ nsCookieService::TryInitDB(bool aRecreateDB)
|
||||||
COOKIE_LOGSTRING(LogLevel::Debug,
|
COOKIE_LOGSTRING(LogLevel::Debug,
|
||||||
("Upgraded database to schema version 8"));
|
("Upgraded database to schema version 8"));
|
||||||
}
|
}
|
||||||
|
MOZ_FALLTHROUGH;
|
||||||
|
|
||||||
|
case 8:
|
||||||
|
{
|
||||||
|
// Add the sameSite column to the table.
|
||||||
|
rv = mDefaultDBState->dbConn->ExecuteSimpleSQL(
|
||||||
|
NS_LITERAL_CSTRING("ALTER TABLE moz_cookies ADD sameSite INTEGER"));
|
||||||
|
COOKIE_LOGSTRING(LogLevel::Debug,
|
||||||
|
("Upgraded database to schema version 9"));
|
||||||
|
}
|
||||||
|
|
||||||
// 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);
|
||||||
|
|
@ -1438,7 +1449,8 @@ nsCookieService::TryInitDB(bool aRecreateDB)
|
||||||
"lastAccessed, "
|
"lastAccessed, "
|
||||||
"creationTime, "
|
"creationTime, "
|
||||||
"isSecure, "
|
"isSecure, "
|
||||||
"isHttpOnly "
|
"isHttpOnly, "
|
||||||
|
"sameSite "
|
||||||
"FROM moz_cookies"), getter_AddRefs(stmt));
|
"FROM moz_cookies"), getter_AddRefs(stmt));
|
||||||
if (NS_SUCCEEDED(rv))
|
if (NS_SUCCEEDED(rv))
|
||||||
break;
|
break;
|
||||||
|
|
@ -1479,7 +1491,8 @@ nsCookieService::TryInitDB(bool aRecreateDB)
|
||||||
"lastAccessed, "
|
"lastAccessed, "
|
||||||
"creationTime, "
|
"creationTime, "
|
||||||
"isSecure, "
|
"isSecure, "
|
||||||
"isHttpOnly"
|
"isHttpOnly, "
|
||||||
|
"sameSite "
|
||||||
") VALUES ("
|
") VALUES ("
|
||||||
":baseDomain, "
|
":baseDomain, "
|
||||||
":originAttributes, "
|
":originAttributes, "
|
||||||
|
|
@ -1491,7 +1504,8 @@ nsCookieService::TryInitDB(bool aRecreateDB)
|
||||||
":lastAccessed, "
|
":lastAccessed, "
|
||||||
":creationTime, "
|
":creationTime, "
|
||||||
":isSecure, "
|
":isSecure, "
|
||||||
":isHttpOnly"
|
":isHttpOnly, "
|
||||||
|
":sameSite"
|
||||||
")"),
|
")"),
|
||||||
getter_AddRefs(mDefaultDBState->stmtInsert));
|
getter_AddRefs(mDefaultDBState->stmtInsert));
|
||||||
NS_ENSURE_SUCCESS(rv, RESULT_RETRY);
|
NS_ENSURE_SUCCESS(rv, RESULT_RETRY);
|
||||||
|
|
@ -1558,6 +1572,7 @@ nsCookieService::CreateTableWorker(const char* aName)
|
||||||
"isSecure INTEGER, "
|
"isSecure INTEGER, "
|
||||||
"isHttpOnly INTEGER, "
|
"isHttpOnly INTEGER, "
|
||||||
"inBrowserElement INTEGER DEFAULT 0, "
|
"inBrowserElement INTEGER DEFAULT 0, "
|
||||||
|
"sameSite INTEGER DEFAULT 0, "
|
||||||
"CONSTRAINT moz_uniqueid UNIQUE (name, host, path, originAttributes)"
|
"CONSTRAINT moz_uniqueid UNIQUE (name, host, path, originAttributes)"
|
||||||
")");
|
")");
|
||||||
return mDefaultDBState->dbConn->ExecuteSimpleSQL(command);
|
return mDefaultDBState->dbConn->ExecuteSimpleSQL(command);
|
||||||
|
|
@ -2476,6 +2491,7 @@ nsCookieService::Add(const nsACString &aHost,
|
||||||
bool aIsSession,
|
bool aIsSession,
|
||||||
int64_t aExpiry,
|
int64_t aExpiry,
|
||||||
JS::HandleValue aOriginAttributes,
|
JS::HandleValue aOriginAttributes,
|
||||||
|
int32_t aSameSite,
|
||||||
JSContext* aCx,
|
JSContext* aCx,
|
||||||
uint8_t aArgc)
|
uint8_t aArgc)
|
||||||
{
|
{
|
||||||
|
|
@ -2491,7 +2507,7 @@ nsCookieService::Add(const nsACString &aHost,
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
||||||
return AddNative(aHost, aPath, aName, aValue, aIsSecure, aIsHttpOnly,
|
return AddNative(aHost, aPath, aName, aValue, aIsSecure, aIsHttpOnly,
|
||||||
aIsSession, aExpiry, &attrs);
|
aIsSession, aExpiry, &attrs, aSameSite);
|
||||||
}
|
}
|
||||||
|
|
||||||
NS_IMETHODIMP_(nsresult)
|
NS_IMETHODIMP_(nsresult)
|
||||||
|
|
@ -2503,7 +2519,8 @@ nsCookieService::AddNative(const nsACString &aHost,
|
||||||
bool aIsHttpOnly,
|
bool aIsHttpOnly,
|
||||||
bool aIsSession,
|
bool aIsSession,
|
||||||
int64_t aExpiry,
|
int64_t aExpiry,
|
||||||
OriginAttributes* aOriginAttributes)
|
OriginAttributes* aOriginAttributes,
|
||||||
|
int32_t aSameSite)
|
||||||
{
|
{
|
||||||
if (NS_WARN_IF(!aOriginAttributes)) {
|
if (NS_WARN_IF(!aOriginAttributes)) {
|
||||||
return NS_ERROR_FAILURE;
|
return NS_ERROR_FAILURE;
|
||||||
|
|
@ -2539,7 +2556,8 @@ nsCookieService::AddNative(const nsACString &aHost,
|
||||||
aIsSession,
|
aIsSession,
|
||||||
aIsSecure,
|
aIsSecure,
|
||||||
aIsHttpOnly,
|
aIsHttpOnly,
|
||||||
key.mOriginAttributes);
|
key.mOriginAttributes,
|
||||||
|
aSameSite);
|
||||||
if (!cookie) {
|
if (!cookie) {
|
||||||
return NS_ERROR_OUT_OF_MEMORY;
|
return NS_ERROR_OUT_OF_MEMORY;
|
||||||
}
|
}
|
||||||
|
|
@ -2671,7 +2689,8 @@ nsCookieService::Read()
|
||||||
"isSecure, "
|
"isSecure, "
|
||||||
"isHttpOnly, "
|
"isHttpOnly, "
|
||||||
"baseDomain, "
|
"baseDomain, "
|
||||||
"originAttributes "
|
"originAttributes, "
|
||||||
|
"sameSite "
|
||||||
"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);
|
||||||
|
|
@ -2732,6 +2751,7 @@ nsCookieService::GetCookieFromRow(T &aRow, const OriginAttributes& aOriginAttrib
|
||||||
int64_t creationTime = aRow->AsInt64(IDX_CREATION_TIME);
|
int64_t creationTime = aRow->AsInt64(IDX_CREATION_TIME);
|
||||||
bool isSecure = 0 != aRow->AsInt32(IDX_SECURE);
|
bool isSecure = 0 != aRow->AsInt32(IDX_SECURE);
|
||||||
bool isHttpOnly = 0 != aRow->AsInt32(IDX_HTTPONLY);
|
bool isHttpOnly = 0 != aRow->AsInt32(IDX_HTTPONLY);
|
||||||
|
int32_t sameSite = aRow->AsInt32(IDX_SAME_SITE);
|
||||||
|
|
||||||
// Create a new nsCookie and assign the data.
|
// Create a new nsCookie and assign the data.
|
||||||
return nsCookie::Create(name, value, host, path,
|
return nsCookie::Create(name, value, host, path,
|
||||||
|
|
@ -2741,7 +2761,8 @@ nsCookieService::GetCookieFromRow(T &aRow, const OriginAttributes& aOriginAttrib
|
||||||
false,
|
false,
|
||||||
isSecure,
|
isSecure,
|
||||||
isHttpOnly,
|
isHttpOnly,
|
||||||
aOriginAttributes);
|
aOriginAttributes,
|
||||||
|
sameSite);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
@ -2850,7 +2871,10 @@ nsCookieService::EnsureReadDomain(const nsCookieKey &aKey)
|
||||||
"lastAccessed, "
|
"lastAccessed, "
|
||||||
"creationTime, "
|
"creationTime, "
|
||||||
"isSecure, "
|
"isSecure, "
|
||||||
"isHttpOnly "
|
"isHttpOnly, "
|
||||||
|
"baseDomain, "
|
||||||
|
"originAttributes, "
|
||||||
|
"sameSite "
|
||||||
"FROM moz_cookies "
|
"FROM moz_cookies "
|
||||||
"WHERE baseDomain = :baseDomain "
|
"WHERE baseDomain = :baseDomain "
|
||||||
" AND originAttributes = :originAttributes"),
|
" AND originAttributes = :originAttributes"),
|
||||||
|
|
@ -2947,7 +2971,8 @@ nsCookieService::EnsureReadComplete()
|
||||||
"isSecure, "
|
"isSecure, "
|
||||||
"isHttpOnly, "
|
"isHttpOnly, "
|
||||||
"baseDomain, "
|
"baseDomain, "
|
||||||
"originAttributes "
|
"originAttributes, "
|
||||||
|
"sameSite "
|
||||||
"FROM moz_cookies "
|
"FROM moz_cookies "
|
||||||
"WHERE baseDomain NOTNULL"), getter_AddRefs(stmt));
|
"WHERE baseDomain NOTNULL"), getter_AddRefs(stmt));
|
||||||
|
|
||||||
|
|
@ -3151,7 +3176,8 @@ nsCookieService::ImportCookies(nsIFile *aCookieFile)
|
||||||
false,
|
false,
|
||||||
Substring(buffer, secureIndex, expiresIndex - secureIndex - 1).EqualsLiteral(kTrue),
|
Substring(buffer, secureIndex, expiresIndex - secureIndex - 1).EqualsLiteral(kTrue),
|
||||||
isHttpOnly,
|
isHttpOnly,
|
||||||
key.mOriginAttributes);
|
key.mOriginAttributes,
|
||||||
|
nsICookie2::SAMESITE_UNSET);
|
||||||
if (!newCookie) {
|
if (!newCookie) {
|
||||||
return NS_ERROR_OUT_OF_MEMORY;
|
return NS_ERROR_OUT_OF_MEMORY;
|
||||||
}
|
}
|
||||||
|
|
@ -3601,7 +3627,8 @@ nsCookieService::SetCookieInternal(nsIURI *aHostURI,
|
||||||
cookieAttributes.isSession,
|
cookieAttributes.isSession,
|
||||||
cookieAttributes.isSecure,
|
cookieAttributes.isSecure,
|
||||||
cookieAttributes.isHttpOnly,
|
cookieAttributes.isHttpOnly,
|
||||||
aKey.mOriginAttributes);
|
aKey.mOriginAttributes,
|
||||||
|
cookieAttributes.sameSite);
|
||||||
if (!cookie)
|
if (!cookie)
|
||||||
return newCookie;
|
return newCookie;
|
||||||
|
|
||||||
|
|
@ -3993,6 +4020,8 @@ nsCookieService::ParseAttributes(nsDependentCString &aCookieHeader,
|
||||||
static const char kMaxage[] = "max-age";
|
static const char kMaxage[] = "max-age";
|
||||||
static const char kSecure[] = "secure";
|
static const char kSecure[] = "secure";
|
||||||
static const char kHttpOnly[] = "httponly";
|
static const char kHttpOnly[] = "httponly";
|
||||||
|
static const char kSameSite[] = "samesite";
|
||||||
|
static const char kSameSiteLax[] = "lax";
|
||||||
|
|
||||||
nsACString::const_char_iterator tempBegin, tempEnd;
|
nsACString::const_char_iterator tempBegin, tempEnd;
|
||||||
nsACString::const_char_iterator cookieStart, cookieEnd;
|
nsACString::const_char_iterator cookieStart, cookieEnd;
|
||||||
|
|
@ -4001,6 +4030,7 @@ nsCookieService::ParseAttributes(nsDependentCString &aCookieHeader,
|
||||||
|
|
||||||
aCookieAttributes.isSecure = false;
|
aCookieAttributes.isSecure = false;
|
||||||
aCookieAttributes.isHttpOnly = false;
|
aCookieAttributes.isHttpOnly = false;
|
||||||
|
aCookieAttributes.sameSite = nsICookie2::SAMESITE_UNSET;
|
||||||
|
|
||||||
nsDependentCSubstring tokenString(cookieStart, cookieStart);
|
nsDependentCSubstring tokenString(cookieStart, cookieStart);
|
||||||
nsDependentCSubstring tokenValue (cookieStart, cookieStart);
|
nsDependentCSubstring tokenValue (cookieStart, cookieStart);
|
||||||
|
|
@ -4049,6 +4079,14 @@ nsCookieService::ParseAttributes(nsDependentCString &aCookieHeader,
|
||||||
// just set the boolean
|
// just set the boolean
|
||||||
else if (tokenString.LowerCaseEqualsLiteral(kHttpOnly))
|
else if (tokenString.LowerCaseEqualsLiteral(kHttpOnly))
|
||||||
aCookieAttributes.isHttpOnly = true;
|
aCookieAttributes.isHttpOnly = true;
|
||||||
|
|
||||||
|
else if (tokenString.LowerCaseEqualsLiteral(kSameSite)) {
|
||||||
|
if (tokenValue.LowerCaseEqualsLiteral(kSameSiteLax)) {
|
||||||
|
aCookieAttributes.sameSite = nsICookie2::SAMESITE_LAX;
|
||||||
|
} else {
|
||||||
|
aCookieAttributes.sameSite = nsICookie2::SAMESITE_STRICT;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// rebind aCookieHeader, in case we need to process another cookie
|
// rebind aCookieHeader, in case we need to process another cookie
|
||||||
|
|
@ -5213,6 +5251,10 @@ bindCookieParameters(mozIStorageBindingParamsArray *aParamsArray,
|
||||||
aCookie->IsHttpOnly());
|
aCookie->IsHttpOnly());
|
||||||
NS_ASSERT_SUCCESS(rv);
|
NS_ASSERT_SUCCESS(rv);
|
||||||
|
|
||||||
|
rv = params->BindInt32ByName(NS_LITERAL_CSTRING("sameSite"),
|
||||||
|
aCookie->SameSite());
|
||||||
|
NS_ASSERT_SUCCESS(rv);
|
||||||
|
|
||||||
// Bind the params to the array.
|
// Bind the params to the array.
|
||||||
rv = aParamsArray->AddParams(params);
|
rv = aParamsArray->AddParams(params);
|
||||||
NS_ASSERT_SUCCESS(rv);
|
NS_ASSERT_SUCCESS(rv);
|
||||||
|
|
|
||||||
|
|
@ -195,6 +195,7 @@ struct nsCookieAttributes
|
||||||
bool isSession;
|
bool isSession;
|
||||||
bool isSecure;
|
bool isSecure;
|
||||||
bool isHttpOnly;
|
bool isHttpOnly;
|
||||||
|
int8_t sameSite;
|
||||||
};
|
};
|
||||||
|
|
||||||
class nsCookieService final : public nsICookieService
|
class nsCookieService final : public nsICookieService
|
||||||
|
|
|
||||||
|
|
@ -11,10 +11,13 @@
|
||||||
* access of cookie objects
|
* access of cookie objects
|
||||||
*/
|
*/
|
||||||
|
|
||||||
[scriptable, uuid(05c420e5-03d0-4c7b-a605-df7ebe5ca326)]
|
[scriptable, uuid(be205dae-4f4c-11e6-80ba-ea5cd310c1a8)]
|
||||||
|
|
||||||
interface nsICookie2 : nsICookie
|
interface nsICookie2 : nsICookie
|
||||||
{
|
{
|
||||||
|
const uint32_t SAMESITE_UNSET = 0;
|
||||||
|
const uint32_t SAMESITE_LAX = 1;
|
||||||
|
const uint32_t SAMESITE_STRICT = 2;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* the host (possibly fully qualified) of the cookie,
|
* the host (possibly fully qualified) of the cookie,
|
||||||
|
|
@ -60,4 +63,15 @@ interface nsICookie2 : nsICookie
|
||||||
*/
|
*/
|
||||||
readonly attribute int64_t lastAccessed;
|
readonly attribute int64_t lastAccessed;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* the sameSite attribute; this controls the cookie behavior for cross-site
|
||||||
|
* requests as per
|
||||||
|
* https://tools.ietf.org/html/draft-west-first-party-cookies-07
|
||||||
|
*
|
||||||
|
* This should be one of:
|
||||||
|
* - SAMESITE_UNSET - the SameSite attribute is not present
|
||||||
|
* - SAMESITE_LAX - the SameSite attribute is present, but not strict
|
||||||
|
* - SAMESITE_STRICT - the SameSite attribute is present and strict
|
||||||
|
*/
|
||||||
|
readonly attribute int32_t sameSite;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -46,8 +46,12 @@ interface nsICookieManager2 : nsICookieManager
|
||||||
* expiration date, in seconds since midnight (00:00:00), January 1,
|
* expiration date, in seconds since midnight (00:00:00), January 1,
|
||||||
* 1970 UTC. note that expiry time will also be honored for session cookies;
|
* 1970 UTC. note that expiry time will also be honored for session cookies;
|
||||||
* in this way, the more restrictive of the two will take effect.
|
* in this way, the more restrictive of the two will take effect.
|
||||||
* @param aOriginAttributes The originAttributes of this cookie. This
|
* @param aOriginAttributes
|
||||||
* attribute is optional to avoid breaking add-ons.
|
* the originAttributes of this cookie. This attribute is optional to
|
||||||
|
* avoid breaking add-ons.
|
||||||
|
* @param aSameSite
|
||||||
|
* the SameSite attribute. This attribute is optional to avoid breaking
|
||||||
|
* addons
|
||||||
*/
|
*/
|
||||||
[implicit_jscontext, optional_argc]
|
[implicit_jscontext, optional_argc]
|
||||||
void add(in AUTF8String aHost,
|
void add(in AUTF8String aHost,
|
||||||
|
|
@ -58,7 +62,8 @@ interface nsICookieManager2 : nsICookieManager
|
||||||
in boolean aIsHttpOnly,
|
in boolean aIsHttpOnly,
|
||||||
in boolean aIsSession,
|
in boolean aIsSession,
|
||||||
in int64_t aExpiry,
|
in int64_t aExpiry,
|
||||||
[optional] in jsval aOriginAttributes);
|
[optional] in jsval aOriginAttributes,
|
||||||
|
[optional] in int32_t aSameSite);
|
||||||
|
|
||||||
[notxpcom]
|
[notxpcom]
|
||||||
nsresult addNative(in AUTF8String aHost,
|
nsresult addNative(in AUTF8String aHost,
|
||||||
|
|
@ -69,7 +74,8 @@ interface nsICookieManager2 : nsICookieManager
|
||||||
in boolean aIsHttpOnly,
|
in boolean aIsHttpOnly,
|
||||||
in boolean aIsSession,
|
in boolean aIsSession,
|
||||||
in int64_t aExpiry,
|
in int64_t aExpiry,
|
||||||
in OriginAttributesPtr aOriginAttributes);
|
in OriginAttributesPtr aOriginAttributes,
|
||||||
|
in int32_t aSameSite);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Find whether a given cookie already exists.
|
* Find whether a given cookie already exists.
|
||||||
|
|
|
||||||
|
|
@ -212,6 +212,7 @@ struct CookieStruct
|
||||||
int64_t creationTime;
|
int64_t creationTime;
|
||||||
bool isSession;
|
bool isSession;
|
||||||
bool isSecure;
|
bool isSecure;
|
||||||
|
int8_t sameSite;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace ipc
|
} // namespace ipc
|
||||||
|
|
|
||||||
|
|
@ -634,7 +634,8 @@ TEST(TestCookie,TestCookieMain)
|
||||||
false, // is httponly
|
false, // is httponly
|
||||||
true, // is session
|
true, // is session
|
||||||
INT64_MAX, // expiry time
|
INT64_MAX, // expiry time
|
||||||
&attrs))); // originAttributes
|
&attrs, // originAttributes
|
||||||
|
nsICookie2::SAMESITE_UNSET)));
|
||||||
EXPECT_TRUE(NS_SUCCEEDED(cookieMgr2->AddNative(NS_LITERAL_CSTRING("cookiemgr.test"), // domain
|
EXPECT_TRUE(NS_SUCCEEDED(cookieMgr2->AddNative(NS_LITERAL_CSTRING("cookiemgr.test"), // domain
|
||||||
NS_LITERAL_CSTRING("/foo"), // path
|
NS_LITERAL_CSTRING("/foo"), // path
|
||||||
NS_LITERAL_CSTRING("test2"), // name
|
NS_LITERAL_CSTRING("test2"), // name
|
||||||
|
|
@ -643,7 +644,8 @@ TEST(TestCookie,TestCookieMain)
|
||||||
true, // is httponly
|
true, // is httponly
|
||||||
true, // is session
|
true, // is session
|
||||||
PR_Now() / PR_USEC_PER_SEC + 2, // expiry time
|
PR_Now() / PR_USEC_PER_SEC + 2, // expiry time
|
||||||
&attrs))); // originAttributes
|
&attrs, // originAttributes
|
||||||
|
nsICookie2::SAMESITE_UNSET)));
|
||||||
EXPECT_TRUE(NS_SUCCEEDED(cookieMgr2->AddNative(NS_LITERAL_CSTRING("new.domain"), // domain
|
EXPECT_TRUE(NS_SUCCEEDED(cookieMgr2->AddNative(NS_LITERAL_CSTRING("new.domain"), // domain
|
||||||
NS_LITERAL_CSTRING("/rabbit"), // path
|
NS_LITERAL_CSTRING("/rabbit"), // path
|
||||||
NS_LITERAL_CSTRING("test3"), // name
|
NS_LITERAL_CSTRING("test3"), // name
|
||||||
|
|
@ -652,7 +654,8 @@ TEST(TestCookie,TestCookieMain)
|
||||||
false, // is httponly
|
false, // is httponly
|
||||||
true, // is session
|
true, // is session
|
||||||
INT64_MAX, // expiry time
|
INT64_MAX, // expiry time
|
||||||
&attrs))); // originAttributes
|
&attrs, // originAttributes
|
||||||
|
nsICookie2::SAMESITE_UNSET)));
|
||||||
// confirm using enumerator
|
// confirm using enumerator
|
||||||
nsCOMPtr<nsISimpleEnumerator> enumerator;
|
nsCOMPtr<nsISimpleEnumerator> enumerator;
|
||||||
EXPECT_TRUE(NS_SUCCEEDED(cookieMgr->GetEnumerator(getter_AddRefs(enumerator))));
|
EXPECT_TRUE(NS_SUCCEEDED(cookieMgr->GetEnumerator(getter_AddRefs(enumerator))));
|
||||||
|
|
@ -706,7 +709,8 @@ TEST(TestCookie,TestCookieMain)
|
||||||
false, // is httponly
|
false, // is httponly
|
||||||
true, // is session
|
true, // is session
|
||||||
INT64_MIN, // expiry time
|
INT64_MIN, // expiry time
|
||||||
&attrs))); // originAttributes
|
&attrs, // originAttributes
|
||||||
|
nsICookie2::SAMESITE_UNSET)));
|
||||||
EXPECT_TRUE(NS_SUCCEEDED(cookieMgr2->CookieExistsNative(newDomainCookie, &attrs, &found)));
|
EXPECT_TRUE(NS_SUCCEEDED(cookieMgr2->CookieExistsNative(newDomainCookie, &attrs, &found)));
|
||||||
EXPECT_FALSE(found);
|
EXPECT_FALSE(found);
|
||||||
// sleep four seconds, to make sure the second cookie has expired
|
// sleep four seconds, to make sure the second cookie has expired
|
||||||
|
|
@ -764,8 +768,53 @@ TEST(TestCookie,TestCookieMain)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
GetACookie(cookieService, "http://creation.ordering.tests/", nullptr, getter_Copies(cookie));
|
GetACookie(cookieService, "http://creation.ordering.tests/", nullptr, getter_Copies(cookie));
|
||||||
|
|
||||||
EXPECT_TRUE(CheckResult(cookie.get(), MUST_BE_NULL));
|
EXPECT_TRUE(CheckResult(cookie.get(), MUST_BE_NULL));
|
||||||
|
|
||||||
|
|
||||||
|
// *** SameSite attribute - parsing and cookie storage tests
|
||||||
|
// Clear the cookies
|
||||||
|
EXPECT_TRUE(NS_SUCCEEDED(cookieMgr->RemoveAll()));
|
||||||
|
|
||||||
|
// Set cookies with various incantations of the samesite attribute:
|
||||||
|
// No same site attribute present
|
||||||
|
SetACookie(cookieService, "http://samesite.test", nullptr, "unset=yes", nullptr);
|
||||||
|
// samesite attribute present but with no value
|
||||||
|
SetACookie(cookieService, "http://samesite.test", nullptr, "unspecified=yes; samesite", nullptr);
|
||||||
|
// samesite=strict
|
||||||
|
SetACookie(cookieService, "http://samesite.test", nullptr, "strict=yes; samesite=strict", nullptr);
|
||||||
|
// samesite=lax
|
||||||
|
SetACookie(cookieService, "http://samesite.test", nullptr, "lax=yes; samesite=lax", nullptr);
|
||||||
|
|
||||||
|
EXPECT_TRUE(NS_SUCCEEDED(cookieMgr->GetEnumerator(getter_AddRefs(enumerator))));
|
||||||
|
i = 0;
|
||||||
|
|
||||||
|
// check the cookies for the required samesite value
|
||||||
|
while (NS_SUCCEEDED(enumerator->HasMoreElements(&more)) && more) {
|
||||||
|
nsCOMPtr<nsISupports> cookie;
|
||||||
|
if (NS_FAILED(enumerator->GetNext(getter_AddRefs(cookie)))) break;
|
||||||
|
++i;
|
||||||
|
|
||||||
|
// keep tabs on the second and third cookies, so we can check them later
|
||||||
|
nsCOMPtr<nsICookie2> cookie2(do_QueryInterface(cookie));
|
||||||
|
if (!cookie2) break;
|
||||||
|
nsAutoCString name;
|
||||||
|
cookie2->GetName(name);
|
||||||
|
int32_t sameSiteAttr;
|
||||||
|
cookie2->GetSameSite(&sameSiteAttr);
|
||||||
|
if (name.EqualsLiteral("unset")) {
|
||||||
|
EXPECT_TRUE(sameSiteAttr == nsICookie2::SAMESITE_UNSET);
|
||||||
|
} else if (name.EqualsLiteral("unspecified")) {
|
||||||
|
EXPECT_TRUE(sameSiteAttr == nsICookie2::SAMESITE_STRICT);
|
||||||
|
} else if (name.EqualsLiteral("strict")) {
|
||||||
|
EXPECT_TRUE(sameSiteAttr == nsICookie2::SAMESITE_STRICT);
|
||||||
|
} else if (name.EqualsLiteral("lax")) {
|
||||||
|
EXPECT_TRUE(sameSiteAttr == nsICookie2::SAMESITE_LAX);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
EXPECT_TRUE(i == 4);
|
||||||
|
|
||||||
// XXX the following are placeholders: add these tests please!
|
// XXX the following are placeholders: add these tests please!
|
||||||
// *** "noncompliant cookie" tests
|
// *** "noncompliant cookie" tests
|
||||||
// *** IP address tests
|
// *** IP address tests
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue