aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--packages/taler-wallet-webextension/dev-html/.gitignore4
-rw-r--r--packages/taler-wallet-webextension/dev-html/index.html48
-rw-r--r--packages/taler-wallet-webextension/dev-html/popup.html39
-rw-r--r--packages/taler-wallet-webextension/dev-html/tests.html (renamed from packages/taler-wallet-webextension/run-test-in-browser.html)9
-rw-r--r--packages/taler-wallet-webextension/dev-html/wallet.html29
-rw-r--r--packages/taler-wallet-webextension/run-wallet-in-browser.html14
-rw-r--r--packages/taler-wallet-webextension/serve-esbuild.mjs22
-rw-r--r--packages/taler-wallet-webextension/src/background.dev.ts43
-rw-r--r--packages/taler-wallet-webextension/src/background.ts4
-rw-r--r--packages/taler-wallet-webextension/src/browserWorkerEntry.ts12
-rw-r--r--packages/taler-wallet-webextension/src/components/styled/index.tsx2
-rw-r--r--packages/taler-wallet-webextension/src/hooks/useExtendedPermissions.ts35
-rw-r--r--packages/taler-wallet-webextension/src/platform/api.ts123
-rw-r--r--packages/taler-wallet-webextension/src/platform/chrome.ts38
-rw-r--r--packages/taler-wallet-webextension/src/platform/dev.ts159
-rw-r--r--packages/taler-wallet-webextension/src/popup/Application.tsx183
-rw-r--r--packages/taler-wallet-webextension/src/popup/TalerActionFound.tsx2
-rw-r--r--packages/taler-wallet-webextension/src/popupEntryPoint.dev.tsx54
-rw-r--r--packages/taler-wallet-webextension/src/popupEntryPoint.tsx186
-rw-r--r--packages/taler-wallet-webextension/src/svg/chevron-down.svg9
-rw-r--r--packages/taler-wallet-webextension/src/wallet/AddNewActionView.tsx2
-rw-r--r--packages/taler-wallet-webextension/src/wallet/Application.tsx263
-rw-r--r--packages/taler-wallet-webextension/src/wallet/DepositPage.tsx3
-rw-r--r--packages/taler-wallet-webextension/src/walletEntryPoint.dev.tsx54
-rw-r--r--packages/taler-wallet-webextension/src/walletEntryPoint.tsx266
-rw-r--r--packages/taler-wallet-webextension/src/wxApi.ts6
-rw-r--r--packages/taler-wallet-webextension/src/wxBackend.ts5
-rw-r--r--packages/taler-wallet-webextension/static/wallet.html2
28 files changed, 1087 insertions, 529 deletions
diff --git a/packages/taler-wallet-webextension/dev-html/.gitignore b/packages/taler-wallet-webextension/dev-html/.gitignore
new file mode 100644
index 000000000..c4f051f4f
--- /dev/null
+++ b/packages/taler-wallet-webextension/dev-html/.gitignore
@@ -0,0 +1,4 @@
+/mocha.css
+/mocha.js
+/mocha.js.map
+/manifest.json
diff --git a/packages/taler-wallet-webextension/dev-html/index.html b/packages/taler-wallet-webextension/dev-html/index.html
new file mode 100644
index 000000000..c0919e9b9
--- /dev/null
+++ b/packages/taler-wallet-webextension/dev-html/index.html
@@ -0,0 +1,48 @@
+<html>
+ <head>
+ <meta charset="utf-8" />
+ <link rel="manifest" href="./manifest.json" />
+ </head>
+ <body>
+ <script>
+ function openPopup() {
+ window.frames["popup"].location = "/popup.html";
+ }
+ function openWallet() {
+ window.frames["wallet"].location = "/wallet.html";
+ }
+ function closeWallet() {
+ window.frames["wallet"].location = "about:blank";
+ }
+ </script>
+ <input type="text" />
+ <button value="asd" onclick="openPopup()">open popup</button>
+ <button value="asd" onclick="closeWallet();openWallet()">
+ reload wallet page
+ </button>
+ <hr />
+ <iframe
+ id="popup-window"
+ name="popup"
+ src="about:blank"
+ name="popup"
+ width="500"
+ height="325"
+ >
+ </iframe>
+ <hr />
+ <iframe
+ id="wallet-window"
+ name="wallet"
+ src="about:blank"
+ name="wallet"
+ width="800"
+ height="100%"
+ >
+ </iframe>
+ <hr />
+ <iframe src="/tests.html" name="wallet" width="800" height="100%"> </iframe>
+ <hr />
+ <script src="/dist/background.dev.js"></script>
+ </body>
+</html>
diff --git a/packages/taler-wallet-webextension/dev-html/popup.html b/packages/taler-wallet-webextension/dev-html/popup.html
new file mode 100644
index 000000000..93a886d54
--- /dev/null
+++ b/packages/taler-wallet-webextension/dev-html/popup.html
@@ -0,0 +1,39 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8" />
+ <style>
+ html {
+ font-family: sans-serif; /* 1 */
+ }
+ body {
+ margin: 0;
+ }
+ </style>
+ <style>
+ html {
+ }
+ h1 {
+ font-size: 2em;
+ }
+ input {
+ font: inherit;
+ }
+ body {
+ margin: 0;
+ font-size: 100%;
+ padding: 0;
+ overflow: hidden;
+ background-color: #f8faf7;
+ font-family: Arial, Helvetica, sans-serif;
+ }
+ </style>
+
+ <link rel="stylesheet" type="text/css" href="/dist/popupEntryPoint.css" />
+ <script src="/dist/popupEntryPoint.dev.js"></script>
+ </head>
+
+ <body>
+ <taler-popup id="container" class="popup-container"></taler-popup>
+ </body>
+</html>
diff --git a/packages/taler-wallet-webextension/run-test-in-browser.html b/packages/taler-wallet-webextension/dev-html/tests.html
index b027c0716..4b3ec93b5 100644
--- a/packages/taler-wallet-webextension/run-test-in-browser.html
+++ b/packages/taler-wallet-webextension/dev-html/tests.html
@@ -2,19 +2,18 @@
<html>
<head>
<title>Mocha Tests</title>
- <link rel="stylesheet" href="node_modules/mocha/mocha.css" />
+ <link rel="stylesheet" href="/mocha.css" />
</head>
<body>
<div id="mocha"></div>
- <script src="node_modules/mocha/mocha.js"></script>
+ <script src="/mocha.js"></script>
<script>
mocha.setup("bdd");
</script>
<!-- load code you want to test here -->
-
- <script src="dist/stories.test.js"></script>
- <script src="dist/hooks/useTalerActionURL.test.js"></script>
+ <script src="/dist/stories.test.js"></script>
+ <script src="/dist/hooks/useTalerActionURL.test.js"></script>
<!-- load your test files here -->
<script>
diff --git a/packages/taler-wallet-webextension/dev-html/wallet.html b/packages/taler-wallet-webextension/dev-html/wallet.html
new file mode 100644
index 000000000..ff8616847
--- /dev/null
+++ b/packages/taler-wallet-webextension/dev-html/wallet.html
@@ -0,0 +1,29 @@
+<html>
+ <head>
+ <meta charset="utf-8" />
+ <link rel="stylesheet" type="text/css" href="/dist/walletEntryPoint.css" />
+ <style>
+ html {
+ font-family: sans-serif; /* 1 */
+ }
+ h1 {
+ font-size: 2em;
+ }
+ input {
+ font: inherit;
+ }
+ body {
+ margin: 0;
+ font-size: 100%;
+ padding: 0;
+ background-color: #f8faf7;
+ font-family: Arial, Helvetica, sans-serif;
+ }
+ </style>
+ <script src="/dist/walletEntryPoint.dev.js"></script>
+ </head>
+
+ <body>
+ <div id="container" class="wallet-container"></div>
+ </body>
+</html>
diff --git a/packages/taler-wallet-webextension/run-wallet-in-browser.html b/packages/taler-wallet-webextension/run-wallet-in-browser.html
deleted file mode 100644
index d0ee34ac4..000000000
--- a/packages/taler-wallet-webextension/run-wallet-in-browser.html
+++ /dev/null
@@ -1,14 +0,0 @@
-<html>
- <head>
- <link rel="manifest" href="./manifest.json" />
- </head>
- <body>
- <iframe src="./static/popup.html" name="popup" width="500" height="400">
- algo
- </iframe>
- <hr />
- <iframe src="./static/wallet.html" name="wallet" width="800" height="100%">
- otroe
- </iframe>
- </body>
-</html>
diff --git a/packages/taler-wallet-webextension/serve-esbuild.mjs b/packages/taler-wallet-webextension/serve-esbuild.mjs
new file mode 100644
index 000000000..0fa2723ae
--- /dev/null
+++ b/packages/taler-wallet-webextension/serve-esbuild.mjs
@@ -0,0 +1,22 @@
+
+import linaria from '@linaria/esbuild'
+import esbuild from 'esbuild'
+import { buildConfig } from "./build-fast-with-linaria.mjs"
+import fs from 'fs';
+
+fs.writeFileSync("dev-html/manifest.json", fs.readFileSync("manifest-v2.json"))
+fs.writeFileSync("dev-html/mocha.css", fs.readFileSync("node_modules/mocha/mocha.css"))
+fs.writeFileSync("dev-html/mocha.js", fs.readFileSync("node_modules/mocha/mocha.js"))
+fs.writeFileSync("dev-html/mocha.js.map", fs.readFileSync("node_modules/mocha/mocha.js.map"))
+
+const server = await esbuild
+ .serve({
+ servedir: 'dev-html',
+ }, { ...buildConfig, outdir: 'dev-html/dist' })
+ .catch((e) => {
+ console.log(e)
+ process.exit(1)
+ });
+
+console.log("ready!", server.port);
+
diff --git a/packages/taler-wallet-webextension/src/background.dev.ts b/packages/taler-wallet-webextension/src/background.dev.ts
new file mode 100644
index 000000000..1493ec246
--- /dev/null
+++ b/packages/taler-wallet-webextension/src/background.dev.ts
@@ -0,0 +1,43 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+ * Entry point for the background page.
+ *
+ * @author sebasjm
+ */
+
+/**
+ * Imports.
+ */
+import { platform, setupPlatform } from "./platform/api";
+import devAPI from "./platform/dev"
+import { wxMain } from "./wxBackend";
+
+console.log("Wallet setup for Dev API")
+setupPlatform(devAPI)
+
+try {
+ platform.registerOnInstalled(() => {
+ platform.openWalletPage("/welcome")
+ })
+} catch (e) {
+ console.error(e);
+}
+
+platform.notifyWhenAppIsReady(() => {
+ wxMain();
+})
diff --git a/packages/taler-wallet-webextension/src/background.ts b/packages/taler-wallet-webextension/src/background.ts
index 9c572c176..7cda6e9ef 100644
--- a/packages/taler-wallet-webextension/src/background.ts
+++ b/packages/taler-wallet-webextension/src/background.ts
@@ -30,8 +30,8 @@ import { wxMain } from "./wxBackend";
const isFirefox = typeof (window as any)['InstallTrigger'] !== 'undefined'
-//FIXME: create different entry point for any platform instead of
-//switching in runtime
+// FIXME: create different entry point for any platform instead of
+// switching in runtime
if (isFirefox) {
console.log("Wallet setup for Firefox API")
setupPlatform(firefoxAPI)
diff --git a/packages/taler-wallet-webextension/src/browserWorkerEntry.ts b/packages/taler-wallet-webextension/src/browserWorkerEntry.ts
index 4494b9af8..f14e03d75 100644
--- a/packages/taler-wallet-webextension/src/browserWorkerEntry.ts
+++ b/packages/taler-wallet-webextension/src/browserWorkerEntry.ts
@@ -32,7 +32,7 @@ const worker: Worker = self as any as Worker;
async function handleRequest(
operation: string,
id: number,
- args: string[],
+ req: unknown,
): Promise<void> {
const impl = nativeCrypto;
@@ -42,7 +42,7 @@ async function handleRequest(
}
try {
- const result = await (impl as any)[operation](...args);
+ const result = await (impl as any)[operation](req);
worker.postMessage({ result, id });
} catch (e) {
logger.error("error during operation", e);
@@ -51,9 +51,9 @@ async function handleRequest(
}
worker.onmessage = (msg: MessageEvent) => {
- const args = msg.data.args;
- if (!Array.isArray(args)) {
- console.error("args must be array");
+ const req = msg.data.req;
+ if (typeof req !== "object") {
+ console.error("request must be an object");
return;
}
const id = msg.data.id;
@@ -67,7 +67,7 @@ worker.onmessage = (msg: MessageEvent) => {
return;
}
- handleRequest(operation, id, args).catch((e) => {
+ handleRequest(operation, id, req).catch((e) => {
console.error("error in browser worker", e);
});
};
diff --git a/packages/taler-wallet-webextension/src/components/styled/index.tsx b/packages/taler-wallet-webextension/src/components/styled/index.tsx
index 13e3189fb..e1b4dd2ac 100644
--- a/packages/taler-wallet-webextension/src/components/styled/index.tsx
+++ b/packages/taler-wallet-webextension/src/components/styled/index.tsx
@@ -143,7 +143,7 @@ export const Middle = styled.div`
export const PopupBox = styled.div<{ noPadding?: boolean; devMode: boolean }>`
height: 290px;
width: 500px;
- overflow-y: scroll;
+ overflow-y: visible;
display: flex;
flex-direction: column;
justify-content: space-between;
diff --git a/packages/taler-wallet-webextension/src/hooks/useExtendedPermissions.ts b/packages/taler-wallet-webextension/src/hooks/useExtendedPermissions.ts
index 66d710705..a35801741 100644
--- a/packages/taler-wallet-webextension/src/hooks/useExtendedPermissions.ts
+++ b/packages/taler-wallet-webextension/src/hooks/useExtendedPermissions.ts
@@ -40,41 +40,18 @@ async function handleExtendedPerm(isEnabled: boolean, onChange: (value: boolean)
if (!isEnabled) {
// We set permissions here, since apparently FF wants this to be done
// as the result of an input event ...
- const granted = await platform.getPermissionsApi().request(getReadRequestPermissions());
- console.log("permissions granted:", granted);
- const lastError = platform.getLastError();
- if (lastError) {
+ let granted: boolean;
+ try {
+ granted = await platform.getPermissionsApi().request(getReadRequestPermissions());
+ } catch (lastError) {
console.error("error requesting permissions");
console.error(lastError);
onChange(false);
- return;
+ return
}
- // try {
+ console.log("permissions granted:", granted);
const res = await wxApi.setExtendedPermissions(granted);
onChange(res.newValue);
- // } finally {
- // return
- // }
-
- // return new Promise<void>((res) => {
- // platform.getPermissionsApi().request(getReadRequestPermissions(), async (granted: boolean) => {
- // console.log("permissions granted:", granted);
- // const lastError = getLastError()
- // if (lastError) {
- // console.error("error requesting permissions");
- // console.error(lastError);
- // onChange(false);
- // return;
- // }
- // try {
- // const res = await wxApi.setExtendedPermissions(granted);
- // onChange(res.newValue);
- // } finally {
- // res()
- // }
-
- // });
- // })
}
await wxApi.setExtendedPermissions(false).then(r => onChange(r.newValue));
return
diff --git a/packages/taler-wallet-webextension/src/platform/api.ts b/packages/taler-wallet-webextension/src/platform/api.ts
index 9b4e02ffb..112f9721c 100644
--- a/packages/taler-wallet-webextension/src/platform/api.ts
+++ b/packages/taler-wallet-webextension/src/platform/api.ts
@@ -38,7 +38,7 @@ export interface CrossBrowserPermissionsApi {
request(p: Permissions): Promise<boolean>;
remove(p: Permissions): Promise<boolean>;
- addPermissionsListener(callback: (p: Permissions) => void): void;
+ addPermissionsListener(callback: (p: Permissions, lastError?: string) => void): void;
}
@@ -57,31 +57,132 @@ export interface WalletVersion {
*/
export interface PlatformAPI {
/**
+ * FIXME: should not be needed
+ *
* check if the platform is firefox
*/
isFirefox(): boolean;
+
/**
- *
+ * Permission API for checking and add a listener
*/
getPermissionsApi(): CrossBrowserPermissionsApi;
+
+ /**
+ * Backend API
+ *
+ * Register a callback to be called when the wallet is ready to start
+ * @param callback
+ */
notifyWhenAppIsReady(callback: () => void): void;
- openWalletURIFromPopup(uriType: TalerUriType, talerUri: string): void;
+
+ /**
+ * Popup API
+ *
+ * Used when an TalerURI is found and open up from the popup UI.
+ * Closes the popup and open the URI into the wallet UI.
+ *
+ * @param talerUri
+ */
+ openWalletURIFromPopup(talerUri: string): void;
+
+ /**
+ * Backend API
+ *
+ * Open a page into the wallet UI
+ * @param page
+ */
openWalletPage(page: string): void;
+
+ /**
+ * Popup API
+ *
+ * Open a page into the wallet UI and closed the popup
+ * @param page
+ */
openWalletPageFromPopup(page: string): void;
- setMessageToWalletBackground(operation: string, payload: any): Promise<CoreApiResponse>;
- listenToWalletNotifications(listener: (m: any) => void): () => void;
- sendMessageToAllChannels(message: MessageFromBackend): void;
- registerAllIncomingConnections(): void;
- registerOnNewMessage(onNewMessage: (message: any, sender: any, callback: any) => void): void;
- registerReloadOnNewVersion(): void;
+
+ /**
+ * Backend API
+ *
+ * When a tab has been detected to have a Taler action the background process
+ * can use this function to redirect the tab to the wallet UI
+ *
+ * @param tabId
+ * @param page
+ */
redirectTabToWalletPage(tabId: number, page: string): void;
+
+ /**
+ * Get the wallet version from manifest
+ */
getWalletVersion(): WalletVersion;
+
+
+ /**
+ * Backend API
+ */
+ registerAllIncomingConnections(): void;
+ /**
+ * Backend API
+ */
+ registerReloadOnNewVersion(): void;
+ /**
+ * Backend API
+ */
registerTalerHeaderListener(onHeader: (tabId: number, url: string) => void): void;
+ /**
+ * Backend API
+ */
registerOnInstalled(callback: () => void): void;
+
+ /**
+ * Backend API
+ *
+ * Check if background process run as service worker. This is used from the
+ * wallet use different http api and crypto worker.
+ */
useServiceWorkerAsBackgroundProcess(): boolean;
- getLastError(): string | undefined;
- searchForTalerLinks(): string | undefined;
+
+ /**
+ * Popup API
+ *
+ * Read the current tab html and try to find any Taler URI or QR code present.
+ *
+ * @return Taler URI if found
+ */
findTalerUriInActiveTab(): Promise<string | undefined>;
+
+ /**
+ * Used from the frontend to send commands to the wallet
+ *
+ * @param operation
+ * @param payload
+ *
+ * @return response from the backend
+ */
+ sendMessageToWalletBackground(operation: string, payload: any): Promise<CoreApiResponse>;
+
+ /**
+ * Used from the frontend to receive notifications about new information
+ * @param listener
+ * @return function to unsubscribe the listener
+ */
+ listenToWalletBackground(listener: (message: MessageFromBackend) => void): () => void;
+
+ /**
+ * Use by the wallet backend to receive operations from frontend (popup & wallet)
+ * and send a response back.
+ *
+ * @param onNewMessage
+ */
+ listenToAllChannels(onNewMessage: (message: any, sender: any, sendResponse: (r: CoreApiResponse) => void) => void): void;
+
+ /**
+ * Used by the wallet backend to send notification about new information
+ * @param message
+ */
+ sendMessageToAllChannels(message: MessageFromBackend): void;
}
export let platform: PlatformAPI = undefined as any;
diff --git a/packages/taler-wallet-webextension/src/platform/chrome.ts b/packages/taler-wallet-webextension/src/platform/chrome.ts
index dada23c57..91ccc220d 100644
--- a/packages/taler-wallet-webextension/src/platform/chrome.ts
+++ b/packages/taler-wallet-webextension/src/platform/chrome.ts
@@ -14,17 +14,16 @@
TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
*/
-import { TalerUriType } from "@gnu-taler/taler-util";
+import { classifyTalerUri, CoreApiResponse, TalerUriType } from "@gnu-taler/taler-util";
import { getReadRequestPermissions } from "../permissions";
import { CrossBrowserPermissionsApi, MessageFromBackend, Permissions, PlatformAPI } from "./api.js";
const api: PlatformAPI = {
isFirefox,
findTalerUriInActiveTab,
- getLastError,
getPermissionsApi,
getWalletVersion,
- listenToWalletNotifications,
+ listenToWalletBackground,
notifyWhenAppIsReady,
openWalletPage,
openWalletPageFromPopup,
@@ -32,12 +31,11 @@ const api: PlatformAPI = {
redirectTabToWalletPage,
registerAllIncomingConnections,
registerOnInstalled,
- registerOnNewMessage,
+ listenToAllChannels,
registerReloadOnNewVersion,
registerTalerHeaderListener,
- searchForTalerLinks,
sendMessageToAllChannels,
- setMessageToWalletBackground,
+ sendMessageToWalletBackground,
useServiceWorkerAsBackgroundProcess
}
@@ -50,7 +48,7 @@ function isFirefox(): boolean {
export function contains(p: Permissions): Promise<boolean> {
return new Promise((res, rej) => {
chrome.permissions.contains(p, (resp) => {
- const le = getLastError()
+ const le = chrome.runtime.lastError?.message
if (le) {
rej(le)
}
@@ -62,7 +60,7 @@ export function contains(p: Permissions): Promise<boolean> {
export async function request(p: Permissions): Promise<boolean> {
return new Promise((res, rej) => {
chrome.permissions.request(p, (resp) => {
- const le = getLastError()
+ const le = chrome.runtime.lastError?.message
if (le) {
rej(le)
}
@@ -74,7 +72,7 @@ export async function request(p: Permissions): Promise<boolean> {
export async function remove(p: Permissions): Promise<boolean> {
return new Promise((res, rej) => {
chrome.permissions.remove(p, (resp) => {
- const le = getLastError()
+ const le = chrome.runtime.lastError?.message
if (le) {
rej(le)
}
@@ -83,9 +81,12 @@ export async function remove(p: Permissions): Promise<boolean> {
})
}
-function addPermissionsListener(callback: (p: Permissions) => void): void {
+function addPermissionsListener(callback: (p: Permissions, lastError?: string) => void): void {
console.log("addPermissionListener is not supported for Firefox");
- chrome.permissions.onAdded.addListener(callback)
+ chrome.permissions.onAdded.addListener((perm: Permissions) => {
+ const lastError = chrome.runtime.lastError?.message;
+ callback(perm, lastError)
+ })
}
function getPermissionsApi(): CrossBrowserPermissionsApi {
@@ -107,7 +108,9 @@ function notifyWhenAppIsReady(callback: () => void) {
}
-function openWalletURIFromPopup(uriType: TalerUriType, talerUri: string) {
+function openWalletURIFromPopup(talerUri: string) {
+ const uriType = classifyTalerUri(talerUri);
+
let url: string | undefined = undefined;
switch (uriType) {
case TalerUriType.TalerWithdraw:
@@ -150,7 +153,7 @@ function openWalletPageFromPopup(page: string) {
);
}
-async function setMessageToWalletBackground(operation: string, payload: any): Promise<any> {
+async function sendMessageToWalletBackground(operation: string, payload: any): Promise<any> {
return new Promise<any>((resolve, reject) => {
chrome.runtime.sendMessage({ operation, payload, id: "(none)" }, (resp) => {
if (chrome.runtime.lastError) {
@@ -164,7 +167,7 @@ async function setMessageToWalletBackground(operation: string, payload: any): Pr
}
let notificationPort: chrome.runtime.Port | undefined;
-function listenToWalletNotifications(listener: (m: any) => void) {
+function listenToWalletBackground(listener: (m: any) => void) {
if (notificationPort === undefined) {
notificationPort = chrome.runtime.connect({ name: "notifications" })
}
@@ -203,7 +206,7 @@ function registerAllIncomingConnections() {
});
}
-function registerOnNewMessage(cb: (message: any, sender: any, callback: any) => void) {
+function listenToAllChannels(cb: (message: any, sender: any, callback: (r: CoreApiResponse) => void) => void) {
chrome.runtime.onMessage.addListener((m, s, c) => {
cb(m, s, c)
@@ -311,11 +314,6 @@ function useServiceWorkerAsBackgroundProcess() {
return chrome.runtime.getManifest().manifest_version === 3
}
-function getLastError() {
- return chrome.runtime.lastError?.message;
-}
-
-
function searchForTalerLinks(): string | undefined {
let found;
found = document.querySelector("a[href^='taler://'")
diff --git a/packages/taler-wallet-webextension/src/platform/dev.ts b/packages/taler-wallet-webextension/src/platform/dev.ts
new file mode 100644
index 000000000..a761bb014
--- /dev/null
+++ b/packages/taler-wallet-webextension/src/platform/dev.ts
@@ -0,0 +1,159 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
+ */
+
+import { classifyTalerUri, CoreApiResponse, TalerUriType } from "@gnu-taler/taler-util";
+import { MessageFromBackend, PlatformAPI } from "./api";
+
+const frames = ["popup", "wallet"]
+
+const api: PlatformAPI = ({
+ isFirefox: () => false,
+ findTalerUriInActiveTab: async () => undefined,
+ getPermissionsApi: () => ({
+ addPermissionsListener: () => undefined, contains: async () => true, remove: async () => false, request: async () => false
+ }),
+ getWalletVersion: () => ({
+ version: 'none'
+ }),
+ notifyWhenAppIsReady: (fn: () => void) => {
+ let total = frames.length
+ function waitAndNotify() {
+ total--
+ if (total < 1) {
+ console.log('done')
+ fn()
+ }
+ }
+ frames.forEach(f => {
+ const theFrame = window.frames[f as any]
+ if (theFrame.location.href === 'about:blank') {
+ waitAndNotify()
+ } else {
+ theFrame.addEventListener("load", waitAndNotify)
+ }
+ })
+ },
+
+ openWalletPage: (page: string) => {
+ window.frames['wallet' as any].location = `/wallet.html#${page}`
+ },
+ openWalletPageFromPopup: (page: string) => {
+ window.parent.frames['wallet' as any].location = `/wallet.html#${page}`
+ window.location.href = "about:blank"
+ },
+ openWalletURIFromPopup: (page: string) => {
+ alert('openWalletURIFromPopup not implemented yet')
+ },
+ redirectTabToWalletPage: (tabId: number, page: string) => {
+ alert('redirectTabToWalletPage not implemented yet')
+ },
+
+ registerAllIncomingConnections: () => undefined,
+ registerOnInstalled: (fn: () => void) => fn(),
+ registerReloadOnNewVersion: () => undefined,
+ registerTalerHeaderListener: () => undefined,
+
+ useServiceWorkerAsBackgroundProcess: () => false,
+
+ listenToAllChannels: (fn: (m: any, s: any, c: (r: CoreApiResponse) => void) => void) => {
+ window.addEventListener("message", (event: MessageEvent<IframeMessageType>) => {
+ if (event.data.type !== 'command') return
+ const sender = event.data.header.replyMe
+ fn(event.data.body, sender, (resp: CoreApiResponse) => {
+ if (event.source) {
+ const msg: IframeMessageResponse = {
+ type: "response",
+ header: { responseId: sender },
+ body: resp
+ }
+ window.parent.postMessage(msg)
+ }
+ })
+ })
+ },
+ sendMessageToAllChannels: (message: MessageFromBackend) => {
+ Array.from(window.frames).forEach(w => {
+ try {
+ w.postMessage({
+ header: {}, body: message
+ });
+ } catch (e) {
+ console.error(e)
+ }
+ })
+ },
+ listenToWalletBackground: (onNewMessage: (m: MessageFromBackend) => void) => {
+ function listener(event: MessageEvent<IframeMessageType>) {
+ if (event.data.type !== 'notification') return
+ onNewMessage(event.data.body)
+ }
+ window.parent.addEventListener("message", listener)
+ return () => {
+ window.parent.removeEventListener("message", listener)
+ }
+ },
+ sendMessageToWalletBackground: async (operation: string, payload: any) => {
+ const replyMe = `reply-${Math.floor(Math.random() * 100000)}`
+ const message: IframeMessageCommand = {
+ type: 'command',
+ header: { replyMe },
+ body: { operation, payload, id: "(none)" }
+ }
+ window.parent.postMessage(message)
+
+ return new Promise((res, rej) => {
+ function listener(event: MessageEvent<IframeMessageType>) {
+ if (event.data.type !== "response" || event.data.header.responseId !== replyMe) {
+ return
+ }
+ res(event.data.body)
+ window.parent.removeEventListener("message", listener)
+ }
+ window.parent.addEventListener("message", listener, {
+
+ })
+ })
+
+ },
+})
+
+type IframeMessageType = IframeMessageNotification | IframeMessageResponse | IframeMessageCommand;
+interface IframeMessageNotification {
+ type: "notification";
+ header: {
+ },
+ body: MessageFromBackend
+}
+interface IframeMessageResponse {
+ type: "response";
+ header: {
+ responseId: string;
+ },
+ body: CoreApiResponse
+}
+
+interface IframeMessageCommand {
+ type: "command";
+ header: {
+ replyMe: string;
+ },
+ body: {
+ operation: any, id: string, payload: any
+ }
+}
+
+export default api;
+
diff --git a/packages/taler-wallet-webextension/src/popup/Application.tsx b/packages/taler-wallet-webextension/src/popup/Application.tsx
new file mode 100644
index 000000000..71b2d6c49
--- /dev/null
+++ b/packages/taler-wallet-webextension/src/popup/Application.tsx
@@ -0,0 +1,183 @@
+/*
+ This file is part of GNU Taler
+ (C) 2020 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+ * Main entry point for extension pages.
+ *
+ * @author sebasjm
+ */
+
+import { createHashHistory } from "history";
+import { Fragment, h, VNode } from "preact";
+import Router, { route, Route } from "preact-router";
+import { Match } from "preact-router/match";
+import { useEffect, useState } from "preact/hooks";
+import PendingTransactions from "../components/PendingTransactions";
+import { PopupBox } from "../components/styled";
+import { DevContextProvider } from "../context/devContext";
+import { IoCProviderForRuntime } from "../context/iocContext";
+import {
+ TranslationProvider,
+ useTranslationContext,
+} from "../context/translation";
+import { useTalerActionURL } from "../hooks/useTalerActionURL";
+import { Pages, PopupNavBar } from "../NavigationBar";
+import { platform } from "../platform/api";
+import { BackupPage } from "../wallet/BackupPage";
+import { ProviderDetailPage } from "../wallet/ProviderDetailPage";
+import { BalancePage } from "./BalancePage";
+import { TalerActionFound } from "./TalerActionFound";
+
+function CheckTalerActionComponent(): VNode {
+ const [talerActionUrl] = useTalerActionURL();
+
+ useEffect(() => {
+ if (talerActionUrl)
+ route(Pages.cta.replace(":action", encodeURIComponent(talerActionUrl)));
+ }, [talerActionUrl]);
+
+ return <Fragment />;
+}
+
+export function Application(): VNode {
+ const hash_history = createHashHistory();
+ return (
+ <TranslationProvider>
+ <DevContextProvider>
+ {({ devMode }: { devMode: boolean }) => (
+ <IoCProviderForRuntime>
+ <PendingTransactions
+ goToTransaction={(txId: string) =>
+ route(Pages.balance_transaction.replace(":tid", txId))
+ }
+ />
+ <Match>
+ {({ path }: { path: string }) => <PopupNavBar path={path} />}
+ </Match>
+ <CheckTalerActionComponent />
+ <PopupBox devMode={devMode}>
+ <Router history={hash_history}>
+ <Route
+ path={Pages.balance}
+ component={BalancePage}
+ goToWalletManualWithdraw={() =>
+ route(
+ Pages.balance_manual_withdraw.replace(":currency?", ""),
+ )
+ }
+ goToWalletDeposit={(currency: string) =>
+ route(Pages.balance_deposit.replace(":currency", currency))
+ }
+ goToWalletHistory={(currency: string) =>
+ route(Pages.balance_history.replace(":currency?", currency))
+ }
+ />
+
+ <Route
+ path={Pages.cta}
+ component={function Action({ action }: { action: string }) {
+ const [, setDismissed] = useTalerActionURL();
+
+ return (
+ <TalerActionFound
+ url={decodeURIComponent(action)}
+ onDismiss={() => {
+ setDismissed(true);
+ route(Pages.balance);
+ }}
+ />
+ );
+ }}
+ />
+
+ <Route
+ path={Pages.backup}
+ component={BackupPage}
+ onAddProvider={() => {
+ route(Pages.backup_provider_add);
+ }}
+ />
+ <Route
+ path={Pages.backup_provider_detail}
+ component={ProviderDetailPage}
+ onBack={() => {
+ route(Pages.backup);
+ }}
+ />
+
+ <Route
+ path={Pages.balance_transaction}
+ component={RedirectToWalletPage}
+ />
+ <Route
+ path={Pages.balance_manual_withdraw}
+ component={RedirectToWalletPage}
+ />
+ <Route
+ path={Pages.balance_deposit}
+ component={RedirectToWalletPage}
+ />
+ <Route
+ path={Pages.balance_history}
+ component={RedirectToWalletPage}
+ />
+ <Route
+ path={Pages.backup_provider_add}
+ component={RedirectToWalletPage}
+ />
+ <Route path={Pages.settings} component={RedirectToWalletPage} />
+ <Route
+ path={Pages.settings_exchange_add}
+ component={RedirectToWalletPage}
+ />
+ <Route path={Pages.dev} component={RedirectToWalletPage} />
+
+ <Route default component={Redirect} to={Pages.balance} />
+ </Router>
+ </PopupBox>
+ </IoCProviderForRuntime>
+ )}
+ </DevContextProvider>
+ </TranslationProvider>
+ );
+}
+
+function RedirectToWalletPage(): VNode {
+ const page = (document.location.hash || "#/").replace("#", "");
+ const [showText, setShowText] = useState(false);
+ useEffect(() => {
+ platform.openWalletPageFromPopup(page);
+ setTimeout(() => {
+ setShowText(true);
+ }, 250);
+ });
+ const { i18n } = useTranslationContext();
+ if (!showText) return <Fragment />;
+ return (
+ <span>
+ <i18n.Translate>
+ this popup is being closed and you are being redirected to {page}
+ </i18n.Translate>
+ </span>
+ );
+}
+
+function Redirect({ to }: { to: string }): null {
+ useEffect(() => {
+ route(to, true);
+ });
+ return null;
+}
diff --git a/packages/taler-wallet-webextension/src/popup/TalerActionFound.tsx b/packages/taler-wallet-webextension/src/popup/TalerActionFound.tsx
index a1082ad92..2af6526c2 100644
--- a/packages/taler-wallet-webextension/src/popup/TalerActionFound.tsx
+++ b/packages/taler-wallet-webextension/src/popup/TalerActionFound.tsx
@@ -34,7 +34,7 @@ export function TalerActionFound({ url, onDismiss }: Props) {
const uriType = classifyTalerUri(url);
const { i18n } = useTranslationContext();
function redirectToWallet() {
- platform.openWalletURIFromPopup(uriType, url);
+ platform.openWalletURIFromPopup(url);
}
return (
<Fragment>
diff --git a/packages/taler-wallet-webextension/src/popupEntryPoint.dev.tsx b/packages/taler-wallet-webextension/src/popupEntryPoint.dev.tsx
new file mode 100644
index 000000000..551b47bfc
--- /dev/null
+++ b/packages/taler-wallet-webextension/src/popupEntryPoint.dev.tsx
@@ -0,0 +1,54 @@
+/*
+ This file is part of GNU Taler
+ (C) 2020 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+ * Main entry point for extension pages.
+ *
+ * @author sebasjm
+ */
+
+import { setupI18n } from "@gnu-taler/taler-util";
+import { Fragment, h, render } from "preact";
+import { strings } from "./i18n/strings";
+import { setupPlatform } from "./platform/api";
+import devAPI from "./platform/dev";
+import { Application } from "./popup/Application";
+
+console.log("Wallet setup for Dev API");
+setupPlatform(devAPI);
+
+function main(): void {
+ try {
+ const container = document.getElementById("container");
+ if (!container) {
+ throw Error("container not found, can't mount page contents");
+ }
+ render(<Application />, container);
+ } catch (e) {
+ console.error("got error", e);
+ if (e instanceof Error) {
+ document.body.innerText = `Fatal error: "${e.message}". Please report this bug at https://bugs.gnunet.org/.`;
+ }
+ }
+}
+
+setupI18n("en", strings);
+
+if (document.readyState === "loading") {
+ document.addEventListener("DOMContentLoaded", main);
+} else {
+ main();
+}
diff --git a/packages/taler-wallet-webextension/src/popupEntryPoint.tsx b/packages/taler-wallet-webextension/src/popupEntryPoint.tsx
index dfb12666b..d68918f7f 100644
--- a/packages/taler-wallet-webextension/src/popupEntryPoint.tsx
+++ b/packages/taler-wallet-webextension/src/popupEntryPoint.tsx
@@ -21,29 +21,23 @@
*/
import { setupI18n } from "@gnu-taler/taler-util";
-import { createHashHistory } from "history";
-import { Fragment, h, render, VNode } from "preact";
-import Router, { route, Route } from "preact-router";
-import { Match } from "preact-router/match";
-import { useEffect, useState } from "preact/hooks";
-import PendingTransactions from "./components/PendingTransactions";
-import { PopupBox } from "./components/styled";
-import { DevContextProvider } from "./context/devContext";
-import { IoCProviderForRuntime } from "./context/iocContext";
-import {
- TranslationProvider,
- useTranslationContext,
-} from "./context/translation";
-import { useTalerActionURL } from "./hooks/useTalerActionURL";
+import { Fragment, h, render } from "preact";
import { strings } from "./i18n/strings";
-import { Pages, PopupNavBar } from "./NavigationBar";
-import { platform, setupPlatform } from "./platform/api";
+import { setupPlatform } from "./platform/api";
import chromeAPI from "./platform/chrome";
import firefoxAPI from "./platform/firefox";
-import { BalancePage } from "./popup/BalancePage";
-import { TalerActionFound } from "./popup/TalerActionFound";
-import { BackupPage } from "./wallet/BackupPage";
-import { ProviderDetailPage } from "./wallet/ProviderDetailPage";
+import { Application } from "./popup/Application";
+
+//FIXME: create different entry point for any platform instead of
+//switching in runtime
+const isFirefox = typeof (window as any)["InstallTrigger"] !== "undefined";
+if (isFirefox) {
+ console.log("Wallet setup for Firefox API");
+ setupPlatform(firefoxAPI);
+} else {
+ console.log("Wallet setup for Chrome API");
+ setupPlatform(chromeAPI);
+}
function main(): void {
try {
@@ -62,160 +56,8 @@ function main(): void {
setupI18n("en", strings);
-//FIXME: create different entry point for any platform instead of
-//switching in runtime
-const isFirefox = typeof (window as any)["InstallTrigger"] !== "undefined";
-if (isFirefox) {
- console.log("Wallet setup for Firefox API");
- setupPlatform(firefoxAPI);
-} else {
- console.log("Wallet setup for Chrome API");
- setupPlatform(chromeAPI);
-}
-
if (document.readyState === "loading") {
document.addEventListener("DOMContentLoaded", main);
} else {
main();
}
-
-function CheckTalerActionComponent(): VNode {
- const [talerActionUrl] = useTalerActionURL();
-
- useEffect(() => {
- if (talerActionUrl)
- route(Pages.cta.replace(":action", encodeURIComponent(talerActionUrl)));
- }, [talerActionUrl]);
-
- return <Fragment />;
-}
-
-function Application(): VNode {
- const hash_history = createHashHistory();
- return (
- <TranslationProvider>
- <DevContextProvider>
- {({ devMode }: { devMode: boolean }) => (
- <IoCProviderForRuntime>
- <PendingTransactions
- goToTransaction={(txId: string) =>
- route(Pages.balance_transaction.replace(":tid", txId))
- }
- />
- <Match>
- {({ path }: { path: string }) => <PopupNavBar path={path} />}
- </Match>
- <CheckTalerActionComponent />
- <PopupBox devMode={devMode}>
- <Router history={hash_history}>
- <Route
- path={Pages.balance}
- component={BalancePage}
- goToWalletManualWithdraw={() =>
- route(
- Pages.balance_manual_withdraw.replace(":currency?", ""),
- )
- }
- goToWalletDeposit={(currency: string) =>
- route(Pages.balance_deposit.replace(":currency", currency))
- }
- goToWalletHistory={(currency: string) =>
- route(Pages.balance_history.replace(":currency?", currency))
- }
- />
-
- <Route
- path={Pages.cta}
- component={function Action({ action }: { action: string }) {
- const [, setDismissed] = useTalerActionURL();
-
- return (
- <TalerActionFound
- url={decodeURIComponent(action)}
- onDismiss={() => {
- setDismissed(true);
- route(Pages.balance);
- }}
- />
- );
- }}
- />
-
- <Route
- path={Pages.backup}
- component={BackupPage}
- onAddProvider={() => {
- route(Pages.backup_provider_add);
- }}
- />
- <Route
- path={Pages.backup_provider_detail}
- component={ProviderDetailPage}
- onBack={() => {
- route(Pages.backup);
- }}
- />
-
- <Route
- path={Pages.balance_transaction}
- component={RedirectToWalletPage}
- />
- <Route
- path={Pages.balance_manual_withdraw}
- component={RedirectToWalletPage}
- />
- <Route
- path={Pages.balance_deposit}
- component={RedirectToWalletPage}
- />
- <Route
- path={Pages.balance_history}
- component={RedirectToWalletPage}
- />
- <Route
- path={Pages.backup_provider_add}
- component={RedirectToWalletPage}
- />
- <Route path={Pages.settings} component={RedirectToWalletPage} />
- <Route
- path={Pages.settings_exchange_add}
- component={RedirectToWalletPage}
- />
- <Route path={Pages.dev} component={RedirectToWalletPage} />
-
- <Route default component={Redirect} to={Pages.balance} />
- </Router>
- </PopupBox>
- </IoCProviderForRuntime>
- )}
- </DevContextProvider>
- </TranslationProvider>
- );
-}
-
-function RedirectToWalletPage(): VNode {
- const page = (document.location.hash || "#/").replace("#", "");
- const [showText, setShowText] = useState(false);
- useEffect(() => {
- platform.openWalletPageFromPopup(page);
- setTimeout(() => {
- setShowText(true);
- }, 250);
- });
- const { i18n } = useTranslationContext();
- if (!showText) return <Fragment />;
- return (
- <span>
- <i18n.Translate>
- this popup is being closed and you are being redirected to {page}
- </i18n.Translate>
- </span>
- );
-}
-
-function Redirect({ to }: { to: string }): null {
- useEffect(() => {
- route(to, true);
- });
- return null;
-}
diff --git a/packages/taler-wallet-webextension/src/svg/chevron-down.svg b/packages/taler-wallet-webextension/src/svg/chevron-down.svg
index 36adbc1c6..0e1c0aeda 100644
--- a/packages/taler-wallet-webextension/src/svg/chevron-down.svg
+++ b/packages/taler-wallet-webextension/src/svg/chevron-down.svg
@@ -1,7 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 19.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
- width="92px" height="92px" viewBox="0 0 92 92" enable-background="new 0 0 92 92" xml:space="preserve">
-<path id="XMLID_467_" d="M46,63c-1.1,0-2.1-0.4-2.9-1.2l-25-26c-1.5-1.6-1.5-4.1,0.1-5.7c1.6-1.5,4.1-1.5,5.7,0.1l22.1,23l22.1-23
- c1.5-1.6,4.1-1.6,5.7-0.1c1.6,1.5,1.6,4.1,0.1,5.7l-25,26C48.1,62.6,47.1,63,46,63z"/>
-</svg>
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 92 92" enable-background="new 0 0 92 92" xml:space="preserve">
+ <path id="XMLID_467_" d="M46,63c-1.1,0-2.1-0.4-2.9-1.2l-25-26c-1.5-1.6-1.5-4.1,0.1-5.7c1.6-1.5,4.1-1.5,5.7,0.1l22.1,23l22.1-23
+ c1.5-1.6,4.1-1.6,5.7-0.1c1.6,1.5,1.6,4.1,0.1,5.7l-25,26C48.1,62.6,47.1,63,46,63z" />
+</svg> \ No newline at end of file
diff --git a/packages/taler-wallet-webextension/src/wallet/AddNewActionView.tsx b/packages/taler-wallet-webextension/src/wallet/AddNewActionView.tsx
index bebf036c9..751dbfba7 100644
--- a/packages/taler-wallet-webextension/src/wallet/AddNewActionView.tsx
+++ b/packages/taler-wallet-webextension/src/wallet/AddNewActionView.tsx
@@ -15,7 +15,7 @@ export function AddNewActionView({ onCancel }: Props): VNode {
const { i18n } = useTranslationContext();
function redirectToWallet() {
- platform.openWalletURIFromPopup(uriType, url);
+ platform.openWalletURIFromPopup(url);
}
return (
diff --git a/packages/taler-wallet-webextension/src/wallet/Application.tsx b/packages/taler-wallet-webextension/src/wallet/Application.tsx
new file mode 100644
index 000000000..2116b500e
--- /dev/null
+++ b/packages/taler-wallet-webextension/src/wallet/Application.tsx
@@ -0,0 +1,263 @@
+/*
+ This file is part of GNU Taler
+ (C) 2020 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+ * Main entry point for extension pages.
+ *
+ * @author sebasjm
+ */
+
+import { createHashHistory } from "history";
+import { Fragment, h, VNode } from "preact";
+import Router, { route, Route } from "preact-router";
+import Match from "preact-router/match";
+import { useEffect, useState } from "preact/hooks";
+import { LogoHeader } from "../components/LogoHeader";
+import PendingTransactions from "../components/PendingTransactions";
+import { SuccessBox, WalletBox } from "../components/styled";
+import { DevContextProvider } from "../context/devContext";
+import { IoCProviderForRuntime } from "../context/iocContext";
+import {
+ TranslationProvider,
+ useTranslationContext,
+} from "../context/translation";
+import { PayPage } from "../cta/Pay";
+import { RefundPage } from "../cta/Refund";
+import { TipPage } from "../cta/Tip";
+import { WithdrawPage } from "../cta/Withdraw";
+import { Pages, WalletNavBar } from "../NavigationBar";
+import { DeveloperPage } from "../popup/DeveloperPage";
+import { BackupPage } from "./BackupPage";
+import { DepositPage } from "./DepositPage";
+import { ExchangeAddPage } from "./ExchangeAddPage";
+import { HistoryPage } from "./History";
+import { ManualWithdrawPage } from "./ManualWithdrawPage";
+import { ProviderAddPage } from "./ProviderAddPage";
+import { ProviderDetailPage } from "./ProviderDetailPage";
+import { SettingsPage } from "./Settings";
+import { TransactionPage } from "./Transaction";
+import { WelcomePage } from "./Welcome";
+
+export function Application(): VNode {
+ const [globalNotification, setGlobalNotification] = useState<
+ VNode | undefined
+ >(undefined);
+ const hash_history = createHashHistory();
+ function clearNotification(): void {
+ setGlobalNotification(undefined);
+ }
+ function clearNotificationWhenMovingOut(): void {
+ // const movingOutFromNotification =
+ // globalNotification && e.url !== globalNotification.to;
+ if (globalNotification) {
+ //&& movingOutFromNotification) {
+ setGlobalNotification(undefined);
+ }
+ }
+ const { i18n } = useTranslationContext();
+
+ return (
+ <TranslationProvider>
+ <DevContextProvider>
+ <IoCProviderForRuntime>
+ {/* <Match/> won't work in the first render if <Router /> is not called first */}
+ {/* https://github.com/preactjs/preact-router/issues/415 */}
+ <Router history={hash_history} />
+ <Match>
+ {({ path }: { path: string }) => {
+ if (path && path.startsWith("/cta")) return;
+ return (
+ <Fragment>
+ <LogoHeader />
+ <WalletNavBar path={path} />
+ <div
+ style={{
+ backgroundColor: "lightcyan",
+ display: "flex",
+ justifyContent: "center",
+ }}
+ >
+ <PendingTransactions
+ goToTransaction={(txId: string) =>
+ route(Pages.balance_transaction.replace(":tid", txId))
+ }
+ />
+ </div>
+ </Fragment>
+ );
+ }}
+ </Match>
+ <WalletBox>
+ {globalNotification && (
+ <SuccessBox onClick={clearNotification}>
+ <div>{globalNotification}</div>
+ </SuccessBox>
+ )}
+ <Router
+ history={hash_history}
+ onChange={clearNotificationWhenMovingOut}
+ >
+ <Route path={Pages.welcome} component={WelcomePage} />
+
+ {/**
+ * BALANCE
+ */}
+
+ <Route
+ path={Pages.balance_history}
+ component={HistoryPage}
+ goToWalletDeposit={(currency: string) =>
+ route(Pages.balance_deposit.replace(":currency", currency))
+ }
+ goToWalletManualWithdraw={(currency?: string) =>
+ route(
+ Pages.balance_manual_withdraw.replace(
+ ":currency?",
+ currency || "",
+ ),
+ )
+ }
+ />
+ <Route
+ path={Pages.balance_transaction}
+ component={TransactionPage}
+ goToWalletHistory={(currency?: string) => {
+ route(
+ Pages.balance_history.replace(":currency?", currency || ""),
+ );
+ }}
+ />
+
+ <Route
+ path={Pages.balance_manual_withdraw}
+ component={ManualWithdrawPage}
+ onCancel={() => {
+ route(Pages.balance);
+ }}
+ />
+
+ <Route
+ path={Pages.balance_deposit}
+ component={DepositPage}
+ onCancel={(currency: string) => {
+ route(Pages.balance_history.replace(":currency?", currency));
+ }}
+ onSuccess={(currency: string) => {
+ route(Pages.balance_history.replace(":currency?", currency));
+ setGlobalNotification(
+ <i18n.Translate>
+ All done, your transaction is in progress
+ </i18n.Translate>,
+ );
+ }}
+ />
+ {/**
+ * PENDING
+ */}
+ <Route path={Pages.settings} component={SettingsPage} />
+
+ {/**
+ * BACKUP
+ */}
+ <Route
+ path={Pages.backup}
+ component={BackupPage}
+ onAddProvider={() => {
+ route(Pages.backup_provider_add);
+ }}
+ />
+ <Route
+ path={Pages.backup_provider_detail}
+ component={ProviderDetailPage}
+ onBack={() => {
+ route(Pages.backup);
+ }}
+ />
+ <Route
+ path={Pages.backup_provider_add}
+ component={ProviderAddPage}
+ onBack={() => {
+ route(Pages.backup);
+ }}
+ />
+
+ {/**
+ * SETTINGS
+ */}
+ <Route
+ path={Pages.settings_exchange_add}
+ component={ExchangeAddPage}
+ onBack={() => {
+ route(Pages.balance);
+ }}
+ />
+
+ {/**
+ * DEV
+ */}
+
+ <Route path={Pages.dev} component={DeveloperPage} />
+
+ {/**
+ * CALL TO ACTION
+ */}
+ <Route
+ path={Pages.cta_pay}
+ component={PayPage}
+ goToWalletManualWithdraw={(currency?: string) =>
+ route(
+ Pages.balance_manual_withdraw.replace(
+ ":currency?",
+ currency || "",
+ ),
+ )
+ }
+ goBack={() => route(Pages.balance)}
+ />
+ <Route path={Pages.cta_refund} component={RefundPage} />
+ <Route path={Pages.cta_tips} component={TipPage} />
+ <Route path={Pages.cta_withdraw} component={WithdrawPage} />
+
+ {/**
+ * NOT FOUND
+ * all redirects should be at the end
+ */}
+ <Route
+ path={Pages.balance}
+ component={Redirect}
+ to={Pages.balance_history.replace(":currency?", "")}
+ />
+
+ <Route
+ default
+ component={Redirect}
+ to={Pages.balance_history.replace(":currency?", "")}
+ />
+ </Router>
+ </WalletBox>
+ </IoCProviderForRuntime>
+ </DevContextProvider>
+ </TranslationProvider>
+ );
+}
+
+function Redirect({ to }: { to: string }): null {
+ useEffect(() => {
+ console.log("got some wrong route", to);
+ route(to, true);
+ });
+ return null;
+}
diff --git a/packages/taler-wallet-webextension/src/wallet/DepositPage.tsx b/packages/taler-wallet-webextension/src/wallet/DepositPage.tsx
index b420c7ebb..df93b0c4e 100644
--- a/packages/taler-wallet-webextension/src/wallet/DepositPage.tsx
+++ b/packages/taler-wallet-webextension/src/wallet/DepositPage.tsx
@@ -253,9 +253,6 @@ export function View({
There is no known bank account to send money to
</i18n.Translate>
</p>
- <ButtonBoxWarning>
- <i18n.Translate>Withdraw</i18n.Translate>
- </ButtonBoxWarning>
</WarningBox>
<footer>
<Button onClick={onCancel}>
diff --git a/packages/taler-wallet-webextension/src/walletEntryPoint.dev.tsx b/packages/taler-wallet-webextension/src/walletEntryPoint.dev.tsx
new file mode 100644
index 000000000..ceceaf04c
--- /dev/null
+++ b/packages/taler-wallet-webextension/src/walletEntryPoint.dev.tsx
@@ -0,0 +1,54 @@
+/*
+ This file is part of GNU Taler
+ (C) 2020 Taler Systems S.A.
+
+ GNU Taler is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
+ */
+
+/**
+ * Main entry point for extension pages.
+ *
+ * @author sebasjm
+ */
+
+import { setupI18n } from "@gnu-taler/taler-util";
+import { Fragment, h, render } from "preact";
+import { strings } from "./i18n/strings";
+import { setupPlatform } from "./platform/api";
+import devAPI from "./platform/dev";
+import { Application } from "./wallet/Application";
+
+console.log("Wallet setup for Dev API");
+setupPlatform(devAPI);
+
+function main(): void {
+ try {
+ const container = document.getElementById("container");
+ if (!container) {
+ throw Error("container not found, can't mount page contents");
+ }
+ render(<Application />, container);
+ } catch (e) {
+ console.error("got error", e);
+ if (e instanceof Error) {
+ document.body.innerText = `Fatal error: "${e.message}". Please report this bug at https://bugs.gnunet.org/.`;
+ }
+ }
+}
+
+setupI18n("en", strings);
+
+if (document.readyState === "loading") {
+ document.addEventListener("DOMContentLoaded", main);
+} else {
+ main();
+}
diff --git a/packages/taler-wallet-webextension/src/walletEntryPoint.tsx b/packages/taler-wallet-webextension/src/walletEntryPoint.tsx
index e7cb1f5e6..549eee507 100644
--- a/packages/taler-wallet-webextension/src/walletEntryPoint.tsx
+++ b/packages/taler-wallet-webextension/src/walletEntryPoint.tsx
@@ -21,40 +21,24 @@
*/
import { setupI18n } from "@gnu-taler/taler-util";
-import { createHashHistory } from "history";
-import { Fragment, h, render, VNode } from "preact";
-import Router, { route, Route } from "preact-router";
-import Match from "preact-router/match";
-import { useEffect, useState } from "preact/hooks";
-import { LogoHeader } from "./components/LogoHeader";
-import PendingTransactions from "./components/PendingTransactions";
-import { SuccessBox, WalletBox } from "./components/styled";
-import { DevContextProvider } from "./context/devContext";
-import { IoCProviderForRuntime } from "./context/iocContext";
-import {
- TranslationProvider,
- useTranslationContext,
-} from "./context/translation";
-import { PayPage } from "./cta/Pay";
-import { RefundPage } from "./cta/Refund";
-import { TipPage } from "./cta/Tip";
-import { WithdrawPage } from "./cta/Withdraw";
+import { Fragment, h, render } from "preact";
import { strings } from "./i18n/strings";
-import { Pages, WalletNavBar } from "./NavigationBar";
import { setupPlatform } from "./platform/api";
import chromeAPI from "./platform/chrome";
import firefoxAPI from "./platform/firefox";
-import { DeveloperPage } from "./popup/DeveloperPage";
-import { BackupPage } from "./wallet/BackupPage";
-import { DepositPage } from "./wallet/DepositPage";
-import { ExchangeAddPage } from "./wallet/ExchangeAddPage";
-import { HistoryPage } from "./wallet/History";
-import { ManualWithdrawPage } from "./wallet/ManualWithdrawPage";
-import { ProviderAddPage } from "./wallet/ProviderAddPage";
-import { ProviderDetailPage } from "./wallet/ProviderDetailPage";
-import { SettingsPage } from "./wallet/Settings";
-import { TransactionPage } from "./wallet/Transaction";
-import { WelcomePage } from "./wallet/Welcome";
+import { Application } from "./wallet/Application";
+
+const isFirefox = typeof (window as any)["InstallTrigger"] !== "undefined";
+
+//FIXME: create different entry point for any platform instead of
+//switching in runtime
+if (isFirefox) {
+ console.log("Wallet setup for Firefox API");
+ setupPlatform(firefoxAPI);
+} else {
+ console.log("Wallet setup for Chrome API");
+ setupPlatform(chromeAPI);
+}
function main(): void {
try {
@@ -73,230 +57,8 @@ function main(): void {
setupI18n("en", strings);
-const isFirefox = typeof (window as any)["InstallTrigger"] !== "undefined";
-//FIXME: create different entry point for any platform instead of
-//switching in runtime
-if (isFirefox) {
- console.log("Wallet setup for Firefox API");
- setupPlatform(firefoxAPI);
-} else {
- console.log("Wallet setup for Chrome API");
- setupPlatform(chromeAPI);
-}
-
if (document.readyState === "loading") {
document.addEventListener("DOMContentLoaded", main);
} else {
main();
}
-
-function Application(): VNode {
- const [globalNotification, setGlobalNotification] = useState<
- VNode | undefined
- >(undefined);
- const hash_history = createHashHistory();
- function clearNotification(): void {
- setGlobalNotification(undefined);
- }
- function clearNotificationWhenMovingOut(): void {
- // const movingOutFromNotification =
- // globalNotification && e.url !== globalNotification.to;
- if (globalNotification) {
- //&& movingOutFromNotification) {
- setGlobalNotification(undefined);
- }
- }
- const { i18n } = useTranslationContext();
-
- return (
- <TranslationProvider>
- <DevContextProvider>
- <IoCProviderForRuntime>
- {/* <Match/> won't work in the first render if <Router /> is not called first */}
- {/* https://github.com/preactjs/preact-router/issues/415 */}
- <Router history={hash_history} />
- <Match>
- {({ path }: { path: string }) => {
- if (path && path.startsWith("/cta")) return;
- return (
- <Fragment>
- <LogoHeader />
- <WalletNavBar path={path} />
- <div
- style={{
- backgroundColor: "lightcyan",
- display: "flex",
- justifyContent: "center",
- }}
- >
- <PendingTransactions
- goToTransaction={(txId: string) =>
- route(Pages.balance_transaction.replace(":tid", txId))
- }
- />
- </div>
- </Fragment>
- );
- }}
- </Match>
- <WalletBox>
- {globalNotification && (
- <SuccessBox onClick={clearNotification}>
- <div>{globalNotification}</div>
- </SuccessBox>
- )}
- <Router
- history={hash_history}
- onChange={clearNotificationWhenMovingOut}
- >
- <Route path={Pages.welcome} component={WelcomePage} />
-
- {/**
- * BALANCE
- */}
-
- <Route
- path={Pages.balance_history}
- component={HistoryPage}
- goToWalletDeposit={(currency: string) =>
- route(Pages.balance_deposit.replace(":currency", currency))
- }
- goToWalletManualWithdraw={(currency?: string) =>
- route(
- Pages.balance_manual_withdraw.replace(
- ":currency?",
- currency || "",
- ),
- )
- }
- />
- <Route
- path={Pages.balance_transaction}
- component={TransactionPage}
- goToWalletHistory={(currency?: string) => {
- route(
- Pages.balance_history.replace(":currency?", currency || ""),
- );
- }}
- />
-
- <Route
- path={Pages.balance_manual_withdraw}
- component={ManualWithdrawPage}
- onCancel={() => {
- route(Pages.balance);
- }}
- />
-
- <Route
- path={Pages.balance_deposit}
- component={DepositPage}
- onCancel={(currency: string) => {
- route(Pages.balance_history.replace(":currency?", currency));
- }}
- onSuccess={(currency: string) => {
- route(Pages.balance_history.replace(":currency?", currency));
- setGlobalNotification(
- <i18n.Translate>
- All done, your transaction is in progress
- </i18n.Translate>,
- );
- }}
- />
- {/**
- * PENDING
- */}
- <Route path={Pages.settings} component={SettingsPage} />
-
- {/**
- * BACKUP
- */}
- <Route
- path={Pages.backup}
- component={BackupPage}
- onAddProvider={() => {
- route(Pages.backup_provider_add);
- }}
- />
- <Route
- path={Pages.backup_provider_detail}
- component={ProviderDetailPage}
- onBack={() => {
- route(Pages.backup);
- }}
- />
- <Route
- path={Pages.backup_provider_add}
- component={ProviderAddPage}
- onBack={() => {
- route(Pages.backup);
- }}
- />
-
- {/**
- * SETTINGS
- */}
- <Route
- path={Pages.settings_exchange_add}
- component={ExchangeAddPage}
- onBack={() => {
- route(Pages.balance);
- }}
- />
-
- {/**
- * DEV
- */}
-
- <Route path={Pages.dev} component={DeveloperPage} />
-
- {/**
- * CALL TO ACTION
- */}
- <Route
- path={Pages.cta_pay}
- component={PayPage}
- goToWalletManualWithdraw={(currency?: string) =>
- route(
- Pages.balance_manual_withdraw.replace(
- ":currency?",
- currency || "",
- ),
- )
- }
- goBack={() => route(Pages.balance)}
- />
- <Route path={Pages.cta_refund} component={RefundPage} />
- <Route path={Pages.cta_tips} component={TipPage} />
- <Route path={Pages.cta_withdraw} component={WithdrawPage} />
-
- {/**
- * NOT FOUND
- * all redirects should be at the end
- */}
- <Route
- path={Pages.balance}
- component={Redirect}
- to={Pages.balance_history.replace(":currency?", "")}
- />
-
- <Route
- default
- component={Redirect}
- to={Pages.balance_history.replace(":currency?", "")}
- />
- </Router>
- </WalletBox>
- </IoCProviderForRuntime>
- </DevContextProvider>
- </TranslationProvider>
- );
-}
-
-function Redirect({ to }: { to: string }): null {
- useEffect(() => {
- console.log("got some wrong route", to);
- route(to, true);
- });
- return null;
-}
diff --git a/packages/taler-wallet-webextension/src/wxApi.ts b/packages/taler-wallet-webextension/src/wxApi.ts
index dd53a4feb..01db2fd91 100644
--- a/packages/taler-wallet-webextension/src/wxApi.ts
+++ b/packages/taler-wallet-webextension/src/wxApi.ts
@@ -97,7 +97,7 @@ export interface UpgradeResponse {
async function callBackend(operation: string, payload: any): Promise<any> {
let response: CoreApiResponse;
try {
- response = await platform.setMessageToWalletBackground(operation, payload);
+ response = await platform.sendMessageToWalletBackground(operation, payload);
} catch (e) {
console.log("Error calling backend");
throw new Error(`Error contacting backend: ${e}`);
@@ -417,11 +417,11 @@ export function onUpdateNotification(
messageTypes: Array<NotificationType>,
doCallback: () => void,
): () => void {
- const listener = (message: MessageFromBackend): void => {
+ const onNewMessage = (message: MessageFromBackend): void => {
const shouldNotify = messageTypes.includes(message.type);
if (shouldNotify) {
doCallback();
}
};
- return platform.listenToWalletNotifications(listener);
+ return platform.listenToWalletBackground(onNewMessage);
}
diff --git a/packages/taler-wallet-webextension/src/wxBackend.ts b/packages/taler-wallet-webextension/src/wxBackend.ts
index 048c8fc79..6b73acd02 100644
--- a/packages/taler-wallet-webextension/src/wxBackend.ts
+++ b/packages/taler-wallet-webextension/src/wxBackend.ts
@@ -269,7 +269,7 @@ export async function wxMain(): Promise<void> {
// Handlers for messages coming directly from the content
// script on the page
- platform.registerOnNewMessage((message, sender, callback) => {
+ platform.listenToAllChannels((message, sender, callback) => {
afterWalletIsInitialized.then(() => {
dispatch(message, sender, callback);
});
@@ -285,8 +285,7 @@ export async function wxMain(): Promise<void> {
// On platforms that support it, also listen to external
// modification of permissions.
- platform.getPermissionsApi().addPermissionsListener((perm) => {
- const lastError = platform.getLastError()
+ platform.getPermissionsApi().addPermissionsListener((perm, lastError) => {
if (lastError) {
console.error(lastError);
return;
diff --git a/packages/taler-wallet-webextension/static/wallet.html b/packages/taler-wallet-webextension/static/wallet.html
index f9dd8a19b..2c9c74b7f 100644
--- a/packages/taler-wallet-webextension/static/wallet.html
+++ b/packages/taler-wallet-webextension/static/wallet.html
@@ -2,7 +2,7 @@
<html>
<head>
<meta charset="utf-8" />
- <link rel="stylesheet" type="text/css" href="/dist/popupEntryPoint.css" />
+ <link rel="stylesheet" type="text/css" href="/dist/walletEntryPoint.css" />
<link rel="icon" href="/static/img/icon.png" />
<script src="/dist/walletEntryPoint.js"></script>
<style>