From ad63d4c0e1ab249362e1f684ac9dbe5fae2ef34e Mon Sep 17 00:00:00 2001 From: Sebastian Date: Mon, 12 Sep 2022 14:28:53 -0300 Subject: add clipboard perms --- .../taler-wallet-webextension/manifest-v2.json | 5 +- .../taler-wallet-webextension/manifest-v3.json | 5 +- .../taler-wallet-webextension/src/background.ts | 8 --- .../src/hooks/useAutoOpenPermissions.ts | 72 +++++++++++++++++++++ .../src/hooks/useClipboardPermissions.ts | 73 ++++++++++++++++++++++ .../src/hooks/useExtendedPermissions.ts | 72 --------------------- .../src/hooks/useTalerActionURL.ts | 3 +- .../taler-wallet-webextension/src/platform/api.ts | 4 ++ .../src/platform/chrome.ts | 59 +++++++++++++++-- .../taler-wallet-webextension/src/platform/dev.ts | 3 + .../src/platform/firefox.ts | 18 ++++-- .../src/wallet/Settings.stories.tsx | 12 ++-- .../src/wallet/Settings.tsx | 47 +++++++++++--- .../src/wallet/Welcome.tsx | 4 +- .../taler-wallet-webextension/src/wxBackend.ts | 14 ++++- 15 files changed, 284 insertions(+), 115 deletions(-) create mode 100644 packages/taler-wallet-webextension/src/hooks/useAutoOpenPermissions.ts create mode 100644 packages/taler-wallet-webextension/src/hooks/useClipboardPermissions.ts delete mode 100644 packages/taler-wallet-webextension/src/hooks/useExtendedPermissions.ts (limited to 'packages/taler-wallet-webextension') diff --git a/packages/taler-wallet-webextension/manifest-v2.json b/packages/taler-wallet-webextension/manifest-v2.json index e2dd67623..74f103feb 100644 --- a/packages/taler-wallet-webextension/manifest-v2.json +++ b/packages/taler-wallet-webextension/manifest-v2.json @@ -24,7 +24,8 @@ "optional_permissions": [ "http://*/*", "https://*/*", - "webRequest" + "webRequest", + "clipboardRead" ], "browser_action": { "default_icon": { @@ -45,4 +46,4 @@ "page": "static/background.html", "persistent": true } -} +} \ No newline at end of file diff --git a/packages/taler-wallet-webextension/manifest-v3.json b/packages/taler-wallet-webextension/manifest-v3.json index 3ddaec513..78dcac623 100644 --- a/packages/taler-wallet-webextension/manifest-v3.json +++ b/packages/taler-wallet-webextension/manifest-v3.json @@ -27,7 +27,8 @@ } }, "optional_permissions": [ - "webRequest" + "webRequest", + "clipboardRead" ], "host_permissions": [ "http://*/*", @@ -51,4 +52,4 @@ "background": { "service_worker": "service_worker.js" } -} +} \ No newline at end of file diff --git a/packages/taler-wallet-webextension/src/background.ts b/packages/taler-wallet-webextension/src/background.ts index 0085ee4fd..0e2ea3f3a 100644 --- a/packages/taler-wallet-webextension/src/background.ts +++ b/packages/taler-wallet-webextension/src/background.ts @@ -42,14 +42,6 @@ if (isFirefox) { setupPlatform(chromeAPI); } -try { - platform.registerOnInstalled(() => { - platform.openWalletPage("/welcome"); - }); -} catch (e) { - console.error(e); -} - // setGlobalLogLevelFromString("trace") platform.notifyWhenAppIsReady(() => { wxMain(); diff --git a/packages/taler-wallet-webextension/src/hooks/useAutoOpenPermissions.ts b/packages/taler-wallet-webextension/src/hooks/useAutoOpenPermissions.ts new file mode 100644 index 000000000..727d653af --- /dev/null +++ b/packages/taler-wallet-webextension/src/hooks/useAutoOpenPermissions.ts @@ -0,0 +1,72 @@ +/* + 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 + */ + +import { useState, useEffect } from "preact/hooks"; +import * as wxApi from "../wxApi.js"; +import { platform } from "../platform/api.js"; +import { ToggleHandler } from "../mui/handlers.js"; +import { TalerError } from "@gnu-taler/taler-wallet-core"; + +export function useAutoOpenPermissions(): ToggleHandler { + const [enabled, setEnabled] = useState(false); + const [error, setError] = useState(); + const toggle = async (): Promise => { + return handleAutoOpenPerm(enabled, setEnabled).catch((e) => { + setError(TalerError.fromException(e)); + }); + }; + + useEffect(() => { + async function getValue(): Promise { + const res = await wxApi.containsHeaderListener(); + setEnabled(res.newValue); + } + getValue(); + }, []); + return { + value: enabled, + button: { + onClick: toggle, + error, + }, + }; +} + +async function handleAutoOpenPerm( + isEnabled: boolean, + onChange: (value: boolean) => void, +): Promise { + if (!isEnabled) { + // We set permissions here, since apparently FF wants this to be done + // as the result of an input event ... + let granted: boolean; + try { + granted = await platform.getPermissionsApi().requestHostPermissions(); + } catch (lastError) { + onChange(false); + throw lastError; + } + const res = await wxApi.toggleHeaderListener(granted); + onChange(res.newValue); + } else { + try { + await wxApi.toggleHeaderListener(false).then((r) => onChange(r.newValue)); + } catch (e) { + console.log(e); + } + } + return; +} diff --git a/packages/taler-wallet-webextension/src/hooks/useClipboardPermissions.ts b/packages/taler-wallet-webextension/src/hooks/useClipboardPermissions.ts new file mode 100644 index 000000000..c69b116b7 --- /dev/null +++ b/packages/taler-wallet-webextension/src/hooks/useClipboardPermissions.ts @@ -0,0 +1,73 @@ +/* + 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 + */ + +import { useState, useEffect } from "preact/hooks"; +import * as wxApi from "../wxApi.js"; +import { platform } from "../platform/api.js"; +import { ToggleHandler } from "../mui/handlers.js"; +import { TalerError } from "@gnu-taler/taler-wallet-core"; + +export function useClipboardPermissions(): ToggleHandler { + const [enabled, setEnabled] = useState(false); + const [error, setError] = useState(); + const toggle = async (): Promise => { + return handleClipboardPerm(enabled, setEnabled).catch((e) => { + setError(TalerError.fromException(e)); + }); + }; + + useEffect(() => { + async function getValue(): Promise { + const res = await wxApi.containsHeaderListener(); + setEnabled(res.newValue); + } + getValue(); + }, []); + + return { + value: enabled, + button: { + onClick: toggle, + error, + }, + }; +} + +async function handleClipboardPerm( + isEnabled: boolean, + onChange: (value: boolean) => void, +): Promise { + if (!isEnabled) { + // We set permissions here, since apparently FF wants this to be done + // as the result of an input event ... + let granted: boolean; + try { + granted = await platform.getPermissionsApi().requestClipboardPermissions(); + } catch (lastError) { + onChange(false); + throw lastError; + } + // const res = await wxApi.toggleHeaderListener(granted); + onChange(granted); + } else { + try { + await wxApi.toggleHeaderListener(false).then((r) => onChange(r.newValue)); + } catch (e) { + console.log(e); + } + } + return; +} diff --git a/packages/taler-wallet-webextension/src/hooks/useExtendedPermissions.ts b/packages/taler-wallet-webextension/src/hooks/useExtendedPermissions.ts deleted file mode 100644 index 06ae84593..000000000 --- a/packages/taler-wallet-webextension/src/hooks/useExtendedPermissions.ts +++ /dev/null @@ -1,72 +0,0 @@ -/* - 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 - */ - -import { useState, useEffect } from "preact/hooks"; -import * as wxApi from "../wxApi.js"; -import { platform } from "../platform/api.js"; -import { ToggleHandler } from "../mui/handlers.js"; -import { TalerError } from "@gnu-taler/taler-wallet-core"; - -export function useExtendedPermissions(): ToggleHandler { - const [enabled, setEnabled] = useState(false); - const [error, setError] = useState(); - const toggle = async (): Promise => { - return handleExtendedPerm(enabled, setEnabled).catch((e) => { - setError(TalerError.fromException(e)); - }); - }; - - useEffect(() => { - async function getExtendedPermValue(): Promise { - const res = await wxApi.containsHeaderListener(); - setEnabled(res.newValue); - } - getExtendedPermValue(); - }, []); - return { - value: enabled, - button: { - onClick: toggle, - error, - }, - }; -} - -async function handleExtendedPerm( - isEnabled: boolean, - onChange: (value: boolean) => void, -): Promise { - if (!isEnabled) { - // We set permissions here, since apparently FF wants this to be done - // as the result of an input event ... - let granted: boolean; - try { - granted = await platform.getPermissionsApi().requestHostPermissions(); - } catch (lastError) { - onChange(false); - throw lastError; - } - const res = await wxApi.toggleHeaderListener(granted); - onChange(res.newValue); - } else { - try { - await wxApi.toggleHeaderListener(false).then((r) => onChange(r.newValue)); - } catch (e) { - console.log(e); - } - } - return; -} diff --git a/packages/taler-wallet-webextension/src/hooks/useTalerActionURL.ts b/packages/taler-wallet-webextension/src/hooks/useTalerActionURL.ts index e1b08278b..75a92fd3c 100644 --- a/packages/taler-wallet-webextension/src/hooks/useTalerActionURL.ts +++ b/packages/taler-wallet-webextension/src/hooks/useTalerActionURL.ts @@ -31,7 +31,6 @@ export function useTalerActionURL(): [ ); const [dismissed, setDismissed] = useState(false); const { findTalerUriInActiveTab, findTalerUriInClipboard } = useIocContext(); - useEffect(() => { async function check(): Promise { const clipUri = await findTalerUriInClipboard(); @@ -52,7 +51,7 @@ export function useTalerActionURL(): [ } } check(); - }, [setTalerActionUrl]); + }, []); const url = dismissed ? undefined : talerActionUrl; return [url, setDismissed]; diff --git a/packages/taler-wallet-webextension/src/platform/api.ts b/packages/taler-wallet-webextension/src/platform/api.ts index 23fd80ed7..da257c25f 100644 --- a/packages/taler-wallet-webextension/src/platform/api.ts +++ b/packages/taler-wallet-webextension/src/platform/api.ts @@ -37,6 +37,10 @@ export interface CrossBrowserPermissionsApi { requestHostPermissions(): Promise; removeHostPermissions(): Promise; + containsClipboardPermissions(): Promise; + requestClipboardPermissions(): Promise; + removeClipboardPermissions(): Promise; + addPermissionsListener( callback: (p: Permissions, lastError?: string) => void, ): void; diff --git a/packages/taler-wallet-webextension/src/platform/chrome.ts b/packages/taler-wallet-webextension/src/platform/chrome.ts index 7311354c9..75900882f 100644 --- a/packages/taler-wallet-webextension/src/platform/chrome.ts +++ b/packages/taler-wallet-webextension/src/platform/chrome.ts @@ -77,6 +77,18 @@ const hostPermissions = { origins: ["http://*/*", "https://*/*"], }; +export function containsClipboardPermissions(): Promise { + return new Promise((res, rej) => { + chrome.permissions.contains({ permissions: ["clipboardRead"] }, (resp) => { + const le = chrome.runtime.lastError?.message; + if (le) { + rej(le); + } + res(resp); + }); + }); +} + export function containsHostPermissions(): Promise { return new Promise((res, rej) => { chrome.permissions.contains(hostPermissions, (resp) => { @@ -89,6 +101,18 @@ export function containsHostPermissions(): Promise { }); } +export async function requestClipboardPermissions(): Promise { + return new Promise((res, rej) => { + chrome.permissions.request({ permissions: ["clipboardRead"] }, (resp) => { + const le = chrome.runtime.lastError?.message; + if (le) { + rej(le); + } + res(resp); + }) + }); +} + export async function requestHostPermissions(): Promise { return new Promise((res, rej) => { chrome.permissions.request(hostPermissions, (resp) => { @@ -155,6 +179,18 @@ export async function removeHostPermissions(): Promise { }); } +export function removeClipboardPermissions(): Promise { + return new Promise((res, rej) => { + chrome.permissions.remove({ permissions: ["clipboardRead"] }, (resp) => { + const le = chrome.runtime.lastError?.message; + if (le) { + rej(le); + } + res(resp); + }); + }); +} + function addPermissionsListener( callback: (p: Permissions, lastError?: string) => void, ): void { @@ -170,6 +206,9 @@ function getPermissionsApi(): CrossBrowserPermissionsApi { containsHostPermissions, requestHostPermissions, removeHostPermissions, + requestClipboardPermissions, + removeClipboardPermissions, + containsClipboardPermissions, }; } @@ -382,11 +421,9 @@ function registerTalerHeaderListener( } async function tabListener(tabId: number, info: chrome.tabs.TabChangeInfo): Promise { - console.log("tab update", tabId, info) if (tabId < 0) return; if (info.status !== "complete") return; const uri = await findTalerUriInTab(tabId); - console.log("uri", uri) if (!uri) return; logger.info(`Found a Taler URI in the tab ${tabId}`) callback(tabId, uri) @@ -585,7 +622,6 @@ async function registerIconChangeOnTalerContent(): Promise { chrome.tabs.onUpdated.addListener( async (tabId, info: chrome.tabs.TabChangeInfo) => { if (tabId < 0) return; - logger.info("tab updated", tabId, info); if (info.status !== "complete") return; const uri = await findTalerUriInTab(tabId); if (uri) { @@ -690,9 +726,22 @@ async function findTalerUriInTab(tabId: number): Promise { } } +async function timeout(ms: number): Promise { + return new Promise(resolve => setTimeout(resolve, ms)); +} async function findTalerUriInClipboard(): Promise { - const textInClipboard = await window.navigator.clipboard.readText(); - return textInClipboard.startsWith("taler://") || textInClipboard.startsWith("taler+http://") ? textInClipboard : undefined + try { + //It looks like clipboard promise does not return, so we need a timeout + const textInClipboard = await Promise.any([ + timeout(100), + window.navigator.clipboard.readText() + ]) + if (!textInClipboard) return; + return textInClipboard.startsWith("taler://") || textInClipboard.startsWith("taler+http://") ? textInClipboard : undefined + } catch (e) { + logger.error("could not read clipboard", e) + return undefined + } } async function findTalerUriInActiveTab(): Promise { diff --git a/packages/taler-wallet-webextension/src/platform/dev.ts b/packages/taler-wallet-webextension/src/platform/dev.ts index bb7e181c4..8a410b062 100644 --- a/packages/taler-wallet-webextension/src/platform/dev.ts +++ b/packages/taler-wallet-webextension/src/platform/dev.ts @@ -32,6 +32,9 @@ const api: PlatformAPI = { containsHostPermissions: async () => true, removeHostPermissions: async () => false, requestHostPermissions: async () => false, + containsClipboardPermissions: async () => true, + removeClipboardPermissions: async () => false, + requestClipboardPermissions: async () => 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 a56e21f24..943168956 100644 --- a/packages/taler-wallet-webextension/src/platform/firefox.ts +++ b/packages/taler-wallet-webextension/src/platform/firefox.ts @@ -16,9 +16,12 @@ import { CrossBrowserPermissionsApi, Permissions, PlatformAPI } from "./api.js"; import chromePlatform, { - containsHostPermissions as chromeContains, - removeHostPermissions as chromeRemove, - requestHostPermissions as chromeRequest, + containsHostPermissions as chromeHostContains, + removeHostPermissions as chromeHostRemove, + requestHostPermissions as chromeHostRequest, + containsClipboardPermissions as chromeClipContains, + removeClipboardPermissions as chromeClipRemove, + requestClipboardPermissions as chromeClipRequest, } from "./chrome.js"; const api: PlatformAPI = { @@ -43,9 +46,12 @@ function addPermissionsListener(callback: (p: Permissions) => void): void { function getPermissionsApi(): CrossBrowserPermissionsApi { return { addPermissionsListener, - containsHostPermissions: chromeContains, - requestHostPermissions: chromeRequest, - removeHostPermissions: chromeRemove, + 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 9e85a9bed..d0707952f 100644 --- a/packages/taler-wallet-webextension/src/wallet/Settings.stories.tsx +++ b/packages/taler-wallet-webextension/src/wallet/Settings.stories.tsx @@ -46,21 +46,24 @@ const version = { export const AllOff = createExample(TestedComponent, { deviceName: "this-is-the-device-name", - permissionToggle: { value: false, button: {} }, + autoOpenToggle: { value: false, button: {} }, + clipboardToggle: { value: false, button: {} }, setDeviceName: () => Promise.resolve(), ...version, }); export const OneChecked = createExample(TestedComponent, { deviceName: "this-is-the-device-name", - permissionToggle: { value: false, button: {} }, + autoOpenToggle: { value: false, button: {} }, + clipboardToggle: { value: false, button: {} }, setDeviceName: () => Promise.resolve(), ...version, }); export const WithOneExchange = createExample(TestedComponent, { deviceName: "this-is-the-device-name", - permissionToggle: { value: false, button: {} }, + autoOpenToggle: { value: false, button: {} }, + clipboardToggle: { value: false, button: {} }, setDeviceName: () => Promise.resolve(), knownExchanges: [ { @@ -80,7 +83,8 @@ export const WithOneExchange = createExample(TestedComponent, { export const WithExchangeInDifferentState = createExample(TestedComponent, { deviceName: "this-is-the-device-name", - permissionToggle: { value: false, button: {} }, + autoOpenToggle: { value: false, button: {} }, + clipboardToggle: { 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 4a520c3bb..5219bbb38 100644 --- a/packages/taler-wallet-webextension/src/wallet/Settings.tsx +++ b/packages/taler-wallet-webextension/src/wallet/Settings.tsx @@ -33,17 +33,19 @@ import { useDevContext } from "../context/devContext.js"; import { useTranslationContext } from "../context/translation.js"; import { useAsyncAsHook } from "../hooks/useAsyncAsHook.js"; import { useBackupDeviceName } from "../hooks/useBackupDeviceName.js"; -import { useExtendedPermissions } from "../hooks/useExtendedPermissions.js"; +import { useAutoOpenPermissions } from "../hooks/useAutoOpenPermissions.js"; import { ToggleHandler } from "../mui/handlers.js"; import { Pages } from "../NavigationBar.js"; import { buildTermsOfServiceStatus } from "../utils/index.js"; import * as wxApi from "../wxApi.js"; import { platform } from "../platform/api.js"; +import { useClipboardPermissions } from "../hooks/useClipboardPermissions.js"; const GIT_HASH = typeof __GIT_HASH__ !== "undefined" ? __GIT_HASH__ : undefined; export function SettingsPage(): VNode { - const permissionToggle = useExtendedPermissions(); + const autoOpenToggle = useAutoOpenPermissions(); + const clipboardToggle = useClipboardPermissions(); const { devMode, toggleDevMode } = useDevContext(); const { name, update } = useBackupDeviceName(); const webex = platform.getWalletWebExVersion(); @@ -63,7 +65,8 @@ export function SettingsPage(): VNode { knownExchanges={exchanges} deviceName={name} setDeviceName={update} - permissionToggle={permissionToggle} + autoOpenToggle={autoOpenToggle} + clipboardToggle={clipboardToggle} developerMode={devMode} toggleDeveloperMode={toggleDevMode} webexVersion={{ @@ -78,7 +81,8 @@ export function SettingsPage(): VNode { export interface ViewProps { deviceName: string; setDeviceName: (s: string) => Promise; - permissionToggle: ToggleHandler; + autoOpenToggle: ToggleHandler; + clipboardToggle: ToggleHandler; developerMode: boolean; toggleDeveloperMode: () => Promise; knownExchanges: Array; @@ -91,7 +95,8 @@ export interface ViewProps { export function SettingsView({ knownExchanges, - permissionToggle, + autoOpenToggle, + clipboardToggle, developerMode, coreVersion, webexVersion, @@ -102,10 +107,16 @@ export function SettingsView({ return (
- {permissionToggle.button.error && ( + {autoOpenToggle.button.error && ( Could not toggle auto-open} - error={permissionToggle.button.error.errorDetail} + error={autoOpenToggle.button.error.errorDetail} + /> + )} + {clipboardToggle.button.error && ( + Could not toggle clipboard} + error={clipboardToggle.button.error.errorDetail} /> )} @@ -117,15 +128,31 @@ export function SettingsView({ Automatically open wallet based on page content } - name="perm" + name="autoOpen" + description={ + + Enabling this option below will make using the wallet faster, but + requires more permissions from your browser. + + } + enabled={autoOpenToggle.value!} + onToggle={autoOpenToggle.button.onClick!} + /> + + Automatically check clipboard for Taler URI + + } + name="clipboard" description={ Enabling this option below will make using the wallet faster, but requires more permissions from your browser. } - enabled={permissionToggle.value!} - onToggle={permissionToggle.button.onClick!} + enabled={clipboardToggle.value!} + onToggle={clipboardToggle.button.onClick!} /> diff --git a/packages/taler-wallet-webextension/src/wallet/Welcome.tsx b/packages/taler-wallet-webextension/src/wallet/Welcome.tsx index 0f327640e..659a6c2cf 100644 --- a/packages/taler-wallet-webextension/src/wallet/Welcome.tsx +++ b/packages/taler-wallet-webextension/src/wallet/Welcome.tsx @@ -26,12 +26,12 @@ import { Checkbox } from "../components/Checkbox.js"; import { SubTitle, Title } from "../components/styled/index.js"; import { useTranslationContext } from "../context/translation.js"; import { useDiagnostics } from "../hooks/useDiagnostics.js"; -import { useExtendedPermissions } from "../hooks/useExtendedPermissions.js"; +import { useAutoOpenPermissions } from "../hooks/useAutoOpenPermissions.js"; import { ToggleHandler } from "../mui/handlers.js"; import { platform } from "../platform/api.js"; export function WelcomePage(): VNode { - const permissionToggle = useExtendedPermissions(); + const permissionToggle = useAutoOpenPermissions(); const [diagnostics, timedOut] = useDiagnostics(); return ( { platform.registerAllIncomingConnections(); try { - platform.registerTalerHeaderListener(parseTalerUriAndRedirect); + platform.registerOnInstalled(() => { + platform.openWalletPage("/welcome"); + + // + try { + platform.registerTalerHeaderListener(parseTalerUriAndRedirect); + } catch (e) { + logger.error("could not register header listener", e); + } + }); } catch (e) { - logger.error("could not register header listener", e); + console.error(e); } + // On platforms that support it, also listen to external // modification of permissions. platform.getPermissionsApi().addPermissionsListener((perm, lastError) => { -- cgit v1.2.3