Files
bookmarks-api/extension/background.js
T

115 lines
3.1 KiB
JavaScript

"use strict";
const HOST_NAME = "com.easygoingaming.firefox_agent_bridge";
const RECONNECT_MS = 2000;
const ALLOWED = {
"meta.ping": async () => ({ ok: true, extension: "bookmarks-api" }),
"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;
let hostUp = false;
function asArray(value) {
if (value === undefined || value === null) {
return [];
}
return Array.isArray(value) ? value : [value];
}
async function dispatchBookmark(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;
hostUp = true;
port.onMessage.addListener(async (message) => {
if (message && message.type === "auth") {
try {
const client = await findClientByTokenHash(message.token_hash);
port.postMessage({
type: "auth-result",
id: message.id,
ok: Boolean(client),
client: client || null,
});
} catch (err) {
port.postMessage({
type: "auth-result",
id: message.id,
ok: false,
error: err && err.message ? err.message : String(err),
});
}
return;
}
if (message && message.type) {
return;
}
const id = message && message.id;
try {
const result = await dispatchBookmark(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;
hostUp = false;
scheduleReconnect();
});
}
function scheduleReconnect() {
if (reconnectTimer) {
return;
}
reconnectTimer = setTimeout(() => {
reconnectTimer = null;
connect();
}, RECONNECT_MS);
}
function connect() {
try {
attach(browser.runtime.connectNative(HOST_NAME));
} catch (err) {
hostUp = false;
console.error("native host connect failed", err);
scheduleReconnect();
}
}
browser.runtime.onMessage.addListener((message) => {
if (message && message.type === "status") {
return Promise.resolve({ hostUp, port: 17634 });
}
return undefined;
});
connect();