22

Chrome バージョン 42.0.2311.152m でテストしており、次の例のように通知クリックでウィンドウを開くように実装したいと考えています: (ソース: https://developer.mozilla.org/en-US/docs/Web/API /ウィンドウクライアント )

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

私はいつも得るという問題があります

無効なアクセス エラー

client.openWindow('/') または client.openWindow(' https://myurl.no-ip.org/app/index.html ') を service-worker.js で呼び出すと、次のエラーが表示されます。

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

client.url が単なる「/」ではないため、「return client.focus()」行に到達することはありません。見つめている

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 が「/」だけではないことだと思います。そのためのアイデアはありますか?

どうもありがとうございました!
よろしく
アンディ

4

1 に答える 1

51

あなたのコードは私にとっては問題なく動作するので、openWindow/を使用するための要件focusと、「ウィンドウを [open|focus] することは許可されていません」というエラー メッセージを回避する方法について説明します。

clients.openWindow()通知をwindowClient.focus()クリックした後にのみ許可され(少なくともChrome 47では)、クリックハンドラーの期間中、これらのメソッドの最大1つを呼び出すことができます。この動作はhttps://github.com/slightlyoff/ServiceWorker/issues/602で指定されています。

openWindow/focus呼び出しがエラー メッセージで拒否された場合

「窓を開けてはいけません。」「ウィンドウにフォーカスすることは許可されopenWindow
ていません。」為にfocus

openWindow/の要件を満たしていませんfocus。たとえば (すべてのポイントfocusは だけでなく にも適用されますopenWindow)。

  • openWindow通知がクリックされていないときに呼び出されました。
  • openWindowハンドラーが返された後に呼び出されましたが、promise を使用してnotificationclick呼び出していませんでした。event.waitUntil
  • openWindowに渡された promiseevent.waitUntilが解決された後に呼び出されました。
  • promise は解決されませんでしたが、「時間がかかりすぎた」( Chrome では 10 秒) かかったため、呼び出しの一時的な許可がopenWindow期限切れになりました。

openWindow/は、ハンドラーが終了focusする前に、多くても 1 回呼び出す必要があります。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 以降で機能すること (およびChrome 42 でも機能する/代わりに開くこと) を確認したことは言及する価値があります。https://example.com

于 2015-12-13T10:47:22.827 に答える