diff options
Diffstat (limited to 'packages/taler-wallet-webextension/src/wxBackend.ts')
-rw-r--r-- | packages/taler-wallet-webextension/src/wxBackend.ts | 201 |
1 files changed, 114 insertions, 87 deletions
diff --git a/packages/taler-wallet-webextension/src/wxBackend.ts b/packages/taler-wallet-webextension/src/wxBackend.ts index 28adfa037..c94b390ff 100644 --- a/packages/taler-wallet-webextension/src/wxBackend.ts +++ b/packages/taler-wallet-webextension/src/wxBackend.ts @@ -25,8 +25,6 @@ */ import { classifyTalerUri, - CoreApiResponse, - CoreApiResponseSuccess, Logger, TalerErrorCode, TalerUriType, @@ -36,20 +34,27 @@ import { DbAccess, deleteTalerDatabase, exportDb, + getErrorDetailFromException, importDb, makeErrorDetail, OpenedPromise, openPromise, openTalerDatabase, + SetTimeoutTimerAPI, Wallet, + WalletOperations, WalletStoresV1, } from "@gnu-taler/taler-wallet-core"; -import { SetTimeoutTimerAPI } from "@gnu-taler/taler-wallet-core"; -import { BrowserCryptoWorkerFactory } from "./browserCryptoWorkerFactory.js"; import { BrowserHttpLib } from "./browserHttpLib.js"; -import { MessageFromBackend, platform } from "./platform/api.js"; +import { + MessageFromBackend, + MessageFromFrontend, + MessageResponse, + platform, +} from "./platform/api.js"; import { SynchronousCryptoWorkerFactory } from "./serviceWorkerCryptoWorkerFactory.js"; import { ServiceWorkerHttpLib } from "./serviceWorkerHttpLib.js"; +import { BackgroundOperations, ExtendedPermissionsResponse } from "./wxApi.js"; /** * Currently active wallet instance. Might be unloaded and @@ -107,92 +112,115 @@ async function getDiagnostics(): Promise<WalletDiagnostics> { return diagnostics; } -async function dispatch( - req: any, - sender: any, - sendResponse: any, -): Promise<void> { - let r: CoreApiResponse; +type BackendHandlerType = { + [Op in keyof BackgroundOperations]: ( + req: BackgroundOperations[Op]["request"], + ) => Promise<BackgroundOperations[Op]["response"]>; +}; + +async function containsHeaderListener(): Promise<ExtendedPermissionsResponse> { + const result = await platform.containsTalerHeaderListener(); + return { newValue: result }; +} + +async function resetDb(): Promise<void> { + await deleteTalerDatabase(indexedDB as any); + await reinitWallet(); +} + +async function runGarbageCollector(): Promise<void> { + const dbBeforeGc = currentDatabase; + if (!dbBeforeGc) { + throw Error("no current db before running gc"); + } + const dump = await exportDb(dbBeforeGc.idbHandle()); + + await deleteTalerDatabase(indexedDB as any); + logger.info("cleaned"); + await reinitWallet(); + logger.info("init"); + + const dbAfterGc = currentDatabase; + if (!dbAfterGc) { + throw Error("no current db before running gc"); + } + await importDb(dbAfterGc.idbHandle(), dump); + logger.info("imported"); +} + +async function toggleHeaderListener( + newVal: boolean, +): Promise<ExtendedPermissionsResponse> { + logger.trace("new extended permissions value", newVal); + if (newVal) { + platform.registerTalerHeaderListener(parseTalerUriAndRedirect); + return { newValue: true }; + } + + const rem = await platform.getPermissionsApi().removeHostPermissions(); + logger.trace("permissions removed:", rem); + return { newValue: false }; +} - const wrapResponse = (result: unknown): CoreApiResponseSuccess => { +const backendHandlers: BackendHandlerType = { + containsHeaderListener, + getDiagnostics, + resetDb, + runGarbageCollector, + toggleHeaderListener, +}; + +async function dispatch<Op extends WalletOperations | BackgroundOperations>( + req: MessageFromFrontend<Op> & { id: string }, +): Promise<MessageResponse> { + if (req.channel === "background") { + const handler = backendHandlers[req.operation] as (req: any) => any; + if (!handler) { + return { + type: "error", + id: req.id, + operation: String(req.operation), + error: getErrorDetailFromException( + Error(`unknown background operation`), + ), + }; + } + const result = await handler(req.payload); return { type: "response", id: req.id, - operation: req.operation, + operation: String(req.operation), result, }; - }; + } - try { - switch (req.operation) { - case "wxGetDiagnostics": { - r = wrapResponse(await getDiagnostics()); - break; - } - case "reset-db": { - await deleteTalerDatabase(indexedDB as any); - r = wrapResponse(await reinitWallet()); - break; - } - case "run-gc": { - logger.info("gc"); - const dump = await exportDb(currentDatabase!.idbHandle()); - await deleteTalerDatabase(indexedDB as any); - logger.info("cleaned"); - await reinitWallet(); - logger.info("init"); - await importDb(currentDatabase!.idbHandle(), dump); - logger.info("imported"); - r = wrapResponse({ result: true }); - break; - } - case "containsHeaderListener": { - const res = await platform.containsTalerHeaderListener(); - r = wrapResponse({ newValue: res }); - break; - } - //FIXME: implement type checked api like WalletCoreApi - case "toggleHeaderListener": { - const newVal = req.payload.value; - logger.trace("new extended permissions value", newVal); - if (newVal) { - platform.registerTalerHeaderListener(parseTalerUriAndRedirect); - r = wrapResponse({ newValue: true }); - } else { - const rem = await platform - .getPermissionsApi() - .removeHostPermissions(); - logger.trace("permissions removed:", rem); - r = wrapResponse({ newVal: false }); - } - break; - } - default: { - const w = currentWallet; - if (!w) { - r = { - type: "error", - id: req.id, - operation: req.operation, - error: makeErrorDetail( - TalerErrorCode.WALLET_CORE_NOT_AVAILABLE, - {}, - "wallet core not available", - ), - }; - break; - } - r = await w.handleCoreApiRequest(req.operation, req.id, req.payload); - console.log("response received from wallet", r); - break; - } + if (req.channel === "wallet") { + const w = currentWallet; + if (!w) { + return { + type: "error", + id: req.id, + operation: req.operation, + error: makeErrorDetail( + TalerErrorCode.WALLET_CORE_NOT_AVAILABLE, + {}, + "wallet core not available", + ), + }; } - sendResponse(r); - } catch (e) { - logger.error(`Error sending operation: ${req.operation}`, e); - // might fail if tab disconnected + return await w.handleCoreApiRequest(req.operation, req.id, req.payload); } + + const anyReq = req as any; + return { + type: "error", + id: anyReq.id, + operation: String(anyReq.operation), + error: getErrorDetailFromException( + Error(`unknown channel ${anyReq.channel}`), + ), + }; } async function reinitWallet(): Promise<void> { @@ -328,12 +356,11 @@ export async function wxMain(): Promise<void> { // Handlers for messages coming directly from the content // script on the page - platform.listenToAllChannels((message, sender, callback) => { - afterWalletIsInitialized.then(() => { - dispatch(message, sender, (response: CoreApiResponse) => { - callback(response); - }); - }); + platform.listenToAllChannels(async (message) => { + //wait until wallet is initialized + await afterWalletIsInitialized; + const result = await dispatch(message); + return result; }); platform.registerAllIncomingConnections(); |