wallet-core/packages/taler-wallet-webextension/src/wxApi.ts

209 lines
5.0 KiB
TypeScript
Raw Normal View History

2016-02-19 04:23:00 +01:00
/*
2022-06-06 17:05:26 +02:00
This file is part of GNU Taler
(C) 2022 Taler Systems S.A.
2016-02-19 04:23:00 +01:00
2022-06-06 17:05:26 +02:00
GNU Taler is free software; you can redistribute it and/or modify it under the
2016-02-19 04:23:00 +01:00
terms of the GNU General Public License as published by the Free Software
Foundation; either version 3, or (at your option) any later version.
2022-06-06 17:05:26 +02:00
GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
2016-02-19 04:23:00 +01:00
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
2022-06-06 17:05:26 +02:00
GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
2016-02-19 04:23:00 +01:00
*/
/**
* Interface to the wallet through WebExtension messaging.
*/
/**
* Imports.
*/
2020-08-13 20:43:51 +02:00
import {
AbsoluteTime,
CoreApiResponse,
Logger,
NotificationType,
2023-01-09 12:38:48 +01:00
TalerErrorCode,
TalerErrorDetail,
WalletDiagnostics,
2021-03-27 14:35:58 +01:00
} from "@gnu-taler/taler-util";
2021-11-15 15:18:58 +01:00
import {
TalerError,
WalletCoreApiClient,
WalletCoreOpKeys,
WalletCoreRequestType,
WalletCoreResponseType,
2023-01-09 12:38:48 +01:00
WalletOperations,
2021-11-15 15:18:58 +01:00
} from "@gnu-taler/taler-wallet-core";
2022-12-21 20:21:25 +01:00
import {
2023-01-09 12:38:48 +01:00
MessageFromBackend,
MessageFromFrontendBackground,
MessageFromFrontendWallet,
} from "./platform/api.js";
import { platform } from "./platform/foreground.js";
2022-02-23 19:18:37 +01:00
/**
*
2022-06-26 20:52:32 +02:00
* @author sebasjm
2022-02-23 19:18:37 +01:00
*/
2022-12-21 20:21:25 +01:00
const logger = new Logger("wxApi");
export interface ExtendedPermissionsResponse {
newValue: boolean;
}
2022-12-21 20:21:25 +01:00
export interface BackgroundOperations {
2022-12-21 20:36:24 +01:00
freeze: {
request: number;
response: void;
};
sum: {
request: number[];
response: number;
};
2022-12-21 20:21:25 +01:00
resetDb: {
request: void;
response: void;
};
containsHeaderListener: {
request: void;
response: ExtendedPermissionsResponse;
};
getDiagnostics: {
request: void;
response: WalletDiagnostics;
};
toggleHeaderListener: {
request: boolean;
response: ExtendedPermissionsResponse;
};
runGarbageCollector: {
request: void;
response: void;
};
}
export interface BackgroundApiClient {
call<Op extends keyof BackgroundOperations>(
operation: Op,
payload: BackgroundOperations[Op]["request"],
): Promise<BackgroundOperations[Op]["response"]>;
2017-06-05 03:20:28 +02:00
}
2023-01-09 12:38:48 +01:00
export class BackgroundError extends Error {
public errorDetail: TalerErrorDetail;
constructor(title: string, e: TalerErrorDetail) {
super(title);
2023-01-09 12:38:48 +01:00
this.errorDetail = e;
}
}
/**
2022-12-21 20:21:25 +01:00
* BackgroundApiClient integration with browser platform
*/
2022-12-21 20:21:25 +01:00
class BackgroundApiClientImpl implements BackgroundApiClient {
async call<Op extends keyof BackgroundOperations>(
operation: Op,
payload: BackgroundOperations[Op]["request"],
): Promise<BackgroundOperations[Op]["response"]> {
let response: CoreApiResponse;
const message: MessageFromFrontendBackground<Op> = {
channel: "background",
operation,
payload,
};
try {
response = await platform.sendMessageToBackground(message);
2023-01-09 12:38:48 +01:00
} catch (error) {
2022-12-21 20:21:25 +01:00
console.log("Error calling backend");
2023-01-09 12:38:48 +01:00
if (error instanceof Error) {
throw new BackgroundError(operation, {
code: TalerErrorCode.GENERIC_UNEXPECTED_REQUEST_ERROR,
when: AbsoluteTime.now(),
2023-01-09 12:38:48 +01:00
});
}
throw error;
2022-12-21 20:21:25 +01:00
}
logger.info("got response", response);
if (response.type === "error") {
throw new BackgroundError(
`Background operation "${operation}" failed`,
response.error,
);
2022-12-21 20:21:25 +01:00
}
return response.result as any;
}
2016-10-12 02:55:53 +02:00
}
2022-12-21 20:21:25 +01:00
/**
* WalletCoreApiClient integration with browser platform
*/
class WalletApiClientImpl implements WalletCoreApiClient {
async call<Op extends WalletCoreOpKeys>(
operation: Op,
payload: WalletCoreRequestType<Op>,
): Promise<WalletCoreResponseType<Op>> {
let response: CoreApiResponse;
try {
2022-12-21 20:21:25 +01:00
const message: MessageFromFrontendWallet<Op> = {
channel: "wallet",
operation,
payload,
2022-12-21 20:21:25 +01:00
};
response = await platform.sendMessageToBackground(message);
} catch (e) {
console.log("Error calling backend");
throw new Error(`Error contacting backend: ${e}`);
}
logger.info("got response", response);
if (response.type === "error") {
throw new BackgroundError(
`Wallet operation "${operation}" failed`,
response.error,
);
}
return response.result as any;
}
}
2022-10-25 17:23:08 +02:00
function onUpdateNotification(
2022-03-23 21:24:23 +01:00
messageTypes: Array<NotificationType>,
2022-10-25 17:23:08 +02:00
doCallback: undefined | (() => void),
2022-03-23 21:24:23 +01:00
): () => void {
2022-10-25 17:23:08 +02:00
//if no callback, then ignore
if (!doCallback)
return () => {
return;
};
2022-03-25 20:57:27 +01:00
const onNewMessage = (message: MessageFromBackend): void => {
const shouldNotify = messageTypes.includes(message.type);
if (shouldNotify) {
doCallback();
}
};
2022-03-25 20:57:27 +01:00
return platform.listenToWalletBackground(onNewMessage);
}
2022-08-31 05:20:35 +02:00
export type WxApiType = {
wallet: WalletCoreApiClient;
background: BackgroundApiClient;
listener: {
onUpdateNotification: typeof onUpdateNotification;
2022-12-15 21:12:03 +01:00
};
};
2022-10-25 17:23:08 +02:00
export const wxApi = {
2022-12-21 20:21:25 +01:00
wallet: new WalletApiClientImpl(),
background: new BackgroundApiClientImpl(),
2022-10-25 17:23:08 +02:00
listener: {
onUpdateNotification,
},
};