<all_urls> doesn't grant access to all urls upon installation

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.

However at this time, trying to read image data from arbitary website will result in a SecurityError: The operation is insecure..

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.

1 Like

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 :tada:

(and it was actually me who requested that :smiley: )

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 :smiley: , 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…

1 Like

Hi, thanks for answering my question.

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.

Thank you again for taking the time to help me.

1 Like

That is surprising. I banged my head against this for a while, but couldn’t find a good reason for this behavior. I just opened bug 1957794 to investigate.

It’s also worth noting that this issue does not present in Manifest V2 extensions. My best guess is that this bug is directly related to (temproarily) reintroducing support for granting host permissions at installation time (see 1889402, but that’s just a guess.

I’m all for guiding devs towards activeTab, but that approach doesn’t work well in cases like this because the image may be on a different origin than the page the user is interacting with. activeTab only grants temporary host permissions for that page, not it’s sub-resources, so the extension would still encounter CORS issues when trying to access a cross-origin ImageData in the popup.

I’m a bit confused, I though he is using the captureVisibleTab to scan the image on the page. Because you don’t need to download the image, you only need it’s position on the page - which you can get with getBoundingClientRect. And this feels 100% better than asking for all_urls permission.

That’s one of the techniques being used. It’s specifically used to capture a region of the screen that’s selected by the user.

Another thing the extension does is let the user right click on an image and select “scan image for QR code” Ifrom the context menu. This works directly on an img tag’s src attribute. Arguably just capturing a screenshot of the page isn’t sufficient as the page may contain multiple QR codes, the code may not be fully visible, the lib may not be able to identify QR codes if there’s too much other content in the image, etc.

1 Like