+ A [=push subscription=] has an associated scope, which
+ is a [=/URL=].
+
+
+ A [=push subscription=] is considered to have a window-accessible scope when its [=push subscription/scope=] is
+ a [=/list=] of [=list/size=] 1 and [=push subscription/scope=][0] is the empty string.
+
+
+ I.e., the [=url/path=] component of the [=/URL=] serializes as "`/`".
A push subscription has an associated push endpoint. It MUST be the
@@ -192,12 +202,9 @@
- If the user agent has to change the keys for any reason, it MUST fire the
- "`pushsubscriptionchange`" event with the service worker registration
- associated with the push subscription as |registration|, a {{PushSubscription}}
- instance representing the push subscription having the old keys as
- |oldSubscription| and a {{PushSubscription}} instance representing the push
- subscription having the new keys as |newSubscription|.
+ If the user agent has to change the keys of a [=push subscription=] for any reason
+ and the [=push subscription=]'s [=associated service worker registration=] is non-null,
+ it MUST [=refresh=] the [=push subscription=].
To create a push subscription, given an {{PushSubscriptionOptionsInit}}
@@ -242,17 +249,41 @@
- Subscription Refreshes
+ Relationship to service worker registrations
+
+
+ A [=push subscription=]'s associated service worker registration is the
+ [=service worker registration=] whose [=service worker registration/scope URL=]
+ [=URL/equals=] the [=push subscription=]'s [=push subscription/scope=], if any;
+ otherwise null.
+
+
+ A [=push subscription=]'s [=associated service worker registration=] can only be null
+ when it has a [=push subscription/window-accessible scope=].
+
+
+ And vice versa, a [=service worker registration=]'s associated push
+ subscription is the [=push subscription=] whose [=push subscription/scope=]
+ [=URL/equals=] the [=service worker registration=]'s [=service worker
+ registration/scope URL=], if any; otherwise null.
+
+
+
+
+ Subscription refreshes
A user agent or push service MAY choose to refresh a push
- subscription at any time, for example because it has reached a certain age.
+ subscription whose [=associated service worker registration=] is non-null at any
+ time, for example because it has reached a certain age.
When this happens, the user agent MUST run the steps to create a push
subscription given the PushSubscriptionOptions that were provided for
- creating the current push subscription. The new push subscription MUST
- have a key pair that's different from the original subscription.
+ creating the current push subscription, and set the new [=push subscription=]'s
+ [=push subscription/scope=] to the original subscription's [=push subscription/scope=].
+ The new push subscription MUST have a key pair that's different from the
+ original subscription.
- Extensions to the `ServiceWorkerRegistration` Interface
+
+ `PushManagerAttribute` mixin
- The Service Worker specification defines a {{ServiceWorkerRegistration}} interface
- [[SERVICE-WORKERS]], which this specification extends.
+ This specifications extends the {{Window}} and {{ServiceWorkerRegistration}} objects
+ through the {{PushManagerAttribute}} mixin. [[HTML]] [[SERVICE-WORKERS]]
- The pushManager attribute exposes a {{PushManager}}, which has an associated
- service worker registration represented by the {{ServiceWorkerRegistration}} on
- which the attribute is exposed.
+ The pushManager attribute exposes a {{PushManager}}.
@@ -578,7 +609,23 @@
Let |global| be [=this=]' [=relevant global object=].
-
Return |promise| and continue [=in parallel=].
+
Let |scope| be null.
+
+
Let |registration| be null.
+
+
If [=this=] is a {{Window}} object, then set |scope| to the result of running the
+ [=basic URL parser=] given "`/`" and |global|'s associated Document's
+ [=Document/URL=].
+
+
Otherwise:
+
+
[=/Assert=]: [=this=] is a {{ServiceWorkerRegistration}} object.
+
+
Set |registration| to [=this=]'s associated [=service worker registration=].
+
+
+
+
Run these steps [=in parallel=]:
-
-
If the |options| argument has a {{PushSubscriptionOptionsInit/userVisibleOnly}} value
- set to `false` and the user agent requires it to be `true`, [=queue a global task=] on the
- [=networking task source=] using |global| to [=reject=] |promise| {{"NotAllowedError"}}
- {{DOMException}}
-
-
If the |options| argument does not include a non-null value for the
- {{PushSubscriptionOptionsInit/applicationServerKey}} member, and the push service
- requires one to be given, [=queue a global task=] on the [=networking task source=] using
- |global| to [=reject=] |promise| with a {{"NotSupportedError"}} {{DOMException}}.
-
-
If the |options| argument includes a non-null value for the
- {{PushSubscriptionOptions/applicationServerKey}} attribute, run the following sub-steps:
-
If |options|'s {{PushSubscriptionOptionsInit/applicationServerKey}} is a
- {{DOMString}}, set its value to an {{ArrayBuffer}} containing the sequence of octets
- that result from decoding |options|'s
- {{PushSubscriptionOptionsInit/applicationServerKey}} using the base64url encoding
- [[RFC7515]].
+
If the |options| argument has a {{PushSubscriptionOptionsInit/userVisibleOnly}}
+ value set to `false` and the user agent requires it to be `true`, [=queue a global
+ task=] on the [=networking task source=] using |global| to [=reject=] |promise|
+ {{"NotAllowedError"}} {{DOMException}}
-
If decoding fails, [=queue a global task=] on the [=networking task source=] using
- |global| to [=reject=] |promise| with an {{"InvalidCharacterError"}} {{DOMException}}
- and terminate these steps.
+
If the |options| argument does not include a non-null value for the
+ {{PushSubscriptionOptionsInit/applicationServerKey}} member, and the push
+ service requires one to be given, [=queue a global task=] on the [=networking task
+ source=] using |global| to [=reject=] |promise| with a {{"NotSupportedError"}}
+ {{DOMException}}.
-
Ensure that |options|'s {{PushSubscriptionOptionsInit/applicationServerKey}}
- describes a valid point on the P-256 curve. If its value is invalid, [=queue a global
- task=] on the [=networking task source=] using |global| to [=reject=] |promise| with an
- {{"InvalidAccessError"}} {{DOMException}} and terminate these steps.
+
If the |options| argument includes a non-null value for the
+ {{PushSubscriptionOptions/applicationServerKey}} attribute:
+
+
If |options|'s {{PushSubscriptionOptionsInit/applicationServerKey}} is a
+ {{DOMString}}, set its value to an {{ArrayBuffer}} containing the sequence of
+ octets that result from decoding |options|'s
+ {{PushSubscriptionOptionsInit/applicationServerKey}} using the base64url encoding
+ [[RFC7515]].
+
+
If decoding fails, [=queue a global task=] on the [=networking task source=]
+ using |global| to [=reject=] |promise| with an {{"InvalidCharacterError"}}
+ {{DOMException}} and terminate these steps.
+
+
Ensure that |options|'s {{PushSubscriptionOptionsInit/applicationServerKey}}
+ describes a valid point on the P-256 curve. If its value is invalid, [=queue a
+ global task=] on the [=networking task source=] using |global| to [=reject=]
+ |promise| with an {{"InvalidAccessError"}} {{DOMException}} and terminate these
+ steps.
+
If |registration|'s [=service worker registration/active worker=] is null, [=queue a
- global task=] on the [=networking task source=] using |global| to [=reject=] |promise| with
- an {{"InvalidStateError"}} {{DOMException}} and terminate these steps.
-
-
Let |permission| be [=request permission to use=] "push".
-
-
If |permission| is {{PermissionState/"denied"}}, [=queue a global task=] on the [=user
- interaction task source=] using |global| to [=reject=] |promise| with a
- {{"NotAllowedError"}} {{DOMException}} and terminate these steps.
-
Let |subscription| be the result of obtaining |registration|'s push
- subscription. If there is an error, [=queue a global task=] on the [=networking
- task source=] using |global| to [=reject=] |promise| with an {{"AbortError"}}
- {{DOMException}} and terminate these steps.
+
Let |subscription| be null.
+
+
If |scope| is non-null:
+
+
If there is a [=push subscription=] with a [=push
+ subscription/window-accessible scope=] whose [=push subscription/scope=]
+ [=URL/equals=] |scope|, then set |subscription| to that [=push subscription=].
+
+
-
Compare the |options| argument with the `options` attribute of |subscription|. The
- contents of {{BufferSource}} values are compared for equality rather than
- [=ECMAScript/reference record|reference=].
+
Otherwise:
+
+
[=/Assert=]: |registration| is non-null.
+
+
If |registration|'s [=service worker registration/active worker=] is null,
+ [=queue a global task=] on the [=networking task source=] using |global| to
+ [=reject=] |promise| with an {{"InvalidStateError"}} {{DOMException}} and terminate
+ these steps.
+
+
If |registration|'s [=associated push subscription=] is non-null, then set
+ |subscription| to |registration|'s [=associated push subscription=].
+
+
Set |scope| to |registration|'s [=service worker registration/scope URL=].
+
+
-
If any attribute on |options| contains a different value to that stored for
- |subscription|, then [=queue a global task=] on the [=networking task source=] using
- |global| to [=reject=] |promise| with an {{"InvalidStateError"}} {{DOMException}} and
- terminate these steps.
+
Let |permission| be [=request permission to use=] "push".
-
When the request has been completed, [=queue a global task=] on the [=networking
- task source=] using |global| to [=resolve=] |promise| with |subscription| and terminate
- these steps.
+
If |permission| is {{PermissionState/"denied"}}, [=queue a global task=] on the
+ [=user interaction task source=] using |global| to [=reject=] |promise| with a
+ {{"NotAllowedError"}} {{DOMException}} and terminate these steps.
+
+
If |subscription| is non-null:
+
+
If there is an error with |subscription|, then [=queue a global task=] on the
+ [=networking task source=] using |global| to [=reject=] |promise| with an
+ {{"AbortError"}} {{DOMException}} and terminate these steps.
+
+
Compare the |options| argument with the `options` attribute of |subscription|.
+ The contents of {{BufferSource}} values are compared for equality rather than
+ [=ECMAScript/reference record|reference=].
+
+
If any attribute on |options| contains a different value to that stored for
+ |subscription|, then [=queue a global task=] on the [=networking task source=]
+ using |global| to [=reject=] |promise| with an {{"InvalidStateError"}}
+ {{DOMException}} and terminate these steps.
+
+
[=Queue a global task=] on the [=networking task source=] using |global| to
+ [=resolve=] |promise| with |subscription| and terminate these steps.
+
+
+
+
[=/Assert=]: |subscription| is null and |scope| is a [=/URL=].
+
+
Set |subscription| to the result of trying to [=create a push subscription=] with
+ |options|. If creating the subscription [=exception/throws=] an [=exception=], [=queue
+ a global task=] on the [=networking task source=] using |global| to [=reject=]
+ |promise| with a that [=exception=] and terminate these steps.
+
+
Set |subscription|'s [=push subscription/scope=] to |scope|.
+
+
[=Queue a global task=] on the [=networking task source=] using |global| to
+ [=resolve=] |promise| with a {{PushSubscription}} corresponding to |subscription|.
-
Let |subscription| be the result of trying to [=create a push subscription=] with
- |options|. If creating the subscription [=exception/throws=] an [=exception=], [=queue a
- global task=] on the [=networking task source=] using |global| to [=reject=] |promise| with
- a that [=exception=] and terminate these these steps.
-
-
Otherwise, [=queue a global task=] on the [=networking task source=] using |global| to
- [=resolve=] |promise| with a {{PushSubscription}} providing the details of the new
- |subscription|.
+
If there is an error, reject |promise| with a {{DOMException}} whose name is
- {{"AbortError"}} and terminate these steps.
+
If [=this=] is a {{Window}} object, then set |windowScope| to the result of running the
+ [=basic URL parser=] given "`/`" and [=this=]'s associated Document's
+ [=Document/URL=].
+
+
Otherwise:
+
+
[=/Assert=]: [=this=] is a {{ServiceWorkerRegistration}} object.
+
+
Set |registration| to [=this=]'s associated [=service worker registration=].
+
+
+
+
Run these steps [=/in parallel=]:
+
+
Let |subscription| be null.
+
+
If |windowScope| is non-null:
+
+
If there is a [=push subscription=] whose [=push subscription/scope=] is
+ |windowScope|, then set |subscription| to that [=push subscription=].
+
+
+
+
Otherwise:
+
+
[=/Assert=]: |registration| is non-null.
+
+
If |registration|'s [=associated push subscription=] is non-null, then set
+ |subscription| to |registration|'s [=associated push subscription=].
+
+
+
+
If [=subscription=] is null, then resolve |promise| with null.
+
+
If there is an error with |subscription|, reject |promise| with a {{DOMException}}
+ whose name is {{"AbortError"}} and terminate these steps.
+
+
Resolve |promise| with a {{PushSubscription}} corresponding to |subscription|.
+
+
-
When the request has been completed, resolve |promise| with a {{PushSubscription}}
- providing the details of the retrieved push subscription.
+