Send asks for the host permission after an await and before saving: refused on Firefox, and nothing is kept #22
Labels
No labels
bug
documentation
enhancement
performance
security
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
Postulo/postulo-chromium#22
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Found on 2026-09-29 in a read-only review of postulo-chromium at
7998de372, comparing how each click handler asks for the instance's origin.When the instance's origin is not granted, the popup's two Send buttons and the captures page first
await hasHostPermission(pattern)and only then callpermissions.request. Firefox acceptspermissions.requestonly while it is still handling the click, and that ends at the firstawait; the options page knows this ("Firefox insists on this",src/options.js:79-82) and callsrequestHostPermissionas its first await. In the popup the rejection comes beforesave("waiting"), so the reviewed capture is not stored and the person is shown Firefox's own English message. On the captures page the rejection is not caught at all, so the button does nothing visible.src/popup.js:150-158, the Send handler:if (!(await hasHostPermission(pattern))) { say(t("allowing")); await requestHostPermission(pattern); }, thenconst record = await save("waiting");. Its comment says "Asked for here, from the click, while the browser still counts it as one".src/popup.js:324-331, the Send handler for ticked postings: the same order, beforesavePicked("waiting").src/captures.js:40-57,allowFromClick()andsend(): the sameawaitbefore the request, and the records are markedwaitingonly afterwards.src/captures.js:97,:104and:191-196:button(t("tryNow"), () => send([record.id]), true), Send for review and Send everything callsend()with nocatch.src/lib/i18n.js:55-63,explain(): a plainErroris shown by itsmessage, untranslated.requestHostPermission(pattern)synchronously, before anyawaitand with nocontains()before it (requesting an origin already granted resolvestruewithout a prompt), and startsave("waiting")(orsavePicked, or thestore.updateloop) in the same tick, without waiting for the prompt; then await both. A refused or interrupted prompt then never costs the capture, and the outbox sends it once the permission exists. Wrap the captures page'ssend()intry/catchand report throughsay(explain(error), true), and give a refused request a translated sentence of its own.Done when
permissionsobject that rejects anyrequestmade after another awaited call shows that Send callsrequestbefore any other await and stores the capture aswaitingeven when the request is refused (the click handlers need moving into a testable function insrc/lib/; nothing testspopup.jstoday).