Skip to content
Draft
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
116 changes: 97 additions & 19 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -392,14 +392,26 @@ <h3>
</dd>
</dl>
</dd>
<dt>
<code>app_badge</code>
</dt>
<dd>
<p>
A boolean or a [=/64-bit unsigned integer=].
</p>
<p class="note">
Platform conventions are likely to impose a lower limit with regards to what is
displayed to the end user. [[BADGING]]
</p>
</dd>
<dt>
<code>mutable</code>
</dt>
<dd>
<p>
A boolean. When true causes a <code>push</code> event to be dispatched to a service
worker (if any) containing the {{Notification}} object described by the
<a>declarative push message</a>.
worker (if any) containing the {{Notification}} object and app badge number (if
any) described by the <a>declarative push message</a>.
</p>
</dd>
</dl>
Expand All @@ -411,7 +423,8 @@ <h3>
<p>
A <dfn>declarative push message parser result</dfn> is a [=/tuple=] consisting of a
<dfn data-dfn-for="declarative push message parser result">notification</dfn> (a
[=/notification=]) and a <dfn data-dfn-for=
[=/notification=]), an <dfn data-dfn-for="declarative push message parser result">app
badge</dfn> (null or an integer), and a <dfn data-dfn-for=
"declarative push message parser result">mutable</dfn> (a boolean).
</p>
<p>
Expand Down Expand Up @@ -673,6 +686,18 @@ <h3>
<var>notification</var>'s [=notification/actions=] is null, then return failure.
</p>
</li>
<li>
<p>
Let <var>appBadge</var> be null.
</p>
</li>
<li>
<p>
If <var>message</var>["`app_badge`"] [=map/exists=] and
<var>message</var>["`app_badge`"] is a [=/64-bit unsigned integer=], then set
<var>appBadge</var> to <var>message</var>["`app_badge`"].
</p><!-- unsigned long long in Web IDL -->
</li>
<li>
<p>
Let <var>mutable</var> be false.
Expand All @@ -687,7 +712,7 @@ <h3>
</li>
<li>
<p>
Return (<var>notification</var>, <var>mutable</var>).
Return (<var>notification</var>, <var>appBadge</var>, <var>mutable</var>).
</p>
</li>
</ol>
Expand Down Expand Up @@ -1598,11 +1623,13 @@ <h2>
constructor(DOMString type, optional PushEventInit eventInitDict = {});
readonly attribute PushMessageData? data;
readonly attribute Notification? notification;
readonly attribute unsigned long long? appBadge;
};

dictionary PushEventInit : ExtendableEventInit {
PushMessageDataInit? data = null;
Notification? notification = null;
unsigned long long? appBadge = null;
};

typedef (BufferSource or USVString) PushMessageDataInit;
Expand All @@ -1629,6 +1656,9 @@ <h2>
<p>
The <dfn>notification</dfn> attribute must return the value it was initialized with.
</p>
<p>
The <dfn>appBadge</dfn> attribute must return the value it was initialized with.
</p>
</section>
<section>
<h2>
Expand Down Expand Up @@ -1715,6 +1745,11 @@ <h2>
Let |notificationShown| be false.
</p>
</li>
<li>
<p>
Let |appBadgeSet| be false.
</p>
</li>
<li>
<p>
If |declarativeResult|'s [=declarative push message parser result/mutable=]
Expand All @@ -1724,14 +1759,16 @@ <h2>
<li>
<p>
Let |result| be the result of [=fire a push event|firing a push event=]
given |registration|, null, and a new {{Notification}} object
representing |notification|.
given |registration|, null, a new {{Notification}} object representing
|notification|, and |declarativeResult|'s [=declarative push message
parser result/app badge=].
</p>
</li>
<li>
<p>
If |result| is not failure, then set |notificationShown| to |result|'s
[=push event result/notification shown=].
[=push event result/notification shown=] and |appBadgeSet| to |result|'s
[=push event result/app badge set=].
</p>
</li>
</ol>
Expand All @@ -1742,6 +1779,27 @@ <h2>
given |notification|.
</p>
</li>
<li data-cite="appmanifest">
<p>
If |appBadgeSet| is false and the web application associated with the <a>push
subscription</a> is an [=installed web application=]:
Copy link
Member Author

Choose a reason for hiding this comment

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

We should use |subscription| here, I think? Maybe

If appBadgeSet is false and |subscription| has an associated installed web application:

Copy link
Member Author

Choose a reason for hiding this comment

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

Though it would be nice to also support this outside of installed web applications. But I suppose that's a separate change.

Copy link
Member

Choose a reason for hiding this comment

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

Setting a badge is pretty tightly bound to installation at the moment, as that's how it's been implemented by everyone. We could change this if this changes.

</p>
<ol>
<li>
<p>
Let |identity| be the web application's [=installed web
application/identity=] [=/URL=].
</p>
</li>
<li>
<p>
[=Set the application badge for installed web application=] given
Copy link
Member

Choose a reason for hiding this comment

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

|identity| and |declarativeResult|'s [=declarative push message parser
result/app badge=].
</p>
</li>
</ol>
</li>
<li>
<p>
[=acknowledge a push message|Acknowledge=] the <a>push message</a> and abort
Expand All @@ -1761,7 +1819,7 @@ <h2>
<li>
<p>
Let |result| be the result of [=fire a push event|firing a push event=] given
|registration|, |data|, and null.
|registration|, |data|, null, and null.
</p>
</li>
<li>
Expand All @@ -1779,20 +1837,27 @@ <h2>
</li>
</ol>
<p>
A <dfn>push event result</dfn> is a [=/tuple=] consisting of a <dfn data-dfn-for=
"push event result">notification shown</dfn> (a [=/boolean=]).
A <dfn>push event result</dfn> is a [=/tuple=] consisting of a <dfn for=
"push event result">notification shown</dfn> (a [=/boolean=]) and an <dfn for=
"push event result">app badge set</dfn> (a [=/boolean=]).
</p>
<p>
To <dfn>fire a push event</dfn> given a [=/service worker registration=] |registration|,
{{PushMessageData}} object or null |data|, and a [=/notification=] or null
|notification|, run these steps. They return failure or a [=/push event result=].
{{PushMessageData}} object or null |data|, a [=/notification=] or null |notification|,
and an integer or null |appBadge|, run these steps. They return failure or a [=/push
event result=].
</p>
<ol>
<li>
<p>
Let |notificationResult| be null.
</p>
</li>
<li>
<p>
Let |appBadgeResult| be null.
</p>
</li>
<li>
<p>
Set |registration|'s [=service worker registration/has shownotification() been
Expand All @@ -1817,6 +1882,12 @@ <h2>
<dd>
|notification|
</dd>
<dt>
{{PushEvent/appBadge}}
</dt>
<dd>
|appBadge|
</dd>
</dl>
<p>
Then run the following steps in parallel, with |dispatchedEvent|:
Expand All @@ -1830,21 +1901,28 @@ <h2>
</li>
<li>
<p>
If they do not resolve successfully, then set |notificationResult| to failure.
If they do not resolve successfully, then set |notificationResult| and
|appBadgeResult| to failure and abort these steps.
</p>
</li>
<li>
<p>
Set |notificationResult| to |registration|'s [=service worker registration/has
shownotification() been successfully invoked|has `showNotification()` been
successfully invoked=].
</p>
</li>
<li>
<p>
Otherwise, set |notificationResult| to |registration|'s [=service worker
registration/has shownotification() been successfully invoked|has
`showNotification()` been successfully invoked=].
Set |appBadgeResult| to true if {{NavigatorBadge/setAppBadge()}} has been
invoked; otherwise false.
Copy link
Member Author

Choose a reason for hiding this comment

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

@marcoscaceres we need a hook for this similar to "has showNotification() been successfully invoked". People were not happy with this being defined in a hand-wavy way.

Copy link
Member

@marcoscaceres marcoscaceres Sep 10, 2025

Choose a reason for hiding this comment

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

IIUC, in the case of notifications, it emulates calling showNotification()...

Instead, for the Badging case, can we reuse "set the application badge for an installed web application" and I can get that to return a boolean if it worked?

Copy link
Member Author

Choose a reason for hiding this comment

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

No, this is specifically to catch the case where the developer used setAppBadge() (and maybe even clearAppBadge(), come to think of it) and so we don't want to use the declarative app badge result.

See https://notifications.spec.whatwg.org/#service-worker-registration-has-shownotification-been-successfully-invoked and how showNotification() ends up setting it to true. (We set it to false here first before dispatching the event to the service worker.) We need the same for app badge.

Copy link
Member

Choose a reason for hiding this comment

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

ah, ok... I'll have another look.

</p>
</li>
</ol>
</li>
<li>
<p>
Wait for |notificationResult| to be non-null.
Wait for |notificationResult| and |appBadgeResult| to be non-null.
</p>
</li>
<li>
Expand All @@ -1854,12 +1932,12 @@ <h2>
</li>
<li>
<p>
[=/Assert=]: |notificationResult| is a [=/boolean=].
[=/Assert=]: |notificationResult| and |appBadgeResult| are [=/booleans=].
</p>
</li>
<li>
<p>
Return (|notificationResult|).
Return (|notificationResult|, |appBadgeResult|).
</p>
</li>
</ol>
Expand Down
Loading