37

My site uses desktop notifications which have never worked on mobile devices but I've recently started to receive the following exception in Chrome Version 42.0.2311.108 on Android 4.4:

Failed to construct 'Notification': Illegal constructor. Use ServiceWorkerRegistration.showNotification() instead. TypeError: Failed to construct 'Notification': Illegal constructor. Use ServiceWorkerRegistration.showNotification() instead.

My notification code is simple, after checking if the user has granted permissions I initialize a new Notification object as follows:

var notification = new Notification(messageOptions.title, { icon: messageOptions.icon });

How do I change this code to use the ServiceWorkerRegistration.showNotification, which comes up as undefined, to support notifications in the mobile version of Chrome or if that isn't possible do a feature detection and prevent the exceptions from happening if this really isn't supported [yet].

SignalRichard
  • 1,572
  • 2
  • 17
  • 32
  • 1
    I just put this together, does this work for you? http://jsbin.com/rexede/latest/quiet/ – Matt Gaunt Apr 27 '15 at 13:29
  • Same error message for your example. Works fine on desktop chrome but fails on android. Chrome 42.0.2311.109 on Android 5.1.0; Nexus 5 Build/LMY47I – user1397423 Apr 27 '15 at 20:19

2 Answers2

29

See crbug.com/481856 on the Chrome issue tracker:

new Notification() is on the path to deprecation, because it implicitly assumes that the page will outlive the notification, which is very unlikely on mobile (and far from guaranteed on desktop too).

Hence we will never implement it on Android. We might one day remove it on desktop too, after a deprecation period.

Websites should use ServiceWorkerRegistration.showNotification() (see spec) instead whenever it is available.

The best way I can think of to feature-detect new Notification() is to try it (before you have permission) and catch the error:

function isNewNotificationSupported() {
    if (!window.Notification || !Notification.requestPermission)
        return false;
    if (Notification.permission == 'granted')
        throw new Error('You must only call this *before* calling Notification.requestPermission(), otherwise this feature detect would bug the user with an actual notification!');
    try {
        new Notification('');
    } catch (e) {
        if (e.name == 'TypeError')
            return false;
    }
    return true;
}

You could then use it like this:

if (window.Notification && Notification.permission == 'granted') {
    // We would only have prompted the user for permission if new
    // Notification was supported (see below), so assume it is supported.
    doStuffThatUsesNewNotification();
} else if (isNewNotificationSupported()) {
    // new Notification is supported, so prompt the user for permission.
    showOptInUIForNotifications();
}
Community
  • 1
  • 1
Matt Gaunt
  • 9,434
  • 3
  • 36
  • 57
  • 2
    Note that the linked Chrome issue has been [updated](https://github.com/whatwg/notifications/issues/26#issuecomment-126310459) in the meantime and now says `It seems we're keeping non-persistent notifications.` – Udo G Sep 24 '20 at 13:08
3

According to this:

Note: Trying to create a notification inside the ServiceWorkerGlobalScope using the Notification() constructor will throw an error.

If you want to send notification in a Service Worker, use self.registration.showNotification(). See https://developer.mozilla.org/en-US/docs/Web/API/ServiceWorkerRegistration/showNotification

Old Geezer
  • 14,854
  • 31
  • 111
  • 198