From 5bc674383b4f2daba599ba0f383105676f2f779c Mon Sep 17 00:00:00 2001 From: Killari Date: Fri, 3 Mar 2023 11:20:34 +0200 Subject: [PATCH 1/6] Manifest v3 --- extension/app/html/popupV3.html | 21 ++++++ extension/app/manifestV3.json | 40 ++++++++++ extension/app/ts/backgroundServiceWorker.ts | 72 ++++++++++++++++++ extension/app/ts/listenContentScript.ts | 42 +++++++++++ extension/build/bundler.ts | 66 ++++++++++++++++ extension/build/package.json | 3 +- extension/package-lock.json | 83 +++++++++++++++++---- extension/package.json | 7 +- 8 files changed, 316 insertions(+), 18 deletions(-) create mode 100644 extension/app/html/popupV3.html create mode 100644 extension/app/manifestV3.json create mode 100644 extension/app/ts/backgroundServiceWorker.ts create mode 100644 extension/app/ts/listenContentScript.ts create mode 100644 extension/build/bundler.ts diff --git a/extension/app/html/popupV3.html b/extension/app/html/popupV3.html new file mode 100644 index 00000000..cd5f9f96 --- /dev/null +++ b/extension/app/html/popupV3.html @@ -0,0 +1,21 @@ + + + + The Interceptor + + + + + + + + + + +
Loading...
+ + + + + + diff --git a/extension/app/manifestV3.json b/extension/app/manifestV3.json new file mode 100644 index 00000000..728a6cce --- /dev/null +++ b/extension/app/manifestV3.json @@ -0,0 +1,40 @@ +{ + "name": "Interceptor", + "description": "Interceptor", + "version": "0.0.0", + "manifest_version": 3, + "action": { + "default_icon": { + "128": "img/head-not-active.png" + }, + "default_title": "The Interceptor" + }, + "background": { + "service_worker": "./js/backgroundServiceWorker.js", + "type": "module" + }, + "icons": { + "128": "img/head.png", + "400": "img/LOGOA_400x400.png" + }, + "permissions": [ + "activeTab", + "storage", + "webNavigation", + "scripting" + ], + "web_accessible_resources": [ + { + "resources": ["vendor/*", "js/*", "inpage/*"], + "matches": [""] // not sure if this is right? + } + ], + "content_security_policy": { + "extension_pages": "script-src 'self'; object-src 'self'" + }, + "host_permissions": [ + "file://*/*", + "http://*/*", + "https://*/*" + ] +} diff --git a/extension/app/ts/backgroundServiceWorker.ts b/extension/app/ts/backgroundServiceWorker.ts new file mode 100644 index 00000000..e213cf2c --- /dev/null +++ b/extension/app/ts/backgroundServiceWorker.ts @@ -0,0 +1,72 @@ +import './background/background.js' + +chrome.runtime.onStartup.addListener(() => { + console.log('onStartup()') +}) + +chrome.runtime.onMessage.addListener((message: unknown) => { + console.log('OnMessage') + console.log(message) + return false +}) + +chrome.runtime.onMessageExternal.addListener(({ type, name }) => { + console.log('onMessageExternal') + console.log(type) + console.log(name) + return false +}) + +self.addEventListener('install', () => { + console.log('install') +}) + +self.addEventListener('message', (mess) => { + console.log('window.message') + console.log(mess) +}) +/* +async function onContentScriptConnected(port: chrome.runtime.Port) { + console.log('content script connected') + port.onMessage.addListener(async (payload) => { + if(!( + 'data' in payload + && typeof payload.data === 'object' + && payload.data !== null + && 'interceptorRequest' in payload.data + )) return + console.log(payload) + const request = InterceptedRequest.parse(payload.data) + console.log(request.options.method) + }) +} +chrome.runtime.onConnect.addListener(port => onContentScriptConnected(port).catch(console.error)) +*/ + +const injectContentScript = async () => { + try { + await chrome.scripting.registerContentScripts([{ + id: 'inpage2', + matches: ['file://*/*', 'http://*/*', 'https://*/*'], + js: ['/vendor/webextension-polyfill/browser-polyfill.js', './js/listenContentScript.js'], + runAt: 'document_start', + } ]) + await chrome.scripting.registerContentScripts([{ + id: 'inpage', + matches: ['file://*/*', 'http://*/*', 'https://*/*'], + js: ['/inpage/js/inpage.js'], + runAt: 'document_start', + world: 'MAIN', + } ]) + } catch (err) { + console.warn(err) + } +} + +injectContentScript() + +chrome.action.onClicked.addListener((_tab) => { + chrome.action.setPopup({ + popup: 'html/popup.html' + }) +}) diff --git a/extension/app/ts/listenContentScript.ts b/extension/app/ts/listenContentScript.ts new file mode 100644 index 00000000..7aa99d6d --- /dev/null +++ b/extension/app/ts/listenContentScript.ts @@ -0,0 +1,42 @@ +function listenInContentScript() { + /** + * this script executed within the context of the active tab when the user clicks the extension bar button + * this script serves as a _very thin_ proxy between the page scripts (dapp) and the extension, simply forwarding messages between the two + */ + // the content script is a very thin proxy between the background script and the page script + const extensionPort = browser.runtime.connect() + let connected = true + + // forward all message events to the background script, which will then filter and process them + window.addEventListener('message', messageEvent => { + try { + console.log(messageEvent) + // we only want the data element, if it exists, and postMessage will fail if it can't clone the object fully (and it cannot clone a MessageEvent) + if (!('data' in messageEvent)) return + if (connected) extensionPort.postMessage({ data: messageEvent.data }) + } catch (error) { + // CONSIDER: should we catch data clone error and then do `extensionPort.postMessage({data:JSON.parse(JSON.stringify(messageEvent.data))})`? + if (error instanceof Error) { + if (error.message?.includes('Extension context invalidated.')) { + // this error happens when the extension is refreshed and the page cannot reach The Interceptor anymore + return + } + } + throw error + } + }) + + // forward all messages we get from the background script to the window so the page script can filter and process them + extensionPort.onMessage.addListener(response => { + try { + if (connected) window.postMessage(response, '*') + } catch (error) { + console.error(error) + } + }) + + extensionPort.onDisconnect.addListener(() => { + connected = false + }) +} +listenInContentScript() diff --git a/extension/build/bundler.ts b/extension/build/bundler.ts new file mode 100644 index 00000000..99664dde --- /dev/null +++ b/extension/build/bundler.ts @@ -0,0 +1,66 @@ +import * as path from 'path' +import * as url from 'url' +import { promises as fs } from 'fs' + +const directoryOfThisFile = path.dirname(url.fileURLToPath(import.meta.url)) + +const dependencyPaths = [ + { packageName: 'ethers', subfolderToVendor: 'dist', entrypointFile: 'ethers.esm.js' }, + { packageName: 'webextension-polyfill', subfolderToVendor: 'dist', entrypointFile: 'browser-polyfill.js' }, + { packageName: 'preact', subfolderToVendor: 'dist', entrypointFile: 'preact.module.js' }, + { packageName: 'preact/jsx-runtime', subfolderToVendor: 'dist', entrypointFile: 'jsxRuntime.module.js' }, + { packageName: 'preact/hooks', subfolderToVendor: 'dist', entrypointFile: 'hooks.module.js' }, + { packageName: 'funtypes', subfolderToVendor: 'lib', entrypointFile: 'index.mjs' }, + { packageName: 'node-fetch', subfolderToVendor: 'lib', entrypointFile: 'index.mjs' }, + { packageName: '@zoltu/ethereum-abi-encoder', subfolderToVendor: 'output-esm', entrypointFile: 'index.js' }, + { packageName: '@zoltu/ethereum-crypto', subfolderToVendor: 'output-esm', entrypointFile: 'index.js' }, + { packageName: '@zoltu/rlp-encoder', subfolderToVendor: 'output-esm', entrypointFile: 'index.js' }, + { packageName: '@darkflorist/address-metadata', subfolderToVendor: 'lib', entrypointFile: 'index.js' }, +] + +export function replaceImport(filePath: string, text: string) { + let replaced = text + dependencyPaths.forEach((dependency) => { + const newLocation = path.join(directoryOfThisFile, '..', 'app', 'vendor', dependency.packageName, dependency.entrypointFile) + const fileFolder = path.dirname(filePath) + replaced = replaced.replace(`import '${ dependency.packageName }'`, `import '${ path.relative(fileFolder, newLocation).replace(/\\/g, '/') }'`) + replaced = replaced.replace(` from '${ dependency.packageName }'`, ` from '${ path.relative(fileFolder, newLocation).replace(/\\/g, '/') }'`) + replaced = replaced.replace(` from "${ dependency.packageName }"`, ` from '${ path.relative(fileFolder, newLocation).replace(/\\/g, '/') }'`) + replaced = replaced.replace(`from'${ dependency.packageName }'`, ` from '${ path.relative(fileFolder, newLocation).replace(/\\/g, '/') }'`) + replaced = replaced.replace(`from"${ dependency.packageName }"`, ` from '${ path.relative(fileFolder, newLocation).replace(/\\/g, '/') }'`) + replaced = replaced.replace(`require("${ dependency.packageName }")`, `require('${ path.relative(fileFolder, newLocation).replace(/\\/g, '/') }')`) + }) + return replaced +} + +async function* getFiles(topDir: string): AsyncGenerator { + const dirContents = await fs.readdir(topDir, { withFileTypes: true }) + for (const dir of dirContents) { + const res = path.resolve(topDir, dir.name); + if (dir.isDirectory()) { + yield* getFiles(res) + } else { + yield res + } + } +} + +async function replaceImportsInJSFiles() { + const folders = [ + path.join(directoryOfThisFile, '..', 'app', 'js'), + path.join(directoryOfThisFile, '..', 'app', 'vendor') + ] + for (const folder of folders) { + for await (const filePath of getFiles(folder)) { + if (path.extname(filePath) !== '.js' && path.extname(filePath) !== '.mjs') continue + const replaced = replaceImport(filePath, await fs.readFile(filePath, 'utf8')) + await fs.writeFile(filePath, replaced) + } + } +} + +replaceImportsInJSFiles().catch(error => { + console.error(error) + debugger + process.exit(1) +}) diff --git a/extension/build/package.json b/extension/build/package.json index 157fd71a..69638931 100644 --- a/extension/build/package.json +++ b/extension/build/package.json @@ -7,6 +7,7 @@ "typescript": "4.7.3" }, "scripts": { - "vendor": "npx ts-node vendor.ts" + "vendor": "npx ts-node vendor.ts", + "bundle": "npx ts-node bundler.ts" } } diff --git a/extension/package-lock.json b/extension/package-lock.json index 85bd3579..ad30a059 100644 --- a/extension/package-lock.json +++ b/extension/package-lock.json @@ -7,6 +7,7 @@ "name": "interceptor-extension", "dependencies": { "@darkflorist/address-metadata": "0.2.0", + "@types/chrome": "^0.0.218", "@types/node-fetch": "2.6.1", "@zoltu/ethereum-abi-encoder": "5.0.4", "@zoltu/ethereum-crypto": "2.2.2", @@ -15,10 +16,10 @@ "ethers": "5.5.1", "funtypes": "5.0.3", "preact": "10.8.1", - "webextension-polyfill": "0.9.0" + "webextension-polyfill": "0.10.0" }, "devDependencies": { - "@types/firefox-webext-browser": "94.0.1", + "@types/firefox-webext-browser": "109.0.0", "node-fetch": "^2.6.7", "typescript": "4.9.3" } @@ -697,12 +698,39 @@ "@ethersproject/strings": "^5.5.0" } }, + "node_modules/@types/chrome": { + "version": "0.0.218", + "resolved": "https://registry.npmjs.org/@types/chrome/-/chrome-0.0.218.tgz", + "integrity": "sha512-GC/c9B3Eo3h3l+fV5G6A9cRMEZOYo46E21mjHHfkXz+/A5uypXstMVAMk04IeGY2DJ7PxVxbn26oFBPZOa4Dkw==", + "dependencies": { + "@types/filesystem": "*", + "@types/har-format": "*" + } + }, + "node_modules/@types/filesystem": { + "version": "0.0.32", + "resolved": "https://registry.npmjs.org/@types/filesystem/-/filesystem-0.0.32.tgz", + "integrity": "sha512-Yuf4jR5YYMR2DVgwuCiP11s0xuVRyPKmz8vo6HBY3CGdeMj8af93CFZX+T82+VD1+UqHOxTq31lO7MI7lepBtQ==", + "dependencies": { + "@types/filewriter": "*" + } + }, + "node_modules/@types/filewriter": { + "version": "0.0.29", + "resolved": "https://registry.npmjs.org/@types/filewriter/-/filewriter-0.0.29.tgz", + "integrity": "sha512-BsPXH/irW0ht0Ji6iw/jJaK8Lj3FJemon2gvEqHKpCdDCeemHa+rI3WBGq5z7cDMZgoLjY40oninGxqk+8NzNQ==" + }, "node_modules/@types/firefox-webext-browser": { - "version": "94.0.1", - "resolved": "https://registry.npmjs.org/@types/firefox-webext-browser/-/firefox-webext-browser-94.0.1.tgz", - "integrity": "sha512-I6iHRQJSTZ+gYt2IxdH2RRAMvcUyK8v5Ig7fHQR0IwUNYP7hz9+cziBVIKxLCO6XI7fiyRsNOWObfl3/4Js2Lg==", + "version": "109.0.0", + "resolved": "https://registry.npmjs.org/@types/firefox-webext-browser/-/firefox-webext-browser-109.0.0.tgz", + "integrity": "sha512-tkEjBP/zZxaS5bv8MH/0kUs3WeUm8KU3Ew1B9BtQQdq5PwtG23SXvAbjxjMSQpoIzbxyWG4Yu4mi1uB2S8W7ng==", "dev": true }, + "node_modules/@types/har-format": { + "version": "1.2.10", + "resolved": "https://registry.npmjs.org/@types/har-format/-/har-format-1.2.10.tgz", + "integrity": "sha512-o0J30wqycjF5miWDKYKKzzOU1ZTLuA42HZ4HE7/zqTOc/jTLdQ5NhYWvsRQo45Nfi1KHoRdNhteSI4BAxTF1Pg==" + }, "node_modules/@types/node": { "version": "18.11.18", "resolved": "https://registry.npmjs.org/@types/node/-/node-18.11.18.tgz", @@ -972,9 +1000,9 @@ } }, "node_modules/webextension-polyfill": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/webextension-polyfill/-/webextension-polyfill-0.9.0.tgz", - "integrity": "sha512-LTtHb0yR49xa9irkstDxba4GATDAcDw3ncnFH9RImoFwDlW47U95ME5sn5IiQX2ghfaECaf6xyXM8yvClIBkkw==" + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/webextension-polyfill/-/webextension-polyfill-0.10.0.tgz", + "integrity": "sha512-c5s35LgVa5tFaHhrZDnr3FpQpjj1BB+RXhLTYUxGqBVN460HkbM8TBtEqdXWbpTKfzwCcjAZVF7zXCYSKtcp9g==" }, "node_modules/webidl-conversions": { "version": "3.0.1", @@ -1388,12 +1416,39 @@ "@ethersproject/strings": "^5.5.0" } }, + "@types/chrome": { + "version": "0.0.218", + "resolved": "https://registry.npmjs.org/@types/chrome/-/chrome-0.0.218.tgz", + "integrity": "sha512-GC/c9B3Eo3h3l+fV5G6A9cRMEZOYo46E21mjHHfkXz+/A5uypXstMVAMk04IeGY2DJ7PxVxbn26oFBPZOa4Dkw==", + "requires": { + "@types/filesystem": "*", + "@types/har-format": "*" + } + }, + "@types/filesystem": { + "version": "0.0.32", + "resolved": "https://registry.npmjs.org/@types/filesystem/-/filesystem-0.0.32.tgz", + "integrity": "sha512-Yuf4jR5YYMR2DVgwuCiP11s0xuVRyPKmz8vo6HBY3CGdeMj8af93CFZX+T82+VD1+UqHOxTq31lO7MI7lepBtQ==", + "requires": { + "@types/filewriter": "*" + } + }, + "@types/filewriter": { + "version": "0.0.29", + "resolved": "https://registry.npmjs.org/@types/filewriter/-/filewriter-0.0.29.tgz", + "integrity": "sha512-BsPXH/irW0ht0Ji6iw/jJaK8Lj3FJemon2gvEqHKpCdDCeemHa+rI3WBGq5z7cDMZgoLjY40oninGxqk+8NzNQ==" + }, "@types/firefox-webext-browser": { - "version": "94.0.1", - "resolved": "https://registry.npmjs.org/@types/firefox-webext-browser/-/firefox-webext-browser-94.0.1.tgz", - "integrity": "sha512-I6iHRQJSTZ+gYt2IxdH2RRAMvcUyK8v5Ig7fHQR0IwUNYP7hz9+cziBVIKxLCO6XI7fiyRsNOWObfl3/4Js2Lg==", + "version": "109.0.0", + "resolved": "https://registry.npmjs.org/@types/firefox-webext-browser/-/firefox-webext-browser-109.0.0.tgz", + "integrity": "sha512-tkEjBP/zZxaS5bv8MH/0kUs3WeUm8KU3Ew1B9BtQQdq5PwtG23SXvAbjxjMSQpoIzbxyWG4Yu4mi1uB2S8W7ng==", "dev": true }, + "@types/har-format": { + "version": "1.2.10", + "resolved": "https://registry.npmjs.org/@types/har-format/-/har-format-1.2.10.tgz", + "integrity": "sha512-o0J30wqycjF5miWDKYKKzzOU1ZTLuA42HZ4HE7/zqTOc/jTLdQ5NhYWvsRQo45Nfi1KHoRdNhteSI4BAxTF1Pg==" + }, "@types/node": { "version": "18.11.18", "resolved": "https://registry.npmjs.org/@types/node/-/node-18.11.18.tgz", @@ -1616,9 +1671,9 @@ "dev": true }, "webextension-polyfill": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/webextension-polyfill/-/webextension-polyfill-0.9.0.tgz", - "integrity": "sha512-LTtHb0yR49xa9irkstDxba4GATDAcDw3ncnFH9RImoFwDlW47U95ME5sn5IiQX2ghfaECaf6xyXM8yvClIBkkw==" + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/webextension-polyfill/-/webextension-polyfill-0.10.0.tgz", + "integrity": "sha512-c5s35LgVa5tFaHhrZDnr3FpQpjj1BB+RXhLTYUxGqBVN460HkbM8TBtEqdXWbpTKfzwCcjAZVF7zXCYSKtcp9g==" }, "webidl-conversions": { "version": "3.0.1", diff --git a/extension/package.json b/extension/package.json index 70f1971b..13c59366 100644 --- a/extension/package.json +++ b/extension/package.json @@ -10,19 +10,20 @@ "vendor": "cd build && npm ci --ignore-scripts && npm run vendor" }, "dependencies": { + "@darkflorist/address-metadata": "0.2.0", "@types/node-fetch": "2.6.1", "@zoltu/ethereum-abi-encoder": "5.0.4", "@zoltu/ethereum-crypto": "2.2.2", "@zoltu/ethereum-types": "9.0.4", "@zoltu/rlp-encoder": "2.0.6", - "@darkflorist/address-metadata": "0.2.0", "ethers": "5.5.1", "funtypes": "5.0.3", "preact": "10.8.1", - "webextension-polyfill": "0.9.0" + "webextension-polyfill": "0.10.0" }, "devDependencies": { - "@types/firefox-webext-browser": "94.0.1", + "@types/chrome": "^0.0.218", + "@types/firefox-webext-browser": "109.0.0", "node-fetch": "^2.6.7", "typescript": "4.9.3" } From 67cee845ea8264fbe7510172c1a1a89a5dce0629 Mon Sep 17 00:00:00 2001 From: Killari Date: Mon, 6 Mar 2023 09:00:39 +0200 Subject: [PATCH 2/6] seems to work now --- extension/app/html3/addressBookV3.html | 19 +++ extension/app/html3/changeChainV3.html | 19 +++ extension/app/html3/confirmTransactionV3.html | 20 +++ extension/app/html3/favicon.ico | Bin 0 -> 8209 bytes extension/app/html3/interceptorAccessV3.html | 19 +++ extension/app/html3/personalSignV3.html | 19 +++ extension/app/{html => html3}/popupV3.html | 1 - .../inpage/output/injected_document_start.js | 4 +- extension/app/inpage/ts/document_start.ts | 4 +- extension/app/ts/AddressBook.tsx | 8 +- .../app/ts/background/accessManagement.ts | 64 ++++---- extension/app/ts/background/background.ts | 154 +++++++++--------- .../app/ts/background/backgroundUtils.ts | 10 +- extension/app/ts/background/iconHandler.ts | 28 ++-- .../app/ts/background/popupMessageHandlers.ts | 108 ++++++------ .../ts/background/providerMessageHandlers.ts | 22 +-- .../ts/background/simulationModeHanders.ts | 12 +- .../app/ts/background/windows/changeChain.ts | 2 +- .../background/windows/confirmTransaction.ts | 6 +- .../background/windows/interceptorAccess.ts | 68 ++++---- .../app/ts/background/windows/personalSign.ts | 24 +-- extension/app/ts/backgroundServiceWorker.ts | 14 +- extension/app/ts/components/App.tsx | 2 +- .../app/ts/components/pages/ChangeChain.tsx | 4 +- .../app/ts/components/subcomponents/Hint.tsx | 6 +- .../components/subcomponents/clipboardcopy.ts | 8 +- extension/app/ts/listenContentScript.ts | 5 +- extension/app/ts/utils/imageToUri.ts | 27 ++- extension/package.json | 5 +- 29 files changed, 385 insertions(+), 297 deletions(-) create mode 100644 extension/app/html3/addressBookV3.html create mode 100644 extension/app/html3/changeChainV3.html create mode 100644 extension/app/html3/confirmTransactionV3.html create mode 100644 extension/app/html3/favicon.ico create mode 100644 extension/app/html3/interceptorAccessV3.html create mode 100644 extension/app/html3/personalSignV3.html rename extension/app/{html => html3}/popupV3.html (91%) diff --git a/extension/app/html3/addressBookV3.html b/extension/app/html3/addressBookV3.html new file mode 100644 index 00000000..c4cc7bd5 --- /dev/null +++ b/extension/app/html3/addressBookV3.html @@ -0,0 +1,19 @@ + + + + Address Book - The Interceptor + + + + + + + + + +
Loading...
+ + + + + diff --git a/extension/app/html3/changeChainV3.html b/extension/app/html3/changeChainV3.html new file mode 100644 index 00000000..5fd50a7a --- /dev/null +++ b/extension/app/html3/changeChainV3.html @@ -0,0 +1,19 @@ + + + + Change Chain - The Interceptor + + + + + + + + + +
Loading...
+ + + + + diff --git a/extension/app/html3/confirmTransactionV3.html b/extension/app/html3/confirmTransactionV3.html new file mode 100644 index 00000000..98e1fd6b --- /dev/null +++ b/extension/app/html3/confirmTransactionV3.html @@ -0,0 +1,20 @@ + + + + Confirm Transaction - The Interceptor + + + + + + + + + + +
Loading...
+ + + + + diff --git a/extension/app/html3/favicon.ico b/extension/app/html3/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..bfc8aa934677046e46dae67c11ad704c8bc9c9ca GIT binary patch literal 8209 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 + + + Access Request - The Interceptor + + + + + + + + + +
Loading...
+ + + + + diff --git a/extension/app/html3/personalSignV3.html b/extension/app/html3/personalSignV3.html new file mode 100644 index 00000000..8dd28dbb --- /dev/null +++ b/extension/app/html3/personalSignV3.html @@ -0,0 +1,19 @@ + + + + Personal Sign - The Interceptor + + + + + + + + + +
Loading...
+ + + + + diff --git a/extension/app/html/popupV3.html b/extension/app/html3/popupV3.html similarity index 91% rename from extension/app/html/popupV3.html rename to extension/app/html3/popupV3.html index cd5f9f96..bd1a65a6 100644 --- a/extension/app/html/popupV3.html +++ b/extension/app/html3/popupV3.html @@ -14,7 +14,6 @@
Loading...
- diff --git a/extension/app/inpage/output/injected_document_start.js b/extension/app/inpage/output/injected_document_start.js index b20fe4b0..dc2ea669 100644 --- a/extension/app/inpage/output/injected_document_start.js +++ b/extension/app/inpage/output/injected_document_start.js @@ -8,7 +8,7 @@ function listenInContentScript() { const extensionPort = browser.runtime.connect(); let connected = true; // forward all message events to the background script, which will then filter and process them - window.addEventListener('message', messageEvent => { + globalThis.addEventListener('message', messageEvent => { try { // we only want the data element, if it exists, and postMessage will fail if it can't clone the object fully (and it cannot clone a MessageEvent) if (!('data' in messageEvent)) @@ -31,7 +31,7 @@ function listenInContentScript() { extensionPort.onMessage.addListener(response => { try { if (connected) - window.postMessage(response, '*'); + globalThis.postMessage(response, '*'); } catch (error) { console.error(error); diff --git a/extension/app/inpage/ts/document_start.ts b/extension/app/inpage/ts/document_start.ts index 7eb9a87d..ac8266ce 100644 --- a/extension/app/inpage/ts/document_start.ts +++ b/extension/app/inpage/ts/document_start.ts @@ -8,7 +8,7 @@ function listenInContentScript() { let connected = true // forward all message events to the background script, which will then filter and process them - window.addEventListener('message', messageEvent => { + globalThis.addEventListener('message', messageEvent => { try { // we only want the data element, if it exists, and postMessage will fail if it can't clone the object fully (and it cannot clone a MessageEvent) if (!('data' in messageEvent)) return @@ -28,7 +28,7 @@ function listenInContentScript() { // forward all messages we get from the background script to the window so the page script can filter and process them extensionPort.onMessage.addListener(response => { try { - if (connected) window.postMessage(response, '*') + if (connected) globalThis.postMessage(response, '*') } catch (error) { console.error(error) } diff --git a/extension/app/ts/AddressBook.tsx b/extension/app/ts/AddressBook.tsx index 8e69de5e..30561df1 100644 --- a/extension/app/ts/AddressBook.tsx +++ b/extension/app/ts/AddressBook.tsx @@ -244,11 +244,11 @@ export function AddressBook() { changeFilter(activeFilter) browser.runtime.onMessage.addListener(popupMessageListener) const scrollListener = () => update() - window.addEventListener('scroll', scrollListener) + globalThis.addEventListener('scroll', scrollListener) return () => { browser.runtime.onMessage.removeListener(popupMessageListener) - window.removeEventListener('scroll', scrollListener) + globalThis.removeEventListener('scroll', scrollListener) } }, []) @@ -258,7 +258,7 @@ export function AddressBook() { setAddressBookState((previousState) => { if (previousState === undefined) return previousState const pageSizePx = PAGE_SIZE * (ELEMENT_SIZE_PX[previousState.activeFilter] + ELEMENT_PADDING_PX) - const newPage = Math.min(Math.floor(window.scrollY / pageSizePx + 0.5), previousState.maxPages) + const newPage = Math.min(Math.floor(globalThis.scrollY / pageSizePx + 0.5), previousState.maxPages) if (currentPageRef.current === newPage) return previousState setCurrentPage(newPage) @@ -330,7 +330,7 @@ export function AddressBook() { } function getWindowSizeInPages(filter: ActiveFilter) { - return Math.ceil(window.innerHeight / getPageSizeInPixels(filter) ) + return Math.ceil(globalThis.innerHeight / getPageSizeInPixels(filter) ) } function openNewAddress(filter: ActiveFilter) { diff --git a/extension/app/ts/background/accessManagement.ts b/extension/app/ts/background/accessManagement.ts index 9c760adf..475e170a 100644 --- a/extension/app/ts/background/accessManagement.ts +++ b/extension/app/ts/background/accessManagement.ts @@ -11,19 +11,19 @@ import { Settings, WebsiteAccessArray, WebsiteAddressAccess } from '../utils/int function setWebsitePortApproval(port: browser.runtime.Port, websiteOrigin: string, approved: boolean) { const tabId = port.sender?.tab?.id - if (window.interceptor.websitePortApprovals.get(port) === undefined) { + if (globalThis.interceptor.websitePortApprovals.get(port) === undefined) { setEthereumNodeBlockPolling(true) // if we don't already have this connection, clean up afterwards port.onDisconnect.addListener((port) => { - window.interceptor.websitePortApprovals.delete(port) - if (window.interceptor.websitePortApprovals.size === 0) { + globalThis.interceptor.websitePortApprovals.delete(port) + if (globalThis.interceptor.websitePortApprovals.size === 0) { setEthereumNodeBlockPolling(false) } if (tabId !== undefined) { //check if there are still ports using this tab, if not, delete - if (Array.from(window.interceptor.websitePortApprovals.entries()).filter( ([mapPort, _approval]) => mapPort.sender?.tab?.id === tabId ).length == 0) { - window.interceptor.websiteTabApprovals.delete(tabId) + if (Array.from(globalThis.interceptor.websitePortApprovals.entries()).filter( ([mapPort, _approval]) => mapPort.sender?.tab?.id === tabId ).length == 0) { + globalThis.interceptor.websiteTabApprovals.delete(tabId) } } }) @@ -32,18 +32,18 @@ function setWebsitePortApproval(port: browser.runtime.Port, websiteOrigin: strin websiteOrigin: websiteOrigin, approved: approved } - window.interceptor.websitePortApprovals.set(port, websiteApproval) + globalThis.interceptor.websitePortApprovals.set(port, websiteApproval) if (tabId !== undefined) { - window.interceptor.websiteTabApprovals.set(tabId, websiteApproval) + globalThis.interceptor.websiteTabApprovals.set(tabId, websiteApproval) } } export async function verifyAccess(port: browser.runtime.Port, callMethod: string) { if (port.sender === undefined || port.sender.url === undefined) return false - if (window.interceptor.settings == undefined) return false + if (globalThis.interceptor.settings == undefined) return false // check if access has been granted/rejected already - const connection = window.interceptor.websitePortApprovals.get(port) + const connection = globalThis.interceptor.websitePortApprovals.get(port) if ( connection && connection.approved ) return true const websiteOrigin = (new URL(port.sender.url)).hostname @@ -53,19 +53,19 @@ export async function verifyAccess(port: browser.runtime.Port, callMethod: strin const activeAddress = getActiveAddress() if (activeAddress !== undefined) { - const addressAccess = hasAddressAccess(window.interceptor.settings.websiteAccess, websiteOrigin, activeAddress) + const addressAccess = hasAddressAccess(globalThis.interceptor.settings.websiteAccess, websiteOrigin, activeAddress) if (addressAccess === 'hasAccess') { return connectToPort(port, websiteOrigin) } // access not found, ask access - const addressInfo = findAddressInfo(activeAddress, window.interceptor.settings.userAddressBook.addressInfos) + const addressInfo = findAddressInfo(activeAddress, globalThis.interceptor.settings.userAddressBook.addressInfos) const website = await retrieveWebsiteDetails(port, websiteOrigin) - const accessReply = await requestAccessFromUser(port, website, addressInfo, getAssociatedAddresses(window.interceptor.settings, websiteOrigin, addressInfo )) + const accessReply = await requestAccessFromUser(port, website, addressInfo, getAssociatedAddresses(globalThis.interceptor.settings, websiteOrigin, addressInfo )) if (accessReply.userRequestedAddressChange) { const changedActiveAddress = getActiveAddress() if (changedActiveAddress === undefined) return false - const addressAccess = hasAddressAccess(window.interceptor.settings.websiteAccess, websiteOrigin, changedActiveAddress) + const addressAccess = hasAddressAccess(globalThis.interceptor.settings.websiteAccess, websiteOrigin, changedActiveAddress) if (addressAccess === 'hasAccess') { return connectToPort(port, websiteOrigin) } @@ -83,13 +83,13 @@ export async function verifyAccess(port: browser.runtime.Port, callMethod: strin return false } - const access = hasAccess(window.interceptor.settings.websiteAccess, websiteOrigin) + const access = hasAccess(globalThis.interceptor.settings.websiteAccess, websiteOrigin) if (access === 'hasAccess') { return connectToPort(port, websiteOrigin) } const website = await retrieveWebsiteDetails(port, websiteOrigin) - const accessReply = await requestAccessFromUser(port, website, undefined, getAssociatedAddresses(window.interceptor.settings, websiteOrigin, undefined ) ) + const accessReply = await requestAccessFromUser(port, website, undefined, getAssociatedAddresses(globalThis.interceptor.settings, websiteOrigin, undefined ) ) if (accessReply.userRequestedAddressChange === true || accessReply.requestAccessToAddress !== undefined) throw new Error('We did not ask for address specific address but got one anyway') if (access === 'notFound' @@ -105,7 +105,7 @@ export async function verifyAccess(port: browser.runtime.Port, callMethod: strin export function sendMessageToApprovedWebsitePorts(method: string, data: unknown) { // inform all the tabs about the address change - for (const [port, connection] of window.interceptor.websitePortApprovals.entries() ) { + for (const [port, connection] of globalThis.interceptor.websitePortApprovals.entries() ) { if ( !connection.approved ) continue postMessageIfStillConnected(port, { interceptorApproved: true, @@ -115,11 +115,11 @@ export function sendMessageToApprovedWebsitePorts(method: string, data: unknown) } } export function sendActiveAccountChangeToApprovedWebsitePorts() { - if ( !window.interceptor.settings ) return + if ( !globalThis.interceptor.settings ) return // inform all the tabs about the address change - for (const [port, connection] of window.interceptor.websitePortApprovals.entries() ) { + for (const [port, connection] of globalThis.interceptor.websitePortApprovals.entries() ) { if ( !connection.approved ) continue - const activeAddress = getActiveAddressForDomain(window.interceptor.settings.websiteAccess, connection.websiteOrigin) + const activeAddress = getActiveAddressForDomain(globalThis.interceptor.settings.websiteAccess, connection.websiteOrigin) postMessageIfStillConnected(port, { interceptorApproved: true, options: { method: 'accountsChanged' }, @@ -148,7 +148,7 @@ export function hasAddressAccess(websiteAccess: WebsiteAccessArray, websiteOrigi } } } - const askForAddressAccess = window.interceptor.settings?.userAddressBook.addressInfos.find((x) => x.address === address )?.askForAddressAccess + const askForAddressAccess = globalThis.interceptor.settings?.userAddressBook.addressInfos.find((x) => x.address === address )?.askForAddressAccess if (askForAddressAccess === false) return 'hasAccess' return 'notFound' } @@ -244,17 +244,17 @@ function connectToPort(port: browser.runtime.Port, websiteOrigin: string): true setWebsitePortApproval(port, websiteOrigin, true) updateExtensionIcon(port) - if (window.interceptor.settings === undefined) return true - if (window.interceptor.settings.activeChain === undefined) return true + if (globalThis.interceptor.settings === undefined) return true + if (globalThis.interceptor.settings.activeChain === undefined) return true postMessageIfStillConnected(port, { interceptorApproved: true, options: { method: 'connect' }, - result: [EthereumQuantity.serialize(window.interceptor.settings.activeChain)] + result: [EthereumQuantity.serialize(globalThis.interceptor.settings.activeChain)] }) // seems like dapps also want to get account changed and chain changed events after we connect again, so let's send them too - const activeAddress = getActiveAddressForDomain(window.interceptor.settings.websiteAccess, websiteOrigin) + const activeAddress = getActiveAddressForDomain(globalThis.interceptor.settings.websiteAccess, websiteOrigin) postMessageIfStillConnected(port, { interceptorApproved: true, options: { method: 'accountsChanged' }, @@ -264,7 +264,7 @@ function connectToPort(port: browser.runtime.Port, websiteOrigin: string): true postMessageIfStillConnected(port, { interceptorApproved: true, options: { method: 'chainChanged' }, - result: EthereumQuantity.serialize(window.interceptor.settings.activeChain) + result: EthereumQuantity.serialize(globalThis.interceptor.settings.activeChain) }) return true } @@ -290,10 +290,10 @@ export function getAssociatedAddresses(settings: Settings, websiteOrigin: string } async function askUserForAccessOnConnectionUpdate(port: browser.runtime.Port, websiteOrigin: string, activeAddress: AddressInfoEntry | undefined) { - if (window.interceptor.settings === undefined) return + if (globalThis.interceptor.settings === undefined) return const website = await retrieveWebsiteDetails(port, websiteOrigin) - const accessReply = await requestAccessFromUser(port, website, activeAddress, getAssociatedAddresses(window.interceptor.settings, websiteOrigin, activeAddress)) + const accessReply = await requestAccessFromUser(port, website, activeAddress, getAssociatedAddresses(globalThis.interceptor.settings, websiteOrigin, activeAddress)) // here if the reply was for diferent address (requestAccessFromUser can change the target address), we still want to connect even if the address is diferent if (accessReply.approved) { connectToPort(port, websiteOrigin) @@ -301,19 +301,19 @@ async function askUserForAccessOnConnectionUpdate(port: browser.runtime.Port, we } export function updateWebsiteApprovalAccesses() { - if (window.interceptor.settings === undefined) return + if (globalThis.interceptor.settings === undefined) return const activeAddress = getActiveAddress() // update port connections and disconnect from ports that should not have access anymore - for (const [port, connection] of window.interceptor.websitePortApprovals.entries() ) { + for (const [port, connection] of globalThis.interceptor.websitePortApprovals.entries() ) { updateExtensionIcon(port) - const websiteAccess = hasAccess(window.interceptor.settings.websiteAccess, connection.websiteOrigin) + const websiteAccess = hasAccess(globalThis.interceptor.settings.websiteAccess, connection.websiteOrigin) if (activeAddress) { // check for address access changes - const addressAccess = hasAddressAccess(window.interceptor.settings.websiteAccess, connection.websiteOrigin, activeAddress) + const addressAccess = hasAddressAccess(globalThis.interceptor.settings.websiteAccess, connection.websiteOrigin, activeAddress) if (addressAccess === 'notFound') { - askUserForAccessOnConnectionUpdate(port, connection.websiteOrigin, findAddressInfo(activeAddress, window.interceptor.settings.userAddressBook.addressInfos) ) + askUserForAccessOnConnectionUpdate(port, connection.websiteOrigin, findAddressInfo(activeAddress, globalThis.interceptor.settings.userAddressBook.addressInfos) ) } // access has been denied or removed for the address, but it was approved before diff --git a/extension/app/ts/background/background.ts b/extension/app/ts/background/background.ts index 3f083211..e558db5e 100644 --- a/extension/app/ts/background/background.ts +++ b/extension/app/ts/background/background.ts @@ -29,32 +29,30 @@ let currentPrependMode: PrependTransactionMode = PrependTransactionMode.NO_PREPE let simulator: Simulator | undefined = undefined declare global { - interface Window { - interceptor: { - simulation: { - simulationId: number, - simulationState: SimulationState | undefined, - visualizerResults: SimResults[] | undefined, - addressBookEntries: AddressBookEntry[], - tokenPrices: TokenPriceEstimate[], - } - websiteAccessAddressMetadata: AddressInfoEntry[], - pendingAccessMetadata: [string, AddressInfoEntry][], - prependTransactionMode: PrependTransactionMode, - signerChain: bigint | undefined, - signerName: SignerName | undefined, - websiteTabSignerStates: Map, - websitePortApprovals: Map, // map of ports that are either approved or not-approved by interceptor - websiteTabApprovals: Map, - websiteTabConnection: Map, - settings: Settings | undefined, - currentBlockNumber: bigint | undefined, - signerAccounts: readonly EthereumAddress[] | undefined, + var interceptor: { + simulation: { + simulationId: number, + simulationState: SimulationState | undefined, + visualizerResults: SimResults[] | undefined, + addressBookEntries: AddressBookEntry[], + tokenPrices: TokenPriceEstimate[], } + websiteAccessAddressMetadata: AddressInfoEntry[], + pendingAccessMetadata: [string, AddressInfoEntry][], + prependTransactionMode: PrependTransactionMode, + signerChain: bigint | undefined, + signerName: SignerName | undefined, + websiteTabSignerStates: Map, + websitePortApprovals: Map, // map of ports that are either approved or not-approved by interceptor + websiteTabApprovals: Map, + websiteTabConnection: Map, + settings: Settings | undefined, + currentBlockNumber: bigint | undefined, + signerAccounts: readonly EthereumAddress[] | undefined, } } -window.interceptor = { +globalThis.interceptor = { prependTransactionMode: PrependTransactionMode.NO_PREPEND, signerAccounts: undefined, websiteAccessAddressMetadata: [], @@ -78,11 +76,11 @@ window.interceptor = { export async function updateSimulationState( getUpdatedSimulationState: () => Promise) { try { - window.interceptor.simulation.simulationId++ + globalThis.interceptor.simulation.simulationId++ if ( simulator === undefined ) { - window.interceptor.simulation = { - simulationId: window.interceptor.simulation.simulationId, + globalThis.interceptor.simulation = { + simulationId: globalThis.interceptor.simulation.simulationId, simulationState: undefined, addressBookEntries: [], tokenPrices: [], @@ -94,14 +92,14 @@ export async function updateSimulationState( getUpdatedSimulationState: () => Pr const updatedSimulationState = await getUpdatedSimulationState() - const simId = window.interceptor.simulation.simulationId + const simId = globalThis.interceptor.simulation.simulationId if ( updatedSimulationState !== undefined ) { const priceEstimator = new PriceEstimator(simulator.ethereum) const transactions = updatedSimulationState.simulatedTransactions.map((x) => ({ ...x.signedTransaction, website: x.website })) const visualizerResult = await simulator.visualizeTransactionChain(transactions, updatedSimulationState.blockNumber, updatedSimulationState.simulatedTransactions.map( x => x.multicallResponse)) const visualizerResultWithWebsites = visualizerResult.map((x,i) => ({ ...x, website: updatedSimulationState.simulatedTransactions[i].website })) - const addressBookEntries = await getAddressBookEntriesForVisualiser(simulator, visualizerResult.map( (x) => x.visualizerResults), updatedSimulationState, window.interceptor.settings?.userAddressBook) + const addressBookEntries = await getAddressBookEntriesForVisualiser(simulator, visualizerResult.map( (x) => x.visualizerResults), updatedSimulationState, globalThis.interceptor.settings?.userAddressBook) function onlyTokensAndTokensWithKnownDecimals(metadata: AddressBookEntry) : metadata is AddressBookEntry & { type: 'token', decimals: `0x${ string }` } { if (metadata.type !== 'token') return false @@ -113,18 +111,18 @@ export async function updateSimulationState( getUpdatedSimulationState: () => Pr } const tokenPrices = await priceEstimator.estimateEthereumPricesForTokens(addressBookEntries.filter(onlyTokensAndTokensWithKnownDecimals).map(metadataRestructure)) - if (simId !== window.interceptor.simulation.simulationId) return // do not update state if we are already calculating a new one + if (simId !== globalThis.interceptor.simulation.simulationId) return // do not update state if we are already calculating a new one - window.interceptor.simulation = { - simulationId: window.interceptor.simulation.simulationId, + globalThis.interceptor.simulation = { + simulationId: globalThis.interceptor.simulation.simulationId, tokenPrices: tokenPrices, addressBookEntries: addressBookEntries, visualizerResults: visualizerResultWithWebsites, simulationState: updatedSimulationState, } } else { - window.interceptor.simulation = { - simulationId: window.interceptor.simulation.simulationId, + globalThis.interceptor.simulation = { + simulationId: globalThis.interceptor.simulation.simulationId, addressBookEntries: [], tokenPrices: [], visualizerResults: [], @@ -152,7 +150,7 @@ export async function refreshConfirmTransactionSimulation(activeAddress: bigint, const appended = await newSimulator.appendTransaction({ ...transactionToSimulate, website: website }) const transactions = appended.simulationState.simulatedTransactions.map(x => ({ ...x.signedTransaction, website: x.website }) ) const visualizerResult = await simulator.visualizeTransactionChain(transactions, appended.simulationState.blockNumber, appended.simulationState.simulatedTransactions.map( x => x.multicallResponse)) - const addressMetadata = await getAddressBookEntriesForVisualiser(simulator, visualizerResult.map( (x) => x.visualizerResults), appended.simulationState, window.interceptor.settings?.userAddressBook) + const addressMetadata = await getAddressBookEntriesForVisualiser(simulator, visualizerResult.map( (x) => x.visualizerResults), appended.simulationState, globalThis.interceptor.settings?.userAddressBook) const tokenPrices = await priceEstimator.estimateEthereumPricesForTokens( addressMetadata.map( (x) => x.type === 'token' && x.decimals !== undefined ? { token: x.address, decimals: x.decimals } : { token: 0x0n, decimals: 0x0n } @@ -170,7 +168,7 @@ export async function refreshConfirmTransactionSimulation(activeAddress: bigint, addressBookEntries: addressMetadata, tokenPrices: tokenPrices, activeAddress: activeAddress, - signerName: window.interceptor.signerName, + signerName: globalThis.interceptor.signerName, website: website, } } @@ -178,27 +176,27 @@ export async function refreshConfirmTransactionSimulation(activeAddress: bigint, // returns true if simulation state was changed export async function updatePrependMode(forceRefresh: boolean = false) { - if ( currentPrependMode === window.interceptor.prependTransactionMode && !forceRefresh ) return + if ( currentPrependMode === globalThis.interceptor.prependTransactionMode && !forceRefresh ) return if ( simulator === undefined ) return - if ( window.interceptor.settings === undefined ) return - if ( !window.interceptor.settings.simulationMode ) { + if ( globalThis.interceptor.settings === undefined ) return + if ( !globalThis.interceptor.settings.simulationMode ) { await updateSimulationState(async () => await simulator?.simulationModeNode.setPrependTransactionsQueue([])) - currentPrependMode = window.interceptor.prependTransactionMode + currentPrependMode = globalThis.interceptor.prependTransactionMode return true } - switch(window.interceptor.prependTransactionMode) { + switch(globalThis.interceptor.prependTransactionMode) { case PrependTransactionMode.NO_PREPEND: { await updateSimulationState(async () => await simulator?.simulationModeNode.setPrependTransactionsQueue([])) break } case PrependTransactionMode.RICH_MODE: { const activeAddress = getActiveAddress() - const chainId = window.interceptor.settings.activeChain.toString() + const chainId = globalThis.interceptor.settings.activeChain.toString() if ( !isSupportedChain(chainId) ) return false if ( activeAddress === undefined ) return false await updateSimulationState(async () => { - if ( window.interceptor.settings === undefined ) return undefined + if ( globalThis.interceptor.settings === undefined ) return undefined if ( simulator === undefined ) return undefined if ( !isSupportedChain(chainId) ) return undefined const queue = [{ @@ -213,7 +211,7 @@ export async function updatePrependMode(forceRefresh: boolean = false) { break } } - currentPrependMode = window.interceptor.prependTransactionMode + currentPrependMode = globalThis.interceptor.prependTransactionMode return true } @@ -361,7 +359,7 @@ async function handleSigningMode(simulator: Simulator, port: browser.runtime.Por case 'eth_signTypedData_v4': return await signTypedData(simulator, parsedRequest, request?.requestId, false) case 'wallet_switchEthereumChain': return await switchEthereumChain(simulator, parsedRequest, port, request?.requestId, false) case 'eth_sendTransaction': { - if (window.interceptor.settings && isSupportedChain(window.interceptor.settings.activeChain.toString()) ) { + if (globalThis.interceptor.settings && isSupportedChain(globalThis.interceptor.settings.activeChain.toString()) ) { return sendTransaction(getActiveAddressForDomain, simulator, parsedRequest, port, request.requestId, false) } return forwardToSigner() @@ -371,24 +369,24 @@ async function handleSigningMode(simulator: Simulator, port: browser.runtime.Por } function newBlockCallback(blockNumber: bigint) { - window.interceptor.currentBlockNumber = blockNumber + globalThis.interceptor.currentBlockNumber = blockNumber sendPopupMessageToOpenWindows({ method: 'popup_new_block_arrived', data: { blockNumber } }) if (simulator !== undefined) refreshSimulation(simulator) } export async function changeActiveAddressAndChainAndResetSimulation(activeAddress: bigint | undefined | 'noActiveAddressChange', activeChain: bigint | 'noActiveChainChange') { - if (window.interceptor.settings === undefined) return + if (globalThis.interceptor.settings === undefined) return if ( simulator === undefined ) return let chainChanged = false if (activeChain !== 'noActiveChainChange') { - window.interceptor.settings.activeChain = activeChain + globalThis.interceptor.settings.activeChain = activeChain saveActiveChain(activeChain) const chainString = activeChain.toString() if (isSupportedChain(chainString)) { const isPolling = simulator.ethereum.isBlockPolling() - window.interceptor.currentBlockNumber = undefined + globalThis.interceptor.currentBlockNumber = undefined simulator.cleanup() simulator = new Simulator(chainString, isPolling, newBlockCallback) } @@ -398,11 +396,11 @@ export async function changeActiveAddressAndChainAndResetSimulation(activeAddres } if (activeAddress !== 'noActiveAddressChange') { - if (window.interceptor.settings.simulationMode) { - window.interceptor.settings.activeSimulationAddress = activeAddress + if (globalThis.interceptor.settings.simulationMode) { + globalThis.interceptor.settings.activeSimulationAddress = activeAddress saveActiveSimulationAddress(activeAddress) } else { - window.interceptor.settings.activeSigningAddress = activeAddress + globalThis.interceptor.settings.activeSigningAddress = activeAddress saveActiveSigningAddress(activeAddress) } } @@ -413,7 +411,7 @@ export async function changeActiveAddressAndChainAndResetSimulation(activeAddres } if (chainChanged) { - sendMessageToApprovedWebsitePorts('chainChanged', EthereumQuantity.serialize(window.interceptor.settings.activeChain)) + sendMessageToApprovedWebsitePorts('chainChanged', EthereumQuantity.serialize(globalThis.interceptor.settings.activeChain)) sendPopupMessageToOpenWindows({ method: 'popup_chain_update' }) } @@ -425,8 +423,8 @@ export async function changeActiveAddressAndChainAndResetSimulation(activeAddres } export async function changeActiveChain(chainId: bigint) { - if (window.interceptor.settings === undefined) return - if (window.interceptor.settings.simulationMode) { + if (globalThis.interceptor.settings === undefined) return + if (globalThis.interceptor.settings.simulationMode) { return await changeActiveAddressAndChainAndResetSimulation('noActiveAddressChange', chainId) } sendMessageToApprovedWebsitePorts('request_signer_to_wallet_switchEthereumChain', EthereumQuantity.serialize(chainId)) @@ -443,7 +441,7 @@ const providerHandlers = new Map([ export function postMessageIfStillConnected(port: browser.runtime.Port, message: InterceptedRequestForward) { const tabId = port.sender?.tab?.id if (tabId === undefined) return false - if (!window.interceptor.websiteTabConnection.has(tabId)) return false + if (!globalThis.interceptor.websiteTabConnection.has(tabId)) return false try { port.postMessage(message) } catch (error) { @@ -464,7 +462,7 @@ async function onContentScriptConnected(port: browser.runtime.Port) { connectionStatus = 'disconnected' const tabId = port.sender?.tab?.id if ( tabId === undefined ) return - window.interceptor.websiteTabConnection.delete(tabId) + globalThis.interceptor.websiteTabConnection.delete(tabId) }) port.onMessage.addListener(async (payload) => { if (connectionStatus === 'disconnected') return @@ -482,7 +480,7 @@ async function onContentScriptConnected(port: browser.runtime.Port) { const tabId = port.sender?.tab?.id if ( tabId === undefined ) return - if (!window.interceptor.websiteTabConnection.has(tabId)) { + if (!globalThis.interceptor.websiteTabConnection.has(tabId)) { updateExtensionIcon(port) } @@ -503,19 +501,19 @@ async function onContentScriptConnected(port: browser.runtime.Port) { } }) } - if (connectionStatus === 'notInitialized' && window.interceptor.settings?.activeChain !== undefined) { + if (connectionStatus === 'notInitialized' && globalThis.interceptor.settings?.activeChain !== undefined) { console.log('send connect!') postMessageIfStillConnected(port, { interceptorApproved: true, options: { method: 'connect' }, - result: [EthereumQuantity.serialize(window.interceptor.settings.activeChain)] + result: [EthereumQuantity.serialize(globalThis.interceptor.settings.activeChain)] }) connectionStatus = 'connected' } - if (!window.interceptor.settings?.simulationMode || window.interceptor.settings?.useSignersAddressAsActiveAddress) { + if (!globalThis.interceptor.settings?.simulationMode || globalThis.interceptor.settings?.useSignersAddressAsActiveAddress) { // request info (chain and accounts) from the connection right away after the user has approved connection if (port.sender?.tab?.id !== undefined) { - if ( window.interceptor.websiteTabSignerStates.get(port.sender.tab.id) === undefined) { + if ( globalThis.interceptor.websiteTabSignerStates.get(port.sender.tab.id) === undefined) { postMessageIfStillConnected(port, { interceptorApproved: true, options: { method: 'request_signer_to_eth_requestAccounts' }, @@ -532,7 +530,7 @@ async function onContentScriptConnected(port: browser.runtime.Port) { // if simulation mode is not on, we only intercept eth_sendTransaction and personalSign if ( simulator === undefined ) throw 'Interceptor not ready' - const resolved = window.interceptor.settings?.simulationMode || request.usingInterceptorWithoutSigner ? await handleSimulationMode(simulator, port, request) : await handleSigningMode(simulator, port, request) + const resolved = globalThis.interceptor.settings?.simulationMode || request.usingInterceptorWithoutSigner ? await handleSimulationMode(simulator, port, request) : await handleSigningMode(simulator, port, request) if ('error' in resolved) { return postMessageIfStillConnected(port, { ...resolved, @@ -605,7 +603,7 @@ async function popupMessageHandler(simulator: Simulator, request: unknown) { case 'popup_reviewNotification': return await reviewNotification(simulator, parsedRequest) case 'popup_rejectNotification': return await rejectNotification(simulator, parsedRequest) case 'popup_addOrModifyAddressBookEntry': return await addOrModifyAddressInfo(simulator, parsedRequest) - case 'popup_getAddressBookData': return await getAddressBookData(parsedRequest, window.interceptor.settings?.userAddressBook) + case 'popup_getAddressBookData': return await getAddressBookData(parsedRequest, globalThis.interceptor.settings?.userAddressBook) case 'popup_removeAddressBookEntry': return await removeAddressBookEntry(simulator, parsedRequest) case 'popup_openAddressBook': return await openAddressBook(simulator) case 'popup_personalSignReadyAndListening': return // handled elsewhere (personalSign.ts) @@ -618,43 +616,43 @@ async function popupMessageHandler(simulator: Simulator, request: unknown) { } async function startup() { - window.interceptor.settings = await getSettings() - if (window.interceptor.settings.makeMeRich) { - window.interceptor.prependTransactionMode = PrependTransactionMode.RICH_MODE + globalThis.interceptor.settings = await getSettings() + if (globalThis.interceptor.settings.makeMeRich) { + globalThis.interceptor.prependTransactionMode = PrependTransactionMode.RICH_MODE } else { - window.interceptor.prependTransactionMode = PrependTransactionMode.NO_PREPEND + globalThis.interceptor.prependTransactionMode = PrependTransactionMode.NO_PREPEND } - browser.browserAction.setIcon( { path: ICON_NOT_ACTIVE } ) - browser.browserAction.setBadgeBackgroundColor( { color: '#58a5b3' } ) + chrome.action.setIcon( { path: ICON_NOT_ACTIVE }) + browser.action.setBadgeBackgroundColor( { color: '#58a5b3' } ) // if we are using signers mode, update our active address representing to signers address - if (window.interceptor.settings.useSignersAddressAsActiveAddress || window.interceptor.settings.simulationMode === false) { - const signerAcc = (window.interceptor.signerAccounts && window.interceptor.signerAccounts.length > 0) ? window.interceptor.signerAccounts[0] : undefined - if(window.interceptor.settings.simulationMode) { - window.interceptor.settings.activeSimulationAddress = signerAcc + if (globalThis.interceptor.settings.useSignersAddressAsActiveAddress || globalThis.interceptor.settings.simulationMode === false) { + const signerAcc = (globalThis.interceptor.signerAccounts && globalThis.interceptor.signerAccounts.length > 0) ? globalThis.interceptor.signerAccounts[0] : undefined + if(globalThis.interceptor.settings.simulationMode) { + globalThis.interceptor.settings.activeSimulationAddress = signerAcc } else { - window.interceptor.settings.activeSigningAddress = signerAcc + globalThis.interceptor.settings.activeSigningAddress = signerAcc } } - window.interceptor.websiteAccessAddressMetadata = getAddressMetadataForAccess(window.interceptor.settings.websiteAccess) + globalThis.interceptor.websiteAccessAddressMetadata = getAddressMetadataForAccess(globalThis.interceptor.settings.websiteAccess) - const chainString = window.interceptor.settings.activeChain.toString() + const chainString = globalThis.interceptor.settings.activeChain.toString() if (isSupportedChain(chainString)) { simulator = new Simulator(chainString, false, newBlockCallback) } else { simulator = new Simulator('1', false, newBlockCallback) // initialize with mainnet, if user is not using any supported chains } - if (window.interceptor.settings.simulationMode) { - changeActiveAddressAndChainAndResetSimulation(window.interceptor.settings.activeSimulationAddress, window.interceptor.settings.activeChain) + if (globalThis.interceptor.settings.simulationMode) { + changeActiveAddressAndChainAndResetSimulation(globalThis.interceptor.settings.activeSimulationAddress, globalThis.interceptor.settings.activeChain) } browser.runtime.onMessage.addListener(async function(message: unknown) { if (simulator === undefined) throw new Error('Interceptor not ready yet') await popupMessageHandler(simulator, message) }) - await setPendingAccessRequests(window.interceptor.settings.pendingAccessRequests) + await setPendingAccessRequests(globalThis.interceptor.settings.pendingAccessRequests) } startup() diff --git a/extension/app/ts/background/backgroundUtils.ts b/extension/app/ts/background/backgroundUtils.ts index 06dcb801..f57faaaa 100644 --- a/extension/app/ts/background/backgroundUtils.ts +++ b/extension/app/ts/background/backgroundUtils.ts @@ -1,8 +1,8 @@ import { MessageToPopup, PopupMessage, WindowMessage } from '../utils/interceptor-messages.js' export function getActiveAddress() { - if (window.interceptor.settings === undefined) return undefined - return window.interceptor.settings.simulationMode ? window.interceptor.settings.activeSimulationAddress : window.interceptor.settings.activeSigningAddress + if (globalThis.interceptor.settings === undefined) return undefined + return globalThis.interceptor.settings.simulationMode ? globalThis.interceptor.settings.activeSimulationAddress : globalThis.interceptor.settings.activeSigningAddress } export async function sendPopupMessageToOpenWindows(message: MessageToPopup) { @@ -24,13 +24,15 @@ export async function sendPopupMessageToBackgroundPage(message: PopupMessage) { await browser.runtime.sendMessage(PopupMessage.serialize(message)) } +export const INTERNAL_CHANNEL_NAME = 'internalChannel' + export function sendInternalWindowMessage(message: WindowMessage) { - window.postMessage(WindowMessage.serialize(message), window.location.origin) + new BroadcastChannel(INTERNAL_CHANNEL_NAME).postMessage(WindowMessage.serialize(message)) } export function createInternalMessageListener(handler: (message: WindowMessage) => void) { return (message: MessageEvent) => { - if (message.origin !== window.location.origin) return + if (message.origin !== globalThis.location.origin) return handler(WindowMessage.parse(message.data)) } } diff --git a/extension/app/ts/background/iconHandler.ts b/extension/app/ts/background/iconHandler.ts index c9a60769..7581e70f 100644 --- a/extension/app/ts/background/iconHandler.ts +++ b/extension/app/ts/background/iconHandler.ts @@ -7,47 +7,47 @@ import { imageToUri } from '../utils/imageToUri.js' import { Future } from '../utils/future.js' function setInterceptorIcon(tabId: number, icon: string, iconReason: string) { - window.interceptor.websiteTabConnection.set(tabId, { + globalThis.interceptor.websiteTabConnection.set(tabId, { icon: icon, iconReason: iconReason }) sendPopupMessageToOpenWindows({ method: 'popup_websiteIconChanged' }) - return browser.browserAction.setIcon({ + return chrome.action.setIcon({ path: { 128: icon }, tabId: tabId }) } export function updateExtensionIcon(port: browser.runtime.Port) { - if (!window.interceptor.settings) return + if (!globalThis.interceptor.settings) return if (port.sender?.tab?.id === undefined) return if (port.sender?.url === undefined) return const websiteOrigin = (new URL(port.sender.url)).hostname const activeAddress = getActiveAddress() - const censoredActiveAddress = getActiveAddressForDomain(window.interceptor.settings.websiteAccess, websiteOrigin) + const censoredActiveAddress = getActiveAddressForDomain(globalThis.interceptor.settings.websiteAccess, websiteOrigin) if ( activeAddress === undefined) return setInterceptorIcon(port.sender.tab.id, ICON_NOT_ACTIVE, 'No active address selected.') - if (hasAddressAccess(window.interceptor.settings.websiteAccess, websiteOrigin, activeAddress ) === 'notFound') { + if (hasAddressAccess(globalThis.interceptor.settings.websiteAccess, websiteOrigin, activeAddress ) === 'notFound') { // we don't have active address selected, or no access specified - return setInterceptorIcon(port.sender.tab.id, ICON_NOT_ACTIVE, `${ websiteOrigin } has PENDING access request for ${ getAddressMetaData(activeAddress, window.interceptor.settings?.userAddressBook).name }!`) + return setInterceptorIcon(port.sender.tab.id, ICON_NOT_ACTIVE, `${ websiteOrigin } has PENDING access request for ${ getAddressMetaData(activeAddress, globalThis.interceptor.settings?.userAddressBook).name }!`) } if (censoredActiveAddress === undefined) { - if ( hasAccess(window.interceptor.settings.websiteAccess, websiteOrigin) === 'noAccess') { + if ( hasAccess(globalThis.interceptor.settings.websiteAccess, websiteOrigin) === 'noAccess') { return setInterceptorIcon(port.sender.tab.id, ICON_ACCESS_DENIED, `The access for ${ websiteOrigin } has been DENIED!`) } - return setInterceptorIcon(port.sender.tab.id, ICON_ACCESS_DENIED, `The access to ${ getAddressMetaData(activeAddress, window.interceptor.settings?.userAddressBook).name } for ${ websiteOrigin } has been DENIED!`) + return setInterceptorIcon(port.sender.tab.id, ICON_ACCESS_DENIED, `The access to ${ getAddressMetaData(activeAddress, globalThis.interceptor.settings?.userAddressBook).name } for ${ websiteOrigin } has been DENIED!`) } - if (window.interceptor.settings?.simulationMode) return setInterceptorIcon(port.sender.tab.id, ICON_SIMULATING, `The Interceptor simulates your sent transactions.`) - if (!isSupportedChain(window.interceptor.settings.activeChain.toString())) return setInterceptorIcon(port.sender.tab.id, ICON_SIGNING_NOT_SUPPORTED, `Interceptor is on an unsupported network and simulation mode is disabled.`) + if (globalThis.interceptor.settings?.simulationMode) return setInterceptorIcon(port.sender.tab.id, ICON_SIMULATING, `The Interceptor simulates your sent transactions.`) + if (!isSupportedChain(globalThis.interceptor.settings.activeChain.toString())) return setInterceptorIcon(port.sender.tab.id, ICON_SIGNING_NOT_SUPPORTED, `Interceptor is on an unsupported network and simulation mode is disabled.`) - return setInterceptorIcon(port.sender.tab.id, ICON_SIGNING, `The Interceptor forwards your transactions to ${ getSignerName(window.interceptor.signerName) } once sent.`) + return setInterceptorIcon(port.sender.tab.id, ICON_SIGNING, `The Interceptor forwards your transactions to ${ getSignerName(globalThis.interceptor.signerName) } once sent.`) } export async function updateExtensionBadge() { - if (!window.interceptor.settings) return - const count = window.interceptor.settings.pendingAccessRequests.length - return await browser.browserAction.setBadgeText( { text: count === 0 ? '' : count.toString() } ) + if (!globalThis.interceptor.settings) return + const count = globalThis.interceptor.settings.pendingAccessRequests.length + return await browser.action.setBadgeText( { text: count === 0 ? '' : count.toString() } ) } export async function retrieveWebsiteDetails(port: browser.runtime.Port, websiteOrigin: string) { diff --git a/extension/app/ts/background/popupMessageHandlers.ts b/extension/app/ts/background/popupMessageHandlers.ts index 8a5b8c5d..5366ad35 100644 --- a/extension/app/ts/background/popupMessageHandlers.ts +++ b/extension/app/ts/background/popupMessageHandlers.ts @@ -27,46 +27,46 @@ export async function confirmRequestAccess(_simulator: Simulator, confirmation: } export async function changeActiveAddress(_simulator: Simulator, addressChange: ChangeActiveAddress) { - if (window.interceptor.settings === undefined) return - window.interceptor.settings.useSignersAddressAsActiveAddress = addressChange.options === 'signer' + if (globalThis.interceptor.settings === undefined) return + globalThis.interceptor.settings.useSignersAddressAsActiveAddress = addressChange.options === 'signer' // if using signers address, set the active address to signers address if available, otherwise we don't know active address and set it to be undefined if(addressChange.options === 'signer') { - await changeActiveAddressAndChainAndResetSimulation(window.interceptor.signerAccounts && window.interceptor.signerAccounts.length > 0 ? window.interceptor.signerAccounts[0] : undefined, 'noActiveChainChange') + await changeActiveAddressAndChainAndResetSimulation(globalThis.interceptor.signerAccounts && globalThis.interceptor.signerAccounts.length > 0 ? globalThis.interceptor.signerAccounts[0] : undefined, 'noActiveChainChange') } else { await changeActiveAddressAndChainAndResetSimulation(addressChange.options, 'noActiveChainChange') } - saveUseSignersAddressAsActiveAddress(window.interceptor.settings.useSignersAddressAsActiveAddress) + saveUseSignersAddressAsActiveAddress(globalThis.interceptor.settings.useSignersAddressAsActiveAddress) } export async function changeMakeMeRich(_simulator: Simulator, makeMeRichChange: ChangeMakeMeRich) { - if (window.interceptor.settings === undefined) return + if (globalThis.interceptor.settings === undefined) return if (makeMeRichChange.options) { - window.interceptor.prependTransactionMode = PrependTransactionMode.RICH_MODE + globalThis.interceptor.prependTransactionMode = PrependTransactionMode.RICH_MODE } else { - window.interceptor.prependTransactionMode = PrependTransactionMode.NO_PREPEND + globalThis.interceptor.prependTransactionMode = PrependTransactionMode.NO_PREPEND } - window.interceptor.settings.makeMeRich = makeMeRichChange.options + globalThis.interceptor.settings.makeMeRich = makeMeRichChange.options saveMakeMeRich(makeMeRichChange.options) await updatePrependMode(true) } export async function removeAddressBookEntry(_simulator: Simulator, removeAddressBookEntry: RemoveAddressBookEntry) { - if (window.interceptor.settings === undefined) return + if (globalThis.interceptor.settings === undefined) return switch(removeAddressBookEntry.options.addressBookCategory) { case 'My Active Addresses': { - window.interceptor.settings.userAddressBook.addressInfos = window.interceptor.settings.userAddressBook.addressInfos.filter((info) => info.address !== removeAddressBookEntry.options.address) - saveAddressInfos(window.interceptor.settings.userAddressBook.addressInfos) + globalThis.interceptor.settings.userAddressBook.addressInfos = globalThis.interceptor.settings.userAddressBook.addressInfos.filter((info) => info.address !== removeAddressBookEntry.options.address) + saveAddressInfos(globalThis.interceptor.settings.userAddressBook.addressInfos) updateWebsiteApprovalAccesses() sendPopupMessageToOpenWindows({ method: 'popup_addressBookEntriesChanged' }) return } case 'My Contacts': { - window.interceptor.settings.userAddressBook.contacts = window.interceptor.settings.userAddressBook.contacts.filter((contact) => contact.address !== removeAddressBookEntry.options.address) - saveContacts(window.interceptor.settings.userAddressBook.contacts) + globalThis.interceptor.settings.userAddressBook.contacts = globalThis.interceptor.settings.userAddressBook.contacts.filter((contact) => contact.address !== removeAddressBookEntry.options.address) + saveContacts(globalThis.interceptor.settings.userAddressBook.contacts) sendPopupMessageToOpenWindows({ method: 'popup_addressBookEntriesChanged' }) return } @@ -78,30 +78,30 @@ export async function removeAddressBookEntry(_simulator: Simulator, removeAddres } export async function addOrModifyAddressInfo(_simulator: Simulator, entry: AddOrEditAddressBookEntry) { - if (window.interceptor.settings === undefined) return + if (globalThis.interceptor.settings === undefined) return const newEntry = entry.options switch (newEntry.type) { case 'NFT': case 'other contract': case 'token': throw new Error(`No support to modify this entry yet! ${ newEntry.type }`) case 'addressInfo': { - if (window.interceptor.settings.userAddressBook.addressInfos.find( (x) => x.address === entry.options.address) ) { - window.interceptor.settings.userAddressBook.addressInfos = window.interceptor.settings.userAddressBook.addressInfos.map( (x) => x.address === newEntry.address ? newEntry : x ) + if (globalThis.interceptor.settings.userAddressBook.addressInfos.find( (x) => x.address === entry.options.address) ) { + globalThis.interceptor.settings.userAddressBook.addressInfos = globalThis.interceptor.settings.userAddressBook.addressInfos.map( (x) => x.address === newEntry.address ? newEntry : x ) } else { - window.interceptor.settings.userAddressBook.addressInfos = window.interceptor.settings.userAddressBook.addressInfos.concat([newEntry]) + globalThis.interceptor.settings.userAddressBook.addressInfos = globalThis.interceptor.settings.userAddressBook.addressInfos.concat([newEntry]) } - saveAddressInfos(window.interceptor.settings.userAddressBook.addressInfos) + saveAddressInfos(globalThis.interceptor.settings.userAddressBook.addressInfos) updateWebsiteApprovalAccesses() sendPopupMessageToOpenWindows({ method: 'popup_addressBookEntriesChanged' }) return } case 'contact': { - if (window.interceptor.settings.userAddressBook.contacts.find( (x) => x.address === entry.options.address) ) { - window.interceptor.settings.userAddressBook.contacts = window.interceptor.settings.userAddressBook.contacts.map( (x) => x.address === newEntry.address ? newEntry : x ) + if (globalThis.interceptor.settings.userAddressBook.contacts.find( (x) => x.address === entry.options.address) ) { + globalThis.interceptor.settings.userAddressBook.contacts = globalThis.interceptor.settings.userAddressBook.contacts.map( (x) => x.address === newEntry.address ? newEntry : x ) } else { - window.interceptor.settings.userAddressBook.contacts = window.interceptor.settings.userAddressBook.contacts.concat([newEntry]) + globalThis.interceptor.settings.userAddressBook.contacts = globalThis.interceptor.settings.userAddressBook.contacts.concat([newEntry]) } - saveContacts(window.interceptor.settings.userAddressBook.contacts) + saveContacts(globalThis.interceptor.settings.userAddressBook.contacts) sendPopupMessageToOpenWindows({ method: 'popup_addressBookEntriesChanged' }) return } @@ -110,16 +110,16 @@ export async function addOrModifyAddressInfo(_simulator: Simulator, entry: AddOr } export async function changeInterceptorAccess(_simulator: Simulator, accessChange: ChangeInterceptorAccess) { - if (window.interceptor.settings === undefined) return - window.interceptor.settings.websiteAccess = accessChange.options + if (globalThis.interceptor.settings === undefined) return + globalThis.interceptor.settings.websiteAccess = accessChange.options saveWebsiteAccess(accessChange.options) updateWebsiteApprovalAccesses() sendPopupMessageToOpenWindows({ method: 'popup_interceptor_access_changed' }) } export async function changePage(_simulator: Simulator, page: ChangePage) { - if (window.interceptor.settings === undefined) return - window.interceptor.settings.page = page.options + if (globalThis.interceptor.settings === undefined) return + globalThis.interceptor.settings.page = page.options savePage(page.options) } @@ -156,39 +156,39 @@ export async function changeChainDialog(_simulator: Simulator, chainChange: Chai } export async function enableSimulationMode(_simulator: Simulator, params: EnableSimulationMode) { - if (window.interceptor.settings === undefined) return + if (globalThis.interceptor.settings === undefined) return - window.interceptor.settings.simulationMode = params.options + globalThis.interceptor.settings.simulationMode = params.options saveSimulationMode(params.options) // if we are on unsupported chain, force change to a supported one - const chainToSwitch = isSupportedChain(window.interceptor.settings.activeChain.toString()) ? window.interceptor.settings.activeChain : 1n + const chainToSwitch = isSupportedChain(globalThis.interceptor.settings.activeChain.toString()) ? globalThis.interceptor.settings.activeChain : 1n - if(window.interceptor.settings.useSignersAddressAsActiveAddress || window.interceptor.settings.simulationMode === false) { - await changeActiveAddressAndChainAndResetSimulation(window.interceptor.signerAccounts && window.interceptor.signerAccounts.length > 0 ? window.interceptor.signerAccounts[0] : undefined, chainToSwitch) + if(globalThis.interceptor.settings.useSignersAddressAsActiveAddress || globalThis.interceptor.settings.simulationMode === false) { + await changeActiveAddressAndChainAndResetSimulation(globalThis.interceptor.signerAccounts && globalThis.interceptor.signerAccounts.length > 0 ? globalThis.interceptor.signerAccounts[0] : undefined, chainToSwitch) } else { - await changeActiveAddressAndChainAndResetSimulation(window.interceptor.settings.simulationMode ? window.interceptor.settings.activeSimulationAddress : window.interceptor.settings.activeSigningAddress, chainToSwitch) + await changeActiveAddressAndChainAndResetSimulation(globalThis.interceptor.settings.simulationMode ? globalThis.interceptor.settings.activeSimulationAddress : globalThis.interceptor.settings.activeSigningAddress, chainToSwitch) } if (!params.options) { sendMessageToApprovedWebsitePorts('request_signer_to_eth_requestAccounts', []) - sendMessageToApprovedWebsitePorts('request_signer_chainId', EthereumQuantity.serialize(window.interceptor.settings.activeChain)) + sendMessageToApprovedWebsitePorts('request_signer_chainId', EthereumQuantity.serialize(globalThis.interceptor.settings.activeChain)) } } export async function reviewNotification(_simulator: Simulator, params: ReviewNotification) { - if (window.interceptor.settings === undefined) return - const notification = window.interceptor.settings.pendingAccessRequests.find( (x) => x.website.websiteOrigin === params.options.website.websiteOrigin && x.requestAccessToAddress === params.options.requestAccessToAddress) + if (globalThis.interceptor.settings === undefined) return + const notification = globalThis.interceptor.settings.pendingAccessRequests.find( (x) => x.website.websiteOrigin === params.options.website.websiteOrigin && x.requestAccessToAddress === params.options.requestAccessToAddress) if (notification === undefined) return await resolveExistingInterceptorAccessAsNoResponse() - const addressInfo = notification.requestAccessToAddress === undefined ? undefined : findAddressInfo(BigInt(notification.requestAccessToAddress), window.interceptor.settings.userAddressBook.addressInfos) - const metadata = getAssociatedAddresses(window.interceptor.settings, notification.website.websiteOrigin, addressInfo) + const addressInfo = notification.requestAccessToAddress === undefined ? undefined : findAddressInfo(BigInt(notification.requestAccessToAddress), globalThis.interceptor.settings.userAddressBook.addressInfos) + const metadata = getAssociatedAddresses(globalThis.interceptor.settings, notification.website.websiteOrigin, addressInfo) await requestAccessFromUser(undefined, notification.website, addressInfo, metadata) } export async function rejectNotification(_simulator: Simulator, params: RejectNotification) { - if (window.interceptor.settings === undefined) return + if (globalThis.interceptor.settings === undefined) return if (params.options.removeOnly) { - await setPendingAccessRequests( window.interceptor.settings.pendingAccessRequests.filter( (x) => !(x.website.websiteOrigin === params.options.website.websiteOrigin && x.requestAccessToAddress === params.options.requestAccessToAddress) ) ) + await setPendingAccessRequests( globalThis.interceptor.settings.pendingAccessRequests.filter( (x) => !(x.website.websiteOrigin === params.options.website.websiteOrigin && x.requestAccessToAddress === params.options.requestAccessToAddress) ) ) } await resolveInterceptorAccess({ @@ -226,7 +226,7 @@ export async function getAddressBookData(parsed: GetAddressBookData, userAddress export async function openAddressBook(_simulator: Simulator) { const openInNewTab = async () => { - const tab = await browser.tabs.create({ url: '/html/addressBook.html' }) + const tab = await browser.tabs.create({ url: '/html3/addressBookV3.html' }) if (tab.id !== undefined) saveOpenedAddressBookTabId(tab.id) } @@ -240,31 +240,31 @@ export async function openAddressBook(_simulator: Simulator) { } export async function homeOpened() { - if (window.interceptor.settings === undefined) return + if (globalThis.interceptor.settings === undefined) return const tabs = await browser.tabs.query({ active: true, currentWindow: true }) if (tabs.length === 0 || tabs[0].id === undefined ) return - const signerState = window.interceptor.websiteTabSignerStates.get(tabs[0].id) + const signerState = globalThis.interceptor.websiteTabSignerStates.get(tabs[0].id) const signerAccounts = signerState === undefined ? undefined : signerState.signerAccounts - const tabConnection = window.interceptor.websiteTabConnection.get(tabs[0].id) - const tabApproved = window.interceptor.websiteTabApprovals.get(tabs[0].id)?.approved === true + const tabConnection = globalThis.interceptor.websiteTabConnection.get(tabs[0].id) + const tabApproved = globalThis.interceptor.websiteTabApprovals.get(tabs[0].id)?.approved === true sendPopupMessageToOpenWindows({ method: 'popup_UpdateHomePage', data: { simulation: { - simulationState: window.interceptor.simulation.simulationState, - visualizerResults: window.interceptor.simulation.visualizerResults, - addressBookEntries: window.interceptor.simulation.addressBookEntries, - tokenPrices: window.interceptor.simulation.tokenPrices, + simulationState: globalThis.interceptor.simulation.simulationState, + visualizerResults: globalThis.interceptor.simulation.visualizerResults, + addressBookEntries: globalThis.interceptor.simulation.addressBookEntries, + tokenPrices: globalThis.interceptor.simulation.tokenPrices, }, - websiteAccessAddressMetadata: window.interceptor.websiteAccessAddressMetadata, - pendingAccessMetadata: window.interceptor.pendingAccessMetadata, + websiteAccessAddressMetadata: globalThis.interceptor.websiteAccessAddressMetadata, + pendingAccessMetadata: globalThis.interceptor.pendingAccessMetadata, signerAccounts: signerAccounts, - signerChain: window.interceptor.signerChain, - signerName: window.interceptor.signerName, - currentBlockNumber: window.interceptor.currentBlockNumber, - settings: window.interceptor.settings, + signerChain: globalThis.interceptor.signerChain, + signerName: globalThis.interceptor.signerName, + currentBlockNumber: globalThis.interceptor.currentBlockNumber, + settings: globalThis.interceptor.settings, tabConnection: tabConnection, tabApproved: tabApproved, } diff --git a/extension/app/ts/background/providerMessageHandlers.ts b/extension/app/ts/background/providerMessageHandlers.ts index 26bd7cde..47718dff 100644 --- a/extension/app/ts/background/providerMessageHandlers.ts +++ b/extension/app/ts/background/providerMessageHandlers.ts @@ -8,19 +8,19 @@ export function ethAccountsReply(port: browser.runtime.Port, request: ProviderMe if (!('params' in request.options)) return const signerAccounts = EthereumAccountsReply.parse(request.options.params) if ( port.sender?.tab?.id !== undefined ) { - window.interceptor.websiteTabSignerStates.set(port.sender.tab.id, { + globalThis.interceptor.websiteTabSignerStates.set(port.sender.tab.id, { signerAccounts: signerAccounts, - signerChain: window.interceptor.signerChain, + signerChain: globalThis.interceptor.signerChain, }) } - if (window.interceptor) { - window.interceptor.signerAccounts = signerAccounts + if (globalThis.interceptor) { + globalThis.interceptor.signerAccounts = signerAccounts const portSenderId = port.sender?.id if (portSenderId !== undefined) sendInternalWindowMessage({ method: 'window_signer_accounts_changed', data: { portSenderId: portSenderId} }) } // update active address if we are using signers address - if (window.interceptor.settings?.useSignersAddressAsActiveAddress || window.interceptor.settings?.simulationMode === false) { + if (globalThis.interceptor.settings?.useSignersAddressAsActiveAddress || globalThis.interceptor.settings?.simulationMode === false) { changeActiveAddressAndChainAndResetSimulation(signerAccounts[0], 'noActiveChainChange') } sendPopupMessageToOpenWindows({ method: 'popup_accounts_update' }) @@ -28,17 +28,17 @@ export function ethAccountsReply(port: browser.runtime.Port, request: ProviderMe async function changeSignerChain(port: browser.runtime.Port, signerChain: bigint ) { if ( port.sender?.tab?.id !== undefined ) { - window.interceptor.websiteTabSignerStates.set(port.sender.tab.id, { - signerAccounts: window.interceptor.signerAccounts, + globalThis.interceptor.websiteTabSignerStates.set(port.sender.tab.id, { + signerAccounts: globalThis.interceptor.signerAccounts, signerChain: signerChain, }) } - if (window.interceptor) { - window.interceptor.signerChain = signerChain + if (globalThis.interceptor) { + globalThis.interceptor.signerChain = signerChain } // update active address if we are using signers address - if ( !window.interceptor.settings?.simulationMode ) { + if ( !globalThis.interceptor.settings?.simulationMode ) { return changeActiveAddressAndChainAndResetSimulation('noActiveAddressChange', signerChain) } sendPopupMessageToOpenWindows({ method: 'popup_chain_update' }) @@ -63,6 +63,6 @@ export function walletSwitchEthereumChainReply(port: browser.runtime.Port, reque } export function connectedToSigner(_port: browser.runtime.Port, request: ProviderMessage) { - window.interceptor.signerName = ConnectedToSigner.parse(request.options).params[0] + globalThis.interceptor.signerName = ConnectedToSigner.parse(request.options).params[0] sendPopupMessageToOpenWindows({ method: 'popup_signer_name_changed' }) } diff --git a/extension/app/ts/background/simulationModeHanders.ts b/extension/app/ts/background/simulationModeHanders.ts index 2bd6fa53..3d8ee455 100644 --- a/extension/app/ts/background/simulationModeHanders.ts +++ b/extension/app/ts/background/simulationModeHanders.ts @@ -28,15 +28,15 @@ export async function getTransactionReceipt(simulator: Simulator, request: Trans } function getFromField(simulationMode: boolean, request: SendTransactionParams, getActiveAddressForDomain: (websiteAccess: WebsiteAccessArray, websiteOrigin: string) => bigint | undefined, port: browser.runtime.Port) { - if (window.interceptor.settings === undefined) throw new Error('Interceptor is not ready') + if (globalThis.interceptor.settings === undefined) throw new Error('Interceptor is not ready') if (simulationMode && 'from' in request.params[0] && request.params[0].from !== undefined) { return request.params[0].from // use `from` field directly from the dapp if we are in simulation mode and its available } else { - const connection = window.interceptor.websitePortApprovals.get(port) + const connection = globalThis.interceptor.websitePortApprovals.get(port) if (connection === undefined) throw new Error('Not connected') - const from = getActiveAddressForDomain(window.interceptor.settings.websiteAccess, connection.websiteOrigin) + const from = getActiveAddressForDomain(globalThis.interceptor.settings.websiteAccess, connection.websiteOrigin) if (from === undefined) throw new Error('Access to active address is denied') return from } @@ -141,11 +141,11 @@ export async function unsubscribe(simulator: Simulator, request: EthUnSubscribeP } export async function getAccounts(getActiveAddressForDomain: (websiteAccess: WebsiteAccessArray, websiteOrigin: string) => bigint | undefined, _simulator: Simulator, port: browser.runtime.Port) { - const connection = window.interceptor.websitePortApprovals.get(port) - if (connection === undefined || window.interceptor.settings === undefined) { + const connection = globalThis.interceptor.websitePortApprovals.get(port) + if (connection === undefined || globalThis.interceptor.settings === undefined) { return { result: [] } } - const account = getActiveAddressForDomain(window.interceptor.settings.websiteAccess, connection.websiteOrigin) + const account = getActiveAddressForDomain(globalThis.interceptor.settings.websiteAccess, connection.websiteOrigin) if (account === undefined) { return {result: [] } } diff --git a/extension/app/ts/background/windows/changeChain.ts b/extension/app/ts/background/windows/changeChain.ts index fc521782..d78e1dbe 100644 --- a/extension/app/ts/background/windows/changeChain.ts +++ b/extension/app/ts/background/windows/changeChain.ts @@ -61,7 +61,7 @@ export const openChangeChainDialog = async (requestId: number, simulationMode: b openedWindow = await browser.windows.create( { - url: '../html/changeChain.html', + url: '../html3/changeChainV3.html', type: 'popup', height: 400, width: 520, diff --git a/extension/app/ts/background/windows/confirmTransaction.ts b/extension/app/ts/background/windows/confirmTransaction.ts index 10ab0d34..386fce20 100644 --- a/extension/app/ts/background/windows/confirmTransaction.ts +++ b/extension/app/ts/background/windows/confirmTransaction.ts @@ -45,9 +45,9 @@ export async function openConfirmTransactionDialog( transactionToSimulatePromise: () => Promise, ) { if (pendingTransaction !== undefined) return reject() // previous window still loading - if (window.interceptor.settings === undefined) return ERROR_INTERCEPTOR_NOT_READY + if (globalThis.interceptor.settings === undefined) return ERROR_INTERCEPTOR_NOT_READY - const activeAddress = getActiveAddressForDomain(window.interceptor.settings.websiteAccess, website.websiteOrigin) + const activeAddress = getActiveAddressForDomain(globalThis.interceptor.settings.websiteAccess, website.websiteOrigin) if (activeAddress === undefined) return ERROR_INTERCEPTOR_NO_ACTIVE_ADDRESS if (openedConfirmTransactionDialogWindow !== null && openedConfirmTransactionDialogWindow.id) { @@ -75,7 +75,7 @@ export async function openConfirmTransactionDialog( openedConfirmTransactionDialogWindow = await browser.windows.create( { - url: '../html/confirmTransaction.html', + url: '../html3/confirmTransactionV3.html', type: 'popup', height: 600, width: 600, diff --git a/extension/app/ts/background/windows/interceptorAccess.ts b/extension/app/ts/background/windows/interceptorAccess.ts index e3bb7966..39d47058 100644 --- a/extension/app/ts/background/windows/interceptorAccess.ts +++ b/extension/app/ts/background/windows/interceptorAccess.ts @@ -4,7 +4,7 @@ import { InterceptorAccessOptions, PopupMessage, WebsiteAccessArray, WindowMessa import { AddressInfoEntry, PendingAccessRequestArray, Website } from '../../utils/user-interface-types.js' import { getAssociatedAddresses, setAccess, updateWebsiteApprovalAccesses } from '../accessManagement.js' import { changeActiveAddressAndChainAndResetSimulation, postMessageIfStillConnected } from '../background.js' -import { createInternalMessageListener, sendPopupMessageToOpenWindows } from '../backgroundUtils.js' +import { INTERNAL_CHANNEL_NAME, createInternalMessageListener, sendPopupMessageToOpenWindows } from '../backgroundUtils.js' import { updateExtensionBadge } from '../iconHandler.js' import { findAddressInfo } from '../metadataUtils.js' import { savePendingAccessRequests, saveWebsiteAccess } from '../settings.js' @@ -53,48 +53,49 @@ export async function resolveInterceptorAccess(confirmation: InterceptorAccessOp } export function getAddressMetadataForAccess(websiteAccess: WebsiteAccessArray): AddressInfoEntry[] { - if (window.interceptor.settings === undefined) return [] + if (globalThis.interceptor.settings === undefined) return [] const addresses = websiteAccess.map((x) => x.addressAccess === undefined ? [] : x.addressAccess?.map((addr) => addr.address)).flat() const addressSet = new Set(addresses) - const infos = window.interceptor.settings.userAddressBook.addressInfos + const infos = globalThis.interceptor.settings.userAddressBook.addressInfos return Array.from(addressSet).map((x) => findAddressInfo(x, infos)) } export async function setPendingAccessRequests(pendingAccessRequest: PendingAccessRequestArray) { - if (window.interceptor.settings === undefined) return - window.interceptor.settings.pendingAccessRequests = pendingAccessRequest - const addresses = window.interceptor.settings.pendingAccessRequests.map((x) => x.requestAccessToAddress === undefined ? [] : x.requestAccessToAddress).flat() + if (globalThis.interceptor.settings === undefined) return + globalThis.interceptor.settings.pendingAccessRequests = pendingAccessRequest + const addresses = globalThis.interceptor.settings.pendingAccessRequests.map((x) => x.requestAccessToAddress === undefined ? [] : x.requestAccessToAddress).flat() const addressSet = new Set(addresses) - const infos = window.interceptor.settings.userAddressBook.addressInfos - window.interceptor.pendingAccessMetadata = Array.from(addressSet).map((x) => [addressString(x), findAddressInfo(BigInt(x), infos)]) - savePendingAccessRequests(window.interceptor.settings.pendingAccessRequests) + const infos = globalThis.interceptor.settings.userAddressBook.addressInfos + globalThis.interceptor.pendingAccessMetadata = Array.from(addressSet).map((x) => [addressString(x), findAddressInfo(BigInt(x), infos)]) + savePendingAccessRequests(globalThis.interceptor.settings.pendingAccessRequests) await updateExtensionBadge() } export async function changeAccess(confirmation: InterceptorAccessOptions, website: Website) { - if (window.interceptor.settings === undefined) return + if (globalThis.interceptor.settings === undefined) return if (confirmation.type !== 'approval') return if (confirmation.approval === 'NoResponse') return - window.interceptor.settings.websiteAccess = setAccess(window.interceptor.settings.websiteAccess, website, confirmation.approval === 'Approved', confirmation.requestAccessToAddress) - window.interceptor.websiteAccessAddressMetadata = getAddressMetadataForAccess(window.interceptor.settings.websiteAccess) - saveWebsiteAccess(window.interceptor.settings.websiteAccess) + globalThis.interceptor.settings.websiteAccess = setAccess(globalThis.interceptor.settings.websiteAccess, website, confirmation.approval === 'Approved', confirmation.requestAccessToAddress) + globalThis.interceptor.websiteAccessAddressMetadata = getAddressMetadataForAccess(globalThis.interceptor.settings.websiteAccess) + saveWebsiteAccess(globalThis.interceptor.settings.websiteAccess) updateWebsiteApprovalAccesses() sendPopupMessageToOpenWindows({ method: 'popup_websiteAccess_changed' }) - await setPendingAccessRequests(window.interceptor.settings.pendingAccessRequests.filter((x) => !(x.website.websiteOrigin === website.websiteOrigin && x.requestAccessToAddress === confirmation.requestAccessToAddress))) + await setPendingAccessRequests(globalThis.interceptor.settings.pendingAccessRequests.filter((x) => !(x.website.websiteOrigin === website.websiteOrigin && x.requestAccessToAddress === confirmation.requestAccessToAddress))) } async function askForSignerAccountsFromSignerIfNotAvailable(port: browser.runtime.Port) { - if (window.interceptor.signerAccounts !== undefined) return window.interceptor.signerAccounts + if (globalThis.interceptor.signerAccounts !== undefined) return globalThis.interceptor.signerAccounts const portSenderId = port.sender?.id - if (portSenderId === undefined) return window.interceptor.signerAccounts + if (portSenderId === undefined) return globalThis.interceptor.signerAccounts const future = new Future const listener = createInternalMessageListener( (message: WindowMessage) => { if (message.method === 'window_signer_accounts_changed' && message.data.portSenderId === portSenderId) return future.resolve() }) + const channel = new BroadcastChannel(INTERNAL_CHANNEL_NAME) try { - window.addEventListener('message', listener) + channel.addEventListener('message', listener) const messageSent = postMessageIfStillConnected(port, { interceptorApproved: true, options: { method: 'request_signer_to_eth_requestAccounts' }, @@ -102,9 +103,10 @@ async function askForSignerAccountsFromSignerIfNotAvailable(port: browser.runtim }) if (messageSent) await future } finally { - window.removeEventListener('message', listener) + channel.removeEventListener('message', listener) + channel.close() } - return window.interceptor.signerAccounts + return globalThis.interceptor.signerAccounts } type RequestAccessFromUserReply = { @@ -115,15 +117,15 @@ type RequestAccessFromUserReply = { export async function requestAccessFromUser(port: browser.runtime.Port | undefined, website: Website, requestAccessToAddress: AddressInfoEntry | undefined, associatedAddresses: AddressInfoEntry[]): Promise { const rejectReply = { requestAccessToAddress: requestAccessToAddress?.address, approved: false, userRequestedAddressChange: false } - if (window.interceptor.settings === undefined) return rejectReply + if (globalThis.interceptor.settings === undefined) return rejectReply // check if we need to ask address access or not. If address is put to never need to have address specific permision, we don't need to ask for it - const askForAddressAccess = requestAccessToAddress !== undefined && window.interceptor.settings?.userAddressBook.addressInfos.find((x) => x.address === requestAccessToAddress.address)?.askForAddressAccess !== false + const askForAddressAccess = requestAccessToAddress !== undefined && globalThis.interceptor.settings?.userAddressBook.addressInfos.find((x) => x.address === requestAccessToAddress.address)?.askForAddressAccess !== false const accessAddress = askForAddressAccess ? requestAccessToAddress : undefined - const simulationMode = window.interceptor.settings.simulationMode + const simulationMode = globalThis.interceptor.settings.simulationMode - if (window.interceptor.settings.pendingAccessRequests.find((x) => x.website.websiteOrigin === website.websiteOrigin && x.requestAccessToAddress === accessAddress?.address) === undefined) { + if (globalThis.interceptor.settings.pendingAccessRequests.find((x) => x.website.websiteOrigin === website.websiteOrigin && x.requestAccessToAddress === accessAddress?.address) === undefined) { // we didn't have this request pending already, add it to the list - await setPendingAccessRequests(window.interceptor.settings.pendingAccessRequests.concat({ + await setPendingAccessRequests(globalThis.interceptor.settings.pendingAccessRequests.concat({ website, requestAccessToAddress: accessAddress?.address, })) @@ -134,16 +136,16 @@ export async function requestAccessFromUser(port: browser.runtime.Port | undefin const message = PopupMessage.parse(msg) if (message.method !== 'popup_interceptorAccessReadyAndListening') return browser.runtime.onMessage.removeListener(windowReadyAndListening) - if (window.interceptor.settings === undefined) return rejectReply + if (globalThis.interceptor.settings === undefined) return rejectReply return await sendPopupMessageToOpenWindows({ method: 'popup_interceptorAccessDialog', data: { website: website, requestAccessToAddress: accessAddress, associatedAddresses: associatedAddresses, - addressInfos: window.interceptor.settings.userAddressBook.addressInfos, + addressInfos: globalThis.interceptor.settings.userAddressBook.addressInfos, signerAccounts: [], - signerName: window.interceptor.signerName, + signerName: globalThis.interceptor.signerName, simulationMode: simulationMode, allowAddressChanging: port !== undefined, } @@ -164,7 +166,7 @@ export async function requestAccessFromUser(port: browser.runtime.Port | undefin openedInterceptorAccessWindow = await browser.windows.create( { - url: '../html/interceptorAccess.html', + url: '../html3/interceptorAccessV3.html', type: 'popup', height: 600, width: 600, @@ -192,7 +194,7 @@ export async function requestAccessFromUser(port: browser.runtime.Port | undefin if (userRequestedAddressChange) { // clear the original pending request, which was made with other account - await setPendingAccessRequests(window.interceptor.settings.pendingAccessRequests.filter((x) => !(x.website.websiteOrigin === website.websiteOrigin && x.requestAccessToAddress === accessAddress?.address))) + await setPendingAccessRequests(globalThis.interceptor.settings.pendingAccessRequests.filter((x) => !(x.website.websiteOrigin === website.websiteOrigin && x.requestAccessToAddress === accessAddress?.address))) // change address if (confirmation.requestAccessToAddress !== undefined) { @@ -222,8 +224,8 @@ export async function requestAccessFromUser(port: browser.runtime.Port | undefin const proposedAddress = await getProposedAddress(port, confirmation) const newActiveAddress: bigint = proposedAddress === undefined ? accessAddress.address : proposedAddress - const newActiveAddressAddressInfo = findAddressInfo(newActiveAddress, window.interceptor.settings.userAddressBook.addressInfos) - const associatedAddresses = getAssociatedAddresses(window.interceptor.settings, website.websiteOrigin, newActiveAddressAddressInfo) + const newActiveAddressAddressInfo = findAddressInfo(newActiveAddress, globalThis.interceptor.settings.userAddressBook.addressInfos) + const associatedAddresses = getAssociatedAddresses(globalThis.interceptor.settings, website.websiteOrigin, newActiveAddressAddressInfo) pendingInterceptorAccess = { future: new Future(), websiteOrigin: website.websiteOrigin, @@ -235,9 +237,9 @@ export async function requestAccessFromUser(port: browser.runtime.Port | undefin website, requestAccessToAddress: newActiveAddressAddressInfo, associatedAddresses: associatedAddresses, - addressInfos: window.interceptor.settings.userAddressBook.addressInfos, + addressInfos: globalThis.interceptor.settings.userAddressBook.addressInfos, signerAccounts: [], - signerName: window.interceptor.signerName, + signerName: globalThis.interceptor.signerName, simulationMode: simulationMode, allowAddressChanging: port !== undefined, } diff --git a/extension/app/ts/background/windows/personalSign.ts b/extension/app/ts/background/windows/personalSign.ts index ea6dbcda..1964bf87 100644 --- a/extension/app/ts/background/windows/personalSign.ts +++ b/extension/app/ts/background/windows/personalSign.ts @@ -37,7 +37,7 @@ export const openPersonalSignDialog = async (requestId: number, simulationMode: if (pendingPersonalSign) await pendingPersonalSign // wait for previous to clean up } - const activeAddress = simulationMode ? window.interceptor.settings?.activeSimulationAddress : window.interceptor.settings?.activeSigningAddress + const activeAddress = simulationMode ? globalThis.interceptor.settings?.activeSimulationAddress : globalThis.interceptor.settings?.activeSigningAddress if ( activeAddress === undefined) { return { result: { error: { @@ -63,7 +63,7 @@ export const openPersonalSignDialog = async (requestId: number, simulationMode: simulationMode: simulationMode, requestId: requestId, message: params.params[0], - account: getAddressMetaData(params.params[1], window.interceptor.settings?.userAddressBook), + account: getAddressMetaData(params.params[1], globalThis.interceptor.settings?.userAddressBook), method: params.method, } }) @@ -79,12 +79,12 @@ export const openPersonalSignDialog = async (requestId: number, simulationMode: simulationMode: simulationMode, requestId: requestId, message: parsed, - account: getAddressMetaData(params.params[0], window.interceptor.settings?.userAddressBook), + account: getAddressMetaData(params.params[0], globalThis.interceptor.settings?.userAddressBook), method: params.method, addressBookEntries: { - owner: getAddressMetaData(parsed.message.owner, window.interceptor.settings?.userAddressBook), - spender: getAddressMetaData(parsed.message.spender, window.interceptor.settings?.userAddressBook), - verifyingContract: getAddressMetaData(parsed.domain.verifyingContract, window.interceptor.settings?.userAddressBook) + owner: getAddressMetaData(parsed.message.owner, globalThis.interceptor.settings?.userAddressBook), + spender: getAddressMetaData(parsed.message.spender, globalThis.interceptor.settings?.userAddressBook), + verifyingContract: getAddressMetaData(parsed.domain.verifyingContract, globalThis.interceptor.settings?.userAddressBook) }, } }) @@ -100,12 +100,12 @@ export const openPersonalSignDialog = async (requestId: number, simulationMode: simulationMode: simulationMode, requestId: requestId, message: parsed, - account: getAddressMetaData(params.params[0], window.interceptor.settings?.userAddressBook), + account: getAddressMetaData(params.params[0], globalThis.interceptor.settings?.userAddressBook), method: params.method, addressBookEntries: { - token: getAddressMetaData(parsed.message.details.token, window.interceptor.settings?.userAddressBook), - spender: getAddressMetaData(parsed.message.spender, window.interceptor.settings?.userAddressBook), - verifyingContract: getAddressMetaData(parsed.domain.verifyingContract, window.interceptor.settings?.userAddressBook) + token: getAddressMetaData(parsed.message.details.token, globalThis.interceptor.settings?.userAddressBook), + spender: getAddressMetaData(parsed.message.spender, globalThis.interceptor.settings?.userAddressBook), + verifyingContract: getAddressMetaData(parsed.domain.verifyingContract, globalThis.interceptor.settings?.userAddressBook) }, } }) @@ -119,7 +119,7 @@ export const openPersonalSignDialog = async (requestId: number, simulationMode: simulationMode: simulationMode, requestId: requestId, message: stringifyJSONWithBigInts(params.params[1]), - account: getAddressMetaData(params.params[0], window.interceptor.settings?.userAddressBook), + account: getAddressMetaData(params.params[0], globalThis.interceptor.settings?.userAddressBook), method: params.method, } }) @@ -128,7 +128,7 @@ export const openPersonalSignDialog = async (requestId: number, simulationMode: openedPersonalSignDialogWindow = await browser.windows.create( { - url: '../html/personalSign.html', + url: '../html3/personalSignV3.html', type: 'popup', height: 400, width: 520, diff --git a/extension/app/ts/backgroundServiceWorker.ts b/extension/app/ts/backgroundServiceWorker.ts index e213cf2c..9b2b55c2 100644 --- a/extension/app/ts/backgroundServiceWorker.ts +++ b/extension/app/ts/backgroundServiceWorker.ts @@ -1,5 +1,5 @@ import './background/background.js' - +/* chrome.runtime.onStartup.addListener(() => { console.log('onStartup()') }) @@ -16,15 +16,13 @@ chrome.runtime.onMessageExternal.addListener(({ type, name }) => { console.log(name) return false }) +*/ +chrome.action.setPopup({ popup: 'html3/popupV3.html' }) self.addEventListener('install', () => { console.log('install') }) -self.addEventListener('message', (mess) => { - console.log('window.message') - console.log(mess) -}) /* async function onContentScriptConnected(port: chrome.runtime.Port) { console.log('content script connected') @@ -64,9 +62,3 @@ const injectContentScript = async () => { } injectContentScript() - -chrome.action.onClicked.addListener((_tab) => { - chrome.action.setPopup({ - popup: 'html/popup.html' - }) -}) diff --git a/extension/app/ts/components/App.tsx b/extension/app/ts/components/App.tsx index 00725693..8d5697cc 100644 --- a/extension/app/ts/components/App.tsx +++ b/extension/app/ts/components/App.tsx @@ -185,7 +185,7 @@ export function App() { function openAddressBook() { sendPopupMessageToBackgroundPage( { method: 'popup_openAddressBook' } ) - return window.close() // close extension popup, chrome closes it by default, but firefox does not + return globalThis.close() // close extension popup, chrome closes it by default, but firefox does not } return ( diff --git a/extension/app/ts/components/pages/ChangeChain.tsx b/extension/app/ts/components/pages/ChangeChain.tsx index ef1068fc..4b07c776 100644 --- a/extension/app/ts/components/pages/ChangeChain.tsx +++ b/extension/app/ts/components/pages/ChangeChain.tsx @@ -41,13 +41,13 @@ export function ChangeChain() { function approve() { if ( chainChangeData?.requestId === undefined) throw new Error('Request id is missing') sendPopupMessageToBackgroundPage( { method: 'popup_changeChainDialog', options: { accept: true, requestId: chainChangeData.requestId } } ) - window.close() + globalThis.close() } function reject() { if ( chainChangeData?.requestId === undefined) throw new Error('Request id is missing') sendPopupMessageToBackgroundPage( { method: 'popup_changeChainDialog', options: { accept: false, requestId: chainChangeData.requestId } } ) - window.close() + globalThis.close() } return ( diff --git a/extension/app/ts/components/subcomponents/Hint.tsx b/extension/app/ts/components/subcomponents/Hint.tsx index c149cc2f..b00239f9 100644 --- a/extension/app/ts/components/subcomponents/Hint.tsx +++ b/extension/app/ts/components/subcomponents/Hint.tsx @@ -94,7 +94,7 @@ function calculatePosition(clickPosX: number, clickPosY: number, hintWidth: numb const borderPadding = 30 return { - left: positionX + hintWidth > window.innerWidth - borderPadding ? window.innerWidth - borderPadding - hintWidth : (positionX < borderPadding ? borderPadding : positionX), + left: positionX + hintWidth > globalThis.innerWidth - borderPadding ? globalThis.innerWidth - borderPadding - hintWidth : (positionX < borderPadding ? borderPadding : positionX), top: positionY, } } @@ -110,9 +110,9 @@ function Hint(props: HintProps) { } useEffect(() => { - window.addEventListener('resize', clean) + globalThis.addEventListener('resize', clean) return () => { - window.removeEventListener('resize', clean) + globalThis.removeEventListener('resize', clean) } }) diff --git a/extension/app/ts/components/subcomponents/clipboardcopy.ts b/extension/app/ts/components/subcomponents/clipboardcopy.ts index b7d68493..068d7a6a 100644 --- a/extension/app/ts/components/subcomponents/clipboardcopy.ts +++ b/extension/app/ts/components/subcomponents/clipboardcopy.ts @@ -28,22 +28,22 @@ async function copyExecCommand (text: string) { document.body.appendChild(span) // Make a selection object representing the range of text selected by the user - const selection = window.getSelection() + const selection = globalThis.getSelection() if (!selection) return - const range = window.document.createRange() + const range = globalThis.document.createRange() selection.removeAllRanges() range.selectNode(span) selection.addRange(range) // Copy text to the clipboard try { - if (!window.document.execCommand('copy')) { + if (!globalThis.document.execCommand('copy')) { throw makeError() } } finally { // Cleanup selection.removeAllRanges() - window.document.body.removeChild(span) + globalThis.document.body.removeChild(span) } } diff --git a/extension/app/ts/listenContentScript.ts b/extension/app/ts/listenContentScript.ts index 7aa99d6d..795f9766 100644 --- a/extension/app/ts/listenContentScript.ts +++ b/extension/app/ts/listenContentScript.ts @@ -8,9 +8,8 @@ function listenInContentScript() { let connected = true // forward all message events to the background script, which will then filter and process them - window.addEventListener('message', messageEvent => { + globalThis.addEventListener('message', messageEvent => { try { - console.log(messageEvent) // we only want the data element, if it exists, and postMessage will fail if it can't clone the object fully (and it cannot clone a MessageEvent) if (!('data' in messageEvent)) return if (connected) extensionPort.postMessage({ data: messageEvent.data }) @@ -29,7 +28,7 @@ function listenInContentScript() { // forward all messages we get from the background script to the window so the page script can filter and process them extensionPort.onMessage.addListener(response => { try { - if (connected) window.postMessage(response, '*') + if (connected) globalThis.postMessage(response, '*') } catch (error) { console.error(error) } diff --git a/extension/app/ts/utils/imageToUri.ts b/extension/app/ts/utils/imageToUri.ts index e39a159f..4b3e4c97 100644 --- a/extension/app/ts/utils/imageToUri.ts +++ b/extension/app/ts/utils/imageToUri.ts @@ -1,18 +1,17 @@ +import { Future } from './future.js' + export async function imageToUri(url: string, maxSizeInBytes: number = 1048576) { - const canvas = document.createElement('canvas') - const context = canvas.getContext('2d') - if (context === null) return undefined + const response = await fetch(url) + const blob = await response.blob() + const reader = new FileReader() + const future = new Future - const baseImage = new Image() - baseImage.src = url - await new Promise(resolve => baseImage.onload = resolve) - canvas.width = baseImage.width - canvas.height = baseImage.height - context.drawImage(baseImage, 0, 0) - const dataUrl = canvas.toDataURL('image/png') - canvas.remove() + reader.onloadend = () => future.resolve(reader.result === null ? undefined : reader.result as string) + reader.onerror = () => future.resolve(undefined) + reader.onabort = () => future.resolve(undefined) + reader.readAsDataURL(blob) + const data = await future - // if the file is too big, let's not store it - if ( new Blob([dataUrl]).size > maxSizeInBytes ) return undefined - return dataUrl + if (data === undefined || data.length > maxSizeInBytes) return undefined + return data } diff --git a/extension/package.json b/extension/package.json index 13c59366..706c7ee8 100644 --- a/extension/package.json +++ b/extension/package.json @@ -5,9 +5,10 @@ "scripts": { "test": "tsc --project tsconfig-test.json && node test/js/test/run-all.js", "setup": "npm run vendor && npm run inpage && npm run build", - "build": "tsc", + "build": "tsc && npm run bundle", "inpage": "cd inpage && npm ci --ignore-scripts && npm run build", - "vendor": "cd build && npm ci --ignore-scripts && npm run vendor" + "vendor": "cd build && npm ci --ignore-scripts && npm run vendor", + "bundle": "cd build && npm run bundle" }, "dependencies": { "@darkflorist/address-metadata": "0.2.0", From 1398adfab006d6378ba73f9ba77cabc8eaf014da Mon Sep 17 00:00:00 2001 From: Killari Date: Mon, 6 Mar 2023 09:18:39 +0200 Subject: [PATCH 3/6] support for both v2 and v3 --- extension/app/ts/background/background.ts | 2 +- .../app/ts/background/backgroundUtils.ts | 9 ++++ extension/app/ts/background/iconHandler.ts | 2 +- .../app/ts/background/popupMessageHandlers.ts | 4 +- .../app/ts/background/windows/changeChain.ts | 4 +- .../background/windows/confirmTransaction.ts | 4 +- .../background/windows/interceptorAccess.ts | 4 +- .../app/ts/background/windows/personalSign.ts | 4 +- extension/app/ts/backgroundServiceWorker.ts | 42 ++----------------- 9 files changed, 25 insertions(+), 50 deletions(-) diff --git a/extension/app/ts/background/background.ts b/extension/app/ts/background/background.ts index e558db5e..1159a17e 100644 --- a/extension/app/ts/background/background.ts +++ b/extension/app/ts/background/background.ts @@ -623,7 +623,7 @@ async function startup() { globalThis.interceptor.prependTransactionMode = PrependTransactionMode.NO_PREPEND } - chrome.action.setIcon( { path: ICON_NOT_ACTIVE }) + browser.action.setIcon({ path: ICON_NOT_ACTIVE }) browser.action.setBadgeBackgroundColor( { color: '#58a5b3' } ) // if we are using signers mode, update our active address representing to signers address diff --git a/extension/app/ts/background/backgroundUtils.ts b/extension/app/ts/background/backgroundUtils.ts index f57faaaa..0a0a7de8 100644 --- a/extension/app/ts/background/backgroundUtils.ts +++ b/extension/app/ts/background/backgroundUtils.ts @@ -36,3 +36,12 @@ export function createInternalMessageListener(handler: (message: WindowMessage) handler(WindowMessage.parse(message.data)) } } + +type HTMLFile = 'popup' | 'addressBook' | 'changeChain' | 'confirmTransaction' | 'interceptorAccess' | 'personalSign' +export function getHtmlFile(file: HTMLFile) { + const manifest = browser.runtime.getManifest() + if (manifest.version === '2') { + return `html/${ file }.html` + } + return `html3/${ file }V3.html` +} diff --git a/extension/app/ts/background/iconHandler.ts b/extension/app/ts/background/iconHandler.ts index 7581e70f..e91cee52 100644 --- a/extension/app/ts/background/iconHandler.ts +++ b/extension/app/ts/background/iconHandler.ts @@ -12,7 +12,7 @@ function setInterceptorIcon(tabId: number, icon: string, iconReason: string) { iconReason: iconReason }) sendPopupMessageToOpenWindows({ method: 'popup_websiteIconChanged' }) - return chrome.action.setIcon({ + return browser.action.setIcon({ path: { 128: icon }, tabId: tabId }) diff --git a/extension/app/ts/background/popupMessageHandlers.ts b/extension/app/ts/background/popupMessageHandlers.ts index 5366ad35..10c52074 100644 --- a/extension/app/ts/background/popupMessageHandlers.ts +++ b/extension/app/ts/background/popupMessageHandlers.ts @@ -8,7 +8,7 @@ import { changeAccess, requestAccessFromUser, resolveExistingInterceptorAccessAs import { resolveChainChange } from './windows/changeChain.js' import { EthereumQuantity } from '../utils/wire-types.js' import { getAssociatedAddresses, sendMessageToApprovedWebsitePorts, updateWebsiteApprovalAccesses } from './accessManagement.js' -import { sendPopupMessageToOpenWindows } from './backgroundUtils.js' +import { getHtmlFile, sendPopupMessageToOpenWindows } from './backgroundUtils.js' import { isSupportedChain } from '../utils/constants.js' import { getMetadataForAddressBookData } from './medataSearch.js' import { findAddressInfo } from './metadataUtils.js' @@ -226,7 +226,7 @@ export async function getAddressBookData(parsed: GetAddressBookData, userAddress export async function openAddressBook(_simulator: Simulator) { const openInNewTab = async () => { - const tab = await browser.tabs.create({ url: '/html3/addressBookV3.html' }) + const tab = await browser.tabs.create({ url: getHtmlFile('addressBook') }) if (tab.id !== undefined) saveOpenedAddressBookTabId(tab.id) } diff --git a/extension/app/ts/background/windows/changeChain.ts b/extension/app/ts/background/windows/changeChain.ts index d78e1dbe..efb050b7 100644 --- a/extension/app/ts/background/windows/changeChain.ts +++ b/extension/app/ts/background/windows/changeChain.ts @@ -3,7 +3,7 @@ import { Future } from '../../utils/future.js' import { ChainChangeConfirmation, PopupMessage, SignerChainChangeConfirmation, } from '../../utils/interceptor-messages.js' import { Website } from '../../utils/user-interface-types.js' import { changeActiveChain } from '../background.js' -import { sendPopupMessageToOpenWindows } from '../backgroundUtils.js' +import { getHtmlFile, sendPopupMessageToOpenWindows } from '../backgroundUtils.js' let pendForUserReply: Future | undefined = undefined let pendForSignerReply: Future | undefined = undefined @@ -61,7 +61,7 @@ export const openChangeChainDialog = async (requestId: number, simulationMode: b openedWindow = await browser.windows.create( { - url: '../html3/changeChainV3.html', + url: getHtmlFile('changeChain'), type: 'popup', height: 400, width: 520, diff --git a/extension/app/ts/background/windows/confirmTransaction.ts b/extension/app/ts/background/windows/confirmTransaction.ts index 386fce20..85358c79 100644 --- a/extension/app/ts/background/windows/confirmTransaction.ts +++ b/extension/app/ts/background/windows/confirmTransaction.ts @@ -6,7 +6,7 @@ import { Website } from '../../utils/user-interface-types.js' import { EthereumUnsignedTransaction } from '../../utils/wire-types.js' import { getActiveAddressForDomain } from '../accessManagement.js' import { appendTransactionToSimulator, refreshConfirmTransactionSimulation } from '../background.js' -import { sendPopupMessageToOpenWindows } from '../backgroundUtils.js' +import { getHtmlFile, sendPopupMessageToOpenWindows } from '../backgroundUtils.js' export type Confirmation = 'Approved' | 'Rejected' | 'NoResponse' let openedConfirmTransactionDialogWindow: browser.windows.Window | null = null @@ -75,7 +75,7 @@ export async function openConfirmTransactionDialog( openedConfirmTransactionDialogWindow = await browser.windows.create( { - url: '../html3/confirmTransactionV3.html', + url: getHtmlFile('confirmTransaction'), type: 'popup', height: 600, width: 600, diff --git a/extension/app/ts/background/windows/interceptorAccess.ts b/extension/app/ts/background/windows/interceptorAccess.ts index 39d47058..52455c22 100644 --- a/extension/app/ts/background/windows/interceptorAccess.ts +++ b/extension/app/ts/background/windows/interceptorAccess.ts @@ -4,7 +4,7 @@ import { InterceptorAccessOptions, PopupMessage, WebsiteAccessArray, WindowMessa import { AddressInfoEntry, PendingAccessRequestArray, Website } from '../../utils/user-interface-types.js' import { getAssociatedAddresses, setAccess, updateWebsiteApprovalAccesses } from '../accessManagement.js' import { changeActiveAddressAndChainAndResetSimulation, postMessageIfStillConnected } from '../background.js' -import { INTERNAL_CHANNEL_NAME, createInternalMessageListener, sendPopupMessageToOpenWindows } from '../backgroundUtils.js' +import { INTERNAL_CHANNEL_NAME, createInternalMessageListener, getHtmlFile, sendPopupMessageToOpenWindows } from '../backgroundUtils.js' import { updateExtensionBadge } from '../iconHandler.js' import { findAddressInfo } from '../metadataUtils.js' import { savePendingAccessRequests, saveWebsiteAccess } from '../settings.js' @@ -166,7 +166,7 @@ export async function requestAccessFromUser(port: browser.runtime.Port | undefin openedInterceptorAccessWindow = await browser.windows.create( { - url: '../html3/interceptorAccessV3.html', + url: getHtmlFile('interceptorAccess'), type: 'popup', height: 600, width: 600, diff --git a/extension/app/ts/background/windows/personalSign.ts b/extension/app/ts/background/windows/personalSign.ts index 1964bf87..cb1ac149 100644 --- a/extension/app/ts/background/windows/personalSign.ts +++ b/extension/app/ts/background/windows/personalSign.ts @@ -4,7 +4,7 @@ import { Future } from '../../utils/future.js' import { PersonalSign, PopupMessage } from '../../utils/interceptor-messages.js' import { EIP2612Message, Permit2, PersonalSignParams, SignTypedDataParams } from '../../utils/wire-types.js' import { personalSignWithSimulator } from '../background.js' -import { sendPopupMessageToOpenWindows } from '../backgroundUtils.js' +import { getHtmlFile, sendPopupMessageToOpenWindows } from '../backgroundUtils.js' import { getAddressMetaData } from '../metadataUtils.js' let pendingPersonalSign: Future | undefined = undefined @@ -128,7 +128,7 @@ export const openPersonalSignDialog = async (requestId: number, simulationMode: openedPersonalSignDialogWindow = await browser.windows.create( { - url: '../html3/personalSignV3.html', + url: getHtmlFile('personalSign'), type: 'popup', height: 400, width: 520, diff --git a/extension/app/ts/backgroundServiceWorker.ts b/extension/app/ts/backgroundServiceWorker.ts index 9b2b55c2..cead9abb 100644 --- a/extension/app/ts/backgroundServiceWorker.ts +++ b/extension/app/ts/backgroundServiceWorker.ts @@ -1,55 +1,21 @@ import './background/background.js' -/* -chrome.runtime.onStartup.addListener(() => { - console.log('onStartup()') -}) - -chrome.runtime.onMessage.addListener((message: unknown) => { - console.log('OnMessage') - console.log(message) - return false -}) +import { getHtmlFile } from './background/backgroundUtils.js' -chrome.runtime.onMessageExternal.addListener(({ type, name }) => { - console.log('onMessageExternal') - console.log(type) - console.log(name) - return false -}) -*/ -chrome.action.setPopup({ popup: 'html3/popupV3.html' }) +browser.action.setPopup({ popup: getHtmlFile('popup') }) self.addEventListener('install', () => { console.log('install') }) -/* -async function onContentScriptConnected(port: chrome.runtime.Port) { - console.log('content script connected') - port.onMessage.addListener(async (payload) => { - if(!( - 'data' in payload - && typeof payload.data === 'object' - && payload.data !== null - && 'interceptorRequest' in payload.data - )) return - console.log(payload) - const request = InterceptedRequest.parse(payload.data) - console.log(request.options.method) - }) -} -chrome.runtime.onConnect.addListener(port => onContentScriptConnected(port).catch(console.error)) -*/ - const injectContentScript = async () => { try { - await chrome.scripting.registerContentScripts([{ + await browser.scripting.registerContentScripts([{ id: 'inpage2', matches: ['file://*/*', 'http://*/*', 'https://*/*'], js: ['/vendor/webextension-polyfill/browser-polyfill.js', './js/listenContentScript.js'], runAt: 'document_start', } ]) - await chrome.scripting.registerContentScripts([{ + await chrome.scripting.registerContentScripts([{ // we need to use `chrome` here instead of `browser` as `world: 'MAIN'` is not supported otherwise id: 'inpage', matches: ['file://*/*', 'http://*/*', 'https://*/*'], js: ['/inpage/js/inpage.js'], From 8682a35e42d02094ec0cae0d7efa1cb17afe0b3b Mon Sep 17 00:00:00 2001 From: Killari Date: Mon, 6 Mar 2023 09:41:34 +0200 Subject: [PATCH 4/6] separate manifests and add build scripts to build either or --- extension/.gitignore | 1 + extension/Dockerfile | 2 +- extension/app/{manifest.json => manifestV2.json} | 0 extension/package.json | 11 ++++++++--- 4 files changed, 10 insertions(+), 4 deletions(-) rename extension/app/{manifest.json => manifestV2.json} (100%) diff --git a/extension/.gitignore b/extension/.gitignore index 627f427b..43783c9c 100644 --- a/extension/.gitignore +++ b/extension/.gitignore @@ -4,3 +4,4 @@ node_modules/ /app/inpage/build/ /app/inpage/js/ !/app/inpage/output/injected_document_start.js +/app/manifest.json diff --git a/extension/Dockerfile b/extension/Dockerfile index 1f2776b1..46edabd6 100644 --- a/extension/Dockerfile +++ b/extension/Dockerfile @@ -31,7 +31,7 @@ RUN npm run vendor WORKDIR /extension RUN npm run inpage -RUN npm run build +RUN npm run build-firefox RUN npm run test WORKDIR /extension/app diff --git a/extension/app/manifest.json b/extension/app/manifestV2.json similarity index 100% rename from extension/app/manifest.json rename to extension/app/manifestV2.json diff --git a/extension/package.json b/extension/package.json index 706c7ee8..0c6a8f96 100644 --- a/extension/package.json +++ b/extension/package.json @@ -4,11 +4,16 @@ "type": "module", "scripts": { "test": "tsc --project tsconfig-test.json && node test/js/test/run-all.js", - "setup": "npm run vendor && npm run inpage && npm run build", - "build": "tsc && npm run bundle", + "setup-firefox": "npm run vendor && npm run inpage && npm run build-firefox", + "setup-chrome": "npm run vendor && npm run inpage && npm run build-chrome", + "build-firefox": "tsc && npm run firefox", + "build-chrome": "tsc && npm run bundle && npm run chrome", "inpage": "cd inpage && npm ci --ignore-scripts && npm run build", "vendor": "cd build && npm ci --ignore-scripts && npm run vendor", - "bundle": "cd build && npm run bundle" + "bundle": "cd build && npm run bundle", + + "firefox": "node -e \"const fs = require('fs'); fs.copyFileSync('app/manifestV2.json', 'app/manifest.json');\"", + "chrome": "node -e \"const fs = require('fs'); fs.copyFileSync('app/manifestV3.json', 'app/manifest.json');\"" }, "dependencies": { "@darkflorist/address-metadata": "0.2.0", From 467fe601faecc5f0a8066b0896e2a74ebab11d67 Mon Sep 17 00:00:00 2001 From: Killari Date: Mon, 6 Mar 2023 09:54:14 +0200 Subject: [PATCH 5/6] edit v2 manifest as this is not needed in v3 --- extension/build/vendor.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extension/build/vendor.ts b/extension/build/vendor.ts index f885c341..6e8f5a25 100644 --- a/extension/build/vendor.ts +++ b/extension/build/vendor.ts @@ -44,7 +44,7 @@ async function vendorDependencies(files: string[]) { // update the new hash to manifest.json const base64EncodedSHA256 = createHash('sha256').update(importmapJson).digest('base64') - const manifestLocation = path.join(directoryOfThisFile, '..', 'app', 'manifest.json') + const manifestLocation = path.join(directoryOfThisFile, '..', 'app', 'manifestV2.json') const oldManifest = await fs.readFile(manifestLocation, 'utf8') const newManifest = oldManifest.replace(/sha256-[\s\S]*?'/m, `sha256-${ base64EncodedSHA256 }'`) await fs.writeFile(manifestLocation, newManifest) From 4c270399f2c420d5f4672815c226b0a87469894d Mon Sep 17 00:00:00 2001 From: Killari Date: Mon, 6 Mar 2023 10:09:16 +0200 Subject: [PATCH 6/6] fix actions --- extension/app/ts/background/background.ts | 6 ++--- .../app/ts/background/backgroundUtils.ts | 26 ++++++++++++++++++- extension/app/ts/background/iconHandler.ts | 8 +++--- 3 files changed, 32 insertions(+), 8 deletions(-) diff --git a/extension/app/ts/background/background.ts b/extension/app/ts/background/background.ts index 1159a17e..33943476 100644 --- a/extension/app/ts/background/background.ts +++ b/extension/app/ts/background/background.ts @@ -12,7 +12,7 @@ import { CHAINS, ICON_NOT_ACTIVE, isSupportedChain, MAKE_YOU_RICH_TRANSACTION, M import { PriceEstimator } from '../simulation/priceEstimator.js' import { getActiveAddressForDomain, sendActiveAccountChangeToApprovedWebsitePorts, sendMessageToApprovedWebsitePorts, updateWebsiteApprovalAccesses, verifyAccess } from './accessManagement.js' import { getAddressBookEntriesForVisualiser } from './metadataUtils.js' -import { getActiveAddress, sendPopupMessageToOpenWindows } from './backgroundUtils.js' +import { getActiveAddress, sendPopupMessageToOpenWindows, setExtensionBadgeBackgroundColor, setExtensionIcon } from './backgroundUtils.js' import { updateExtensionIcon } from './iconHandler.js' import { connectedToSigner, ethAccountsReply, signerChainChanged, walletSwitchEthereumChainReply } from './providerMessageHandlers.js' import { SimulationModeEthereumClientService } from '../simulation/services/SimulationModeEthereumClientService.js' @@ -623,8 +623,8 @@ async function startup() { globalThis.interceptor.prependTransactionMode = PrependTransactionMode.NO_PREPEND } - browser.action.setIcon({ path: ICON_NOT_ACTIVE }) - browser.action.setBadgeBackgroundColor( { color: '#58a5b3' } ) + await setExtensionIcon({ path: ICON_NOT_ACTIVE }) + await setExtensionBadgeBackgroundColor( { color: '#58a5b3' } ) // if we are using signers mode, update our active address representing to signers address if (globalThis.interceptor.settings.useSignersAddressAsActiveAddress || globalThis.interceptor.settings.simulationMode === false) { diff --git a/extension/app/ts/background/backgroundUtils.ts b/extension/app/ts/background/backgroundUtils.ts index 0a0a7de8..066dcdf9 100644 --- a/extension/app/ts/background/backgroundUtils.ts +++ b/extension/app/ts/background/backgroundUtils.ts @@ -40,8 +40,32 @@ export function createInternalMessageListener(handler: (message: WindowMessage) type HTMLFile = 'popup' | 'addressBook' | 'changeChain' | 'confirmTransaction' | 'interceptorAccess' | 'personalSign' export function getHtmlFile(file: HTMLFile) { const manifest = browser.runtime.getManifest() - if (manifest.version === '2') { + if (manifest.manifest_version === 2) { return `html/${ file }.html` } return `html3/${ file }V3.html` } + +export async function setExtensionIcon(details: browser.action._SetIconDetails) { + const manifest = browser.runtime.getManifest() + if (manifest.manifest_version === 2) { + return browser.browserAction.setIcon(details) + } + return browser.action.setIcon(details) +} + +export async function setExtensionBadgeText(details: browser.browserAction._SetBadgeTextDetails) { + const manifest = browser.runtime.getManifest() + if (manifest.manifest_version === 2) { + return browser.browserAction.setBadgeText(details) + } + return browser.action.setBadgeText(details) +} + +export async function setExtensionBadgeBackgroundColor(details: browser.action._SetBadgeBackgroundColorDetails) { + const manifest = browser.runtime.getManifest() + if (manifest.manifest_version === 2) { + return browser.browserAction.setBadgeBackgroundColor(details) + } + return browser.action.setBadgeBackgroundColor(details) +} diff --git a/extension/app/ts/background/iconHandler.ts b/extension/app/ts/background/iconHandler.ts index e91cee52..0e592af6 100644 --- a/extension/app/ts/background/iconHandler.ts +++ b/extension/app/ts/background/iconHandler.ts @@ -1,18 +1,18 @@ import { getSignerName } from '../components/subcomponents/signers.js' import { ICON_ACCESS_DENIED, ICON_NOT_ACTIVE, ICON_SIGNING, ICON_SIGNING_NOT_SUPPORTED, ICON_SIMULATING, isSupportedChain } from '../utils/constants.js' import { getActiveAddressForDomain, hasAccess, hasAddressAccess } from './accessManagement.js' -import { getActiveAddress, sendPopupMessageToOpenWindows } from './backgroundUtils.js' +import { getActiveAddress, sendPopupMessageToOpenWindows, setExtensionBadgeText, setExtensionIcon } from './backgroundUtils.js' import { getAddressMetaData } from './metadataUtils.js' import { imageToUri } from '../utils/imageToUri.js' import { Future } from '../utils/future.js' -function setInterceptorIcon(tabId: number, icon: string, iconReason: string) { +async function setInterceptorIcon(tabId: number, icon: string, iconReason: string) { globalThis.interceptor.websiteTabConnection.set(tabId, { icon: icon, iconReason: iconReason }) sendPopupMessageToOpenWindows({ method: 'popup_websiteIconChanged' }) - return browser.action.setIcon({ + return await setExtensionIcon({ path: { 128: icon }, tabId: tabId }) @@ -47,7 +47,7 @@ export function updateExtensionIcon(port: browser.runtime.Port) { export async function updateExtensionBadge() { if (!globalThis.interceptor.settings) return const count = globalThis.interceptor.settings.pendingAccessRequests.length - return await browser.action.setBadgeText( { text: count === 0 ? '' : count.toString() } ) + return await setExtensionBadgeText( { text: count === 0 ? '' : count.toString() } ) } export async function retrieveWebsiteDetails(port: browser.runtime.Port, websiteOrigin: string) {