diff options
4 files changed, 116 insertions, 122 deletions
diff --git a/packages/taler-wallet-webextension/src/NavigationBar.tsx b/packages/taler-wallet-webextension/src/NavigationBar.tsx index e8ee4f475..b73704c70 100644 --- a/packages/taler-wallet-webextension/src/NavigationBar.tsx +++ b/packages/taler-wallet-webextension/src/NavigationBar.tsx @@ -38,6 +38,7 @@ import { useAsyncAsHook } from "./hooks/useAsyncAsHook.js"; import qrIcon from "./svg/qr_code_24px.svg"; import settingsIcon from "./svg/settings_black_24dp.svg"; import warningIcon from "./svg/warning_24px.svg"; +import { parseTalerUri, TalerUriAction } from "@gnu-taler/taler-util"; /** * List of pages used by the wallet @@ -115,6 +116,7 @@ export const Pages = { "/settings/exchange/add/:currency?", ), + defaultCta: pageDefinition<{ uri: string }>("/taler-uri/:uri"), cta: pageDefinition<{ action: string }>("/cta/:action"), ctaPay: "/cta/pay", ctaPayTemplate: "/cta/pay/template", @@ -136,6 +138,34 @@ export const Pages = { ), }; +const talerUriActionToPageName: { + [t in TalerUriAction]: keyof typeof Pages | undefined; +} = { + [TalerUriAction.Withdraw]: "ctaWithdraw", + [TalerUriAction.Pay]: "ctaPay", + [TalerUriAction.Tip]: "ctaTips", + [TalerUriAction.Refund]: "ctaRefund", + [TalerUriAction.PayPull]: "ctaInvoicePay", + [TalerUriAction.PayPush]: "ctaTransferPickup", + [TalerUriAction.Restore]: "ctaRecovery", + [TalerUriAction.PayTemplate]: "ctaPayTemplate", + [TalerUriAction.DevExperiment]: undefined, + [TalerUriAction.Exchange]: undefined, + [TalerUriAction.Auditor]: undefined, +}; + +export function getPathnameForTalerURI(talerUri: string): string | undefined { + const uri = parseTalerUri(talerUri); + if (!uri) { + return undefined; + } + const pageName = talerUriActionToPageName[uri.type]; + if (!pageName) { + return undefined; + } + return `${Pages[pageName]}?talerUri=${encodeURIComponent(talerUri)}`; +} + export type PopupNavBarOptions = "balance" | "backup" | "dev"; export function PopupNavBar({ path }: { path?: PopupNavBarOptions }): VNode { const api = useBackendContext(); diff --git a/packages/taler-wallet-webextension/src/platform/chrome.ts b/packages/taler-wallet-webextension/src/platform/chrome.ts index 4b0bdbfb7..03259314e 100644 --- a/packages/taler-wallet-webextension/src/platform/chrome.ts +++ b/packages/taler-wallet-webextension/src/platform/chrome.ts @@ -15,11 +15,11 @@ */ import { - classifyTalerUri, Logger, TalerErrorCode, - TalerUriType, + TalerUriAction, TalerError, + parseTalerUri, } from "@gnu-taler/taler-util"; import { WalletOperations } from "@gnu-taler/taler-wallet-core"; import { BackgroundOperations } from "../wxApi.js"; @@ -239,80 +239,83 @@ function openWalletURIFromPopup(maybeTalerUri: string): void { const talerUri = maybeTalerUri.startsWith("ext+") ? maybeTalerUri.substring(4) : maybeTalerUri; - const uriType = classifyTalerUri(talerUri); + const uri = parseTalerUri(talerUri); + if (!uri) { + logger.warn( + `Response with HTTP 402 the Taler header but could not classify ${talerUri}`, + ); + return; + } + //FIXME: this should redirect to just one place + // the target pathname should handle what happens if the endpoint is not there + // like "trying to open from popup but this uri is not handled" encodeURIComponent; let url: string | undefined = undefined; - switch (uriType) { - case TalerUriType.TalerWithdraw: + switch (uri.type) { + case TalerUriAction.Withdraw: url = chrome.runtime.getURL( - `static/wallet.html#/cta/withdraw?talerWithdrawUri=${encodeURIComponent( + `static/wallet.html#/cta/withdraw?talerUri=${encodeURIComponent( talerUri, )}`, ); break; - case TalerUriType.TalerRecovery: + case TalerUriAction.Restore: url = chrome.runtime.getURL( - `static/wallet.html#/cta/recovery?talerRecoveryUri=${encodeURIComponent( + `static/wallet.html#/cta/recovery?talerUri=${encodeURIComponent( talerUri, )}`, ); break; - case TalerUriType.TalerPay: + case TalerUriAction.Pay: url = chrome.runtime.getURL( - `static/wallet.html#/cta/pay?talerPayUri=${encodeURIComponent( - talerUri, - )}`, + `static/wallet.html#/cta/pay?talerUri=${encodeURIComponent(talerUri)}`, ); break; - case TalerUriType.TalerTip: + case TalerUriAction.Tip: url = chrome.runtime.getURL( - `static/wallet.html#/cta/tip?talerTipUri=${encodeURIComponent( - talerUri, - )}`, + `static/wallet.html#/cta/tip?talerUri=${encodeURIComponent(talerUri)}`, ); break; - case TalerUriType.TalerRefund: + case TalerUriAction.Refund: url = chrome.runtime.getURL( - `static/wallet.html#/cta/refund?talerRefundUri=${encodeURIComponent( + `static/wallet.html#/cta/refund?talerUri=${encodeURIComponent( talerUri, )}`, ); break; - case TalerUriType.TalerPayPull: + case TalerUriAction.PayPull: url = chrome.runtime.getURL( - `static/wallet.html#/cta/invoice/pay?talerPayPullUri=${encodeURIComponent( + `static/wallet.html#/cta/invoice/pay?talerUri=${encodeURIComponent( talerUri, )}`, ); break; - case TalerUriType.TalerPayPush: + case TalerUriAction.PayPush: url = chrome.runtime.getURL( - `static/wallet.html#/cta/transfer/pickup?talerPayPushUri=${encodeURIComponent( + `static/wallet.html#/cta/transfer/pickup?talerUri=${encodeURIComponent( talerUri, )}`, ); break; - case TalerUriType.TalerPayTemplate: + case TalerUriAction.PayTemplate: url = chrome.runtime.getURL( - `static/wallet.html#/cta/pay/template?talerPayTemplateUri=${encodeURIComponent( + `static/wallet.html#/cta/pay/template?talerUri=${encodeURIComponent( talerUri, )}`, ); break; - case TalerUriType.Unknown: - logger.warn( - `Response with HTTP 402 the Taler header but could not classify ${talerUri}`, - ); - return; - case TalerUriType.TalerDevExperiment: + case TalerUriAction.DevExperiment: logger.warn(`taler://dev-experiment URIs are not allowed in headers`); return; - case TalerUriType.TalerTemplate: - logger.warn(`taler://dev-template URIs are not allowed in headers`); + case TalerUriAction.Exchange: + logger.warn(`taler://exchange not yet supported`); + return; + case TalerUriAction.Auditor: + logger.warn(`taler://auditor not yet supported`); return; default: { - const error: never = uriType; + const error: never = uri; logger.warn( `Response with HTTP 402 the Taler header "${error}", but header value is not a taler:// URI.`, ); diff --git a/packages/taler-wallet-webextension/src/wallet/Application.tsx b/packages/taler-wallet-webextension/src/wallet/Application.tsx index 4a5ef30eb..2b03bb947 100644 --- a/packages/taler-wallet-webextension/src/wallet/Application.tsx +++ b/packages/taler-wallet-webextension/src/wallet/Application.tsx @@ -20,7 +20,11 @@ * @author sebasjm */ -import { TranslatedString } from "@gnu-taler/taler-util"; +import { + TalerUriAction, + TranslatedString, + parseTalerUri, +} from "@gnu-taler/taler-util"; import { createHashHistory } from "history"; import { ComponentChildren, Fragment, h, VNode } from "preact"; import { route, Route, Router } from "preact-router"; @@ -55,7 +59,12 @@ import { WithdrawPageFromParams, WithdrawPageFromURI, } from "../cta/Withdraw/index.js"; -import { Pages, WalletNavBar, WalletNavBarOptions } from "../NavigationBar.js"; +import { + Pages, + WalletNavBar, + WalletNavBarOptions, + getPathnameForTalerURI, +} from "../NavigationBar.js"; import { platform } from "../platform/foreground.js"; import CloseIcon from "../svg/close_24px.svg"; import { AddBackupProviderPage } from "./AddBackupProvider/index.js"; @@ -286,11 +295,21 @@ export function Application(): VNode { * CALL TO ACTION */} <Route + path={Pages.defaultCta.pattern} + component={({ uri }: { uri: string }) => { + const path = getPathnameForTalerURI(uri); + if (!path) { + return <Redirect to={Pages.balance} />; + } + return <Redirect to={path} />; + }} + /> + <Route path={Pages.ctaPay} - component={({ talerPayUri }: { talerPayUri: string }) => ( + component={({ talerUri }: { talerUri: string }) => ( <CallToActionTemplate title={i18n.str`Digital cash payment`}> <PaymentPage - talerPayUri={decodeURIComponent(talerPayUri)} + talerPayUri={decodeURIComponent(talerUri)} goToWalletManualWithdraw={(amount?: string) => redirectTo(Pages.receiveCash({ amount })) } @@ -304,14 +323,10 @@ export function Application(): VNode { /> <Route path={Pages.ctaPayTemplate} - component={({ - talerPayTemplateUri, - }: { - talerPayTemplateUri: string; - }) => ( + component={({ talerUri }: { talerUri: string }) => ( <CallToActionTemplate title={i18n.str`Digital cash payment`}> <PaymentTemplatePage - talerTemplateUri={decodeURIComponent(talerPayTemplateUri)} + talerTemplateUri={decodeURIComponent(talerUri)} goToWalletManualWithdraw={(amount?: string) => redirectTo(Pages.receiveCash({ amount })) } @@ -325,10 +340,10 @@ export function Application(): VNode { /> <Route path={Pages.ctaRefund} - component={({ talerRefundUri }: { talerRefundUri: string }) => ( + component={({ talerUri }: { talerUri: string }) => ( <CallToActionTemplate title={i18n.str`Digital cash refund`}> <RefundPage - talerRefundUri={decodeURIComponent(talerRefundUri)} + talerRefundUri={decodeURIComponent(talerUri)} cancel={() => redirectTo(Pages.balance)} onSuccess={(tid: string) => redirectTo(Pages.balanceTransaction({ tid })) @@ -339,10 +354,10 @@ export function Application(): VNode { /> <Route path={Pages.ctaTips} - component={({ talerTipUri }: { talerTipUri: string }) => ( + component={({ talerUri }: { talerUri: string }) => ( <CallToActionTemplate title={i18n.str`Digital cash tip`}> <TipPage - talerTipUri={decodeURIComponent(talerTipUri)} + talerTipUri={decodeURIComponent(talerUri)} onCancel={() => redirectTo(Pages.balance)} onSuccess={(tid: string) => redirectTo(Pages.balanceTransaction({ tid })) @@ -353,14 +368,10 @@ export function Application(): VNode { /> <Route path={Pages.ctaWithdraw} - component={({ - talerWithdrawUri, - }: { - talerWithdrawUri: string; - }) => ( + component={({ talerUri }: { talerUri: string }) => ( <CallToActionTemplate title={i18n.str`Digital cash withdrawal`}> <WithdrawPageFromURI - talerWithdrawUri={decodeURIComponent(talerWithdrawUri)} + talerWithdrawUri={decodeURIComponent(talerUri)} cancel={() => redirectTo(Pages.balance)} onSuccess={(tid: string) => redirectTo(Pages.balanceTransaction({ tid })) @@ -387,15 +398,15 @@ export function Application(): VNode { path={Pages.ctaDeposit} component={({ amount, - talerDepositUri, + talerUri, }: { amount: string; - talerDepositUri: string; + talerUri: string; }) => ( <CallToActionTemplate title={i18n.str`Digital cash deposit`}> <DepositPageCTA amountStr={amount} - talerDepositUri={decodeURIComponent(talerDepositUri)} + talerDepositUri={decodeURIComponent(talerUri)} cancel={() => redirectTo(Pages.balance)} onSuccess={(tid: string) => redirectTo(Pages.balanceTransaction({ tid })) @@ -434,10 +445,10 @@ export function Application(): VNode { /> <Route path={Pages.ctaInvoicePay} - component={({ talerPayPullUri }: { talerPayPullUri: string }) => ( + component={({ talerUri }: { talerUri: string }) => ( <CallToActionTemplate title={i18n.str`Digital cash invoice`}> <InvoicePayPage - talerPayPullUri={decodeURIComponent(talerPayPullUri)} + talerPayPullUri={decodeURIComponent(talerUri)} goToWalletManualWithdraw={(amount?: string) => redirectTo(Pages.receiveCash({ amount })) } @@ -451,10 +462,10 @@ export function Application(): VNode { /> <Route path={Pages.ctaTransferPickup} - component={({ talerPayPushUri }: { talerPayPushUri: string }) => ( + component={({ talerUri }: { talerUri: string }) => ( <CallToActionTemplate title={i18n.str`Digital cash transfer`}> <TransferPickupPage - talerPayPushUri={decodeURIComponent(talerPayPushUri)} + talerPayPushUri={decodeURIComponent(talerUri)} onClose={() => redirectTo(Pages.balance)} onSuccess={(tid: string) => redirectTo(Pages.balanceTransaction({ tid })) diff --git a/packages/taler-wallet-webextension/src/wxBackend.ts b/packages/taler-wallet-webextension/src/wxBackend.ts index 3655c5dbc..c50412053 100644 --- a/packages/taler-wallet-webextension/src/wxBackend.ts +++ b/packages/taler-wallet-webextension/src/wxBackend.ts @@ -34,6 +34,8 @@ import { WalletDiagnostics, makeErrorDetail, getErrorDetailFromException, + parseTalerUri, + TalerUriAction, } from "@gnu-taler/taler-util"; import { DbAccess, @@ -332,69 +334,17 @@ function parseTalerUriAndRedirect(tabId: number, maybeTalerUri: string): void { const talerUri = maybeTalerUri.startsWith("ext+") ? maybeTalerUri.substring(4) : maybeTalerUri; - const uriType = classifyTalerUri(talerUri); - switch (uriType) { - case TalerUriType.TalerWithdraw: - return platform.redirectTabToWalletPage( - tabId, - `/cta/withdraw?talerWithdrawUri=${encodeURIComponent(talerUri)}`, - ); - case TalerUriType.TalerPay: - return platform.redirectTabToWalletPage( - tabId, - `/cta/pay?talerPayUri=${encodeURIComponent(talerUri)}`, - ); - case TalerUriType.TalerTip: - return platform.redirectTabToWalletPage( - tabId, - `/cta/tip?talerTipUri=${encodeURIComponent(talerUri)}`, - ); - case TalerUriType.TalerRefund: - return platform.redirectTabToWalletPage( - tabId, - `/cta/refund?talerRefundUri=${encodeURIComponent(talerUri)}`, - ); - case TalerUriType.TalerPayPull: - return platform.redirectTabToWalletPage( - tabId, - `/cta/invoice/pay?talerPayPullUri=${encodeURIComponent(talerUri)}`, - ); - case TalerUriType.TalerPayPush: - return platform.redirectTabToWalletPage( - tabId, - `/cta/transfer/pickup?talerPayPushUri=${encodeURIComponent(talerUri)}`, - ); - case TalerUriType.TalerRecovery: - return platform.redirectTabToWalletPage( - tabId, - `/cta/transfer/recovery?talerBackupUri=${encodeURIComponent(talerUri)}`, - ); - case TalerUriType.TalerPayTemplate: - return platform.redirectTabToWalletPage( - tabId, - `/cta/pay/template?talerPayTemplateUri=${encodeURIComponent(talerUri)}`, - ); - return; - case TalerUriType.Unknown: - logger.warn( - `Response with HTTP 402 the Taler header but could not classify ${talerUri}`, - ); - return; - case TalerUriType.TalerDevExperiment: - // FIXME: Implement! - logger.warn("not implemented"); - return; - case TalerUriType.TalerTemplate: - logger.warn("not implemented"); - return; - default: { - const error: never = uriType; - logger.warn( - `Response with HTTP 402 the Taler header "${error}", but header value is not a taler:// URI.`, - ); - return; - } + const uri = parseTalerUri(talerUri); + if (!uri) { + logger.warn( + `Response with HTTP 402 the Taler header but could not classify ${talerUri}`, + ); + return; } + return platform.redirectTabToWalletPage( + tabId, + `/taler-uri/${encodeURIComponent(talerUri)}`, + ); } /** |