mdn / content

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

Background Fetch API throws for extension protocol #12370

Open guest271314 opened 2 years ago

guest271314 commented 2 years ago

MDN URL: https://developer.mozilla.org/en-US/docs/Web/API/Background_Fetch_API

What information was incorrect, unhelpful, or incomplete?

Neither the README.md https://github.com/WICG/background-fetch#readme, specification https://wicg.github.io/background-fetch/, nor MDN documentation explains that background fetch will throw for browser extension protocol (not HTTPS or HTTP).

Specific section or headline?

None.

What did you expect to see?

"only the https: scheme is allowed, or http: for loopback IPs."

Did you test this? If so, how?

Yes.

Run the following code in an extension

try {
    const registration = await navigator.serviceWorker.ready;
    console.log(registration);
    const bgFetchReg = await registration.backgroundFetch.fetch('test', ['./worker.js']);
  } catch(err) {
    console.error(err);
  }

observe the TypeError thrown

TypeError: Failed to execute 'fetch' on 'BackgroundFetchManager': Refused to fetch 'chrome-extension://xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx/stream' because only the https: scheme is allowed, or http: for loopback IPs.
MDN Content page report details * Folder: `en-us/web/api/background_fetch_api` * MDN URL: https://developer.mozilla.org/en-US/docs/Web/API/Background_Fetch_API * GitHub URL: https://github.com/mdn/content/blob/main/files/en-us/web/api/background_fetch_api/index.md * Last commit: https://github.com/mdn/content/commit/2279e5ae6c229c707a014a22aa1ec4635a0f981f * Document last modified: 2021-09-14T18:08:09.000Z
sideshowbarker commented 2 years ago

Is the code shown in the issue description served/loaded from an https URL? If so, are you able to test it from an http URL, and report back here about what happens?

That “only the https: scheme is allowed, or http: for loopback IPs” restriction sounds like the browser enforcing Mixed Content blocking, which is specified at https://w3c.github.io/webappsec-mixed-content/ and documented in MDN.

guest271314 commented 2 years ago

No. This appears to be an omission. The BackgroundFetch specification authors were not thinking about MV3 ServiceWorker usage, and MV3 authors developing background ServiceWorker were not thinking about BackgroundFetch - even within the same organization there was a disconnect, not a unified collaborative approach, apparently, hence this one of several omissions, TL;DR this case can be added to the list at https://github.com/w3c/webextensions/issues/72.

People and organizations make mistakes. Whether they admit those mistakes or not is a different issue. Empirical evidence outweighs denials.

Chromium/Chrome Manifest Version 3 ServiceWorker https://developer.chrome.com/docs/extensions/mv3/migrating_to_service_workers/ can fetch() resources across protocols. To prove that I will attach a screenshot of fetching a chrome-extension: protocol resource from this https: GitHib page, listed in the extensions' "web_accessible_resources" field. I used the BackgroundFetch code within the extension itself, the same protocol.

fetch_chrome_extension_protocol_from_https_protocol

sideshowbarker commented 2 years ago

alerting @jakearchibald

guest271314 commented 2 years ago

@sideshowbarker FWIW I emailed the individual you cc'ed re this topic. I was attempting to use BackgroundFetch to keep ServiceWorker active during an indeterminate stream of audio using Native Messaging. Very difficult to do when the ServiceWorker specification is apparently only concerned with battery life of handheld devices and ignores desktops that are plugged in and have no battery, where the 5 minutes before inactivity disconnects the Native Messaging host. That is problematic when I am streaming hours of audio. Thus I created this repository https://github.com/guest271314/persistent-serviceworker to work around the restriction. BackgroundFetch appears to be specifically for such use cases, e.g., podcast streaming https://github.com/w3c/ServiceWorker/issues/980#issuecomment-314632747

I think https://github.com/WICG/background-fetch#playing-a-podcast-as-its-background-fetching would solve the issue posed in https://bugs.chromium.org/p/chromium/issues/detail?id=678798. That considered, I think we better keep the hard lifetime budget to be in favor of battery usage and to not allow maliciously written service workers.

yet does not work for extensions.

Interestingly I was able to keep ServiceWorker active indefinitely using the "externally_connectable" approach https://github.com/guest271314/persistent-serviceworker/issues/1, though not when a Native Messaging host and port is also in use. Unfortunately it is not possible to connect to a Native Messaging host directly https://bugs.chromium.org/p/chromium/issues/detail?id=1250936. When I tried using "externally_connectable" on the page, to pipe from service worker to the web page the browser froze - twice.

Instead of using Native Messaging, which is the preferred method due to using only 12MB with a Python host compared to a local server which uses between 18-25MB depending on NodeJS or PHP server code, I can fetch() the indefinite stream, something like https://plnkr.co/edit/bK1BfoSgjFUDwkIV?preview.

My conjecture is that these handheld-focused restrictions wind up costing the same as indefinite ServiceWorker for both handheld and desktop users - to work around those restrictions https://groups.google.com/a/chromium.org/d/msgid/blink-network-dev/bc89ada5-7b85-49ca-b289-788cd4467df0n%40chromium.org?utm_medium=email&utm_source=footer, and AFAICT no tests have been performed to substantiate the claims of persistent ServiceWorker being more expensive than non-persistent ServiceWorker: The same code will be/is run anyway by users and websites, just because a ServiceWorker is persistent does not mean users or websites will run more or different code than they are already running on the main thread and in dedicated workers.

Re this issue, again, my estimation is that there wan no communication between MV3 extension authors and ServiceWorker authors as to chrome-extension: protocol being allowed for BackgroundFetch. Given I can fetch() chrome-extension: protocol from any origin listed in "web_accessible_resources" it makes no sense to not be able to use BackgroundFetch from within the ServiceWorker or <iframe> with chrome-extension: protocol.

Users in the field are not going to just accept hard-coded 5 minutes restriction.Workarounds. or hacks if you prefer, will be attempted to get around that restriction, for a variety of use cases. I was trying to use the API that appears to be conceived of to do what I am doing: streaming media without the stream being interrupted in 5 minutes. I might want to stream a live jam-session for 3 days.

guest271314 commented 2 years ago

Importantly, the claim that persistent/indefinitely running ServiceWorker will drain CPU, RAM, etc. is strong inference that ServiceWorker itself drains system resources more than running the same code in a site without ServiceWorker code running.

If peristent/indefinitely running ServiceWorker does in fact drain system resources more than sites without ServiceWorker then BackgroundFetch can do the same thing, again, making the 5 minute restriction nonsensical.

Extensions should be able to use BackgroundFetch, or, as this issue requests, notes or normative language be published in specification and documentation clearly notifying extension developers that BackgroundFetch cannot be used in extension code.

jakearchibald commented 2 years ago

BackgroundFetch does not keep the service worker alive. In fact, it's whole reason for existing is to avoid keeping the service worker alive.

The service worker is not supposed to stay alive, and attempts to make it stay alive will be buggy.

Shared workers however do stay alive.

If you think extensions should be able to use shared workers, that's something to propose to extension folks.