diff --git a/main.js b/main.js index 0772bbda..ec853ec1 100644 --- a/main.js +++ b/main.js @@ -2620,10 +2620,14 @@ function initAddons() { if (t.addonId !== addonId) continue; try { t.view?.webContents?.send("addon-event", msg, payload); } catch {} } - if (leftPanel && leftPanelLoadedId && leftPanelLoadedId.startsWith(addonId + ":")) { + // Delivered by what the view has actually loaded, not only by which + // panel was last selected — an add-on's state (addresses, balances) + // must never reach a document that is not that add-on's. + if (leftPanel && leftPanelLoadedId && leftPanelLoadedId.startsWith(addonId + ":") && addonIdForSender(leftPanel.webContents) === addonId) { try { leftPanel.webContents.send("addon-event", msg, payload); } catch {} } if (!sidebar || !sidebarActivePanelId || !sidebarActivePanelId.startsWith(addonId + ":")) return; + if (addonIdForSender(sidebar.webContents) !== addonId) return; try { sidebar.webContents.send("addon-event", msg, payload); } catch {} }, hostRequire: (name) => require(name), @@ -2959,6 +2963,22 @@ function initAddons() { // Given a webContents sender URL, work out which add-on folder it lives in. // Used to gate storage IPC — a page hosted inside addons// can only touch // its own store. +// Add-on panels carry sidebar-preload. A link in a panel used to navigate +// the panel itself to a remote page (keeping that preload), and window.open +// made a bare BrowserWindow with it. Web links open as tabs instead, and a +// panel never leaves file://. +function lockPanelView(view) { + view.webContents.setWindowOpenHandler(({ url }) => { + if (url && /^(?:https?|bns):/i.test(url)) createTab(url); + return { action: "deny" }; + }); + view.webContents.on("will-navigate", (e) => { + const url = String(e.url || ""); + if (/^file:/i.test(url)) return; + e.preventDefault(); + if (/^(?:https?|bns):/i.test(url)) createTab(url); + }); +} function addonIdForSender(sender) { try { const u = new URL(sender.getURL()); @@ -4400,6 +4420,7 @@ function createWindow() { // panel loaded into this view (Aegis, Screenshot, etc.) picks up the // brand scrollbar the moment its DOM is ready. sidebar = new WebContentsView({ webPreferences: { preload: path.join(__dirname, "sidebar-preload.js") } }); + lockPanelView(sidebar); win.contentView.addChildView(sidebar); styleScrollbars(sidebar.webContents); sidebar.setVisible(false); @@ -4433,10 +4454,7 @@ function createWindow() { quickPanel.setVisible(false); // Left add-on panels: same preload and IPC surface as the right sidebar. leftPanel = new WebContentsView({ webPreferences: { preload: path.join(__dirname, "sidebar-preload.js") } }); - leftPanel.webContents.setWindowOpenHandler(({ url }) => { - if (url && /^(?:https?|bns):/i.test(url)) createTab(url); - return { action: "deny" }; - }); + lockPanelView(leftPanel); try { leftPanel.setBackgroundColor(nativeTheme.shouldUseDarkColors ? "#0b0e14" : "#ffffff"); } catch {} win.contentView.addChildView(leftPanel); styleScrollbars(leftPanel.webContents);