Chrome clients.openWindow()“不允许打开窗口,”在serviceWorker谷歌浏览器上

dojqjjoe  于 2023-01-28  发布在  Go
关注(0)|答案(2)|浏览(177)

我正在Chrome Version 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
我有一个问题,我总是得到一个
无效访问错误
在service-worker.js中调用clients. openWindow("/")或clients. openWindow("https://myurl.no-ip.org/app/index.html")时,我收到错误消息:

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

不会到达"return client.focus()"行,因为client.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不仅仅是'/'。你对此有什么想法吗?
非常感谢!
最好的问候
安迪

5uzkadbs

5uzkadbs1#

您的代码运行良好,因此我将解释使用openWindow/focus的要求,以及如何避免出现“Not allowed to [open|焦点]窗口”错误信息。
clients.openWindow()windowClient.focus()只允许在点击通知后使用(至少在Chrome 47中),并且在点击处理程序的持续时间内,最多可以调用一个这些方法。
如果您的openWindow/focus呼叫被拒绝并显示错误消息
“不允许打开窗口。”对于openWindow
对于focus,“不允许聚焦窗口。”
那么你就没有满足openWindow/focus的要求。例如(所有的点也适用于focus,而不仅仅是openWindow)。

  • 在未单击通知时调用了openWindow
  • openWindow是在notificationclick处理程序返回后调用的,并且您没有使用promise调用event.waitUntil
  • 传递给event.waitUntil的承诺得到解决后调用了openWindow
  • 承诺没有得到解决,但花了“太长时间”(在Chrome中为10秒),因此调用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. Service worker还在开发中,所以值得一提的是,我已经验证了上面的评论在Chrome 49中是正确的,并且这个例子在Chrome 43+中也可以工作(并且打开/而不是https://example.com在Chrome 42中也可以工作)。

xu3bshqb

xu3bshqb2#

这对我很有效

addEventListener('notificationclick', (event) => {
    console.log('---- notification clicked ----')
    console.log(event)

    //using notification data to constract specific path 
    const data = event.notification.data
    console.log(data)
    let url  = 'https://exmaple.com'
    if(data){
        url += data['business'] ?
            `/business/messages/${data['respondent']}` :
            `/store/${data['respondent']}/questions`
    }

    console.log('new window url: ' + url)
    event.notification.close()
    //event should wait until we done
    event.waitUntil(
        //do we have some windows of our app?
        self.clients.matchAll({includeUncontrolled: true, type: 'window'})
            .then(list=>{
                console.log('total clients: '+list.length)
                if(list.length === 0){
                    //no windows of our app. We will open new one
                    console.log('no clients found')
                    return self.clients.openWindow(url)
                        .then((windowClient) => {
                            //we should focus new window and return Promise to terminate our event
                            return windowClient ? windowClient.focus() : Promise.resolve()
                        })
                }
                const client = list[0]
                console.log(client)
                //we have a window of our app. Let's focus it and return Promise 
                client.focus()
                console.log('--window focused---')
                return Promise.resolve()
            }))

})

相关问题