клиенты.openWindow () " не разрешается открывать окно."на serviceWorker Гугл Хром

Я тестирую в Chrome версии 42.0.2311.152 m, и я хочу реализовать, чтобы открыть окно на notificationclick, как в этом примере: (источник:https://developer.mozilla.org/en-US/docs/Web/API/WindowClient )

self.addEventListener('notificationclick', function(event) {
  console.log('On notification click: ', event.notification.tag);
  event.notification.close();

  // This looks to see if the current is already open and
  // focuses if it is
  event.waitUntil(clients.matchAll({
    type: "window"
  }).then(function(clientList) {
    for (var i = 0; i < clientList.length; i++) {
      var client = clientList[i];
      if (client.url == '/' && 'focus' in client)
        return client.focus();
    }
    if (clients.openWindow)
      return clients.openWindow('/');
  }));
});

мой filestructure является like:
https://myurl.no-ip.org/app/index.html
https://myurl.no-ip.org/app/manifest.json
https://myurl.no-ip.org/app/service-worker.js

у меня есть проблема, что я всегда получаю

InvalidAccessError

при вызове клиентов.openWindow ( ' /') или клиенты.openWindow ('https://myurl.no-ip.org/app/index.html') в сервис-работнике.js, я получаю ошибка:

{code: 15,
message: "Not allowed to open a window.",
name: "InvalidAccessError"}

"возвращения клиента.focus () " линия никогда не достигается, потому что клиент.url-адрес никогда не является просто'/'. Глядя на

clients.matchAll({type: "window"})
.then(function (clientList) {
console.log(clientList[0])});

Я вижу свой текущий WindowClient:

{focused: false,
frameType: "top-level",
url: "https://myurl.no-ip.org/app/index.html",
visibilityState: "hidden" }

свойства "focused" и "visibilityState" являются правильными и изменяются правильно.
Выполнив вызов ручной фокусировки

clients.matchAll({type: "window"})
    .then(function (clientList) {
    clientList[0].focus()});

Я получаю сообщение об ошибке:

{code: 15,
message: "Not allowed to focus a window.",
name: "InvalidAccessError"}

Я думаю, проблема в том, что url-адрес не просто'/'. У вас есть идеи для это?

большое спасибо!
С наилучшими пожеланиями
Анди

1 ответов


ваш код отлично работает для меня, поэтому я объясню требования для использования openWindow / focus, и как вы можете избежать сообщения об ошибке" не разрешено [открывать|фокусировать] окно".

clients.openWindow() и windowClient.focus() разрешены только после нажатия на уведомление (по крайней мере, в Chrome 47), и не более один из этих методов можно вызвать, на время работы обработчика click. Это поведение было указано в https://github.com/slightlyoff/ServiceWorker/issues/602.

если openWindow / focus отклонить вызов с сообщением об ошибке

" не разрешается открывать окно.- за openWindow
- Нельзя фокусировать окно.- за focus

тогда вы не удовлетворяли требованиям openWindow / focus. Например (все точки также относятся к focus не только openWindow).

  • openWindow был звонил, когда уведомление не было нажато.
  • openWindow название notificationclick обработчик вернулся, и вы не позвонили event.waitUntil с обещанием.
  • openWindow был вызван после того, как обещание перешло к event.waitUntil был решен.
  • 10 секунд в Chrome), поэтому временное разрешение на вызов openWindow истек.

это действительно необходимо, что openWindow / focus вызывается не более одного раза, а перед notificationclick обработчик закончит работу.

как я уже говорил, код в вопросе работает, поэтому я покажу еще один аннотированный пример.

// serviceworker.js
self.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. Сервисные работники все еще находятся в разработке, поэтому стоит отметить, что я проверил, что вышеуказанные замечания верны в Chrome 49, и что пример работает в Chrome 43+ (и открытие / вместо https://example.com также работает в Chrome 42).