[w3c/ServiceWorker] Provide a way to skipWaiting when the last tab refreshes (#1238)

When you have a single ("last/only") tab/client controlled by a Service Worker `v1`, and a new `v2` Service Worker installs, the `v2` SW goes into a "waiting" state. The `v2` SW activates when the last client closes.

Surprisingly, the `v2` Service Worker doesn't activate when the last client refreshes/navigates to a new page, because the navigation request initiates while the last/only tab is still open, so the `v1` Service Worker handles it; I think many developers don't realize that navigation requests start that early.

If we wanted to mitigate the surprise, the "obvious" thing to do would be to always delay the navigation request when there's a `v2` Service Worker waiting, activate the `v2` SW, and let `v2` control the navigation request instead.

But there's a problem. At least one kind of response, where the `Content-Disposition: attachment` header is set, can cause the browser to just initiate a download and cancel the navigation. That would leave a tab that was loaded in `v1` under the control of the `v2` Service Worker, which may be unsafe.

What I'd like is a way of expressing to the Service Worker lifecycle that I know it's safe for the `v2` Service Worker to activate when the last/only client navigates.

Jake suggested a `navigation` event listener, like this:

```js
self.addEventListener('navigation', event => {
  if (registration.waiting) {
    event.waitUntil(
      clients.matchAll().then(clients => {
        if (clients.length < 2) {
          return registration.waiting.skipWaiting();
        }
      })
    );
  }
});
```

The navigation would be delayed until the waiting worker activates, so the navigation request would go through the new worker.

That'd be really nice.

-- 
You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub:
https://github.com/w3c/ServiceWorker/issues/1238

Received on Thursday, 30 November 2017 05:26:19 UTC