summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--packages/taler-wallet-webextension/manifest-v3.json1
-rw-r--r--packages/taler-wallet-webextension/src/hooks/useSettings.ts1
-rw-r--r--packages/taler-wallet-webextension/src/platform/api.ts25
-rw-r--r--packages/taler-wallet-webextension/src/platform/chrome.ts268
-rw-r--r--packages/taler-wallet-webextension/src/platform/dev.ts2
-rw-r--r--packages/taler-wallet-webextension/src/platform/firefox.ts9
-rw-r--r--packages/taler-wallet-webextension/src/wallet/Settings.stories.tsx5
-rw-r--r--packages/taler-wallet-webextension/src/wallet/Settings.tsx32
-rw-r--r--packages/taler-wallet-webextension/src/wxApi.ts10
-rw-r--r--packages/taler-wallet-webextension/src/wxBackend.ts72
10 files changed, 328 insertions, 97 deletions
diff --git a/packages/taler-wallet-webextension/manifest-v3.json b/packages/taler-wallet-webextension/manifest-v3.json
index 93a1a7fc8..bdee05539 100644
--- a/packages/taler-wallet-webextension/manifest-v3.json
+++ b/packages/taler-wallet-webextension/manifest-v3.json
@@ -15,6 +15,7 @@
"permissions": [
"unlimitedStorage",
"storage",
+ "webRequest",
"activeTab",
"scripting",
"declarativeContent",
diff --git a/packages/taler-wallet-webextension/src/hooks/useSettings.ts b/packages/taler-wallet-webextension/src/hooks/useSettings.ts
index 7332c15bb..563f3628a 100644
--- a/packages/taler-wallet-webextension/src/hooks/useSettings.ts
+++ b/packages/taler-wallet-webextension/src/hooks/useSettings.ts
@@ -35,6 +35,7 @@ export const codecForSettings = (): Codec<Settings> =>
buildCodecForObject<Settings>()
.property("walletAllowHttp", codecForBoolean())
.property("injectTalerSupport", codecForBoolean())
+ .property("autoOpenByHeader", codecForBoolean())
.property("advanceMode", codecForBoolean())
.property("backup", codecForBoolean())
.property("langSelector", codecForBoolean())
diff --git a/packages/taler-wallet-webextension/src/platform/api.ts b/packages/taler-wallet-webextension/src/platform/api.ts
index 44b5959a8..56d668a97 100644
--- a/packages/taler-wallet-webextension/src/platform/api.ts
+++ b/packages/taler-wallet-webextension/src/platform/api.ts
@@ -16,20 +16,18 @@
import {
CoreApiResponse,
- NotificationType,
TalerUri,
- WalletNotification,
+ WalletNotification
} from "@gnu-taler/taler-util";
import {
WalletConfig,
- WalletConfigParameter,
- WalletOperations,
+ WalletOperations
} from "@gnu-taler/taler-wallet-core";
-import { BackgroundOperations } from "../wxApi.js";
import {
ExtensionOperations,
MessageFromExtension,
} from "../taler-wallet-interaction-loader.js";
+import { BackgroundOperations } from "../wxApi.js";
export interface Permissions {
/**
@@ -48,9 +46,9 @@ export interface Permissions {
* Compatibility API that works on multiple browsers.
*/
export interface CrossBrowserPermissionsApi {
- // containsHostPermissions(): Promise<boolean>;
- // requestHostPermissions(): Promise<boolean>;
- // removeHostPermissions(): Promise<boolean>;
+ containsHostPermissions(): Promise<boolean>;
+ requestHostPermissions(): Promise<boolean>;
+ removeHostPermissions(): Promise<boolean>;
containsClipboardPermissions(): Promise<boolean>;
requestClipboardPermissions(): Promise<boolean>;
@@ -102,6 +100,7 @@ type WebexWalletConfig = {
export interface Settings extends WebexWalletConfig {
injectTalerSupport: boolean;
+ autoOpenByHeader: boolean;
advanceMode: boolean;
backup: boolean;
langSelector: boolean;
@@ -112,6 +111,7 @@ export interface Settings extends WebexWalletConfig {
export const defaultSettings: Settings = {
injectTalerSupport: true,
+ autoOpenByHeader: true,
advanceMode: false,
backup: false,
langSelector: false,
@@ -206,6 +206,15 @@ export interface BackgroundPlatformAPI {
message: MessageFromFrontend<Op> & { id: string },
) => Promise<MessageResponse>,
): void;
+
+ /**
+ * Backend API
+ */
+ registerTalerHeaderListener(
+ onHeader: (tabId: number, url: string) => void,
+ ): void;
+
+ containsTalerHeaderListener(): boolean;
}
export interface ForegroundPlatformAPI {
/**
diff --git a/packages/taler-wallet-webextension/src/platform/chrome.ts b/packages/taler-wallet-webextension/src/platform/chrome.ts
index b0934f107..3151bd6ab 100644
--- a/packages/taler-wallet-webextension/src/platform/chrome.ts
+++ b/packages/taler-wallet-webextension/src/platform/chrome.ts
@@ -59,6 +59,8 @@ const api: BackgroundPlatformAPI & ForegroundPlatformAPI = {
useServiceWorkerAsBackgroundProcess,
keepAlive,
listenNetworkConnectionState,
+ registerTalerHeaderListener,
+ containsTalerHeaderListener,
};
export default api;
@@ -95,10 +97,6 @@ function isFirefox(): boolean {
return false;
}
-// const hostPermissions = {
-// permissions: ["webRequest"],
-// origins: ["http://*/*", "https://*/*"],
-// };
export function containsClipboardPermissions(): Promise<boolean> {
return new Promise((res, rej) => {
@@ -113,18 +111,6 @@ export function containsClipboardPermissions(): Promise<boolean> {
});
}
-// export function containsHostPermissions(): Promise<boolean> {
-// return new Promise((res, rej) => {
-// chrome.permissions.contains(hostPermissions, (resp) => {
-// const le = chrome.runtime.lastError?.message;
-// if (le) {
-// rej(le);
-// }
-// res(resp);
-// });
-// });
-// }
-
export async function requestClipboardPermissions(): Promise<boolean> {
return new Promise((res, rej) => {
res(false);
@@ -138,67 +124,7 @@ export async function requestClipboardPermissions(): Promise<boolean> {
});
}
-// export async function requestHostPermissions(): Promise<boolean> {
-// return new Promise((res, rej) => {
-// chrome.permissions.request(hostPermissions, (resp) => {
-// const le = chrome.runtime.lastError?.message;
-// if (le) {
-// rej(le);
-// }
-// res(resp);
-// });
-// });
-// }
-
-// type HeaderListenerFunc = (
-// details: chrome.webRequest.WebResponseHeadersDetails,
-// ) => void;
-// let currentHeaderListener: HeaderListenerFunc | undefined = undefined;
-
-// type TabListenerFunc = (tabId: number, info: chrome.tabs.TabChangeInfo) => void;
-// let currentTabListener: TabListenerFunc | undefined = undefined;
-
-// export async function removeHostPermissions(): Promise<boolean> {
-// //if there is a handler already, remove it
-// if (
-// currentHeaderListener &&
-// chrome?.webRequest?.onHeadersReceived?.hasListener(currentHeaderListener)
-// ) {
-// chrome.webRequest.onHeadersReceived.removeListener(currentHeaderListener);
-// }
-// if (
-// currentTabListener &&
-// chrome?.tabs?.onUpdated?.hasListener(currentTabListener)
-// ) {
-// chrome.tabs.onUpdated.removeListener(currentTabListener);
-// }
-
-// currentHeaderListener = undefined;
-// currentTabListener = undefined;
-
-// //notify the browser about this change, this operation is expensive
-// if ("webRequest" in chrome) {
-// chrome.webRequest.handlerBehaviorChanged(() => {
-// if (chrome.runtime.lastError) {
-// logger.error(JSON.stringify(chrome.runtime.lastError));
-// }
-// });
-// }
-
-// if (extensionIsManifestV3()) {
-// // Trying to remove host permissions with manifest >= v3 throws an error
-// return true;
-// }
-// return new Promise((res, rej) => {
-// chrome.permissions.remove(hostPermissions, (resp) => {
-// const le = chrome.runtime.lastError?.message;
-// if (le) {
-// rej(le);
-// }
-// res(resp);
-// });
-// });
-// }
+
export function removeClipboardPermissions(): Promise<boolean> {
return new Promise((res, rej) => {
@@ -225,9 +151,9 @@ function addPermissionsListener(
function getPermissionsApi(): CrossBrowserPermissionsApi {
return {
addPermissionsListener,
- // containsHostPermissions,
- // requestHostPermissions,
- // removeHostPermissions,
+ containsHostPermissions,
+ requestHostPermissions,
+ removeHostPermissions,
requestClipboardPermissions,
removeClipboardPermissions,
containsClipboardPermissions,
@@ -365,7 +291,7 @@ async function sendMessageToBackground<
const timerId = setTimeout(() => {
timedout = true;
reject(TalerError.fromDetail(TalerErrorCode.GENERIC_TIMEOUT, {}) );
- }, 20 * 1000); //five seconds
+ }, 20 * 1000);
chrome.runtime.sendMessage(messageWithId, (backgroundResponse) => {
if (timedout) {
return false; //already rejected
@@ -782,3 +708,183 @@ function listenNetworkConnectionState(
window.removeEventListener("online", notifyOnline);
};
}
+
+type HeaderListenerFunc = (
+ details: chrome.webRequest.WebResponseHeadersDetails,
+) => void;
+let currentHeaderListener: HeaderListenerFunc | undefined = undefined;
+
+type TabListenerFunc = (tabId: number, info: chrome.tabs.TabChangeInfo) => void;
+let currentTabListener: TabListenerFunc | undefined = undefined;
+
+
+function containsTalerHeaderListener(): boolean {
+ return (
+ currentHeaderListener !== undefined || currentTabListener !== undefined
+ );
+}
+function registerTalerHeaderListener(
+ callback: (tabId: number, url: string) => void,
+): void {
+ logger.info("setting up header listener");
+
+ function headerListener(
+ details: chrome.webRequest.WebResponseHeadersDetails,
+ ): void {
+ if (chrome.runtime.lastError) {
+ logger.error(JSON.stringify(chrome.runtime.lastError));
+ return;
+ }
+ if (
+ details.statusCode === 402 ||
+ details.statusCode === 202 ||
+ details.statusCode === 200
+ ) {
+ const values = (details.responseHeaders || [])
+ .filter((h) => h.name.toLowerCase() === "taler")
+ .map((h) => h.value)
+ .filter((value): value is string => !!value);
+ if (values.length > 0) {
+ logger.info(
+ `Found a Taler URI in a response header for the request ${details.url} from tab ${details.tabId}`,
+ );
+ callback(details.tabId, values[0]);
+ }
+ }
+ return;
+ }
+
+ async function tabListener(
+ tabId: number,
+ info: chrome.tabs.TabChangeInfo,
+ ): Promise<void> {
+ if (tabId < 0) return;
+ const tabLocationHasBeenUpdated = info.status === "complete";
+ const tabTitleHasBeenUpdated = info.title !== undefined;
+ if (tabLocationHasBeenUpdated || tabTitleHasBeenUpdated) {
+ const uri = await findTalerUriInTab(tabId);
+ if (!uri) return;
+ logger.info(`Found a Taler URI in the tab ${tabId}`);
+ callback(tabId, uri);
+ }
+ }
+
+ const prevHeaderListener = currentHeaderListener;
+ const prevTabListener = currentTabListener;
+
+ getPermissionsApi()
+ .containsHostPermissions()
+ .then((result) => {
+ //if there is a handler already, remove it
+ if (
+ prevHeaderListener &&
+ chrome?.webRequest?.onHeadersReceived?.hasListener(prevHeaderListener)
+ ) {
+ chrome.webRequest.onHeadersReceived.removeListener(prevHeaderListener);
+ }
+ if (
+ prevTabListener &&
+ chrome?.tabs?.onUpdated?.hasListener(prevTabListener)
+ ) {
+ chrome.tabs.onUpdated.removeListener(prevTabListener);
+ }
+
+ //if the result was positive, add the headerListener
+ if (result) {
+ const headersEvent:
+ | chrome.webRequest.WebResponseHeadersEvent
+ | undefined = chrome?.webRequest?.onHeadersReceived;
+ if (headersEvent) {
+ headersEvent.addListener(headerListener, { urls: ["<all_urls>"] }, [
+ "responseHeaders",
+ ]);
+ currentHeaderListener = headerListener;
+ }
+
+ const tabsEvent: chrome.tabs.TabUpdatedEvent | undefined =
+ chrome?.tabs?.onUpdated;
+ if (tabsEvent) {
+ tabsEvent.addListener(tabListener);
+ currentTabListener = tabListener;
+ }
+ }
+
+ //notify the browser about this change, this operation is expensive
+ chrome?.webRequest?.handlerBehaviorChanged(() => {
+ if (chrome.runtime.lastError) {
+ logger.error(JSON.stringify(chrome.runtime.lastError));
+ }
+ });
+ });
+}
+
+const hostPermissions = {
+ permissions: ["webRequest"],
+ origins: ["http://*/*", "https://*/*"],
+};
+
+export function containsHostPermissions(): Promise<boolean> {
+ return new Promise((res, rej) => {
+ chrome.permissions.contains(hostPermissions, (resp) => {
+ const le = chrome.runtime.lastError?.message;
+ if (le) {
+ rej(le);
+ }
+ res(resp);
+ });
+ });
+}
+
+export async function requestHostPermissions(): Promise<boolean> {
+ return new Promise((res, rej) => {
+ chrome.permissions.request(hostPermissions, (resp) => {
+ const le = chrome.runtime.lastError?.message;
+ if (le) {
+ rej(le);
+ }
+ res(resp);
+ });
+ });
+}
+
+export async function removeHostPermissions(): Promise<boolean> {
+ //if there is a handler already, remove it
+ if (
+ currentHeaderListener &&
+ chrome?.webRequest?.onHeadersReceived?.hasListener(currentHeaderListener)
+ ) {
+ chrome.webRequest.onHeadersReceived.removeListener(currentHeaderListener);
+ }
+ if (
+ currentTabListener &&
+ chrome?.tabs?.onUpdated?.hasListener(currentTabListener)
+ ) {
+ chrome.tabs.onUpdated.removeListener(currentTabListener);
+ }
+
+ currentHeaderListener = undefined;
+ currentTabListener = undefined;
+
+ //notify the browser about this change, this operation is expensive
+ if ("webRequest" in chrome) {
+ chrome.webRequest.handlerBehaviorChanged(() => {
+ if (chrome.runtime.lastError) {
+ logger.error(JSON.stringify(chrome.runtime.lastError));
+ }
+ });
+ }
+
+ if (extensionIsManifestV3()) {
+ // Trying to remove host permissions with manifest >= v3 throws an error
+ return true;
+ }
+ return new Promise((res, rej) => {
+ chrome.permissions.remove(hostPermissions, (resp) => {
+ const le = chrome.runtime.lastError?.message;
+ if (le) {
+ rej(le);
+ }
+ res(resp);
+ });
+ });
+} \ No newline at end of file
diff --git a/packages/taler-wallet-webextension/src/platform/dev.ts b/packages/taler-wallet-webextension/src/platform/dev.ts
index 976ac05f5..218422ded 100644
--- a/packages/taler-wallet-webextension/src/platform/dev.ts
+++ b/packages/taler-wallet-webextension/src/platform/dev.ts
@@ -44,6 +44,8 @@ const api: BackgroundPlatformAPI & ForegroundPlatformAPI = {
removeClipboardPermissions: async () => false,
requestClipboardPermissions: async () => false,
}),
+ registerTalerHeaderListener: () => false,
+ containsTalerHeaderListener: () => false,
getWalletWebExVersion: () => ({
version: "none",
}),
diff --git a/packages/taler-wallet-webextension/src/platform/firefox.ts b/packages/taler-wallet-webextension/src/platform/firefox.ts
index 9f666e7ae..cc734ebf7 100644
--- a/packages/taler-wallet-webextension/src/platform/firefox.ts
+++ b/packages/taler-wallet-webextension/src/platform/firefox.ts
@@ -26,6 +26,9 @@ import chromePlatform, {
containsClipboardPermissions as chromeClipContains,
removeClipboardPermissions as chromeClipRemove,
requestClipboardPermissions as chromeClipRequest,
+ containsHostPermissions as chromeHostContains,
+ requestHostPermissions as chromeHostRequest,
+ removeHostPermissions as chromeHostRemove,
} from "./chrome.js";
const api: BackgroundPlatformAPI & ForegroundPlatformAPI = {
@@ -51,9 +54,9 @@ function addPermissionsListener(callback: (p: Permissions) => void): void {
function getPermissionsApi(): CrossBrowserPermissionsApi {
return {
addPermissionsListener,
- // containsHostPermissions: chromeHostContains,
- // requestHostPermissions: chromeHostRequest,
- // removeHostPermissions: chromeHostRemove,
+ containsHostPermissions: chromeHostContains,
+ requestHostPermissions: chromeHostRequest,
+ removeHostPermissions: chromeHostRemove,
containsClipboardPermissions: chromeClipContains,
removeClipboardPermissions: chromeClipRemove,
requestClipboardPermissions: chromeClipRequest,
diff --git a/packages/taler-wallet-webextension/src/wallet/Settings.stories.tsx b/packages/taler-wallet-webextension/src/wallet/Settings.stories.tsx
index da4a20437..c18c0d9bb 100644
--- a/packages/taler-wallet-webextension/src/wallet/Settings.stories.tsx
+++ b/packages/taler-wallet-webextension/src/wallet/Settings.stories.tsx
@@ -43,12 +43,14 @@ const version = {
version: "0.9.0.13",
hash: "d439c3e1bc743f2aa47de4457953dba6ecb0e20f",
},
+
};
export const AllOff = tests.createExample(TestedComponent, {
deviceName: "this-is-the-device-name",
advanceToggle: { value: false, button: {} },
autoOpenToggle: { value: false, button: {} },
+ injectTalerToggle: { value: false, button: {} },
langToggle: { value: false, button: {} },
setDeviceName: () => Promise.resolve(),
...version,
@@ -58,6 +60,7 @@ export const OneChecked = tests.createExample(TestedComponent, {
deviceName: "this-is-the-device-name",
advanceToggle: { value: false, button: {} },
autoOpenToggle: { value: false, button: {} },
+ injectTalerToggle: { value: false, button: {} },
langToggle: { value: false, button: {} },
setDeviceName: () => Promise.resolve(),
...version,
@@ -67,6 +70,7 @@ export const WithOneExchange = tests.createExample(TestedComponent, {
deviceName: "this-is-the-device-name",
advanceToggle: { value: false, button: {} },
autoOpenToggle: { value: false, button: {} },
+ injectTalerToggle: { value: false, button: {} },
langToggle: { value: false, button: {} },
setDeviceName: () => Promise.resolve(),
knownExchanges: [
@@ -91,6 +95,7 @@ export const WithExchangeInDifferentState = tests.createExample(
deviceName: "this-is-the-device-name",
advanceToggle: { value: false, button: {} },
autoOpenToggle: { value: false, button: {} },
+ injectTalerToggle: { value: false, button: {} },
langToggle: { value: false, button: {} },
setDeviceName: () => Promise.resolve(),
knownExchanges: [
diff --git a/packages/taler-wallet-webextension/src/wallet/Settings.tsx b/packages/taler-wallet-webextension/src/wallet/Settings.tsx
index 45a6db5df..2319fe30a 100644
--- a/packages/taler-wallet-webextension/src/wallet/Settings.tsx
+++ b/packages/taler-wallet-webextension/src/wallet/Settings.tsx
@@ -73,6 +73,14 @@ export function SettingsPage(): VNode {
deviceName={name}
setDeviceName={update}
autoOpenToggle={{
+ value: settings.autoOpenByHeader,
+ button: {
+ onClick: safely("update support injection", async () => {
+ updateSettings("autoOpenByHeader", !settings.autoOpenByHeader);
+ }),
+ },
+ }}
+ injectTalerToggle={{
value: settings.injectTalerSupport,
button: {
onClick: safely("update support injection", async () => {
@@ -109,6 +117,7 @@ export interface ViewProps {
deviceName: string;
setDeviceName: (s: string) => Promise<void>;
autoOpenToggle: ToggleHandler;
+ injectTalerToggle: ToggleHandler;
advanceToggle: ToggleHandler;
langToggle: ToggleHandler;
knownExchanges: Array<ExchangeListItem>;
@@ -122,6 +131,7 @@ export interface ViewProps {
export function SettingsView({
knownExchanges,
autoOpenToggle,
+ injectTalerToggle,
advanceToggle,
langToggle,
coreVersion,
@@ -207,7 +217,23 @@ export function SettingsView({
<i18n.Translate>Add an exchange</i18n.Translate>
</LinkPrimary>
</div>
-
+ <EnabledBySettings name="advanceMode">
+ <SubTitle>
+ <i18n.Translate>Navigator</i18n.Translate>
+ </SubTitle>
+ <Checkbox
+ label={i18n.str`Automatically open wallet based on page content`}
+ name="autoOpen"
+ description={
+ <i18n.Translate>
+ Enabling this option below will make using the wallet faster,
+ but requires more permissions from your browser.
+ </i18n.Translate>
+ }
+ enabled={autoOpenToggle.value!}
+ onToggle={autoOpenToggle.button.onClick!}
+ />
+ </EnabledBySettings>
{coreVersion && (<Fragment>
{LibtoolVersion.compare(coreVersion.version, WALLET_CORE_SUPPORTED_VERSION)?.compatible ? undefined :
@@ -276,8 +302,8 @@ export function SettingsView({
open the wallet using the keyboard shortcut
</i18n.Translate>
}
- enabled={autoOpenToggle.value!}
- onToggle={autoOpenToggle.button.onClick!}
+ enabled={injectTalerToggle.value!}
+ onToggle={injectTalerToggle.button.onClick!}
/>
<SubTitle>
<i18n.Translate>Version</i18n.Translate>
diff --git a/packages/taler-wallet-webextension/src/wxApi.ts b/packages/taler-wallet-webextension/src/wxApi.ts
index 21162ccbf..8fb8211ae 100644
--- a/packages/taler-wallet-webextension/src/wxApi.ts
+++ b/packages/taler-wallet-webextension/src/wxApi.ts
@@ -53,7 +53,7 @@ import { platform } from "./platform/foreground.js";
const logger = new Logger("wxApi");
-export const WALLET_CORE_SUPPORTED_VERSION = "0:0:0"
+export const WALLET_CORE_SUPPORTED_VERSION = "1:0:0"
export interface ExtendedPermissionsResponse {
newValue: boolean;
@@ -83,6 +83,14 @@ export interface BackgroundOperations {
};
response: void;
};
+ containsHeaderListener: {
+ request: void;
+ response: ExtendedPermissionsResponse;
+ };
+ toggleHeaderListener: {
+ request: boolean;
+ response: ExtendedPermissionsResponse;
+ };
}
export interface BackgroundApiClient {
diff --git a/packages/taler-wallet-webextension/src/wxBackend.ts b/packages/taler-wallet-webextension/src/wxBackend.ts
index 40b7077af..23d3d64fa 100644
--- a/packages/taler-wallet-webextension/src/wxBackend.ts
+++ b/packages/taler-wallet-webextension/src/wxBackend.ts
@@ -31,6 +31,7 @@ import {
WalletNotification,
getErrorDetailFromException,
makeErrorDetail,
+ parseTalerUri,
setGlobalLogLevelFromString,
setLogLevelFromString,
} from "@gnu-taler/taler-util";
@@ -54,7 +55,7 @@ import {
import { MessageFromFrontend, MessageResponse } from "./platform/api.js";
import { platform } from "./platform/background.js";
import { ExtensionOperations } from "./taler-wallet-interaction-loader.js";
-import { BackgroundOperations } from "./wxApi.js";
+import { BackgroundOperations, ExtendedPermissionsResponse } from "./wxApi.js";
import { HttpRequestLibrary } from "@gnu-taler/taler-util/http";
/**
@@ -132,14 +133,26 @@ async function isInjectionEnabled(): Promise<boolean> {
return settings.injectTalerSupport === true;
}
+async function isHeaderListenerEnabled(): Promise<boolean> {
+ const settings = await platform.getSettingsFromStorage();
+ return settings.autoOpenByHeader === true;
+}
+
const backendHandlers: BackendHandlerType = {
freeze,
sum,
resetDb,
runGarbageCollector,
setLoggingLevel,
+ containsHeaderListener,
+ toggleHeaderListener,
};
+async function containsHeaderListener(): Promise<ExtendedPermissionsResponse> {
+ const result = await platform.containsTalerHeaderListener();
+ return { newValue: result };
+}
+
async function setLoggingLevel({
tag,
level,
@@ -340,4 +353,61 @@ export async function wxMain(): Promise<void> {
} catch (e) {
console.error(e);
}
+ // On platforms that support it, also listen to external
+ // modification of permissions.
+ platform.getPermissionsApi().addPermissionsListener((perm, lastError) => {
+ logger.info(`permission added: ${perm}`, )
+ if (lastError) {
+ logger.error(
+ `there was a problem trying to get permission ${perm}`,
+ lastError,
+ );
+ return;
+ }
+ platform.registerTalerHeaderListener(parseTalerUriAndRedirect);
+ });
+
+ if (await isHeaderListenerEnabled()) {
+ if (await platform.getPermissionsApi().containsHostPermissions()) {
+ try {
+ platform.registerTalerHeaderListener(parseTalerUriAndRedirect);
+ } catch (e) {
+ logger.error("could not register header listener", e);
+ }
+ } else {
+ await platform.getPermissionsApi().requestHostPermissions()
+ }
+ }
+
+}
+
+
+async function toggleHeaderListener(
+ newVal: boolean,
+): Promise<ExtendedPermissionsResponse> {
+ logger.trace("new extended permissions value", newVal);
+ if (newVal) {
+ platform.registerTalerHeaderListener(parseTalerUriAndRedirect);
+ return { newValue: true };
+ }
+
+ const rem = await platform.getPermissionsApi().removeHostPermissions();
+ logger.trace("permissions removed:", rem);
+ return { newValue: false };
}
+function parseTalerUriAndRedirect(tabId: number, maybeTalerUri: string): void {
+ const talerUri = maybeTalerUri.startsWith("ext+")
+ ? maybeTalerUri.substring(4)
+ : maybeTalerUri;
+ const uri = parseTalerUri(talerUri);
+ if (!uri) {
+ logger.warn(
+ `Response with HTTP 402 the Taler header but could not classify ${talerUri}`,
+ );
+ return;
+ }
+ return platform.redirectTabToWalletPage(
+ tabId,
+ `/taler-uri/${encodeURIComponent(talerUri)}`,
+ );
+} \ No newline at end of file