Bug 180816 - Service worker script fetching currently always uses the network cache
Summary: Service worker script fetching currently always uses the network cache
Status: RESOLVED FIXED
Alias: None
Product: WebKit
Classification: Unclassified
Component: Service Workers (show other bugs)
Version: WebKit Nightly Build
Hardware: Unspecified Unspecified
: P2 Normal
Assignee: Chris Dumez
URL:
Keywords: InRadar
Depends on:
Blocks:
 
Reported: 2017-12-14 09:41 PST by Chris Dumez
Modified: 2017-12-15 13:38 PST (History)
6 users (show)

See Also:


Attachments
WIP Patch (20.32 KB, patch)
2017-12-14 09:50 PST, Chris Dumez
no flags Details | Formatted Diff | Diff
Patch (30.35 KB, patch)
2017-12-14 10:55 PST, Chris Dumez
no flags Details | Formatted Diff | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Chris Dumez 2017-12-14 09:41:35 PST
Service worker script fetching currently always uses the network cache. This is incorrect as per:
- https://w3c.github.io/ServiceWorker/#update-algorithm (step 7.2)
Comment 1 Chris Dumez 2017-12-14 09:50:04 PST
Created attachment 329358 [details]
WIP Patch

Working on writing a test.
Comment 2 Chris Dumez 2017-12-14 10:55:00 PST
Created attachment 329365 [details]
Patch
Comment 3 Alex Christensen 2017-12-14 11:39:40 PST
Comment on attachment 329365 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=329365&action=review

> Source/WebCore/workers/service/server/SWServerJobQueue.cpp:315
> +    //   current time minus registration's last update check time is greater than 86400.

Why 86400?  Why do we want to force the cache to refresh every day?  Can't the server say how long it stays valid?
Comment 4 Alex Christensen 2017-12-14 11:40:53 PST
Comment on attachment 329365 [details]
Patch

As much as I think that's a bad idea, it's what the spec says.
Comment 5 youenn fablet 2017-12-14 11:42:08 PST
Comment on attachment 329365 [details]
Patch

I wonder whether cachePolicy could be a parameter of ServiceWorkerJobData.
That might help not passing this parameter explicitly everywhere.

Also, the test would be a good candidate for WPT upload. Would need to be testharness.js based and use WPT server.
Comment 6 Chris Dumez 2017-12-14 11:45:20 PST
(In reply to youenn fablet from comment #5)
> Comment on attachment 329365 [details]
> Patch
> 
> I wonder whether cachePolicy could be a parameter of ServiceWorkerJobData.
> That might help not passing this parameter explicitly everywhere.

The job is passed from the WebProcess to the StorageProcess. Then when we trigger the script fetch, we only pass the job identifier from the StorageProcess to the WebProcess and the WebProcess looks up the job in its own map.

Wether or not we want to bypass the cache is determined by the StorageProcess so it cannot be passed via the Job.

> 
> Also, the test would be a good candidate for WPT upload. Would need to be
> testharness.js based and use WPT server.
Comment 7 Chris Dumez 2017-12-14 11:55:07 PST
Comment on attachment 329365 [details]
Patch

Clearing flags on attachment: 329365

Committed r225916: <https://trac.webkit.org/changeset/225916>
Comment 8 Chris Dumez 2017-12-14 11:55:08 PST
All reviewed patches have been landed.  Closing bug.
Comment 9 Radar WebKit Bug Importer 2017-12-14 11:56:47 PST
<rdar://problem/36054182>
Comment 10 Geoffrey Garen 2017-12-14 17:55:59 PST
> As much as I think that's a bad idea, it's what the spec says.

I think we should file a PR to remove this policy from the spec. It is stupid.
Comment 11 Chris Dumez 2017-12-14 18:35:02 PST
(In reply to Geoffrey Garen from comment #10)
> > As much as I think that's a bad idea, it's what the spec says.
> 
> I think we should file a PR to remove this policy from the spec. It is
> stupid.

What exactly do you guys object to? You think updating a service worker should always consult the disk cache?

The way it is currently specified, it lets the developer decide what the behavior should be.
Comment 12 youenn fablet 2017-12-14 19:02:04 PST
Maybe the issue is the 84600 seconds rule.

Note that it might not have a terrific impact since it will in most cases end up in a conditional request. Nothing too harmful here. Maybe this overriding of HTTP cache headers is a security counter measure, it would be good to know the rationale.

The spec does not say a word about when a user agent is expected to stop a service worker. It may also update it based on its own rules. By having this simple rule, one benefit is some consistency in what web developers can expect across all browsers.

If we are offline though, the update will fail and IIUC, we might retry everytime until we succeed to have a response. If so, maybe there is some room for optimization.

In the same vein, in many cases, we might get the same script resource.
Might not be worth doing the full update thing in that case.
Comment 13 Geoffrey Garen 2017-12-14 19:04:25 PST
> What exactly do you guys object to? You think updating a service worker
> should always consult the disk cache?
> 
> The way it is currently specified, it lets the developer decide what the
> behavior should be.

I'm objecting to the needless inefficiency of reloading each service worker every day, even if there's a valid unexpired cache entry.

In what sense does the developer decide? Can the developer specify not to perform the daily reload?
Comment 14 Chris Dumez 2017-12-14 19:20:39 PST
(In reply to Geoffrey Garen from comment #13)
> > What exactly do you guys object to? You think updating a service worker
> > should always consult the disk cache?
> > 
> > The way it is currently specified, it lets the developer decide what the
> > behavior should be.
> 
> I'm objecting to the needless inefficiency of reloading each service worker
> every day, even if there's a valid unexpired cache entry.
> 
> In what sense does the developer decide? Can the developer specify not to
> perform the daily reload?

Ok. The 24-hour force reload is indeed not something the developer can control. As I said, Alex and your comment were so vague, I had no idea what your were objecting to.

I would agree that the 24-hour force reload is excessive, especially in combination with soft update (which we do not implement yet). Without soft update (which happens when a load is intercepted by a service worker), we only fetch the script when:
1. The page registers a service worker
2. The page calls update() explicitly on its service worker

Therefore, without soft update, this happens rarely.
Comment 15 Chris Dumez 2017-12-14 19:25:51 PST
(In reply to Chris Dumez from comment #14)
> (In reply to Geoffrey Garen from comment #13)
> > > What exactly do you guys object to? You think updating a service worker
> > > should always consult the disk cache?
> > > 
> > > The way it is currently specified, it lets the developer decide what the
> > > behavior should be.
> > 
> > I'm objecting to the needless inefficiency of reloading each service worker
> > every day, even if there's a valid unexpired cache entry.
> > 
> > In what sense does the developer decide? Can the developer specify not to
> > perform the daily reload?
> 
> Ok. The 24-hour force reload is indeed not something the developer can
> control. As I said, Alex and your comment were so vague, I had no idea what
> your were objecting to.
> 
> I would agree that the 24-hour force reload is excessive, especially in
> combination with soft update (which we do not implement yet). Without soft
> update (which happens when a load is intercepted by a service worker), we
> only fetch the script when:
> 1. The page registers a service worker
> 2. The page calls update() explicitly on its service worker
> 
> Therefore, without soft update, this happens rarely.

Soft update on handle fetch is specified at:
- https://w3c.github.io/ServiceWorker/#ref-for-soft-update①

This is the part that I think is too aggressive. But we do not implement this yet.

Without soft update, update only happens when the page's script explicitly asks us to update. Therefore, I think it is fine to go to the network in such case IMHO.
Comment 16 youenn fablet 2017-12-14 19:36:25 PST
Note also that this might be a protection against buggy service worker scripts.
It is indeed much more difficult to update a buggy service worker than a buggy web page.
Comment 17 Geoffrey Garen 2017-12-15 11:58:54 PST
> Without soft update, update only happens when the page's script explicitly
> asks us to update. Therefore, I think it is fine to go to the network in
> such case IMHO.

Yes, we agree: An explicit registration or call to update() is a fine time to reload from origin if 24 hours have passed; but soft update goes too far by mandating reload for each service worker every 24 hours.
Comment 18 youenn fablet 2017-12-15 12:32:13 PST
(In reply to Geoffrey Garen from comment #17)
> > Without soft update, update only happens when the page's script explicitly
> > asks us to update. Therefore, I think it is fine to go to the network in
> > such case IMHO.
> 
> Yes, we agree: An explicit registration or call to update() is a fine time
> to reload from origin if 24 hours have passed; but soft update goes too far
> by mandating reload for each service worker every 24 hours.

Some links:
- https://github.com/w3c/ServiceWorker/issues/514
- https://github.com/w3c/ServiceWorker/issues/715

Other browsers seem to implement this rule.

Buggy/malicious service workers blocking any kind of update seems to be one of the main reason for the current policy.
This policy allows preventing web developers from making errors that they could not easily fix.

I do not see any easy solution other than doing some regular pinging to the server or hoping that web devs will not fall into that very easy trap.
Do we have a better plan here?

The pinging modality could be optimized though, like updating all service worker at the same time for instance.
Comment 19 Geoffrey Garen 2017-12-15 12:43:36 PST
> Buggy/malicious service workers blocking any kind of update seems to be one
> of the main reason for the current policy.
> This policy allows preventing web developers from making errors that they
> could not easily fix.

I don't see how this situation is different from any other case of serving a bad main resource with a long cache expiry date. Yes, those bugs happen sometimes. But they have not brought down the internet, and there is nothing unique about ServiceWorkers here.

After an author has done appropriate user testing and deployed some software, caching for more than a day should be possible. Developers who only want to cache for a day can send a cache expiry value of 24 hours.
Comment 20 youenn fablet 2017-12-15 13:38:24 PST
> I don't see how this situation is different from any other case of serving a
> bad main resource with a long cache expiry date. Yes, those bugs happen
> sometimes. But they have not brought down the internet, and there is nothing
> unique about ServiceWorkers here.

I guess one difference is the amplitude of the risk.

If you screw things up on one main resource, only this main resource will be affected.
Chances are users will anyway navigate to some other resources and scripts can just bust the cache with fetch+"no-cache".

If you screw things up with the SW script, all web site main resources might be screwed.
There might be no possibility to inject new code to fix that bug.
One might need to rely on user cleaning the cache or doing some hard reload.