Initial Firefox Agent Bridge: allowlisted bookmarks RPC for local scripts.
This commit is contained in:
@@ -0,0 +1,81 @@
|
||||
"use strict";
|
||||
|
||||
const HOST_NAME = "com.easygoingaming.firefox_agent_bridge";
|
||||
const RECONNECT_MS = 2000;
|
||||
|
||||
const ALLOWED = {
|
||||
"meta.ping": async () => ({ ok: true, extension: "firefox-agent-bridge" }),
|
||||
"meta.methods": async () => Object.keys(ALLOWED).sort(),
|
||||
"bookmarks.getTree": () => browser.bookmarks.getTree(),
|
||||
"bookmarks.getSubTree": (id) => browser.bookmarks.getSubTree(id),
|
||||
"bookmarks.getChildren": (id) => browser.bookmarks.getChildren(id),
|
||||
"bookmarks.get": (idOrIds) => browser.bookmarks.get(idOrIds),
|
||||
"bookmarks.search": (query) => browser.bookmarks.search(query),
|
||||
"bookmarks.create": (details) => browser.bookmarks.create(details),
|
||||
"bookmarks.update": (id, changes) => browser.bookmarks.update(id, changes),
|
||||
"bookmarks.move": (id, destination) => browser.bookmarks.move(id, destination),
|
||||
"bookmarks.remove": (id) => browser.bookmarks.remove(id),
|
||||
"bookmarks.removeTree": (id) => browser.bookmarks.removeTree(id),
|
||||
"bookmarks.getRecent": (numberOfItems) => browser.bookmarks.getRecent(numberOfItems),
|
||||
};
|
||||
|
||||
let port = null;
|
||||
let reconnectTimer = null;
|
||||
|
||||
function asArray(value) {
|
||||
if (value === undefined || value === null) {
|
||||
return [];
|
||||
}
|
||||
return Array.isArray(value) ? value : [value];
|
||||
}
|
||||
|
||||
async function dispatch(message) {
|
||||
const method = message && message.method;
|
||||
const fn = ALLOWED[method];
|
||||
if (!fn) {
|
||||
throw new Error(`method not allowed: ${method || "(missing)"}`);
|
||||
}
|
||||
return fn(...asArray(message.args));
|
||||
}
|
||||
|
||||
function attach(nextPort) {
|
||||
port = nextPort;
|
||||
port.onMessage.addListener(async (message) => {
|
||||
const id = message && message.id;
|
||||
try {
|
||||
const result = await dispatch(message);
|
||||
port.postMessage({ id, ok: true, result });
|
||||
} catch (err) {
|
||||
port.postMessage({
|
||||
id,
|
||||
ok: false,
|
||||
error: err && err.message ? err.message : String(err),
|
||||
});
|
||||
}
|
||||
});
|
||||
port.onDisconnect.addListener(() => {
|
||||
port = null;
|
||||
scheduleReconnect();
|
||||
});
|
||||
}
|
||||
|
||||
function scheduleReconnect() {
|
||||
if (reconnectTimer) {
|
||||
return;
|
||||
}
|
||||
reconnectTimer = setTimeout(() => {
|
||||
reconnectTimer = null;
|
||||
connect();
|
||||
}, RECONNECT_MS);
|
||||
}
|
||||
|
||||
function connect() {
|
||||
try {
|
||||
attach(browser.runtime.connectNative(HOST_NAME));
|
||||
} catch (err) {
|
||||
console.error("native host connect failed", err);
|
||||
scheduleReconnect();
|
||||
}
|
||||
}
|
||||
|
||||
connect();
|
||||
@@ -0,0 +1,16 @@
|
||||
{
|
||||
"manifest_version": 3,
|
||||
"name": "Firefox Agent Bridge",
|
||||
"version": "0.1.0",
|
||||
"description": "Expose an allowlisted WebExtension API to local scripts and agents over native messaging.",
|
||||
"browser_specific_settings": {
|
||||
"gecko": {
|
||||
"id": "firefox-agent-bridge@easygoingaming.com",
|
||||
"strict_min_version": "115.0"
|
||||
}
|
||||
},
|
||||
"permissions": ["bookmarks", "nativeMessaging"],
|
||||
"background": {
|
||||
"scripts": ["background.js"]
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user