mdn / content

The content behind MDN Web Docs
https://developer.mozilla.org
Other
9.24k stars 22.49k forks source link

Documentation on runtime.connect does not address manifest V3 background scripts dropping ports when they drop off after inactivity #36097

Open TruBlu2U opened 2 months ago

TruBlu2U commented 2 months ago

MDN URL

https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/runtime/connect

What specific section or headline is this issue about?

Examples

What information was incorrect, unhelpful, or incomplete?

When trying to create a V3 browser extension, I am finding that the extension background page is unloaded (as expected) after a period of inactivity. This creates a Port.onDisconnect event in the content script from which the connection was initiated, but often results in the inability to successfully open a new port to the background script if inactivity is about 20 seconds or more.

What did you expect to see?

I expected to see some direction regarding how to successfully and reliably reconnect to the background script after it gets unloaded.

Do you have any supporting links, references, or citations?

Extension Testing.txt

Do you have anything more you want to share?

No response

MDN metadata

Page report details * Folder: `en-us/mozilla/add-ons/webextensions/api/runtime/connect` * MDN URL: https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/runtime/connect * GitHub URL: https://github.com/mdn/content/blob/main/files/en-us/mozilla/add-ons/webextensions/api/runtime/connect/index.md * Last commit: https://github.com/mdn/content/commit/b8a0743ca8b1e1b1b1a95cc93a4413c020f11262 * Document last modified: 2024-09-01T17:04:58.000Z
TruBlu2U commented 2 months ago

By the way, I am using the Firefox Browser Console tool to capture the log console log entries, so as to prevent the presence of the extension Inspect tool from throwing warning messages indicating that hooks from the Inspect tool were preventing the background script from being unloaded.

TruBlu2U commented 2 months ago

Also, the background script is being loaded from a background.html file specified in the manifest.

dotproto commented 1 month ago

I attempted to reproduce this issue using the extension and steps outlined in this gist.

I suspect that the problem you're running into is that the browser.runtime.onConnect event listener is not being registered synchronously when the event page is first initialized. That would account for the behavior you're describing: if the background is running when a content script attempts to open a port the browser can dispatch the onConnect event as expected, but if the background is not running the browser returns a "Could not establish connection" error.

To fix this issue, move the browser.runtime.onConnect.addListener() call outside of any nested functions in your background script.

TruBlu2U commented 1 month ago

The browser.runtime.onConnect.addListener() call is not within any function, but rather placed at the 'top level' of statements. Also, I suspect the issue may be related to the background script being called from a background.html page referenced in the manifest.json file. The connection always works fine on initial load, and seems to always work within about 5 seconds after the background script is unloaded and triggers a port.onDisconnect event for each connected content script. It also seems to always work fine if the new connection request is initiated about 1 minute or more after the background script is unloaded. The problem seems to be happening when the new connection request occurs within 20 to 30 seconds after the background script is unloaded.

TruBlu2U commented 1 month ago

After looking closely at your gist, I noticed 2 things you are using that I am not.

  1. globalThis.browser ??= chrome;
  2. use of a service worker for the bg.js (not mentioned in any documentation or examples I have seen)

Also, I am limiting my extension to a specific domain (youtube.com) rather than matching to any url "matches": [""],

dotproto commented 1 month ago

Neither of those differences should affect the this case. globalThis.browser ??= chrome is a minimal shim to get the browser global variable to work in Chrome. Basically, it means "if globalThis.browser (a way of referencing the global variable browser) is null or undefined, assign it the value of the variable chrome." Similarly, the declaration of background.service_worker in the manifest is for Chrome. In both cases Firefox should ignore those parts since they're not relevant to it.

I also don't expect that the difference between the host permission patterns would have any affect here.

Could you share a version of the extension that demonstrates the problem? Also, what version of Firefox and operating system are you using? That info may be relevant for investigation purposes.