wallet-core/packages/taler-wallet-webextension/src/platform/dev.ts
2022-09-12 14:28:53 -03:00

179 lines
5.2 KiB
TypeScript

/*
This file is part of GNU Taler
(C) 2022 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 { CoreApiResponse } from "@gnu-taler/taler-util";
import { MessageFromBackend, PlatformAPI } from "./api.js";
const frames = ["popup", "wallet"];
const api: PlatformAPI = {
isFirefox: () => false,
keepAlive: (cb: VoidFunction) => cb(),
findTalerUriInActiveTab: async () => undefined,
findTalerUriInClipboard: async () => undefined,
containsTalerHeaderListener: () => {
return true;
},
getPermissionsApi: () => ({
addPermissionsListener: () => undefined,
containsHostPermissions: async () => true,
removeHostPermissions: async () => false,
requestHostPermissions: async () => false,
containsClipboardPermissions: async () => true,
removeClipboardPermissions: async () => false,
requestClipboardPermissions: async () => false,
}),
getWalletWebExVersion: () => ({
version: "none",
}),
notifyWhenAppIsReady: (fn: () => void) => {
let total = frames.length;
function waitAndNotify(): void {
total--;
if (total < 1) {
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) => undefined,
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>): void {
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>): void {
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: Record<string, never>;
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;