Replace Ed25519 with hashed API tokens and an in-Firefox client manager.
This commit is contained in:
+55
-2
@@ -21,6 +21,8 @@ const ALLOWED = {
|
||||
|
||||
let port = null;
|
||||
let reconnectTimer = null;
|
||||
let hostUp = false;
|
||||
const adminWait = new Map();
|
||||
|
||||
function asArray(value) {
|
||||
if (value === undefined || value === null) {
|
||||
@@ -29,7 +31,7 @@ function asArray(value) {
|
||||
return Array.isArray(value) ? value : [value];
|
||||
}
|
||||
|
||||
async function dispatch(message) {
|
||||
async function dispatchBookmark(message) {
|
||||
const method = message && message.method;
|
||||
const fn = ALLOWED[method];
|
||||
if (!fn) {
|
||||
@@ -38,12 +40,42 @@ async function dispatch(message) {
|
||||
return fn(...asArray(message.args));
|
||||
}
|
||||
|
||||
function adminCall(method, args) {
|
||||
if (!port) {
|
||||
return Promise.reject(new Error("native host is not connected"));
|
||||
}
|
||||
const id = crypto.randomUUID();
|
||||
return new Promise((resolve, reject) => {
|
||||
const timer = setTimeout(() => {
|
||||
adminWait.delete(id);
|
||||
reject(new Error("host did not answer"));
|
||||
}, 8000);
|
||||
adminWait.set(id, { resolve, reject, timer });
|
||||
port.postMessage({ type: "admin", id, method, args: args || [] });
|
||||
});
|
||||
}
|
||||
|
||||
function attach(nextPort) {
|
||||
port = nextPort;
|
||||
hostUp = true;
|
||||
port.onMessage.addListener(async (message) => {
|
||||
if (message && message.type === "admin-result") {
|
||||
const pending = adminWait.get(message.id);
|
||||
if (!pending) {
|
||||
return;
|
||||
}
|
||||
adminWait.delete(message.id);
|
||||
clearTimeout(pending.timer);
|
||||
if (message.ok) {
|
||||
pending.resolve(message.result);
|
||||
} else {
|
||||
pending.reject(new Error(message.error || "admin failed"));
|
||||
}
|
||||
return;
|
||||
}
|
||||
const id = message && message.id;
|
||||
try {
|
||||
const result = await dispatch(message);
|
||||
const result = await dispatchBookmark(message);
|
||||
port.postMessage({ id, ok: true, result });
|
||||
} catch (err) {
|
||||
port.postMessage({
|
||||
@@ -55,6 +87,12 @@ function attach(nextPort) {
|
||||
});
|
||||
port.onDisconnect.addListener(() => {
|
||||
port = null;
|
||||
hostUp = false;
|
||||
for (const [id, pending] of adminWait.entries()) {
|
||||
clearTimeout(pending.timer);
|
||||
pending.reject(new Error("native host disconnected"));
|
||||
adminWait.delete(id);
|
||||
}
|
||||
scheduleReconnect();
|
||||
});
|
||||
}
|
||||
@@ -73,9 +111,24 @@ 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) => {
|
||||
const kind = message && message.type;
|
||||
if (kind === "status") {
|
||||
return Promise.resolve({ hostUp, port: 17634 });
|
||||
}
|
||||
if (kind === "admin") {
|
||||
return adminCall(message.method, message.args).then(
|
||||
(result) => ({ ok: true, result }),
|
||||
(err) => ({ ok: false, error: err.message })
|
||||
);
|
||||
}
|
||||
return undefined;
|
||||
});
|
||||
|
||||
connect();
|
||||
|
||||
Reference in New Issue
Block a user