aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSebastian <sebasjm@gmail.com>2024-06-18 12:51:05 -0300
committerSebastian <sebasjm@gmail.com>2024-06-18 14:26:31 -0300
commit61211b5237b0eeb0ab935f530328a4b57f844be3 (patch)
tree08dc486626aaa5917146861ec18bc278108b9c4f
parent4b9a2f78957587b9ba0a8b52d104b1a879912349 (diff)
downloadwallet-core-61211b5237b0eeb0ab935f530328a4b57f844be3.tar.xz
filter obs by screen
-rw-r--r--packages/taler-wallet-webextension/src/components/Modal.tsx3
-rw-r--r--packages/taler-wallet-webextension/src/components/WalletActivity.tsx155
-rw-r--r--packages/taler-wallet-webextension/src/platform/api.ts1
-rw-r--r--packages/taler-wallet-webextension/src/platform/chrome.ts62
-rw-r--r--packages/taler-wallet-webextension/src/platform/dev.ts5
-rw-r--r--packages/taler-wallet-webextension/src/taler-wallet-interaction-loader.ts145
-rw-r--r--packages/taler-wallet-webextension/src/wxApi.ts1
-rw-r--r--packages/taler-wallet-webextension/src/wxBackend.ts43
8 files changed, 235 insertions, 180 deletions
diff --git a/packages/taler-wallet-webextension/src/components/Modal.tsx b/packages/taler-wallet-webextension/src/components/Modal.tsx
index f8c0f1651..c5f716c76 100644
--- a/packages/taler-wallet-webextension/src/components/Modal.tsx
+++ b/packages/taler-wallet-webextension/src/components/Modal.tsx
@@ -52,8 +52,7 @@ const Body = styled.div`
export function Modal({ title, children, onClose }: Props): VNode {
return (
- <div style={{ top: 0, width: "100%", height: "100%" }}>
-
+ <div style={{ top: 0, position: "fixed", width: "100%", height: "100%" }}>
<FullSize onClick={onClose?.onClick}>
<div
onClick={(e) => e.stopPropagation()}
diff --git a/packages/taler-wallet-webextension/src/components/WalletActivity.tsx b/packages/taler-wallet-webextension/src/components/WalletActivity.tsx
index f29d0b0f7..b3b1a5c1f 100644
--- a/packages/taler-wallet-webextension/src/components/WalletActivity.tsx
+++ b/packages/taler-wallet-webextension/src/components/WalletActivity.tsx
@@ -39,6 +39,7 @@ import { WxApiType } from "../wxApi.js";
import { WalletActivityTrack } from "../wxBackend.js";
import { Modal } from "./Modal.js";
import { Time } from "./Time.js";
+import { Checkbox } from "./Checkbox.js";
const OPEN_ACTIVITY_HEIGHT_PX = 250;
const CLOSE_ACTIVITY_HEIGHT_PX = 40;
@@ -212,7 +213,10 @@ function ShowBackupOperationError({ events, onClick }: MoreInfoPRops): VNode {
<dd>{error.hint ?? "--"}</dd>
<dt>Time</dt>
<dd>
- <Time timestamp={error.when} format="yyyy/MM/dd HH:mm:ss" />
+ <Time
+ timestamp={error.when}
+ format="yyyy/MM/dd HH:mm:ss.SSS"
+ />
</dd>
</dl>
<pre
@@ -360,28 +364,36 @@ function ShowObservabilityEvent({ events, onClick }: MoreInfoPRops): VNode {
const title = (function () {
switch (not.event.type) {
- case ObservabilityEventType.HttpFetchFinishError:
- case ObservabilityEventType.HttpFetchFinishSuccess:
case ObservabilityEventType.HttpFetchStart:
return "HTTP Request";
- case ObservabilityEventType.DbQueryFinishSuccess:
- case ObservabilityEventType.DbQueryFinishError:
+ case ObservabilityEventType.HttpFetchFinishSuccess:
+ return "HTTP Request (o)";
+ case ObservabilityEventType.HttpFetchFinishError:
+ return "HTTP Request (x)";
case ObservabilityEventType.DbQueryStart:
return "Database";
- case ObservabilityEventType.RequestFinishSuccess:
- case ObservabilityEventType.RequestFinishError:
+ case ObservabilityEventType.DbQueryFinishSuccess:
+ return "Database (o)";
+ case ObservabilityEventType.DbQueryFinishError:
+ return "Database (x)";
case ObservabilityEventType.RequestStart:
return "Wallet";
- case ObservabilityEventType.CryptoFinishSuccess:
- case ObservabilityEventType.CryptoFinishError:
+ case ObservabilityEventType.RequestFinishSuccess:
+ return "Wallet (o)";
+ case ObservabilityEventType.RequestFinishError:
+ return "Wallet (x)";
case ObservabilityEventType.CryptoStart:
return "Crypto";
+ case ObservabilityEventType.CryptoFinishSuccess:
+ return "Crypto (o)";
+ case ObservabilityEventType.CryptoFinishError:
+ return "Crypto (x)";
case ObservabilityEventType.TaskStart:
- return "Task start";
+ return "Task";
case ObservabilityEventType.TaskStop:
- return "Task stop";
+ return "Task (s)";
case ObservabilityEventType.TaskReset:
- return "Task reset";
+ return "Task (r)";
case ObservabilityEventType.ShepherdTaskResult:
return "Schedule";
case ObservabilityEventType.DeclareTaskDependency:
@@ -401,12 +413,11 @@ function ShowObservabilityEvent({ events, onClick }: MoreInfoPRops): VNode {
);
});
return (
- <table>
+ <table style={{ width: "100%" }}>
<thead>
<td>Event</td>
<td>Info</td>
- <td>Start</td>
- <td>End</td>
+ <td>When</td>
</thead>
<tbody>{asd}</tbody>
</table>
@@ -417,11 +428,9 @@ function ShowObervavilityDetails({
title,
notif,
onClick,
- prev,
}: {
title: string;
notif: ObservaNotifWithTime;
- prev?: ObservaNotifWithTime;
onClick: (content: VNode) => void;
}): VNode {
switch (notif.event.type) {
@@ -443,7 +452,7 @@ function ShowObervavilityDetails({
wordBreak: "break-word",
}}
>
- {JSON.stringify({ event: notif, prev }, undefined, 2)}
+ {JSON.stringify({ event: notif }, undefined, 2)}
</pre>
</Fragment>,
);
@@ -454,21 +463,21 @@ function ShowObervavilityDetails({
</td>
<td>
{notif.event.url}{" "}
- {prev?.event.type ===
+ {notif?.event.type ===
ObservabilityEventType.HttpFetchFinishSuccess ? (
- `(${prev.event.status})`
- ) : prev?.event.type ===
+ `(${notif.event.status})`
+ ) : notif?.event.type ===
ObservabilityEventType.HttpFetchFinishError ? (
<a
href="#"
onClick={(e) => {
e.preventDefault();
if (
- prev.event.type !==
+ notif.event.type !==
ObservabilityEventType.HttpFetchFinishError
)
return;
- const error = prev.event.error;
+ const error = notif.event.error;
onClick(
<Fragment>
<dl>
@@ -482,7 +491,7 @@ function ShowObervavilityDetails({
<dd>
<Time
timestamp={error.when}
- format="yyyy/MM/dd HH:mm:ss"
+ format="yyyy/MM/dd HH:mm:ss.SSS"
/>
</dd>
</dl>
@@ -504,11 +513,7 @@ function ShowObervavilityDetails({
</td>
<td>
{" "}
- <Time timestamp={notif.when} format="yyyy/MM/dd HH:mm:ss" />
- </td>
- <td>
- {" "}
- <Time timestamp={prev?.when} format="yyyy/MM/dd HH:mm:ss" />
+ <Time timestamp={notif.when} format="yyyy/MM/dd HH:mm:ss.SSS" />
</td>
</tr>
);
@@ -531,7 +536,7 @@ function ShowObervavilityDetails({
wordBreak: "break-word",
}}
>
- {JSON.stringify({ event: notif, prev }, undefined, 2)}
+ {JSON.stringify({ event: notif }, undefined, 2)}
</pre>
</Fragment>,
);
@@ -544,10 +549,7 @@ function ShowObervavilityDetails({
{notif.event.location} {notif.event.name}
</td>
<td>
- <Time timestamp={notif.when} format="yyyy/MM/dd HH:mm:ss" />
- </td>
- <td>
- <Time timestamp={prev?.when} format="yyyy/MM/dd HH:mm:ss" />
+ <Time timestamp={notif.when} format="yyyy/MM/dd HH:mm:ss.SSS" />
</td>
</tr>
);
@@ -572,7 +574,7 @@ function ShowObervavilityDetails({
wordBreak: "break-word",
}}
>
- {JSON.stringify({ event: notif, prev }, undefined, 2)}
+ {JSON.stringify({ event: notif }, undefined, 2)}
</pre>
</Fragment>,
);
@@ -583,10 +585,7 @@ function ShowObervavilityDetails({
</td>
<td>{notif.event.taskId}</td>
<td>
- <Time timestamp={notif.when} format="yyyy/MM/dd HH:mm:ss" />
- </td>
- <td>
- <Time timestamp={prev?.when} format="yyyy/MM/dd HH:mm:ss" />
+ <Time timestamp={notif.when} format="yyyy/MM/dd HH:mm:ss.SSS" />
</td>
</tr>
);
@@ -607,7 +606,7 @@ function ShowObervavilityDetails({
wordBreak: "break-word",
}}
>
- {JSON.stringify({ event: notif, prev }, undefined, 2)}
+ {JSON.stringify({ event: notif }, undefined, 2)}
</pre>
</Fragment>,
);
@@ -618,10 +617,7 @@ function ShowObervavilityDetails({
</td>
<td>{notif.event.resultType}</td>
<td>
- <Time timestamp={notif.when} format="yyyy/MM/dd HH:mm:ss" />
- </td>
- <td>
- <Time timestamp={prev?.when} format="yyyy/MM/dd HH:mm:ss" />
+ <Time timestamp={notif.when} format="yyyy/MM/dd HH:mm:ss.SSS" />
</td>
</tr>
);
@@ -644,7 +640,7 @@ function ShowObervavilityDetails({
wordBreak: "break-word",
}}
>
- {JSON.stringify({ event: notif, prev }, undefined, 2)}
+ {JSON.stringify({ event: notif }, undefined, 2)}
</pre>
</Fragment>,
);
@@ -655,10 +651,7 @@ function ShowObervavilityDetails({
</td>
<td>{notif.event.operation}</td>
<td>
- <Time timestamp={notif.when} format="yyyy/MM/dd HH:mm:ss" />
- </td>
- <td>
- <Time timestamp={prev?.when} format="yyyy/MM/dd HH:mm:ss" />
+ <Time timestamp={notif.when} format="yyyy/MM/dd HH:mm:ss.SSS" />
</td>
</tr>
);
@@ -681,7 +674,7 @@ function ShowObervavilityDetails({
wordBreak: "break-word",
}}
>
- {JSON.stringify({ event: notif, prev }, undefined, 2)}
+ {JSON.stringify({ event: notif }, undefined, 2)}
</pre>
</Fragment>,
);
@@ -692,10 +685,7 @@ function ShowObervavilityDetails({
</td>
<td>{notif.event.type}</td>
<td>
- <Time timestamp={notif.when} format="yyyy/MM/dd HH:mm:ss" />
- </td>
- <td>
- <Time timestamp={prev?.when} format="yyyy/MM/dd HH:mm:ss" />
+ <Time timestamp={notif.when} format="yyyy/MM/dd HH:mm:ss.SSS" />
</td>
</tr>
);
@@ -706,13 +696,18 @@ function ShowObervavilityDetails({
}
}
+function createTabId(tab: chrome.tabs.Tab | undefined) {
+ return !tab ? "popup" : `${tab.windowId}:${tab.id}`;
+}
+
function refresh(
api: WxApiType,
onUpdate: (list: WalletActivityTrack[]) => void,
filter: string,
+ fromView?: chrome.tabs.Tab,
) {
api.background
- .call("getNotifications", { filter })
+ .call("getNotifications", { filter, operationsFrom: createTabId(fromView) })
.then((notif) => {
onUpdate(notif);
})
@@ -721,6 +716,15 @@ function refresh(
});
}
+let currentTab: chrome.tabs.Tab | undefined;
+// Allow running outside the extension for testing
+// tslint:disable-next-line:no-string-literal
+if (typeof chrome !== "undefined") {
+ chrome.tabs.getCurrent().then((d) => {
+ currentTab = d;
+ });
+}
+
export function ObservabilityEventsTable(): VNode {
const { i18n } = useTranslationContext();
const api = useBackendContext();
@@ -728,11 +732,17 @@ export function ObservabilityEventsTable(): VNode {
const [notifications, setNotifications] = useState<WalletActivityTrack[]>([]);
const [showDetails, setShowDetails] = useState<VNode>();
const [filter, onChangeFilter] = useState("");
+ const [onlyThisScreen, setOnlyThisScreen] = useState(true);
useEffect(() => {
let lastTimeout: ReturnType<typeof setTimeout>;
function periodicRefresh() {
- refresh(api, setNotifications, filter);
+ refresh(
+ api,
+ setNotifications,
+ filter,
+ onlyThisScreen ? currentTab : undefined,
+ );
lastTimeout = setTimeout(() => {
periodicRefresh();
@@ -743,7 +753,7 @@ export function ObservabilityEventsTable(): VNode {
};
}
return periodicRefresh();
- }, [filter]);
+ }, [filter, onlyThisScreen]);
return (
<div>
@@ -754,6 +764,12 @@ export function ObservabilityEventsTable(): VNode {
value={filter}
onChange={onChangeFilter}
/>
+ <Checkbox
+ label={i18n.str`All events`}
+ name="terms"
+ onToggle={async () => setOnlyThisScreen((v) => !v)}
+ enabled={!onlyThisScreen}
+ />
<div
style={{
padding: 4,
@@ -763,7 +779,12 @@ export function ObservabilityEventsTable(): VNode {
}}
onClick={() => {
api.background.call("clearNotifications", undefined).then(() => {
- refresh(api, setNotifications, filter);
+ refresh(
+ api,
+ setNotifications,
+ filter,
+ onlyThisScreen ? currentTab : undefined,
+ );
});
}}
>
@@ -784,7 +805,7 @@ export function ObservabilityEventsTable(): VNode {
)}
{notifications.map((not) => {
return (
- <details key={not.id}>
+ <details key={not.groupId}>
<summary>
<div
style={{
@@ -829,10 +850,13 @@ export function ObservabilityEventsTable(): VNode {
})()}
</div>
<div style={{ padding: 4 }}>
- <Time timestamp={not.start} format="yyyy/MM/dd HH:mm:ss" />
+ <Time
+ timestamp={not.start}
+ format="yyyy/MM/dd HH:mm:ss.SSS"
+ />
</div>
<div style={{ padding: 4 }}>
- <Time timestamp={not.end} format="yyyy/MM/dd HH:mm:ss" />
+ <Time timestamp={not.end} format="yyyy/MM/dd HH:mm:ss.SSS" />
</div>
</div>
</summary>
@@ -936,7 +960,7 @@ function ErroDetailModal({
<dd>{error.hint ?? "--"}</dd>
<dt>Time</dt>
<dd>
- <Time timestamp={error.when} format="yyyy/MM/dd HH:mm:ss" />
+ <Time timestamp={error.when} format="yyyy/MM/dd HH:mm:ss.SSS" />
</dd>
</dl>
<pre style={{ whiteSpace: "pre-wrap", wordBreak: "break-word" }}>
@@ -1009,11 +1033,14 @@ export function ActiveTasksTable(): VNode {
<td>
<Time
timestamp={task.firstTry}
- format="yyyy/MM/dd HH:mm:ss"
+ format="yyyy/MM/dd HH:mm:ss.SSS"
/>
</td>
<td>
- <Time timestamp={task.nextTry} format="yyyy/MM/dd HH:mm:ss" />
+ <Time
+ timestamp={task.nextTry}
+ format="yyyy/MM/dd HH:mm:ss.SSS"
+ />
</td>
<td>
{!task.lastError?.code ? (
diff --git a/packages/taler-wallet-webextension/src/platform/api.ts b/packages/taler-wallet-webextension/src/platform/api.ts
index 3c116fab2..2388647c1 100644
--- a/packages/taler-wallet-webextension/src/platform/api.ts
+++ b/packages/taler-wallet-webextension/src/platform/api.ts
@@ -227,6 +227,7 @@ export interface BackgroundPlatformAPI {
listenToAllChannels(
notifyNewMessage: <Op extends WalletOperations | BackgroundOperations>(
message: MessageFromFrontend<Op> & { id: string },
+ from: string,
) => Promise<MessageResponse>,
): void;
diff --git a/packages/taler-wallet-webextension/src/platform/chrome.ts b/packages/taler-wallet-webextension/src/platform/chrome.ts
index 056351e3f..276d464a0 100644
--- a/packages/taler-wallet-webextension/src/platform/chrome.ts
+++ b/packages/taler-wallet-webextension/src/platform/chrome.ts
@@ -53,7 +53,7 @@ const api: BackgroundPlatformAPI & ForegroundPlatformAPI = {
redirectTabToWalletPage,
registerAllIncomingConnections,
registerOnInstalled,
- listenToAllChannels ,
+ listenToAllChannels,
registerReloadOnNewVersion,
sendMessageToAllChannels,
openNewURLFromPopup,
@@ -276,18 +276,20 @@ async function sendMessageToBackground<
Op extends WalletOperations | BackgroundOperations,
>(message: MessageFromFrontend<Op>): Promise<MessageResponse> {
nextMessageIndex = (nextMessageIndex + 1) % (Number.MAX_SAFE_INTEGER - 100);
- const messageWithId = { ...message, id: `id_${nextMessageIndex}` };
+ const messageWithId = { ...message, id: `fg:${nextMessageIndex}` };
return new Promise<MessageResponse>((resolve, reject) => {
logger.trace("send operation to the wallet background", message);
let timedout = false;
const timerId = setTimeout(() => {
timedout = true;
- reject(TalerError.fromDetail(TalerErrorCode.GENERIC_TIMEOUT, {
- requestMethod: "wallet",
- requestUrl: message.operation,
- timeoutMs: 20 * 1000,
- }));
+ reject(
+ TalerError.fromDetail(TalerErrorCode.GENERIC_TIMEOUT, {
+ requestMethod: "wallet",
+ requestUrl: message.operation,
+ timeoutMs: 20 * 1000,
+ }),
+ );
}, 20 * 1000);
chrome.runtime.sendMessage(messageWithId, (backgroundResponse) => {
if (timedout) {
@@ -309,7 +311,9 @@ async function sendMessageToBackground<
* To be used by the foreground
*/
let notificationPort: chrome.runtime.Port | undefined;
-function listenToWalletBackground(listener: (message: MessageFromBackend) => void): () => void {
+function listenToWalletBackground(
+ listener: (message: MessageFromBackend) => void,
+): () => void {
if (notificationPort === undefined) {
notificationPort = chrome.runtime.connect({ name: "notifications" });
}
@@ -380,13 +384,18 @@ function registerAllIncomingConnections(): void {
});
}
+function createTabId(tab: chrome.tabs.Tab | undefined) {
+ return !tab ? "popup" : `${tab.windowId}:${tab.id}`;
+}
+
function listenToAllChannels(
notifyNewMessage: <Op extends WalletOperations | BackgroundOperations>(
message: MessageFromFrontend<Op> & { id: string },
+ id: string,
) => Promise<MessageResponse>,
): void {
chrome.runtime.onMessage.addListener((message, sender, reply) => {
- notifyNewMessage(message)
+ notifyNewMessage(message, createTabId(sender.tab))
.then((apiResponse) => {
try {
reply(apiResponse);
@@ -483,26 +492,26 @@ function setAlertedIcon(): void {
interface OffscreenCanvasRenderingContext2D
extends CanvasState,
- CanvasTransform,
- CanvasCompositing,
- CanvasImageSmoothing,
- CanvasFillStrokeStyles,
- CanvasShadowStyles,
- CanvasFilters,
- CanvasRect,
- CanvasDrawPath,
- CanvasUserInterface,
- CanvasText,
- CanvasDrawImage,
- CanvasImageData,
- CanvasPathDrawingStyles,
- CanvasTextDrawingStyles,
- CanvasPath {
+ CanvasTransform,
+ CanvasCompositing,
+ CanvasImageSmoothing,
+ CanvasFillStrokeStyles,
+ CanvasShadowStyles,
+ CanvasFilters,
+ CanvasRect,
+ CanvasDrawPath,
+ CanvasUserInterface,
+ CanvasText,
+ CanvasDrawImage,
+ CanvasImageData,
+ CanvasPathDrawingStyles,
+ CanvasTextDrawingStyles,
+ CanvasPath {
readonly canvas: OffscreenCanvas;
}
declare const OffscreenCanvasRenderingContext2D: {
prototype: OffscreenCanvasRenderingContext2D;
- new(): OffscreenCanvasRenderingContext2D;
+ new (): OffscreenCanvasRenderingContext2D;
};
interface OffscreenCanvas extends EventTarget {
@@ -515,7 +524,7 @@ interface OffscreenCanvas extends EventTarget {
}
declare const OffscreenCanvas: {
prototype: OffscreenCanvas;
- new(width: number, height: number): OffscreenCanvas;
+ new (width: number, height: number): OffscreenCanvas;
};
function createCanvas(size: number): OffscreenCanvas {
@@ -760,7 +769,6 @@ function listenNetworkConnectionState(
};
}
-
function runningOnPrivateMode(): boolean {
return chrome.extension.inIncognitoContext;
}
diff --git a/packages/taler-wallet-webextension/src/platform/dev.ts b/packages/taler-wallet-webextension/src/platform/dev.ts
index b53e8f3c4..844a5c517 100644
--- a/packages/taler-wallet-webextension/src/platform/dev.ts
+++ b/packages/taler-wallet-webextension/src/platform/dev.ts
@@ -95,7 +95,7 @@ const api: BackgroundPlatformAPI & ForegroundPlatformAPI = {
useServiceWorkerAsBackgroundProcess: () => false,
listenToAllChannels: (
- notifyNewMessage: (message: any) => Promise<MessageResponse>,
+ notifyNewMessage: (message: any, from: string) => Promise<MessageResponse>,
) => {
window.addEventListener(
"message",
@@ -103,7 +103,7 @@ const api: BackgroundPlatformAPI & ForegroundPlatformAPI = {
if (event.data.type !== "command") return;
const sender = event.data.header.replyMe;
- notifyNewMessage(event.data.body as any).then((resp) => {
+ notifyNewMessage(event.data.body as any, sender).then((resp) => {
logger.trace(`listenToAllChannels: from ${sender}`, event);
if (event.source) {
const msg: IframeMessageResponse = {
@@ -199,4 +199,3 @@ interface IframeMessageCommand {
}
export default api;
-
diff --git a/packages/taler-wallet-webextension/src/taler-wallet-interaction-loader.ts b/packages/taler-wallet-webextension/src/taler-wallet-interaction-loader.ts
index 3b7cbcbb7..5e781121b 100644
--- a/packages/taler-wallet-webextension/src/taler-wallet-interaction-loader.ts
+++ b/packages/taler-wallet-webextension/src/taler-wallet-interaction-loader.ts
@@ -14,7 +14,11 @@
GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
*/
-import { CoreApiResponse, TalerError, TalerErrorCode } from "@gnu-taler/taler-util";
+import {
+ CoreApiResponse,
+ TalerError,
+ TalerErrorCode,
+} from "@gnu-taler/taler-util";
import type { MessageFromBackend } from "./platform/api.js";
/**
@@ -51,8 +55,6 @@ const rootElementIsHTML =
// "meta[name=taler-support]",
// );
-
-
function validateTalerUri(uri: string): boolean {
return (
!!uri && (uri.startsWith("taler://") || uri.startsWith("taler+http://"))
@@ -61,7 +63,9 @@ function validateTalerUri(uri: string): boolean {
function convertURIToWebExtensionPath(uri: string) {
const url = new URL(
- chrome.runtime.getURL(`static/wallet.html#/taler-uri/${encodeURIComponent(uri)}`),
+ chrome.runtime.getURL(
+ `static/wallet.html#/taler-uri/${encodeURIComponent(uri)}`,
+ ),
);
return url.href;
}
@@ -75,7 +79,7 @@ const shouldNotInject =
!rootElementIsHTML;
const logger = {
- debug: (...msg: any[]) => { },
+ debug: (...msg: any[]) => {},
info: (...msg: any[]) =>
console.log(`${new Date().toISOString()} TALER`, ...msg),
error: (...msg: any[]) =>
@@ -87,7 +91,7 @@ const logger = {
/**
*/
function redirectToTalerActionHandler(element: HTMLMetaElement) {
- const name = element.getAttribute("name")
+ const name = element.getAttribute("name");
if (!name) return;
if (name !== "taler-uri") return;
const uri = element.getAttribute("content");
@@ -98,20 +102,20 @@ function redirectToTalerActionHandler(element: HTMLMetaElement) {
return;
}
- const walletPage = convertURIToWebExtensionPath(uri)
- window.location.replace(walletPage)
+ const walletPage = convertURIToWebExtensionPath(uri);
+ window.location.replace(walletPage);
}
function injectTalerSupportScript(head: HTMLHeadElement, trusted: boolean) {
- const meta = head.querySelector("meta[name=taler-support]")
+ const meta = head.querySelector("meta[name=taler-support]");
if (!meta) return;
const content = meta.getAttribute("content");
if (!content) return;
- const features = content.split(",")
+ const features = content.split(",");
const debugEnabled = meta.getAttribute("debug") === "true";
- const hijackEnabled = features.indexOf("uri") !== -1
- const talerApiEnabled = features.indexOf("api") !== -1 && trusted
+ const hijackEnabled = features.indexOf("uri") !== -1;
+ const talerApiEnabled = features.indexOf("api") !== -1 && trusted;
const scriptTag = document.createElement("script");
scriptTag.setAttribute("async", "false");
@@ -131,14 +135,16 @@ function injectTalerSupportScript(head: HTMLHeadElement, trusted: boolean) {
scriptTag.src = url.href;
try {
- head.insertBefore(scriptTag, head.children.length ? head.children[0] : null);
+ head.insertBefore(
+ scriptTag,
+ head.children.length ? head.children[0] : null,
+ );
} catch (e) {
logger.info("inserting link handler failed!");
logger.error(e);
}
}
-
export interface ExtensionOperations {
isAutoOpenEnabled: {
request: void;
@@ -177,31 +183,38 @@ async function callBackground<Op extends keyof ExtensionOperations>(
return response.result as any;
}
-
let nextMessageIndex = 0;
/**
- *
- * @param message
- * @returns
+ *
+ * @param message
+ * @returns
*/
async function sendMessageToBackground<Op extends keyof ExtensionOperations>(
message: MessageFromExtension<Op>,
): Promise<MessageResponse> {
- const messageWithId = { ...message, id: `id_${nextMessageIndex++ % 1000}` };
+ const messageWithId = { ...message, id: `ld:${nextMessageIndex++ % 1000}` };
if (!chrome.runtime.id) {
- return Promise.reject(TalerError.fromDetail(TalerErrorCode.WALLET_CORE_NOT_AVAILABLE, {}))
+ return Promise.reject(
+ TalerError.fromDetail(TalerErrorCode.WALLET_CORE_NOT_AVAILABLE, {}),
+ );
}
return new Promise<any>((resolve, reject) => {
- logger.debug("send operation to the wallet background", message, chrome.runtime.id);
+ logger.debug(
+ "send operation to the wallet background",
+ message,
+ chrome.runtime.id,
+ );
let timedout = false;
const timerId = setTimeout(() => {
timedout = true;
- reject(TalerError.fromDetail(TalerErrorCode.GENERIC_TIMEOUT, {
- requestMethod: "wallet",
- requestUrl: message.operation,
- timeoutMs: 20 * 1000,
- }))
+ reject(
+ TalerError.fromDetail(TalerErrorCode.GENERIC_TIMEOUT, {
+ requestMethod: "wallet",
+ requestUrl: message.operation,
+ timeoutMs: 20 * 1000,
+ }),
+ );
}, 20 * 1000); //five seconds
try {
chrome.runtime.sendMessage(messageWithId, (backgroundResponse) => {
@@ -218,7 +231,7 @@ async function sendMessageToBackground<Op extends keyof ExtensionOperations>(
return true;
});
} catch (e) {
- console.log(e)
+ console.log(e);
}
});
}
@@ -240,71 +253,76 @@ function listenToWalletBackground(listener: (m: any) => void): () => void {
const loaderSettings = {
isAutoOpenEnabled: false,
isDomainTrusted: false,
-}
+};
function start(
onTalerMetaTagFound: (listener: (el: HTMLMetaElement) => void) => void,
- onHeadReady: (listener: (el: HTMLHeadElement) => void) => void
+ onHeadReady: (listener: (el: HTMLHeadElement) => void) => void,
) {
// do not run everywhere, this is just expected to run on site
// that are aware of taler
if (shouldNotInject) return;
- const isAutoOpenEnabled_promise = callBackground("isAutoOpenEnabled", undefined).then(result => {
+ const isAutoOpenEnabled_promise = callBackground(
+ "isAutoOpenEnabled",
+ undefined,
+ ).then((result) => {
loaderSettings.isAutoOpenEnabled = result;
return result;
- })
+ });
const isDomainTrusted_promise = callBackground("isDomainTrusted", {
- domain: window.location.origin
- }).then(result => {
+ domain: window.location.origin,
+ }).then((result) => {
loaderSettings.isDomainTrusted = result;
return result;
- })
+ });
onTalerMetaTagFound(async (el) => {
await isAutoOpenEnabled_promise;
if (!loaderSettings.isAutoOpenEnabled) {
return;
}
- redirectToTalerActionHandler(el)
- })
+ redirectToTalerActionHandler(el);
+ });
onHeadReady(async (el) => {
- const trusted = await isDomainTrusted_promise
- injectTalerSupportScript(el, trusted)
- })
+ const trusted = await isDomainTrusted_promise;
+ injectTalerSupportScript(el, trusted);
+ });
listenToWalletBackground((e: MessageFromBackend) => {
- if (e.type === "web-extension" && e.notification.type === "settings-change") {
- const settings = e.notification.currentValue
- loaderSettings.isAutoOpenEnabled = settings.autoOpen
+ if (
+ e.type === "web-extension" &&
+ e.notification.type === "settings-change"
+ ) {
+ const settings = e.notification.currentValue;
+ loaderSettings.isAutoOpenEnabled = settings.autoOpen;
}
- })
-
+ });
}
function isCorrectMetaElement(el: HTMLMetaElement): boolean {
- const name = el.getAttribute("name")
+ const name = el.getAttribute("name");
if (!name) return false;
if (name !== "taler-uri") return false;
const uri = el.getAttribute("content");
if (!uri) return false;
- return true
+ return true;
}
/**
* Tries to find taler meta tag ASAP and report
- * @param notify
- * @returns
+ * @param notify
+ * @returns
*/
function notifyWhenTalerUriIsFound(notify: (el: HTMLMetaElement) => void) {
if (document.head) {
- const element = document.head.querySelector("meta[name=taler-uri]")
+ const element = document.head.querySelector("meta[name=taler-uri]");
if (!element) return;
if (!(element instanceof HTMLMetaElement)) return;
if (isCorrectMetaElement(element)) {
- notify(element)
+ notify(element);
}
return;
}
@@ -315,34 +333,33 @@ function notifyWhenTalerUriIsFound(notify: (el: HTMLMetaElement) => void) {
mut.addedNodes.forEach((added) => {
if (added instanceof HTMLMetaElement) {
if (isCorrectMetaElement(added)) {
- notify(added)
- obs.disconnect()
+ notify(added);
+ obs.disconnect();
}
}
});
}
});
} catch (e) {
- console.error(e)
+ console.error(e);
}
- })
+ });
obs.observe(document, {
childList: true,
subtree: true,
attributes: false,
- })
-
+ });
}
/**
* Tries to find HEAD tag ASAP and report
- * @param notify
- * @returns
+ * @param notify
+ * @returns
*/
function notifyWhenHeadIsFound(notify: (el: HTMLHeadElement) => void) {
if (document.head) {
- notify(document.head)
+ notify(document.head);
return;
}
const obs = new MutationObserver(async function (mutations) {
@@ -351,22 +368,22 @@ function notifyWhenHeadIsFound(notify: (el: HTMLHeadElement) => void) {
if (mut.type === "childList") {
mut.addedNodes.forEach((added) => {
if (added instanceof HTMLHeadElement) {
- notify(added)
- obs.disconnect()
+ notify(added);
+ obs.disconnect();
}
});
}
});
} catch (e) {
- console.error(e)
+ console.error(e);
}
- })
+ });
obs.observe(document, {
childList: true,
subtree: true,
attributes: false,
- })
+ });
}
start(notifyWhenTalerUriIsFound, notifyWhenHeadIsFound);
diff --git a/packages/taler-wallet-webextension/src/wxApi.ts b/packages/taler-wallet-webextension/src/wxApi.ts
index 0fed0a855..57a49f0cb 100644
--- a/packages/taler-wallet-webextension/src/wxApi.ts
+++ b/packages/taler-wallet-webextension/src/wxApi.ts
@@ -77,6 +77,7 @@ export interface BackgroundOperations {
getNotifications: {
request: {
filter: string;
+ operationsFrom?: string;
};
response: WalletActivityTrack[];
};
diff --git a/packages/taler-wallet-webextension/src/wxBackend.ts b/packages/taler-wallet-webextension/src/wxBackend.ts
index 1601f7703..ab3c465c4 100644
--- a/packages/taler-wallet-webextension/src/wxBackend.ts
+++ b/packages/taler-wallet-webextension/src/wxBackend.ts
@@ -91,19 +91,15 @@ async function resetDb(): Promise<void> {
}
export type WalletActivityTrack = {
- id: number;
+ // id: number;
events: (WalletNotification & { when: AbsoluteTime })[];
start: AbsoluteTime;
type: NotificationType;
end: AbsoluteTime;
groupId: string;
+ requestId?: string; //only for request event
};
-let counter = 0;
-function getUniqueId(): number {
- return counter++;
-}
-
//FIXME: maybe circular buffer
const activity: WalletActivityTrack[] = [];
@@ -123,7 +119,6 @@ function convertWalletActivityNotification(
return undefined;
}
return {
- id: getUniqueId(),
type: event.type,
start: event.when,
end: AbsoluteTime.never(),
@@ -134,7 +129,6 @@ function convertWalletActivityNotification(
case NotificationType.BackupOperationError: {
const groupId = "";
return {
- id: getUniqueId(),
type: event.type,
start: event.when,
end: AbsoluteTime.never(),
@@ -151,7 +145,6 @@ function convertWalletActivityNotification(
return undefined;
}
return {
- id: getUniqueId(),
type: event.type,
start: event.when,
end: AbsoluteTime.never(),
@@ -171,7 +164,6 @@ function convertWalletActivityNotification(
return undefined;
}
return {
- id: getUniqueId(),
type: event.type,
start: event.when,
end: AbsoluteTime.never(),
@@ -182,7 +174,6 @@ function convertWalletActivityNotification(
case NotificationType.Idle: {
const groupId = "";
return {
- id: getUniqueId(),
type: event.type,
start: event.when,
end: AbsoluteTime.never(),
@@ -199,7 +190,6 @@ function convertWalletActivityNotification(
return undefined;
}
return {
- id: getUniqueId(),
type: event.type,
start: event.when,
end: AbsoluteTime.never(),
@@ -216,12 +206,12 @@ function convertWalletActivityNotification(
return undefined;
}
return {
- id: getUniqueId(),
type: event.type,
start: event.when,
end: AbsoluteTime.never(),
events: [event],
groupId,
+ requestId: event.requestId,
};
}
}
@@ -241,14 +231,24 @@ function addNewWalletActivityNotification(
async function getNotifications({
filter,
+ operationFrom,
}: {
filter: string;
+ operationFrom?: string;
}): Promise<WalletActivityTrack[]> {
- if (!filter) return activity;
-
const rg = new RegExp(`.*${filter}.*`);
return activity.filter((event) => {
- return rg.test(event.groupId.toLowerCase());
+ if (operationFrom) {
+ if (event.type !== NotificationType.RequestObservabilityEvent) {
+ return false;
+ }
+ if (event.requestId) {
+ return event.requestId.startsWith(operationFrom);
+ }
+ }
+ if (!filter) return true;
+ const testFilter = rg.test(event.groupId.toLowerCase());
+ return testFilter;
});
}
@@ -318,7 +318,10 @@ let nextMessageIndex = 0;
async function dispatch<
Op extends WalletOperations | BackgroundOperations | ExtensionOperations,
->(req: MessageFromFrontend<Op> & { id: string }): Promise<MessageResponse> {
+>(
+ req: MessageFromFrontend<Op> & { id: string },
+ from: string,
+): Promise<MessageResponse> {
nextMessageIndex = (nextMessageIndex + 1) % (Number.MAX_SAFE_INTEGER - 100);
switch (req.channel) {
@@ -402,7 +405,7 @@ async function dispatch<
};
}
//multiple client can create the same id, send the wallet an unique key
- const newId = `${req.id}_${nextMessageIndex}`;
+ const newId = `${from}:${req.id}`;
const resp = await w.handleCoreApiRequest(
req.operation,
newId,
@@ -516,10 +519,10 @@ export async function wxMain(): Promise<void> {
// Handlers for messages coming directly from the content
// script on the page
logger.trace("listen all channels");
- platform.listenToAllChannels(async (message) => {
+ platform.listenToAllChannels(async (message, from) => {
//wait until wallet is initialized
await afterWalletIsInitialized;
- const result = await dispatch(message);
+ const result = await dispatch(message, from);
return result;
});