One-time permissions are here to stay!
One-time camera and microphone permissions are now in Chrome (since M116), joining Firefox and Safari. This means that per-session permissions are now available to use cross-browser. Chrome calls the option “Allow this time”, where “this time” (as in “one-time”) refers to the scope of the grant, which the browser forgets once the user closes the page. This is the default in Firefox and Safari.
This gives users more control over their privacy, and forces sites to work without persistent permission. We’ll explore where old patterns break and how to build device selection that works for everyone.
Why do browsers offer one-time permissions?
Users might not be comfortable making long-term decisions about a website’s permissions.
For camera and microphone, the risk of untimely recording is of particular concern: For backwards compatibility, navigator.mediaDevices.getUserMedia()
doesn’t require transient activation. This means open tabs might turn on the camera or microphone at any time. Invasive or malicious applications can abuse this.
Users might not even trust legitimate websites with this decision, for fear of confusion over when people can and can’t see them. They might feel better knowing recording cannot commence without the push of a button.
More browsers now support one-time permission than support persistent permission. So it seems time for applications to design for them.
Why do websites need to care? (The web model)
Many users assume configuration and selection of their cameras and microphones is handled by browsers. They don’t realize how much of this experience websites control. Web developers are faced with navigating several browser differences:
Browser | Permission models | Devices granted | Devices enumerable |
---|---|---|---|
Firefox | one-time & persisted | per-device & all of a kind | after use |
Chrome | one-time & persisted | all of a kind | after permission (not to spec) |
Safari | one-time only | all of a kind | after use |
In hindsight, this may have been a mistake. As Uncle Ben would say, “with great power comes great responsibility“. So it might be good to review how websites are faring in this area.
Goodbye persistent permission mindset
This anti-pattern of the past worked in only one browser, where not having persistent permission was a tell that someone was a first-time user. In a nutshell, the mindset was: divert users without persisted permission to a separate priming page, and the main application needn’t bother with permission at all. A major simplification.
This was never interoperable, yet influenced early web design. Web developers were given the navigator.permissions.query()
API to navigate implementation-defined behavior to help escalate permission.
Users who didn’t (or couldn’t) persist permission were stuck in a “slow lane”, treated as first-time users every meeting. They were lucky if the website remembered their devices or let them choose at all. Some websites didn’t even work.
This mindset no longer fits any browser, so hopefully we’ve seen the last of it.
Designing for all users
With Chrome M116, users can easily reset permissions from the URL bar in all modern browsers. This renders priming anti-patterns of the past obsolete.
Less is more. Don’t grill users for permission, and don’t expect it to stay from a previous visit. Simply let the browser ask for it at point-of-use, and you’ll be fine and interoperable!
The hardest remaining part is device selection, which is the focus of the remainder of this post.
Selecting camera / mic — with privacy
Websites—not browsers—build the picker UI (don’t ask). They call navigator.mediaDevices.enumerateDevices()
to fill the UI, but exposing every device up-front would hand trackers a stable fingerprint.
So the rule today is: use first, list later. A page must call getUserMedia()
before it can list devices.
In contrast, early spec drafts let sites enumerate devices on return visits if the user had once granted access. But this form of persistence was hostile to privacy—trackers still try it on 8% of page loads.
So in 2020 the W3C Privacy Interest Group closed the loophole, and browsers agreed to block enumeration until after use of camera or microphone.
One engine still ignores this (crbug 40138537), tempting sites to ship workflows that rely on persistence between visits. Backwards compatibility with websites that were never interoperable in the first place, is somehow holding up progress. That seems backwards.
So if you happen to work on one of these websites, we’re here to help! Here are some ideas for making device selection work with one-time permissions (with interoperability as a bonus)!
Simple selection: Make it secondary
Most users have just one microphone and one front-facing camera. So the most obvious solution is to put selection under ⚙️ settings:
- Remember what camera and microphone they used last time
- Open the user’s camera and microphone first
- Direct the user to a ⚙️ Settings page to change camera or microphone
A benefit of this model is the user sees the result instantly.
Advanced selection: without permission
More websites are letting users into meetings without requiring permission upfront. We support this trend, as it is great for user privacy!
But some of them also offer device selection directly in the room. How can they do both? We’ll cover some strategies:
- remember choices — recall the user’s device choices from last time from
localStorage
- cache the device list — copy the device list to localStorage (it doesn’t change that often)
- call gUM — don’t be afraid to call
getUserMedia
to refresh a selector the user interacts with
Here’s a demo of 1 and 2:
If it’s your first time here, you might see “Camera 1” and “Microphone 1” listed until you turn on camera and microphone. This is for privacy reasons. But once you’ve done this once, the webpage caches your choices and device list from last time. You’ll see informative device labels from then on.
This should work well for most people who don’t switch out devices a lot. And if you don’t see your devices listed, turn on any camera or microphone to update the list. Best of all, it works across browsers and permission choices!
Feel free to look at the source. It follows best practices for things like extracting selected deviceId
s (Firefox users will thank you), and using {exact}
constraints sparingly to allow fallback for removed devices.
If you end up needing to write your own, make sure to try it out in all major browsers. Interactive device selection can be tricky. There’s a lot of state to keep track of!
Long-term solutions and future improvements
Work in standardization and implementations continues to improve this experience further. The challenge is balancing user experience with privacy and interoperability. Here are some recent improvements made to the spec:
- Extend device exposure to camera if microphone is in use and vice versa #1038
- Set device information exposure to true once permission is granted even if capture fails #1039
Other improvements are still being discussed:
- Should enumerateDevices exposure survive same origin navigation? #1043
There are also promising discussions about PEPC (Page-Embedded Permission Control), that may someday put native <camera>
and <microphone>
mute-toggles into the browsers. Once we have those, it’s easy to imagine a device selection drop-list hanging off of them. This would put device selection back in the browser, and put the horse back in front of the cart!
But it is still early days here. I hope the demo and suggestions are helpful right away. And stay tuned for updates on this! Any questions? Ask me on X.