Closed
Description
Operating System
IOS 18
Environment (if applicable)
Safari
Firebase SDK Version
11.1.0
Firebase SDK Product(s)
Messaging
Project Tooling
React Application. webpack
Detailed Problem Description
My PWA is deployed to /web-pwa context path on my server and it does not receive notification in IOS (Android works fine) presumably because of getting a wrong token when worker scope is dffer from default '/'
Steps and code to reproduce issue
App.js
import {initializeApp} from "firebase/app";
import {getMessaging, getToken} from "firebase/messaging";
const firebaseConfig = {
apiKey: "...",
authDomain: "...",
databaseURL: "...",
projectId: "...",
storageBucket: "...",
messagingSenderId: "...",
appId: "...",
measurementId: "..."
};
export default class App extends React.Component{
init = ()=>{
if ('serviceWorker' in navigator) {
if ('Notification' in window) {
Notification.requestPermission().then((permission) =>{
if (permission === 'granted') {
this.registerWorkers();
}
}).catch(function(error) {
console.log('error:', error);
});
}
}
registerWorkers = () => {
let r;
navigator.serviceWorker.register('/web-pwa/firebase-messaging-sw.js', {scope: '/web-pwa/'})
.then(swRegistration => {
console.log('Service Worker is registered for scope '+swRegistration.scope);
r = swRegistration;
console.log(swRegistration.scope);
return navigator.serviceWorker.ready;
}).then(registration=>{
console.log('Service Worker is '+ (registration.active?'active':'inactive') + ' for scope:' + registration.scope);
return registration.pushManager.subscribe({
userVisibleOnly: true,
applicationServerKey: urlBase64ToUint8Array('...my-vapid-key...')
});
})
.then(subscription => {
this.logString('web-push-subscription:'+ JSON.stringify(subscription.toJSON()));
if(!this.state.fcmToken) {
getToken(messaging, {
serviceWorkerRegistration: r,
}).then(token => {
console.log('got FCM: '+ token);
this.setState({fcmToken: token});
}).catch(error => {
console.error('Error getting token:', error.message);
});
}else{
this.logString('FCM is already present')
}
})
.catch(error => {
console.error('Service Worker registration failed:', error);
});
console.log('navigator.serviceWorker.addEventListener')
}
render(){
return(
<div className="App">
<button onClick={this.init}>initialize</button>
<input type='text' value='{this.state.fcmToken}'/>
</div>
);
}
}
function urlBase64ToUint8Array (base64String){
const padding = '='.repeat((4 - (base64String.length % 4)) % 4);
const base64 = (base64String + padding).replace(/-/g, '+').replace(/_/g, '/');
const rawData = window.atob(base64);
const outputArray = new Uint8Array(rawData.length);
for (let i = 0; i < rawData.length; ++i) {
outputArray[i] = rawData.charCodeAt(i);
}
return outputArray;
};
firebase-messaging-sw.js
importScripts('https://www.gstatic.com/firebasejs/11.1.0/firebase-app-compat.js');
importScripts('https://www.gstatic.com/firebasejs/11.1.0/firebase-messaging-compat.js');
const firebaseConfig = {
apiKey: "...",
authDomain: "...",
databaseURL: "...",
projectId: "...",
storageBucket: "...",
messagingSenderId: "...",
appId: "...",
measurementId: "..."
};
firebase.initializeApp(firebaseConfig);
// Retrieve firebase messaging
const messaging = firebase.messaging();
self.addEventListener('push', function(event) {
event.waitUntil(
self.clients.matchAll({ type: 'window', includeUncontrolled: true }).then(function(clientList) {
if (clientList.length > 0) {
clientList.forEach(client=>{
client.postMessage({type: 'push', data: {}});
});
}else{
self.clients.openWindow('/web-pwa/').then(function(client) {
client.postMessage({type: 'push', data: {}});
});
}
})
);
let notificationTitle = 'test';
let notificationOptions = {
body: 'hello',
}
try {
let payload = event.data.json();
console.log('push with payload', payload);
notificationTitle = payload.data.id;
notificationOptions = {
body: payload.data.messageId,
data: {...payload.data}
};
}catch (e){
console.log(e);
}
event.waitUntil(
self.registration.showNotification(notificationTitle+'-push', notificationOptions)
);
});
self.addEventListener('notificationclick', function(event) {
event.notification.close();
event.waitUntil(
self.clients.matchAll({ type: 'window', includeUncontrolled: true }).then(function(clientList) {
if (clientList.length > 0) {
let client = clientList[0];
client.focus();
client.postMessage({type: 'notificationPressed', data: event.notification.data});
}else{
self.clients.openWindow('/web-pwa/').then(function(client) {
client.postMessage({type: 'notificationPressed', data: event.notification.data});
});
}
})
);
});
When I press 'initialize' button in PWA installed on real devices (Android phone and iPhone) I'm getting a FCM token successfully. But when I send test notifications from firebase console using tokens I got from apps, Android is showing notifications as expected, but no luck in IOS.