fix: closing a transaction or signature approval window leaves the request pending (closes #673)
check / check (push) Waiting to run
e2e / e2e-chrome (push) Waiting to run
e2e / e2e-firefox (push) Waiting to run

The browser can close the approval window when the user clicks away from it,
for example to copy the password from a password manager. Closing it used to
reject the request with 4001. Now the request stays pending and the site gets
no answer. Until it is answered, the toolbar popup opens the oldest such
approval.

Reject now closes its window only after the background has the rejection. Sent
as the window closed, the rejection could be lost, which the old window-close
rejection hid.

Site-connection and network-switch windows still reject the request when
closed.

Model: opus-5-5
This commit is contained in:
2026-10-26 20:28:33 +00:00
parent c316d9ee78
commit 7c5944b4d1
9 changed files with 540 additions and 146 deletions
+22 -13
View File
@@ -470,7 +470,9 @@ window of its own, and the password is required to be absent from every message
the approval window sends to the background — with the message that would carry
it required to be present, so that check cannot pass by observing nothing. That
last one is the standing floor under
[#157](https://git.eeqj.de/sneak/AutistMask/issues/157).
[#157](https://git.eeqj.de/sneak/AutistMask/issues/157). A transaction or
signature approval whose window is closed is required to leave the page without
an answer. The suite then answers it from the page the toolbar button opens.
The limits of that coverage and of the rest of the Chrome suite, none of them
papered over:
@@ -479,9 +481,10 @@ papered over:
network with real funds; that remains a human pass before 1.0.0.
- The site-connection prompt is raised through `chrome.action.openPopup()`, and
headless Chromium's browser-action popup is not a page Playwright can see or
click, so that one prompt is driven at the URL the extension itself puts on
the action — the same page and the same approval id, but whether a real
toolbar click shows it is not observable here.
click. So that prompt, and an approval reopened after its window closed, are
driven at the URL the extension itself puts on the action — the same page and
the same approval id, but whether a real toolbar click shows it is not
observable here.
- Each site-connection request is made 1.5 seconds after the tab it will be
driven in is opened (`APPROVAL_TAB_SETTLE_MS` in `tests/e2e/run.js`), because
opening that tab closes the previous prompt's toolbar popup; a request made
@@ -604,11 +607,12 @@ It covers popup load, the StateRecovery screen (the same cases as the Chrome
suite), wallet creation through the UI, the Add Token screen, and the dApp round
trips — `eth_requestAccounts`, `personal_sign`, `wallet_switchEthereumChain`
rejected and then approved, `eth_sendTransaction`, and a closed approval window
rejecting with EIP-1193 4001 — driven through the real content script,
background page and approval windows. The popup open all along is required to
show the `[TESTNET]` banner once the switch to Sepolia is approved and to drop
it once the switch back is. The `personal_sign` prompt is also required to fit
its window without scrolling sideways, with the extension's pages at 170% zoom.
that leaves its request pending until it is rejected — driven through the real
content script, background page and approval windows. The popup open all along
is required to show the `[TESTNET]` banner once the switch to Sepolia is
approved and to drop it once the switch back is. The `personal_sign` prompt is
also required to fit its window without scrolling sideways, with the extension's
pages at 170% zoom.
The suite lives in `tests/e2e/firefox/`. Its WebDriver client (`driver.js`) has
**no npm dependencies at all**: it is built on global `fetch` and
@@ -2482,8 +2486,12 @@ view would leave a wallet one click from deletion.
Data Model) → full-sentence error on the error line saying why, nothing
signed (no screen change)
- "Reject" → closes popup (returns rejection to background)
- Popup window closed without answering → the request is rejected with
EIP-1193 code 4001
- Popup window closed without answering → the request stays pending, and the
site gets no answer. The browser can close this window when the user
clicks away from it, for example to copy the password from a password
manager. Until the request is answered, the toolbar button opens this
screen instead of the wallet. With several closed requests waiting, the
toolbar button opens the oldest first.
#### SignApproval (`approve-sign`)
@@ -2569,8 +2577,9 @@ view would leave a wallet one click from deletion.
- "Sign" (wrong password, or a signing failure) → error line, no screen
change
- "Reject" → closes popup (returns rejection to background)
- Popup window closed without answering → the request is rejected with
EIP-1193 code 4001
- Popup window closed without answering → the request stays pending, as on
TxApproval. Until the request is answered, the toolbar button opens this
screen instead of the wallet.
#### NetworkApproval (`approve-network`)