clients.openWindow()"不允许打开窗口。"在serviceWorker Google Chrome上

时间:2015-05-18 11:58:23

标签: google-chrome service-worker

我在Chrome版本42.0.2311.152m下进行测试,我希望实现在通知中打开一个窗口,如下例所示:(来源: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('/');
  }));
});

我的文件结构如下:
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

在service-worker.js中调用clients.openWindow(&#39; /&#39;)或clients.openWindow(&#39; https://myurl.no-ip.org/app/index.html&#39;)时,收到错误:

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

&#34;返回client.focus()&#34;永远不会达到这一行,因为client.url永远不会只是&#39; /&#39;。 看着

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" }

属性&#39;聚焦&#39;和&#39; visibilityState&#39;是正确的,正确的改变 通过手动对焦呼叫

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

我收到错误:

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

我认为问题在于网址不仅仅是&#39; /&#39;。你有什么想法吗?

非常感谢! 最好的问候 岸堤

1 个答案:

答案 0 :(得分:33)

您的代码适用于我,因此我将解释使用openWindow / focus的要求,以及如何避免“不允许[打开|关注]窗口”错误消息。

clients.openWindow()windowClient.focus()仅在点击通知后允许(至少在Chrome 47中),并且在此期间最多可以调用一个这些方法点击处理程序。此行为在https://github.com/slightlyoff/ServiceWorker/issues/602中指定。

如果您的openWindow / focus来电被拒绝,并显示错误消息

  

“不允许打开窗户。”对于openWindow
  “不允许聚焦窗户。” focus

然后您无法满足openWindow / focus的要求。例如(所有点也适用于focus,而不只是openWindow)。

  • openWindow在未点击通知时被调用。
  • 在返回openWindow处理程序后调用
  • notificationclick,并且您没有使用承诺调用event.waitUntil
  • 传递给openWindow的承诺解决后,
  • event.waitUntil被调用。
  • 承诺未得到解决,但过了“太长时间”(10 seconds in 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)。