2022-07-29 10:37:20 +00:00
|
|
|
export {};
|
|
|
|
|
|
|
|
// Need to declare the browser variable so typescript doesn't complain. We
|
|
|
|
// declare it as 'any' because typescript doesn't know type 'Browser'.
|
|
|
|
declare var browser: any;
|
|
|
|
|
|
|
|
// This is the same as the dataFn declared in libskynet, but since it is the
|
|
|
|
// only import I decided to re-implement it here.
|
|
|
|
type dataFn = (data?: any) => void;
|
|
|
|
|
|
|
|
// Create the object that will track the current auth status of the kernel. We
|
|
|
|
// need a promise because the client may connect to the bridge after all of the
|
|
|
|
// auth messages have been processed, there's no guarantee that the client will
|
|
|
|
// catch the initial messages.
|
|
|
|
//
|
|
|
|
// blockForAuthStatus is a promise that will resolve when the auth status is
|
|
|
|
// initially known. 'authStatus' is the object that contains the latest auth
|
|
|
|
// information from
|
|
|
|
let authStatus: any; // matches the data field of the kernelAuthStatus message
|
|
|
|
let authStatusKnown = false;
|
|
|
|
let authStatusResolve: dataFn;
|
|
|
|
let blockForAuthStatus: Promise<void> = new Promise((resolve) => {
|
|
|
|
authStatusResolve = resolve;
|
|
|
|
});
|
|
|
|
|
|
|
|
// Create the handler for messages from the background page. The background
|
|
|
|
// will be exclusively relaying messages from the bridge to the kernel.
|
|
|
|
function handleBackgroundMessage(data: any) {
|
|
|
|
// If this is the first auth status message from the kernel, resolve the
|
|
|
|
// auth promise.
|
|
|
|
if (data.method === "kernelAuthStatus") {
|
|
|
|
authStatus = data.data;
|
|
|
|
if (authStatusKnown === false) {
|
|
|
|
authStatusKnown = true;
|
|
|
|
authStatusResolve();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Pass the message through to the main page.
|
|
|
|
window.postMessage(data);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Connect to the background page.
|
|
|
|
let port = browser.runtime.connect();
|
|
|
|
port.onMessage.addListener(handleBackgroundMessage);
|
|
|
|
|
|
|
|
// handleVersion will send a response providing the version of the bridge. When
|
|
|
|
// the bridge version is queried, the bridge assumes that a new consumer has
|
|
|
|
// appeared which will need the auth status of the kernel repeated.
|
|
|
|
function handleVersion(data: any) {
|
|
|
|
// Send a message indicating that the bridge is alive.
|
2022-07-29 23:42:49 +00:00
|
|
|
const message = {
|
2022-07-29 10:37:20 +00:00
|
|
|
nonce: data.nonce,
|
|
|
|
method: "response",
|
|
|
|
err: null,
|
|
|
|
data: {
|
|
|
|
version: "v0.2.0",
|
|
|
|
},
|
2022-07-29 23:42:49 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
window.postMessage(message);
|
|
|
|
port.postMessage(message);
|
2022-07-29 10:37:20 +00:00
|
|
|
|
|
|
|
// Wait until the kernel auth status is known, then send a message with
|
|
|
|
// the kernel auth status.
|
|
|
|
blockForAuthStatus.then(() => {
|
|
|
|
window.postMessage({
|
|
|
|
method: "kernelAuthStatus",
|
|
|
|
data: authStatus,
|
|
|
|
});
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
// handleKernelQuery handles messages sent by the page that are intended to
|
|
|
|
// eventually reach the kernel.
|
|
|
|
function handleKernelQuery(data: any) {
|
|
|
|
// Check for a kernel query. We already checked that a nonce exists.
|
|
|
|
if (!("data" in data)) {
|
|
|
|
window.postMessage({
|
|
|
|
nonce: data.nonce,
|
|
|
|
method: "response",
|
|
|
|
err: "missing data from newKernelQuery message: " + JSON.stringify(data),
|
|
|
|
});
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Pass the message along to the kernel. The caller is responsible for
|
|
|
|
// ensuring the nonce is unique.
|
|
|
|
port.postMessage(data.data);
|
|
|
|
}
|
|
|
|
|
|
|
|
// handleQueryUpdate will forward an update to a query to the kernel.
|
|
|
|
function handleQueryUpdate(data: any) {
|
|
|
|
// Send the update to the kernel.
|
|
|
|
port.postMessage(data);
|
|
|
|
}
|
|
|
|
|
|
|
|
// This is the listener for the content script, it will receive messages from
|
|
|
|
// the page script that it can forward to the kernel.
|
|
|
|
function handleMessage(event: MessageEvent) {
|
|
|
|
// Throughout this function, errors are typically not logged because we
|
|
|
|
// will be receiving all messages sent to the window, including messages
|
|
|
|
// that have nothing to do with the Skynet kernel protocol. If there is an
|
|
|
|
// error, we generally assume that the message has an unrelated purpose and
|
|
|
|
// doesn't need to be logged.
|
|
|
|
|
|
|
|
// Authenticate the message as a message from the kernel.
|
|
|
|
if (event.source !== window) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
// Check that a nonce and method were both provided.
|
|
|
|
if (!("nonce" in event.data) || !("method" in event.data)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Switch on the method.
|
|
|
|
if (event.data.method === "kernelBridgeVersion") {
|
|
|
|
handleVersion(event.data);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (event.data.method === "newKernelQuery") {
|
|
|
|
handleKernelQuery(event.data);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (event.data.method === "queryUpdate") {
|
|
|
|
handleQueryUpdate(event.data);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Everything else just gets ignored.
|
|
|
|
}
|
|
|
|
window.addEventListener("message", handleMessage);
|
2022-07-31 04:51:02 +00:00
|
|
|
port.postMessage({
|
|
|
|
method: "bridgeLoaded",
|
|
|
|
});
|