clients.openWindow()“不允许打开窗口”。在一个serviceWorker谷歌浏览器 [英] clients.openWindow() "Not allowed to open a window." on a serviceWorker Google Chrome

查看:362
本文介绍了clients.openWindow()“不允许打开窗口”。在一个serviceWorker谷歌浏览器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在Chrome版本42.0.2311.152m下进行测试,并且想要实现在此示例中的通知类型中打开窗口:(source: 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();

//这看起来是看当前是否已经打开,
//如果是
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


当调用clients.openWindow('/')或clients.openWindow(' https://myurl.no-ip.org/app/index.html ) -worker.js,我收到错误:

  {code:15,
message:不允许打开一个窗口。,
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()});

我收到错误消息:

<$ p $ {code:15,
message:不允许关注窗口,
name:InvalidAccessError}

我认为问题在于url不仅仅是'/'。你有什么想法吗?



非常感谢你!

祝你好运
Andi

解决方案

你的代码适合我,所以我将解释使用 openWindow / focus ,以及如何避免不允许[open | focus]窗口错误消息。



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



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


不允许打开窗口。 for openWindow

不允许关注窗口。 for focus


然后你没有满足 openWindow / focus 。例如(所有的点也适用于焦点,而不仅仅是 openWindow )。


$


确实需要 openWindow / notificationclick 处理程序完成之前,最多只会调用焦点



我之前说过,问题wo中的代码rks,所以我会展示另一个带注释的例子。


$ b

  // serviceworker.js 
self.addEventListener('notificationclick',function(event){
//关闭通知。
event.notification.close();

//示例:3秒后打开窗口。
//(这样做是非常糟糕的用户体验,因为
//用户不知道3秒钟会发生什么。)
var promise = new Promise(function(resolve ){
setTimeout(resolve,3000);
})。then(function(){
//返回openWindow返回的promise,以防万一
//打开任何来源只适用于Chrome 43+。
return clients.openWindow('https://example.com');
});

//现在等待承诺保持许可权。
event.waitUntil(promise);
});

index.html

< button id =show-notification-btn>显示通知< / 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){
//显示通知如果用户点击在这个
//通知,然后通知点击被解雇。
registration.showNotification('Test');
});
}
});
}
< / script>

PS。服务人员仍在开发中,所以值得一提的是,我已经验证上述评论在Chrome 49中是正确的,并且该示例在Chrome 43+中运行(并打开 / 而不是 https://example.com 也适用于Chrome 42)。


I'm testing under Chrome Version 42.0.2311.152m and I want to implement to open a window on a notificationclick like in this example: (source: 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('/');
  }));
});

My filestructure is 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

I have the issue that I always get an

InvalidAccessError

when calling clients.openWindow('/') or clients.openWindow('https://myurl.no-ip.org/app/index.html') in the service-worker.js, I receive the error:

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

The "return client.focus()" line is never reached because the client.url is never just '/'. Looking at

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

I see my current WindowClient:

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

The properties 'focused' and 'visibilityState' are correct and change correctly.
By doing a manual focus call

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

I receive the error:

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

I think the problem is that url is not just '/'. Do you have any ideas for that?

Thank you very much!
Best regards
Andi

解决方案

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.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 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).

这篇关于clients.openWindow()“不允许打开窗口”。在一个serviceWorker谷歌浏览器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆