Hi everyone. I’m facing some obstacles trying to fix a bug for my extension QR Lite. Would really appreciate some help.
The related functionality works like this: upon invoking the context menu on an image and choosing “Scan QR Code in Image”, the extension will open the popup and the popup will read the target image (via CanvasRenderingContext2D.getImageData()) and try to decode any QR code in it.
For the extension to be able to read image data from any URL, I’ve declared <all_urls> host permission in manifest.json. After installing the extension, when I go to about:addons to check the extension’s permission settings, I can see Access your data for all websites is turned on. I can also confirm that permissions.contains({ origins: ['<all_urls>'] }) returns true.
Surprisingly, if I turn the Access your data for all websites permission off and on again, or if simply turn it off and let the extension request for it again, the error goes away.
I’ve been trying to find an explanation for this behavior but to no avail. Did I miss something?
Any help would be appreciated.
Why do you even need the all_urls permission? You should avoid using it whenever possible.
People don’t like extensions that can “Access your data for all websites”.
And since the addon is controlled through popup, you can get access to the currently opened page through activeTab permission.
Checking your code:
async function injectPickerLoader (tab) {
// in firefox, the '<all_urls>' permission is required to call captureVisibleTab
// https://bugzilla.mozilla.org/show_bug.cgi?id=1784920
if (typeof apiNs.tabs.captureVisibleTab !== 'function') {
const res = await apiNs.permissions.request({ origins: ['<all_urls>'] })
if (!res) {
throw new Error('Permission not granted')
}
}
Look, you even linked the bugzilla thread that says it’s fixed in 126 version
(and it was actually me who requested that )
Also, your code is a bit wrong - the permissions.request requires user-action, it will never work in the background script or in an async function (unless it’s being called/executed synchronously).
Also, typeof apiNs.tabs.captureVisibleTab !== 'function' won’t work either , the function is there, but calling it without activeTab or all_urls permission will fail.
And lastly, the error SecurityError: The operation is insecure sounds familiar, yet strange. But I’m pretty sure this is not an error you would normally see as result of missing host permissions, that’s for sure. Something else is going on…
I believe you and I talked before on reddit 1 or 2 years ago? You said the same thing about <all_urls> and directed me to that bug report you filed.
Anyway, I think you pointed me to the right direction. I didn’t use CORS when loading the image. According to this page, drawing images loaded without CORS approval on a canvas would taint the canvas, causing getImageData() to fail. I was able to make the error go away by adding crossorigin='anonymous'to the image tag and leave everything else unchanged. Although I’m still not sure why toggling the permission off and on would make it work before.
Regarding the use of the <all_urls> permission. Despite that we can already capture the active page without it, I think I still have to keep it because I have to load the image the user clicked on on the extension’s side via CORS, which will result in a CORS error if the relevant host permission is not granted. Or is there a way around this?
Regarding the piece of code you quoted. You’re completely right. Clearly I wasn’t thinking clearly when I wrote that. Thank you for catching that.