19

I would liked to detect whether or not microphone permissions have been granted on my site when it loads without actually running something like the following:

navigator.webkitGetUserMedia({audio: active}, 
    function(){alert('worked')}, 
    function(){alert('failed')});

Is there a simple API to detect whether the user has permanently granted microphone access to my application (which runs over https)?

E T
  • 311
  • 1
  • 4
  • 12

4 Answers4

30

Update

microphone has been added to the Permission API even if it's not yet available on Safari nor Internet Explorer.

You could hope that it would be accessible from the permission api, but it isn't :(

Perhaps in the feature this could work like the rest of this:

navigator.permissions.query(
    // { name: 'camera' }
    { name: 'microphone' }
    // { name: 'geolocation' }
    // { name: 'notifications' } 
    // { name: 'midi', sysex: false }
    // { name: 'midi', sysex: true }
    // { name: 'push', userVisibleOnly: true }
    // { name: 'push' } // without userVisibleOnly isn't supported in chrome M45, yet
).then(function(permissionStatus){

    console.log(permissionStatus.state); // granted, denied, prompt

    permissionStatus.onchange = function(){
        console.log("Permission changed to " + this.state);
    }

})

Old answer

The only way i see it possible is if you keep track of this yourself with a key/value item in localStorage when you ask for permission.

Unfortunately it doesn't notify you when it has been changed

// initialization
if( localStorage.getItem('voice_access') === null ){
    // just assume it is prompt
    localStorage.setItem('voice_access', 'prompt');
}

// Then somewhere
navigator.getUserMedia({ audio: true }, function (e) {
    // http://stackoverflow.com/q/15993581/1008999
    //
    // In chrome, If your app is running from SSL (https://),
    // this permission will be persistent.
    // That is, users won't have to grant/deny access every time.
    localStorage.setItem("voice_access", "granted");

}, function (err) {
    if (err.name === 'PermissionDismissedError') {
        localStorage.setItem('voice_access', 'prompt')
    }
    if (err.name === 'PermissionDeniedError') {
        localStorage.setItem('voice_access', 'denied')
    }
})

You could go the extra mile and build a nice little wrapper with this code above and extend/replace the permission api to handle more enum names and create a broadcast api to tell the other tabs when it changes. but why make it so complicated...? The localStorage can't be 100% trusted. it can be changed anywhere any time both with permission and storage cleared

Jorgu
  • 137
  • 1
  • 11
Endless
  • 34,080
  • 13
  • 108
  • 131
  • The above mentioned first snipet is not working for audio as you have pointed. But is there anyway we can find its status as of the location status? – Atchyut Nagabhairava Sep 06 '16 at 10:03
  • 2
    Very useful @Endless. `navigator.permissions.query({name: 'microphone'}).then(...)` and `navigator.permissions.query({name: 'camera'}).then(...)` are now available in Chrome as of now ( >= 69) and return states in `granted`, `denied`, `prompt` Thanks! – Philippe Sultan Oct 08 '18 at 11:13
  • I recommend to use old answer, `permissions` API only checks the browser permission. However, there is a SYSTEM PERMISSION for microphone. (you can find it on `Privacy Setting / App Permissions / Microphone). The old answer also works with system permission. – mharti Jul 13 '21 at 05:54
1

you already got the polling method for checking permissions. here is some information from MDN: https://developer.mozilla.org/en-US/docs/Web/API/Navigator.getUserMedia

and some more: https://developer.mozilla.org/en-US/docs/WebRTC

here is an example:

navigator.getMedia (
// 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) {
    console.log("The following error occured: " + err);
   }

);
Zezura
  • 128
  • 1
  • 9
  • 1
    He is asking how to get the permission state, this means without getting a user media stream – Endless Sep 21 '15 at 23:53
  • You could create the media stream outside of the screen area, then you have your check and the user doesn't know/mind. Just like a back buffer canvas for a html5 game. – Zezura Sep 22 '15 at 20:50
1

navigator.getUserMedia is now obsolete, replaced by MediaDevices.getUserMedia, which returns a promise. If the promise gets rejected you get an DOMException with indication of the problem. Insufficient permissions is one of the options there.

Details here: https://developer.mozilla.org/en-US/docs/Web/API/MediaDevices/getUserMedia

asiop
  • 707
  • 4
  • 11
0

I guess this would be helpful:

function isMicrophoneAllowed(){
    navigator.permissions.query({
        name: 'microphone'
    }).then(function(permissionStatus){
        return permissionStatus.state !== 'denied';
    });
}