Firefox 扩展 API - permissions.request 只能从用户输入处理程序调用吗?

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

我正在使用 Firefox 权限 API 已记录 HERE

我在使用 request 方法时遇到问题,其中我所有的权限请求导致:

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

您可以通过调试任何插件或扩展并在控制台中输入 browser.permissions.request({origins: ["https://google.com/*"]}) 在 firefox 中生成此文件。

我发现很难接受权限请求必须始终在父堆栈跟踪中具有用户输入事件回调。我正在使用 Vue.js,我的权限是由于用户交互,但我的用户交互与他们触发的事件无关。

What counts as a user input handler?

一个 DOM 对应于用户输入的事件处理程序(例如,target.addEventHandler("click", ...) 或一个对应于用户输入的 WebExtension 事件侦听器(例如,browser.browserAction.onClicked.addListener(...)

Why does it work like this?

部分是为了基本的用户体验(如果用户没有直接与扩展程序交互并且突然出现扩展程序的提示,很容易混淆他们),同时也是为了避免在提示出现的地方进行点击劫持攻击精心选择的时刻,用户可能会期待一些不相关的提示。

Is there a good work-around?

我认为组织代码以便从用户输入处理程序请求权限可能是最好的选择。

Is there a good work-around"

我想用一些代码示例来补充 Andrew 的回答。

事实证明,承诺链破坏了浏览器关于用户输入处理程序触发和不触发的概念。以下面的代码为例:

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

此代码按预期工作。我最初假设是 Vue.js 独特的事件处理框架正在吞噬我的 "browser events",例如当你做 <div @click="somefunc"></div> 时。这实际上工作得很好,只要你把你的权限请求放在 somefunc.

现在变得有趣了。如果您将您的权限请求替换为解决然后执行权限请求的承诺,VIOLA!

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

结果:

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

Why does this happen?

我猜这与堆栈跟踪有关。如果权限请求发生在 promise 链中,Firefox 无法检测到权限来自具有用户输入事件的堆栈。

我认为这是一个非常过分的设计选择。我的应用程序很大(>4K LoC),为了保持简单,我依靠承诺链来避免意大利面条。这削弱了我编写干净代码的能力,因此,我已经从要求 optional_permissions 然后仅在需要时提示用户权限转变为在安装时过于宽容。

GG,火狐。