Send asks for the host permission after an await and before saving: refused on Firefox, and nothing is kept #22

Closed
opened 2026-10-01 10:47:17 +00:00 by tiagoagueda · 0 comments
Owner

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 call permissions.request. Firefox accepts permissions.request only while it is still handling the click, and that ends at the first await; the options page knows this ("Firefox insists on this", src/options.js:79-82) and calls requestHostPermission as its first await. In the popup the rejection comes before save("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.

  • Where:
    • src/popup.js:150-158, the Send handler: if (!(await hasHostPermission(pattern))) { say(t("allowing")); await requestHostPermission(pattern); }, then const 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, before savePicked("waiting").
    • src/captures.js:40-57, allowFromClick() and send(): the same await before the request, and the records are marked waiting only afterwards.
    • src/captures.js:97, :104 and :191-196: button(t("tryNow"), () => send([record.id]), true), Send for review and Send everything call send() with no catch.
    • src/lib/i18n.js:55-63, explain(): a plain Error is shown by its message, untranslated.
  • What happens: on Firefox, a person who refused the permission when saving the settings, or withdrew it later on the add-on's Permissions page (a state that postulo/postulo-firefox#3 and #4 in this repository plan for), captures and corrects a posting and presses Send for review. Instead of being asked, they see Firefox's "permissions.request may only be called from a user input handler", and the capture exists only in the open popup; if it closes, the corrections are gone. On Captures in this browser, Try now and Send do nothing and the records stay as they were. Separately, in any browser, saving after the prompt means a popup that closes while the prompt is up loses the capture for the same reason.
  • Why it matters: Send is the one place, apart from the settings, where the extension can win the permission back, and postulo/postulo-firefox#3 assumes "Send, Save and Test already ask from their click"; for Send this does not hold. A reviewed capture can be lost.
  • Fix: in each handler, start requestHostPermission(pattern) synchronously, before any await and with no contains() before it (requesting an origin already granted resolves true without a prompt), and start save("waiting") (or savePicked, or the store.update loop) 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's send() in try/catch and report through say(explain(error), true), and give a refused request a translated sentence of its own.

Done when

  • A test with a stand-in permissions object that rejects any request made after another awaited call shows that Send calls request before any other await and stores the capture as waiting even when the request is refused (the click handlers need moving into a testable function in src/lib/; nothing tests popup.js today).
  • Manually on Firefox 140 with the origin withdrawn: Send for review shows the permission prompt; refusing it leaves the capture listed as waiting.
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 call `permissions.request`. Firefox accepts `permissions.request` only while it is still handling the click, and that ends at the first `await`; the options page knows this ("Firefox insists on this", `src/options.js:79-82`) and calls `requestHostPermission` as its first await. In the popup the rejection comes before `save("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. - **Where:** - `src/popup.js:150-158`, the Send handler: `if (!(await hasHostPermission(pattern))) { say(t("allowing")); await requestHostPermission(pattern); }`, then `const 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, before `savePicked("waiting")`. - `src/captures.js:40-57`, `allowFromClick()` and `send()`: the same `await` before the request, and the records are marked `waiting` only afterwards. - `src/captures.js:97`, `:104` and `:191-196`: `button(t("tryNow"), () => send([record.id]), true)`, Send for review and Send everything call `send()` with no `catch`. - `src/lib/i18n.js:55-63`, `explain()`: a plain `Error` is shown by its `message`, untranslated. - **What happens:** on Firefox, a person who refused the permission when saving the settings, or withdrew it later on the add-on's Permissions page (a state that postulo/postulo-firefox#3 and #4 in this repository plan for), captures and corrects a posting and presses Send for review. Instead of being asked, they see Firefox's "permissions.request may only be called from a user input handler", and the capture exists only in the open popup; if it closes, the corrections are gone. On Captures in this browser, Try now and Send do nothing and the records stay as they were. Separately, in any browser, saving after the prompt means a popup that closes while the prompt is up loses the capture for the same reason. - **Why it matters:** Send is the one place, apart from the settings, where the extension can win the permission back, and postulo/postulo-firefox#3 assumes "Send, Save and Test already ask from their click"; for Send this does not hold. A reviewed capture can be lost. - **Fix:** in each handler, start `requestHostPermission(pattern)` synchronously, before any `await` and with no `contains()` before it (requesting an origin already granted resolves `true` without a prompt), and start `save("waiting")` (or `savePicked`, or the `store.update` loop) 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's `send()` in `try`/`catch` and report through `say(explain(error), true)`, and give a refused request a translated sentence of its own. ## Done when - A test with a stand-in `permissions` object that rejects any `request` made after another awaited call shows that Send calls `request` before any other await and stores the capture as `waiting` even when the request is refused (the click handlers need moving into a testable function in `src/lib/`; nothing tests `popup.js` today). - Manually on Firefox 140 with the origin withdrawn: Send for review shows the permission prompt; refusing it leaves the capture listed as waiting.
tiagoagueda added this to the 0.6.0 milestone 2026-10-01 10:47:17 +00:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
Postulo/postulo-chromium#22
No description provided.