Add Tampermonkey WebExtension manifest and managed storage compatibility

This commit is contained in:
wuggy 2026-09-19 04:45:24 -07:00
commit cc3106406f
5 changed files with 80 additions and 3 deletions

View file

@ -197,6 +197,19 @@ this.ExtensionStorage = {
});
},
getManaged(keys) {
// Managed storage is populated by enterprise policy, which this UXP
// branch does not implement. Return the requested defaults, matching the
// WebExtension storage contract for an empty managed area.
if (keys === null || keys === undefined) {
return Promise.resolve({});
}
if (typeof(keys) == "object" && !Array.isArray(keys)) {
return Promise.resolve(Object.assign({}, keys));
}
return Promise.resolve({});
},
addOnChangedListener(extensionId, listener) {
let listeners = this.listeners.get(extensionId) || new Set();
listeners.add(listener);

View file

@ -41,6 +41,27 @@ function storageApiFactory(context) {
},
},
managed: {
get: function(keys) {
keys = sanitize(keys);
return context.childManager.callParentAsyncFunction("storage.managed.get", [
keys,
]);
},
set: function() {
throw new context.cloneScope.Error(
"storage.managed is read-only");
},
remove: function() {
throw new context.cloneScope.Error(
"storage.managed is read-only");
},
clear: function() {
throw new context.cloneScope.Error(
"storage.managed is read-only");
},
},
sync: {
get: function(keys) {
keys = sanitize(keys);

View file

@ -29,6 +29,27 @@ function storageApiFactory(context) {
},
},
// UXP has no enterprise managed-storage backend. Expose the namespace
// as an empty, read-only area so extensions can feature-detect it and
// continue using their defaults.
managed: {
get: function(spec) {
return ExtensionStorage.getManaged(spec);
},
set: function() {
throw new context.cloneScope.Error(
"storage.managed is read-only");
},
remove: function() {
throw new context.cloneScope.Error(
"storage.managed is read-only");
},
clear: function() {
throw new context.cloneScope.Error(
"storage.managed is read-only");
},
},
onChanged: new EventManager(context, "storage.onChanged", fire => {
let listenerLocal = changes => {
fire(changes, "local");

View file

@ -183,6 +183,29 @@
"optional": true
},
"optional_permissions": {
"type": "array",
"items": {
"choices": [
{ "$ref": "Permission" },
{
"type": "string",
"deprecated": "Unknown optional permission ${value}"
}
]
},
"optional": true
},
"user_scripts": {
"type": "object",
"optional": true,
"properties": {
"api_script": { "$ref": "ExtensionURL" }
},
"additionalProperties": { "$ref": "UnrecognizedProperty" }
},
"web_accessible_resources": {
"type": "array",
"items": { "type": "string" },
@ -218,6 +241,7 @@
"enum": [
"alarms",
"clipboardWrite",
"contextualIdentities",
"dns",
"idle",
"menus",
@ -387,8 +411,7 @@
},
{
"id": "PersistentBackgroundProperty",
"type": "boolean",
"deprecated": "Event pages are not currently supported. This will run as a persistent background page."
"type": "boolean"
}
]
}

View file

@ -220,7 +220,6 @@
}
},
"managed": {
"unsupported": true,
"$ref": "StorageArea",
"description": "Items in the <code>managed</code> storage area are set by the domain administrator, and are read-only for the extension; trying to modify this namespace results in an error."
}