How to prevent idle state?

Introduction

I am writing my very first Firefox Extension and I got an issue where my content_script.js goes into idle state.

The purpose of my extension is very simple - click a button on youtube.com whenever the user is asked “Video paused. Continue watching?”. I do that by adding an event listener to the pause event of the video element and then search for the button. If the button is found, it is clicked.

"host_permissions": [
	"https://*.youtube.com/watch*"
],
"content_scripts": [{
	"matches": [
		"https://*.youtube.com/watch*"
	],
	"js": ["content_script.js"]
}]

manifest.json

However, if the browser window is minimized or the tab is not focused, the tab can go into “idle” mode and the video pause event is not caught. Or not emitted - I don’t know. But the music/video stops and as soon as I bring the Window or browser tab into focus (e.i. displayed) then the button is clicked and the video continue.

Question

  1. How do I prevent an extension from going into idle mode?
  2. Is the video element pause event emitted if the tab is in idle mode? Though the video does pause.

Other resources

I’ve read up on Background page but the background page seem to go into idle mode immediately and it’s not clear how that would solve the problem with the pause event on a video element on a page.

“Event Pages”, seems to be another name for “Background pages”.

Service workers are not supported in Firefox.

1 Like

I’d love to know that too, I have the same problem currently, with my background event page getting killed while my async background task is running :frowning:

Have you ever solved it?

Hey @licat

I’ve sortof solved it. In Firefox I reverted back to manifest 2 with proper background pages, while in Chrome I’m running tabs.query every ~15s to avoid the service worker going to sleep. That seems to work for Chrome > v110

You could have picked a less expensive call :slight_smile:, for example browser.runtime.getPlatformInfo() will also work, while execution takes ~0ms.

BTW, here is my TypeScript helper function for keeping service worker running while some slow async task is running:

// executes long-running async work without letting the service worker to die
export async function withoutKillingWorker<T>(asyncWork: AsyncWork<T>): Promise<T> {
  const id = self.setInterval(() => browser.runtime.getPlatformInfo(), 2e4);
  return await asyncWork().finally(() => self.clearInterval(id));
}

Regarding the content script - if the tab is not focused or minimized, some API calls are throttled, for example setTimeout will take much longer and requestAnimationFrame maybe a whole minute. At least this is what my comments says when I was working on something like this.

There is one API worth checking though, the warmup (Firefox only):


Although, it didn’t really helped for the cases I needed, but maybe it can help here.
1 Like

Discussion in this thread seems like it may be conflating two related, but different concepts: the extension’s background context and content scripts. This is important because they have different API access, behaviors, and lifetimes.

An extension’s background context refers to the background page or service worker declared in "background" field of the extension’s manifest.json file. Regardless of the which browser you’re using the extension in, all Manifest V3 background contexts are event-based. In other words, the background will be started as needed and terminated when idle. The extension’s background context runs on it’s own origin, which means it doesn’t share CPU time with anything except other scripts running on the extension’s origin. The background context and other pages run on the extension’s origin (except sandboxed pages) have full access to WebExtension APIs.

Content scripts are injected into websites and are essentially an extension’s way to hook into a website. While extension scripts are executed in an isolated JavaScript environment, they run on the same thread as the page’s scripts and therefore share execution time with the page itself. Content scripts can only access a limited set of WebExtensions APIs. Content scripts “live” as long as the page they’re injected into does. They’re also bound by the same performance features as the host page is, such as background throttling or the discarding unused pages.

Based on original post, it sounds like it should be possible to implement the “continue watching” functionality using only a content script. As I recall browsers do not throttle pages that are actively playing audio or video, so the content script shouldn’t have any issue detecting and reacting to the “continue watching” prompts. @dotnetcarpenter, can you share more about how the extension’s background context is relevant here?

1 Like