Revert "Bug 1955685 - Improve cookie validation - part 7 - Fix existing tests, r=valentin,webdriver-reviewers,extension-reviewers,settings-reviewers,devtools-reviewers,cookie-reviewers,sessionstore-reviewers,migration-reviewers,backup-reviewers,sthompson,robwu,ochameau" for causing multiple failures

This reverts commit 585626d8fc.

Revert "Bug 1955685 - Improve cookie validation - part 6 - CookieValidation for web-ext, r=robwu,cookie-reviewers,valentin"

This reverts commit b38d308433.

Revert "Bug 1955685 - Improve cookie validation - part 5 - 0x20 as invalid chars for cookie names and values r=valentin,cookie-reviewers"

This reverts commit 3578880f65.

Revert "Bug 1955685 - Improve cookie validation - part 4 - expiry validation, r=edgul,cookie-reviewers,valentin"

This reverts commit 26e16d402f.

Revert "Bug 1955685 - Improve cookie validation - part 3 - nsICookieValidation in cookieManager.add, r=edgul,extension-reviewers,settings-reviewers,search-reviewers,devtools-reviewers,cookie-reviewers,sessionstore-reviewers,backup-reviewers,nchevobbe,mconley,Standard8,webdriver-reviewers,whimboo,valentin,sfoster,robwu"

This reverts commit 433a4d736d.

Revert "Bug 1955685 - Improve cookie validation - part 2 - nsICookieValidation in cookieManager.addNative, r=edgul,cookie-reviewers,geckoview-reviewers,nalexander,glandium"

This reverts commit 818c2c1769.

Revert "Bug 1955685 - Improve cookie validation - part 1 - nsICookieValidation, r=edgul,cookie-reviewers"

This reverts commit 55ad680779.
This commit is contained in:
Alexandru Marc
2025-05-20 12:27:23 +03:00
committed by amarc@mozilla.com
parent a4d8da212e
commit 43acd12a3b
88 changed files with 754 additions and 1548 deletions

View File

@@ -59,7 +59,7 @@ function checkIndexedDB(host, originAttributes) {
}
function createHostCookie(host, originAttributes) {
const cv = Services.cookies.add(
Services.cookies.add(
host,
"/test",
"foo",
@@ -69,14 +69,13 @@ function createHostCookie(host, originAttributes) {
false,
Date.now() + 24000 * 60 * 60,
originAttributes,
Ci.nsICookie.SAMESITE_UNSET,
Ci.nsICookie.SAMESITE_NONE,
Ci.nsICookie.SCHEME_HTTPS
);
is(cv.result, Ci.nsICookieValidation.eOK, "Valid cookie");
}
function createDomainCookie(host, originAttributes) {
const cv = Services.cookies.add(
Services.cookies.add(
"." + host,
"/test",
"foo",
@@ -86,10 +85,9 @@ function createDomainCookie(host, originAttributes) {
false,
Date.now() + 24000 * 60 * 60,
originAttributes,
Ci.nsICookie.SAMESITE_UNSET,
Ci.nsICookie.SAMESITE_NONE,
Ci.nsICookie.SCHEME_HTTPS
);
is(cv.result, Ci.nsICookieValidation.eOK, "Valid cookie");
}
function checkCookie(host, originAttributes) {

View File

@@ -316,7 +316,7 @@ class BackupTest(MarionetteTestCase):
false,
Date.now() / 1000 + 1,
{},
Ci.nsICookie.SAMESITE_UNSET,
Ci.nsICookie.SAMESITE_NONE,
Ci.nsICookie.SCHEME_HTTP
);
})().then(outerResolve);

View File

@@ -94,7 +94,7 @@ function addTestCookie(isSessionCookie) {
gCookieCounter++;
let name = `Cookie name: ${gCookieCounter}`;
const cv = Services.cookies.add(
Services.cookies.add(
COOKIE_HOST,
COOKIE_PATH,
name,
@@ -104,10 +104,9 @@ function addTestCookie(isSessionCookie) {
isSessionCookie,
Date.now() / 1000 + 1,
COOKIE_ORIGIN_ATTRIBUTES,
Ci.nsICookie.SAMESITE_UNSET,
Ci.nsICookie.SAMESITE_NONE,
Ci.nsICookie.SCHEME_HTTP
);
Assert.equal(cv.result, Ci.nsICookieValidation.eOK);
return name;
}

View File

@@ -12,7 +12,7 @@ const { FileTestUtils } = ChromeUtils.importESModule(
add_task(async function test_save_jsonview() {
// Create a cookie that will be valid for the given JSON Document
const cv = Services.cookies.add(
Services.cookies.add(
"example.org",
"/",
"cookieKey",
@@ -20,12 +20,11 @@ add_task(async function test_save_jsonview() {
false,
false,
false,
Date.now() + 24000 * 60 * 60,
Number.MAX_SAFE_INTEGER,
{},
Ci.nsICookie.SAMESITE_LAX,
Ci.nsICookie.SCHEME_HTTPS
);
Assert.equal(cv.result, Ci.nsICookieValidation.eOK);
// Set up the download
let MockFilePicker = SpecialPowers.MockFilePicker;

View File

@@ -7,7 +7,7 @@ const ORIGIN_DOMAIN = "browser_policy_clear_blocked_cookies.org";
add_task(async function setup() {
const expiry = Date.now() + 24 * 60 * 60;
let cv = Services.cookies.add(
Services.cookies.add(
HOSTNAME_DOMAIN,
"/",
"secure",
@@ -17,12 +17,10 @@ add_task(async function setup() {
false,
expiry,
{},
Ci.nsICookie.SAMESITE_UNSET,
Ci.nsICookie.SAMESITE_NONE,
Ci.nsICookie.SCHEME_HTTPS
);
Assert.equal(cv.result, Ci.nsICookieValidation.eOK);
cv = Services.cookies.add(
Services.cookies.add(
HOSTNAME_DOMAIN,
"/",
"insecure",
@@ -32,12 +30,10 @@ add_task(async function setup() {
false,
expiry,
{},
Ci.nsICookie.SAMESITE_UNSET,
Ci.nsICookie.SAMESITE_NONE,
Ci.nsICookie.SCHEME_HTTP
);
Assert.equal(cv.result, Ci.nsICookieValidation.eOK);
cv = Services.cookies.add(
Services.cookies.add(
ORIGIN_DOMAIN,
"/",
"secure",
@@ -47,12 +43,10 @@ add_task(async function setup() {
false,
expiry,
{},
Ci.nsICookie.SAMESITE_UNSET,
Ci.nsICookie.SAMESITE_NONE,
Ci.nsICookie.SCHEME_HTTPS
);
Assert.equal(cv.result, Ci.nsICookieValidation.eOK);
cv = Services.cookies.add(
Services.cookies.add(
ORIGIN_DOMAIN,
"/",
"insecure",
@@ -62,12 +56,10 @@ add_task(async function setup() {
false,
expiry,
{},
Ci.nsICookie.SAMESITE_UNSET,
Ci.nsICookie.SAMESITE_NONE,
Ci.nsICookie.SCHEME_HTTP
);
Assert.equal(cv.result, Ci.nsICookieValidation.eOK);
cv = Services.cookies.add(
Services.cookies.add(
"example.net",
"/",
"secure",
@@ -77,11 +69,9 @@ add_task(async function setup() {
false,
expiry,
{},
Ci.nsICookie.SAMESITE_UNSET,
Ci.nsICookie.SAMESITE_NONE,
Ci.nsICookie.SCHEME_HTTPS
);
Assert.equal(cv.result, Ci.nsICookieValidation.eOK);
await setupPolicyEngineWithJson({
policies: {
Cookies: {

View File

@@ -163,7 +163,7 @@ class TestFirefoxRefresh(MarionetteTestCase):
let expireTime = Math.floor(Date.now() / 1000) + 15 * 60;
Services.cookies.add(arguments[0], arguments[1], arguments[2], arguments[3],
true, false, false, expireTime, {},
Ci.nsICookie.SAMESITE_UNSET, Ci.nsICookie.SCHEME_UNSET);
Ci.nsICookie.SAMESITE_NONE, Ci.nsICookie.SCHEME_UNSET);
""",
script_args=(
self._cookieHost,

View File

@@ -190,7 +190,7 @@ add_task(async function () {
// Add some test cookies.
let uri = Services.io.newURI("https://example.com");
let uri2 = Services.io.newURI("https://example.org");
let cv = Services.cookies.add(
Services.cookies.add(
uri.host,
uri.pathQueryRef,
"test1",
@@ -200,12 +200,10 @@ add_task(async function () {
false,
Date.now() + 1000 * 60 * 60,
{},
Ci.nsICookie.SAMESITE_UNSET,
Ci.nsICookie.SAMESITE_NONE,
Ci.nsICookie.SCHEME_HTTPS
);
Assert.equal(cv.result, Ci.nsICookieValidation.eOK);
cv = Services.cookies.add(
Services.cookies.add(
uri.host,
uri.pathQueryRef,
"test2",
@@ -215,12 +213,10 @@ add_task(async function () {
false,
Date.now() + 1000 * 60 * 60,
{},
Ci.nsICookie.SAMESITE_UNSET,
Ci.nsICookie.SAMESITE_NONE,
Ci.nsICookie.SCHEME_HTTPS
);
Assert.equal(cv.result, Ci.nsICookieValidation.eOK);
cv = Services.cookies.add(
Services.cookies.add(
uri2.host,
uri2.pathQueryRef,
"test1",
@@ -230,13 +226,12 @@ add_task(async function () {
false,
Date.now() + 1000 * 60 * 60,
{},
Ci.nsICookie.SAMESITE_UNSET,
Ci.nsICookie.SAMESITE_NONE,
Ci.nsICookie.SCHEME_HTTPS
);
Assert.equal(cv.result, Ci.nsICookieValidation.eOK);
// Ensure that private browsing cookies are ignored.
cv = Services.cookies.add(
Services.cookies.add(
uri.host,
uri.pathQueryRef,
"test3",
@@ -246,10 +241,9 @@ add_task(async function () {
false,
Date.now() + 1000 * 60 * 60,
{ privateBrowsingId: 1 },
Ci.nsICookie.SAMESITE_UNSET,
Ci.nsICookie.SAMESITE_NONE,
Ci.nsICookie.SCHEME_HTTPS
);
Assert.equal(cv.result, Ci.nsICookieValidation.eOK);
// Get the exact creation date from the cookies (to avoid intermittents
// from minimal time differences, since we round up to minutes).

View File

@@ -47,7 +47,7 @@ async function openTabInUserContext(uri, userContextId) {
function simulateGoogleAccountSignIn(originAttributes = {}) {
// Manually set the cookie that is present when the client is signed in to a
// Google account.
const cv = Services.cookies.add(
Services.cookies.add(
"accounts.google.com",
"",
"SID",
@@ -57,10 +57,9 @@ function simulateGoogleAccountSignIn(originAttributes = {}) {
false,
Date.now() + 1000 * 60 * 60,
originAttributes,
Ci.nsICookie.SAMESITE_UNSET,
Ci.nsICookie.SAMESITE_NONE,
Ci.nsICookie.SCHEME_HTTPS
);
is(cv.result, Ci.nsICookieValidation.eOK, "Valid cookie");
}
add_setup(async function () {

View File

@@ -81,7 +81,7 @@ const TESTS = [
{
setUp() {
Services.cookies.removeAll();
const cv = Services.cookies.add(
Services.cookies.add(
"www.bing.com",
"/",
"SRCHS",
@@ -91,10 +91,9 @@ const TESTS = [
false,
Date.now() + 1000 * 60 * 60,
{},
Ci.nsICookie.SAMESITE_UNSET,
Ci.nsICookie.SAMESITE_NONE,
Ci.nsICookie.SCHEME_HTTPS
);
Assert.equal(cv.result, Ci.nsICookieValidation.eOK, "Valid cookie");
},
tearDown() {
Services.cookies.removeAll();

View File

@@ -190,7 +190,7 @@ const TESTS = [
{
setUp() {
Services.cookies.removeAll();
const cv = Services.cookies.add(
Services.cookies.add(
"www.example3.com",
"/",
"_dummyCookieName",
@@ -198,12 +198,11 @@ const TESTS = [
false,
false,
false,
Math.round(Date.now() / 1000) + 10 * 60 * 60,
Date.now() + 1000 * 60 * 60,
{},
Ci.nsICookie.SAMESITE_UNSET,
Ci.nsICookie.SAMESITE_NONE,
Ci.nsICookie.SCHEME_HTTPS
);
Assert.equal(cv.result, Ci.nsICookieValidation.eOK, "Valid cookie");
},
tearDown() {
Services.cookies.removeAll();
@@ -229,7 +228,45 @@ const TESTS = [
{
setUp() {
Services.cookies.removeAll();
const cv = Services.cookies.add(
Services.cookies.add(
"www.example3.com",
"/",
"_dummyCookieName",
"def=ghi&abc=tb",
false,
false,
false,
Date.now() + 1000 * 60 * 60,
{},
Ci.nsICookie.SAMESITE_NONE,
Ci.nsICookie.SCHEME_HTTPS
);
},
tearDown() {
Services.cookies.removeAll();
},
title: "Tagged follow-on with cookie param at end",
trackingUrl:
"https://www.example3.com/search?q=test&a=next&dummyExtraCodeParamName=xyz",
expectedSearchCountEntry: "example3:tagged-follow-on:tb",
expectedAdKey: "example3:tagged-follow-on",
adUrls: ["https://www.example.com/ad2"],
nonAdUrls: ["https://www.example.com/ad3"],
impression: {
provider: "example3",
tagged: "true",
partner_code: "tb",
source: "unknown",
is_shopping_page: "false",
is_private: "false",
shopping_tab_displayed: "false",
is_signed_in: "false",
},
},
{
setUp() {
Services.cookies.removeAll();
Services.cookies.add(
"www.example4.com",
"/",
"_dummyCookieName",
@@ -237,12 +274,11 @@ const TESTS = [
false,
false,
false,
Math.round(Date.now() / 1000) + 10 * 60 * 60,
Date.now() + 1000 * 60 * 60,
{},
Ci.nsICookie.SAMESITE_UNSET,
Ci.nsICookie.SAMESITE_NONE,
Ci.nsICookie.SCHEME_HTTPS
);
Assert.equal(cv.result, Ci.nsICookieValidation.eOK, "Valid cookie");
},
tearDown() {
Services.cookies.removeAll();
@@ -277,9 +313,9 @@ const TESTS = [
false,
false,
false,
Math.round(Date.now() / 1000) + 10 * 60 * 60,
Date.now() + 1000 * 60 * 60,
{},
Ci.nsICookie.SAMESITE_UNSET,
Ci.nsICookie.SAMESITE_NONE,
Ci.nsICookie.SCHEME_HTTPS
);
},

View File

@@ -71,7 +71,7 @@ var SessionCookiesInternal = {
cookie.originAttributes?.partitionKey?.length > 0;
try {
const cv = Services.cookies.add(
Services.cookies.add(
cookie.host,
cookie.path || "",
cookie.name || "",
@@ -81,20 +81,10 @@ var SessionCookiesInternal = {
/* isSession = */ true,
expiry,
cookie.originAttributes || {},
// If sameSite is undefined, we are migrating from a pre bug 1955685 session).
cookie.sameSite === undefined
? Ci.nsICookie.SAMESITE_NONE
: cookie.sameSite,
cookie.sameSite || Ci.nsICookie.SAMESITE_NONE,
cookie.schemeMap || Ci.nsICookie.SCHEME_HTTPS,
isPartitioned
);
if (cv.result !== Ci.nsICookieValidation.eOK) {
console.error(
`CookieService::Add failed with error '${cv.result}' for cookie ${JSON.stringify(
cookie
)}.`
);
}
} catch (ex) {
console.error(
`CookieService::Add failed with error '${ex}' for cookie ${JSON.stringify(
@@ -267,7 +257,9 @@ var CookieStore = {
jscookie.originAttributes = cookie.originAttributes;
}
jscookie.sameSite = cookie.sameSite;
if (cookie.sameSite) {
jscookie.sameSite = cookie.sameSite;
}
if (cookie.schemeMap) {
jscookie.schemeMap = cookie.schemeMap;

View File

@@ -8,7 +8,6 @@ function createTestState() {
path: "/",
name: `name${r}`,
value: `value${r}`,
sameSite: Ci.nsICookie.SAMESITE_UNSET,
};
let state = {

View File

@@ -27,12 +27,12 @@ add_task(async function runTest() {
let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, TEST_URL);
// Add a partitioned cookie.
const cv = Services.cookies.add(
Services.cookies.add(
TEST_HOST,
"/",
"foo",
"bar",
true,
false,
false,
true,
MAX_EXPIRY,
@@ -41,8 +41,6 @@ add_task(async function runTest() {
Ci.nsICookie.SCHEME_HTTPS,
true
);
is(cv.result, Ci.nsICookieValidation.eOK, "Valid cookie");
await TabStateFlusher.flush(tab.linkedBrowser);
// Get the sessionstore state for the window.

View File

@@ -5,7 +5,7 @@ const MAX_EXPIRY = Math.pow(2, 62);
function addCookie(scheme, secure = false) {
let cookie = createTestCookie(scheme, secure);
const cv = Services.cookies.add(
Services.cookies.add(
cookie.host,
cookie.path,
cookie.name,
@@ -15,10 +15,9 @@ function addCookie(scheme, secure = false) {
/* isSession = */ true,
MAX_EXPIRY,
/* originAttributes = */ {},
Ci.nsICookie.SAMESITE_UNSET,
Ci.nsICookie.SAMESITE_NONE,
Ci.nsICookie.SCHEME_HTTPS
);
is(cv.result, Ci.nsICookieValidation.eOK, "Valid cookie");
return cookie;
}

View File

@@ -24,7 +24,7 @@ async function verifyRestore(url, sameSiteSetting) {
// Add a cookie with specific same-site setting.
let r = Math.floor(Math.random() * MAX_EXPIRY);
const cv = Services.cookies.add(
Services.cookies.add(
url,
"/",
"name" + r,
@@ -39,8 +39,6 @@ async function verifyRestore(url, sameSiteSetting) {
? Ci.nsICookie.SCHEME_HTTPS
: Ci.nsICookie.SCHEME_HTTP
);
is(cv.result, Ci.nsICookieValidation.eOK, "Valid cookie");
await TabStateFlusher.flush(tab.linkedBrowser);
// Get the sessionstore state for the window.
@@ -81,11 +79,11 @@ async function verifyRestore(url, sameSiteSetting) {
*/
add_task(async function () {
// Test for various possible values of cookie.sameSite and schemeMap.
await verifyRestore(TEST_HTTP_URL, Ci.nsICookie.SAMESITE_UNSET);
await verifyRestore(TEST_HTTP_URL, Ci.nsICookie.SAMESITE_NONE);
await verifyRestore(TEST_HTTP_URL, Ci.nsICookie.SAMESITE_LAX);
await verifyRestore(TEST_HTTP_URL, Ci.nsICookie.SAMESITE_STRICT);
await verifyRestore(TEST_HTTPS_URL, Ci.nsICookie.SAMESITE_UNSET);
await verifyRestore(TEST_HTTPS_URL, Ci.nsICookie.SAMESITE_NONE);
await verifyRestore(TEST_HTTPS_URL, Ci.nsICookie.SAMESITE_LAX);
await verifyRestore(TEST_HTTPS_URL, Ci.nsICookie.SAMESITE_STRICT);
});

View File

@@ -9,7 +9,6 @@ const COOKIE = {
name: "test1",
value: "yes1",
path: "/browser/browser/components/sessionstore/test/",
sameSite: Ci.nsICookie.SAMESITE_UNSET,
};
const SESSION_DATA = JSON.stringify({
version: ["sessionrestore", 1],
@@ -59,7 +58,6 @@ const SESSION_DATA = JSON.stringify({
value: "yes1",
path: "/browser/browser/components/sessionstore/test/",
name: "test1",
sameSite: Ci.nsICookie.SAMESITE_UNSET,
},
],
},
@@ -122,7 +120,6 @@ const SESSION_DATA_OA = JSON.stringify({
value: "yes1",
path: "/browser/browser/components/sessionstore/test/",
name: "test1",
sameSite: Ci.nsICookie.SAMESITE_UNSET,
originAttributes: {
addonId: "",
inIsolatedMozBrowser: false,

View File

@@ -314,7 +314,6 @@
@RESPATH@/res/locale/layout/MediaDocument.properties
@RESPATH@/res/locale/layout/xmlparser.properties
@RESPATH@/res/locale/dom/dom.properties
@RESPATH@/res/locale/necko/necko.properties
#ifdef XP_MACOSX
@RESPATH@/res/MainMenu.nib/
#endif

View File

@@ -136,8 +136,8 @@ add_task(async function testInvalidSameSiteMessage() {
await checkConsoleOutputForWarningGroup(hud, [
`▼︎⚠ ${COOKIE_GROUP} 2`,
`| ${message2}`,
`| ${message1}`,
`| ${message2}`,
]);
// Source map are being resolved in background and we might have

View File

@@ -4785,9 +4785,7 @@ static const char* gPropertiesFiles[nsContentUtils::PropertiesFile_COUNT] = {
"chrome://global/locale/security/security.properties",
"chrome://necko/locale/necko.properties",
"resource://gre/res/locale/layout/HtmlForm.properties",
"resource://gre/res/locale/dom/dom.properties",
"resource://gre/res/locale/necko/necko.properties",
};
"resource://gre/res/locale/dom/dom.properties"};
/* static */
nsresult nsContentUtils::EnsureStringBundle(PropertiesFile aFile) {

View File

@@ -1312,7 +1312,6 @@ class nsContentUtils {
eNECKO_PROPERTIES,
eFORMS_PROPERTIES_en_US,
eDOM_PROPERTIES_en_US,
eNECKO_PROPERTIES_en_US,
PropertiesFile_COUNT
};
static nsresult ReportToConsole(

View File

@@ -14,7 +14,6 @@
#include "mozilla/net/CookieParser.h"
#include "mozilla/Components.h"
#include "mozilla/net/CookieCommons.h"
#include "mozilla/net/CookieValidation.h"
#include "mozilla/net/CookieServiceParent.h"
#include "mozilla/net/NeckoParent.h"
#include "mozilla/Unused.h"
@@ -356,9 +355,10 @@ bool CookieStoreParent::SetRequestOnMainThread(
const nsAString& aValue, bool aSession, int64_t aExpires,
const nsAString& aPath, int32_t aSameSite, bool aPartitioned,
const nsID& aOperationID) {
AssertIsOnMainThread();
MOZ_ASSERT(NS_IsMainThread());
nsresult rv;
bool requireMatch = false;
NS_ConvertUTF16toUTF8 domain(aDomain);
nsAutoCString domainWithDot;
@@ -379,6 +379,7 @@ bool CookieStoreParent::SetRequestOnMainThread(
if (NS_FAILED(rv)) {
return false;
}
requireMatch = true;
}
domainWithDot.Append(domain);
@@ -413,28 +414,18 @@ bool CookieStoreParent::SetRequestOnMainThread(
notificationWatcher->CallbackWhenNotified(aOperationID, notificationCb);
OriginAttributes attrs(aOriginAttributes);
nsCOMPtr<nsICookieValidation> validation;
rv = service->AddNative(
aCookieURI, domainWithDot, NS_ConvertUTF16toUTF8(aPath),
NS_ConvertUTF16toUTF8(aName), NS_ConvertUTF16toUTF8(aValue),
/* secure: */ true,
/* http-only: */ false, aSession, aSession ? INT64_MAX : aExpires, &attrs,
aSameSite, nsICookie::SCHEME_HTTPS, aPartitioned, /* from http: */ false,
&aOperationID, getter_AddRefs(validation));
&aOperationID, [&](mozilla::net::CookieStruct& aCookieStruct) -> bool {
return CookieParser::CheckCookieStruct(aCookieStruct, aCookieURI, ""_ns,
domain, requireMatch, false) ==
CookieParser::NoRejection;
});
if (NS_WARN_IF(NS_FAILED(rv))) {
if (rv == NS_ERROR_ILLEGAL_VALUE && validation &&
CookieValidation::Cast(validation)->Result() !=
nsICookieValidation::eOK) {
RefPtr<ContentParent> contentParent = aParent->GetContentParent();
if (contentParent) {
contentParent->KillHard(
"CookieStore does not accept invalid cookies in the parent "
"process");
}
}
return false;
}

View File

@@ -12,7 +12,7 @@ const RESOURCE_URL =
add_task(async function test_fetch_defaults_to_credentialless() {
// Ensure cookie is set up:
let expiry = Date.now() / 1000 + 24 * 60 * 60;
const cv = Services.cookies.add(
Services.cookies.add(
"example.com",
"/",
"foo",
@@ -22,10 +22,9 @@ add_task(async function test_fetch_defaults_to_credentialless() {
false,
expiry,
{},
Ci.nsICookie.SAMESITE_UNSET,
Ci.nsICookie.SAMESITE_NONE,
Ci.nsICookie.SCHEME_HTTPS
);
is(cv.result, Ci.nsICookieValidation.eOK, "Valid cookie");
// Explicitly send cookie header by using `same-origin` in the init dict, to
// ensure cookies are stored correctly and can be sent.

View File

@@ -156,7 +156,6 @@
@BINPATH@/res/locale/layout/MediaDocument.properties
@BINPATH@/res/locale/layout/xmlparser.properties
@BINPATH@/res/locale/dom/dom.properties
@BINPATH@/res/locale/necko/necko.properties
#ifndef MOZ_ANDROID_EXCLUDE_FONTS
@BINPATH@/res/fonts/*

View File

@@ -1808,10 +1808,6 @@ pref("extensions.install_origins.enabled", false);
pref("extensions.browser_style_mv3.supported", false);
pref("extensions.browser_style_mv3.same_as_mv2", false);
// If set to true, browser.cookies.set() will throw exceptions if the cookie is
// invalid. Otherwise, a warning message will be shown in the console.
pref("extensions.cookie.rejectWhenInvalid", false);
// Experimental Inference API
#ifdef NIGHTLY_BUILD
pref("extensions.ml.enabled", true);

View File

@@ -206,6 +206,61 @@ void CookieCommons::NotifyRejected(nsIURI* aHostURI, nsIChannel* aChannel,
aRejectedReason);
}
bool CookieCommons::CheckPathSize(const CookieStruct& aCookieData) {
return aCookieData.path().Length() <= kMaxBytesPerPath;
}
bool CookieCommons::CheckNameAndValueSize(const CookieStruct& aCookieData) {
// reject cookie if it's over the size limit, per RFC2109
return (aCookieData.name().Length() + aCookieData.value().Length()) <=
kMaxBytesPerCookie;
}
bool CookieCommons::CheckName(const CookieStruct& aCookieData) {
const char illegalNameCharacters[] = {
0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x0A, 0x0B, 0x0C, 0x0D,
0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19,
0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x3B, 0x3D, 0x7F, 0x00};
const auto* start = aCookieData.name().BeginReading();
const auto* end = aCookieData.name().EndReading();
auto charFilter = [&](unsigned char c) {
if (StaticPrefs::network_cookie_blockUnicode() && c >= 0x80) {
return true;
}
return std::find(std::begin(illegalNameCharacters),
std::end(illegalNameCharacters),
c) != std::end(illegalNameCharacters);
};
return std::find_if(start, end, charFilter) == end;
}
bool CookieCommons::CheckValue(const CookieStruct& aCookieData) {
// reject cookie if value contains an RFC 6265 disallowed character - see
// https://bugzilla.mozilla.org/show_bug.cgi?id=1191423
// NOTE: this is not the full set of characters disallowed by 6265 - notably
// 0x09, 0x20, 0x22, 0x2C, and 0x5C are missing from this list.
const char illegalCharacters[] = {
0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x0A, 0x0B, 0x0C,
0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x3B, 0x7F, 0x00};
const auto* start = aCookieData.value().BeginReading();
const auto* end = aCookieData.value().EndReading();
auto charFilter = [&](unsigned char c) {
if (StaticPrefs::network_cookie_blockUnicode() && c >= 0x80) {
return true;
}
return std::find(std::begin(illegalCharacters), std::end(illegalCharacters),
c) != std::end(illegalCharacters);
};
return std::find_if(start, end, charFilter) == end;
}
// static
bool CookieCommons::CheckCookiePermission(nsIChannel* aChannel,
CookieStruct& aCookieData) {
@@ -1016,16 +1071,5 @@ int64_t CookieCommons::MaybeReduceExpiry(int64_t aCurrentTimeInSec,
return aExpiryInSec;
}
// static
bool CookieCommons::IsSubdomainOf(const nsACString& a, const nsACString& b) {
if (a == b) {
return true;
}
if (a.Length() > b.Length()) {
return a[a.Length() - b.Length() - 1] == '.' && StringEndsWith(a, b);
}
return false;
}
} // namespace net
} // namespace mozilla

View File

@@ -57,6 +57,8 @@ static const char kPrefCookiePurgeAge[] = "network.cookie.purgeAge";
static const uint32_t kMaxCookiesPerHost = 180;
static const uint32_t kCookieQuotaPerHost = 150;
static const uint32_t kMaxNumberOfCookies = 3000;
static const uint32_t kMaxBytesPerCookie = 4096;
static const uint32_t kMaxBytesPerPath = 1024;
static const int64_t kCookiePurgeAge =
int64_t(30 * 24 * 60 * 60) * PR_USEC_PER_SEC; // 30 days in microseconds
@@ -89,6 +91,14 @@ class CookieCommons final {
uint32_t aRejectedReason,
CookieOperation aOperation);
static bool CheckPathSize(const CookieStruct& aCookieData);
static bool CheckNameAndValueSize(const CookieStruct& aCookieData);
static bool CheckName(const CookieStruct& aCookieData);
static bool CheckValue(const CookieStruct& aCookieData);
static bool CheckCookiePermission(nsIChannel* aChannel,
CookieStruct& aCookieData);
@@ -177,10 +187,6 @@ class CookieCommons final {
// Return a reduced expiry attribute value if needed.
static int64_t MaybeReduceExpiry(int64_t aCurrentTimeInSec,
int64_t aExpiryInSec);
// returns true if 'a' is equal to or a subdomain of 'b',
// assuming no leading dots are present.
static bool IsSubdomainOf(const nsACString& a, const nsACString& b);
};
} // namespace net

View File

@@ -5,9 +5,9 @@
#include "CookieParser.h"
#include "CookieLogging.h"
#include "CookieValidation.h"
#include "mozilla/CheckedInt.h"
#include "mozilla/dom/nsMixedContentBlocker.h"
#include "mozilla/glean/NetwerkMetrics.h"
#include "mozilla/net/Cookie.h"
#include "mozilla/StaticPrefs_network.h"
@@ -21,7 +21,14 @@
constexpr char ATTRIBUTE_PATH[] = "path";
constexpr uint64_t ATTRIBUTE_MAX_LENGTH = 1024;
constexpr auto CONSOLE_CHIPS_CATEGORY = "cookiesCHIPS"_ns;
constexpr auto CONSOLE_OVERSIZE_CATEGORY = "cookiesOversize"_ns;
constexpr auto CONSOLE_REJECTION_CATEGORY = "cookiesRejection"_ns;
constexpr auto CONSOLE_SAMESITE_CATEGORY = "cookieSameSite"_ns;
constexpr auto CONSOLE_INVALID_ATTRIBUTE_CATEGORY = "cookieInvalidAttribute"_ns;
constexpr auto SAMESITE_MDN_URL =
"https://developer.mozilla.org/docs/Web/HTTP/Reference/Headers/Set-Cookie#"
u"samesitesamesite-value"_ns;
namespace mozilla {
namespace net {
@@ -36,10 +43,6 @@ CookieParser::CookieParser(nsIConsoleReportCollector* aCRC, nsIURI* aHostURI)
CookieParser::~CookieParser() {
MOZ_COUNT_DTOR(CookieParser);
if (mValidation) {
mValidation->ReportErrorsAndWarnings(mCRC, mHostURI);
}
#define COOKIE_LOGGING_WITH_NAME(category, x) \
CookieLogging::LogMessageToConsole( \
mCRC, mHostURI, nsIScriptError::errorFlag, category, x, \
@@ -54,11 +57,77 @@ CookieParser::~CookieParser() {
"CookieRejectedInvalidCharAttributes"_ns);
break;
case RejectedNoneRequiresSecure:
COOKIE_LOGGING_WITH_NAME(CONSOLE_SAMESITE_CATEGORY,
"CookieRejectedNonRequiresSecure2"_ns);
break;
case RejectedPartitionedRequiresSecure:
COOKIE_LOGGING_WITH_NAME(CONSOLE_REJECTION_CATEGORY,
"CookieRejectedPartitionedRequiresSecure"_ns);
break;
case RejectedEmptyNameAndValue:
CookieLogging::LogMessageToConsole(
mCRC, mHostURI, nsIScriptError::warningFlag,
CONSOLE_REJECTION_CATEGORY, "CookieRejectedEmptyNameAndValue"_ns,
nsTArray<nsString>());
break;
case RejectedNameValueOversize: {
AutoTArray<nsString, 2> params = {
NS_ConvertUTF8toUTF16(mCookieData.name())};
nsString size;
size.AppendInt(kMaxBytesPerCookie);
params.AppendElement(size);
CookieLogging::LogMessageToConsole(
mCRC, mHostURI, nsIScriptError::warningFlag,
CONSOLE_OVERSIZE_CATEGORY, "CookieOversize"_ns, params);
break;
}
case RejectedInvalidCharName:
COOKIE_LOGGING_WITH_NAME(CONSOLE_REJECTION_CATEGORY,
"CookieRejectedInvalidCharName"_ns);
break;
case RejectedInvalidDomain:
COOKIE_LOGGING_WITH_NAME(CONSOLE_REJECTION_CATEGORY,
"CookieRejectedInvalidDomain"_ns);
break;
case RejectedInvalidPrefix:
COOKIE_LOGGING_WITH_NAME(CONSOLE_REJECTION_CATEGORY,
"CookieRejectedInvalidPrefix"_ns);
break;
case RejectedInvalidPath:
COOKIE_LOGGING_WITH_NAME(CONSOLE_REJECTION_CATEGORY,
"CookieRejectedInvalidPath"_ns);
break;
case RejectedInvalidCharValue:
COOKIE_LOGGING_WITH_NAME(CONSOLE_REJECTION_CATEGORY,
"CookieRejectedInvalidCharValue"_ns);
break;
case RejectedHttpOnlyButFromScript:
COOKIE_LOGGING_WITH_NAME(CONSOLE_REJECTION_CATEGORY,
"CookieRejectedHttpOnlyButFromScript"_ns);
break;
case RejectedSecureButNonHttps:
COOKIE_LOGGING_WITH_NAME(CONSOLE_REJECTION_CATEGORY,
"CookieRejectedSecureButNonHttps"_ns);
break;
case RejectedForNonSameSiteness:
COOKIE_LOGGING_WITH_NAME(CONSOLE_SAMESITE_CATEGORY,
"CookieRejectedForNonSameSiteness"_ns);
break;
case RejectedForeignNoPartitionedError:
COOKIE_LOGGING_WITH_NAME(CONSOLE_CHIPS_CATEGORY,
"CookieForeignNoPartitionedError"_ns);
@@ -77,8 +146,7 @@ CookieParser::~CookieParser() {
#undef COOKIE_LOGGING_WITH_NAME
if (mRejection != NoRejection || !mValidation ||
mValidation->Result() != nsICookieValidation::eOK) {
if (mRejection != NoRejection || !mContainsCookie) {
return;
}
@@ -117,6 +185,29 @@ CookieParser::~CookieParser() {
AutoTArray<nsString, 1>{NS_ConvertUTF8toUTF16(mCookieData.name())});
}
if (mWarnings.mSameSiteNoneRequiresSecureForBeta) {
CookieLogging::LogMessageToConsole(
mCRC, mHostURI, nsIScriptError::warningFlag, CONSOLE_SAMESITE_CATEGORY,
"CookieRejectedNonRequiresSecureForBeta3"_ns,
AutoTArray<nsString, 2>{NS_ConvertUTF8toUTF16(mCookieData.name()),
SAMESITE_MDN_URL});
}
if (mWarnings.mSameSiteLaxForced) {
CookieLogging::LogMessageToConsole(
mCRC, mHostURI, nsIScriptError::infoFlag, CONSOLE_SAMESITE_CATEGORY,
"CookieLaxForced2"_ns,
AutoTArray<nsString, 1>{NS_ConvertUTF8toUTF16(mCookieData.name())});
}
if (mWarnings.mSameSiteLaxForcedForBeta) {
CookieLogging::LogMessageToConsole(
mCRC, mHostURI, nsIScriptError::warningFlag, CONSOLE_SAMESITE_CATEGORY,
"CookieLaxForcedForBeta2"_ns,
AutoTArray<nsString, 2>{NS_ConvertUTF8toUTF16(mCookieData.name()),
SAMESITE_MDN_URL});
}
if (mWarnings.mForeignNoPartitionedWarning) {
CookieLogging::LogMessageToConsole(
mCRC, mHostURI, nsIScriptError::warningFlag, CONSOLE_CHIPS_CATEGORY,
@@ -401,6 +492,43 @@ void CookieParser::ParseAttributes(nsCString& aCookieHeader,
}
}
// re-assign aCookieHeader, in case we need to process another cookie
aCookieHeader.Assign(Substring(cookieStart, cookieEnd));
// If same-site is explicitly set to 'none' but this is not a secure context,
// let's abort the parsing.
if (!mCookieData.isSecure() &&
mCookieData.sameSite() == nsICookie::SAMESITE_NONE) {
if (StaticPrefs::network_cookie_sameSite_noneRequiresSecure()) {
RejectCookie(RejectedNoneRequiresSecure);
return;
}
// Still warn about the missing Secure attribute when not enforcing.
mWarnings.mSameSiteNoneRequiresSecureForBeta = true;
}
// Ensure the partitioned cookie is set with the secure attribute if CHIPS
// is enabled.
if (StaticPrefs::network_cookie_CHIPS_enabled() &&
mCookieData.isPartitioned() && !mCookieData.isSecure()) {
RejectCookie(RejectedPartitionedRequiresSecure);
return;
}
if (mCookieData.sameSite() == nsICookie::SAMESITE_UNSET) {
bool laxByDefault =
StaticPrefs::network_cookie_sameSite_laxByDefault() &&
!nsContentUtils::IsURIInPrefList(
mHostURI, "network.cookie.sameSite.laxByDefault.disabledHosts");
if (laxByDefault) {
mWarnings.mSameSiteLaxForced = true;
} else if (StaticPrefs::
network_cookie_sameSite_laxByDefaultWarningsForBeta()) {
mWarnings.mSameSiteLaxForcedForBeta = true;
}
}
// Cookie accepted.
aAcceptedByParser = true;
}
@@ -439,14 +567,73 @@ nsAutoCString GetPathFromURI(nsIURI* aHostURI) {
} // namespace
// static
void CookieParser::FixPath(CookieStruct& aCookieData, nsIURI* aHostURI) {
bool CookieParser::CheckPath(CookieStruct& aCookieData, nsIURI* aHostURI,
CookieParser* aParser) {
// if a path is given, check the host has permission
if (aCookieData.path().IsEmpty() || aCookieData.path().First() != '/') {
nsAutoCString path = GetPathFromURI(aHostURI);
if (CheckAttributeSize(aCookieData.path(), ATTRIBUTE_PATH, path)) {
if (CheckAttributeSize(aCookieData.path(), ATTRIBUTE_PATH, path, aParser)) {
aCookieData.path() = path;
}
}
MOZ_ASSERT(CookieCommons::CheckPathSize(aCookieData));
return !aCookieData.path().Contains('\t');
}
// static
bool CookieParser::HasSecurePrefix(const nsACString& aString) {
return StringBeginsWith(aString, "__Secure-"_ns,
nsCaseInsensitiveCStringComparator);
}
// static
bool CookieParser::HasHostPrefix(const nsACString& aString) {
return StringBeginsWith(aString, "__Host-"_ns,
nsCaseInsensitiveCStringComparator);
}
// CheckPrefixes
//
// Reject cookies whose name starts with the magic prefixes from
// https://datatracker.ietf.org/doc/html/draft-ietf-httpbis-rfc6265bis
// if they do not meet the criteria required by the prefix.
//
// Must not be called until after CheckDomain() and CheckPath() have
// regularized and validated the CookieStruct values!
// static
bool CookieParser::CheckPrefixes(CookieStruct& aCookieData,
bool aSecureRequest) {
bool hasSecurePrefix = HasSecurePrefix(aCookieData.name());
bool hasHostPrefix = HasHostPrefix(aCookieData.name());
if (!hasSecurePrefix && !hasHostPrefix) {
// not one of the magic prefixes: carry on
return true;
}
if (!aSecureRequest || !aCookieData.isSecure()) {
// the magic prefixes may only be used from a secure request and
// the secure attribute must be set on the cookie
return false;
}
if (hasHostPrefix) {
// The host prefix requires that the path is "/" and that the cookie
// had no domain attribute. CheckDomain() and CheckPath() MUST be run
// first to make sure invalid attributes are rejected and to regularlize
// them. In particular all explicit domain attributes result in a host
// that starts with a dot, and if the host doesn't start with a dot it
// correctly matches the true host.
if (aCookieData.host()[0] == '.' ||
!aCookieData.path().EqualsLiteral("/")) {
return false;
}
}
return true;
}
bool CookieParser::ParseMaxAgeAttribute(const nsACString& aMaxage,
@@ -569,10 +756,24 @@ bool CookieParser::GetExpiry(CookieStruct& aCookieData,
return true;
}
// returns true if 'a' is equal to or a subdomain of 'b',
// assuming no leading dots are present.
static inline bool IsSubdomainOf(const nsACString& a, const nsACString& b) {
if (a == b) {
return true;
}
if (a.Length() > b.Length()) {
return a[a.Length() - b.Length() - 1] == '.' && StringEndsWith(a, b);
}
return false;
}
// processes domain attribute, and returns true if host has permission to set
// for this domain.
// static
void CookieParser::FixDomain(CookieStruct& aCookieData, nsIURI* aHostURI,
const nsACString& aBaseDomain,
bool aRequireHostMatch) {
bool CookieParser::CheckDomain(CookieStruct& aCookieData, nsIURI* aHostURI,
const nsACString& aBaseDomain,
bool aRequireHostMatch) {
// Note: The logic in this function is mirrored in
// toolkit/components/extensions/ext-cookies.js:checkSetCookiePermissions().
// If it changes, please update that function, or file a bug for someone
@@ -582,53 +783,47 @@ void CookieParser::FixDomain(CookieStruct& aCookieData, nsIURI* aHostURI,
nsAutoCString hostFromURI;
nsContentUtils::GetHostOrIPv6WithBrackets(aHostURI, hostFromURI);
// no domain specified, use hostFromURI
if (aCookieData.host().IsEmpty()) {
aCookieData.host() = hostFromURI;
return;
}
// if a domain is given, check the host has permission
if (!aCookieData.host().IsEmpty()) {
// Tolerate leading '.' characters, but not if it's otherwise an empty host.
if (aCookieData.host().Length() > 1 && aCookieData.host().First() == '.') {
aCookieData.host().Cut(0, 1);
}
nsCString cookieHost = aCookieData.host();
// switch to lowercase now, to avoid case-insensitive compares everywhere
ToLowerCase(aCookieData.host());
// Tolerate leading '.' characters, but not if it's otherwise an empty host.
if (cookieHost.Length() > 1 && cookieHost.First() == '.') {
cookieHost.Cut(0, 1);
}
// switch to lowercase now, to avoid case-insensitive compares everywhere
ToLowerCase(cookieHost);
if (aRequireHostMatch) {
// check whether the host is either an IP address, an alias such as
// 'localhost', an eTLD such as 'co.uk', or the empty string. in these
// cases, require an exact string match for the domain, and leave the cookie
// as a non-domain one. bug 105917 originally noted the requirement to deal
// with IP addresses.
if (hostFromURI.Equals(cookieHost)) {
aCookieData.host() = cookieHost;
if (aRequireHostMatch) {
return hostFromURI.Equals(aCookieData.host());
}
// If the match fails, we keep the aCookieData.Host() as it was. The
// Validator will reject the cookie with the correct reason.
return;
// ensure the proposed domain is derived from the base domain; and also
// that the host domain is derived from the proposed domain (per RFC2109).
if (IsSubdomainOf(aCookieData.host(), aBaseDomain) &&
IsSubdomainOf(hostFromURI, aCookieData.host())) {
// prepend a dot to indicate a domain cookie
aCookieData.host().InsertLiteral(".", 0);
return true;
}
/*
* note: RFC2109 section 4.3.2 requires that we check the following:
* that the portion of host not in domain does not contain a dot.
* this prevents hosts of the form x.y.co.nz from setting cookies in the
* entire .co.nz domain. however, it's only a only a partial solution and
* it breaks sites (IE doesn't enforce it), so we don't perform this check.
*/
return false;
}
// ensure the proposed domain is derived from the base domain; and also
// that the host domain is derived from the proposed domain (per RFC2109).
if (CookieCommons::IsSubdomainOf(cookieHost, aBaseDomain) &&
CookieCommons::IsSubdomainOf(hostFromURI, cookieHost)) {
// prepend a dot to indicate a domain cookie
cookieHost.InsertLiteral(".", 0);
aCookieData.host() = cookieHost;
}
/*
* note: RFC2109 section 4.3.2 requires that we check the following:
* that the portion of host not in domain does not contain a dot.
* this prevents hosts of the form x.y.co.nz from setting cookies in the
* entire .co.nz domain. however, it's only a only a partial solution and
* it breaks sites (IE doesn't enforce it), so we don't perform this check.
*/
// no domain specified, use hostFromURI
aCookieData.host() = hostFromURI;
return true;
}
static void RecordPartitionedTelemetry(const CookieStruct& aCookieData,
@@ -646,6 +841,90 @@ static void RecordPartitionedTelemetry(const CookieStruct& aCookieData,
}
}
// static
CookieParser::Rejection CookieParser::CheckCookieStruct(
CookieStruct& aCookieStruct, nsIURI* aHostURI,
const nsCString& aCookieString, const nsACString& aBaseDomain,
bool aRequireHostMatch, bool aFromHttp, CookieParser* aParser) {
// reject cookie if name and value are empty, per RFC6265bis
if (aCookieStruct.name().IsEmpty() && aCookieStruct.value().IsEmpty()) {
COOKIE_LOGFAILURE(SET_COOKIE, aHostURI, aCookieString,
"cookie name and value are empty");
return RejectedEmptyNameAndValue;
}
// reject cookie if it's over the size limit, per RFC2109
if (!CookieCommons::CheckNameAndValueSize(aCookieStruct)) {
COOKIE_LOGFAILURE(SET_COOKIE, aHostURI, aCookieString,
"cookie too big (> 4kb)");
return RejectedNameValueOversize;
}
if (!CookieCommons::CheckName(aCookieStruct)) {
COOKIE_LOGFAILURE(SET_COOKIE, aHostURI, aCookieString,
"invalid name character");
return RejectedInvalidCharName;
}
// domain & path checks
if (!CheckDomain(aCookieStruct, aHostURI, aBaseDomain, aRequireHostMatch)) {
COOKIE_LOGFAILURE(SET_COOKIE, aHostURI, aCookieString,
"failed the domain tests");
return RejectedInvalidDomain;
}
if (!CheckPath(aCookieStruct, aHostURI, aParser)) {
COOKIE_LOGFAILURE(SET_COOKIE, aHostURI, aCookieString,
"failed the path tests");
return RejectedInvalidPath;
}
// If a cookie is nameless, then its value must not start with
// `__Host-` or `__Secure-`
if (aCookieStruct.name().IsEmpty() &&
(HasSecurePrefix(aCookieStruct.value()) ||
HasHostPrefix(aCookieStruct.value()))) {
COOKIE_LOGFAILURE(SET_COOKIE, aHostURI, aCookieString,
"failed hidden prefix tests");
return RejectedInvalidPrefix;
}
bool potentiallyTrustworthy =
nsMixedContentBlocker::IsPotentiallyTrustworthyOrigin(aHostURI);
// magic prefix checks. MUST be run after CheckDomain() and CheckPath()
if (!CheckPrefixes(aCookieStruct, potentiallyTrustworthy)) {
COOKIE_LOGFAILURE(SET_COOKIE, aHostURI, aCookieString,
"failed the prefix tests");
return RejectedInvalidPrefix;
}
if (!CookieCommons::CheckValue(aCookieStruct)) {
COOKIE_LOGFAILURE(SET_COOKIE, aHostURI, aCookieString,
"invalid value character");
return RejectedInvalidCharValue;
}
// if the new cookie is httponly, make sure we're not coming from script
if (!aFromHttp && aCookieStruct.isHttpOnly()) {
COOKIE_LOGFAILURE(SET_COOKIE, aHostURI, aCookieString,
"cookie is httponly; coming from script");
return RejectedHttpOnlyButFromScript;
}
// If the new cookie is non-https and wants to set secure flag,
// browser have to ignore this new cookie.
// (draft-ietf-httpbis-cookie-alone section 3.1)
if (aCookieStruct.isSecure() && !potentiallyTrustworthy) {
COOKIE_LOGFAILURE(SET_COOKIE, aHostURI, aCookieString,
"non-https cookie can't set secure flag");
return RejectedSecureButNonHttps;
}
return NoRejection;
}
// processes a single cookie, and returns true if there are more cookies
// to be processed
void CookieParser::Parse(const nsACString& aBaseDomain, bool aRequireHostMatch,
@@ -653,7 +932,7 @@ void CookieParser::Parse(const nsACString& aBaseDomain, bool aRequireHostMatch,
const nsACString& aDateHeader, bool aFromHttp,
bool aIsForeignAndNotAddon, bool aPartitionedOnly,
bool aIsInPrivateBrowsing, bool aOn3pcbException) {
MOZ_ASSERT(!mValidation);
MOZ_ASSERT(!mContainsCookie);
// init expiryTime such that session cookies won't prematurely expire
mCookieData.expiry() = INT64_MAX;
@@ -686,8 +965,38 @@ void CookieParser::Parse(const nsACString& aBaseDomain, bool aRequireHostMatch,
mCookieData.isSession() = true;
}
FixDomain(mCookieData, mHostURI, aBaseDomain, aRequireHostMatch);
FixPath(mCookieData, mHostURI);
// We count SetCookie operations in the parent process only for HTTP set
// cookies to prevent double counting.
if (XRE_IsParentProcess() || !aFromHttp) {
RecordPartitionedTelemetry(mCookieData, aIsForeignAndNotAddon);
}
auto result =
CheckCookieStruct(mCookieData, mHostURI, mCookieString, aBaseDomain,
aRequireHostMatch, aFromHttp, this);
if (result != NoRejection) {
RejectCookie(result);
return;
}
// If the new cookie is same-site but in a cross site context,
// browser must ignore the cookie.
bool laxByDefault =
StaticPrefs::network_cookie_sameSite_laxByDefault() &&
!nsContentUtils::IsURIInPrefList(
mHostURI, "network.cookie.sameSite.laxByDefault.disabledHosts");
uint32_t sameSite = mCookieData.sameSite();
if (sameSite == nsICookie::SAMESITE_UNSET) {
sameSite =
laxByDefault ? nsICookie::SAMESITE_LAX : nsICookie::SAMESITE_NONE;
}
if (sameSite != nsICookie::SAMESITE_NONE && aIsForeignAndNotAddon) {
COOKIE_LOGFAILURE(SET_COOKIE, mHostURI, mCookieString,
"failed the samesite tests");
RejectCookie(RejectedForNonSameSiteness);
return;
}
// If the cookie is on the 3pcd exception list, we apply partitioned
// attribute to the cookie.
@@ -712,6 +1021,8 @@ void CookieParser::Parse(const nsACString& aBaseDomain, bool aRequireHostMatch,
(aIsInPrivateBrowsing &&
StaticPrefs::
network_cookie_cookieBehavior_optInPartitioning_pbmode())) {
COOKIE_LOGFAILURE(SET_COOKIE, mHostURI, mCookieString,
"foreign cookies must be partitioned");
RejectCookie(RejectedForeignNoPartitionedError);
return;
}
@@ -719,20 +1030,7 @@ void CookieParser::Parse(const nsACString& aBaseDomain, bool aRequireHostMatch,
mWarnings.mForeignNoPartitionedWarning = true;
}
mValidation = CookieValidation::ValidateInContext(
mCookieData, mHostURI, aBaseDomain, aRequireHostMatch, aFromHttp,
aIsForeignAndNotAddon, aPartitionedOnly, aIsInPrivateBrowsing);
MOZ_ASSERT(mValidation);
if (mValidation->Result() != nsICookieValidation::eOK) {
return;
}
// We count SetCookie operations in the parent process only for HTTP set
// cookies to prevent double counting.
if (XRE_IsParentProcess() || !aFromHttp) {
RecordPartitionedTelemetry(mCookieData, aIsForeignAndNotAddon);
}
mContainsCookie = true;
}
void CookieParser::RejectCookie(Rejection aRejection) {

View File

@@ -8,10 +8,9 @@
#include "CookieCommons.h"
#include "CookieValidation.h"
#include "mozilla/net/NeckoChannelParams.h"
#include "nsCOMPtr.h"
#include "nsTArray.h"
#include "nsCOMPtr.h"
class nsIConsoleReportCollector;
class nsIURI;
@@ -26,7 +25,18 @@ class CookieParser final {
NoRejection,
RejectedInvalidCharAttributes,
RejectedNoneRequiresSecure,
RejectedPartitionedRequiresSecure,
RejectedEmptyNameAndValue,
RejectedNameValueOversize,
RejectedInvalidCharName,
RejectedInvalidDomain,
RejectedInvalidPrefix,
RejectedInvalidPath,
RejectedInvalidCharValue,
RejectedHttpOnlyButFromScript,
RejectedSecureButNonHttps,
RejectedForNonSameSiteness,
RejectedForeignNoPartitionedError,
RejectedByPermissionManager,
RejectedNonsecureOverSecure,
@@ -44,7 +54,8 @@ class CookieParser final {
bool aIsInPrivateBrowsing, bool aOn3pcbException);
bool ContainsCookie() const {
return mValidation && mValidation->Result() == nsICookieValidation::eOK;
MOZ_ASSERT_IF(mContainsCookie, mRejection == NoRejection);
return mContainsCookie;
}
void RejectCookie(Rejection aRejection);
@@ -59,6 +70,13 @@ class CookieParser final {
// Public for testing
bool ParseMaxAgeAttribute(const nsACString& aMaxage, int64_t* aValue);
static Rejection CheckCookieStruct(CookieStruct& aCookieStruct,
nsIURI* aHostURI,
const nsCString& aCookieString,
const nsACString& aBaseDomain,
bool aRequireHostMatch, bool aFromHttp,
CookieParser* aParser = nullptr);
private:
static void GetTokenValue(nsACString::const_char_iterator& aIter,
nsACString::const_char_iterator& aEndIter,
@@ -73,19 +91,26 @@ class CookieParser final {
const nsACString& aMaxage, int64_t aCurrentTime,
const nsACString& aDateHeader, bool aFromHttp);
static bool CheckPath(CookieStruct& aCookieData, nsIURI* aHostURI,
CookieParser* aParser = nullptr);
static bool CheckAttributeSize(const nsACString& currentValue,
const char* aAttribute,
const nsACString& aValue,
CookieParser* aParser = nullptr);
static void FixPath(CookieStruct& aCookieData, nsIURI* aHostURI);
static void FixDomain(CookieStruct& aCookieData, nsIURI* aHostURI,
const nsACString& aBaseDomain, bool aRequireHostMatch);
static bool CheckDomain(CookieStruct& aCookieData, nsIURI* aHostURI,
const nsACString& aBaseDomain,
bool aRequireHostMatch);
static bool HasSecurePrefix(const nsACString& aString);
static bool HasHostPrefix(const nsACString& aString);
static bool CheckPrefixes(CookieStruct& aCookieData, bool aSecureRequest);
nsCOMPtr<nsIConsoleReportCollector> mCRC;
nsCOMPtr<nsIURI> mHostURI;
// True if the parsing succeeded.
bool mContainsCookie = false;
Rejection mRejection = NoRejection;
RefPtr<CookieValidation> mValidation;
struct Warnings {
nsTArray<const char*> mAttributeOversize;
@@ -93,6 +118,9 @@ class CookieParser final {
bool mInvalidSameSiteAttribute = false;
bool mInvalidMaxAgeAttribute = false;
bool mSameSiteNoneRequiresSecureForBeta = false;
bool mSameSiteLaxForced = false;
bool mSameSiteLaxForcedForBeta = false;
bool mForeignNoPartitionedWarning = false;
} mWarnings;

View File

@@ -8,7 +8,6 @@
#include "CookieLogging.h"
#include "CookieParser.h"
#include "CookieService.h"
#include "CookieValidation.h"
#include "mozilla/AppShutdown.h"
#include "mozilla/ClearOnShutdown.h"
#include "mozilla/Components.h"
@@ -136,6 +135,8 @@ namespace net {
static StaticRefPtr<CookieService> gCookieService;
constexpr auto CONSOLE_REJECTION_CATEGORY = "cookiesRejection"_ns;
namespace {
// Return false if the cookie should be ignored for the current channel.
@@ -712,67 +713,17 @@ CookieService::Add(const nsACString& aHost, const nsACString& aPath,
bool aIsSecure, bool aIsHttpOnly, bool aIsSession,
int64_t aExpiry, JS::Handle<JS::Value> aOriginAttributes,
int32_t aSameSite, nsICookie::schemeType aSchemeMap,
bool aIsPartitioned, JSContext* aCx,
nsICookieValidation** aValidation) {
NS_ENSURE_ARG_POINTER(aCx);
NS_ENSURE_ARG_POINTER(aValidation);
bool aIsPartitioned, JSContext* aCx) {
OriginAttributes attrs;
if (!aOriginAttributes.isObject() || !attrs.Init(aCx, aOriginAttributes)) {
return NS_ERROR_INVALID_ARG;
}
nsCOMPtr<nsICookieValidation> validation;
nsresult rv =
AddInternal(nullptr, aHost, aPath, aName, aValue, aIsSecure, aIsHttpOnly,
aIsSession, aExpiry, &attrs, aSameSite, aSchemeMap,
aIsPartitioned, /* from-http: */ true, nullptr,
/* reject when invalid: */ true, getter_AddRefs(validation));
if (rv != NS_ERROR_ILLEGAL_VALUE || !validation ||
CookieValidation::Cast(validation)->Result() ==
nsICookieValidation::eOK) {
validation.forget(aValidation);
return rv;
}
validation.forget(aValidation);
return NS_OK;
}
NS_IMETHODIMP
CookieService::AddForAddOn(const nsACString& aHost, const nsACString& aPath,
const nsACString& aName, const nsACString& aValue,
bool aIsSecure, bool aIsHttpOnly, bool aIsSession,
int64_t aExpiry,
JS::Handle<JS::Value> aOriginAttributes,
int32_t aSameSite, nsICookie::schemeType aSchemeMap,
bool aIsPartitioned, JSContext* aCx,
nsICookieValidation** aValidation) {
NS_ENSURE_ARG_POINTER(aCx);
NS_ENSURE_ARG_POINTER(aValidation);
OriginAttributes attrs;
if (!aOriginAttributes.isObject() || !attrs.Init(aCx, aOriginAttributes)) {
return NS_ERROR_INVALID_ARG;
}
nsCOMPtr<nsICookieValidation> validation;
nsresult rv = AddInternal(nullptr, aHost, aPath, aName, aValue, aIsSecure,
aIsHttpOnly, aIsSession, aExpiry, &attrs, aSameSite,
aSchemeMap, aIsPartitioned, /* from-http: */
true, nullptr, /* reject when invalid: */ false,
getter_AddRefs(validation));
if (rv != NS_ERROR_ILLEGAL_VALUE || !validation ||
CookieValidation::Cast(validation)->Result() ==
nsICookieValidation::eOK) {
validation.forget(aValidation);
return rv;
}
validation.forget(aValidation);
return NS_OK;
return AddNative(nullptr, aHost, aPath, aName, aValue, aIsSecure, aIsHttpOnly,
aIsSession, aExpiry, &attrs, aSameSite, aSchemeMap,
aIsPartitioned, /* from-http: */ true, nullptr,
[](CookieStruct&) -> bool { return true; });
}
NS_IMETHODIMP_(nsresult)
@@ -783,24 +734,7 @@ CookieService::AddNative(nsIURI* aCookieURI, const nsACString& aHost,
OriginAttributes* aOriginAttributes, int32_t aSameSite,
nsICookie::schemeType aSchemeMap, bool aIsPartitioned,
bool aFromHttp, const nsID* aOperationID,
nsICookieValidation** aValidation) {
return AddInternal(aCookieURI, aHost, aPath, aName, aValue, aIsSecure,
aIsHttpOnly, aIsSession, aExpiry, aOriginAttributes,
aSameSite, aSchemeMap, aIsPartitioned, aFromHttp,
aOperationID,
/* reject when invalid: */ true, aValidation);
}
nsresult CookieService::AddInternal(
nsIURI* aCookieURI, const nsACString& aHost, const nsACString& aPath,
const nsACString& aName, const nsACString& aValue, bool aIsSecure,
bool aIsHttpOnly, bool aIsSession, int64_t aExpiry,
OriginAttributes* aOriginAttributes, int32_t aSameSite,
nsICookie::schemeType aSchemeMap, bool aIsPartitioned, bool aFromHttp,
const nsID* aOperationID, bool aRejectWhenInvalid,
nsICookieValidation** aValidation) {
NS_ENSURE_ARG_POINTER(aValidation);
const std::function<bool(CookieStruct&)>& aCheck) {
if (NS_WARN_IF(!aOriginAttributes)) {
return NS_ERROR_FAILURE;
}
@@ -827,11 +761,8 @@ nsresult CookieService::AddInternal(
aIsHttpOnly, aIsSession, aIsSecure, aIsPartitioned,
aSameSite, aSchemeMap);
RefPtr<CookieValidation> cv = CookieValidation::Validate(cookieData);
if (aRejectWhenInvalid && cv->Result() != nsICookieValidation::eOK) {
cv.forget(aValidation);
return NS_ERROR_ILLEGAL_VALUE;
if (!aCheck(cookieData)) {
return NS_ERROR_FAILURE;
}
RefPtr<Cookie> cookie = Cookie::Create(cookieData, *aOriginAttributes);
@@ -842,8 +773,6 @@ nsresult CookieService::AddInternal(
currentTimeInUsec, aCookieURI, VoidCString(), aFromHttp,
!aOriginAttributes->mPartitionKey.IsEmpty(), nullptr,
aOperationID);
cv.forget(aValidation);
return NS_OK;
}
@@ -1720,11 +1649,20 @@ bool CookieService::SetCookiesFromIPC(const nsACString& aBaseDomain,
int64_t currentTimeInUsec = PR_Now();
for (const CookieStruct& cookieData : aCookies) {
RefPtr<CookieValidation> validation = CookieValidation::ValidateForHost(
cookieData, aHostURI, aBaseDomain, false, aFromHttp);
MOZ_ASSERT(validation);
if (!CookieCommons::CheckPathSize(cookieData)) {
return false;
}
if (validation->Result() != nsICookieValidation::eOK) {
// reject cookie if it's over the size limit, per RFC2109
if (!CookieCommons::CheckNameAndValueSize(cookieData)) {
return false;
}
if (!CookieCommons::CheckName(cookieData)) {
return false;
}
if (!CookieCommons::CheckValue(cookieData)) {
return false;
}

View File

@@ -140,17 +140,6 @@ class CookieService final : public nsICookieService,
// private browsing.
RefPtr<CookieStorage> mPersistentStorage;
RefPtr<CookieStorage> mPrivateStorage;
private:
nsresult AddInternal(nsIURI* aCookieURI, const nsACString& aHost,
const nsACString& aPath, const nsACString& aName,
const nsACString& aValue, bool aIsSecure,
bool aIsHttpOnly, bool aIsSession, int64_t aExpiry,
OriginAttributes* aOriginAttributes, int32_t aSameSite,
nsICookie::schemeType aSchemeMap, bool aIsPartitioned,
bool aFromHttp, const nsID* aOperationID,
bool aRejectWhenInvalid,
nsICookieValidation** aValidation);
};
} // namespace net

View File

@@ -1,559 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* 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/. */
#include "CookieValidation.h"
#include "CookieLogging.h"
#include "CookieService.h"
#include "mozilla/dom/nsMixedContentBlocker.h"
#include "mozilla/StaticPrefs_network.h"
constexpr uint32_t kMaxBytesPerCookie = 4096;
constexpr uint32_t kMaxBytesPerDomain = 1024;
constexpr uint32_t kMaxBytesPerPath = 1024;
using namespace mozilla::net;
NS_IMPL_ISUPPORTS(CookieValidation, nsICookieValidation)
CookieValidation::CookieValidation(const CookieStruct& aCookieData)
: mCookieData(aCookieData) {}
// static
already_AddRefed<CookieValidation> CookieValidation::Validate(
const CookieStruct& aCookieData) {
RefPtr<CookieValidation> cv = new CookieValidation(aCookieData);
cv->ValidateInternal();
return cv.forget();
}
// static
already_AddRefed<CookieValidation> CookieValidation::ValidateForHost(
const CookieStruct& aCookieData, nsIURI* aHostURI,
const nsACString& aBaseDomain, bool aRequireHostMatch, bool aFromHttp) {
RefPtr<CookieValidation> cv = new CookieValidation(aCookieData);
cv->ValidateForHostInternal(aHostURI, aBaseDomain, aRequireHostMatch,
aFromHttp);
return cv.forget();
}
// static
already_AddRefed<CookieValidation> CookieValidation::ValidateInContext(
const CookieStruct& aCookieData, nsIURI* aHostURI,
const nsACString& aBaseDomain, bool aRequireHostMatch, bool aFromHttp,
bool aIsForeignAndNotAddon, bool aPartitionedOnly,
bool aIsInPrivateBrowsing) {
RefPtr<CookieValidation> cv = new CookieValidation(aCookieData);
cv->ValidateInContextInternal(aHostURI, aBaseDomain, aRequireHostMatch,
aFromHttp, aIsForeignAndNotAddon,
aPartitionedOnly, aIsInPrivateBrowsing);
return cv.forget();
}
void CookieValidation::ValidateInternal() {
MOZ_ASSERT(mResult == eOK);
// reject cookie if name and value are empty, per RFC6265bis
if (mCookieData.name().IsEmpty() && mCookieData.value().IsEmpty()) {
mResult = eRejectedEmptyNameAndValue;
return;
}
// reject cookie if it's over the size limit, per RFC2109
if (!CheckNameAndValueSize(mCookieData)) {
mResult = eRejectedNameValueOversize;
return;
}
if (!CheckName(mCookieData)) {
mResult = eRejectedInvalidCharName;
return;
}
if (!CheckValue(mCookieData)) {
mResult = eRejectedInvalidCharValue;
return;
}
if (mCookieData.path().Length() > kMaxBytesPerPath) {
mResult = eRejectedAttributePathOversize;
return;
}
if (mCookieData.path().Contains('\t')) {
mResult = eRejectedInvalidPath;
return;
}
if (mCookieData.host().Length() > kMaxBytesPerDomain) {
mResult = eRejectedAttributeDomainOversize;
return;
}
// If a cookie is nameless, then its value must not start with
// `__Host-` or `__Secure-`
if (mCookieData.name().IsEmpty() && (HasSecurePrefix(mCookieData.value()) ||
HasHostPrefix(mCookieData.value()))) {
mResult = eRejectedInvalidPrefix;
return;
}
// If same-site is explicitly set to 'none' but this is not a secure context,
// let's abort the parsing.
if (!mCookieData.isSecure() &&
mCookieData.sameSite() == nsICookie::SAMESITE_NONE) {
if (StaticPrefs::network_cookie_sameSite_noneRequiresSecure()) {
mResult = eRejectedNoneRequiresSecure;
return;
}
// Still warn about the missing Secure attribute when not enforcing.
mWarnings.mSameSiteNoneRequiresSecureForBeta = true;
}
// This part checks if the caleers have set the expiry value to max 400 days.
if (!mCookieData.isSession()) {
int64_t maxageCap = StaticPrefs::network_cookie_maxageCap();
int64_t currentTimeInSec = PR_Now() / PR_USEC_PER_SEC;
int64_t expiry = mCookieData.expiry() / PR_USEC_PER_SEC;
if (maxageCap && expiry > currentTimeInSec + maxageCap) {
mResult = eRejectedAttributeExpiryOversize;
return;
}
}
}
void CookieValidation::ValidateForHostInternal(nsIURI* aHostURI,
const nsACString& aBaseDomain,
bool aRequireHostMatch,
bool aFromHttp) {
MOZ_ASSERT(mResult == eOK);
ValidateInternal();
if (mResult != eOK) {
return;
}
if (!aBaseDomain.IsEmpty() &&
!CheckDomain(mCookieData, aHostURI, aBaseDomain, aRequireHostMatch)) {
mResult = eRejectedInvalidDomain;
return;
}
// if the new cookie is httponly, make sure we're not coming from script
if (!aFromHttp && mCookieData.isHttpOnly()) {
mResult = eRejectedHttpOnlyButFromScript;
return;
}
bool potentiallyTrustworthy =
nsMixedContentBlocker::IsPotentiallyTrustworthyOrigin(aHostURI);
if (!CheckPrefixes(mCookieData, potentiallyTrustworthy)) {
mResult = eRejectedInvalidPrefix;
return;
}
// If the new cookie is non-https and wants to set secure flag,
// browser have to ignore this new cookie.
// (draft-ietf-httpbis-cookie-alone section 3.1)
if (mCookieData.isSecure() && !potentiallyTrustworthy) {
mResult = eRejectedSecureButNonHttps;
return;
}
if (mCookieData.sameSite() == nsICookie::SAMESITE_UNSET) {
bool laxByDefault =
StaticPrefs::network_cookie_sameSite_laxByDefault() &&
!nsContentUtils::IsURIInPrefList(
aHostURI, "network.cookie.sameSite.laxByDefault.disabledHosts");
if (laxByDefault) {
mWarnings.mSameSiteLaxForced = true;
} else if (StaticPrefs::
network_cookie_sameSite_laxByDefaultWarningsForBeta()) {
mWarnings.mSameSiteLaxForcedForBeta = true;
}
}
}
void CookieValidation::ValidateInContextInternal(
nsIURI* aHostURI, const nsACString& aBaseDomain, bool aRequireHostMatch,
bool aFromHttp, bool aIsForeignAndNotAddon, bool aPartitionedOnly,
bool aIsInPrivateBrowsing) {
MOZ_ASSERT(mResult == eOK);
ValidateForHostInternal(aHostURI, aBaseDomain, aRequireHostMatch, aFromHttp);
if (mResult != eOK) {
return;
}
// If the cookie is same-site but in a cross site context, browser must
// ignore the cookie.
bool laxByDefault =
StaticPrefs::network_cookie_sameSite_laxByDefault() &&
!nsContentUtils::IsURIInPrefList(
aHostURI, "network.cookie.sameSite.laxByDefault.disabledHosts");
uint32_t sameSite = mCookieData.sameSite();
if (sameSite == nsICookie::SAMESITE_UNSET) {
sameSite =
laxByDefault ? nsICookie::SAMESITE_LAX : nsICookie::SAMESITE_NONE;
}
if (sameSite != nsICookie::SAMESITE_NONE && aIsForeignAndNotAddon) {
mResult = eRejectedForNonSameSiteness;
return;
}
// Ensure the partitioned cookie is set with the secure attribute if CHIPS
// is enabled. This check should be part of ValidateInternal but it's not
// because of bug 1965880.
if (StaticPrefs::network_cookie_CHIPS_enabled() &&
mCookieData.isPartitioned() && !mCookieData.isSecure()) {
mResult = eRejectedPartitionedRequiresSecure;
return;
}
}
NS_IMETHODIMP
CookieValidation::GetResult(nsICookieValidation::ValidationError* aRetval) {
NS_ENSURE_ARG_POINTER(aRetval);
*aRetval = mResult;
return NS_OK;
}
// static
bool CookieValidation::CheckDomain(const CookieStruct& aCookieData,
nsIURI* aHostURI,
const nsACString& aBaseDomain,
bool aRequireHostMatch) {
// Note: The logic in this function is mirrored in
// toolkit/components/extensions/ext-cookies.js:checkSetCookiePermissions().
// If it changes, please update that function, or file a bug for someone
// else to do so.
if (aCookieData.host().IsEmpty()) {
return false;
}
// get host from aHostURI
nsAutoCString hostFromURI;
nsContentUtils::GetHostOrIPv6WithBrackets(aHostURI, hostFromURI);
// check whether the host is either an IP address, an alias such as
// 'localhost', an eTLD such as 'co.uk', or the empty string. in these
// cases, require an exact string match for the domain, and leave the cookie
// as a non-domain one. bug 105917 originally noted the requirement to deal
// with IP addresses.
if (aRequireHostMatch) {
return hostFromURI.Equals(aCookieData.host());
}
nsCString cookieHost = aCookieData.host();
// Tolerate leading '.' characters, but not if it's otherwise an empty host.
if (aCookieData.host().Length() > 1 && aCookieData.host().First() == '.') {
cookieHost.Cut(0, 1);
}
// ensure the proposed domain is derived from the base domain; and also
// that the host domain is derived from the proposed domain (per RFC2109).
if (CookieCommons::IsSubdomainOf(cookieHost, aBaseDomain) &&
CookieCommons::IsSubdomainOf(hostFromURI, cookieHost)) {
return true;
}
/*
* note: RFC2109 section 4.3.2 requires that we check the following:
* that the portion of host not in domain does not contain a dot.
* this prevents hosts of the form x.y.co.nz from setting cookies in the
* entire .co.nz domain. however, it's only a only a partial solution and
* it breaks sites (IE doesn't enforce it), so we don't perform this check.
*/
return false;
}
// static
bool CookieValidation::HasSecurePrefix(const nsACString& aString) {
return StringBeginsWith(aString, "__Secure-"_ns,
nsCaseInsensitiveCStringComparator);
}
// static
bool CookieValidation::HasHostPrefix(const nsACString& aString) {
return StringBeginsWith(aString, "__Host-"_ns,
nsCaseInsensitiveCStringComparator);
}
// CheckPrefixes
//
// Reject cookies whose name starts with the magic prefixes from
// https://datatracker.ietf.org/doc/html/draft-ietf-httpbis-rfc6265bis
// if they do not meet the criteria required by the prefix.
bool CookieValidation::CheckPrefixes(const CookieStruct& aCookieData,
bool aSecureRequest) {
bool hasSecurePrefix = HasSecurePrefix(aCookieData.name());
bool hasHostPrefix = HasHostPrefix(aCookieData.name());
if (!hasSecurePrefix && !hasHostPrefix) {
// not one of the magic prefixes: carry on
return true;
}
if (!aSecureRequest || !aCookieData.isSecure()) {
// the magic prefixes may only be used from a secure request and
// the secure attribute must be set on the cookie
return false;
}
if (hasHostPrefix) {
// The host prefix requires that the path is "/" and that the cookie had no
// domain attribute. FixDomain() and FixPath() from CookieParser MUST be
// run first to make sure invalid attributes are rejected and to
// regularlize them. In particular all explicit domain attributes result in
// a host that starts with a dot, and if the host doesn't start with a dot
// it correctly matches the true host.
if (aCookieData.host()[0] == '.' ||
!aCookieData.path().EqualsLiteral("/")) {
return false;
}
}
return true;
}
void CookieValidation::RetrieveErrorLogData(uint32_t* aFlags,
nsACString& aCategory,
nsACString& aKey,
nsTArray<nsString>& aParams) const {
MOZ_ASSERT(aFlags);
MOZ_ASSERT(aParams.IsEmpty());
*aFlags = nsIScriptError::errorFlag;
#define SET_LOG_DATA(category, x) \
aCategory = category; \
aKey = x; \
aParams.AppendElement(NS_ConvertUTF8toUTF16(mCookieData.name()));
switch (mResult) {
case eOK:
return;
case eRejectedEmptyNameAndValue: {
*aFlags = nsIScriptError::warningFlag;
aCategory.Assign(CONSOLE_REJECTION_CATEGORY);
aKey.Assign("CookieRejectedEmptyNameAndValue"_ns);
return;
}
case eRejectedNoneRequiresSecure: {
SET_LOG_DATA(CONSOLE_SAMESITE_CATEGORY,
"CookieRejectedNonRequiresSecure2"_ns);
return;
}
case eRejectedPartitionedRequiresSecure: {
SET_LOG_DATA(CONSOLE_REJECTION_CATEGORY,
"CookieRejectedPartitionedRequiresSecure"_ns);
return;
}
case eRejectedNameValueOversize: {
*aFlags = nsIScriptError::warningFlag;
aCategory.Assign(CONSOLE_OVERSIZE_CATEGORY);
aKey.Assign("CookieOversize"_ns);
aParams.AppendElement(NS_ConvertUTF8toUTF16(mCookieData.name()));
nsString size;
size.AppendInt(kMaxBytesPerCookie);
aParams.AppendElement(size);
return;
}
case eRejectedInvalidCharName: {
SET_LOG_DATA(CONSOLE_REJECTION_CATEGORY,
"CookieRejectedInvalidCharName"_ns);
return;
}
case eRejectedInvalidCharValue: {
SET_LOG_DATA(CONSOLE_REJECTION_CATEGORY,
"CookieRejectedInvalidCharValue"_ns);
return;
}
case eRejectedAttributePathOversize: {
SET_LOG_DATA(CONSOLE_REJECTION_CATEGORY,
"CookieRejectedAttributePathOversize"_ns);
return;
}
case eRejectedAttributeDomainOversize: {
SET_LOG_DATA(CONSOLE_REJECTION_CATEGORY,
"CookieRejectedAttributeDomainOversize"_ns);
return;
}
case eRejectedAttributeExpiryOversize: {
SET_LOG_DATA(CONSOLE_REJECTION_CATEGORY,
"CookieRejectedAttributeExpiryOversize"_ns);
return;
}
case eRejectedInvalidPath: {
SET_LOG_DATA(CONSOLE_REJECTION_CATEGORY, "CookieRejectedInvalidPath"_ns);
return;
}
case eRejectedInvalidDomain: {
SET_LOG_DATA(CONSOLE_REJECTION_CATEGORY,
"CookieRejectedInvalidDomain"_ns);
return;
}
case eRejectedInvalidPrefix: {
SET_LOG_DATA(CONSOLE_REJECTION_CATEGORY,
"CookieRejectedInvalidPrefix"_ns);
return;
}
case eRejectedHttpOnlyButFromScript: {
SET_LOG_DATA(CONSOLE_REJECTION_CATEGORY,
"CookieRejectedHttpOnlyButFromScript"_ns);
return;
}
case eRejectedSecureButNonHttps: {
SET_LOG_DATA(CONSOLE_REJECTION_CATEGORY,
"CookieRejectedSecureButNonHttps"_ns);
return;
}
case eRejectedForNonSameSiteness: {
SET_LOG_DATA(CONSOLE_SAMESITE_CATEGORY,
"CookieRejectedForNonSameSiteness"_ns);
return;
}
}
#undef SET_LOG_DATA
}
void CookieValidation::ReportErrorsAndWarnings(nsIConsoleReportCollector* aCRC,
nsIURI* aHostURI) const {
if (mResult != eOK) {
uint32_t flags;
nsAutoCString category;
nsAutoCString key;
nsTArray<nsString> params;
RetrieveErrorLogData(&flags, category, key, params);
CookieLogging::LogMessageToConsole(aCRC, aHostURI, flags, category, key,
params);
return;
}
if (mWarnings.mSameSiteNoneRequiresSecureForBeta) {
CookieLogging::LogMessageToConsole(
aCRC, aHostURI, nsIScriptError::warningFlag, CONSOLE_SAMESITE_CATEGORY,
"CookieRejectedNonRequiresSecureForBeta3"_ns,
AutoTArray<nsString, 2>{NS_ConvertUTF8toUTF16(mCookieData.name()),
SAMESITE_MDN_URL});
}
if (mWarnings.mSameSiteLaxForced) {
CookieLogging::LogMessageToConsole(
aCRC, aHostURI, nsIScriptError::infoFlag, CONSOLE_SAMESITE_CATEGORY,
"CookieLaxForced2"_ns,
AutoTArray<nsString, 1>{NS_ConvertUTF8toUTF16(mCookieData.name())});
}
if (mWarnings.mSameSiteLaxForcedForBeta) {
CookieLogging::LogMessageToConsole(
aCRC, aHostURI, nsIScriptError::warningFlag, CONSOLE_SAMESITE_CATEGORY,
"CookieLaxForcedForBeta2"_ns,
AutoTArray<nsString, 2>{NS_ConvertUTF8toUTF16(mCookieData.name()),
SAMESITE_MDN_URL});
}
}
NS_IMETHODIMP
CookieValidation::GetErrorString(nsAString& aResult) {
if (mResult == eOK) {
return NS_OK;
}
uint32_t flags;
nsAutoCString category;
nsAutoCString key;
nsTArray<nsString> params;
RetrieveErrorLogData(&flags, category, key, params);
return nsContentUtils::FormatLocalizedString(
nsContentUtils::eNECKO_PROPERTIES_en_US, key.get(), params, aResult);
}
// static
bool CookieValidation::CheckNameAndValueSize(const CookieStruct& aCookieData) {
// reject cookie if it's over the size limit, per RFC2109
return (aCookieData.name().Length() + aCookieData.value().Length()) <=
kMaxBytesPerCookie;
}
bool CookieValidation::CheckName(const CookieStruct& aCookieData) {
if (!aCookieData.name().IsEmpty() && (aCookieData.name().First() == 0x20 ||
aCookieData.name().Last() == 0x20)) {
return false;
}
const char illegalNameCharacters[] = {
0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x0A, 0x0B, 0x0C, 0x0D,
0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19,
0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x3B, 0x3D, 0x7F, 0x00};
const auto* start = aCookieData.name().BeginReading();
const auto* end = aCookieData.name().EndReading();
auto charFilter = [&](unsigned char c) {
if (StaticPrefs::network_cookie_blockUnicode() && c >= 0x80) {
return true;
}
return std::find(std::begin(illegalNameCharacters),
std::end(illegalNameCharacters),
c) != std::end(illegalNameCharacters);
};
return std::find_if(start, end, charFilter) == end;
}
bool CookieValidation::CheckValue(const CookieStruct& aCookieData) {
if (!aCookieData.value().IsEmpty() && (aCookieData.value().First() == 0x20 ||
aCookieData.value().Last() == 0x20)) {
return false;
}
// reject cookie if value contains an RFC 6265 disallowed character - see
// https://bugzilla.mozilla.org/show_bug.cgi?id=1191423
// NOTE: this is not the full set of characters disallowed by 6265 - notably
// 0x09, 0x20, 0x22, 0x2C, and 0x5C are missing from this list.
const char illegalCharacters[] = {
0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x0A, 0x0B, 0x0C,
0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x3B, 0x7F, 0x00};
const auto* start = aCookieData.value().BeginReading();
const auto* end = aCookieData.value().EndReading();
auto charFilter = [&](unsigned char c) {
if (StaticPrefs::network_cookie_blockUnicode() && c >= 0x80) {
return true;
}
return std::find(std::begin(illegalCharacters), std::end(illegalCharacters),
c) != std::end(illegalCharacters);
};
return std::find_if(start, end, charFilter) == end;
}

View File

@@ -1,100 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* 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/. */
#ifndef mozilla_net_CookieValidation_h
#define mozilla_net_CookieValidation_h
#include "nsICookieValidation.h"
#include "Cookie.h"
class nsIConsoleReportCollector;
namespace mozilla {
namespace net {
constexpr auto CONSOLE_CHIPS_CATEGORY = "cookiesCHIPS"_ns;
constexpr auto CONSOLE_OVERSIZE_CATEGORY = "cookiesOversize"_ns;
constexpr auto CONSOLE_REJECTION_CATEGORY = "cookiesRejection"_ns;
constexpr auto CONSOLE_SAMESITE_CATEGORY = "cookieSameSite"_ns;
constexpr auto SAMESITE_MDN_URL =
"https://developer.mozilla.org/docs/Web/HTTP/Reference/Headers/Set-Cookie#"
u"samesitesamesite-value"_ns;
class CookieValidation final : public nsICookieValidation {
NS_DECL_ISUPPORTS
NS_DECL_NSICOOKIEVALIDATION
public:
static already_AddRefed<CookieValidation> Validate(
const CookieStruct& aCookieData);
static already_AddRefed<CookieValidation> ValidateForHost(
const CookieStruct& aCookieData, nsIURI* aHostURI,
const nsACString& aBaseDomain, bool aRequireHostMatch, bool aFromHttp);
static already_AddRefed<CookieValidation> ValidateInContext(
const CookieStruct& aCookieData, nsIURI* aHostURI,
const nsACString& aBaseDomain, bool aRequireHostMatch, bool aFromHttp,
bool aIsForeignAndNotAddon, bool aPartitionedOnly,
bool aIsInPrivateBrowsing);
static CookieValidation* Cast(nsICookieValidation* aValidation) {
return static_cast<CookieValidation*>(aValidation);
}
nsICookieValidation::ValidationError Result() const { return mResult; }
void ReportErrorsAndWarnings(nsIConsoleReportCollector* aCRC,
nsIURI* aHostURI) const;
private:
explicit CookieValidation(const CookieStruct& aCookieData);
~CookieValidation() = default;
void ValidateInternal();
void ValidateForHostInternal(nsIURI* aHostURI, const nsACString& aBaseDomain,
bool aRequireHostMatch, bool aFromHttp);
void ValidateInContextInternal(
nsIURI* aHostURI, const nsACString& aBaseDomain, bool aRequireHostMatch,
bool aFromHttp, bool aIsForeignAndNotAddon, bool aPartitionedOnly,
bool aIsInPrivateBrowsing);
static bool CheckNameAndValueSize(const CookieStruct& aCookieData);
static bool CheckName(const CookieStruct& aCookieData);
static bool CheckValue(const CookieStruct& aCookieData);
static bool CheckDomain(const CookieStruct& aCookieData, nsIURI* aHostURI,
const nsACString& aBaseDomain,
bool aRequireHostMatch);
static bool CheckPrefixes(const CookieStruct& aCookieData,
bool aSecureRequest);
static bool HasSecurePrefix(const nsACString& aString);
static bool HasHostPrefix(const nsACString& aString);
CookieStruct mCookieData;
nsICookieValidation::ValidationError mResult = eOK;
void RetrieveErrorLogData(uint32_t* aFlags, nsACString& aCategory,
nsACString& aKey,
nsTArray<nsString>& aParams) const;
struct Warnings {
bool mSameSiteLaxForced = false;
bool mSameSiteLaxForcedForBeta = false;
bool mSameSiteNoneRequiresSecureForBeta = false;
} mWarnings;
};
} // namespace net
} // namespace mozilla
#endif // mozilla_net_CookieValidation_h

View File

@@ -15,7 +15,6 @@ XPIDL_SOURCES += [
"nsICookieNotification.idl",
"nsICookiePermission.idl",
"nsICookieService.idl",
"nsICookieValidation.idl",
"nsIThirdPartyCookieBlockingExceptionListService.idl",
]
@@ -35,7 +34,6 @@ EXPORTS.mozilla.net = [
"CookieServiceChild.h",
"CookieServiceParent.h",
"CookieStorage.h",
"CookieValidation.h",
"ThirdPartyCookieBlockingExceptions.h",
]
UNIFIED_SOURCES += [
@@ -51,7 +49,6 @@ UNIFIED_SOURCES += [
"CookieServiceChild.cpp",
"CookieServiceParent.cpp",
"CookieStorage.cpp",
"CookieValidation.cpp",
"ThirdPartyCookieBlockingExceptions.cpp",
]
XPCSHELL_TESTS_MANIFESTS += [

View File

@@ -1,5 +1,6 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* 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/. */

View File

@@ -19,8 +19,7 @@ class CookieStruct;
%}
[ptr] native OriginAttributesPtr(mozilla::OriginAttributes);
interface nsICookieValidation;
native CheckStructFunctionRef(const std::function< bool(mozilla::net::CookieStruct&) > &);
/**
* An optional interface for accessing or removing the cookies
@@ -133,42 +132,19 @@ interface nsICookieManager : nsISupports
* true if the cookie should be stored with the Partitioned attribute.
*/
[implicit_jscontext]
nsICookieValidation add(in AUTF8String aHost,
in AUTF8String aPath,
in ACString aName,
in AUTF8String aValue,
in boolean aIsSecure,
in boolean aIsHttpOnly,
in boolean aIsSession,
in int64_t aExpiry,
in jsval aOriginAttributes,
in int32_t aSameSite,
in nsICookie_schemeType aSchemeMap,
[optional] in boolean aIsPartitioned);
void add(in AUTF8String aHost,
in AUTF8String aPath,
in ACString aName,
in AUTF8String aValue,
in boolean aIsSecure,
in boolean aIsHttpOnly,
in boolean aIsSession,
in int64_t aExpiry,
in jsval aOriginAttributes,
in int32_t aSameSite,
in nsICookie_schemeType aSchemeMap,
[optional] in boolean aIsPartitioned);
/**
* Similar to the previous method but without validation as a blocker.
* This method is a temporary thing. See bug XXX.
*/
[implicit_jscontext]
nsICookieValidation addForAddOn(in AUTF8String aHost,
in AUTF8String aPath,
in ACString aName,
in AUTF8String aValue,
in boolean aIsSecure,
in boolean aIsHttpOnly,
in boolean aIsSession,
in int64_t aExpiry,
in jsval aOriginAttributes,
in int32_t aSameSite,
in nsICookie_schemeType aSchemeMap,
[optional] in boolean aIsPartitioned);
/**
* This method is the non-xpcom version of add(). In case of an invalid
* cookie, it returns a nsICookieValidation object and NS_ERROR_ILLEGAL_VALUE
* as error code.
*/
[notxpcom]
nsresult addNative(in nsIURI aCookieURI,
in AUTF8String aHost,
@@ -185,7 +161,7 @@ interface nsICookieManager : nsISupports
in boolean aIsPartitioned,
in boolean aFromHttp,
in nsIDPtr aOperationID,
out nsICookieValidation aValidation);
in CheckStructFunctionRef aCheckValid);
/**
* Find whether a given cookie already exists.

View File

@@ -1,34 +0,0 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* 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/. */
#include "nsISupports.idl"
[scriptable, builtinclass, uuid(79c99e25-8b06-4e68-8935-bdbe22fa4010)]
interface nsICookieValidation : nsISupports
{
cenum ValidationError : 32 {
eOK,
eRejectedEmptyNameAndValue,
eRejectedNameValueOversize,
eRejectedInvalidCharName,
eRejectedInvalidCharValue,
eRejectedInvalidPath,
eRejectedInvalidDomain,
eRejectedInvalidPrefix,
eRejectedNoneRequiresSecure,
eRejectedPartitionedRequiresSecure,
eRejectedHttpOnlyButFromScript,
eRejectedSecureButNonHttps,
eRejectedForNonSameSiteness,
eRejectedAttributePathOversize,
eRejectedAttributeDomainOversize,
eRejectedAttributeExpiryOversize,
};
readonly attribute nsICookieValidation_ValidationError result;
// This returns an empty string if the result is `eOK`.
readonly attribute AString errorString;
};

View File

@@ -101,8 +101,8 @@ add_task(async () => {
});
await validateTelemetryValues(
{
setCookies: 5,
setForeigns: 1,
setCookies: 6,
setForeigns: 2,
setPartitioneds: 3,
setForeignPartitioneds: 1,
},
@@ -121,8 +121,8 @@ add_task(async () => {
await validateTelemetryValues(
{
setCookies: 6,
setForeigns: 2,
setCookies: 8,
setForeigns: 4,
setPartitioneds: 4,
setForeignPartitioneds: 2,
},

View File

@@ -176,7 +176,7 @@ add_task(async _ => {
}
info("Let's set a cookie without scheme");
const cv = Services.cookies.add(
Services.cookies.add(
"example.org",
"/",
"a",
@@ -189,7 +189,6 @@ add_task(async _ => {
Ci.nsICookie.SAMESITE_LAX,
Ci.nsICookie.SCHEME_UNSET
);
Assert.equal(cv.result, Ci.nsICookieValidation.eOK, "Valid cookie");
let cookies = Services.cookies.getCookiesFromHost("example.org", {});
Assert.equal(cookies.length, 1, "We expect 1 cookie only");

View File

@@ -69,12 +69,6 @@ CookieRejectedInvalidPrefix=Cookie “%1$S” has been rejected for invalid pref
CookieRejectedInvalidPath=Cookie “%1$S” has been rejected for invalid path.
# LOCALIZATION NOTE (CookieRejectedInvalidCharValue): %1$S is the cookie name.
CookieRejectedInvalidCharValue=Cookie “%1$S” has been rejected for invalid characters in the value.
# LOCALIZATION NOTE (CookieRejectedAttributePathOversize): %1$S is the cookie name.
CookieRejectedAttributePathOversize=Cookie “%1$S” has been rejected because its path attribute is too big.
# LOCALIZATION NOTE (CookieRejectedAttributeDomainOversize): %1$S is the cookie name.
CookieRejectedAttributeDomainOversize=Cookie “%1$S” has been rejected because its path attribute is too big.
# LOCALIZATION NOTE (CookieRejectedAttributeExpiryOversize): %1$S is the cookie name.
CookieRejectedAttributeExpiryOversize=Cookie “%1$S” has been rejected because its expiration date is over the limit.
# LOCALIZATION NOTE (CookieRejectedHttpOnlyButFromScript): %1$S is the cookie name.
CookieRejectedHttpOnlyButFromScript=Cookie “%1$S” has been rejected because there is already an HTTP-Only cookie but script tried to store a new one.
# LOCALIZATION NOTE (CookieRejectedSecureButHttp): %1$S is the cookie name.

View File

@@ -5,7 +5,3 @@
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
JAR_MANIFESTS += ["jar.mn"]
RESOURCE_FILES.locale.necko += [
"en-US/necko.properties",
]

View File

@@ -24,7 +24,6 @@
#include "mozilla/Preferences.h"
#include "mozilla/Unused.h"
#include "mozilla/net/CookieJarSettings.h"
#include "mozilla/net/CookieValidation.h"
#include "Cookie.h"
#include "CookieParser.h"
#include "nsIURI.h"
@@ -263,7 +262,7 @@ TEST(TestCookie, TestCookieMain)
// test some variations of the domain & path, for different domains of
// a domain cookie
SetACookie(cookieService, "http://www.domain.com",
"test=domain; domain=domain.com; sameSite=lax");
"test=domain; domain=domain.com");
GetACookie(cookieService, "http://domain.com", cookie);
EXPECT_TRUE(CheckResult(cookie.get(), MUST_EQUAL, "test=domain"));
GetACookie(cookieService, "http://domain.com.", cookie);
@@ -758,29 +757,23 @@ TEST(TestCookie, TestCookieMain)
// first, ensure a clean slate
EXPECT_NS_SUCCEEDED(cookieMgr->RemoveAll());
nsCOMPtr<nsICookieValidation> cv;
// add some cookies
EXPECT_TRUE(NS_SUCCEEDED(cookieMgr2->AddNative(uri,
"cookiemgr.test"_ns, // domain
"/foo"_ns, // path
"test1"_ns, // name
"yes"_ns, // value
false, // is secure
false, // is httponly
true, // is session
INT64_MAX, // expiry time
&attrs, // originAttributes
nsICookie::SAMESITE_LAX,
nsICookie::SCHEME_HTTP,
false, // is partitioned
true, // from http
nullptr, // operation ID
getter_AddRefs(cv))));
EXPECT_TRUE(!!cv);
EXPECT_EQ(CookieValidation::Cast(cv)->Result(), nsICookieValidation::eOK);
EXPECT_TRUE(NS_SUCCEEDED(
cookieMgr2->AddNative(uri,
"cookiemgr.test"_ns, // domain
"/foo"_ns, // path
"test1"_ns, // name
"yes"_ns, // value
false, // is secure
false, // is httponly
true, // is session
INT64_MAX, // expiry time
&attrs, // originAttributes
nsICookie::SAMESITE_NONE, nsICookie::SCHEME_HTTPS,
false, // is partitioned
true, // from http
nullptr, // operation ID
[](CookieStruct&) -> bool { return true; })));
EXPECT_TRUE(NS_SUCCEEDED(
cookieMgr2->AddNative(uri,
"cookiemgr.test"_ns, // domain
@@ -792,33 +785,27 @@ TEST(TestCookie, TestCookieMain)
true, // is session
PR_Now() / PR_USEC_PER_SEC + 2, // expiry time
&attrs, // originAttributes
nsICookie::SAMESITE_LAX, nsICookie::SCHEME_HTTP,
nsICookie::SAMESITE_NONE, nsICookie::SCHEME_HTTPS,
false, // is partitioned
true, // from http
nullptr, // operation ID
getter_AddRefs(cv))));
EXPECT_TRUE(!!cv);
EXPECT_EQ(CookieValidation::Cast(cv)->Result(), nsICookieValidation::eOK);
EXPECT_TRUE(NS_SUCCEEDED(cookieMgr2->AddNative(uri,
"new.domain"_ns, // domain
"/rabbit"_ns, // path
"test3"_ns, // name
"yes"_ns, // value
false, // is secure
false, // is httponly
true, // is session
INT64_MAX, // expiry time
&attrs, // originAttributes
nsICookie::SAMESITE_LAX,
nsICookie::SCHEME_HTTP,
false, // is partitioned
true, // from http
nullptr, // operation ID
getter_AddRefs(cv))));
EXPECT_TRUE(!!cv);
EXPECT_EQ(CookieValidation::Cast(cv)->Result(), nsICookieValidation::eOK);
[](CookieStruct&) -> bool { return true; })));
EXPECT_TRUE(NS_SUCCEEDED(
cookieMgr2->AddNative(uri,
"new.domain"_ns, // domain
"/rabbit"_ns, // path
"test3"_ns, // name
"yes"_ns, // value
false, // is secure
false, // is httponly
true, // is session
INT64_MAX, // expiry time
&attrs, // originAttributes
nsICookie::SAMESITE_NONE, nsICookie::SCHEME_HTTPS,
false, // is partitioned
true, // from http
nullptr, // operation ID
[](CookieStruct&) -> bool { return true; })));
// confirm using enumerator
nsTArray<RefPtr<nsICookie>> cookies;
EXPECT_NS_SUCCEEDED(cookieMgr->GetCookies(cookies));
@@ -1016,45 +1003,6 @@ TEST(TestCookie, TestCookieMain)
// *** speed tests
}
TEST(TestCookie, InvalidCharsInNameAndValue)
{
nsresult rv;
nsCOMPtr<nsICookieManager> cookieMgr =
do_GetService(NS_COOKIEMANAGER_CONTRACTID, &rv);
ASSERT_NS_SUCCEEDED(rv);
nsCOMPtr<nsIURI> uri;
NS_NewURI(getter_AddRefs(uri), "https://cookie.test"_ns);
mozilla::OriginAttributes attrs;
// Test some invalid chars
#define TEST_INVALID_CHARS(name, value, error) \
{ \
nsCOMPtr<nsICookieValidation> cv; \
EXPECT_EQ( \
cookieMgr->AddNative(uri, "cookiemgr.test"_ns, "/foo"_ns, name, value, \
false, false, true, INT64_MAX, &attrs, \
nsICookie::SAMESITE_LAX, nsICookie::SCHEME_HTTP, \
false, true, nullptr, getter_AddRefs(cv)), \
NS_ERROR_ILLEGAL_VALUE); \
EXPECT_TRUE(!!cv); \
EXPECT_EQ(CookieValidation::Cast(cv)->Result(), error); \
}
TEST_INVALID_CHARS(" test invalid name"_ns, "test valid value"_ns,
nsICookieValidation::eRejectedInvalidCharName)
TEST_INVALID_CHARS("test invalid name "_ns, "test valid value"_ns,
nsICookieValidation::eRejectedInvalidCharName)
TEST_INVALID_CHARS("test valid name"_ns, " test invalid value"_ns,
nsICookieValidation::eRejectedInvalidCharValue)
TEST_INVALID_CHARS("test valid name"_ns, "test invalid value "_ns,
nsICookieValidation::eRejectedInvalidCharValue)
#undef TEST_INVALID_CHARS
}
TEST(TestCookie, OnionSite)
{
Preferences::SetBool("dom.securecontext.allowlist_onions", true);

View File

@@ -114,7 +114,7 @@ addMessageListener("init", ({ domain }) => {
true,
Math.pow(2, 62),
{},
Ci.nsICookie.SAMESITE_UNSET,
Ci.nsICookie.SAMESITE_NONE,
Ci.nsICookie.SCHEME_HTTPS
);
is(

View File

@@ -6,7 +6,7 @@ function run_test() {
Assert.notEqual(cm, null, "Retrieving the cookie manager failed");
const time = new Date("Jan 1, 2030").getTime() / 1000;
const cv = cm.add(
cm.add(
"example.com",
"/",
"C",
@@ -16,10 +16,9 @@ function run_test() {
false,
time,
{},
Ci.nsICookie.SAMESITE_UNSET,
Ci.nsICookie.SAMESITE_NONE,
Ci.nsICookie.SCHEME_HTTPS
);
Assert.equal(cv.result, Ci.nsICookieValidation.eOK, "Valid cookie");
const now = Math.floor(new Date().getTime() / 1000);
var found = false;

View File

@@ -22,7 +22,7 @@ add_task(async () => {
// test that variants of 'baz.com' get normalized appropriately, but that
// malformed hosts are rejected
let cv = cm.add(
cm.add(
"baz.com",
"/",
"foo",
@@ -32,10 +32,9 @@ add_task(async () => {
true,
expiry,
{},
Ci.nsICookie.SAMESITE_UNSET,
Ci.nsICookie.SAMESITE_NONE,
Ci.nsICookie.SCHEME_HTTPS
);
Assert.equal(cv.result, Ci.nsICookieValidation.eOK);
Assert.equal(cm.countCookiesFromHost("baz.com"), 1);
Assert.equal(cm.countCookiesFromHost("BAZ.com"), 1);
Assert.equal(cm.countCookiesFromHost(".baz.com"), 1);
@@ -56,7 +55,7 @@ add_task(async () => {
Assert.equal(cm.countCookiesFromHost("baz.com"), 0);
// Test that 'baz.com' and 'baz.com.' are treated differently
cv = cm.add(
cm.add(
"baz.com.",
"/",
"foo",
@@ -66,10 +65,9 @@ add_task(async () => {
true,
expiry,
{},
Ci.nsICookie.SAMESITE_UNSET,
Ci.nsICookie.SAMESITE_NONE,
Ci.nsICookie.SCHEME_HTTPS
);
Assert.equal(cv.result, Ci.nsICookieValidation.eOK);
Assert.equal(cm.countCookiesFromHost("baz.com"), 0);
Assert.equal(cm.countCookiesFromHost("BAZ.com"), 0);
Assert.equal(cm.countCookiesFromHost(".baz.com"), 0);
@@ -82,7 +80,7 @@ add_task(async () => {
// test that domain cookies are illegal for IP addresses, aliases such as
// 'localhost', and eTLD's such as 'co.uk'
cv = cm.add(
cm.add(
"192.168.0.1",
"/",
"foo",
@@ -92,10 +90,9 @@ add_task(async () => {
true,
expiry,
{},
Ci.nsICookie.SAMESITE_UNSET,
Ci.nsICookie.SAMESITE_NONE,
Ci.nsICookie.SCHEME_HTTPS
);
Assert.equal(cv.result, Ci.nsICookieValidation.eOK);
Assert.equal(cm.countCookiesFromHost("192.168.0.1"), 1);
Assert.equal(cm.countCookiesFromHost("192.168.0.1."), 0);
do_check_throws(function () {
@@ -105,7 +102,7 @@ add_task(async () => {
cm.countCookiesFromHost(".192.168.0.1.");
}, Cr.NS_ERROR_ILLEGAL_VALUE);
cv = cm.add(
cm.add(
"localhost",
"/",
"foo",
@@ -115,10 +112,9 @@ add_task(async () => {
true,
expiry,
{},
Ci.nsICookie.SAMESITE_UNSET,
Ci.nsICookie.SAMESITE_NONE,
Ci.nsICookie.SCHEME_HTTPS
);
Assert.equal(cv.result, Ci.nsICookieValidation.eOK);
Assert.equal(cm.countCookiesFromHost("localhost"), 1);
Assert.equal(cm.countCookiesFromHost("localhost."), 0);
do_check_throws(function () {
@@ -128,7 +124,7 @@ add_task(async () => {
cm.countCookiesFromHost(".localhost.");
}, Cr.NS_ERROR_ILLEGAL_VALUE);
cv = cm.add(
cm.add(
"co.uk",
"/",
"foo",
@@ -138,10 +134,9 @@ add_task(async () => {
true,
expiry,
{},
Ci.nsICookie.SAMESITE_UNSET,
Ci.nsICookie.SAMESITE_NONE,
Ci.nsICookie.SCHEME_HTTPS
);
Assert.equal(cv.result, Ci.nsICookieValidation.eOK);
Assert.equal(cm.countCookiesFromHost("co.uk"), 1);
Assert.equal(cm.countCookiesFromHost("co.uk."), 0);
do_check_throws(function () {
@@ -201,7 +196,7 @@ add_task(async () => {
// test that an empty host to add() or remove() works,
// but a host of '.' doesn't
cv = cm.add(
cm.add(
"",
"/",
"foo2",
@@ -211,13 +206,12 @@ add_task(async () => {
true,
expiry,
{},
Ci.nsICookie.SAMESITE_UNSET,
Ci.nsICookie.SAMESITE_NONE,
Ci.nsICookie.SCHEME_HTTPS
);
Assert.equal(cv.result, Ci.nsICookieValidation.eOK);
Assert.equal(getCookieCount(), 1);
do_check_throws(function () {
const cv = cm.add(
cm.add(
".",
"/",
"foo3",
@@ -227,10 +221,9 @@ add_task(async () => {
true,
expiry,
{},
Ci.nsICookie.SAMESITE_UNSET,
Ci.nsICookie.SAMESITE_NONE,
Ci.nsICookie.SCHEME_HTTPS
);
Assert.equal(cv.result, Ci.nsICookieValidation.eOK);
}, Cr.NS_ERROR_ILLEGAL_VALUE);
Assert.equal(getCookieCount(), 1);

View File

@@ -11,7 +11,7 @@ add_task(async () => {
// Test our handling of host names with a single character at the beginning
// followed by a dot.
const cv = Services.cookies.add(
Services.cookies.add(
"e.com",
"/",
"foo",
@@ -21,10 +21,9 @@ add_task(async () => {
true,
expiry,
{},
Ci.nsICookie.SAMESITE_UNSET,
Ci.nsICookie.SAMESITE_NONE,
Ci.nsICookie.SCHEME_HTTP
);
Assert.equal(cv.result, Ci.nsICookieValidation.eOK, "Valid cookie");
Assert.equal(Services.cookies.countCookiesFromHost("e.com"), 1);
CookieXPCShellUtils.createServer({ hosts: ["e.com"] });

View File

@@ -9,7 +9,7 @@ add_task(async () => {
// Test our handling of host names with a single character consisting only
// of a single character
const cv = Services.cookies.add(
Services.cookies.add(
"a",
"/",
"foo",
@@ -19,10 +19,9 @@ add_task(async () => {
true,
expiry,
{},
Ci.nsICookie.SAMESITE_UNSET,
Ci.nsICookie.SAMESITE_NONE,
Ci.nsICookie.SCHEME_HTTP
);
Assert.equal(cv.result, Ci.nsICookieValidation.eOK, "Valid cookie");
Assert.equal(Services.cookies.countCookiesFromHost("a"), 1);
CookieXPCShellUtils.createServer({ hosts: ["a"] });

View File

@@ -140,7 +140,7 @@ async function run_test_1() {
db.close();
// Attempt to insert a cookie with the same (name, host, path) triplet.
const cv = Services.cookies.add(
Services.cookies.add(
cookie.host,
cookie.path,
cookie.name,
@@ -150,10 +150,9 @@ async function run_test_1() {
cookie.isSession,
cookie.expiry,
{},
Ci.nsICookie.SAMESITE_UNSET,
Ci.nsICookie.SAMESITE_NONE,
Ci.nsICookie.SCHEME_HTTPS
);
Assert.equal(cv.result, Ci.nsICookieValidation.eOK, "Valid cookie");
// Check that the cookie service accepted the new cookie.
Assert.equal(Services.cookies.countCookiesFromHost(cookie.host), 1);

View File

@@ -36,7 +36,7 @@ add_task(async function test_chips_migration() {
false,
false,
{},
Ci.nsICookie.SAMESITE_UNSET,
Ci.nsICookie.SAMESITE_NONE,
Ci.nsICookie.SCHEME_UNSET,
false // isPartitioned
);
@@ -56,7 +56,7 @@ add_task(async function test_chips_migration() {
false,
false,
{},
Ci.nsICookie.SAMESITE_UNSET,
Ci.nsICookie.SAMESITE_NONE,
Ci.nsICookie.SCHEME_UNSET,
true // isPartitioned
);
@@ -76,7 +76,7 @@ add_task(async function test_chips_migration() {
false,
false,
{},
Ci.nsICookie.SAMESITE_UNSET,
Ci.nsICookie.SAMESITE_NONE,
Ci.nsICookie.SCHEME_UNSET,
true // isPartitioned
);
@@ -96,7 +96,7 @@ add_task(async function test_chips_migration() {
false,
false,
{ partitionKey: "(https,example.com)" },
Ci.nsICookie.SAMESITE_UNSET,
Ci.nsICookie.SAMESITE_NONE,
Ci.nsICookie.SCHEME_UNSET,
true // isPartitioned
);

View File

@@ -71,7 +71,7 @@ add_task(async () => {
}, Cr.NS_ERROR_NOT_AVAILABLE);
do_check_throws(function () {
const cv = Services.cookies.add(
Services.cookies.add(
"foo.com",
"",
"oh4",
@@ -81,10 +81,9 @@ add_task(async () => {
false,
0,
{},
Ci.nsICookie.SAMESITE_UNSET,
Ci.nsICookie.SAMESITE_NONE,
Ci.nsICookie.SCHEME_HTTPS
);
Assert.equal(cv.result, Ci.nsICookieValidation.eOK, "Valid cookie");
}, Cr.NS_ERROR_NOT_AVAILABLE);
do_check_throws(function () {

View File

@@ -48,7 +48,7 @@ add_task(async function test_purge_counting() {
Assert.equal(validCookies, totalCookies);
// add a valid cookie - this triggers the purge
const cv = Services.cookies.add(
Services.cookies.add(
"cookie-host0.com", // any host
"/", // path
"cookie-name-x",
@@ -58,10 +58,9 @@ add_task(async function test_purge_counting() {
true, // isSession
futureExpiry,
{}, // OA
Ci.nsICookie.SAMESITE_UNSET, // SameSite
Ci.nsICookie.SAMESITE_NONE, // SameSite
Ci.nsICookie.SCHEME_HTTPS
);
Assert.equal(cv.result, Ci.nsICookieValidation.eOK, "Valid cookie");
// check that we purge all the expired cookies and not the unexpired
validCookies = Services.cookies.cookies.length;

View File

@@ -55,7 +55,7 @@ add_task(async function test_purge_counting_per_host() {
Assert.equal(validCookies, cookieCountMax);
// add a cookie - this will trigger the purge
const cv = Services.cookies.add(
Services.cookies.add(
host,
"/", // path
"cookie-name-x",
@@ -65,10 +65,9 @@ add_task(async function test_purge_counting_per_host() {
true, // isSession
futureExpiry,
{}, // OA
Ci.nsICookie.SAMESITE_UNSET, // SameSite
Ci.nsICookie.SAMESITE_NONE, // SameSite
Ci.nsICookie.SCHEME_HTTPS
);
Assert.equal(cv.result, Ci.nsICookieValidation.eOK, "Valid cookie");
// check that we purge down to the cookieMax (plus the cookie added)
validCookies = Services.cookies.countCookiesFromHost(host);

View File

@@ -67,7 +67,7 @@ function* do_run_test() {
// Test that expired cookies for a domain are evicted before live ones.
let shortExpiry = Math.floor(Date.now() / 1000 + 2);
setCookies("captchart.com", 49, futureExpiry);
let cv = Services.cookies.add(
Services.cookies.add(
"captchart.com",
"",
"test100",
@@ -77,16 +77,14 @@ function* do_run_test() {
false,
shortExpiry,
{},
Ci.nsICookie.SAMESITE_UNSET,
Ci.nsICookie.SAMESITE_NONE,
Ci.nsICookie.SCHEME_HTTPS
);
Assert.equal(cv.result, Ci.nsICookieValidation.eOK, "Valid cookie");
do_timeout(2100, continue_test);
yield;
Assert.equal(countCookies("captchart.com", "captchart.com"), 50);
cv = Services.cookies.add(
Services.cookies.add(
"captchart.com",
"",
"test200",
@@ -96,11 +94,9 @@ function* do_run_test() {
false,
futureExpiry,
{},
Ci.nsICookie.SAMESITE_UNSET,
Ci.nsICookie.SAMESITE_NONE,
Ci.nsICookie.SCHEME_HTTPS
);
Assert.equal(cv.result, Ci.nsICookieValidation.eOK, "Valid cookie");
Assert.equal(countCookies("captchart.com", "captchart.com"), 50);
for (let cookie of Services.cookies.getCookiesFromHost("captchart.com", {})) {
@@ -113,7 +109,7 @@ function* do_run_test() {
// set 'aNumber' cookies with host 'aHost', with distinct names.
function setCookies(aHost, aNumber, aExpiry) {
for (let i = 0; i < aNumber; ++i) {
const cv = Services.cookies.add(
Services.cookies.add(
aHost,
"",
"test" + i,
@@ -123,10 +119,9 @@ function setCookies(aHost, aNumber, aExpiry) {
false,
aExpiry,
{},
Ci.nsICookie.SAMESITE_UNSET,
Ci.nsICookie.SAMESITE_NONE,
Ci.nsICookie.SCHEME_HTTPS
);
Assert.equal(cv.result, Ci.nsICookieValidation.eOK, "Valid cookie");
}
}

View File

@@ -191,7 +191,7 @@ function set_cookies(begin, end, expiry) {
let beginTime;
for (let i = begin; i < end; ++i) {
let host = "eviction." + i + ".tests";
const cv = Services.cookies.add(
Services.cookies.add(
host,
"",
"test",
@@ -201,10 +201,9 @@ function set_cookies(begin, end, expiry) {
false,
expiry,
{},
Ci.nsICookie.SAMESITE_UNSET,
Ci.nsICookie.SAMESITE_NONE,
Ci.nsICookie.SCHEME_HTTPS
);
Assert.equal(cv.result, Ci.nsICookieValidation.eOK, "Valid cookie");
if (i == begin) {
beginTime = get_creationTime(i);

View File

@@ -39,7 +39,7 @@ add_task(async function run_test() {
false, // isHttpOnly
false, // isBrowserElement
{ partitionKey: "(https,example.com)" },
Ci.nsICookie.SAMESITE_UNSET,
Ci.nsICookie.SAMESITE_NONE,
Ci.nsICookie.SCHEME_UNSET,
false // isPartitioned
);
@@ -59,7 +59,7 @@ add_task(async function run_test() {
false, // isHttpOnly
false, // isBrowserElement
{ partitionKey: "(https,example.com)" },
Ci.nsICookie.SAMESITE_UNSET,
Ci.nsICookie.SAMESITE_NONE,
Ci.nsICookie.SCHEME_UNSET,
true // isPartitioned
);
@@ -79,7 +79,7 @@ add_task(async function run_test() {
false, // isHttpOnly
false, // isBrowserElement
{},
Ci.nsICookie.SAMESITE_UNSET,
Ci.nsICookie.SAMESITE_NONE,
Ci.nsICookie.SCHEME_UNSET,
false // isPartitioned
);
@@ -99,7 +99,7 @@ add_task(async function run_test() {
false, // isHttpOnly
false, // isBrowserElement
{ partitionKey: "(https,example.org)" },
Ci.nsICookie.SAMESITE_UNSET,
Ci.nsICookie.SAMESITE_NONE,
Ci.nsICookie.SCHEME_UNSET,
false // isPartitioned
);
@@ -119,7 +119,7 @@ add_task(async function run_test() {
false, // isHttpOnly
false, // isBrowserElement
{ partitionKey: "(https,example.org)" },
Ci.nsICookie.SAMESITE_UNSET,
Ci.nsICookie.SAMESITE_NONE,
Ci.nsICookie.SCHEME_UNSET,
true // isPartitioned
);

View File

@@ -49,7 +49,7 @@ add_task(async function test_schema_13_db() {
false,
false,
{},
Ci.nsICookie.SAMESITE_UNSET,
Ci.nsICookie.SAMESITE_NONE,
Ci.nsICookie.SCHEME_UNSET,
!!(i % 2) // isPartitioned
);

View File

@@ -41,7 +41,7 @@ add_task(async function test_schema_14_migration() {
false,
false,
{},
Ci.nsICookie.SAMESITE_UNSET,
Ci.nsICookie.SAMESITE_NONE,
Ci.nsICookie.SCHEME_UNSET,
!!(i % 2) // isPartitioned
);

View File

@@ -73,7 +73,7 @@ function run_test() {
// Sets a cookie for the test domain
do_await_remote_message("set-cookie").then(() => {
const expiry = Date.now() + 24 * 60 * 60;
const cv = Services.cookies.add(
Services.cookies.add(
TEST_DOMAIN,
"/",
"cookieName",
@@ -83,10 +83,9 @@ function run_test() {
false,
expiry,
{},
Ci.nsICookie.SAMESITE_UNSET,
Ci.nsICookie.SAMESITE_NONE,
Ci.nsICookie.SCHEME_HTTPS
);
Assert.equal(cv.result, Ci.nsICookieValidation.eOK, "Valid cookie");
do_send_remote_message("set-cookie-done");
});

View File

@@ -312,9 +312,8 @@ export class Network extends Domain {
]);
let success = true;
let cv;
try {
cv = Services.cookies.add(
Services.cookies.add(
hostname,
cookie.path,
cookie.name,
@@ -331,10 +330,6 @@ export class Network extends Domain {
success = false;
}
if (cv && cv.result != Ci.nsICookieValidation.eOK) {
throw new TypeError(cv.errorString);
}
return { success };
}

View File

@@ -301,9 +301,8 @@ class StorageModule extends RootBiDiModule {
const isPartitioned = originAttributes.partitionKey?.length > 0;
let cv;
try {
cv = Services.cookies.add(
Services.cookies.add(
domain,
path === null ? "/" : path,
name,
@@ -322,12 +321,6 @@ class StorageModule extends RootBiDiModule {
throw new lazy.error.UnableToSetCookieError(e);
}
if (cv.result !== Ci.nsICookieValidation.eOK) {
throw new lazy.error.UnableToSetCookieError(
`Invalid cookie: ${cv.errorString}`
);
}
return {
partitionKey: this.#formatPartitionKey(partitionKey, originAttributes),
};
@@ -797,12 +790,9 @@ class StorageModule extends RootBiDiModule {
case "strict": {
return Ci.nsICookie.SAMESITE_STRICT;
}
case "none": {
return Ci.nsICookie.SAMESITE_NONE;
}
}
return Ci.nsICookie.SAMESITE_UNSET;
return Ci.nsICookie.SAMESITE_NONE;
}
/**

View File

@@ -40,7 +40,6 @@ async def test_partition_context(
domain=domain_value(),
name=cookie_name,
value=NetworkStringValue(cookie_value),
secure=True,
),
partition=partition,
)
@@ -74,7 +73,6 @@ async def test_partition_context_iframe_with_set_cookie(
domain=domain_value(domain),
name=cookie_name,
value=NetworkStringValue(cookie_value),
secure=True,
),
partition=frame_partition,
)

View File

@@ -42,7 +42,6 @@ async def test_partition_context(
domain=cookie_domain,
name=cookie_name,
value=NetworkStringValue(cookie_value),
secure=True,
),
partition=new_tab_partition,
)
@@ -63,7 +62,7 @@ async def test_partition_context(
"name": cookie_name,
"path": "/",
"sameSite": "none",
"secure": True,
"secure": False,
"size": 6,
"value": {"type": "string", "value": cookie_value},
}
@@ -110,7 +109,6 @@ async def test_partition_context_iframe(
domain=domain_value(domain),
name=cookie_name,
value=NetworkStringValue(cookie_value),
secure=True,
),
partition=iframe_partition,
)
@@ -125,7 +123,7 @@ async def test_partition_context_iframe(
"name": cookie_name,
"path": "/",
"sameSite": "none",
"secure": True,
"secure": False,
"size": 6,
"value": {"type": "string", "value": cookie_value},
}

View File

@@ -44,7 +44,6 @@ async def test_partition_context(bidi_session, set_cookie, top_context, test_pag
domain=domain_value(),
name=cookie_name,
value=NetworkStringValue(cookie_value),
secure=True,
),
partition=partition,
)

View File

@@ -237,8 +237,7 @@ def test_add_cookie_with_valid_samesite_flag(session, url, same_site):
new_cookie = {
"name": "hello",
"value": "world",
"secure": True,
"sameSite": same_site,
"sameSite": same_site
}
session.url = url("/common/blank.html")

View File

@@ -99,7 +99,7 @@ export var SiteDataTestUtils = {
: principal.originAttributes;
}
const cv = Services.cookies.add(
Services.cookies.add(
host,
path,
name,
@@ -109,12 +109,9 @@ export var SiteDataTestUtils = {
false,
Math.floor(Date.now() / 1000) + 24 * 60 * 60,
originAttributes,
Ci.nsICookie.SAMESITE_UNSET,
Ci.nsICookie.SAMESITE_NONE,
Ci.nsICookie.SCHEME_UNSET
);
if (cv.result !== Ci.nsICookieValidation.eOK) {
throw new Error(`Invalid cookie: ${cv.result}`);
}
},
/**

View File

@@ -49,7 +49,7 @@ class MovedOriginDirectoryCleanupTestCase(MarionetteTestCase):
false,
Math.floor(Date.now() / 1000) + 24 * 60 * 60,
{},
Ci.nsICookie.SAMESITE_UNSET,
Ci.nsICookie.SAMESITE_NONE,
Ci.nsICookie.SCHEME_UNSET
);
return promise;

View File

@@ -9,7 +9,7 @@
add_task(async function test_all_cookies() {
const expiry = Date.now() + 24 * 60 * 60;
const cv = Services.cookies.add(
Services.cookies.add(
"example.net",
"path",
"name",
@@ -22,7 +22,6 @@ add_task(async function test_all_cookies() {
Ci.nsICookie.SAMESITE_NONE,
Ci.nsICookie.SCHEME_HTTPS
);
Assert.equal(cv.result, Ci.nsICookieValidation.eOK, "Valid cookie");
Assert.equal(Services.cookies.countCookiesFromHost("example.net"), 1);
await new Promise(aResolve => {
@@ -40,7 +39,7 @@ add_task(async function test_all_cookies() {
add_task(async function test_range_cookies() {
const expiry = Date.now() + 24 * 60 * 60;
const cv = Services.cookies.add(
Services.cookies.add(
"example.net",
"path",
"name",
@@ -53,7 +52,6 @@ add_task(async function test_range_cookies() {
Ci.nsICookie.SAMESITE_NONE,
Ci.nsICookie.SCHEME_HTTPS
);
Assert.equal(cv.result, Ci.nsICookieValidation.eOK, "Valid cookie");
Assert.equal(Services.cookies.countCookiesFromHost("example.net"), 1);
// The cookie is out of time range here.
@@ -93,7 +91,7 @@ add_task(async function test_range_cookies() {
add_task(async function test_principal_cookies() {
const expiry = Date.now() + 24 * 60 * 60;
const cv = Services.cookies.add(
Services.cookies.add(
"example.net",
"path",
"name",
@@ -106,7 +104,6 @@ add_task(async function test_principal_cookies() {
Ci.nsICookie.SAMESITE_NONE,
Ci.nsICookie.SCHEME_HTTPS
);
Assert.equal(cv.result, Ci.nsICookieValidation.eOK, "Valid cookie");
Assert.equal(Services.cookies.countCookiesFromHost("example.net"), 1);
let uri = Services.io.newURI("http://example.com");
@@ -148,7 +145,7 @@ add_task(async function test_principal_cookies() {
add_task(async function test_localfile_cookies() {
const expiry = Date.now() + 24 * 60 * 60;
const cv = Services.cookies.add(
Services.cookies.add(
"", // local file
"path",
"name",
@@ -158,10 +155,10 @@ add_task(async function test_localfile_cookies() {
false /* session */,
expiry,
{},
Ci.nsICookie.SAMESITE_UNSET,
Ci.nsICookie.SAMESITE_NONE,
Ci.nsICookie.SCHEME_HTTP
);
Assert.equal(cv.result, Ci.nsICookieValidation.eOK, "Valid cookie");
Assert.notEqual(Services.cookies.countCookiesFromHost(""), 0);
await new Promise(aResolve => {
@@ -399,7 +396,7 @@ add_task(async function test_baseDomain_cookies_subdomain() {
function addCookiesForHost(host) {
const expiry = Date.now() + 24 * 60 * 60;
const cv = Services.cookies.add(
Services.cookies.add(
host,
"path",
"name",
@@ -412,7 +409,6 @@ function addCookiesForHost(host) {
Ci.nsICookie.SAMESITE_NONE,
Ci.nsICookie.SCHEME_HTTPS
);
Assert.equal(cv.result, Ci.nsICookieValidation.eOK, "Valid cookie");
}
function addIpv6Cookies() {

View File

@@ -25,7 +25,7 @@ const COOKIE = {
};
function createCookie(userContextId) {
const cv = Services.cookies.add(
Services.cookies.add(
COOKIE.host,
COOKIE.path,
COOKIE.name,
@@ -35,10 +35,9 @@ function createCookie(userContextId) {
COOKIE.isSession,
COOKIE.expiry,
{ userContextId },
Ci.nsICookie.SAMESITE_UNSET,
Ci.nsICookie.SAMESITE_NONE,
Ci.nsICookie.SCHEME_HTTP
);
Assert.equal(cv.result, Ci.nsICookieValidation.eOK, "Valid cookie");
}
function hasCookie(userContextId) {

View File

@@ -16,7 +16,6 @@
#include "mozilla/Components.h"
#include "Cookie.h"
#include "nsIHttpProtocolHandler.h"
#include "mozilla/net/CookieValidation.h"
#include "mozilla/StaticPrefs_cookiebanners.h"
#include "nsNetUtil.h"
@@ -324,29 +323,12 @@ nsresult nsCookieInjector::InjectCookiesFromRules(
MOZ_LOG(gCookieInjectorLog, LogLevel::Info,
("Setting cookie: %s, %s, %s, %s\n", c.Host().get(), c.Name().get(),
c.Path().get(), c.Value().get()));
nsCOMPtr<nsICookieValidation> validation;
rv = cookieManager->AddNative(
nullptr, c.Host(), c.Path(), c.Name(), c.Value(), c.IsSecure(),
c.IsHttpOnly(), c.IsSession(), c.Expiry(), &aOriginAttributes,
c.SameSite(), static_cast<nsICookie::schemeType>(c.SchemeMap()),
/* is partitioned: */ false, /* is from http: */ true, nullptr,
getter_AddRefs(validation));
if (rv == NS_ERROR_ILLEGAL_VALUE) {
net::CookieValidation* cv = net::CookieValidation::Cast(validation);
MOZ_ASSERT(cv);
MOZ_ASSERT(cv->Result() != nsICookieValidation::eOK);
nsAutoString errorString;
rv = cv->GetErrorString(errorString);
NS_ENSURE_SUCCESS(rv, rv);
MOZ_LOG(gCookieInjectorLog, LogLevel::Error,
("Invalid cookie: %s",
NS_ConvertUTF16toUTF8(errorString).BeginReading()));
continue;
}
[](mozilla::net::CookieStruct&) { return true; });
NS_ENSURE_SUCCESS(rv, rv);
aHasInjectedCookie = true;

View File

@@ -81,7 +81,7 @@ add_task(async function test_insertAndGetRule() {
false,
false,
false,
Ci.nsICookie.SAMESITE_UNSET,
0,
0
);
rule.addCookie(
@@ -95,7 +95,7 @@ add_task(async function test_insertAndGetRule() {
false,
false,
false,
Ci.nsICookie.SAMESITE_UNSET,
0,
0
);
rule.addCookie(
@@ -109,7 +109,7 @@ add_task(async function test_insertAndGetRule() {
false,
false,
true,
Ci.nsICookie.SAMESITE_UNSET,
0,
0
);
@@ -153,7 +153,7 @@ add_task(async function test_insertAndGetRule() {
false,
false,
false,
Ci.nsICookie.SAMESITE_UNSET,
0,
0
);
@@ -412,7 +412,7 @@ add_task(async function test_overwriteRule() {
false,
false,
false,
Ci.nsICookie.SAMESITE_UNSET,
0,
0
);
@@ -444,7 +444,7 @@ add_task(async function test_overwriteRule() {
false,
false,
false,
Ci.nsICookie.SAMESITE_UNSET,
0,
0
);
@@ -498,7 +498,7 @@ add_task(async function test_globalRules() {
false,
false,
false,
Ci.nsICookie.SAMESITE_UNSET,
0,
0
);
rule.addClickRule(
@@ -529,7 +529,7 @@ add_task(async function test_globalRules() {
false,
false,
false,
Ci.nsICookie.SAMESITE_UNSET,
0,
0
);
ruleGlobalA.addClickRule(

View File

@@ -330,7 +330,7 @@ function insertTestCookieRules() {
false,
false,
false,
Ci.nsICookie.SAMESITE_UNSET,
0,
0
);
ruleA.addCookie(
@@ -344,7 +344,7 @@ function insertTestCookieRules() {
false,
false,
false,
Ci.nsICookie.SAMESITE_UNSET,
0,
0
);
@@ -366,7 +366,7 @@ function insertTestCookieRules() {
false,
false,
true,
Ci.nsICookie.SAMESITE_UNSET,
0,
0
);
}

View File

@@ -4,19 +4,6 @@
"use strict";
XPCOMUtils.defineLazyPreferenceGetter(
this,
"gCookiesRejectWhenInvalid",
"extensions.cookie.rejectWhenInvalid",
false
);
XPCOMUtils.defineLazyPreferenceGetter(
this,
"gCookiesMaxageCap",
"network.cookie.maxageCap",
0
);
var { ExtensionError } = ExtensionUtils;
const SAME_SITE_STATUSES = new Map([
@@ -693,14 +680,6 @@ this.cookies = class extends ExtensionAPIPersistent {
? Number.MAX_SAFE_INTEGER
: details.expirationDate;
// maxage cap for expiry
if (gCookiesMaxageCap > 0) {
expiry = Math.min(
expiry,
Math.round(Date.now() / 1000) + gCookiesMaxageCap
);
}
let { originAttributes } = oaFromDetails(details, context);
let cookieAttrs = {
@@ -739,10 +718,7 @@ this.cookies = class extends ExtensionAPIPersistent {
// The permission check may have modified the domain, so use
// the new value instead.
let fn = gCookiesRejectWhenInvalid
? Services.cookies.add
: Services.cookies.addForAddOn;
const cv = fn(
Services.cookies.add(
cookieAttrs.host,
path,
name,
@@ -757,16 +733,6 @@ this.cookies = class extends ExtensionAPIPersistent {
isPartitioned
);
if (cv.result !== Ci.nsICookieValidation.eOK) {
if (gCookiesRejectWhenInvalid) {
return Promise.reject({ message: cv.errorString });
}
Services.console.logStringMessage(
`Extension ${extension.id} tried to create an invalid cookie: ${cv.errorString}`
);
}
return self.cookies.get(details);
},

View File

@@ -131,7 +131,7 @@ async function testCookies(options) {
false,
options.expiry,
{},
Ci.nsICookie.SAMESITE_UNSET,
Ci.nsICookie.SAMESITE_NONE,
options.url.startsWith("https")
? Ci.nsICookie.SCHEME_HTTPS
: Ci.nsICookie.SCHEME_HTTP
@@ -147,7 +147,7 @@ async function testCookies(options) {
false,
options.expiry,
{},
Ci.nsICookie.SAMESITE_UNSET,
Ci.nsICookie.SAMESITE_NONE,
options.url.startsWith("https")
? Ci.nsICookie.SCHEME_HTTPS
: Ci.nsICookie.SCHEME_HTTP
@@ -163,7 +163,7 @@ async function testCookies(options) {
false,
options.expiry,
{},
Ci.nsICookie.SAMESITE_UNSET,
Ci.nsICookie.SAMESITE_NONE,
options.url.startsWith("https")
? Ci.nsICookie.SCHEME_HTTPS
: Ci.nsICookie.SCHEME_HTTP
@@ -195,7 +195,7 @@ async function testCookies(options) {
false,
options.expiry,
{},
Ci.nsICookie.SAMESITE_UNSET,
Ci.nsICookie.SAMESITE_NONE,
options.url.startsWith("https")
? Ci.nsICookie.SCHEME_HTTPS
: Ci.nsICookie.SCHEME_HTTP
@@ -211,7 +211,7 @@ async function testCookies(options) {
false,
options.expiry,
{},
Ci.nsICookie.SAMESITE_UNSET,
Ci.nsICookie.SAMESITE_NONE,
options.url.startsWith("https")
? Ci.nsICookie.SCHEME_HTTPS
: Ci.nsICookie.SCHEME_HTTP

View File

@@ -38,7 +38,7 @@ add_task(async function test_cookies() {
async function testIpCookie(ipAddress, setHostOnly) {
const IP_TEST_HOST = ipAddress;
const IP_TEST_URL = `http://${IP_TEST_HOST}/`;
const IP_THE_FUTURE = Math.round(Date.now()/1000) + 5 * 60;
const IP_THE_FUTURE = Date.now() + 5 * 60;
const IP_STORE_ID = "firefox-default";
let expectedCookie = {
@@ -122,7 +122,7 @@ add_task(async function test_cookies() {
const TEST_URL = "http://example.org/";
const TEST_SECURE_URL = "https://example.org/";
const THE_FUTURE = Math.round(Date.now()/1000) + 5 * 60;
const THE_FUTURE = Date.now() + 5 * 60;
const TEST_PATH = "set_path";
const TEST_URL_WITH_PATH = TEST_URL + TEST_PATH;
const TEST_COOKIE_PATH = `/${TEST_PATH}`;

View File

@@ -34,7 +34,7 @@ add_task(async function test_cookie_containers() {
}
const TEST_URL = "http://example.org/";
const THE_FUTURE = Math.round(Date.now()/1000) + 5 * 60;
const THE_FUTURE = Date.now() + 5 * 60;
let expected = {
name: "name1",

View File

@@ -45,7 +45,7 @@ add_task(async function test_cookies_expiry() {
let chromeScript = loadChromeScript(() => {
const {sendAsyncMessage} = this;
Services.cookies.add(".example.com", "/", "first", "one", false, false, false, Date.now() / 1000 + 1, {}, Ci.nsICookie.SAMESITE_UNSET, Ci.nsICookie.SCHEME_HTTP);
Services.cookies.add(".example.com", "/", "first", "one", false, false, false, Date.now() / 1000 + 1, {}, Ci.nsICookie.SAMESITE_NONE, Ci.nsICookie.SCHEME_HTTP);
sendAsyncMessage("done");
});
await chromeScript.promiseOneMessage("done");
@@ -56,7 +56,7 @@ add_task(async function test_cookies_expiry() {
chromeScript = loadChromeScript(() => {
const {sendAsyncMessage} = this;
Services.cookies.add(".example.com", "/", "first", "one-again", false, false, false, Date.now() / 1000 + 10, {}, Ci.nsICookie.SAMESITE_UNSET, Ci.nsICookie.SCHEME_HTTP);
Services.cookies.add(".example.com", "/", "first", "one-again", false, false, false, Date.now() / 1000 + 10, {}, Ci.nsICookie.SAMESITE_NONE, Ci.nsICookie.SCHEME_HTTP);
sendAsyncMessage("done");
});
await chromeScript.promiseOneMessage("done");

View File

@@ -86,10 +86,10 @@ add_task(async function test_cookies_incognito_not_allowed() {
/* eslint-env mozilla/chrome-script */
Services.cookies.add("example.org", "/", "public", `foo${Math.random()}`,
false, false, false, Number.MAX_SAFE_INTEGER, {},
Ci.nsICookie.SAMESITE_UNSET);
Ci.nsICookie.SAMESITE_NONE);
Services.cookies.add("example.org", "/", "private", `foo${Math.random()}`,
false, false, false, Number.MAX_SAFE_INTEGER, {privateBrowsingId: 1},
Ci.nsICookie.SAMESITE_UNSET);
Ci.nsICookie.SAMESITE_NONE);
});
extension.sendMessage("test-cookie-store");
await extension.awaitFinish("cookies");

View File

@@ -25,7 +25,7 @@ const COOKIE_ORG = {
let since, oldCookie;
function addCookie(cookie) {
const cv = Services.cookies.add(
Services.cookies.add(
cookie.host,
cookie.path,
cookie.name,
@@ -35,10 +35,9 @@ function addCookie(cookie) {
false,
Date.now() / 1000 + 10000,
{},
Ci.nsICookie.SAMESITE_UNSET,
Ci.nsICookie.SAMESITE_NONE,
Ci.nsICookie.SCHEME_HTTPS
);
Assert.strictEqual(cv.result, Ci.nsICookieValidation.eOK, "Valid cookie");
ok(
Services.cookies.cookieExists(cookie.host, cookie.path, cookie.name, {}),
`Cookie ${cookie.name} was created.`

View File

@@ -41,7 +41,7 @@ function cookieExists(cookie) {
function addCookie(cookie) {
const THE_FUTURE = Date.now() + 5 * 60;
const cv = Services.cookies.add(
Services.cookies.add(
cookie.host,
cookie.path,
cookie.name,
@@ -51,11 +51,10 @@ function addCookie(cookie) {
false,
THE_FUTURE,
cookie.originAttributes,
Ci.nsICookie.SAMESITE_UNSET,
Ci.nsICookie.SAMESITE_NONE,
Ci.nsICookie.SCHEME_HTTPS
);
Assert.strictEqual(cv.result, Ci.nsICookieValidation.eOK, "Valid cookie");
ok(cookieExists(cookie), `Cookie ${cookie.name} was created.`);
}

View File

@@ -1,61 +0,0 @@
"use strict";
add_task(async function test_no_reject_invalid_cookies() {
async function backgroundScript() {
const kOneDay = 60 * 60 * 24;
const kTenDays = kOneDay * 10;
const kFourHundredDays = kTenDays * 40;
const kNow = Math.round(Date.now() / 1000);
await browser.cookies.set({
url: "https://example.com",
name: "a",
value: "b",
// kFourHundredDays * 10 exceeds the limit from network.cookie.maxageCap
expirationDate: kNow + kFourHundredDays * 10,
});
let cookie = await browser.cookies.getAll({
url: "https://example.com",
name: "a",
});
browser.test.assertEq(cookie.length, 1, "Cookie with 400-days expiry");
// The extra day is just to avoid out-of-sync timing between parent and content processes.
browser.test.assertTrue(
cookie[0].expirationDate <= kNow + kFourHundredDays + kOneDay,
"ExpirationDate is normalized to max 400 days"
);
await browser.cookies.set({
url: "https://example.com",
name: "a",
value: "b",
expirationDate: kNow + kTenDays,
});
cookie = await browser.cookies.getAll({
url: "https://example.com",
name: "a",
});
browser.test.assertEq(cookie.length, 1, "Cookie with 10-day expiry");
browser.test.assertTrue(
cookie[0].expirationDate <= kNow + kTenDays,
"ExpirationDate is around 10 days"
);
browser.test.sendMessage("done");
}
const extension = ExtensionTestUtils.loadExtension({
background: backgroundScript,
manifest: {
permissions: ["cookies", "https://example.com/*"],
},
});
await extension.startup();
await extension.awaitMessage("done");
await extension.unload();
});

View File

@@ -1,119 +0,0 @@
"use strict";
add_task(
{ pref_set: [["extensions.cookie.rejectWhenInvalid", true]] },
async function test_no_reject_invalid_cookies() {
await do_test_invalid_cookies({ failure: true });
}
);
add_task(
{ pref_set: [["extensions.cookie.rejectWhenInvalid", false]] },
async function test_warn_on_invalid_cookies() {
await do_test_invalid_cookies({ failure: false });
}
);
async function do_test_invalid_cookies(options) {
async function backgroundScript() {
browser.test.onMessage.addListener(async message => {
let failure = true;
try {
await browser.cookies.set({
...message.cookie,
url: "https://example.com",
});
failure = false;
} catch (e) {
browser.test.assertEq(
e.message,
message.errorString,
`${message.title} - correct exception`
);
} finally {
browser.test.assertEq(failure, message.failure, message.title);
browser.test.sendMessage("completed");
}
});
browser.test.sendMessage("ready");
}
const extension = ExtensionTestUtils.loadExtension({
background: backgroundScript,
manifest: {
permissions: ["cookies", "https://example.com/*"],
},
});
let readyPromise = extension.awaitMessage("ready");
await extension.startup();
await readyPromise;
const tests = [
{
cookie: { name: "", value: "" },
title: "Empty name and value",
errorString:
"Cookie with an empty name and an empty value has been rejected.",
},
{
cookie: { name: "a".repeat(3000), value: "a".repeat(3000) },
title: "Name/value oversize",
errorString: `Cookie “${"a".repeat(3000)}” is invalid because its size is too big. Max size is 4096 B.`,
},
{
cookie: { name: ";", value: "a" },
title: "Invalid chars in the name",
errorString:
"Cookie “;” has been rejected for invalid characters in the name.",
},
{
cookie: { name: " ", value: "a" },
title: "Invalid chars in the name (2)",
errorString:
"Cookie “ ” has been rejected for invalid characters in the name.",
},
{
cookie: { name: "a", value: ";" },
title: "Invalid chars in the value",
errorString:
"Cookie “a” has been rejected for invalid characters in the value.",
},
{
cookie: { name: "a", value: " " },
title: "Invalid chars in the value (2)",
errorString:
"Cookie “a” has been rejected for invalid characters in the value.",
},
{
cookie: { name: "", value: "__Secure-wow" },
title: "Invalid prefix (__Secure)",
errorString: "Cookie “” has been rejected for invalid prefix.",
},
{
cookie: { name: "", value: "__Host-wow" },
title: "Invalid prefix (__Host)",
errorString: "Cookie “” has been rejected for invalid prefix.",
},
{
cookie: { name: "a", value: "b", sameSite: "no_restriction" },
title: "None requires secure",
errorString:
"Cookie “a” rejected because it has the “SameSite=None” attribute but is missing the “secure” attribute.",
},
{
cookie: { name: "a", value: "b", path: "a".repeat(1025) },
title: "Path oversize",
errorString:
"Cookie “a” has been rejected because its path attribute is too big.",
},
];
for (const test of tests) {
extension.sendMessage({ ...test, ...options });
await extension.awaitMessage("completed");
}
await extension.unload();
}

View File

@@ -187,8 +187,6 @@ skip-if = [
["test_ext_cookies_errors.js"]
["test_ext_cookies_expirationDate.js"]
["test_ext_cookies_firstParty.js"]
skip-if = [
"appname == 'thunderbird'",
@@ -203,8 +201,6 @@ skip-if = [
["test_ext_cookies_sort.js"]
["test_ext_cookies_validation.js"]
["test_ext_cors_mozextension.js"]
["test_ext_csp_frame_ancestors.js"]

View File

@@ -46,7 +46,7 @@ const PREFERENCE_NAME = "test-pref";
*/
function add_cookie(aDomain) {
check_cookie_exists(aDomain, false);
const cv = Services.cookies.add(
Services.cookies.add(
aDomain,
COOKIE_PATH,
COOKIE_NAME,
@@ -56,10 +56,9 @@ function add_cookie(aDomain) {
false,
COOKIE_EXPIRY,
{},
Ci.nsICookie.SAMESITE_UNSET,
Ci.nsICookie.SAMESITE_NONE,
Ci.nsICookie.SCHEME_HTTPS
);
Assert.equal(cv.result, Ci.nsICookieValidation.eOK, "Valid cookie");
check_cookie_exists(aDomain, true);
}

View File

@@ -567,7 +567,7 @@ add_task(async function discopane_no_cookies() {
let requestPromise = new Promise(resolve => {
amoServer.registerPathHandler("/discoapi", resolve);
});
const cv = Services.cookies.add(
Services.cookies.add(
AMO_TEST_HOST,
"/",
"name",
@@ -577,10 +577,9 @@ add_task(async function discopane_no_cookies() {
false,
Date.now() / 1000 + 600,
{},
Ci.nsICookie.SAMESITE_UNSET,
Ci.nsICookie.SAMESITE_NONE,
Ci.nsICookie.SCHEME_HTTP
);
is(cv.result, Ci.nsICookieValidation.eOK, "Valid cookie");
let win = await loadInitialView("discover");
let request = await requestPromise;
ok(!request.hasHeader("Cookie"), "discovery API should not receive cookies");

View File

@@ -110,7 +110,7 @@ add_task(async function test_cookies() {
const COOKIE = "test";
let expiration = Date.now() / 1000 + 60 * 60;
const cv = Services.cookies.add(
Services.cookies.add(
"example.com",
"/",
COOKIE,
@@ -120,10 +120,9 @@ add_task(async function test_cookies() {
false,
expiration,
{},
Ci.nsICookie.SAMESITE_UNSET,
Ci.nsICookie.SAMESITE_NONE,
Ci.nsICookie.SCHEME_HTTP
);
Assert.equal(cv.result, Ci.nsICookieValidation.eOK, "Valid cookie");
await AddonRepository.getAvailableLangpacks();

View File

@@ -52,7 +52,7 @@ add_task(async function test_cookies() {
const COOKIE = "test";
// cookies.add() takes a time in seconds
let expiration = Date.now() / 1000 + 60 * 60;
const cv = Services.cookies.add(
Services.cookies.add(
"example.com",
"/",
COOKIE,
@@ -62,10 +62,9 @@ add_task(async function test_cookies() {
false,
expiration,
{},
Ci.nsICookie.SAMESITE_UNSET,
Ci.nsICookie.SAMESITE_NONE,
Ci.nsICookie.SCHEME_HTTP
);
Assert.equal(cv.result, Ci.nsICookieValidation.eOK, "Valid cookie");
await promiseStartupManager();

View File

@@ -10,7 +10,7 @@ function test() {
Harness.installsCompletedCallback = finish_test;
Harness.setup();
const cv = Services.cookies.add(
Services.cookies.add(
"example.com",
"/browser/" + RELATIVE_DIR,
"xpinstall",
@@ -20,10 +20,9 @@ function test() {
true,
Date.now() / 1000 + 60,
{},
Ci.nsICookie.SAMESITE_UNSET,
Ci.nsICookie.SAMESITE_NONE,
Ci.nsICookie.SCHEME_HTTP
);
Assert.equal(cv.result, Ci.nsICookieValidation.eOK, "Valid cookie");
PermissionTestUtils.add(
"http://example.com/",

View File

@@ -20,7 +20,7 @@ function test() {
true,
Date.now() / 1000 + 60,
{},
Ci.nsICookie.SAMESITE_UNSET,
Ci.nsICookie.SAMESITE_NONE,
Ci.nsICookie.SCHEME_HTTP
);

View File

@@ -21,7 +21,7 @@ function test() {
true,
Date.now() / 1000 + 60,
{},
Ci.nsICookie.SAMESITE_UNSET,
Ci.nsICookie.SAMESITE_NONE,
Ci.nsICookie.SCHEME_HTTP
);