Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Handling push in main service worker vs. a background worker #3

Open
karmanyaahm opened this issue Jun 25, 2022 · 5 comments
Open

Handling push in main service worker vs. a background worker #3

karmanyaahm opened this issue Jun 25, 2022 · 5 comments

Comments

@karmanyaahm
Copy link
Member

This is something I need to investigate. The current implementation on my repo uses a background worker and passes push to the app when it's in the foreground, but that's not a good experience for app devs because the background worker doesn't have access to anything fancy (like keys for matrix).

@karmanyaahm
Copy link
Member Author

W3C:

A service worker registration of an identical scope url when one already exists in the user agent causes the existing service worker registration to be replaced.

MDN:

The scope parameter is optional, and can be used to specify the subset of your content that you want the service worker to control. In this case, we have specified '/sw-test/', which means all content under the app's origin. If you leave it out, it will default to this value anyway, but we specified it here for illustration purposes.
Each time a page within your scope is loaded, the service worker is installed against that page and operates on it. Bear in mind therefore that you need to be careful with global variables in the service worker script: each page doesn't get its own unique worker.

Practically speaking, we can't make flutter apps run from different URLs, therefore, adding our own service worker (in the same scope) could mess with the default flutter one. Let's find a way to get this working without adding a service worker.

That also prevents us from running into initialization problems with other variables/dependencies the app uses.

@karmanyaahm
Copy link
Member Author

FlutterFire, Firebase's Flutter library says the following:

https://firebase.flutter.dev/docs/messaging/usage#background-messages

Unfortunately we haven't yet been able to establish a proper way of communicating with the Service Worker and Flutter applications. Right now, all web background code must be executed in the JavaScript Service Worker file.

window.addEventListener('load', function () {

// ADD THIS LINE
navigator.serviceWorker.register('/firebase-messaging-sw.js');

// Wait for registration to finish before dropping the <script> tag.
// Otherwise, the browser will load the script multiple times,
// potentially different versions.
var serviceWorkerUrl = 'flutter_service_worker.js?v=' + serviceWorkerVersion;

// ...
});

So, the Flutter app isn't running in a worker. It's running on the main thread, attached to the DOM. that's why there's no reasonable way to make things better than running push stuff in JS.

@karmanyaahm
Copy link
Member Author

karmanyaahm commented Jun 27, 2022

I don't know any open source Flutter apps that do webpush, much less apps that are also e2ee in dart.

But the following JS implementations exist:
Hydrogen (matrix client): https://github.com/vector-im/hydrogen-web/blob/13428bd03c7ec3821352ab13eb631fb0bbe23e94/src/platform/web/sw.js#L265-L316

mastodon-web: https://github.com/mastodon/mastodon/blob/main/app/javascript/mastodon/service_worker/web_push_notifications.js

@karmanyaahm
Copy link
Member Author

karmanyaahm commented Jun 27, 2022

window.addEventListener('load', function () {

// ADD THIS LINE
navigator.serviceWorker.register('/firebase-messaging-sw.js');

// Wait for registration to finish before dropping the <script> tag.
// Otherwise, the browser will load the script multiple times,
// potentially different versions.
var serviceWorkerUrl = 'flutter_service_worker.js?v=' + serviceWorkerVersion;

// ...
});

Another observation here. They register the push worker right before the flutter worker is registered. That ensures that the flutter worker is the 'active' (?) worker.

Another way to do this is to register it in dart, so app devs don't have to manually register this each time. However, the main obstacle to that is that the lib would have to make sure the right 'flutter_service_worker.js' got registered once after the push worker. This could be done by only registering the service worker if it hasn't already been registered, so the first run of the app is the only one where flutter_service_worker isn't 'active'. However, this might be susceptible to browser timeout behaviors and other edge cases. IDK, maybe just imitating the Firebase architecture is the right choice here.

@karmanyaahm
Copy link
Member Author

karmanyaahm commented Jun 27, 2022

Another question that needs to be asked and documented...
Do we send the push to each open window (if the app happens to be open in multiple tabs), or only the focused/visible one?

Probably making it configurable by the app dev is the simplest solution

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant