How to ask `browser.permissions.request` from content_script?

I’m developing an extension that should synchronize data between two third-party websites (the user performs actions on one website, and a report on these actions is sent to the other website).

I would like to insert the widget into the interface of the first website. I do this by content_script.

I have added the necessary URLs to the host_permissions. But they are disabled by default. Okay. But when the user clicks the “Synchronise” button, I need to ask him for this permission to access this URL.

How do I do this? I can’t call browser.permissions.request in the content_script. I tried sending a message to the background script when user click button and requesting permissions from there, but I get an error: permissions.request may only be called from a user input handler

So, what should I do?

1 Like

This sounds like the new MV3 restriction :slight_smile:.

Here are some workarounds I can think of:

  1. downgrade to MV2 - seriously, there is like 0 advantages of using MV3 in Firefox right now :slight_smile:

  2. send message to background script that will open new tab or modal window with a UI explaining why you need a new permission and then a huge button “Request permission” that user clicks.

  3. make it mandatory - in the background script check if the permission is missing and if yes, open new tab where you explain why you need it. This will then fire when the addon is installed (as a part of onboarding process) and also whenever user wants to use it.

And that’s about that. I’ve been dealing with this in Safari not long ago and I ended up with telling user to open the popup where I showed a button to request the permission.

Also, note that you can’t use browser.browserAction.openPopup() from the content script and you can’t call it from background script either. Maybe in the future though.

What doesn’t work

  1. Create an HTML page with an “Ask for optional permission” button that calls browser.permissions.request
  2. Put the HTML page inside your extension.
  3. Insert an iFrame into the first website, and make this iFrame point to the HTML page.

Clicking the button causes a “TypeError: browser.permissions is undefined”.

The HTML page wasn’t opened with windows.create() or tabs.create(), so it doesn’t count as an extension page.
And only extension pages “get access to the same privileged JavaScript APIs that are available to your extension’s background scripts.”

Also related to your question

Extension UI surface (browserAction, pageAction, sidebar) cannot be opened from non-extension pages
(especially comment 12)

What I would do

  1. Create an extension without a popup.
  2. When the user clicks on the extension action, call browser.permissions.request
  3. Insert instructions into the website: “Click the browser action to get the optional permissions. The browser actions looks like this…”
  4. But if the user hasn’t pinned the browser action, the instructions might just confuse him.
1 Like

I was also trying the trick with iframe and I was shocked it doesn’t work! :smiley:
Actually, I’m still not sure why, since other (normally restricted) API will be accessible, right?

In the iFrame, console.log(browser); prints:

Object {
    menus: Getter & Setter
    manifest: Getter & Setter
    normandyAddonStudy: Getter & Setter
    extension: Getter & Setter
    i18n: Getter & Setter
    runtime: Getter & Setter
    storage: Getter & Setter
    test: Getter & Setter
    userScripts: Getter & Setter
}

These are the WebExtension APIs available to content scripts.

Makes sense, because I created the iFrame in a content script.