Hello,
my addon uses a background script which collects information (using webRequest API, so I think I need to use a background script) and it has a browser action which opens a popup. The popup needs to get some info from the background script. For this, the popup script calls runtime.getBackgroundPage
, and this works properly in normal tabs/windows. However, for tabs/windows in private mode, getBackgroundPage
always returns (or more precisely, gets fulfilled with) null
. Is this intended? If so, what would be the right approach for communicating between popup and background script?
Hi,
I am having the same issue. The popup scripts returns null for getBackgroundPage. Please resolve the issue.
To be honest, I donāt really see how this improves the behavior of an extension, but I also donāt think that it will change soon.
what would be the right approach for communicating between popup and background script?
You will have to use this:
Thanks for the reply. So it is intended? Is this documented anywhere? I think it should be. Perhaps their should be separate instances of the background page for private mode?
Now Iām trying to use the runtime.connect approach. Right away I noticed that itās not possible to send arbitrary JS objects, e.g. the object Iām sending contains a Map instance, but this gets silently dropped. The documentation does say that one can only send āJSON objectsā, which I guess means objects which can be completely expressed in JSON.
Chrome can do that, and if you decide to go with a single instance (and the user explicitly enables the extension for incognito) it wonāt load extension tabs in the incognito windows. I havenāt tested panels yet.
I guess means objects which can be completely expressed in JSON.
Exactly that.
A little update on this:
The mozilla sources contain a test case browser/components/extensions/test/browser/browser_ext_incognito_views.js
in which it says: "Should not be able to access background page in incognito context"
.
So this is intended behavior.
On the other hand it does not happen if Firefox starts in the Private-only mode, so there should always be at least one window that can hold tabs that do have access to the background page.
Since Chrome (in spanning mode) wonāt open extension tabs in incognito windows at all (network error), I think it is acceptable to tell the user to open extension pages in a non-private window in Firefox too (or rather, do that automatically).
Especially because there are other problems too, for example blob:
-URLs created in the non-private context wonāt be available in private windows.
Which still leaves the problem which panels in Firefox Private Windows.
What I decided to do is to open a (non-private) poup window at the same spot where the panel would be. Then I manually implement the close-on-blur behavior. The visual difference is quite small and the performance can be acceptable too.
My implementation can be found here:
Hi, new here and trying to understand how this works.
So I have a popup that uses the background pageās variables and functions directly, accessed via runtime.getBackgroundPage
.
But in order for the popup to work in private mode, Iām supposed to have the popup use runtime.connect
to send a JSON message to the background, then background does its jobs, and then sends results in a JSON message back to the popup. Like that?
And does this mean for an extension to support private mode, I should forget about runtime.getBackgroundPage
altogether? Or should I accommodate with both pathways, one for private one for normal?
For what itās worth: In popup.js, I use browser.runtime.sendMessage() to request data I want or to send changes to global vars. In background.js I use browser.runtime.onMessage.addListener() to respond to the requests. I donāt know whether it is better to use browser.runtime.connect().
Example:
- https://github.com/jscher2000/Content-Type-Fixer-extension/blob/master/popup.js
- https://github.com/jscher2000/Content-Type-Fixer-extension/blob/master/background.js#L264
Disclaimer: As you can tell, Iām not a trained programmer.
Hi
I had this exact problem before doing a refactor of my addon.
In my non background page process I do this:
let port = browser.runtime.connect({
name: 'someUniqueName'
})
...
something.addEventListener('change', () => {
...
port.postMessage({
thisCanBeAnyJSONObject: true
})
}
Then in my background process I have this
browser.runtime.onConnect.addListener((port) => {
if (port.name === 'someUniqueName') {
port.onMessage.addListener((msg) => {
// here the `msg` variable holds the JSON we sent from the non background script
// // I just needed to check for a flag, in your case you probably need to deseralise your data
if (msg.thisCanBeAnyJSONObject) {
doSomethingThing()
}
})
}
})
This setup a control flow of user clicks element -> message background page -> background page does something
The advantage of using a Port is you can establish two way communication if you later need to add extra steps such as a control flow of
Non background process -> Background process -> Non background process again
by registering a listener to the port in your non background process as well.
Note the functions for Port based communication with content scripts are different
Hi everyone,
Belated thanks for your responses. I have since refactored and worked with browser.runtime.connect()
to pass data between popup and background.
New question. This message is frequently seen in the addon console:
Unchecked lastError value: Error: Could not establish connection. Receiving end does not exist.
Do I just ignore, or is this a sign to use browser.runtime.sendMessage()
instead? I assume because a popup is too brief an instance, compared to a content script, for connect()
to be appropriate?
That is a sign that youāre trying to connect when the popup isnāt open. You likely want to open the connection from the popupās side.
Yes it was opened from the popupās side.
Reworked my code to use sendMessage
instead, to see if the error will go away. It didnāt. I now suspect itās an error from a different extension (Iām working on this āmanuallyā in my regular Firefox profile, not via web-ext
) so itās really nothing of mine to worry about.
I think sendMessage
seems more appropriate anyway; itās just the popup requesting data from the background a few times within its brief lifetimes. The flow of code is more straightforward too, since response handling can be placed immediately after a request, unlike with connect
.
For anyone else ending up here, Iāll share some helpful info that are all over, found in not-so-intuitive places, and should probably be put into one article somewhere:
Content scripts - Choosing between one-off messages and connection-based messaging
runtime.onMessage