1
0
Fork 0
firefox/remote/webdriver-bidi/modules/root/storage.sys.mjs
Daniel Baumann 5e9a113729
Adding upstream version 140.0.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
2025-06-25 09:37:52 +02:00

977 lines
28 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/* 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/. */
import { RootBiDiModule } from "chrome://remote/content/webdriver-bidi/modules/RootBiDiModule.sys.mjs";
const lazy = {};
ChromeUtils.defineESModuleGetters(lazy, {
assert: "chrome://remote/content/shared/webdriver/Assert.sys.mjs",
BytesValueType:
"chrome://remote/content/webdriver-bidi/modules/root/network.sys.mjs",
deserializeBytesValue:
"chrome://remote/content/webdriver-bidi/modules/root/network.sys.mjs",
error: "chrome://remote/content/shared/webdriver/Errors.sys.mjs",
pprint: "chrome://remote/content/shared/Format.sys.mjs",
TabManager: "chrome://remote/content/shared/TabManager.sys.mjs",
UserContextManager:
"chrome://remote/content/shared/UserContextManager.sys.mjs",
});
const PREF_COOKIE_CHIPS_ENABLED = "network.cookie.CHIPS.enabled";
const PREF_COOKIE_BEHAVIOR = "network.cookie.cookieBehavior";
// This is a static preference, so it cannot be modified during runtime and we can cache its value.
ChromeUtils.defineLazyGetter(lazy, "cookieCHIPSEnabled", () =>
Services.prefs.getBoolPref(PREF_COOKIE_CHIPS_ENABLED)
);
const CookieFieldsMapping = {
domain: "host",
expiry: "expiry",
httpOnly: "isHttpOnly",
name: "name",
path: "path",
sameSite: "sameSite",
secure: "isSecure",
size: "size",
value: "value",
};
const MAX_COOKIE_EXPIRY = Number.MAX_SAFE_INTEGER;
/**
* Enum of possible partition types supported by the
* storage.getCookies command.
*
* @readonly
* @enum {PartitionType}
*/
const PartitionType = {
Context: "context",
StorageKey: "storageKey",
};
const PartitionKeyAttributes = ["sourceOrigin", "userContext"];
/**
* Enum of possible SameSite types supported by the
* storage.getCookies command.
*
* @readonly
* @enum {SameSiteType}
*/
const SameSiteType = {
[Ci.nsICookie.SAMESITE_NONE]: "none",
[Ci.nsICookie.SAMESITE_LAX]: "lax",
[Ci.nsICookie.SAMESITE_STRICT]: "strict",
[Ci.nsICookie.SAMESITE_UNSET]: "none",
};
class StorageModule extends RootBiDiModule {
destroy() {}
/**
* Used as an argument for storage.getCookies command
* to represent fields which should be used to filter the output
* of the command.
*
* @typedef CookieFilter
*
* @property {string=} domain
* @property {number=} expiry
* @property {boolean=} httpOnly
* @property {string=} name
* @property {string=} path
* @property {SameSiteType=} sameSite
* @property {boolean=} secure
* @property {number=} size
* @property {Network.BytesValueType=} value
*/
/**
* Used as an argument for storage.getCookies command as one of the available variants
* {BrowsingContextPartitionDescriptor} or {StorageKeyPartitionDescriptor}, to represent
* fields should be used to build a partition key.
*
* @typedef PartitionDescriptor
*/
/**
* @typedef BrowsingContextPartitionDescriptor
*
* @property {PartitionType} [type=PartitionType.context]
* @property {string} context
*/
/**
* @typedef StorageKeyPartitionDescriptor
*
* @property {PartitionType} [type=PartitionType.storageKey]
* @property {string=} sourceOrigin
* @property {string=} userContext
*/
/**
* @typedef PartitionKey
*
* @property {string=} sourceOrigin
* @property {string=} userContext
*/
/**
* An object that holds the result of storage.getCookies command.
*
* @typedef GetCookiesResult
*
* @property {Array<Cookie>} cookies
* List of cookies.
* @property {PartitionKey} partitionKey
* An object which represent the partition key which was used
* to retrieve the cookies.
*/
/**
* Remove zero or more cookies which match a set of provided parameters.
*
* @param {object=} options
* @param {CookieFilter=} options.filter
* An object which holds field names and values, which
* should be used to filter the output of the command.
* @param {PartitionDescriptor=} options.partition
* An object which holds the information which
* should be used to build a partition key.
*
* @returns {PartitionKey}
* An object with the partition key which was used to
* retrieve cookies which had to be removed.
* @throws {InvalidArgumentError}
* If the provided arguments are not valid.
* @throws {NoSuchFrameError}
* If the provided browsing context cannot be found.
*/
async deleteCookies(options = {}) {
let { filter = {} } = options;
const { partition: partitionSpec = null } = options;
this.#assertPartition(partitionSpec);
filter = this.#assertCookieFilter(filter);
const partitionKey = this.#expandStoragePartitionSpec(partitionSpec);
const store = this.#getTheCookieStore(partitionKey);
const cookies = this.#getMatchingCookies(store, filter);
for (const cookie of cookies) {
Services.cookies.remove(
cookie.host,
cookie.name,
cookie.path,
cookie.originAttributes
);
}
return { partitionKey: this.#formatPartitionKey(partitionKey) };
}
/**
* Retrieve zero or more cookies which match a set of provided parameters.
*
* @param {object=} options
* @param {CookieFilter=} options.filter
* An object which holds field names and values, which
* should be used to filter the output of the command.
* @param {PartitionDescriptor=} options.partition
* An object which holds the information which
* should be used to build a partition key.
*
* @returns {GetCookiesResult}
* An object which holds a list of retrieved cookies and
* the partition key which was used.
* @throws {InvalidArgumentError}
* If the provided arguments are not valid.
* @throws {NoSuchFrameError}
* If the provided browsing context cannot be found.
*/
async getCookies(options = {}) {
let { filter = {} } = options;
const { partition: partitionSpec = null } = options;
this.#assertPartition(partitionSpec);
filter = this.#assertCookieFilter(filter);
const partitionKey = this.#expandStoragePartitionSpec(partitionSpec);
const store = this.#getTheCookieStore(partitionKey);
const cookies = this.#getMatchingCookies(store, filter);
const serializedCookies = [];
for (const cookie of cookies) {
serializedCookies.push(this.#serializeCookie(cookie));
}
return {
cookies: serializedCookies,
partitionKey: this.#formatPartitionKey(partitionKey),
};
}
/**
* An object representation of the cookie which should be set.
*
* @typedef PartialCookie
*
* @property {string} domain
* @property {number=} expiry
* @property {boolean=} httpOnly
* @property {string} name
* @property {string=} path
* @property {SameSiteType=} sameSite
* @property {boolean=} secure
* @property {number=} size
* @property {Network.BytesValueType} value
*/
/**
* Create a new cookie in a cookie store.
*
* @param {object=} options
* @param {PartialCookie} options.cookie
* An object representation of the cookie which
* should be set.
* @param {PartitionDescriptor=} options.partition
* An object which holds the information which
* should be used to build a partition key.
*
* @returns {PartitionKey}
* An object with the partition key which was used to
* add the cookie.
* @throws {InvalidArgumentError}
* If the provided arguments are not valid.
* @throws {NoSuchFrameError}
* If the provided browsing context cannot be found.
* @throws {UnableToSetCookieError}
* If the cookie was not added.
*/
async setCookie(options = {}) {
const { cookie: cookieSpec, partition: partitionSpec = null } = options;
lazy.assert.object(
cookieSpec,
lazy.pprint`Expected "cookie" to be an object, got ${cookieSpec}`
);
const {
domain,
expiry = null,
httpOnly = null,
name,
path = null,
sameSite = null,
secure = null,
value,
} = cookieSpec;
this.#assertCookie({
domain,
expiry,
httpOnly,
name,
path,
sameSite,
secure,
value,
});
this.#assertPartition(partitionSpec);
const partitionKey = this.#expandStoragePartitionSpec(partitionSpec);
// The cookie store is defined by originAttributes.
const originAttributes = this.#getOriginAttributes(partitionKey, domain);
// The cookie value is a network.BytesValue.
const deserializedValue = lazy.deserializeBytesValue(value);
// The XPCOM interface requires to be specified if a cookie is session.
const isSession = expiry === null;
let schemeType;
if (secure) {
schemeType = Ci.nsICookie.SCHEME_HTTPS;
} else {
schemeType = Ci.nsICookie.SCHEME_HTTP;
}
const isPartitioned = originAttributes.partitionKey?.length > 0;
try {
Services.cookies.add(
domain,
path === null ? "/" : path,
name,
deserializedValue,
secure === null ? false : secure,
httpOnly === null ? false : httpOnly,
isSession,
// The XPCOM interface requires the expiry field even for session cookies.
expiry === null ? MAX_COOKIE_EXPIRY : expiry,
originAttributes,
this.#getSameSitePlatformProperty(sameSite),
schemeType,
isPartitioned
);
} catch (e) {
throw new lazy.error.UnableToSetCookieError(e);
}
return {
partitionKey: this.#formatPartitionKey(partitionKey, originAttributes),
};
}
#assertCookie(cookie) {
lazy.assert.object(
cookie,
lazy.pprint`Expected "cookie" to be an object, got ${cookie}`
);
const { domain, expiry, httpOnly, name, path, sameSite, secure, value } =
cookie;
lazy.assert.string(
domain,
lazy.pprint`Expected cookie "domain" to be a string, got ${domain}`
);
lazy.assert.string(
name,
lazy.pprint`Expected cookie "name" to be a string, got ${name}`
);
this.#assertValue(value);
if (expiry !== null) {
lazy.assert.positiveInteger(
expiry,
lazy.pprint`Expected cookie "expiry" to be a positive integer, got ${expiry}`
);
}
if (httpOnly !== null) {
lazy.assert.boolean(
httpOnly,
lazy.pprint`Expected cookie "httpOnly" to be a boolean, got ${httpOnly}`
);
}
if (path !== null) {
lazy.assert.string(
path,
lazy.pprint`Expected cookie "path" to be a string, got ${path}`
);
}
this.#assertSameSite(sameSite);
if (secure !== null) {
lazy.assert.boolean(
secure,
lazy.pprint`Expected cookie "secure" to be a boolean, got ${secure}`
);
}
}
#assertCookieFilter(filter) {
lazy.assert.object(
filter,
lazy.pprint`Expected "filter" to be an object, got ${filter}`
);
const {
domain = null,
expiry = null,
httpOnly = null,
name = null,
path = null,
sameSite = null,
secure = null,
size = null,
value = null,
} = filter;
if (domain !== null) {
lazy.assert.string(
domain,
lazy.pprint`Expected filter "domain" to be a string, got ${domain}`
);
}
if (expiry !== null) {
lazy.assert.positiveInteger(
expiry,
lazy.pprint`Expected filter "expiry" to be a positive integer, got ${expiry}`
);
}
if (httpOnly !== null) {
lazy.assert.boolean(
httpOnly,
lazy.pprint`Expected filter "httpOnly" to be a boolean, got ${httpOnly}`
);
}
if (name !== null) {
lazy.assert.string(
name,
lazy.pprint`Expected filter "name" to be a string, got ${name}`
);
}
if (path !== null) {
lazy.assert.string(
path,
lazy.pprint`Expected filter "path" to be a string, got ${path}`
);
}
this.#assertSameSite(sameSite, "filter.sameSite");
if (secure !== null) {
lazy.assert.boolean(
secure,
lazy.pprint`Expected filter "secure" to be a boolean, got ${secure}`
);
}
if (size !== null) {
lazy.assert.positiveInteger(
size,
lazy.pprint`Expected filter "size" to be a positive integer, got ${size}`
);
}
if (value !== null) {
this.#assertValue(value, "filter.value");
}
return {
domain,
expiry,
httpOnly,
name,
path,
sameSite,
secure,
size,
value,
};
}
#assertPartition(partitionSpec) {
if (partitionSpec === null) {
return;
}
lazy.assert.object(
partitionSpec,
lazy.pprint`Expected "partition" to be an object, got ${partitionSpec}`
);
const { type } = partitionSpec;
lazy.assert.string(
type,
lazy.pprint`Expected partition "type" to be a string, got ${type}`
);
switch (type) {
case PartitionType.Context: {
const { context } = partitionSpec;
lazy.assert.string(
context,
lazy.pprint`Expected partition "context" to be a string, got ${context}`
);
break;
}
case PartitionType.StorageKey: {
const { sourceOrigin = null, userContext = null } = partitionSpec;
if (sourceOrigin !== null) {
lazy.assert.string(
sourceOrigin,
lazy.pprint`Expected partition "sourceOrigin" to be a string, got ${sourceOrigin}`
);
lazy.assert.that(
sourceOrigin => URL.canParse(sourceOrigin),
lazy.pprint`Expected partition "sourceOrigin" to be a valid URL, got ${sourceOrigin}`
)(sourceOrigin);
const url = new URL(sourceOrigin);
lazy.assert.that(
url => url.pathname === "/" && url.hash === "" && url.search === "",
lazy.pprint`Expected partition "sourceOrigin" to contain only origin, got ${sourceOrigin}`
)(url);
}
if (userContext !== null) {
lazy.assert.string(
userContext,
lazy.pprint`Expected partition "userContext" to be a string, got ${userContext}`
);
if (!lazy.UserContextManager.hasUserContextId(userContext)) {
throw new lazy.error.NoSuchUserContextError(
`User Context with id ${userContext} was not found`
);
}
}
break;
}
default: {
throw new lazy.error.InvalidArgumentError(
`Expected "partition.type" to be one of ${Object.values(
PartitionType
)}, got ${type}`
);
}
}
}
#assertSameSite(sameSite, fieldName = "sameSite") {
if (sameSite !== null) {
const sameSiteTypeValue = Object.values(SameSiteType);
lazy.assert.in(
sameSite,
sameSiteTypeValue,
`Expected "${fieldName}" to be one of ${sameSiteTypeValue}, ` +
lazy.pprint`got ${sameSite}`
);
}
}
#assertValue(value, fieldName = "value") {
lazy.assert.object(
value,
`Expected "${fieldName}" to be an object, ` + lazy.pprint`got ${value}`
);
const { type, value: protocolBytesValue } = value;
const bytesValueTypeValue = Object.values(lazy.BytesValueType);
lazy.assert.in(
type,
bytesValueTypeValue,
`Expected ${fieldName} "type" to be one of ${bytesValueTypeValue}, ` +
lazy.pprint`got ${type}`
);
lazy.assert.string(
protocolBytesValue,
`Expected ${fieldName} "value" to be string, ` +
lazy.pprint`got ${protocolBytesValue}`
);
}
/**
* Deserialize filter.
*
* @see https://w3c.github.io/webdriver-bidi/#deserialize-filter
*/
#deserializeFilter(filter) {
const deserializedFilter = {};
for (const [fieldName, value] of Object.entries(filter)) {
if (value === null) {
continue;
}
const deserializedName = CookieFieldsMapping[fieldName];
let deserializedValue;
switch (deserializedName) {
case "sameSite":
deserializedValue = this.#getSameSitePlatformProperty(value);
break;
case "value":
deserializedValue = lazy.deserializeBytesValue(value);
break;
default:
deserializedValue = value;
}
deserializedFilter[deserializedName] = deserializedValue;
}
return deserializedFilter;
}
/**
* Build a partition key.
*
* @see https://w3c.github.io/webdriver-bidi/#expand-a-storage-partition-spec
*/
#expandStoragePartitionSpec(partitionSpec) {
if (partitionSpec === null) {
partitionSpec = {};
}
if (partitionSpec.type === PartitionType.Context) {
const { context: contextId } = partitionSpec;
const browsingContext = this.#getBrowsingContext(contextId);
const principal = Services.scriptSecurityManager.createContentPrincipal(
browsingContext.currentURI,
{}
);
// Define browsing contexts associated storage partition as combination of user context id
// and the origin of the document in this browsing context. We also add here `isThirdPartyURI`
// which is required to filter out third-party cookies in case they are not allowed.
return {
// In case we have the browsing context of an iframe here, we perform a check
// if the URI of the top context is considered third-party to the URI of the iframe principal.
// It's considered a third-party if base domains or hosts (in case one or both base domains
// can not be determined) do not match.
isThirdPartyURI: browsingContext.parent
? principal.isThirdPartyURI(browsingContext.top.currentURI)
: false,
sourceOrigin: browsingContext.currentURI.prePath,
userContext: browsingContext.originAttributes.userContextId,
};
}
const partitionKey = {};
for (const keyName of PartitionKeyAttributes) {
if (keyName in partitionSpec) {
// Retrieve a platform user context id.
if (keyName === "userContext") {
partitionKey[keyName] = lazy.UserContextManager.getInternalIdById(
partitionSpec.userContext
);
} else {
partitionKey[keyName] = partitionSpec[keyName];
}
}
}
return partitionKey;
}
/**
* Prepare the partition key in the right format for returning to a client.
*/
#formatPartitionKey(partitionKey, originAttributes) {
if ("userContext" in partitionKey) {
// Exchange platform id for Webdriver BiDi id for the user context to return it to the client.
partitionKey.userContext = lazy.UserContextManager.getIdByInternalId(
partitionKey.userContext
);
}
// If sourceOrigin matches the cookie domain we don't set the partitionKey
// in the setCookie command. In that case we should also remove sourceOrigin
// from the returned partitionKey.
if (
originAttributes &&
"sourceOrigin" in partitionKey &&
originAttributes.partitionKey === ""
) {
delete partitionKey.sourceOrigin;
}
// This key is not used for partitioning and was required to only filter out third-party cookies.
delete partitionKey.isThirdPartyURI;
return partitionKey;
}
/**
* Retrieves a browsing context based on its id.
*
* @param {number} contextId
* Id of the browsing context.
* @returns {BrowsingContext}
* The browsing context.
* @throws {NoSuchFrameError}
* If the browsing context cannot be found.
*/
#getBrowsingContext(contextId) {
const context = lazy.TabManager.getBrowsingContextById(contextId);
if (context === null) {
throw new lazy.error.NoSuchFrameError(
`Browsing Context with id ${contextId} not found`
);
}
return context;
}
/**
* Since cookies retrieved from the platform API
* always contain expiry even for session cookies,
* we should check ourselves if it's a session cookie
* and do not return expiry in case it is.
*/
#getCookieExpiry(cookie) {
const { expiry, isSession } = cookie;
return isSession ? null : expiry;
}
#getCookieSize(cookie) {
const { name, value } = cookie;
return name.length + value.length;
}
/**
* Filter and serialize given cookies with provided filter.
*
* @see https://w3c.github.io/webdriver-bidi/#get-matching-cookies
*/
#getMatchingCookies(cookieStore, filter) {
const cookies = [];
const deserializedFilter = this.#deserializeFilter(filter);
for (const storedCookie of cookieStore) {
if (this.#matchCookie(storedCookie, deserializedFilter)) {
cookies.push(storedCookie);
}
}
return cookies;
}
/**
* Prepare the data in the required for platform API format.
*/
#getOriginAttributes(partitionKey, domain) {
const originAttributes = {};
if (partitionKey.sourceOrigin) {
if (
"isThirdPartyURI" in partitionKey &&
domain &&
!this.#shouldIncludePartitionedCookies() &&
partitionKey.sourceOrigin !== "about:"
) {
// This is a workaround until CHIPS support is enabled (see Bug 1898253).
// It handles the "context" type partitioning of the `setCookie` command
// (when domain is provided) and if partitioned cookies are disabled,
// but ignore `about` pаges.
const principal =
Services.scriptSecurityManager.createContentPrincipalFromOrigin(
partitionKey.sourceOrigin
);
// Do not set partition key if the cookie domain matches the `sourceOrigin`.
if (principal.host.endsWith(domain)) {
originAttributes.partitionKey = "";
} else {
originAttributes.partitionKey = ChromeUtils.getPartitionKeyFromURL(
partitionKey.sourceOrigin,
"",
false
);
}
} else {
originAttributes.partitionKey = ChromeUtils.getPartitionKeyFromURL(
partitionKey.sourceOrigin,
"",
false
);
}
}
if ("userContext" in partitionKey) {
originAttributes.userContextId = partitionKey.userContext;
}
return originAttributes;
}
#getSameSitePlatformProperty(sameSite) {
switch (sameSite) {
case "lax": {
return Ci.nsICookie.SAMESITE_LAX;
}
case "strict": {
return Ci.nsICookie.SAMESITE_STRICT;
}
}
return Ci.nsICookie.SAMESITE_NONE;
}
/**
* Return a cookie store of the storage partition for a given storage partition key.
*
* The implementation differs here from the spec, since in gecko there is no
* direct way to get all the cookies for a given partition key.
*
* @see https://w3c.github.io/webdriver-bidi/#get-the-cookie-store
*/
#getTheCookieStore(storagePartitionKey) {
let store = [];
// Prepare the data in the format required for the platform API.
const originAttributes = this.#getOriginAttributes(storagePartitionKey);
// Retrieve the cookies which exactly match a built partition attributes.
const cookiesWithOriginAttributes =
Services.cookies.getCookiesWithOriginAttributes(
JSON.stringify(originAttributes)
);
const isFirstPartyOrCrossSiteAllowed =
!storagePartitionKey.isThirdPartyURI ||
this.#shouldIncludeCrossSiteCookie();
// Check if we accessing the first party storage or cross-site cookies are allowed.
if (isFirstPartyOrCrossSiteAllowed) {
// In case we want to get the cookies for a certain `sourceOrigin`,
// we have to separately retrieve cookies for a hostname built from `sourceOrigin`,
// and with `partitionKey` equal an empty string to retrieve the cookies that which were set
// by this hostname but without `partitionKey`, e.g. with `document.cookie`.
if (storagePartitionKey.sourceOrigin) {
const url = new URL(storagePartitionKey.sourceOrigin);
const hostname = url.hostname;
const principal = Services.scriptSecurityManager.createContentPrincipal(
url.URI,
{}
);
const isSecureProtocol = principal.isOriginPotentiallyTrustworthy;
// We want to keep `userContext` id here, if it's present,
// but set the `partitionKey` to an empty string.
const cookiesMatchingHostname =
Services.cookies.getCookiesWithOriginAttributes(
JSON.stringify({ ...originAttributes, partitionKey: "" }),
hostname
);
for (const cookie of cookiesMatchingHostname) {
// Ignore secure cookies for non-secure protocols.
if (cookie.isSecure && !isSecureProtocol) {
continue;
}
store.push(cookie);
}
}
store = store.concat(cookiesWithOriginAttributes);
}
// If we're trying to access the store in the third party context and
// the preferences imply that we shouldn't include cross site cookies,
// but we should include partitioned cookies, add only partitioned cookies.
else if (this.#shouldIncludePartitionedCookies()) {
for (const cookie of cookiesWithOriginAttributes) {
if (cookie.isPartitioned) {
store.push(cookie);
}
}
}
return store;
}
/**
* Match a provided cookie with provided filter.
*
* @see https://w3c.github.io/webdriver-bidi/#match-cookie
*/
#matchCookie(storedCookie, filter) {
for (const [fieldName, value] of Object.entries(filter)) {
// Since we set `null` to not specified values, we have to check for `null` here
// and not match on these values.
if (value === null) {
continue;
}
let storedCookieValue = storedCookie[fieldName];
// The platform represantation of cookie doesn't contain a size field,
// so we have to calculate it to match.
if (fieldName === "size") {
storedCookieValue = this.#getCookieSize(storedCookie);
}
// Let's map any SAMESITE_UNSET to SAMESITE_NONE.
if (
fieldName === "sameSite" &&
storedCookieValue === Ci.nsICookie.SAMESITE_UNSET
) {
storedCookieValue = Ci.nsICookie.SAMESITE_NONE;
}
if (storedCookieValue !== value) {
return false;
}
}
return true;
}
/**
* Serialize a cookie.
*
* @see https://w3c.github.io/webdriver-bidi/#serialize-cookie
*/
#serializeCookie(storedCookie) {
const cookie = {};
for (const [serializedName, cookieName] of Object.entries(
CookieFieldsMapping
)) {
switch (serializedName) {
case "expiry": {
const expiry = this.#getCookieExpiry(storedCookie);
if (expiry !== null) {
cookie.expiry = expiry;
}
break;
}
case "sameSite":
cookie.sameSite = SameSiteType[storedCookie.sameSite];
break;
case "size":
cookie.size = this.#getCookieSize(storedCookie);
break;
case "value":
// Bug 1879309. Add support for non-UTF8 cookies,
// when a byte representation of value is available.
// For now, use a value field, which is returned as a string.
cookie.value = {
type: lazy.BytesValueType.String,
value: storedCookie.value,
};
break;
default:
cookie[serializedName] = storedCookie[cookieName];
}
}
return cookie;
}
#shouldIncludeCrossSiteCookie() {
const cookieBehavior = Services.prefs.getIntPref(PREF_COOKIE_BEHAVIOR);
if (
cookieBehavior === Ci.nsICookieService.BEHAVIOR_REJECT_FOREIGN ||
cookieBehavior ===
Ci.nsICookieService.BEHAVIOR_REJECT_TRACKER_AND_PARTITION_FOREIGN
) {
return false;
}
return true;
}
#shouldIncludePartitionedCookies() {
const cookieBehavior = Services.prefs.getIntPref(PREF_COOKIE_BEHAVIOR);
return (
cookieBehavior ===
Ci.nsICookieService.BEHAVIOR_REJECT_TRACKER_AND_PARTITION_FOREIGN &&
lazy.cookieCHIPSEnabled
);
}
}
export const storage = StorageModule;