Merge branch 'main' into fix/low-severity-security
All checks were successful
check / check (push) Successful in 22s

This commit is contained in:
2026-02-27 23:18:53 +01:00

View File

@@ -93,11 +93,13 @@ function resetPopupUrl() {
} }
} }
// Fallback: open approval in a separate window (used when openPopup is unavailable) // Open approval in a separate popup window.
// This is the primary mechanism for tx/sign approvals (triggered programmatically,
// not from a user gesture) and the fallback for site-connection approvals.
function openApprovalWindow(id) { function openApprovalWindow(id) {
const popupUrl = runtime.getURL("src/popup/index.html?approval=" + id); const popupUrl = runtime.getURL("src/popup/index.html?approval=" + id);
const popupWidth = 400; const popupWidth = 360;
const popupHeight = 500; const popupHeight = 600;
windowsApi.getLastFocused((currentWin) => { windowsApi.getLastFocused((currentWin) => {
const opts = { const opts = {
@@ -148,7 +150,9 @@ function requestApproval(origin, hostname) {
} }
// Open a tx-approval popup and return a promise that resolves with txHash or error. // Open a tx-approval popup and return a promise that resolves with txHash or error.
// Uses the toolbar popup only — no fallback window. // Uses windows.create() directly because tx approvals are triggered programmatically
// (from a dApp RPC call), not from a user gesture, so action.openPopup() is
// unreliable in this context.
function requestTxApproval(origin, hostname, txParams) { function requestTxApproval(origin, hostname, txParams) {
return new Promise((resolve) => { return new Promise((resolve) => {
const id = crypto.randomUUID(); const id = crypto.randomUUID();
@@ -160,27 +164,14 @@ function requestTxApproval(origin, hostname, txParams) {
type: "tx", type: "tx",
}; };
if (actionApi && typeof actionApi.setPopup === "function") { openApprovalWindow(id);
actionApi.setPopup({
popup: "src/popup/index.html?approval=" + id,
});
}
if (actionApi && typeof actionApi.openPopup === "function") {
try {
const result = actionApi.openPopup();
if (result && typeof result.catch === "function") {
result.catch(() => {});
}
} catch {
// openPopup unsupported — user clicks toolbar icon
}
}
}); });
} }
// Open a sign-approval popup and return a promise that resolves with { signature } or { error }. // Open a sign-approval popup and return a promise that resolves with { signature } or { error }.
// Uses the toolbar popup only — no fallback window. If openPopup() fails the // Uses windows.create() directly because sign approvals are triggered programmatically
// popup URL is still set, so the user can click the toolbar icon to respond. // (from a dApp RPC call), not from a user gesture, so action.openPopup() is
// unreliable in this context.
function requestSignApproval(origin, hostname, signParams) { function requestSignApproval(origin, hostname, signParams) {
return new Promise((resolve) => { return new Promise((resolve) => {
const id = crypto.randomUUID(); const id = crypto.randomUUID();
@@ -192,27 +183,14 @@ function requestSignApproval(origin, hostname, signParams) {
type: "sign", type: "sign",
}; };
if (actionApi && typeof actionApi.setPopup === "function") { openApprovalWindow(id);
actionApi.setPopup({
popup: "src/popup/index.html?approval=" + id,
});
}
if (actionApi && typeof actionApi.openPopup === "function") {
try {
const result = actionApi.openPopup();
if (result && typeof result.catch === "function") {
result.catch(() => {});
}
} catch {
// openPopup unsupported — user clicks toolbar icon
}
}
}); });
} }
// Detect when an approval popup (browser-action) closes without a response. // Detect when an approval popup (browser-action) closes without a response.
// TX and sign approvals are NOT auto-rejected on disconnect because toolbar // TX and sign approvals now use windows.create() and are handled by the
// popups naturally close on focus loss and the user can reopen them. // windowsApi.onRemoved listener below, but we still handle site-connection
// approval disconnects here.
runtime.onConnect.addListener((port) => { runtime.onConnect.addListener((port) => {
if (port.name.startsWith("approval:")) { if (port.name.startsWith("approval:")) {
const id = port.name.split(":")[1]; const id = port.name.split(":")[1];