Bug 1854581 - [bidi] Implement "storage.deleteCookies" command. r=webdriver-reviewers,whimboo

Differential Revision: https://phabricator.services.mozilla.com/D200935
This commit is contained in:
Alexandra Borovova 2024-02-27 17:26:16 +00:00
parent 1abb9944e0
commit cbd246264a

View file

@ -118,6 +118,56 @@ class StorageModule extends Module {
* to retrieve the cookies. * 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.
* @throws {UnsupportedOperationError}
* Raised when the command is called with `userContext` as
* in `partition` argument.
*/
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
);
}
// Bug 1875255. Exchange platform id for Webdriver BiDi id for the user context to return it to the client.
// For now we use platform user context id for returning cookies for a specific browsing context in the platform API,
// but we can not return it directly to the client, so for now we just remove it from the response.
delete partitionKey.userContext;
return { partitionKey };
}
/** /**
* Retrieve zero or more cookies which match a set of provided parameters. * Retrieve zero or more cookies which match a set of provided parameters.
* *
@ -145,18 +195,23 @@ class StorageModule extends Module {
const { partition: partitionSpec = null } = options; const { partition: partitionSpec = null } = options;
this.#assertPartition(partitionSpec); this.#assertPartition(partitionSpec);
filter = this.#assertGetCookieFilter(filter); filter = this.#assertCookieFilter(filter);
const partitionKey = this.#expandStoragePartitionSpec(partitionSpec); const partitionKey = this.#expandStoragePartitionSpec(partitionSpec);
const store = this.#getTheCookieStore(partitionKey); const store = this.#getTheCookieStore(partitionKey);
const cookies = this.#getMatchingCookies(store, filter); const cookies = this.#getMatchingCookies(store, filter);
const serializedCookies = [];
for (const cookie of cookies) {
serializedCookies.push(this.#serializeCookie(cookie));
}
// Bug 1875255. Exchange platform id for Webdriver BiDi id for the user context to return it to the client. // Bug 1875255. Exchange platform id for Webdriver BiDi id for the user context to return it to the client.
// For now we use platform user context id for returning cookies for a specific browsing context in the platform API, // For now we use platform user context id for returning cookies for a specific browsing context in the platform API,
// but we can not return it directly to the client, so for now we just remove it from the response. // but we can not return it directly to the client, so for now we just remove it from the response.
delete partitionKey.userContext; delete partitionKey.userContext;
return { cookies, partitionKey }; return { cookies: serializedCookies, partitionKey };
} }
/** /**
@ -318,7 +373,7 @@ class StorageModule extends Module {
} }
} }
#assertGetCookieFilter(filter) { #assertCookieFilter(filter) {
lazy.assert.object( lazy.assert.object(
filter, filter,
`Expected "filter" to be an object, got ${filter}` `Expected "filter" to be an object, got ${filter}`
@ -504,6 +559,40 @@ class StorageModule extends Module {
); );
} }
/**
* 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 = this.#deserializeProtocolBytes(value);
break;
default:
deserializedValue = value;
}
deserializedFilter[deserializedName] = deserializedValue;
}
return deserializedFilter;
}
/** /**
* Deserialize the value to string, since platform API * Deserialize the value to string, since platform API
* returns cookie's value as a string. * returns cookie's value as a string.
@ -595,11 +684,11 @@ class StorageModule extends Module {
*/ */
#getMatchingCookies(cookieStore, filter) { #getMatchingCookies(cookieStore, filter) {
const cookies = []; const cookies = [];
const deserializedFilter = this.#deserializeFilter(filter);
for (const storedCookie of cookieStore) { for (const storedCookie of cookieStore) {
const serializedCookie = this.#serializeCookie(storedCookie); if (this.#matchCookie(storedCookie, deserializedFilter)) {
if (this.#matchCookie(serializedCookie, filter)) { cookies.push(storedCookie);
cookies.push(serializedCookie);
} }
} }
return cookies; return cookies;
@ -702,19 +791,23 @@ class StorageModule extends Module {
* @see https://w3c.github.io/webdriver-bidi/#match-cookie * @see https://w3c.github.io/webdriver-bidi/#match-cookie
*/ */
#matchCookie(storedCookie, filter) { #matchCookie(storedCookie, filter) {
for (const [fieldName] of Object.entries(CookieFieldsMapping)) { for (const [fieldName, value] of Object.entries(filter)) {
let value = filter[fieldName]; // Since we set `null` to not specified values, we have to check for `null` here
if (value !== null) { // and not match on these values.
let storedCookieValue = storedCookie[fieldName]; if (value === null) {
continue;
}
if (fieldName === "value") { let storedCookieValue = storedCookie[fieldName];
value = this.#deserializeProtocolBytes(value);
storedCookieValue = this.#deserializeProtocolBytes(storedCookieValue);
}
if (storedCookieValue !== value) { // The platform represantation of cookie doesn't contain a size field,
return false; // so we have to calculate it to match.
} if (fieldName === "size") {
storedCookieValue = this.#getCookieSize(storedCookie);
}
if (storedCookieValue !== value) {
return false;
} }
} }