Firefox Extension API - permissions.request may only be called from a user input handler?

て烟熏妆下的殇ゞ 提交于 2019-12-04 19:25:03

Is there a good work-around"

I'd like to add onto Andrew's answer with some code examples.

As it turns out, promise chains destroy the browser's notion of what is and isn't triggered by a user input handler. Take the code below, for example:

document.getElementById('foo').addEventListener('click', event => {
  browser.permissions.request({origins: ["https://google.com/*"]})
})

This code works as expected. I originally assumed that it was Vue.js's unique event handling framework that was eating my "browser events", such as when you do <div @click="somefunc"></div>. This actually works just fine, as long as you put your permissions request in somefunc.

Now it gets fun. If you replace your permissions request with a promise that resolves and then does a permissions request, VIOLA!

Promise.resolve('foobar').then(foobar => {
    browser.permissions.request({origins: ["https://google.com/*"]})
})

Results in:

Error: permissions.request may only be called from a user input handler

Why does this happen?

I'm going to guess it has to do with stack traces. Firefox can't detect that a permission came from a stack with a user input event at the root if the permissions request happens in a promise chain.

I consider this to be a pretty egregious design choice. My app is large (>4K LoC) and to keep it simple I rely on promise chains to keep the spaghetti away. This has crippled my ability to write clean code, and as a result, I've moved from asking for optional_permissions and then prompting the user for permissions only when needed to just being overly permissive at the time of installation.

GG, Firefox.

What counts as a user input handler?

A DOM event handler that corresponds to user input (e.g., target.addEventHandler("click", ...) or a WebExtension event listener that corresponds to user input (e.g., browser.browserAction.onClicked.addListener(...)

Why does it work like this?

Partly for basic UX (if a user is not directly interacting with an extension and a prompt for the extension suddenly prompts up, it can easily confuse them), but also to avoid clickjacking attacks where the prompt is put up at a carefully chosen moment when the user is likely to be expecting some unrelated prompt.

Is there a good work-around?

I think just organizing your code so that you request permissions from a user input handler is probably your best bet.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!