firebase / firebase-js-sdk

Firebase Javascript SDK
https://firebase.google.com/docs/web/setup
Other
4.82k stars 884 forks source link

[Bug]: Service worker event listeners don't work in iOS if app is opened from home screen. #7309

Open stefan-krajnik opened 1 year ago

stefan-krajnik commented 1 year ago

Operating System

iOS 16.4.1 (a)

Browser Version

Safari

Firebase SDK Version

9.22.0

Firebase SDK Product:

Messaging

Describe your project's tooling

NodeJs Express

Describe the problem

In the demo app, I listen on messages posted from service worker. As you can see in the video on desktop Safari it works as intended but it doesn't on iOS (16.4.1 (a) - iPhone 8)

With further investigation I found out event listeners in service workers are not always called, if I open the app from home screen clicks on notification don't do anything, but if the app is opened by click on notification then it works as intended, meaning clicks on next notification trigger event listeners in service worker.

https://github.com/firebase/firebase-js-sdk/assets/16229997/0ddcf4c4-c213-493f-80cb-ca72222e6af6

Steps and code to reproduce issue

Here you can see the reproduction demo https://github.com/stefan-krajnik/fcm-web-push-example Provide correct firebase config here - https://github.com/stefan-krajnik/fcm-web-push-example/blob/master/index.html#L80 Generate Firebase Admin SDK private key and provide correct path to it - https://github.com/stefan-krajnik/fcm-web-push-example/blob/master/server.js#L5

I deployed the reproduction app to https://fcm-webpush-test.onrender.com

looptheloop88 commented 1 year ago

Hi @stefan-krajnik, I'm not sure if I understood the issue well so correct me if I'm wrong here. If the web app is open, you send a notification and the app receives it successfully, you click the notification, it doesn't redirect to the target page.

I checked the code reproduction you've shared and I noticed the way you handle creating and receiving of the notification are different from our documentation and quickstart project. You're not using the onMessage and onBackgroundMessage callbacks available in the Messaging SDK.

Could you please try to use the suggested implementation and see if the issue persists?

stefan-krajnik commented 1 year ago

Hey @looptheloop88 , thanks for replying.

correct me if I'm wrong here. If the web app is open, you send a notification and the app receives it successfully, you click the notification, it doesn't redirect to the target page. Yes that's correct. But only if the app is open, if app is completely closed, the notification click works properly as expected.

I implemented your suggestion, you can check it out. The behavior is a little bit different from the initial one but the issue is still there, clicking on notification when the app is opened doesn't do anything.

looptheloop88 commented 1 year ago

Hi @stefan-krajnik, could you please verify if onMessage callback is triggered when the message is received while the app has focus or is currently opened? I would like to isolate the possible cause, since the notification is created locally and not by the FCM SDK.

stefan-krajnik commented 1 year ago

@looptheloop88 No onMessage is not triggered if the app is opened from the homescreen.

Heerschop commented 1 year ago

I'm experiencing the same problem, however I do not think this has anything to do with Firebase. I have tried several different implementations, and they all have the same issue. For example:

I think this problem is related to Safari 16 WebKit API as described in this bug report: https://bugs.webkit.org/show_bug.cgi?id=252544

Here's what happens: 1 - The app launches and starts a page load for the root URL of the web app - https://taoshu.in/web/push-demo/ in this case. This happens in web content process A. 2 - That load has a ScriptExecutionContextIdentifier associated with it. Importantly, this identifier is what the eventual Document will have, but that document does not exist yet. 3 - The networking process is asked to load https://taoshu.in/web/push-demo/. As part of that resource load it is given the context identifier. So the networking process remembers "There is a window client for this URL with this identifier. 4 - The service worker is fired up in web content process B to handle the notification click. This happens right away, before the main page document has really started loading. 5 - In the notification click handler, the SW does a matchAll on clients looking for window clients 6 - That matchAll goes to the networking process, which knows about the eventual client. So it returns that UUID 7 - Back in web content B, the SW has the results of the matchAll and tries to call focus() on the window client. 8 - That focus call is routed to the networking process based on UUID, which knows that the document should be in Web Content process A. So it forwards the call there 9 - In Web Content process A, the focus() attempt tries to look up the Document for that UUID and fails. Remember from step 2, the eventual Document that will be created will have that UUID, but that Document doesn't exist yet. 10 - The failure is routed to Networking, which then routes to Web Content B, and then rejects the focus() promise. Whoops! 11 - Almost immediately after that rejection, data does come in for the main page document, therefore actually creating the Document object in Web Content A, ensuring that a future focus() call would actually work.

A PR has been merged for this: https://github.com/WebKit/WebKit/pull/11848, but it will probably take a while for this to end up in Safari.

Heerschop commented 1 year ago

Just as a note: I have experienced when you add and remove the site from the home screen several times, every so often you will end up with a fully working version, let's say one out of every 15 attempts.

taoso commented 1 year ago

@Heerschop Here is my screen record.

I call the API with data=123. After I click the notification, the data in the bottom of the page changed to 123.

This is done by the following code

navigator.serviceWorker.addEventListener("message", (event) => {
  let wn = document.getElementById("web-notification");
  wn.innerHTML = event.data;
});

So please do not repeat the issue not fixed. Offer the minimal code to reproduce it. Please offer code use the native API. I do not think there will be anyone willing to debug firebase's framework.

https://github.com/firebase/firebase-js-sdk/assets/2030591/ff965d72-90bc-4893-b1a9-ced5a0b2660b

Heerschop commented 1 year ago

@taoso Thank you so much for sharing.

I have seen your version work, on my device as well. But when I removed it from the home screen and added it back, it didn't work anymore. I have tested this on Beta iOS 16.6. I can restore it to a working version by adding and removing it several times, eventually I will have a working version again.

jbalidiong commented 1 year ago

Hi @stefan-krajnik, I'll be taking over this issue from @looptheloop88. I was able to replicate the behavior wherein onMessage() is not triggered if the app is opened from home screen. It looks like this is more of a Safari issue. However, I'll check this with our FCM team to see what we can do for this issue. I’ll update this thread if I have any information to share.

jbalidiong commented 1 year ago

Hi all, just an update from our investigation with the engineers. This is more likely a Safari issue and the details from https://github.com/firebase/firebase-js-sdk/issues/7309#issuecomment-1566653392 are spot on. I'll leave this issue open for tracking until the PR is released on Safari's end.

MYKEU commented 1 year ago

Experiencing this exact same issue - notification clicks works only if I open my app from a notification.

Curious if anyone has further updates regarding this?

Sisyphusean commented 1 year ago

Having this same issue. Moving to server sent event for iOS messages. Notifications will be only in app.

DellaBitta commented 1 year ago

Hi @MYKEU and @Sisyphusean,

Please see the comment from @jbalidiong above. We believe this to be an issue in WebKit, which has been patched but it requires that Safari incorporate the fix and distribute a new release of Safari. I hope this helps.

goetzrobin commented 10 months ago

@Heerschop Here is my screen record.

I call the API with data=123. After I click the notification, the data in the bottom of the page changed to 123.

This is done by the following code

navigator.serviceWorker.addEventListener("message", (event) => {
  let wn = document.getElementById("web-notification");
  wn.innerHTML = event.data;
});

So please do not repeat the issue not fixed. Offer the minimal code to reproduce it. Please offer code use the native API. I do not think there will be anyone willing to debug firebase's framework.

2_1685427976.mp4

@taoso thank you for sharing this. I know it has been quite some time, but I just tested this on iOS 17 and it seems to be broken again. Do you see the same issue on your device?

taoso commented 10 months ago

@goetzrobin I have rechecked, it still works.

Here is a live demo https://bugs.webkit.org/show_bug.cgi?id=252544#c3

goetzrobin commented 10 months ago

@goetzrobin I have rechecked, it still works.

Here is a live demo https://bugs.webkit.org/show_bug.cgi?id=252544#c3

@taoso Thanks for checking! This is really weird. I don't know what it is but on my phone I simply do not get it to work correctly. Here is a screen recording of me not getting the custom data: https://share.icloud.com/photos/073J3LdefkwK8XXsrWHxyalag

Let me know what you think!

ereshidov commented 7 months ago

@goetzrobin I have rechecked, it still works. Here is a live demo https://bugs.webkit.org/show_bug.cgi?id=252544#c3

@taoso Thanks for checking! This is really weird. I don't know what it is but on my phone I simply do not get it to work correctly. Here is a screen recording of me not getting the custom data: https://share.icloud.com/photos/073J3LdefkwK8XXsrWHxyalag

Let me know what you think!

Hi :) were you able to figure out what the problem was?

nmalzieu commented 7 months ago

Hi there! I have the exact same issue on iOS 17.2.1

If I kill my PWA, then send a notification and click on it, the notificationclick event is triggered, and if I send other notifications and click on them, the notificationclick events are triggered (wether the PWA is foreground or background).

However, if I kill my PWA, then open it from the home screen, if I send notifications, click on them, the notificationclick event is never triggered.

N.B.: to detect if notificationclick is triggered I tried many things: postMessage to the client, fetch a specific URI on my server where I can detect it was called, etc. Always the same behaviour, it just seems the notificationclick event is not subscribed when app has been opened manually from the home screen on iOS (i.e. not via clicking a notification)

I'm not 100% sure this is the same thing as https://bugs.webkit.org/show_bug.cgi?id=252544 because when I try to trigger a fetch to an URI on my server, I don't think safari would care that a client is available, it's just the service worker that executes? Maybe I'm wrong though

ereshidov commented 7 months ago

Hi there! I have the exact same issue on iOS 17.2.1

If I kill my PWA, then send a notification and click on it, the notificationclick event is triggered, and if I send other notifications and click on them, the notificationclick events are triggered (wether the PWA is foreground or background).

However, if I kill my PWA, then open it from the home screen, if I send notifications, click on them, the notificationclick event is never triggered.

N.B.: to detect if notificationclick is triggered I tried many things: postMessage to the client, fetch a specific URI on my server where I can detect it was called, etc. Always the same behaviour, it just seems the notificationclick event is not subscribed when app has been opened manually from the home screen on iOS (i.e. not via clicking a notification)

I'm not 100% sure this is the same thing as https://bugs.webkit.org/show_bug.cgi?id=252544 because when I try to trigger a fetch to an URI on my server, I don't think safari would care that a client is available, it's just the service worker that executes? Maybe I'm wrong though

seems like this problem is not related to firebase sdk, i have exact same problem on iOS 17.2.1 using vite and my own web push configuration (web-push on server and my own service worker file)

goetzrobin commented 7 months ago

Hi there! I have the exact same issue on iOS 17.2.1

If I kill my PWA, then send a notification and click on it, the notificationclick event is triggered, and if I send other notifications and click on them, the notificationclick events are triggered (wether the PWA is foreground or background).

However, if I kill my PWA, then open it from the home screen, if I send notifications, click on them, the notificationclick event is never triggered.

N.B.: to detect if notificationclick is triggered I tried many things: postMessage to the client, fetch a specific URI on my server where I can detect it was called, etc. Always the same behaviour, it just seems the notificationclick event is not subscribed when app has been opened manually from the home screen on iOS (i.e. not via clicking a notification)

I'm not 100% sure this is the same thing as https://bugs.webkit.org/show_bug.cgi?id=252544 because when I try to trigger a fetch to an URI on my server, I don't think safari would care that a client is available, it's just the service worker that executes? Maybe I'm wrong though

this is exactly what I am experiencing! Good to know I am not going insane at least!

nmalzieu commented 7 months ago

I agree, seems to be an Apple / Safari / Webkit issue and not a firebase issue. Also, I don't think it is the same as https://bugs.webkit.org/show_bug.cgi?id=252544 - this one is fixed and supposedly live in "the latest iOS 16 and 17 betas" from a message sent 2023-06-07… Should we open a new webkit issue?

ereshidov commented 7 months ago

I agree, seems to be an Apple / Safari / Webkit issue and not a firebase issue. Also, I don't think it is the same as https://bugs.webkit.org/show_bug.cgi?id=252544 - this one is fixed and supposedly live in "the latest iOS 16 and 17 betas" from a message sent 2023-06-07… Should we open a new webkit issue?

Agreed, let's open a new ticket

Ping me on linkedin or twitter if you will need help with testing or code examples maybe

DoronTorangy commented 3 months ago

For me 'notificationclick' doesn't work at all on iOS, it also states that in here.

I'm testing on iOS 17.4.1. I do receive notifications just fine (I use FCM) but click does not work:

service-worker.ts

firebase.initializeApp(firebaseConfig)
const messaging = firebase.messaging()

messaging.onBackgroundMessage(payload => {
  console.log('This is called just fine', payload)
})

self.addEventListener('notificationclick', (event: any) => {
  console.log('NEVER CALLED, REGARDLESS IF APP IS DEAD, IN BACKGROUND OR IN FOREGROUND')
})

my-messaging-server.ts

...
await messaging.sendEach([
  ...,
  {
            token: "...",
            data: {
              ...
            },
            notification: {
              title: "Hello",
              body: "World",
            },
            webpush: {
              fcmOptions: {
                link: `/some-link-in-app`,
              },
            },
  }
])

On Android it automatically opens webpush.fcmOptions.link

egorlitsky commented 3 months ago

@DoronTorangy this is because you define notificationclick event-listener after loading a library. I've had the same issue. Refer https://github.com/firebase/quickstart-js/issues/102 for more details.

dlarocque commented 2 weeks ago

For me 'notificationclick' doesn't work at all on iOS, it also states that in here.

I'm testing on iOS 17.4.1. I do receive notifications just fine (I use FCM) but click does not work:

service-worker.ts

firebase.initializeApp(firebaseConfig)
const messaging = firebase.messaging()

messaging.onBackgroundMessage(payload => {
  console.log('This is called just fine', payload)
})

self.addEventListener('notificationclick', (event: any) => {
  console.log('NEVER CALLED, REGARDLESS IF APP IS DEAD, IN BACKGROUND OR IN FOREGROUND')
})

my-messaging-server.ts

...
await messaging.sendEach([
  ...,
  {
            token: "...",
            data: {
              ...
            },
            notification: {
              title: "Hello",
              body: "World",
            },
            webpush: {
              fcmOptions: {
                link: `/some-link-in-app`,
              },
            },
  }
])

On Android it automatically opens webpush.fcmOptions.link

If you are still experiencing this issue, please open a new bug in this repository.

I've not been able to reproduce this issue with Firebase 10.13.0, and Safari 17.6- so please mention what versions you're using when you submit the issue and steps to reproduce.

dlarocque commented 2 weeks ago

Seeing as the WebKit bug that has been causing this issue has been closed, and I'm not longer able to replicate the issue using latest Safari and Firebase versions, I believe this bug has been fixed.

Is anyone still experiencing this issue in the latest Safari and Firebase versions? If so, please share a full minimal reproduction that will help me confirm the bug.

snovakovic commented 2 weeks ago

@dlarocque We can still replicate this issue on latest iOS version (17.6.1). One thing to mention is that we tried on multiple devices and on some devices we where not able to replicate issue while on others we had same issue as this post explains when once in a while it works but most of the times it don't https://github.com/firebase/firebase-js-sdk/issues/7309#issuecomment-1567875612

Have you been able to confirm it works reliably on multiple devices?

atgillette commented 2 weeks ago

It's still happening for me with 17.6.1.

dlarocque commented 2 weeks ago

@dlarocque We can still replicate this issue on latest iOS version (17.6.1). One thing to mention is that we tried on multiple devices and on some devices we where not able to replicate issue while on others we had same issue as this post explains when once in a while it works but most of the times it don't #7309 (comment)

Have you been able to confirm it works reliably on multiple devices?

I have never been able to reproduce this issue. I have been able to reproduce #8444 in the past on my device, but I'm no longer able to. There is a potentially related bug in WebKit that has been causing other issues in this SDK- and it's pretty unreliable to reproduce, so maybe all of these SW event listener bugs are all being caused by this WebKit bug. https://bugs.webkit.org/show_bug.cgi?id=268797

dlarocque commented 1 week ago

This has been added to a list of known issues with FCM in iOS PWAs caused by WebKit bugs in our Wiki: https://github.com/firebase/firebase-js-sdk/wiki/Known-Issues