Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

reprompt for permissions with getUserMedia() after initial denial

How do we go about requesting camera/microphone access with getUserMedia() after being denied once?

I'm working with getUserMedia to access the user's camera and pipe the data to a canvas. That bit all works fine.

In testing, I hit deny once. At this point in Chrome and Firefox, any subsequent requests with getUserMedia() default to the denied state.

We obviously don't want to annoy the hell out of our users by requesting permissions for camera/microphone on every page load after being denied. That's already annoying enough with the geolocation api.

However, there has to be a way to request it again. Simply because a user hit deny once doesn't mean they want to deny webcam access for all time.

I've been reading about the spec and googling around for a while but I'm not finding anything explicitly about this problem.

Edit: Further research, it appears that hitting Deny in Chrome adds the current site to a block list. This can be manually accessed via chrome://settings/content. Scroll to Media. Manage Exceptions, remove the blocked site(s).

Linking to chrome://settings/content doesn't work (in the case where we want to add a helpful link to let people re-enable permissions).

The whole UX for dealing with permissions around getUserMedia stinks. =(

like image 530
Geuis Avatar asked Apr 13 '13 22:04

Geuis


2 Answers

jeffreyveon's answer will help reduce the chance that your user will choose deny, since she will only have to choose once.

In case she does click deny, you can provide a message that explains why you need the permission and how to update her choice. For example:

navigator.getUserMedia (    // constraints    {       video: true,       audio: true    },     // successCallback    function(localMediaStream) {       var video = document.querySelector('video');       video.src = window.URL.createObjectURL(localMediaStream);       video.onloadedmetadata = function(e) {          // Do something with the video here.       };    },     // errorCallback    function(err) {     if(err === PERMISSION_DENIED) {       // Explain why you need permission and how to update the permission setting     }    } ); 
like image 150
jrullmann Avatar answered Sep 29 '22 01:09

jrullmann


Chrome implements the Permissions API in navigator.permissions, and that applies to both camera and microphone permissions too.

So as of now, before calling getUserMedia(), you could use this API to query the permission state for your camera and microphone :

 navigator.permissions.query({name: 'microphone'})  .then((permissionObj) => {   console.log(permissionObj.state);  })  .catch((error) => {   console.log('Got error :', error);  })   navigator.permissions.query({name: 'camera'})  .then((permissionObj) => {   console.log(permissionObj.state);  })  .catch((error) => {   console.log('Got error :', error);  }) 

On success, permissionObj.state would return denied, granted or prompt.

Useful SF question/answer here

For a cross browser solution, one simple approach can be to monitor the time difference between when the getUserMedia() Promise is called, and when it is rejected or resolved, like so :

// In the Promise handlers, if Date.now() - now < 500 then we can assume this is a persisted user setting var now = Date.now(); navigator.mediaDevices.getUserMedia({audio: true, video: false}) .then(function(stream) {   console.log('Got stream, time diff :', Date.now() - now); }) .catch(function(err) {   console.log('GUM failed with error, time diff: ', Date.now() - now); }); 

This Medium article gives more details.

Hope this helps!

like image 36
Philippe Sultan Avatar answered Sep 29 '22 02:09

Philippe Sultan