Consider making runtime.connect and runtime.sendMessage wait for background page startup unconditionally

NEW
Unassigned

Status

P2
enhancement
9 months ago
4 months ago

People

(Reporter: bdanforth, Unassigned)

Tracking

Firefox Tracking Flags

(Not tracked)

Details

(Reporter)

Description

9 months ago
When a web extension first installs, there is currently no way to guarantee that the background script loads before a content script.

This means it's possible that a content script tries to make a connection via `browser.runtime.connect` before the `browser.runtime.onConnect` listener in the background script is present.

This race condition happens reliably, for example, when a page is already loaded before the web extension is installed.

The current workaround for this is to listen for the `onDisconnect` event in the content script if/when the connection fails and retry (perhaps after a short pause).

It would be great if we could guarantee the connection/message in this situation is always successful on install, like it is on subsequent startups.

Comment 1

8 months ago
Hi Bianca,
this sounds like Bug 1378459, are you able to reproduce with the the preference extensions.webextensions.background-delayed-startup is true? 
(on Nightly this pref is already set to true by default, and Bug 1473757, which has been landed recently, will make it enabled for the other channels).
Flags: needinfo?(bdanforth)
As mentioned in comment 0, this bug is about the race between content scripts and the background page that happens when an extension is installed, not what happens during browser startup.  The logic for blocking messages to the background script during browser startup relies on knowing that there was an onConnect or onMessage listener from a previous browser session, but off the top of my head, I think it should be reasonably straightforward to apply the same logic when an extension is activated at some time after browser startup.
Component: Add-ons Manager → General
Flags: needinfo?(bdanforth)
Product: Toolkit → WebExtensions
Priority: -- → P2

Updated

8 months ago
Severity: normal → enhancement

Comment 3

7 months ago
I’ve also run into this quirk. For me, content scripts for already existing tabs are run before background scripts 100% of the time and messaging fails until the background scripts are loaded. (Firefox Nightly 63.0a1 (2018-09-02) (64-bit))

As far as I can tell, bug 1369841 should have fixed this (at least bug 1369841 comment 2 sounds exactly like what’s being described here), but I might be misunderstanding what that bug is about.

I added a comment there (comment 1369841 comment 36) about the bug being present in Firefox 63, but was asked to open a new issue (bug 1369841 comment 37). When starting to do so, I found this bug. So here goes.

Just in case you need more test cases, I’ll chip in with some extra information.

Basically, the example here does not work for already open tabs:
https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/runtime/connect#Examples

Here’s a minimal extension demonstrating the problem:
https://github.com/lydell/webext-message-issue

Here’s how I work around it in the extension I’m building:
https://github.com/lydell/synth/blob/cea63e1658be6d03013bf97860f60567010c1cba/src/renderer/Program.js#L107-L120
https://github.com/lydell/synth/blob/cea63e1658be6d03013bf97860f60567010c1cba/src/renderer/Program.js#L154-L160
https://github.com/lydell/synth/blob/cea63e1658be6d03013bf97860f60567010c1cba/src/background/Program.js#L121-L129

The first thing I do in the content scripts is to send a message to the background, saying that the content script is alive (they need to sync state with each other). The steps look like this:

1. Try to send the Startup message from content to background.
2. If that succeeds—great, nothing more to do! If that fails, ignore the error and wait for the Workaround message.
3. During the startup phase of the background script, get all open tabs where the content script should run and send a Workaround message.
4. Receive the Workaround message in the content script and re-send the Startup message from content to background.

But ideally the steps would just be:

1. Send the Startup message from content to background. Done.
You need to log in before you can comment on or make changes to this bug.