2015-05-18 10 views
5

sto testando in Chrome versione 42.0.2311.152m e voglio attuare per aprire una finestra su un notificationclick come in questo esempio: (fonte: https://developer.mozilla.org/en-US/docs/Web/API/WindowClient )clients.openWindow() "Non è consentito aprire una finestra." su un ServiceWorker Google Chrome

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('/'); 
    })); 
}); 

mio filestructure è come:
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

ho il problema che ottengo sempre un

InvalidAccessError

quando si chiama clients.openWindow ('/') o clients.openWindow ('https://myurl.no-ip.org/app/index.html') nei servizi-worker.js, ricevo l'errore:

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

Il "cliente tornare. focus() "linea non viene mai raggiunta perché client.url non è mai solo '/'. Guardando

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

vedo la mia attuale WindowClient:

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

Le proprietà 'concentrato' e 'visibilityState' siano corretti e cambiare in modo corretto.
Facendo un focus di chiamata manuale

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

ricevo l'errore:

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

Credo che il problema è che l'URL non è solo '/'. Hai qualche idea per questo?

Grazie mille!
migliori saluti
Andi

+0

Non ho ancora visto questo errore specifico e non riesco a riprodurlo da solo. Chrome 43 sarà presto la versione stabile (e già è su alcune piattaforme). Puoi riprodurlo lì o in Chrome dev/Canary? –

+0

Abbiamo un codice simile che sembra funzionare su Chrome su Mac, ma non su Chrome su Windows. Con quale sistema operativo state testando? –

risposta

20

Il tuo codice funziona bene per me, così ti spiego i requisiti per l'utilizzo di openWindow/focus, e come si può evitare il "non ha permesso di [open | focus] di una finestra " messaggio di errore.

clients.openWindow() e windowClient.focus() sono ammessi solo dopo un clic sulla notifica (in Chrome 47, almeno), e al massimo uno di questi metodi possono essere chiamati, per tutta la durata del gestore click. Questo comportamento è stato specificato in https://github.com/slightlyoff/ServiceWorker/issues/602.

Se la chiamata openWindow/focus viene respinto con il messaggio di errore

"Not allowed to open a window." for openWindow
"Not allowed to focus a window." for focus

allora non soddisfaceva i requisiti di openWindow/focus. Ad esempio (tutti i punti si applicano anche a focus, non solo a openWindow).

  • openWindow è stato chiamato mentre la notifica non è stata selezionata.
  • openWindow è stato chiamato dopo che è stato restituito il gestore notificationclick e non è stato chiamato event.waitUntil con una promessa.
  • openWindow è stato chiamato dopo che la promessa passata a event.waitUntil è stata risolta.
  • La promessa non è stata risolta, ma ci è voluto "troppo tempo" (10 seconds in Chrome), quindi è scaduta l'autorizzazione temporanea per chiamare openWindow.

E 'davvero necessario che openWindow/focus è chiamato più di una volta, e prima che il gestore notificationclick finisce.

Come ho detto prima, il codice nella domanda funziona, quindi mostrerò un altro esempio annotato.

// 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. I service worker sono ancora in fase di sviluppo, quindi vale la pena ricordare che ho verificato che le note sopra riportate siano corrette in Chrome 49 e che l'esempio funzioni in Chrome 43+ (e che apra / invece di https://example.com funzioni anche in Chrome 42).

+0

Penso che, signore, abbia bisogno di più upvotes. –

+0

Qual è lo scopo del timeout? Potresti aprire subito la finestra? – capouch

+1

@capouch Per dimostrare il comportamento asincrono. –

Problemi correlati