I'm currently working on a Firefox Add-on that makes use of the Permissions API to request permissions dynamically for specific origins as needed based on the value of a <select>
, as the user changes the value, without having a separate submit button. When I call browser.permissions.request
the promise is rejected immediately with the error:
permissions.request may only be called from a user input handler
The relevant HTML and JS code is below. I'd like to avoid using a separate save button, but I don't know how I could achieve that. Is it possible, and if so, how?
<div id="domain-settings">
Choose your preferred domain:
<select>
<option>example.com</option>
<option>one.example.com</option>
<option>other.example.com</option>
</select>
</form>
const settings = { domain: 'example.com' };
const $select = $('#domain-settings').find('select');
$select.on('change',function(e){
e.stopPropagation();
const oldValue = settings.domain;
const perm = { origins: [ `https://${$select.val()}/` ] };
browser.permissions.contains(perm)
.then(result => {
if (result)
someFunction();
else browser.permissions.request(perm)
.then(granted => {
if (granted)
someFunction();
else $select.val(oldValue);
});
})
})();
A couple days ago I somehow stumbled across this question when I re-discovered this bug in my codebase, not even remembering I posted about it here. That question has an almost identical answer, but in my case the issue was specifically the fact that I was checking for the permission before I tried requesting it, which, as it turns out, is wholly unnecessary.
The same explanation applies here as well. Firefox did not recognize the handler as coming from user input due to being chained in a promise call, which destroys the call stack that it could use to verify this. If a permissions.request
call is chained after any promise it will not pass this validation.
My solution: drop the permissions.contains
check. Now everything works as expected.
const settings = { domain: 'example.com' };
const $select = $('#domain-settings').find('select');
$select.on('change',function(e){
e.stopPropagation();
const oldValue = settings.domain;
const perm = { origins: [ `https://${$select.val()}/` ] };
browser.permissions.request(perm)
.then(granted => {
if (granted)
someFunction();
else $select.val(oldValue);
});
})();
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With