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

iOS PWA notification click doesn't open the app with proper URL when the app is killed #7698

Open
adampfw opened this issue Oct 13, 2023 · 12 comments

Comments

@adampfw
Copy link

adampfw commented Oct 13, 2023

Operating System

iOS 16.6, iOS 16.4.1

Browser Version

iOS Safari 16.6, iOS Safari 16.4

Firebase SDK Version

9.22.2

Firebase SDK Product:

Messaging

Describe your project's tooling

App is build with Rails and Turbo, compiled with Webpack.
Service Worker is pure JS file available at domain.com/firebase-messaging-sw.js.

Describe the problem

PWA notification click opens PWA with start url, it's not respecting correct URL passed in click_action property inside notification object.

It happens only when the PWA is killed - when the PWA is in the background it gets focused and I receive service worker message with notification-clicked type so I am able to do proper redirect.

It happens only on iOS devices - Android works perfect both when the app is killed and when the app is in the background.

Steps and code to reproduce issue

My manifest.json file has following code:

{
  "name": "My app",
  "short_name": "My app",
  "start_url": "/page",
  "scope": "/",
  "description": "My app description",
  "display": "standalone",
  "theme_color": "#ffffff",
  "background_color": "#ffffff",
  "icons": [
    {
      "src": "https://cdn.mydomain.com/icon192.png",
      "sizes": "192x192",
      "type": "image/png"
    },
    {
      "src": "https://cdn.mydomain.com/icon512.png",
      "sizes": "512x512",
      "type": "image/png"
    }
  ],
  "version": 1
}

My app registers Service Worker with:

navigator.serviceWorker.register('/firebase-messaging-sw.js', { scope: '/page' })

My Service Worker file is available at domain.com/firebase-messaging-sw.js with following code:

self.importScripts('https://www.gstatic.com/firebasejs/9.22.2/firebase-app-compat.js')
self.importScripts('https://www.gstatic.com/firebasejs/9.22.2/firebase-messaging-compat.js')

firebase.initializeApp({
  apiKey: '***',
  authDomain: '***',
  projectId: '***',
  messagingSenderId: '***',
  appId: '',
})

const messaging = firebase.messaging()

self.addEventListener('fetch', function () {})

self.addEventListener('install', function () {})

self.addEventListener('activate', function () {})

When app initializes it execute following code to get messaging token and send it to backend:

const messaging = getMessaging()

getToken(messaging, {
  serviceWorkerRegistration: serviceWorkerRegistration,
  vapidKey: '***'
}).then((token) => {
  registerTokenOnBackend()
})

Also the app has event listener to execute proper redirect on notificaton-click event:

 navigator.serviceWorker.onmessage = (event) => {
    if (event.data.messageType === 'notification-clicked') {
      if (location.href !== event.data.notification.click_action) {
        Turbo.visit(event.data.notification.click_action)
      }
    }
  }

Backend sends FCM notification with following payload:

title: "Hello!",
body: "It's me!",
icon: "https://www.domain.com/favicon.png",
click_action: "https://www.domain.com/page/url_i_want_to_visit"

I receive corrent notification both on Android and iOS devices. But when I click a notification:

  • Android device
    • when PWA is killed
      • PWA gets open on proper URL ✅
    • when PWA is on the background
      • PWA gets focused, notification-clicked handler fires and I redirect user using Turbo ✅
  • iOS device
    • when PWA is killed
      • PWA gets open on start url ❌
    • when PWA is in the background
      • PWA gets focused, notification-clicked handler fires and I redirect user using Turbo ✅

On Android devices when the app is killed

@adampfw adampfw added new A new issue that hasn't be categoirzed as question, bug or feature request question labels Oct 13, 2023
@jbalidiong jbalidiong added needs-attention and removed new A new issue that hasn't be categoirzed as question, bug or feature request labels Oct 13, 2023
@adampfw
Copy link
Author

adampfw commented Oct 19, 2023

Issue update:

Looks like the same thing happens when iOS app is in the background for several hours (about 6) - in this case notification click also opens the PWA on the root URL, without respecting click_action URL from notification payload.

@adampfw
Copy link
Author

adampfw commented Nov 29, 2023

@jbalidiong Do you have any info or update about this one?

@Merwan1010
Copy link

@adampfw
Can you share a github link ? Thank you

@Cyril212
Copy link

Have the same issue. Hope it will be resolved soon.

@givip
Copy link

givip commented Aug 3, 2024

The root issue discussion is here https://bugs.webkit.org/show_bug.cgi?id=268797

@dlarocque
Copy link
Contributor

The root issue discussion is here https://bugs.webkit.org/show_bug.cgi?id=268797

@givip I was relieved to see that there's already an open WebKit bug for this, but unfortunately I can't reproduce the behaviour described in the bug. I've tried a variety of cases, and notificationclick events seem to always be fired. I'm interested to see whether the WebKit team can reproduce this.

@dlarocque
Copy link
Contributor

Hey @adampfw, are you still experiencing this issue?

Could you confirm whether you're able to reproduce the behaviour described in the open WebKit bug https://bugs.webkit.org/show_bug.cgi?id=268797?

@givip
Copy link

givip commented Aug 27, 2024

@dlarocque You can reproduce it by sending push notification to the killed Mobile Safari PWA ONLY.

Code with the problem is here

let client = await getWindowClient(url);

getWindowClient() is not null, but the window is not fully ready to receive channel messages as described here https://bugs.webkit.org/show_bug.cgi?id=268797#c21

In fact, notificationclick is always called, but firebase logic behind this click is not properly working.

We workarounded this issue by posting channel message again after a 5 sec delay.

@adampfw
Copy link
Author

adampfw commented Aug 27, 2024

@dlarocque I'm still expecting the issue. I agree with @givip.

@dlarocque
Copy link
Contributor

@dlarocque You can reproduce it by sending push notification to the killed Mobile Safari PWA ONLY.

Code with the problem is here

let client = await getWindowClient(url);

getWindowClient() is not null, but the window is not fully ready to receive channel messages as described here https://bugs.webkit.org/show_bug.cgi?id=268797#c21

In fact, notificationclick is always called, but firebase logic behind this click is not properly working.

We workarounded this issue by posting channel message again after a 5 sec delay.

As I mentioned, I am not able to reproduce the bug- I've tested this on a PWA. It may be that I'm not able to reproduce this on my device because my window client just happens to be ready to receive messages by the time they're sent and so the timing issue doesn't arise.

Thanks for sharing the workaround you're using- hopefully this is useful for others who are seeing this issue. Just to surface it here, this is the workaround suggested in the Bugzilla thread (https://bugs.webkit.org/show_bug.cgi?id=268797#c20):

self.addEventListener('notificationclick', (event) => {
  let client_count = 0;
  return new Promise((resolve, reject) => {
    clients.matchAll({ 
      type:'window', 
      includeUncontrolled:true // optional based on your requirements
    })
    .then((client_list) => {
      client_list.forEach((client) => {
        if (client.url == YOUR_URL) { // or similar based on your requirements
          client_count++;
          delayed_function(() => { client.postMessage(`Scenario A ${event.notification.title}`); });
        }
      });
      if (!client_count) {
        clients.openWindow(YOUR_URL)
        .then((client) => {
          delayed_function(() => { client.postMessage(`Scenario B ${event.notification.title}`); });
        });
      }
    })
    .catch((e) => {
      console.error('clients.matchAll error', e);
    });
    if (client_count) {
      resolve();
    } else {
      reject();
    }
  });
});

function delayed_function(f) {
  setTimeout(() => {
    f();
  }, 3000); // guestimate - ymmv but if it doesn't fire then make this longer
}

@dlarocque
Copy link
Contributor

It looks like this WebKit bug is causing other issues in our SDK: #8002

@dlarocque dlarocque removed the question label Sep 6, 2024
@dlarocque
Copy link
Contributor

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

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

No branches or pull requests

7 participants