Bug 258922

Summary: Push notifications with same tag do not replace each other
Product: WebKit Reporter: ekzyis <ek>
Component: Service WorkersAssignee: Brady Eidson <beidson>
Status: NEW    
Severity: Normal CC: beidson, bsoft, ik, mrigbyjones, nham, nigelbirkenshaw, thomas, webkit-bug-importer, wilkinson
Priority: P2 Keywords: InRadar
Version: Safari 16   
Hardware: Unspecified   
OS: iOS 16   
Attachments:
Description Flags
notifications with same tag do not replace each other none

ekzyis
Reported 2023-07-06 05:54:48 PDT
Hello! I asked a question on Stack Overflow about this since I wasn't sure if I am doing something wrong. Someone replied that this may indeed be a bug and I should file a bug report with Apple or you. Since I didn't find another bug report about this on here, I am filing this one now. I didn't file a bug report with Apple since I have no Apple developer license. It looks like I need one or an Apple device before I can file a bug. [0] What follows is the body of the question [1] + some changes to respect the Bug Writing Guidelines --- **Overview** We implemented push notifications for a PWA using this guide: https://web.dev/notifications/ We are using the `tag` property to group notifications together. For example, if there is one reply, the user will be shown "you have a new reply". But if there is another, it should show "you have 2 new replies" and replace the previous one. However, this works on Android but not on iOS 16.4 with Safari. Notifications always show up immediately and do not replace each other even though they have the same exact tag. This is the relevant code in our service worker: ```javascript self.addEventListener('push', async function (event) { const payload = event.data?.json() if (!payload) return const { tag } = payload.options event.waitUntil((async () => { if (!['REPLY', 'MENTION'].includes(tag)) { // notifications with REPLY and MENTION as tags need updated title. // other notifications can just replace the old one return self.registration.showNotification(payload.title, payload.options) } const notifications = await self.registration.getNotifications({ tag }) // since we used a tag filter, there should only be zero or one notification if (notifications.length > 1) { console.error(`more than one notification with tag ${tag} found`) return null } if (notifications.length === 0) { return self.registration.showNotification(payload.title, payload.options) } const currentNotification = notifications[0] const amount = currentNotification.data?.amount ? currentNotification.data.amount + 1 : 2 let title = '' if (tag === 'REPLY') { title = `You have ${amount} new replies` } else if (tag === 'MENTION') { title = `You were mentioned ${amount} times` } currentNotification.close() const { icon } = currentNotification return self.registration.showNotification(title, { icon, tag, data: { url: '/notifications', amount } }) })()) }) ``` A notification that we send to the push service may look like this: ```json { "title": "you have a new reply", "options": { "body": <text of reply>, "timestamp": <unix timestamp>, "icon": "/android-chrome-96x96.png", "tag": "REPLY", "data": { "url": "/items/124101" }, } } ``` This works on Android but for some reason does not on iOS 16.4 with Safari. Notifications never get replaced. So if a user gets 3 replies, they get three "you have a new reply" notification. I checked the browser compatibility for various related APIs but I couldn't find a reason why it shouldn't work (see reference). **Steps to Reproduce** Since I don't have access to an Apple device running iOS 16.4, I can't easily provide steps for reproduction at the moment. However, I think the following minimal service worker code should already show the bug: ```javascript self.addEventListener('push', async function(event) { eventWaitUntil(self.registration.showNotification("tag test", { "tag": "TAG" }) } ``` This code above should always show a notification with the title "tag test" if a push message was received. If a new push message is received, it should replace the previous one. **Actual Results** Notifications with same tag show up individually **Expected Results** Notifications with same tag automatically replace each other according to the specs [2] **Build Date & Hardware** Build ??? on iOS 16.4 **Additional information** I have looked through Mozilla MDN to check for browser compatibility for relevant APIs [3-7]. I haven't found a reason why this shouldn't work on iOS 16.4. Since support for these features was only added recently (in 16.4 which shipped on 2023-03-27), I didn't find useful resources on the web about this. Mostly about people asking when support will come. Since I have no access to a Apple device, I can not debug this properly. We would be very happy if someone can help us with this. --- Reference: [0] https://developer.apple.com/bug-reporting/ [1] https://stackoverflow.com/q/76625248/13555687 [2] https://notifications.spec.whatwg.org/#show-steps [3] https://developer.mozilla.org/en-US/docs/Web/API/Notification/Notification#browser_compatibility [4] https://developer.mozilla.org/en-US/docs/Web/API/Notification/tag#browser_compatibility [5] https://developer.mozilla.org/en-US/docs/Web/API/ServiceWorkerRegistration/getNotifications#browser_compatibility [6] https://developer.mozilla.org/en-US/docs/Web/API/ServiceWorkerRegistration/showNotification#browser_compatibility [7] https://developer.mozilla.org/en-US/docs/Web/API/Notifications_API/Using_the_Notifications_API#browser_compatibility
Attachments
notifications with same tag do not replace each other (6.11 MB, image/png)
2023-07-06 06:02 PDT, ekzyis
no flags
ekzyis
Comment 1 2023-07-06 06:02:17 PDT
Created attachment 466943 [details] notifications with same tag do not replace each other
Radar WebKit Bug Importer
Comment 2 2023-07-06 11:10:00 PDT
Ben Nham
Comment 3 2023-07-06 15:21:43 PDT
We don't support tag yet, but we can use this bug to track the feature request. We might dup this to an existing bug tracking the same work (which I think exists, but I can't find it right now).
Ben Nham
Comment 4 2023-07-06 15:37:42 PDT
To be clear: the tag attribute on Notification is exposed. You can set it via the Notification constructor/ServiceWorkerRegistration.showNotification and access its value later on. But the browser currently doesn't use the property to coalesce notifications. That will require additional work.
ekzyis
Comment 5 2023-07-06 15:51:23 PDT
Ah, I see. Thanks for your fast reply and clarification! I created a ticket for MDN to update their support declaration until this feature is supported: https://github.com/mdn/browser-compat-data/issues/20305 Any ETA on when this will be supported?
Mark Rigby-Jones
Comment 6 2023-08-22 10:05:41 PDT
An additional data point: this appears to be partially working on macOS Safari. While a second notification with the same tag appears as a new entry in the system notification center, it does replace an existing one in the array returned by ServiceWorkerRegistration.getNotifications(), and a notificationclose event is fired for the old/replaced notification. (For comparison, macOS Chrome replaces the notification in both places, and does not fire a notificationclose event for the replaced notification.) On iOS Safari, ServiceWorkerRegistration.getNotifications() appears to always return an empty array, so there's no way to compare that behaviour.
Thomas
Comment 7 2023-11-23 01:03:47 PST
Do we have an estimate of when this will be supported?
ekzyis
Comment 8 2024-01-09 17:05:35 PST
Hey, I finally managed to get access to an iPhone running iOS 17.1 so I could debug this on Safari now. I have noticed following things: 1. Notification.close() doesn't work. It seems to do nothing even though MDN says it's fully supported on Safari since 16.4. MDN only says that the 'close' event is not supported but that should be independent, no? [0, 1] 2. Contrary to this comment [2], ServiceWorkerRegistration.getNotifications() does return an array. It seems to correctly return the notifications that are currently displayed to the user. If a notification is swiped away, the next call to getNotifications() reflects that. 3. There is a 'onPush' race condition. If push notifications are received too fast, some calls receive a stale value from getNotifications(). For example, if you send 5 push notifications, the first two might see an empty array returned from getNotifications, while the next 3 push notifications receive an array of size 2. This is not the case on Android. A detailed analysis can be found here: https://github.com/stackernews/stacker.news/issues/411#issuecomment-1882137442 Currently, we would be happy if we at least could close notifications in some way and if this is reflected by getNotifications(). Is that possible somehow? [0] https://developer.mozilla.org/en-US/docs/Web/API/Notification/close [1] https://developer.mozilla.org/en-US/docs/Web/API/Notification/close_event [2] https://bugs.webkit.org/show_bug.cgi?id=258922#c6
ik
Comment 9 2024-01-11 00:56:36 PST
Regarding c#8 2): getNotifications() always returned an empty array until a later 16.x release. It has since been fixed and now returns the correct number of notifications - except if you try to replace a notification with `tag`, then you end up with two notifications but getNotifications() returns 1. The current implementation of the Web Push / notification API in WebKit is incomplete but DOES pass tests, so sites that do proper feature detection will end up with unexpected behaviour. Also, web developers will expect these things to work as MDN indicates they are supported (again, because the tests pass). Please prioritize fixing these problems. Web Push on iOS has been "implemented but incomplete" for almost a year now (feb 2023).
wil
Comment 10 2024-04-15 11:14:46 PDT
hi, can you share if there's been any progress with the bug?
Berni
Comment 11 2024-07-17 08:12:24 PDT
I think it's one thing not to support Notification.close() because of security issues, but not replacing tagged notifications with newer ones with the same tag to avoid a cluttered space is something else entirely. Especially since it works in Safari Desktop 17.5. Please support this in Mobile Safari as well.
ik
Comment 12 2024-07-18 02:03:36 PDT
Don't want to derail the convo here, but what are the security issues with Notification.close()? Is it because then a SW could receive push messages without showing a notification? It can't. It would be able to close existing notifications, but the SW has to show at least one (new) notification in response to a push message. Both Chrome and Firefox support it, so they don't see an issue here? I also think that, if WebKit decides to not support Notification.close(), that the function should not be available or throw an error so we can feature-detect support instead of relying on parsing the user-agent.
Note You need to log in before you can comment on or make changes to this bug.