1

I have a very simple background page for a Chrome extension:

chrome.runtime.onInstalled.addListener((reason) => {
  console.log(reason);
});

The background page runs when my extension is loaded: enter image description here

The extension also has a popup that runs getBackgroundPage(), using:

const serviceWorkerWindow = await chrome.runtime.getBackgroundPage();

This fails with:

Uncaught (in promise) Error: You do not have a background page.

How do I make getBackgroundPage() work?

mikemaccana
  • 110,530
  • 99
  • 389
  • 494
  • ManifestV3 extensions don't have a background page, they have a background script which is a service worker not a page, so getBackgroundPage is meaningless. How did you plan to use it? There may be a different solution e.g. navigator.serviceWorker messaging. – wOxxOm Oct 27 '22 at 16:04
  • Manifest V3 uses service workers, but they are defined using the term `background` and the documented APIs for v3 should work. My use case is to communicate with the background page / service worker. See https://developer.chrome.com/docs/extensions/reference/runtime/#method-getBackgroundPage – mikemaccana Oct 27 '22 at 16:20
  • 1
    Thing is there's no page, so this API won't work. There's no such thing as serviceWorkerWindow either. The documentation is simply outdated because the ManifestV3 team consists of just a few devs who don't have time to do everything. To communicate with the background script you can use [extension messaging](https://developer.chrome.com/extensions/messaging) or navigator.serviceWorker messaging. – wOxxOm Oct 27 '22 at 16:25
  • Thanks @wOxxOm I'll try that. Sad to read the documentation isn't maintained properly. – mikemaccana Oct 27 '22 at 16:27
  • @wOxxOm thanks, I used `chrome.runtime.sendMessage()` in the popup and `chrome.runtime.onMessage.addListener()` in the extension. Knowing that the documentation was outdated (and that `You do not have a background page` was misleading) was critical to trying other ways to communicate to the background page. If you turn your comment into an answer I will mark it as correct. – mikemaccana Oct 27 '22 at 16:41
  • 2
    Further information: [extension.getBackgroundPage, runtime.getBackgroundPage, and serviceWorkers](https://github.com/w3c/webextensions/issues/295) – erosman Oct 29 '22 at 18:52

2 Answers2

0

The getBackgroundPage() method doesn't retrieve the background script, it retrieves the window object associated with the background script. As you know, Manifest V3 doesn't use background scripts, it uses a service worker. Service workers by definition do not have access to window objects.

What is your use case? Maybe I could suggest an alternative approach.

StormyKnight
  • 509
  • 3
  • 13
  • 1
    MV3 extensions do have a background script (that's why it's still declared in `background` section of manifest.json), the difference is that it doesn't belong to a page, but instead is a service worker script. – wOxxOm Oct 27 '22 at 16:12
  • Your answer isn't an answer, but to respond: yes, I'm aware `getBackgroundPage()` returns the window of the background page, hence `const serviceWorkerWindow =` in the question. I am trying to get the serviceWorkers's `window` from the popup - as mentioned in the question. I am not trying to access the DOM in the service worker. Background pages do have a `window`, it's just not the popup's `window` or the pages `window`, see https://developer.chrome.com/docs/extensions/reference/runtime/#method-getBackgroundPage also mentioned in the question. – mikemaccana Oct 27 '22 at 16:23
  • I did understand the question. What I'm trying to get across is that a service as a background script is like a web platform service worker in that it cannot access `window` or the DOM even if it is called a background script. – StormyKnight Oct 27 '22 at 19:09
  • @StormyKnight I might have been a little harsh / unwelcoming here and I apologize. I genuinely believed Google's documentation was correct - when Google said "Retrieves the JavaScript 'window' object for the background page" I thought they meant the JS global object for the background service worker. I still don't think your answer was much of an answer, but I think my tone was off - sorry about that. – mikemaccana Oct 28 '22 at 10:04
  • @mikemaccana I actually debated whether I should give a proper answer or just make a comment. At the time, I didn't think the question was answerable as currently phrased, which is why I made it an answer and ended my answer by asking for a use case. – StormyKnight Nov 04 '22 at 15:37
0

Answering my own question based on @wOxxOm's comment. If wOxxOm writes their own answer I'll mark that as correct.

My expectation based on Google's documentation was that getBackgroundPage():

retrieves the JavaScript 'window' object for the background page running inside the current extension/app.

In modern JS terms, this would be the globalThis for the service worker (the service workers is still referred to as background in manifest v3.

As wOxxOm said.

This API won't work. The documentation is simply outdated because the ManifestV3 team consists of just a few devs who don't have time to do everything.

Essentially the Chrome Extension documentation is not adequately maintained. There is an outstanding W3C issue on the topic of whether getBackgroundPage should work with service workers - thanks @erosman. The best way to communicate between a popup and a background service worker is via extension messaging. Ie:

chrome.runtime.sendMessage()

And:

chrome.runtime.onMessage.addListener()
mikemaccana
  • 110,530
  • 99
  • 389
  • 494