Files
sousa-gecko/devtools/shared/specs/storage.js
T
canalun 88326e4dd9 Bug 1655941 - Add storage.sync support to the extension storage inspector. r=nchevobbe,devtools-backward-compat-reviewers,devtools-reviewers
Display storage.sync items alongside storage.local items in the extension
storage inspector.

Because storage.local and storage.sync can each contain an item with the same
name, the item name alone is no longer unique. Use a compound uniqueKey
consisting of the item name and storage area to disambiguate them within the
same table. This approach follows the one used by the cookies storage actor.

The Storage Inspector client automatically uses the first field returned by
getFields() as the unique identifier for table rows, so exposing the compound
uniqueKey there lets existing interfaces such as getValuesForHost(),
editItem(), and removeItem() receive it without changes to their external
signatures.

Differential Revision: https://phabricator.services.mozilla.com/D304326
2026-06-11 14:18:50 +00:00

322 lines
6.7 KiB
JavaScript

/* 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/. */
"use strict";
const protocol = require("resource://devtools/shared/protocol.js");
const { Arg, RetVal, types } = protocol;
const childSpecs = {};
function createStorageSpec(options) {
// common methods for all storage types
const methods = {
getStoreObjects: {
request: {
host: Arg(0),
names: Arg(1, "nullable:array:string"),
options: Arg(2, "nullable:json"),
},
response: RetVal(options.storeObjectType),
},
getFields: {
request: {
subType: Arg(0, "nullable:string"),
},
response: {
value: RetVal("json"),
},
},
};
// extra methods specific for storage type
Object.assign(methods, options.methods);
childSpecs[options.typeName] = protocol.generateActorSpec({
typeName: options.typeName,
methods,
events: {
"single-store-update": {
type: "storesUpdate",
data: Arg(0, "storeUpdateObject"),
},
"single-store-cleared": {
type: "storesCleared",
data: Arg(0, "json"),
},
},
});
}
// Cookies store object
types.addDictType("cookieobject", {
uniqueKey: "string",
name: "string",
value: "longstring",
path: "nullable:string",
host: "string",
hostOnly: "boolean",
isSecure: "boolean",
isHttpOnly: "boolean",
creationTime: "number",
updateTime: "number",
lastAccessed: "number",
expires: "number",
});
// Array of cookie store objects
types.addDictType("cookiestoreobject", {
total: "number",
offset: "number",
data: "array:nullable:cookieobject",
});
// Result of add/edit cookie operation: can throw error
types.addDictType("cookieoperationresult", {
errorString: "nullable:string",
});
// Common methods for edit/remove
const editRemoveMethods = {
getFields: {
request: {},
response: {
value: RetVal("json"),
},
},
editItem: {
request: {
data: Arg(0, "json"),
},
response: {},
},
removeItem: {
request: {
host: Arg(0, "string"),
name: Arg(1, "string"),
},
response: {},
},
};
// Cookies actor spec
createStorageSpec({
typeName: "cookies",
storeObjectType: "cookiestoreobject",
methods: Object.assign(
{},
editRemoveMethods,
{
addItem: {
request: {
guid: Arg(0, "string"),
host: Arg(1, "nullable:string"),
},
response: RetVal("cookieoperationresult"),
},
},
{
editItem: {
request: editRemoveMethods.editItem.request,
response: RetVal("cookieoperationresult"),
},
},
{
removeAll: {
request: {
host: Arg(0, "string"),
domain: Arg(1, "nullable:string"),
},
response: {},
},
},
{
removeAllSessionCookies: {
request: {
host: Arg(0, "string"),
domain: Arg(1, "nullable:string"),
},
response: {},
},
}
),
});
// Local Storage / Session Storage store object
types.addDictType("storageobject", {
name: "string",
value: "longstring",
});
// Common methods for local/session storage
const storageMethods = Object.assign(
{},
editRemoveMethods,
{
addItem: {
request: {
guid: Arg(0, "string"),
host: Arg(1, "nullable:string"),
},
response: {},
},
},
{
removeAll: {
request: {
host: Arg(0, "string"),
},
response: {},
},
}
);
// Array of Local Storage / Session Storage store objects
types.addDictType("storagestoreobject", {
total: "number",
offset: "number",
data: "array:nullable:storageobject",
});
createStorageSpec({
typeName: "localStorage",
storeObjectType: "storagestoreobject",
methods: storageMethods,
});
createStorageSpec({
typeName: "sessionStorage",
storeObjectType: "storagestoreobject",
methods: storageMethods,
});
types.addDictType("extensionobject", {
uniqueKey: "string",
name: "nullable:string",
value: "nullable:longstring",
area: "string",
isValueEditable: "boolean",
});
types.addDictType("extensionstoreobject", {
total: "number",
offset: "number",
data: "array:nullable:extensionobject",
});
createStorageSpec({
typeName: "extensionStorage",
storeObjectType: "extensionstoreobject",
// Same as storageMethods except for addItem
methods: Object.assign({}, editRemoveMethods, {
removeAll: {
request: {
host: Arg(0, "string"),
},
response: {},
},
}),
});
types.addDictType("cacheobject", {
url: "string",
status: "string",
});
// Array of Cache store objects
types.addDictType("cachestoreobject", {
total: "number",
offset: "number",
data: "array:nullable:cacheobject",
});
// Cache storage spec
createStorageSpec({
typeName: "Cache",
storeObjectType: "cachestoreobject",
methods: {
removeAll: {
request: {
host: Arg(0, "string"),
name: Arg(1, "string"),
},
response: {},
},
removeItem: {
request: {
host: Arg(0, "string"),
name: Arg(1, "string"),
},
response: {},
},
},
});
// Indexed DB store object
// This is a union on idb object, db metadata object and object store metadata
// object
types.addDictType("idbobject", {
uniqueKey: "string",
name: "nullable:string",
db: "nullable:string",
objectStore: "nullable:string",
origin: "nullable:string",
version: "nullable:number",
storage: "nullable:string",
objectStores: "nullable:number",
keyPath: "nullable:string",
autoIncrement: "nullable:boolean",
indexes: "nullable:string",
value: "nullable:longstring",
});
// Array of Indexed DB store objects
types.addDictType("idbstoreobject", {
total: "number",
offset: "number",
data: "array:nullable:idbobject",
});
// Result of Indexed DB delete operation: can block or throw error
types.addDictType("idbdeleteresult", {
blocked: "nullable:boolean",
error: "nullable:string",
});
createStorageSpec({
typeName: "indexedDB",
storeObjectType: "idbstoreobject",
methods: {
removeDatabase: {
request: {
host: Arg(0, "string"),
name: Arg(1, "string"),
},
response: RetVal("idbdeleteresult"),
},
removeAll: {
request: {
host: Arg(0, "string"),
name: Arg(1, "string"),
},
response: {},
},
removeItem: {
request: {
host: Arg(0, "string"),
name: Arg(1, "string"),
},
response: {},
},
},
});
// Update notification object
types.addDictType("storeUpdateObject", {
changed: "nullable:json",
deleted: "nullable:json",
added: "nullable:json",
});
exports.childSpecs = childSpecs;