clients.openWindow() "Not allowed to open a window." on a serviceWorker Google Chrome clients.openWindow() "Not allowed to open a window." on a serviceWorker Google Chrome google-chrome google-chrome

clients.openWindow() "Not allowed to open a window." on a serviceWorker Google Chrome


Your code works fine for me, so I'll explain the requirements for using openWindow / focus, and how you can avoid the "Not allowed to [open|focus] a window" error message.

clients.openWindow() and windowClient.focus() are only allowed after clicking the notification (in Chrome 47 at least), and at most one of these methods can be called, for the duration of the click handler. This behavior was specified in https://github.com/slightlyoff/ServiceWorker/issues/602.

If your openWindow / focus call is rejected with error message

"Not allowed to open a window." for openWindow
"Not allowed to focus a window." for focus

then you didn't satisfy the requirements of openWindow / focus. For example (all points also apply to focus, not just openWindow).

  • openWindow was called while the notification wasn't clicked.
  • openWindow was called after the notificationclick handler returned, and you did not call event.waitUntil with a promise.
  • openWindow was called after the promise passed to event.waitUntil was resolved.
  • The promise was not resolved, but it took "too long" (10 seconds in Chrome), so the temporary permission to call openWindow expired.

It is really necessary that openWindow / focus is called at most once, and before the notificationclick handler finishes.

As I said before, the code in the question works, so I'll show another annotated example.

// serviceworker.jsself.addEventListener('notificationclick', function(event) {    // Close notification.    event.notification.close();    // Example: Open window after 3 seconds.    // (doing so is a terrible user experience by the way, because    //  the user is left wondering what happens for 3 seconds.)    var promise = new Promise(function(resolve) {        setTimeout(resolve, 3000);    }).then(function() {        // return the promise returned by openWindow, just in case.        // Opening any origin only works in Chrome 43+.        return clients.openWindow('https://example.com');    });    // Now wait for the promise to keep the permission alive.    event.waitUntil(promise);});

index.html

<button id="show-notification-btn">Show notification</button><script>navigator.serviceWorker.register('serviceworker.js');document.getElementById('show-notification-btn').onclick = function() {    Notification.requestPermission(function(result) {        // result = 'allowed' / 'denied' / 'default'        if (result !== 'denied') {            navigator.serviceWorker.ready.then(function(registration) {                // Show notification. If the user clicks on this                // notification, then "notificationclick" is fired.                registration.showNotification('Test');            });        }    });}</script>

PS. Service workers are still in development, so it's worth mentioning that I've verified that the above remarks are correct in Chrome 49, and that the example works in Chrome 43+ (and opening / instead of https://example.com also works in Chrome 42).