In Firefox 118 or 119 we intend to ship the "camera" and "microphone" permission descriptors in navigator.permissions.query(), with some adaptations for Firefox's permission model.
Summary: await navigator.permissions.query({name: "camera" || "microphone"}) allow websites to query whether the user has granted them camera or microphone permissions in the past, e.g. to streamline joining a meeting.
Since Firefox grants one-time permissions by default, the values returned are as follows:
- "granted" — the user granted persistent or one-time permission last time, and hasn't explicitly revoked it. This positive signal satisfies the spec which says the caller "can use the feature possibly without having
the user agent asking the user's permission".
- "denied" —The user has blocked permission (or the iframe is missing allow= policy)
- "prompt" — Neither of the above apply (this is the initial state)
This is designed to support one-time permissions as the norm. We appreciate the need to pursue "granted" in other browsers without worrying about differences in Firefox, hence this design.
To web developers concerned that "granted" doesn't guarantee unprompted access in Firefox: the Firefox permission prompt is mostly harmless. Users can refresh the page to undo accidental blocks, unless they explicitly checked "✅ Remember this decision" followed by "Block".
We hope this balances applications' concerns with those of users.
We are not implementing the deviceId part [4] which is being removed from the spec. [5]
Bug: https://bugzil.la/1609427Standard:
- https://www.w3.org/TR/permissions/#permissions-interface
- https://www.w3.org/TR/permissions/#dfn-granted
- https://www.w3.org/TR/permissions/#privacy-considerations
- https://www.w3.org/TR/mediacapture-streams/#permissions-integration
- https://github.com/w3c/mediacapture-main/issues/965
Platform Coverage: Desktop atm, but planning to have it on all available platforms.
Preference: This API will be available by default.
One pref, permissions.media.show_always_ask.enabled, may be available to expose the "Always Ask ✖" permission to users more prominently. By default it only shows in Tools / Page Info.
Other Browsers: Other browsers already implement permissions.query() for "camera" and "microphone". Each have different permission models, none of which matches Firefox's.
- Blink: shipped since 43
- Webkit: shipped since 16
Web-platform-tests: WPT tests for permissions.query() with getUserMedia are being provided, but require manual intervention in Firefox due to
https://bugzil.la/1524074:
Privacy Concerns:
We are implementing this now to mitigate websites' upcoming loss of
ability to infer permission from device labels in Firefox once we
restrict device information exposure in enumerateDevices() ahead of
getUserMedia() success (by turning off the pref media.devices.enumerate.legacy.enabled).
But to implement this, Firefox is internally persisting an "always ask" permission after one-time use of camera and microphone (exposed as "granted").
Since permissions are typically treated separately from website data, permissions.query() is a fingerprinting vector [3].
We are considering (still working on) the following mitigations:
- Replace "denied" with "prompt" ahead of getUserMedia() success, like Safari does
- Clear "always ask" whenever website data is cleared
- Don't persist "always ask" if the privacy.resistFingerprinting pref is set
With these mitigations in place, this should leak no new information.