diff --git a/src/main/background.ts b/src/main/background.ts index 93c3059..07ff4e2 100644 --- a/src/main/background.ts +++ b/src/main/background.ts @@ -1,228 +1,11 @@ -import tldEnum from "@lumeweb/tld-enum"; -import WebEngine from "../webEngine.js"; -import InternalProvider from "../contentProviders/internalProvider.js"; -import ServerProvider from "../contentProviders/serverProvider.js"; -import { init } from "@lumeweb/libkernel/kernel"; -import IpfsProvider from "../contentProviders/ipfsProvider.js"; -import { - addQuery, - clearOpenPorts, - deleteOpenPort, - deleteQuery, - getAuthStatus, - getAuthStatusKnown, - getAuthStatusResolve, - getBlockForBootloader, - getBlockForBridge, - getBridgeLoadedResolve, - getKernelIframe, - getOpenPorts, - getPortsNonce, - getQueries, - getQueriesNonce, - getQuery, - getTimer, - increasePortsNonce, - increaseQueriesNonce, - setAuthStatus, - setAuthStatusKnown, - setKernelIframe, - setOpenPort, - setTimer, - weAreBooted, -} from "../vars.js"; +import { getTimer } from "../vars.js"; import browser from "webextension-polyfill"; - -function logLargeObjects() { - let queriesLen = Object.keys(getQueries()).length; - let portsLen = Object.keys(getOpenPorts()).length; - if (queriesLen > 500) { - console.error("queries appears to be leaking:", queriesLen); - } - if (portsLen > 50) { - console.error("ports appears to be leaking:", portsLen); - } - setTimer(getTimer() * 1.25); - setTimeout(logLargeObjects, getTimer()); -} +import { logLargeObjects } from "./background/util.js"; +import { queryKernel } from "./background/kernel.js"; +import { boot } from "./background/boot.js"; setTimeout(logLargeObjects, getTimer()); -export function queryKernel(query: any): Promise { - return new Promise((resolve) => { - let receiveResponse = function (data: any) { - resolve(data.data); - }; - - getBlockForBootloader().then(() => { - let nonce = getQueriesNonce(); - increaseQueriesNonce(); - query.nonce = nonce; - addQuery(nonce, receiveResponse); - if (getKernelIframe().contentWindow !== null) { - (getKernelIframe() as any).contentWindow.postMessage( - query, - "http://kernel.lume", - ); - } else { - console.error( - "kernelFrame.contentWindow was null, cannot send message!", - ); - } - }); - }); -} - -function handleKernelMessage(event: MessageEvent) { - let data = event.data.data; - - if (event.data.method === "kernelBridgeVersion") { - getBlockForBridge().then(() => { - for (let [, port] of Object.entries(getOpenPorts())) { - try { - (port as any).postMessage(event.data); - } catch {} - } - }); - - return; - } - - if (event.origin !== "http://kernel.lume") { - return; - } - - if (event.data.method === "log") { - if (data.isErr !== null && !data.isErr) { - console.log(data.message); - } else { - console.error(data.message); - } - return; - } - - if (event.data.method === "kernelAuthStatus") { - setAuthStatus(data); - if (!getAuthStatusKnown()) { - getAuthStatusResolve()(); - setAuthStatusKnown(true); - console.log("bootloader is now initialized"); - if (!getAuthStatus().loginComplete) { - console.log("user is not logged in: waiting until login is confirmed"); - } - } - - for (let [, port] of Object.entries(getOpenPorts())) { - 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(getOpenPorts())) { - try { - (port as any).disconnect(); - } catch {} - } - clearOpenPorts(); - } - - return; - } - - if (!(event.data.nonce in getQueries())) { - return; - } - - let receiveResult = getQuery(event.data.nonce); - if (event.data.method === "response") { - deleteQuery(event.data.nonce); - } - - receiveResult(event.data); -} - -function handleBridgeMessage( - port: any, - portNonce: number, - data: any, - domain: string, -) { - if (data.method === "bridgeLoaded") { - getBridgeLoadedResolve()(); - return; - } - - if (!("nonce" in data)) { - return; - } - - if (data.method === "response") { - window.postMessage(data); - return; - } - - if (data.method !== "queryUpdate") { - addQuery(data.nonce, (response: any) => { - if (portNonce in getOpenPorts()) { - port.postMessage(response); - } - }); - data["domain"] = domain; - } - - getKernelIframe().contentWindow!.postMessage(data, "http://kernel.lume"); -} - -function bridgeListener(port: any) { - let portNonce = getPortsNonce(); - increasePortsNonce(); - setOpenPort(portNonce, port); - - port.onDisconnect.addListener(() => { - deleteOpenPort(portNonce); - }); - - let domain = new URL(port.sender.url).hostname; - - port.onMessage.addListener(function (data: any) { - handleBridgeMessage(port, portNonce, data, domain); - }); - - getBlockForBootloader().then(() => { - port.postMessage({ - method: "kernelAuthStatus", - data: getAuthStatus(), - }); - }); -} - -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 IpfsProvider(engine)); - engine.registerContentProvider(new ServerProvider(engine)); - - setKernelIframe(document.createElement("iframe")); - getKernelIframe().src = "http://kernel.lume"; - - await new Promise((resolve) => { - getKernelIframe().onload = () => { - init().then(resolve); - }; - document.body.appendChild(getKernelIframe()); - }); - - weAreBooted(); -} - browser.runtime.onInstalled.addListener(() => { browser.tabs.create({ url: browser.runtime.getURL("onboarding.html"), diff --git a/src/main/background/boot.ts b/src/main/background/boot.ts new file mode 100644 index 0000000..e14358a --- /dev/null +++ b/src/main/background/boot.ts @@ -0,0 +1,34 @@ +import tldEnum from "@lumeweb/tld-enum"; +import { handleKernelMessage } from "./kernel.js"; +import browser from "webextension-polyfill"; +import { bridgeListener } from "./bridge.js"; +import WebEngine from "../../webEngine.js"; +import InternalProvider from "../../contentProviders/internalProvider.js"; +import IpfsProvider from "../../contentProviders/ipfsProvider.js"; +import ServerProvider from "../../contentProviders/serverProvider.js"; +import { getKernelIframe, setKernelIframe, weAreBooted } from "../../vars.js"; +import { init } from "@lumeweb/libkernel/kernel"; + +export 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 IpfsProvider(engine)); + engine.registerContentProvider(new ServerProvider(engine)); + + setKernelIframe(document.createElement("iframe")); + getKernelIframe().src = "http://kernel.lume"; + + await new Promise((resolve) => { + getKernelIframe().onload = () => { + init().then(resolve); + }; + document.body.appendChild(getKernelIframe()); + }); + + weAreBooted(); +} diff --git a/src/main/background/bridge.ts b/src/main/background/bridge.ts new file mode 100644 index 0000000..64d1f32 --- /dev/null +++ b/src/main/background/bridge.ts @@ -0,0 +1,67 @@ +import { + addQuery, + deleteOpenPort, + getAuthStatus, + getBlockForBootloader, + getBridgeLoadedResolve, + getKernelIframe, + getOpenPorts, + getPortsNonce, + increasePortsNonce, + setOpenPort, +} from "../../vars.js"; + +function handleBridgeMessage( + port: any, + portNonce: number, + data: any, + domain: string, +) { + if (data.method === "bridgeLoaded") { + getBridgeLoadedResolve()(); + return; + } + + if (!("nonce" in data)) { + return; + } + + if (data.method === "response") { + window.postMessage(data); + return; + } + + if (data.method !== "queryUpdate") { + addQuery(data.nonce, (response: any) => { + if (portNonce in getOpenPorts()) { + port.postMessage(response); + } + }); + data["domain"] = domain; + } + + getKernelIframe().contentWindow!.postMessage(data, "http://kernel.lume"); +} + +export function bridgeListener(port: any) { + let portNonce = getPortsNonce(); + increasePortsNonce(); + setOpenPort(portNonce, port); + + port.onDisconnect.addListener(() => { + deleteOpenPort(portNonce); + }); + + let domain = new URL(port.sender.url).hostname; + + port.onMessage.addListener(function (data: any) { + handleBridgeMessage(port, portNonce, data, domain); + }); + + getBlockForBootloader().then(() => { + port.postMessage({ + method: "kernelAuthStatus", + data: getAuthStatus(), + }); + }); +} diff --git a/src/main/background/kernel.ts b/src/main/background/kernel.ts new file mode 100644 index 0000000..868d8d4 --- /dev/null +++ b/src/main/background/kernel.ts @@ -0,0 +1,114 @@ +import { + addQuery, + clearOpenPorts, + deleteQuery, + getAuthStatus, + getAuthStatusKnown, + getAuthStatusResolve, + getBlockForBootloader, + getBlockForBridge, + getKernelIframe, + getOpenPorts, + getQueries, + getQueriesNonce, + getQuery, + increaseQueriesNonce, + setAuthStatus, + setAuthStatusKnown, +} from "../../vars.js"; + +export function handleKernelMessage(event: MessageEvent) { + let data = event.data.data; + + if (event.data.method === "kernelBridgeVersion") { + getBlockForBridge().then(() => { + for (let [, port] of Object.entries(getOpenPorts())) { + try { + (port as any).postMessage(event.data); + } catch {} + } + }); + + return; + } + + if (event.origin !== "http://kernel.lume") { + return; + } + + if (event.data.method === "log") { + if (data.isErr !== null && !data.isErr) { + console.log(data.message); + } else { + console.error(data.message); + } + return; + } + + if (event.data.method === "kernelAuthStatus") { + setAuthStatus(data); + if (!getAuthStatusKnown()) { + getAuthStatusResolve()(); + setAuthStatusKnown(true); + console.log("bootloader is now initialized"); + if (!getAuthStatus().loginComplete) { + console.log("user is not logged in: waiting until login is confirmed"); + } + } + + for (let [, port] of Object.entries(getOpenPorts())) { + 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(getOpenPorts())) { + try { + (port as any).disconnect(); + } catch {} + } + clearOpenPorts(); + } + + return; + } + + if (!(event.data.nonce in getQueries())) { + return; + } + + let receiveResult = getQuery(event.data.nonce); + if (event.data.method === "response") { + deleteQuery(event.data.nonce); + } + + receiveResult(event.data); +} + +export function queryKernel(query: any): Promise { + return new Promise((resolve) => { + let receiveResponse = function (data: any) { + resolve(data.data); + }; + + getBlockForBootloader().then(() => { + let nonce = getQueriesNonce(); + increaseQueriesNonce(); + query.nonce = nonce; + addQuery(nonce, receiveResponse); + if (getKernelIframe().contentWindow !== null) { + (getKernelIframe() as any).contentWindow.postMessage( + query, + "http://kernel.lume", + ); + } else { + console.error( + "kernelFrame.contentWindow was null, cannot send message!", + ); + } + }); + }); +} diff --git a/src/main/background/util.ts b/src/main/background/util.ts new file mode 100644 index 0000000..9051f93 --- /dev/null +++ b/src/main/background/util.ts @@ -0,0 +1,14 @@ +import { getOpenPorts, getQueries, getTimer, setTimer } from "../../vars.js"; + +export function logLargeObjects() { + let queriesLen = Object.keys(getQueries()).length; + let portsLen = Object.keys(getOpenPorts()).length; + if (queriesLen > 500) { + console.error("queries appears to be leaking:", queriesLen); + } + if (portsLen > 50) { + console.error("ports appears to be leaking:", portsLen); + } + setTimer(getTimer() * 1.25); + setTimeout(logLargeObjects, getTimer()); +}