Skip to content

Fix gesture drag-drop dying when the <all_urls> permission is missing#20

Open
QingJ01 wants to merge 1 commit into
mozilla-extensions:developfrom
QingJ01:fix/gesture-permission-sync
Open

Fix gesture drag-drop dying when the <all_urls> permission is missing#20
QingJ01 wants to merge 1 commit into
mozilla-extensions:developfrom
QingJ01:fix/gesture-permission-sync

Conversation

@QingJ01

@QingJ01 QingJ01 commented Jun 16, 2026

Copy link
Copy Markdown

Problem

After a Firefox update, the gesture drag-and-drop feature (drag a link/image to open it in a new tab, drag text to search) silently stops working — no error, drag just does nothing. Other features keep working, which makes it look like a mysterious partial failure.

Root cause

<all_urls> is an optional permission (manifest.json optional_permissions). The gesture content script is registered from bg/gestureDragDrop.js based only on the gesture.enabled storage flag:

browser.storage.local.get({"gesture.enabled": false}).then(data => registerOrUnregisterScript(data["gesture.enabled"]));

But browser.scripting.registerContentScripts({ matches: ["<all_urls>"], ... }) succeeds even when the host permission isn't granted — it just injects into no page, so drag dies silently. After a browser update that reinstalls the system add-on, the optional <all_urls> grant can be reset while gesture.enabled stays true → the script stays "registered" but inert, and drag is dead with no error in the console.

A second desync in options/options.js: when <all_urls> is revoked it only does checkbox.checked = false, which does not fire the change event, so gesture.enabled is never written back to false and the background never unregisters the inert script.

Fix

  • Gate registration on both gesture.enabled and permissions.contains(<all_urls>) via a new isGestureUsable() helper.
  • Centralize through syncScriptRegistration(), called on startup, on storage.local.onChanged, and on permissions.onAdded/permissions.onRemoved — so the script always reflects the real (flag ∧ permission) state.
  • Make registerOrUnregisterScript idempotent (unregister-then-register) so a registration persisted from a previous session is replaced instead of colliding with "already registered".
  • In options.js, write gesture.enabled = false to storage when <all_urls> is revoked, so the flag no longer desyncs from the permission/script state.

Scope / testing

Only extension/bg/gestureDragDrop.js and extension/options/options.js change.

  • npm run lint (eslint plugin:mozilla/recommended) passes.
  • Verified on Firefox 140 ESR (China build) via web-ext run: drag-and-drop works again after the fix.

🤖 Generated with Claude Code

The gesture content script is registered based only on the "gesture.enabled"
storage flag, but <all_urls> is an *optional* permission. registerContentScripts()
succeeds even without the host permission, then injects into no page and drag
silently does nothing. After a browser update reinstalls the system add-on, the
optional <all_urls> grant can be reset while the flag stays true, leaving drag
dead with no error.

- Gate registration on BOTH the flag and permissions.contains(<all_urls>).
- Re-sync registration on permissions.onAdded/onRemoved and storage changes.
- Make registration idempotent (unregister-then-register) so a stale persisted
  registration is replaced instead of colliding with "already registered".
- In options.js, write gesture.enabled=false to storage when <all_urls> is
  revoked, so the flag no longer desyncs from the permission/script state.

Co-Authored-By: Claude <noreply@anthropic.com>
@firefoxci-taskcluster

Copy link
Copy Markdown
No Taskcluster jobs started for this pull request

The allowPullRequests configuration for this repository (in .taskcluster.yml on the default branch) does not allow starting tasks for this pull request.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant