harden: list and end site connections made without Remember in Settings (closes #406)
check / check (push) Successful in 2m25s
e2e / e2e-chrome (push) Successful in 3m15s
e2e / e2e-firefox (push) Successful in 2m21s

A site allowed without "Remember" lives only in the background's
in-memory connectedSites map. Settings never listed it, and
AUTISTMASK_REMOVE_SITE, sent on every remove, did nothing, so the user
could not end such a connection.

Settings now asks the background for those sites and lists them under
Connected Sites. Removing a site from Allowed Sites or Connected Sites
drops its remembered entry under every address and sends
AUTISTMASK_REMOVE_SITE with the hostname; the background deletes every
matching connectedSites entry and sends accountsChanged with an empty
list to the site's tabs. Only the extension's own pages may send either
message.

Model: opus-5-5
This commit was merged in pull request #419.
This commit is contained in:
2026-10-04 06:41:39 +02:00
parent 5f54fcbb24
commit 49a7da87e8
6 changed files with 308 additions and 39 deletions
+41 -1
View File
@@ -1110,6 +1110,24 @@ async function broadcastAccountsChanged() {
}
}
// Tell every open tab of a site Settings removed that it has no account.
async function broadcastSiteRemoved(hostname) {
let tabs;
try {
tabs = await tabsQuery({});
} catch {
return;
}
for (const tab of tabs) {
if (!tab.url || extractHostname(tab.url) !== hostname) continue;
tabsSendMessage(tab.id, {
type: "AUTISTMASK_EVENT",
eventName: "accountsChanged",
data: [],
}).catch(() => {});
}
}
// Background balance refresh: every 60 seconds when the popup isn't open.
// When the popup IS open, its 10-second interval keeps lastBalanceRefresh
// fresh, so this naturally skips.
@@ -1306,6 +1324,8 @@ runtime.onMessage.addListener((msg, sender, sendResponse) => {
"AUTISTMASK_TX_RESPONSE",
"AUTISTMASK_SIGN_RESPONSE",
"AUTISTMASK_ADDRESSES_REMOVED",
"AUTISTMASK_GET_CONNECTED_SITES",
"AUTISTMASK_REMOVE_SITE",
];
if (POPUP_ONLY_TYPES.includes(msg.type) && !isExtensionSender(sender)) {
sendResponse({ error: "Unauthorized sender" });
@@ -1662,8 +1682,28 @@ runtime.onMessage.addListener((msg, sender, sendResponse) => {
return false;
}
// Settings lists the sites connected without "Remember", which only this
// worker knows. The origin is what precedes the key's last colon.
if (msg.type === "AUTISTMASK_GET_CONNECTED_SITES") {
sendResponse(
Object.keys(connectedSites).map((key) =>
extractHostname(key.slice(0, key.lastIndexOf(":"))),
),
);
return false;
}
// Settings removed this site and has already dropped its remembered
// entries. Its connections approved without "Remember" end here, under
// every address, and its open tabs are told it has no account.
if (msg.type === "AUTISTMASK_REMOVE_SITE") {
// Popup already saved state; nothing else needed
for (const key of Object.keys(connectedSites)) {
const origin = key.slice(0, key.lastIndexOf(":"));
if (extractHostname(origin) === msg.hostname) {
delete connectedSites[key];
}
}
broadcastSiteRemoved(msg.hostname);
return false;
}
});