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

Consider common API for push messages across browsers #208

Open
oliverdunk opened this issue May 4, 2022 · 11 comments
Open

Consider common API for push messages across browsers #208

oliverdunk opened this issue May 4, 2022 · 11 comments
Labels
implemented: chrome Implemented in Chrome neutral: safari Not opposed or supportive from Safari

Comments

@oliverdunk
Copy link
Member

In the 1Password extension, we open a long-lived WebSocket connection which allows the server to trigger a sync whenever anything changes in an account. With the move to shorter lifetimes in MV3, this is no longer feasible. It may be possible short-term if it becomes an allowed exemption in the offscreen documents proposal, but even if this is the case, it would be better to find a solution for this use case which makes better use of available resources.

Chrome already implements the chrome.gcm API, which (despite the name) supports Firebase Cloud Messaging and offers an extension API built specifically for push messaging.

In other browsers (at least in MV2), there are fewer options:

  • Firefox does support the Push API but it isn't possible to register a service worker from an extension context
  • Safari supports their own push notifications API but this also isn't available from within an extension context: https://developer.apple.com/notifications/safari-push-notifications/
  • It's not feasible to use the Firebase SDK in either due to the lack of the Push API which it depends on

It would be great to discuss our options here for a few reasons:

  • Even if Firefox and Safari are willing to support the Push API in MV3, there is likely still a long period between now and then where extension developers may need different implementations for each browser
  • Chrome's GCM API is great but likely isn't the best solution for the extension ecosystem, as it would be nice to support push notifications independently of any particular service
  • The Push API is heavily linked to the idea of notifications. I haven't looked in to this too much but it's possible the two concepts should be decoupled.

Related: #72

@dotproto dotproto changed the title Consider common API for push notifications across browsers Consider common API for push messages across browsers May 10, 2022
@dotproto
Copy link
Member

dotproto commented May 10, 2022

Thanks for opening this issue, @oliverdunk!

The Push API is heavily linked to the idea of notifications. I haven't looked in to this too much but it's possible the two concepts should be decoupled.

I hope you don't mind, but I took the liberty to update the title to differentiate between push messages and notifications. While these topics are commonly paired in the web world, to my knowledge we do this this is primarily for anti-abuse reasons. Since browser extensions have a different threat model, I think we should discuss them independently.


This topic has been top of mind for me recently. When extension developers ask how to use WebSockets in the background of their Manifest V3 extensions, I've been recommending that they consider adopting a push message + fetch() based model. In this model, extension authors would send data to extensions using push messages (chrome.gcm or Push) and extensions would send update to the backend using one-off fetch() requests.

The main problem with this approach is that Web Push implicitly links push messages with notifications. I haven't tested this in other browsers recently, but in Chrome if a service worker receives a push message and does not display a notification, Chrome will automatically generate a notification for the origin.

I see two potential paths to bringing push message support to webExtensions:

  • Option A: Expose an extension-specific push message API(s).
  • Option B: Allow extensions to receive Push messages and remove the requirement to display a notification on receiving a push message.

The primary difference between these options centers on the overlap between extension APIs and web platform APIs. This may be worthy of a separate discussion or possibly an issue to raise with the W3C's TAG.

Option A could be further broken down into providing a browser-specific APIs (A1) or a common cross-browser API (A2).

Option A1 has the benefit of potentially being faster for browsers to land as they could more directly expose their implementations to extension developers but the disadvantage of being more difficult for extension developers to adopt. That concern may be mitigated through the introduction of a community-maintained library to abstract out platform-specific aspects of the underlying extension APIs.

Option A2 would provide a better experience than A1 extension developers, but requires more upfront work from browser vendors in order to align on a common namespace and API design before they can begin their respective implementations.

Option B seems like the more web-friendly approach as it leverages existing web platform APIs and capabilities. While this aligns with the statement in Chrome's Extensions Manifest that "We should reuse the web platform wherever possible instead of creating new proprietary APIs", the primary disadvantage is that it may introduce confusion on Web Platform vs. WebExtension capabilities and behaviors.

At the moment I'm personally leaning towards Option B.

@larry-xu
Copy link

Our extension uses HTTP long polling for syncing updates from the server, which is not feasible in the MV3 service worker environment. Ideally we would like to continue using HTTP long polling for its simplicity, but a push messaging API that works across all browsers may also help resolve this issue.

I investigated the Push API a bit, but it seems to require a unique service worker per subscription. Currently our extension subscribes to updates from multiple servers via independent connections to each server. I believe supporting this with the Push API would require the browser extension to register multiple service workers. Is this possible?

@oliverdunk
Copy link
Member Author

@Rob--W: Something I forgot to ask in the meeting is if you see this as MV3 dependent. Assuming MV3 lands in Chrome before it's ready in Firefox, it would be great to still have a common API here. Does it sound possible to support the Push API in background pages or would that be too much work?

@Rob--W
Copy link
Member

Rob--W commented May 17, 2022

I don't know the implementation details off the top of my head, but if there is consensus on the shape of the API, I'd expect us to also be interested in a Push API. FYI here is an existing feature request for a Push API in extensions: https://bugzilla.mozilla.org/show_bug.cgi?id=1378096

@justinlulejian
Copy link

justinlulejian commented Aug 17, 2023

In relation to a common push API I'd also like to propose that extensions be able to pass false for userVisibleOnly. This would allow extensions to use push messaging as a communication method without being required to show a user visible effect when a message is received. They could still show a notification, but would have the choice.

Extensions, being a program that runs on behalf of the user in the background that can request and be granted the notification permission, would seem to justify having an exception to the user visible requirement.

From a developer perspective this would allow an additional background client/server communication method that may be preferable to them versus other methods (e.g. WebSockets).

From a browser perspective it would encourage a more efficient way of communication since the browser would only wake up the extension when the server had something to communicate, versus having a persistent open connection (e.g. WebSockets). This is particularly relevant for service worker based extensions that have lifetime restrictions.

This would not change how the notification permissions gates push API functionality. (On chromium I can confirm) we block push subscriptions and push messages if that permissions is not granted.

For chromium we see a lot of value due to requiring the use of service worker based extensions in MV3. We have a change open ([Extensions] Allow extensions to set userVisibleOnly false.) with this behavior implemented and will probably merge it soon.

I'm also happy to write a separate proposal for this for review if desired, but thought to start the discussion here.

@dotproto
Copy link
Member

I'm supportive of this approach to allowing push messages without notifications in extensions. Chrome already allows extensions to receive push messages without displaying notifications via the chrome.gcm API. Allowing extensions to declare userVisibleOnly: false allows extensions to adopt push message code that is much more in line with the web platform than the current extension-specific API.

To make the suggestion a little more concrete, here's a snippet that a developer might add to their extension in order to create a silent push message subscription.

self.addEventListener('activated', (event) => {
  // Note: This promise will reject if "userVisibleOnly" cannot be granted.
  const subscribeRequest = self.registration.pushManager.subscribe({
    userVisibleOnly: false,
    applicationServerKey: "<KEY>",
  });

  event.waitUntil(subscribeRequest);
});

self.addEventListener('push', function(event) {
  console.log('[Service Worker] Push Received.', event);
});

@justinlulejian
Copy link

I'm supportive of this approach to allowing push messages without notifications in extensions. Chrome already allows extensions to receive push messages without displaying notifications via the chrome.gcm API. Allowing extensions to declare userVisibleOnly: false allows extensions to adopt push message code that is much more in line with the web platform than the current extension-specific API.

To make the suggestion a little more concrete, here's a snippet that a developer might add to their extension in order to create a silent push message subscription.

self.addEventListener('activated', (event) => {
  // Note: This promise will reject if "userVisibleOnly" cannot be granted.
  const subscribeRequest = self.registration.pushManager.subscribe({
    userVisibleOnly: false,
    applicationServerKey: "<KEY>",
  });

  event.waitUntil(subscribeRequest);
});

self.addEventListener('push', function(event) {
  console.log('[Service Worker] Push Received.', event);
});

Thank you for the code snippet Simeon! That's exactly the intent.

And also thanks for reminding me of the other benefit here. It's a web platform alternative that is not restricted to chromium extension APIs and Google (Firebase cloud messaging) servers.

@xeenon xeenon added the neutral: safari Not opposed or supportive from Safari label Aug 31, 2023
@kiaraarose
Copy link

kiaraarose commented Aug 31, 2023

WebKit bug tracking this issue:
https://bugs.webkit.org/show_bug.cgi?id=260969

@oliverdunk
Copy link
Member Author

@yankovichv
Copy link

Could somebody have a forecast for the launch of this feature?

@justinlulejian
Copy link

justinlulejian commented Nov 9, 2023

We've implemented the ability to receive push messages without notifications in extensions in Chrome: crrev.com/c/4705862. It should work for both MV2 and MV3 extensions that use service workers. It can be tested now in Canary (121.0.6100.0+) and Dev (121.0.6103.3). Calling PushManager.subscribe() does still require notification permissions which can be granted at runtime or through the manifest.

@justinlulejian justinlulejian added implemented: chrome Implemented in Chrome and removed implemented: chrome Implemented in Chrome labels Nov 9, 2023
@oliverdunk oliverdunk added the implemented: chrome Implemented in Chrome label Nov 9, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
implemented: chrome Implemented in Chrome neutral: safari Not opposed or supportive from Safari
Projects
None yet
Development

No branches or pull requests

8 participants