|
|
|
@ -24,19 +24,6 @@ interface queryMap {
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
declare global {
|
|
|
|
|
interface Window {
|
|
|
|
|
browser: any;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const IS_EXTENSION =
|
|
|
|
|
window.browser?.runtime?.id &&
|
|
|
|
|
window.location.pathname.includes("_generated_background_page.html");
|
|
|
|
|
|
|
|
|
|
const EXTENSION_KERNEL_ORIGIN = "http://kernel.lume";
|
|
|
|
|
const EXTENSION_HOSTED_ORIGIN = "https://kernel.lumeweb.com";
|
|
|
|
|
|
|
|
|
|
// Create the queryMap.
|
|
|
|
|
const queries: queryMap = {};
|
|
|
|
|
|
|
|
|
@ -83,29 +70,20 @@ function handleMessage(event: MessageEvent) {
|
|
|
|
|
// Ignore all messages that aren't from approved kernel sources. The two
|
|
|
|
|
// approved sources are skt.us and the browser extension bridge (which has
|
|
|
|
|
// an event.source equal to 'window')
|
|
|
|
|
const FROM_KERNEL =
|
|
|
|
|
if (
|
|
|
|
|
event.source !== window &&
|
|
|
|
|
event.origin === EXTENSION_KERNEL_ORIGIN &&
|
|
|
|
|
IS_EXTENSION;
|
|
|
|
|
|
|
|
|
|
const FROM_HOSTED_KERNEL =
|
|
|
|
|
event.source !== window && event.origin === EXTENSION_HOSTED_ORIGIN;
|
|
|
|
|
|
|
|
|
|
if (!FROM_KERNEL && !FROM_HOSTED_KERNEL) {
|
|
|
|
|
event.origin !== "https://kernel.lumeweb.com"
|
|
|
|
|
) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (IS_EXTENSION && !event.data?.data) {
|
|
|
|
|
event.data.data = Object.assign({}, event.data);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Ignore any messages that don't have a method and data field.
|
|
|
|
|
if (!("method" in event.data) || !("data" in event.data)) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Handle logging messages.
|
|
|
|
|
if (event.data.method === "log" && !IS_EXTENSION) {
|
|
|
|
|
if (event.data.method === "log") {
|
|
|
|
|
// We display the logging message if the kernel is a browser
|
|
|
|
|
// extension, so that the kernel's logs appear in the app
|
|
|
|
|
// console as well as the extension console. If the kernel is
|
|
|
|
@ -127,7 +105,7 @@ function handleMessage(event: MessageEvent) {
|
|
|
|
|
if (event.data.method === "kernelAuthStatus") {
|
|
|
|
|
// If we have received an auth status message, it means the bootloader
|
|
|
|
|
// at a minimum is working.
|
|
|
|
|
if (!initResolved) {
|
|
|
|
|
if (initResolved === false) {
|
|
|
|
|
initResolved = true;
|
|
|
|
|
|
|
|
|
|
// We can't actually establish that init is complete until the
|
|
|
|
@ -138,30 +116,19 @@ function handleMessage(event: MessageEvent) {
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (IS_EXTENSION && event.data.data.kernelLoaded === "success") {
|
|
|
|
|
const nonce = nextNonce();
|
|
|
|
|
queries[nonce] = {
|
|
|
|
|
resolve: sourceResolve,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const kernelMessage = {
|
|
|
|
|
method: "version",
|
|
|
|
|
nonce,
|
|
|
|
|
data: null,
|
|
|
|
|
};
|
|
|
|
|
kernelSource.postMessage(kernelMessage, kernelOrigin);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// If the auth status message says that login is complete, it means
|
|
|
|
|
// that the user is logged in.
|
|
|
|
|
if (!loginResolved && event.data.data.loginComplete) {
|
|
|
|
|
if (loginResolved === false && event.data.data.loginComplete === true) {
|
|
|
|
|
loginResolved = true;
|
|
|
|
|
loginResolve();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// If the auth status message says that the kernel loaded, it means
|
|
|
|
|
// that the kernel is ready to receive messages.
|
|
|
|
|
if (!kernelLoadedResolved && event.data.data.kernelLoaded !== "not yet") {
|
|
|
|
|
if (
|
|
|
|
|
kernelLoadedResolved === false &&
|
|
|
|
|
event.data.data.kernelLoaded !== "not yet"
|
|
|
|
|
) {
|
|
|
|
|
kernelLoadedResolved = true;
|
|
|
|
|
if (event.data.data.kernelLoaded === "success") {
|
|
|
|
|
kernelLoadedResolve(null);
|
|
|
|
@ -172,8 +139,8 @@ function handleMessage(event: MessageEvent) {
|
|
|
|
|
|
|
|
|
|
// If we have received a message indicating that the user has logged
|
|
|
|
|
// out, we need to reload the page and reset the auth process.
|
|
|
|
|
if (event.data.data.logoutComplete) {
|
|
|
|
|
if (!logoutResolved) {
|
|
|
|
|
if (event.data.data.logoutComplete === true) {
|
|
|
|
|
if (logoutResolved === false) {
|
|
|
|
|
logoutResolve();
|
|
|
|
|
}
|
|
|
|
|
window.location.reload();
|
|
|
|
@ -231,14 +198,14 @@ function launchKernelFrame() {
|
|
|
|
|
iframe.style.position = "absolute";
|
|
|
|
|
document.body.appendChild(iframe);
|
|
|
|
|
kernelSource = <Window>iframe.contentWindow;
|
|
|
|
|
kernelOrigin = EXTENSION_HOSTED_ORIGIN;
|
|
|
|
|
kernelAuthLocation = `${EXTENSION_HOSTED_ORIGIN}/auth.html`;
|
|
|
|
|
kernelOrigin = "https://kernel.lumeweb.com";
|
|
|
|
|
kernelAuthLocation = "https://kernel.lumeweb.com/auth.html";
|
|
|
|
|
sourceResolve();
|
|
|
|
|
|
|
|
|
|
// Set a timer to fail the login process if the kernel doesn't load in
|
|
|
|
|
// time.
|
|
|
|
|
setTimeout(() => {
|
|
|
|
|
if (initResolved) {
|
|
|
|
|
if (initResolved === true) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
initResolved = true;
|
|
|
|
@ -262,72 +229,53 @@ function messageBridge() {
|
|
|
|
|
});
|
|
|
|
|
p.then(([, err]) => {
|
|
|
|
|
// Check if the timeout already elapsed.
|
|
|
|
|
if (bridgeInitComplete) {
|
|
|
|
|
if (bridgeInitComplete === true) {
|
|
|
|
|
logErr("received response from bridge, but init already finished");
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
bridgeInitComplete = true;
|
|
|
|
|
|
|
|
|
|
// Bridge has responded successfully, and there's no error.
|
|
|
|
|
if (IS_EXTENSION) {
|
|
|
|
|
const iframes = Array.from(
|
|
|
|
|
document.getElementsByTagName("iframe"),
|
|
|
|
|
).filter((item) => item.src === EXTENSION_KERNEL_ORIGIN + "/");
|
|
|
|
|
if (!iframes.length) {
|
|
|
|
|
logErr("could not find kernel iframe");
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
kernelSource = iframes[0].contentWindow as Window;
|
|
|
|
|
kernelOrigin = EXTENSION_KERNEL_ORIGIN;
|
|
|
|
|
} else {
|
|
|
|
|
kernelSource = window;
|
|
|
|
|
kernelOrigin = window.origin;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
kernelAuthLocation = `${EXTENSION_KERNEL_ORIGIN}/auth.html`;
|
|
|
|
|
log("established connection to bridge, using browser extension for kernel");
|
|
|
|
|
if (!IS_EXTENSION) {
|
|
|
|
|
sourceResolve();
|
|
|
|
|
}
|
|
|
|
|
kernelSource = window;
|
|
|
|
|
kernelOrigin = window.origin;
|
|
|
|
|
kernelAuthLocation = "http://kernel.lume/auth.html";
|
|
|
|
|
console.log(
|
|
|
|
|
"established connection to bridge, using browser extension for kernel",
|
|
|
|
|
);
|
|
|
|
|
sourceResolve();
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
if (!IS_EXTENSION) {
|
|
|
|
|
// Add the handler to the queries map.
|
|
|
|
|
const nonce = nextNonce();
|
|
|
|
|
queries[nonce] = {
|
|
|
|
|
resolve: bridgeResolve,
|
|
|
|
|
};
|
|
|
|
|
// Add the handler to the queries map.
|
|
|
|
|
const nonce = nextNonce();
|
|
|
|
|
queries[nonce] = {
|
|
|
|
|
resolve: bridgeResolve,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// Send a message to the bridge of the browser extension to determine
|
|
|
|
|
// whether the bridge exists.
|
|
|
|
|
window.postMessage(
|
|
|
|
|
{
|
|
|
|
|
nonce,
|
|
|
|
|
method: "kernelBridgeVersion",
|
|
|
|
|
},
|
|
|
|
|
window.origin,
|
|
|
|
|
);
|
|
|
|
|
// Send a message to the bridge of the browser extension to determine
|
|
|
|
|
// whether the bridge exists.
|
|
|
|
|
window.postMessage(
|
|
|
|
|
{
|
|
|
|
|
nonce,
|
|
|
|
|
method: "kernelBridgeVersion",
|
|
|
|
|
},
|
|
|
|
|
window.origin,
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
// Set a timeout, if we do not hear back from the bridge in 500
|
|
|
|
|
// milliseconds we assume that the bridge is not available.
|
|
|
|
|
setTimeout(() => {
|
|
|
|
|
// If we've already received and processed a message from the
|
|
|
|
|
// bridge, there is nothing to do.
|
|
|
|
|
if (bridgeInitComplete) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
bridgeInitComplete = true;
|
|
|
|
|
// Set a timeout, if we do not hear back from the bridge in 500
|
|
|
|
|
// milliseconds we assume that the bridge is not available.
|
|
|
|
|
setTimeout(() => {
|
|
|
|
|
// If we've already received and processed a message from the
|
|
|
|
|
// bridge, there is nothing to do.
|
|
|
|
|
if (bridgeInitComplete === true) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
bridgeInitComplete = true;
|
|
|
|
|
|
|
|
|
|
if ("localhost" === window.location.hostname) {
|
|
|
|
|
log("browser extension not found, falling back to lumeweb.com");
|
|
|
|
|
launchKernelFrame();
|
|
|
|
|
}
|
|
|
|
|
}, 500);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (IS_EXTENSION) {
|
|
|
|
|
bridgeResolve([null, null]);
|
|
|
|
|
}
|
|
|
|
|
if ("localhost" === window.location.hostname) {
|
|
|
|
|
log("browser extension not found, falling back to lumeweb.com");
|
|
|
|
|
launchKernelFrame();
|
|
|
|
|
}
|
|
|
|
|
}, 500);
|
|
|
|
|
|
|
|
|
|
return initPromise;
|
|
|
|
|
}
|
|
|
|
@ -355,7 +303,7 @@ let sourceResolve: () => void;
|
|
|
|
|
let sourcePromise: Promise<void>; // resolves when the source is known and set
|
|
|
|
|
function init(): Promise<void> {
|
|
|
|
|
// If init has already been called, just return the init promise.
|
|
|
|
|
if (initialized) {
|
|
|
|
|
if (initialized === true) {
|
|
|
|
|
return initPromise;
|
|
|
|
|
}
|
|
|
|
|
initialized = true;
|
|
|
|
@ -545,7 +493,7 @@ function newKernelQuery(
|
|
|
|
|
// promise that blocks until the sendUpdate function is ready to receive
|
|
|
|
|
// the kernel nonce.
|
|
|
|
|
let sendUpdate: DataFn;
|
|
|
|
|
if (!sendUpdates) {
|
|
|
|
|
if (sendUpdates !== true) {
|
|
|
|
|
sendUpdate = () => {};
|
|
|
|
|
readyForKernelNonce(); // We won't get a kernel nonce, no reason to block.
|
|
|
|
|
} else {
|
|
|
|
@ -592,7 +540,7 @@ function newKernelQuery(
|
|
|
|
|
nonce,
|
|
|
|
|
data,
|
|
|
|
|
sendKernelNonce: sendUpdates,
|
|
|
|
|
} as any;
|
|
|
|
|
};
|
|
|
|
|
const backgroundMessage = {
|
|
|
|
|
method: "newKernelQuery",
|
|
|
|
|
nonce,
|
|
|
|
@ -602,10 +550,7 @@ function newKernelQuery(
|
|
|
|
|
// The message structure needs to adjust based on whether we are
|
|
|
|
|
// talking directly to the kernel or whether we are talking to the
|
|
|
|
|
// background page.
|
|
|
|
|
if (kernelOrigin === "https://kernel.lumeweb.com" || IS_EXTENSION) {
|
|
|
|
|
if (IS_EXTENSION) {
|
|
|
|
|
kernelMessage.domain = window.origin;
|
|
|
|
|
}
|
|
|
|
|
if (kernelOrigin === "https://kernel.lumeweb.com") {
|
|
|
|
|
kernelSource.postMessage(kernelMessage, kernelOrigin);
|
|
|
|
|
} else {
|
|
|
|
|
kernelSource.postMessage(backgroundMessage, kernelOrigin);
|
|
|
|
|