2022-07-29 10:37:20 +00:00
|
|
|
import type { DataFn, KernelAuthStatus } from "libskynet";
|
2022-07-31 04:59:51 +00:00
|
|
|
import tldEnum from "@lumeweb/tld-enum";
|
|
|
|
import WebEngine from "../webEngine.js";
|
|
|
|
import InternalProvider from "../contentProviders/internalProvider.js";
|
|
|
|
import SkynetProvider from "../contentProviders/skynetProvider.js";
|
2022-07-31 05:36:06 +00:00
|
|
|
import ServerProvider from "../contentProviders/serverProvider.js";
|
2022-07-31 04:59:51 +00:00
|
|
|
import { init } from "libkernel";
|
2022-08-13 08:19:01 +00:00
|
|
|
import IpfsProvider from "../contentProviders/ipfsProvider.js";
|
2022-08-14 12:21:09 +00:00
|
|
|
import { ready as dnsReady } from "@lumeweb/kernel-dns-client";
|
2022-07-29 10:37:20 +00:00
|
|
|
|
|
|
|
declare var browser: any; // tsc
|
|
|
|
let queriesNonce = 1;
|
|
|
|
let queries: any = {};
|
|
|
|
let portsNonce = 0;
|
|
|
|
let openPorts = {} as any;
|
|
|
|
let timer = 20000;
|
|
|
|
|
|
|
|
function logLargeObjects() {
|
|
|
|
let queriesLen = Object.keys(queries).length;
|
|
|
|
let portsLen = Object.keys(openPorts).length;
|
|
|
|
if (queriesLen > 500) {
|
|
|
|
console.error("queries appears to be leaking:", queriesLen);
|
|
|
|
}
|
|
|
|
if (portsLen > 50) {
|
|
|
|
console.error("ports appears to be leaking:", portsLen);
|
|
|
|
}
|
|
|
|
timer *= 1.25;
|
|
|
|
setTimeout(logLargeObjects, timer);
|
|
|
|
}
|
|
|
|
setTimeout(logLargeObjects, timer);
|
|
|
|
|
|
|
|
let authStatus: KernelAuthStatus;
|
|
|
|
let authStatusKnown = false;
|
|
|
|
let authStatusResolve: DataFn;
|
2022-07-31 04:51:02 +00:00
|
|
|
let bridgeLoadedResolve: DataFn;
|
2022-07-29 10:37:20 +00:00
|
|
|
let blockForBootloader = new Promise((resolve) => {
|
|
|
|
authStatusResolve = resolve;
|
|
|
|
});
|
2022-07-31 04:51:02 +00:00
|
|
|
let blockForBridge = new Promise((resolve) => {
|
|
|
|
bridgeLoadedResolve = resolve;
|
|
|
|
});
|
2022-08-14 12:21:09 +00:00
|
|
|
let kernelFrame: HTMLIFrameElement;
|
2022-07-29 10:37:20 +00:00
|
|
|
|
|
|
|
export function queryKernel(query: any): Promise<any> {
|
|
|
|
return new Promise((resolve) => {
|
|
|
|
let receiveResponse = function (data: any) {
|
|
|
|
resolve(data.data);
|
|
|
|
};
|
|
|
|
|
|
|
|
blockForBootloader.then(() => {
|
|
|
|
let nonce = queriesNonce;
|
|
|
|
queriesNonce += 1;
|
|
|
|
query.nonce = nonce;
|
|
|
|
queries[nonce] = receiveResponse;
|
|
|
|
if (kernelFrame.contentWindow !== null) {
|
|
|
|
kernelFrame.contentWindow.postMessage(query, "http://kernel.skynet");
|
|
|
|
} else {
|
|
|
|
console.error(
|
|
|
|
"kernelFrame.contentWindow was null, cannot send message!"
|
|
|
|
);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
});
|
|
|
|
}
|
|
|
|
function handleKernelMessage(event: MessageEvent) {
|
|
|
|
let data = event.data.data;
|
|
|
|
|
2022-07-29 23:42:49 +00:00
|
|
|
if (event.data.method === "kernelBridgeVersion") {
|
2022-07-31 04:51:02 +00:00
|
|
|
blockForBridge.then(() => {
|
|
|
|
for (let [, port] of Object.entries(openPorts)) {
|
|
|
|
try {
|
|
|
|
(port as any).postMessage(event.data);
|
|
|
|
} catch {}
|
|
|
|
}
|
|
|
|
});
|
2022-07-29 23:42:49 +00:00
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (event.origin !== "http://kernel.skynet") {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2022-07-29 10:37:20 +00:00
|
|
|
if (event.data.method === "log") {
|
|
|
|
if (data.isErr === false) {
|
|
|
|
console.log(data.message);
|
|
|
|
} else {
|
|
|
|
console.error(data.message);
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2022-07-29 12:06:11 +00:00
|
|
|
if (event.data.method === "kernelAuthStatus") {
|
2022-07-29 10:37:20 +00:00
|
|
|
authStatus = data;
|
|
|
|
if (authStatusKnown === false) {
|
|
|
|
authStatusResolve();
|
|
|
|
authStatusKnown = true;
|
|
|
|
console.log("bootloader is now initialized");
|
|
|
|
if (authStatus.loginComplete !== true) {
|
|
|
|
console.log("user is not logged in: waiting until login is confirmed");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for (let [, port] of Object.entries(openPorts)) {
|
|
|
|
try {
|
|
|
|
(port as any).postMessage(event.data);
|
|
|
|
} catch {}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (data.logoutComplete === true) {
|
|
|
|
console.log("received logout signal, clearing all ports");
|
|
|
|
|
|
|
|
for (let [, port] of Object.entries(openPorts)) {
|
|
|
|
try {
|
|
|
|
(port as any).disconnect();
|
|
|
|
} catch {}
|
|
|
|
}
|
|
|
|
openPorts = {};
|
|
|
|
}
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!(event.data.nonce in queries)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
let receiveResult = queries[event.data.nonce];
|
|
|
|
if (event.data.method === "response") {
|
|
|
|
delete queries[event.data.nonce];
|
|
|
|
}
|
|
|
|
|
|
|
|
receiveResult(event.data);
|
|
|
|
}
|
|
|
|
|
|
|
|
function handleBridgeMessage(
|
|
|
|
port: any,
|
|
|
|
portNonce: number,
|
|
|
|
data: any,
|
|
|
|
domain: string
|
|
|
|
) {
|
2022-07-31 04:51:02 +00:00
|
|
|
if (data.method === "bridgeLoaded") {
|
|
|
|
bridgeLoadedResolve();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2022-07-29 10:37:20 +00:00
|
|
|
if (!("nonce" in data)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2022-07-29 23:42:49 +00:00
|
|
|
if (data.method === "response") {
|
|
|
|
window.postMessage(data);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2022-07-29 10:37:20 +00:00
|
|
|
if (data.method !== "queryUpdate") {
|
|
|
|
queries[data.nonce] = (response: any) => {
|
|
|
|
if (portNonce in openPorts) {
|
|
|
|
port.postMessage(response);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
data["domain"] = domain;
|
|
|
|
}
|
|
|
|
kernelFrame.contentWindow!.postMessage(data, "http://kernel.skynet");
|
|
|
|
}
|
|
|
|
function bridgeListener(port: any) {
|
|
|
|
let portNonce = portsNonce;
|
|
|
|
portsNonce++;
|
|
|
|
openPorts[portNonce] = port;
|
|
|
|
|
|
|
|
port.onDisconnect.addListener(() => {
|
|
|
|
delete openPorts[portNonce];
|
|
|
|
});
|
|
|
|
|
|
|
|
let domain = new URL(port.sender.url).hostname;
|
|
|
|
|
|
|
|
port.onMessage.addListener(function (data: any) {
|
|
|
|
handleBridgeMessage(port, portNonce, data, domain);
|
|
|
|
});
|
|
|
|
|
|
|
|
blockForBootloader.then(() => {
|
|
|
|
port.postMessage({
|
2022-07-29 23:41:58 +00:00
|
|
|
method: "kernelAuthStatus",
|
2022-07-29 10:37:20 +00:00
|
|
|
data: authStatus,
|
|
|
|
});
|
|
|
|
});
|
|
|
|
}
|
2022-08-14 12:21:09 +00:00
|
|
|
|
|
|
|
async function boot() {
|
|
|
|
tldEnum.list.push("localhost");
|
|
|
|
window.addEventListener("message", handleKernelMessage);
|
|
|
|
browser.runtime.onConnect.addListener(bridgeListener);
|
|
|
|
|
|
|
|
const engine = new WebEngine();
|
|
|
|
engine.registerContentProvider(new InternalProvider(engine));
|
|
|
|
engine.registerContentProvider(new ServerProvider(engine));
|
|
|
|
engine.registerContentProvider(new SkynetProvider(engine));
|
|
|
|
engine.registerContentProvider(new IpfsProvider(engine));
|
|
|
|
|
|
|
|
// @ts-ignore
|
|
|
|
kernelFrame = document.createElement("iframe");
|
|
|
|
kernelFrame.src = "http://kernel.skynet";
|
|
|
|
kernelFrame.onload = init;
|
|
|
|
document.body.appendChild(kernelFrame);
|
|
|
|
|
|
|
|
await dnsReady();
|
|
|
|
}
|
|
|
|
|
|
|
|
boot();
|