Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Define Purge Service Worker Registrations #1506

Open
wants to merge 2 commits into
base: main
Choose a base branch
from

Conversation

jungkees
Copy link
Collaborator

@jungkees jungkees commented Feb 26, 2020

This change adds an algorithm, Purge Service Worker Registrations, that
immediately unregister - by calling into Clear Registration - service
worker registrations for a given origin. It takes an origin and a
boolean argument for unclaiming controlled clients. This is designed for
Clear-Site-Data's "storage" directive. job's immediate unregister flag
added in this change can be used for unregister({immediate: true}) or
alternative designs as a TODO.

Issue: #614.
CSD issue: w3c/webappsec-clear-site-data#54.
CSD PR: w3c/webappsec-clear-site-data#63.


Preview | Diff

This change adds an algorithm, Purge Service Worker Registrations, that
immediately unregister - by calling into Clear Registration - service
worker registrations for a given origin. It takes an origin and a
boolean argument for unclaiming controlled clients. This is designed for
Clear-Site-Data's "storage" directive. job's immediate unregister flag
added in this change can be used for unregister({immediate: true}) or
alternative designs as a TODO.

Issue: #614.
@jungkees
Copy link
Collaborator Author

jungkees commented Feb 26, 2020

I gave it a try for unblocking the kill-switch work for Clear-Site-Data: "storage". Please take a look.

/cc @asakusuma @n8schloss @asutherland @cdumez @youennf @slightlyoff @SteveBeckerMSFT

jungkees added a commit to jungkees/webappsec-clear-site-data that referenced this pull request Feb 26, 2020
Clear-Site-Data: "storage" has used Service Workers' unregister() as
Service Workers' had no external algorithm that allows immediate purging
of the service worker registrations. This change calls into Purging
Service Worker Reigstration algorithm defined in Service Workers with
the origin and intention to unclaim the controlled clients when
"storage" directive is specified.

Issue: w3c#54.
Service Workers issue: w3c/ServiceWorker#614.
Service Workers PR: w3c/ServiceWorker#1506.
Copy link

@asakusuma asakusuma left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for getting the ball rolling here, @jungkees. And thanks for getting the initial implementation done @SteveBeckerMSFT

docs/index.bs Outdated
1. Assert: |jobQueue| is not null.
1. [=While=] |jobQueue| is not empty:
1. Let |job| be the first item in |jobQueue|.
1. Invoke [=Reject Job Promise=] with |job| and "{{AbortError}}" {{DOMException}}.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not very familiar with speccing errors, but is there a way to ensure that the error message makes it clear that the promise was rejected because the service worker was purged?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think "AbortError" DOMException is most relevant for the error context here. When the service operation sends out the Clear-Site-Data: "storage", it can expect the pending register/update/unregister jobs to be aborted and delete from the queue. Would it make sense?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should use "AbortError" for https://dom.spec.whatwg.org/#aborting-ongoing-activities generally. I'd use the generic error here type. (The message that goes with it is currently not standardized and up to implementations.)

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changed it to TypeError.

docs/index.bs Outdated
1. Set |job|'s [=immediate unregister flag=].
1. Let |jobQueue| be [=scope to job queue map=][|job|'s [=job/scope url=], [=URL serializer|serialized=]].
1. Assert: |jobQueue| is not null.
1. [=While=] |jobQueue| is not empty:

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we only purge the job queue if unclaim is true? It might be unexpected to kill all in-flight jobs without also specifying unclaim.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I made the caller (Clear-Site-Data) purge the registrations with the unclaim enabled. I wanted to consider the possibility of any future change where a caller may want to purge the storage without unclaiming.

However, if our decision is making Clear-Site-Data: "strorage" unclaim by default, I can move the unclaiming steps into Unregister algorithm so it runs when job's immediate unregister flag is set.

docs/index.bs Outdated
1. If |unclaim| is true, then:
1. For each [=/service worker client=] |client| [=using=] |registration|:
1. Assert: |client|'s [=active service worker=] is not null.
1. Invoke [=Handle Service Worker Client Unload=] with |client|.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's the purpose of calling Handle Service Worker Client Unload here? I believe Handle Service Worker Client Unload will call Try Unregister and Try Activate, not sure either of those are necessary since we already did unregister and we shouldn't be trying to activate a new service worker.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you're right. My concern was about taking care of the registration with different scope than the one that is claimed for in the case of claim(): #682. But as we basically purge the registration here entirely, we don't need to update the registration state. Can @asakusuma or anyone confirm that is right?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree we shouldn't be calling "Handle Service Worker Client Unload" here (the client isn't unloading). The registration state is already purged in the unregister job.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed the step calling into Handle Service Worker Client Unload.

Copy link
Contributor

@jakearchibald jakearchibald left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a great step in the right direction. However, it feels like we need to do something about the currently running job.

Right now, this PR dequeues the job and rejects the promise, but it might still be half-way through the update algorithm. As a result, it might start trying to modify the registration after unregistration.

I tried to spec this in detail last year, but ended up feeling like I would have to rewrite the whole spec to accommodate every algorithm potentially aborting at any point. Maybe a slightly hand-wavey way would be better?

Maybe we could have an aborted flag on job, then each algorithm could have a bit of prose like:

If, at any point, job's aborted flag is set, abort this algorithm immediately, abort any ongoing fetches created in steps 3.4, 7, 9.5, and terminate the worker created in step 5.

Would that work?

docs/index.bs Outdated

1. [=map/For each=] <var ignore=''>scope</var> → |registration| of [=scope to registration map=]:
1. Let |scopeURL| be |registration|'s [=service worker registration/scope url=].
1. If |scopeURL|'s [=/origin=] is |origin|, then:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: I tend to invert early-exit conditions like this.

  1. If |scopeURL|'s [=/origin=] is not |origin|, then [=continue=].

Then you don't need to nest the remaining steps.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed. That's nicer indeed.

docs/index.bs Outdated
1. [=queue/Dequeue=] from |jobQueue|.
1. Invoke [=Schedule Job=] with |job|.
1. Wait until |job|'s [=job promise=] settles.
1. If |unclaim| is true, then:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If unclaim is false, wouldn't that leave pages being controlled by a service worker in a "redundant" state? That doesn't seem right. If we're ripping the service worker out, surely we have to unclaim too?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I thought deleting registration and maintaining controller as two separate primitives, but agree to your point that it wouldn't be useful to keep the controller which is in "redundant" state. I moved unclaim steps into Unregister that unconditionally runs when the immediate unregister flag is set.

docs/index.bs Outdated
1. If |unclaim| is true, then:
1. For each [=/service worker client=] |client| [=using=] |registration|:
1. Assert: |client|'s [=active service worker=] is not null.
1. Invoke [=Handle Service Worker Client Unload=] with |client|.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree we shouldn't be calling "Handle Service Worker Client Unload" here (the client isn't unloading). The registration state is already purged in the unregister job.

  - Moving unclaim steps to Unregister running unconditionally when
    immediate unregister flag is set
  - Removing Handle Service Worker Client Unload in unclaim steps
  - Using TypeError instad of AbortError DOMExcetion
@jungkees
Copy link
Collaborator Author

it feels like we need to do something about the currently running job.

Agreed. I'll follow up on this as a TODO.

@annevk
Copy link
Member

annevk commented Jun 12, 2020

One thing that has happened since February is that we're getting much closer to being able to integrate the underlying semantics of Clear-Site-Data into the storage standard. This is being discussed in whatwg/storage#88 and issues referenced from there.

https://storage.spec.whatwg.org/ also defines a set of primitives that service workers need to use to store their data. We're currently working on doing the same for localStorage/sessionStorage/IDB.

The work you are doing here really ties into all that. It might be worth tackling as a follow-up, but I thought I'd raise it now to create some more awareness and alert you to the possibility that the particular way these things integrate might change a bit.

@jungkees
Copy link
Collaborator Author

@annevk, thanks for the heads up. Sounds great. Looking forward to plugging into the primitives Storage comes up with.

@wanderview
Copy link
Member

What is the status of this PR? Is it close to merging? I think Microsoft already implemented and shipped the clear-site-data purging in chromium.

@jungkees
Copy link
Collaborator Author

Things we should address to merge this PR:

I'm afraid I can't find cycles now. If anyone can help with this, I'd appreciate that.

@asakusuma
Copy link

@jungkees @jakearchibald would it be possible to merge this PR or add a placeholder so that we can start cross linking from other specs and proposals, like storage/buckets?

@jakearchibald
Copy link
Contributor

I think we should remove some of the not-quite-correct normative steps, but happy to land a placeholder algorithm.

Base automatically changed from master to main February 4, 2021 19:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants