From c8230997ccf0b62f675f435aa5f74852b8265deb Mon Sep 17 00:00:00 2001 From: darian Date: Tue, 17 Dec 2024 17:29:48 +0200 Subject: [PATCH] unexpected reuseOrCreateTab error should throw --- src/background/services/keyAutoAdd.ts | 125 ++++++++++++------------ src/background/services/openPayments.ts | 74 +++++++------- src/background/utils.ts | 4 +- 3 files changed, 95 insertions(+), 108 deletions(-) diff --git a/src/background/services/keyAutoAdd.ts b/src/background/services/keyAutoAdd.ts index 520f9fb4..19009d1e 100644 --- a/src/background/services/keyAutoAdd.ts +++ b/src/background/services/keyAutoAdd.ts @@ -92,76 +92,71 @@ export class KeyAutoAddService { existingTabId?: TabId, ): Promise { const { resolve, reject, promise } = withResolvers(); - try { - const tab = await reuseOrCreateTab(this.browser, url, existingTabId); - this.tab = tab; + const tab = await reuseOrCreateTab(this.browser, url, existingTabId); + this.tab = tab; + + const onTabCloseListener: OnTabRemovedCallback = (tabId) => { + if (tabId !== tab.id) return; + this.browser.tabs.onRemoved.removeListener(onTabCloseListener); + reject(new ErrorWithKey('connectWallet_error_tabClosed')); + }; + this.browser.tabs.onRemoved.addListener(onTabCloseListener); + + const ports = new Set(); + const onConnectListener: OnConnectCallback = (port) => { + if (port.name !== CONNECTION_NAME) return; + if (port.error) { + reject(new Error(port.error.message)); + return; + } + ports.add(port); + + port.postMessage({ action: 'BEGIN', payload }); + + port.onMessage.addListener(onMessageListener); + + port.onDisconnect.addListener(() => { + ports.delete(port); + // wait for connect again so we can send message again if not connected, + // and not errored already (e.g. page refreshed) + }); + }; - const onTabCloseListener: OnTabRemovedCallback = (tabId) => { - if (tabId !== tab.id) return; + const onMessageListener: OnPortMessageListener = ( + message: KeyAutoAddToBackgroundMessage, + port, + ) => { + if (message.action === 'SUCCESS') { + this.browser.runtime.onConnect.removeListener(onConnectListener); this.browser.tabs.onRemoved.removeListener(onTabCloseListener); - reject(new ErrorWithKey('connectWallet_error_tabClosed')); - }; - this.browser.tabs.onRemoved.addListener(onTabCloseListener); - - const ports = new Set(); - const onConnectListener: OnConnectCallback = (port) => { - if (port.name !== CONNECTION_NAME) return; - if (port.error) { - reject(new Error(port.error.message)); - return; - } - ports.add(port); - - port.postMessage({ action: 'BEGIN', payload }); - - port.onMessage.addListener(onMessageListener); - - port.onDisconnect.addListener(() => { - ports.delete(port); - // wait for connect again so we can send message again if not connected, - // and not errored already (e.g. page refreshed) - }); - }; - - const onMessageListener: OnPortMessageListener = ( - message: KeyAutoAddToBackgroundMessage, - port, - ) => { - if (message.action === 'SUCCESS') { - this.browser.runtime.onConnect.removeListener(onConnectListener); - this.browser.tabs.onRemoved.removeListener(onTabCloseListener); - resolve(message.payload); - } else if (message.action === 'ERROR') { - this.browser.runtime.onConnect.removeListener(onConnectListener); - this.browser.tabs.onRemoved.removeListener(onTabCloseListener); - const { stepName, details: err } = message.payload; - reject( - new ErrorWithKey( - 'connectWalletKeyService_error_failed', - [ - stepName, - isErrorWithKey(err.error) ? this.t(err.error) : err.message, - ], - isErrorWithKey(err.error) ? err.error : undefined, - ), - ); - } else if (message.action === 'PROGRESS') { - // can also save progress to show in popup - for (const p of ports) { - if (p !== port) p.postMessage(message); - } - } else { - reject(new Error(`Unexpected message: ${JSON.stringify(message)}`)); + resolve(message.payload); + } else if (message.action === 'ERROR') { + this.browser.runtime.onConnect.removeListener(onConnectListener); + this.browser.tabs.onRemoved.removeListener(onTabCloseListener); + const { stepName, details: err } = message.payload; + reject( + new ErrorWithKey( + 'connectWalletKeyService_error_failed', + [ + stepName, + isErrorWithKey(err.error) ? this.t(err.error) : err.message, + ], + isErrorWithKey(err.error) ? err.error : undefined, + ), + ); + } else if (message.action === 'PROGRESS') { + // can also save progress to show in popup + for (const p of ports) { + if (p !== port) p.postMessage(message); } - }; + } else { + reject(new Error(`Unexpected message: ${JSON.stringify(message)}`)); + } + }; - this.browser.runtime.onConnect.addListener(onConnectListener); + this.browser.runtime.onConnect.addListener(onConnectListener); - return promise; - } catch (error) { - reject(error); - return promise; - } + return promise; } private async validate(walletAddressUrl: string, keyId: string) { diff --git a/src/background/services/openPayments.ts b/src/background/services/openPayments.ts index 1bb4edcc..e9af76c9 100644 --- a/src/background/services/openPayments.ts +++ b/src/background/services/openPayments.ts @@ -780,54 +780,46 @@ export class OpenPaymentsService { existingTabId?: TabId, ): Promise { const { resolve, reject, promise } = withResolvers(); - try { - const tab = await reuseOrCreateTab(this.browser, url, existingTabId); + const tab = await reuseOrCreateTab(this.browser, url, existingTabId); - const tabCloseListener: TabRemovedCallback = (tabId) => { - if (tabId !== tab.id) return; + const tabCloseListener: TabRemovedCallback = (tabId) => { + if (tabId !== tab.id) return; - this.browser.tabs.onRemoved.removeListener(tabCloseListener); - reject(new ErrorWithKey('connectWallet_error_tabClosed')); - }; + this.browser.tabs.onRemoved.removeListener(tabCloseListener); + reject(new ErrorWithKey('connectWallet_error_tabClosed')); + }; - const getInteractionInfo: TabUpdateCallback = async ( - tabId, - changeInfo, - ) => { - if (tabId !== tab.id) return; - try { - const tabUrl = new URL(changeInfo.url || ''); - const interactRef = tabUrl.searchParams.get('interact_ref'); - const hash = tabUrl.searchParams.get('hash'); - const result = tabUrl.searchParams.get('result'); - - if ( - (interactRef && hash) || - result === 'grant_rejected' || - result === 'grant_invalid' - ) { - this.browser.tabs.onUpdated.removeListener(getInteractionInfo); - this.browser.tabs.onRemoved.removeListener(tabCloseListener); - } + const getInteractionInfo: TabUpdateCallback = async (tabId, changeInfo) => { + if (tabId !== tab.id) return; + try { + const tabUrl = new URL(changeInfo.url || ''); + const interactRef = tabUrl.searchParams.get('interact_ref'); + const hash = tabUrl.searchParams.get('hash'); + const result = tabUrl.searchParams.get('result'); - if (interactRef && hash) { - resolve({ interactRef, hash, tabId }); - } else if (result === 'grant_rejected') { - reject(new ErrorWithKey('connectWallet_error_grantRejected')); - } - } catch { - /* do nothing */ + if ( + (interactRef && hash) || + result === 'grant_rejected' || + result === 'grant_invalid' + ) { + this.browser.tabs.onUpdated.removeListener(getInteractionInfo); + this.browser.tabs.onRemoved.removeListener(tabCloseListener); } - }; - this.browser.tabs.onRemoved.addListener(tabCloseListener); - this.browser.tabs.onUpdated.addListener(getInteractionInfo); + if (interactRef && hash) { + resolve({ interactRef, hash, tabId }); + } else if (result === 'grant_rejected') { + reject(new ErrorWithKey('connectWallet_error_grantRejected')); + } + } catch { + /* do nothing */ + } + }; + + this.browser.tabs.onRemoved.addListener(tabCloseListener); + this.browser.tabs.onUpdated.addListener(getInteractionInfo); - return promise; - } catch (error) { - reject(error); - return promise; - } + return promise; } async disconnectWallet() { diff --git a/src/background/utils.ts b/src/background/utils.ts index 729ed85f..4ba560f3 100644 --- a/src/background/utils.ts +++ b/src/background/utils.ts @@ -99,13 +99,13 @@ export const reuseOrCreateTab = async ( try { const tab = await browser.tabs.get(tabId ?? -1); if (!tab.id) { - throw new Error('Unexpected: tab does not have id'); + throw new Error('Could not retrieve tab.'); } return (await browser.tabs.update(tab.id, { url })) as Tab; } catch { const tab = await browser.tabs.create({ url }); if (!tab.id) { - throw new Error('Unexpected: tab does not have id'); + throw new Error('Newly created tab does not have the id property set.'); } return tab as Tab; }