Title: [286044] trunk
Revision
286044
Author
[email protected]
Date
2021-11-18 20:18:12 -0800 (Thu, 18 Nov 2021)

Log Message

Add support for onpushsubscriptionchange event handler
https://bugs.webkit.org/show_bug.cgi?id=233088

Reviewed by Youenn Fablet.

LayoutTests/imported/w3c:

Rebaseline test results since we now support onpushsubscriptionchange.

* web-platform-tests/push-api/idlharness.https.any.serviceworker-expected.txt:

Source/WebCore:

This adds the ability to send a pushsubscriptionchange event to the appropriate handler on
ServiceWorkerGlobalScope. I didn't implement a completion handler for the event (as we do
for the push event) since it's not required by the standard and I don't think we'd use it.
We only plan on firing this event the first time you visit an origin after we deregister a
PushSubscription for receiving too many silent pushes.

Tests: http/wpt/service-workers/service-worker-spinning-push.https.html
       http/wpt/service-workers/service-worker-spinning-pushsubscriptionchange.https.html

* Modules/push-api/PushSubscription.cpp:
(WebCore::PushSubscription::PushSubscription):
(WebCore::PushSubscription::data const):
(WebCore::PushSubscription::endpoint const):
(WebCore::PushSubscription::expirationTime const):
(WebCore::PushSubscription::options const):
(WebCore::PushSubscription::clientECDHPublicKey const):
(WebCore::PushSubscription::sharedAuthenticationSecret const):
(WebCore::PushSubscription::getKey const):
(WebCore::PushSubscription::toJSON const):
* Modules/push-api/PushSubscription.h:
* Modules/push-api/ServiceWorkerGlobalScope+PushAPI.idl:
* bindings/js/WebCoreBuiltinNames.h:
* dom/EventNames.h:
* testing/Internals.cpp:
(WebCore::Internals::createPushSubscription):
* testing/ServiceWorkerInternals.cpp:
(WebCore::ServiceWorkerInternals::schedulePushSubscriptionChangeEvent):
(WebCore::ServiceWorkerInternals::createPushSubscription):
* testing/ServiceWorkerInternals.h:
* testing/ServiceWorkerInternals.idl:
* workers/service/ServiceWorkerContainer.cpp:
(WebCore::ServiceWorkerContainer::subscribeToPushService):
(WebCore::ServiceWorkerContainer::getPushSubscription):
(WebCore::createPushSubscriptionFromData): Deleted.
* workers/service/ServiceWorkerRegistration.h:
* workers/service/context/SWContextManager.cpp:
(WebCore::SWContextManager::firePushSubscriptionChangeEvent):
* workers/service/context/SWContextManager.h:
* workers/service/context/ServiceWorkerThread.cpp:
(WebCore::ServiceWorkerThread::queueTaskToFirePushSubscriptionChangeEvent):
(WebCore::ServiceWorkerThread::heartBeatTimerFired):
(WebCore::ServiceWorkerThread::willPostTaskToFirePushSubscriptionChangeEvent):
(WebCore::ServiceWorkerThread::finishedFiringPushSubscriptionChangeEvent):
* workers/service/context/ServiceWorkerThread.h:
* workers/service/context/ServiceWorkerThreadProxy.cpp:
(WebCore::ServiceWorkerThreadProxy::firePushSubscriptionChangeEvent):
* workers/service/context/ServiceWorkerThreadProxy.h:

LayoutTests:

 - Modified the pushsubscriptionchange test to send a real event to the service worker.
 - Modified the service worker spinning tests to test for guarding against infinite loops in
   the push and pushsubscriptionchange event handlers.

Note that the existing spinning tests are marked as flaky on ios-wk2. We do the same here
since the test passes locally but is flaky in EWS.

* http/wpt/push-api/pushSubscriptionChangeEvent.any.js:
(promise_test):
(assertSubscriptionsAreEqual):
(test): Deleted.
(promise_test.async newSubscription): Deleted.
(promise_test.async return): Deleted.
* http/wpt/push-api/pushSubscriptionChangeEvent.any.serviceworker-expected.txt:
* http/wpt/service-workers/resources/routines.js:
(async sendSyncMessage):
* http/wpt/service-workers/service-worker-spinning-push.https-expected.txt: Added.
* http/wpt/service-workers/service-worker-spinning-push.https.html: Added.
* http/wpt/service-workers/service-worker-spinning-pushsubscriptionchange.https-expected.txt: Added.
* http/wpt/service-workers/service-worker-spinning-pushsubscriptionchange.https.html: Added.
* http/wpt/service-workers/service-worker-spinning-worker.js:
(respondToPendingEvent):
(pushTest):
* platform/ios-simulator-wk2/TestExpectations:

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (286043 => 286044)


--- trunk/LayoutTests/ChangeLog	2021-11-19 03:12:56 UTC (rev 286043)
+++ trunk/LayoutTests/ChangeLog	2021-11-19 04:18:12 UTC (rev 286044)
@@ -1,3 +1,35 @@
+2021-11-18  Ben Nham  <[email protected]>
+
+        Add support for onpushsubscriptionchange event handler
+        https://bugs.webkit.org/show_bug.cgi?id=233088
+
+        Reviewed by Youenn Fablet.
+
+         - Modified the pushsubscriptionchange test to send a real event to the service worker.
+         - Modified the service worker spinning tests to test for guarding against infinite loops in
+           the push and pushsubscriptionchange event handlers.
+
+        Note that the existing spinning tests are marked as flaky on ios-wk2. We do the same here
+        since the test passes locally but is flaky in EWS.
+
+        * http/wpt/push-api/pushSubscriptionChangeEvent.any.js:
+        (promise_test):
+        (assertSubscriptionsAreEqual):
+        (test): Deleted.
+        (promise_test.async newSubscription): Deleted.
+        (promise_test.async return): Deleted.
+        * http/wpt/push-api/pushSubscriptionChangeEvent.any.serviceworker-expected.txt:
+        * http/wpt/service-workers/resources/routines.js:
+        (async sendSyncMessage):
+        * http/wpt/service-workers/service-worker-spinning-push.https-expected.txt: Added.
+        * http/wpt/service-workers/service-worker-spinning-push.https.html: Added.
+        * http/wpt/service-workers/service-worker-spinning-pushsubscriptionchange.https-expected.txt: Added.
+        * http/wpt/service-workers/service-worker-spinning-pushsubscriptionchange.https.html: Added.
+        * http/wpt/service-workers/service-worker-spinning-worker.js:
+        (respondToPendingEvent):
+        (pushTest):
+        * platform/ios-simulator-wk2/TestExpectations:
+
 2021-11-18  Wenson Hsieh  <[email protected]>
 
         [macOS] [Live Text] Avoid analyzing images in editable content

Modified: trunk/LayoutTests/http/wpt/push-api/pushSubscriptionChangeEvent.any.js (286043 => 286044)


--- trunk/LayoutTests/http/wpt/push-api/pushSubscriptionChangeEvent.any.js	2021-11-19 03:12:56 UTC (rev 286043)
+++ trunk/LayoutTests/http/wpt/push-api/pushSubscriptionChangeEvent.any.js	2021-11-19 04:18:12 UTC (rev 286044)
@@ -2,27 +2,23 @@
 // META: global=serviceworker
 // META: script=constants.js
 
-test(() => {
-    let event = new PushSubscriptionChangeEvent("pushsubscriptionchange");
-    assert_equals(event.newSubscription, null, "new");
-    assert_equals(event.oldSubscription, null, "old");
-}, "PushSubscriptionChangeEvent without data");
+let activatePromise = new Promise(resolve => self._onactivate_ = resolve);
+promise_test(() => {
+   return activatePromise;
+}, "wait for active service worker");
 
-test(() => {
-    let event = new PushSubscriptionChangeEvent("pushsubscriptionchange", { newSubscription: null, oldSubscription: null });
-    assert_equals(event.newSubscription, null, "new");
-    assert_equals(event.oldSubscription, null, "old");
-}, "PushSubscriptionChangeEvent without subscriptions");
-
 let newSubscription = null;
 let oldSubscription = null;
 
-let activatePromise = new Promise(resolve => self._onactivate_ = resolve);
-promise_test(async () => {
-   return activatePromise;
-}, "wait for active service worker");
+function assertSubscriptionsAreEqual(a, b, reason)
+{
+    if (!a || !b)
+        assert_equals(a, b, reason);
+    else
+        assert_equals(JSON.stringify(a.toJSON()), JSON.stringify(b.toJSON()), reason);
+}
 
-promise_test(async() => {
+promise_test(() => {
     newSubscription = self.internals.createPushSubscription(ENDPOINT, EXPIRATION_TIME, VALID_SERVER_KEY, CLIENT_KEY_1, AUTH);
     oldSubscription = self.internals.createPushSubscription(ENDPOINT, EXPIRATION_TIME, VALID_SERVER_KEY, CLIENT_KEY_2, AUTH);
 
@@ -32,20 +28,30 @@
     return new Promise(resolve => resolve());
 }, "create subscriptions");
 
-test(() => {
-    let event = new PushSubscriptionChangeEvent("pushsubscriptionchange", { newSubscription });
-    assert_equals(event.newSubscription, newSubscription, "new");
-    assert_equals(event.oldSubscription, null, "old");
+promise_test(async() => {
+    self.internals.schedulePushSubscriptionChangeEvent(null, null);
+    let event = await new Promise(resolve => self._onpushsubscriptionchange_ = resolve);
+    assertSubscriptionsAreEqual(event.newSubscription, null, "new");
+    assertSubscriptionsAreEqual(event.oldSubscription, null, "old");
+}, "PushSubscriptionChangeEvent without subscriptions");
+
+promise_test(async() => {
+    self.internals.schedulePushSubscriptionChangeEvent(newSubscription, null);
+    let event = await new Promise(resolve => self._onpushsubscriptionchange_ = resolve);
+    assertSubscriptionsAreEqual(event.newSubscription, newSubscription, "new");
+    assertSubscriptionsAreEqual(event.oldSubscription, null, "old");
 }, "PushSubscriptionChangeEvent with new subscription");
 
-test(() => {
-    let event = new PushSubscriptionChangeEvent("pushsubscriptionchange", { oldSubscription });
-    assert_equals(event.newSubscription, null, "new");
-    assert_equals(event.oldSubscription, oldSubscription, "old");
+promise_test(async() => {
+    self.internals.schedulePushSubscriptionChangeEvent(null, oldSubscription);
+    let event = await new Promise(resolve => self._onpushsubscriptionchange_ = resolve);
+    assertSubscriptionsAreEqual(event.newSubscription, null, "new");
+    assertSubscriptionsAreEqual(event.oldSubscription, oldSubscription, "old");
 }, "PushSubscriptionChangeEvent with old subscription");
 
-test(() => {
-    let event = new PushSubscriptionChangeEvent("pushsubscriptionchange", { newSubscription, oldSubscription });
-    assert_equals(event.newSubscription, newSubscription, "new");
-    assert_equals(event.oldSubscription, oldSubscription, "old");
+promise_test(async() => {
+    self.internals.schedulePushSubscriptionChangeEvent(newSubscription, oldSubscription);
+    let event = await new Promise(resolve => self._onpushsubscriptionchange_ = resolve);
+    assertSubscriptionsAreEqual(event.newSubscription, newSubscription, "new");
+    assertSubscriptionsAreEqual(event.oldSubscription, oldSubscription, "old");
 }, "PushSubscriptionChangeEvent with new and old subscription");

Modified: trunk/LayoutTests/http/wpt/push-api/pushSubscriptionChangeEvent.any.serviceworker-expected.txt (286043 => 286044)


--- trunk/LayoutTests/http/wpt/push-api/pushSubscriptionChangeEvent.any.serviceworker-expected.txt	2021-11-19 03:12:56 UTC (rev 286043)
+++ trunk/LayoutTests/http/wpt/push-api/pushSubscriptionChangeEvent.any.serviceworker-expected.txt	2021-11-19 04:18:12 UTC (rev 286044)
@@ -1,8 +1,7 @@
 
-PASS PushSubscriptionChangeEvent without data
-PASS PushSubscriptionChangeEvent without subscriptions
 PASS wait for active service worker
 PASS create subscriptions
+PASS PushSubscriptionChangeEvent without subscriptions
 PASS PushSubscriptionChangeEvent with new subscription
 PASS PushSubscriptionChangeEvent with old subscription
 PASS PushSubscriptionChangeEvent with new and old subscription

Modified: trunk/LayoutTests/http/wpt/service-workers/resources/routines.js (286043 => 286044)


--- trunk/LayoutTests/http/wpt/service-workers/resources/routines.js	2021-11-19 03:12:56 UTC (rev 286043)
+++ trunk/LayoutTests/http/wpt/service-workers/resources/routines.js	2021-11-19 04:18:12 UTC (rev 286044)
@@ -28,6 +28,18 @@
     });
 }
 
+async function sendSyncMessage(worker, messageName, timeout)
+{
+    if (!window.internals)
+        return Promise.reject("requires internals");
+
+    const channel = new MessageChannel();
+    const receivedMessage = new Promise(resolve => channel.port1._onmessage_ = resolve);
+    const timedOut = new Promise((resolve, reject) => setTimeout(reject, timeout || 5000));
+    worker.postMessage(messageName, [channel.port2]);
+    return Promise.race([receivedMessage, timedOut]);
+}
+
 async function waitForServiceWorkerNoLongerRunning(worker)
 {
     if (!window.internals)

Added: trunk/LayoutTests/http/wpt/service-workers/service-worker-spinning-push.https-expected.txt (0 => 286044)


--- trunk/LayoutTests/http/wpt/service-workers/service-worker-spinning-push.https-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/http/wpt/service-workers/service-worker-spinning-push.https-expected.txt	2021-11-19 04:18:12 UTC (rev 286044)
@@ -0,0 +1,4 @@
+
+PASS Spin in push
+PASS Spin after push
+

Added: trunk/LayoutTests/http/wpt/service-workers/service-worker-spinning-push.https.html (0 => 286044)


--- trunk/LayoutTests/http/wpt/service-workers/service-worker-spinning-push.https.html	                        (rev 0)
+++ trunk/LayoutTests/http/wpt/service-workers/service-worker-spinning-push.https.html	2021-11-19 04:18:12 UTC (rev 286044)
@@ -0,0 +1,33 @@
+<!doctype html><!-- webkit-test-runner [ ShouldUseServiceWorkerShortTimeout=true ] -->
+<html>
+<head>
+<script src=""
+<script src=""
+<script src=""
+</head>
+<body>
+<script>
+promise_test(async (test) => {
+    const registration = await navigator.serviceWorker.register("service-worker-spinning-worker.js", { scope : "spin-push" });
+    const worker = registration.installing;
+
+    await waitForState(registration.installing, "activated");
+
+    await sendSyncMessage(worker, "push");
+
+    return waitForServiceWorkerNoLongerRunning(worker);
+}, "Spin in push");
+
+promise_test(async (test) => {
+    const registration = await navigator.serviceWorker.register("service-worker-spinning-worker.js", { scope : "spin-after-push" });
+    const worker = registration.installing;
+
+    await waitForState(registration.installing, "activated");
+
+    await sendSyncMessage(worker, "push");
+
+    return waitForServiceWorkerNoLongerRunning(worker);
+}, "Spin after push");
+</script>
+</body>
+</html>

Added: trunk/LayoutTests/http/wpt/service-workers/service-worker-spinning-pushsubscriptionchange.https-expected.txt (0 => 286044)


--- trunk/LayoutTests/http/wpt/service-workers/service-worker-spinning-pushsubscriptionchange.https-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/http/wpt/service-workers/service-worker-spinning-pushsubscriptionchange.https-expected.txt	2021-11-19 04:18:12 UTC (rev 286044)
@@ -0,0 +1,4 @@
+
+PASS Spin in pushsubscriptionchange
+PASS Spin after pushsubscriptionchange
+

Added: trunk/LayoutTests/http/wpt/service-workers/service-worker-spinning-pushsubscriptionchange.https.html (0 => 286044)


--- trunk/LayoutTests/http/wpt/service-workers/service-worker-spinning-pushsubscriptionchange.https.html	                        (rev 0)
+++ trunk/LayoutTests/http/wpt/service-workers/service-worker-spinning-pushsubscriptionchange.https.html	2021-11-19 04:18:12 UTC (rev 286044)
@@ -0,0 +1,33 @@
+<!doctype html><!-- webkit-test-runner [ ShouldUseServiceWorkerShortTimeout=true ] -->
+<html>
+<head>
+<script src=""
+<script src=""
+<script src=""
+</head>
+<body>
+<script>
+promise_test(async (test) => {
+    const registration = await navigator.serviceWorker.register("service-worker-spinning-worker.js", { scope : "spin-pushsubscriptionchange" });
+    const worker = registration.installing;
+
+    await waitForState(registration.installing, "activated");
+
+    await sendSyncMessage(worker, "pushsubscriptionchange");
+
+    return waitForServiceWorkerNoLongerRunning(worker);
+}, "Spin in pushsubscriptionchange");
+
+promise_test(async (test) => {
+    const registration = await navigator.serviceWorker.register("service-worker-spinning-worker.js", { scope : "spin-after-pushsubscriptionchange" });
+    const worker = registration.installing;
+
+    await waitForState(registration.installing, "activated");
+
+    await sendSyncMessage(worker, "pushsubscriptionchange");
+
+    return waitForServiceWorkerNoLongerRunning(worker);
+}, "Spin after pushsubscriptionchange");
+</script>
+</body>
+</html>

Modified: trunk/LayoutTests/http/wpt/service-workers/service-worker-spinning-worker.js (286043 => 286044)


--- trunk/LayoutTests/http/wpt/service-workers/service-worker-spinning-worker.js	2021-11-19 03:12:56 UTC (rev 286043)
+++ trunk/LayoutTests/http/wpt/service-workers/service-worker-spinning-worker.js	2021-11-19 04:18:12 UTC (rev 286044)
@@ -1,3 +1,14 @@
+let pendingEvent = null;
+
+function respondToPendingEvent()
+{
+    if (!pendingEvent)
+        return;
+
+    pendingEvent.ports[0].postMessage('received');
+    pendingEvent = null;
+}
+
 if (self.registration.scope.includes("spin-run"))
     while(true) { };
 
@@ -19,6 +30,17 @@
 
 function messageTest(event)
 {
+    switch (event.data) {
+    case "push":
+        self.internals.schedulePushEvent("test");
+        pendingEvent = event;
+        return;
+    case "pushsubscriptionchange":
+        self.internals.schedulePushSubscriptionChangeEvent(null, null);
+        pendingEvent = event;
+        return;
+    }
+
     if (self.registration.scope.includes("spin-message"))
         while(true) { };
     if (self.registration.scope.includes("spin-after-message"))
@@ -34,8 +56,29 @@
     event.respondWith(new Response("ok"));
 }
 
+function pushTest(event)
+{
+    respondToPendingEvent();
 
+    if (self.registration.scope.includes("spin-push"))
+        while(true) { };
+    if (self.registration.scope.includes("spin-after-push"))
+        self.setTimeout(() => { while(true) { }; }, 0);
+}
+
+function pushSubscriptionChangeTest(event)
+{
+    respondToPendingEvent();
+
+    if (self.registration.scope.includes("spin-pushsubscriptionchange"))
+        while(true) { };
+    if (self.registration.scope.includes("spin-after-pushsubscriptionchange"))
+        self.setTimeout(() => { while(true) { }; }, 0);
+}
+
 self.addEventListener("install", installTest);
 self.addEventListener("activate", activateTest);
 self.addEventListener("message", messageTest);
 self.addEventListener("fetch", fetchTest);
+self.addEventListener("push", pushTest);
+self.addEventListener("pushsubscriptionchange", pushSubscriptionChangeTest);

Modified: trunk/LayoutTests/imported/w3c/ChangeLog (286043 => 286044)


--- trunk/LayoutTests/imported/w3c/ChangeLog	2021-11-19 03:12:56 UTC (rev 286043)
+++ trunk/LayoutTests/imported/w3c/ChangeLog	2021-11-19 04:18:12 UTC (rev 286044)
@@ -1,3 +1,14 @@
+2021-11-18  Ben Nham  <[email protected]>
+
+        Add support for onpushsubscriptionchange event handler
+        https://bugs.webkit.org/show_bug.cgi?id=233088
+
+        Reviewed by Youenn Fablet.
+
+        Rebaseline test results since we now support onpushsubscriptionchange.
+
+        * web-platform-tests/push-api/idlharness.https.any.serviceworker-expected.txt:
+
 2021-11-18  Martin Robinson  <[email protected]>
 
         Update css-transforms WPT tests

Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/push-api/idlharness.https.any.serviceworker-expected.txt (286043 => 286044)


--- trunk/LayoutTests/imported/w3c/web-platform-tests/push-api/idlharness.https.any.serviceworker-expected.txt	2021-11-19 03:12:56 UTC (rev 286043)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/push-api/idlharness.https.any.serviceworker-expected.txt	2021-11-19 04:18:12 UTC (rev 286044)
@@ -80,7 +80,7 @@
 PASS ServiceWorkerRegistration interface: attribute pushManager
 PASS ServiceWorkerRegistration interface: registration must inherit property "pushManager" with the proper type
 PASS ServiceWorkerGlobalScope interface: attribute onpush
-FAIL ServiceWorkerGlobalScope interface: attribute onpushsubscriptionchange assert_own_property: The global object must have a property "onpushsubscriptionchange" expected property "onpushsubscriptionchange" missing
+PASS ServiceWorkerGlobalScope interface: attribute onpushsubscriptionchange
 PASS ServiceWorkerGlobalScope interface: self must inherit property "onpush" with the proper type
-FAIL ServiceWorkerGlobalScope interface: self must inherit property "onpushsubscriptionchange" with the proper type assert_own_property: expected property "onpushsubscriptionchange" missing
+PASS ServiceWorkerGlobalScope interface: self must inherit property "onpushsubscriptionchange" with the proper type
 

Modified: trunk/LayoutTests/platform/ios-simulator-wk2/TestExpectations (286043 => 286044)


--- trunk/LayoutTests/platform/ios-simulator-wk2/TestExpectations	2021-11-19 03:12:56 UTC (rev 286043)
+++ trunk/LayoutTests/platform/ios-simulator-wk2/TestExpectations	2021-11-19 04:18:12 UTC (rev 286044)
@@ -136,6 +136,8 @@
 webkit.org/b/217669 http/wpt/service-workers/service-worker-spinning-fetch.https.html [ Pass Timeout Failure ]
 webkit.org/b/217669 http/wpt/service-workers/service-worker-spinning-install.https.html [ Pass Timeout Failure ]
 webkit.org/b/217669 http/wpt/service-workers/service-worker-spinning-message.https.html [ Pass Timeout Failure ]
+webkit.org/b/217669 http/wpt/service-workers/service-worker-spinning-push.https.html [ Pass Timeout Failure ]
+webkit.org/b/217669 http/wpt/service-workers/service-worker-spinning-pushsubscriptionchange.https.html [ Pass Timeout Failure ]
 
 webkit.org/b/217687 accessibility/aria-current.html [ Pass Timeout ]
 webkit.org/b/217687 accessibility/insert-newline.html [ Pass Timeout ]

Modified: trunk/Source/WebCore/ChangeLog (286043 => 286044)


--- trunk/Source/WebCore/ChangeLog	2021-11-19 03:12:56 UTC (rev 286043)
+++ trunk/Source/WebCore/ChangeLog	2021-11-19 04:18:12 UTC (rev 286044)
@@ -1,3 +1,58 @@
+2021-11-18  Ben Nham  <[email protected]>
+
+        Add support for onpushsubscriptionchange event handler
+        https://bugs.webkit.org/show_bug.cgi?id=233088
+
+        Reviewed by Youenn Fablet.
+
+        This adds the ability to send a pushsubscriptionchange event to the appropriate handler on
+        ServiceWorkerGlobalScope. I didn't implement a completion handler for the event (as we do
+        for the push event) since it's not required by the standard and I don't think we'd use it.
+        We only plan on firing this event the first time you visit an origin after we deregister a
+        PushSubscription for receiving too many silent pushes.
+
+        Tests: http/wpt/service-workers/service-worker-spinning-push.https.html
+               http/wpt/service-workers/service-worker-spinning-pushsubscriptionchange.https.html
+
+        * Modules/push-api/PushSubscription.cpp:
+        (WebCore::PushSubscription::PushSubscription):
+        (WebCore::PushSubscription::data const):
+        (WebCore::PushSubscription::endpoint const):
+        (WebCore::PushSubscription::expirationTime const):
+        (WebCore::PushSubscription::options const):
+        (WebCore::PushSubscription::clientECDHPublicKey const):
+        (WebCore::PushSubscription::sharedAuthenticationSecret const):
+        (WebCore::PushSubscription::getKey const):
+        (WebCore::PushSubscription::toJSON const):
+        * Modules/push-api/PushSubscription.h:
+        * Modules/push-api/ServiceWorkerGlobalScope+PushAPI.idl:
+        * bindings/js/WebCoreBuiltinNames.h:
+        * dom/EventNames.h:
+        * testing/Internals.cpp:
+        (WebCore::Internals::createPushSubscription):
+        * testing/ServiceWorkerInternals.cpp:
+        (WebCore::ServiceWorkerInternals::schedulePushSubscriptionChangeEvent):
+        (WebCore::ServiceWorkerInternals::createPushSubscription):
+        * testing/ServiceWorkerInternals.h:
+        * testing/ServiceWorkerInternals.idl:
+        * workers/service/ServiceWorkerContainer.cpp:
+        (WebCore::ServiceWorkerContainer::subscribeToPushService):
+        (WebCore::ServiceWorkerContainer::getPushSubscription):
+        (WebCore::createPushSubscriptionFromData): Deleted.
+        * workers/service/ServiceWorkerRegistration.h:
+        * workers/service/context/SWContextManager.cpp:
+        (WebCore::SWContextManager::firePushSubscriptionChangeEvent):
+        * workers/service/context/SWContextManager.h:
+        * workers/service/context/ServiceWorkerThread.cpp:
+        (WebCore::ServiceWorkerThread::queueTaskToFirePushSubscriptionChangeEvent):
+        (WebCore::ServiceWorkerThread::heartBeatTimerFired):
+        (WebCore::ServiceWorkerThread::willPostTaskToFirePushSubscriptionChangeEvent):
+        (WebCore::ServiceWorkerThread::finishedFiringPushSubscriptionChangeEvent):
+        * workers/service/context/ServiceWorkerThread.h:
+        * workers/service/context/ServiceWorkerThreadProxy.cpp:
+        (WebCore::ServiceWorkerThreadProxy::firePushSubscriptionChangeEvent):
+        * workers/service/context/ServiceWorkerThreadProxy.h:
+
 2021-11-18  Mark Lam  <[email protected]>
 
         SubSpace constructors should take a const HeapCellType& instead of a HeapCellType*.

Modified: trunk/Source/WebCore/Modules/push-api/PushSubscription.cpp (286043 => 286044)


--- trunk/Source/WebCore/Modules/push-api/PushSubscription.cpp	2021-11-19 03:12:56 UTC (rev 286043)
+++ trunk/Source/WebCore/Modules/push-api/PushSubscription.cpp	2021-11-19 04:18:12 UTC (rev 286044)
@@ -40,52 +40,59 @@
 
 WTF_MAKE_ISO_ALLOCATED_IMPL(PushSubscription);
 
-PushSubscription::PushSubscription(String&& endpoint, std::optional<EpochTimeStamp> expirationTime, Vector<uint8_t>&& serverVAPIDPublicKey, Vector<uint8_t>&& clientECDHPublicKey, Vector<uint8_t>&& sharedAuthenticationSecret)
-    : m_endpoint(WTFMove(endpoint))
-    , m_expirationTime(expirationTime)
-    , m_options(PushSubscriptionOptions::create(WTFMove(serverVAPIDPublicKey)))
-    , m_clientECDHPublicKey(WTFMove(clientECDHPublicKey))
-    , m_sharedAuthenticationSecret(WTFMove(sharedAuthenticationSecret))
+PushSubscription::PushSubscription(PushSubscriptionData&& data, RefPtr<ServiceWorkerRegistration>&& registration)
+    : m_data(WTFMove(data))
+    , m_serviceWorkerRegistration(WTFMove(registration))
 {
 }
 
-PushSubscription::PushSubscription(Ref<ServiceWorkerRegistration>&& registration, String&& endpoint, std::optional<EpochTimeStamp> expirationTime, Vector<uint8_t>&& serverVAPIDPublicKey, Vector<uint8_t>&& clientECDHPublicKey, Vector<uint8_t>&& sharedAuthenticationSecret)
-    : m_serviceWorkerRegistration(WTFMove(registration))
-    , m_endpoint(WTFMove(endpoint))
-    , m_expirationTime(expirationTime)
-    , m_options(PushSubscriptionOptions::create(WTFMove(serverVAPIDPublicKey)))
-    , m_clientECDHPublicKey(WTFMove(clientECDHPublicKey))
-    , m_sharedAuthenticationSecret(WTFMove(sharedAuthenticationSecret))
+PushSubscription::~PushSubscription() = default;
+
+const PushSubscriptionData& PushSubscription::data() const
 {
+    return m_data;
 }
 
-PushSubscription::~PushSubscription() = default;
-
 const String& PushSubscription::endpoint() const
 {
-    return m_endpoint;
+    return m_data.endpoint;
 }
 
 std::optional<EpochTimeStamp> PushSubscription::expirationTime() const
 {
-    return m_expirationTime;
+    return m_data.expirationTime;
 }
 
 PushSubscriptionOptions& PushSubscription::options() const
 {
-    return m_options;
+    if (!m_options) {
+        auto key = m_data.serverVAPIDPublicKey;
+        m_options = PushSubscriptionOptions::create(WTFMove(key));
+    }
+
+    return *m_options;
 }
 
+const Vector<uint8_t>& PushSubscription::clientECDHPublicKey() const
+{
+    return m_data.clientECDHPublicKey;
+}
+
+const Vector<uint8_t>& PushSubscription::sharedAuthenticationSecret() const
+{
+    return m_data.sharedAuthenticationSecret;
+}
+
 ExceptionOr<RefPtr<JSC::ArrayBuffer>> PushSubscription::getKey(PushEncryptionKeyName name) const
 {
-    const Vector<uint8_t> *source = nullptr;
+    const Vector<uint8_t>* source = nullptr;
 
     switch (name) {
     case PushEncryptionKeyName::P256dh:
-        source = &m_clientECDHPublicKey;
+        source = &clientECDHPublicKey();
         break;
     case PushEncryptionKeyName::Auth:
-        source = &m_sharedAuthenticationSecret;
+        source = &sharedAuthenticationSecret();
         break;
     default:
         return nullptr;
@@ -112,11 +119,11 @@
 PushSubscriptionJSON PushSubscription::toJSON() const
 {
     return PushSubscriptionJSON {
-        m_endpoint,
-        m_expirationTime,
+        endpoint(),
+        expirationTime(),
         Vector<KeyValuePair<String, String>> {
-            { "p256dh"_s, base64URLEncodeToString(m_clientECDHPublicKey) },
-            { "auth"_s, base64URLEncodeToString(m_sharedAuthenticationSecret) }
+            { "p256dh"_s, base64URLEncodeToString(clientECDHPublicKey()) },
+            { "auth"_s, base64URLEncodeToString(sharedAuthenticationSecret()) }
         }
     };
 }

Modified: trunk/Source/WebCore/Modules/push-api/PushSubscription.h (286043 => 286044)


--- trunk/Source/WebCore/Modules/push-api/PushSubscription.h	2021-11-19 03:12:56 UTC (rev 286043)
+++ trunk/Source/WebCore/Modules/push-api/PushSubscription.h	2021-11-19 04:18:12 UTC (rev 286044)
@@ -31,6 +31,7 @@
 #include "ExceptionOr.h"
 #include "JSDOMPromiseDeferred.h"
 #include "PushEncryptionKeyName.h"
+#include "PushSubscriptionData.h"
 #include "PushSubscriptionJSON.h"
 
 #include <optional>
@@ -51,9 +52,14 @@
     template<typename... Args> static Ref<PushSubscription> create(Args&&... args) { return adoptRef(*new PushSubscription(std::forward<Args>(args)...)); }
     WEBCORE_EXPORT ~PushSubscription();
 
+    WEBCORE_EXPORT const PushSubscriptionData& data() const;
+
     const String& endpoint() const;
     std::optional<EpochTimeStamp> expirationTime() const;
     PushSubscriptionOptions& options() const;
+    const Vector<uint8_t>& clientECDHPublicKey() const;
+    const Vector<uint8_t>& sharedAuthenticationSecret() const;
+
     ExceptionOr<RefPtr<JSC::ArrayBuffer>> getKey(PushEncryptionKeyName) const;
     void unsubscribe(ScriptExecutionContext&, DOMPromiseDeferred<IDLBoolean>&&);
 
@@ -60,15 +66,11 @@
     PushSubscriptionJSON toJSON() const;
 
 private:
-    WEBCORE_EXPORT PushSubscription(String&& endpoint, std::optional<EpochTimeStamp> expirationTime, Vector<uint8_t>&& serverVAPIDPublicKey, Vector<uint8_t>&& clientECDHPublicKey, Vector<uint8_t>&& auth);
-    PushSubscription(Ref<ServiceWorkerRegistration>&&, String&& endpoint, std::optional<EpochTimeStamp> expirationTime, Vector<uint8_t>&& serverVAPIDPublicKey, Vector<uint8_t>&& clientECDHPublicKey, Vector<uint8_t>&& auth);
+    WEBCORE_EXPORT explicit PushSubscription(PushSubscriptionData&&, RefPtr<ServiceWorkerRegistration>&& = nullptr);
 
+    PushSubscriptionData m_data;
     RefPtr<ServiceWorkerRegistration> m_serviceWorkerRegistration;
-    String m_endpoint;
-    std::optional<EpochTimeStamp> m_expirationTime;
-    Ref<PushSubscriptionOptions> m_options;
-    Vector<uint8_t> m_clientECDHPublicKey;
-    Vector<uint8_t> m_sharedAuthenticationSecret;
+    mutable RefPtr<PushSubscriptionOptions> m_options;
 };
 
 } // namespace WebCore

Modified: trunk/Source/WebCore/Modules/push-api/ServiceWorkerGlobalScope+PushAPI.idl (286043 => 286044)


--- trunk/Source/WebCore/Modules/push-api/ServiceWorkerGlobalScope+PushAPI.idl	2021-11-19 03:12:56 UTC (rev 286043)
+++ trunk/Source/WebCore/Modules/push-api/ServiceWorkerGlobalScope+PushAPI.idl	2021-11-19 04:18:12 UTC (rev 286044)
@@ -27,4 +27,5 @@
     EnabledAtRuntime=ServiceWorkerEnabled
 ] partial interface ServiceWorkerGlobalScope {
     attribute EventHandler onpush;
+    attribute EventHandler onpushsubscriptionchange;
 };

Modified: trunk/Source/WebCore/bindings/js/WebCoreBuiltinNames.h (286043 => 286044)


--- trunk/Source/WebCore/bindings/js/WebCoreBuiltinNames.h	2021-11-19 03:12:56 UTC (rev 286043)
+++ trunk/Source/WebCore/bindings/js/WebCoreBuiltinNames.h	2021-11-19 04:18:12 UTC (rev 286044)
@@ -453,6 +453,7 @@
     macro(matchingElementInFlatTree) \
     macro(mediaStreamTrackConstraints) \
     macro(onpush) \
+    macro(onpushsubscriptionchange) \
     macro(onrtctransform) \
     macro(ontouchcancel) \
     macro(ontouchend) \

Modified: trunk/Source/WebCore/dom/EventNames.h (286043 => 286044)


--- trunk/Source/WebCore/dom/EventNames.h	2021-11-19 03:12:56 UTC (rev 286043)
+++ trunk/Source/WebCore/dom/EventNames.h	2021-11-19 04:18:12 UTC (rev 286044)
@@ -222,6 +222,7 @@
     macro(processorerror) \
     macro(progress) \
     macro(push) \
+    macro(pushsubscriptionchange) \
     macro(ratechange) \
     macro(readystatechange) \
     macro(rejectionhandled) \

Modified: trunk/Source/WebCore/testing/Internals.cpp (286043 => 286044)


--- trunk/Source/WebCore/testing/Internals.cpp	2021-11-19 03:12:56 UTC (rev 286043)
+++ trunk/Source/WebCore/testing/Internals.cpp	2021-11-19 04:18:12 UTC (rev 286044)
@@ -165,6 +165,7 @@
 #include "PrintContext.h"
 #include "PseudoElement.h"
 #include "PushSubscription.h"
+#include "PushSubscriptionData.h"
 #include "RTCRtpSFrameTransform.h"
 #include "Range.h"
 #include "ReadableStream.h"
@@ -194,6 +195,7 @@
 #include "SerializedScriptValue.h"
 #include "ServiceWorker.h"
 #include "ServiceWorkerProvider.h"
+#include "ServiceWorkerRegistration.h"
 #include "ServiceWorkerRegistrationData.h"
 #include "Settings.h"
 #include "ShadowRoot.h"
@@ -6594,7 +6596,7 @@
     Vector<uint8_t> myClientECDHPublicKey { static_cast<const uint8_t*>(clientECDHPublicKey.data()), clientECDHPublicKey.byteLength() };
     Vector<uint8_t> myAuth { static_cast<const uint8_t*>(auth.data()), auth.byteLength() };
 
-    return PushSubscription::create(WTFMove(myEndpoint), expirationTime, WTFMove(myServerVAPIDPublicKey), WTFMove(myClientECDHPublicKey), WTFMove(myAuth));
+    return PushSubscription::create(PushSubscriptionData { WTFMove(myEndpoint), expirationTime, WTFMove(myServerVAPIDPublicKey), WTFMove(myClientECDHPublicKey), WTFMove(myAuth) });
 }
 #endif
 

Modified: trunk/Source/WebCore/testing/ServiceWorkerInternals.cpp (286043 => 286044)


--- trunk/Source/WebCore/testing/ServiceWorkerInternals.cpp	2021-11-19 03:12:56 UTC (rev 286043)
+++ trunk/Source/WebCore/testing/ServiceWorkerInternals.cpp	2021-11-19 04:18:12 UTC (rev 286044)
@@ -31,7 +31,9 @@
 #include "FetchEvent.h"
 #include "JSFetchResponse.h"
 #include "PushSubscription.h"
+#include "PushSubscriptionData.h"
 #include "SWContextManager.h"
+#include "ServiceWorkerRegistration.h"
 #include <wtf/ProcessID.h>
 
 namespace WebCore {
@@ -82,6 +84,21 @@
     });
 }
 
+void ServiceWorkerInternals::schedulePushSubscriptionChangeEvent(PushSubscription* newSubscription, PushSubscription* oldSubscription)
+{
+    std::optional<PushSubscriptionData> newSubscriptionData;
+    std::optional<PushSubscriptionData> oldSubscriptionData;
+
+    if (newSubscription)
+        newSubscriptionData = newSubscription->data().isolatedCopy();
+    if (oldSubscription)
+        oldSubscriptionData = oldSubscription->data().isolatedCopy();
+
+    callOnMainThread([identifier = m_identifier, newSubscriptionData = WTFMove(newSubscriptionData), oldSubscriptionData = WTFMove(oldSubscriptionData)]() mutable {
+        SWContextManager::singleton().firePushSubscriptionChangeEvent(identifier, WTFMove(newSubscriptionData), WTFMove(oldSubscriptionData));
+    });
+}
+
 void ServiceWorkerInternals::waitForFetchEventToFinish(FetchEvent& event, DOMPromiseDeferred<IDLInterface<FetchResponse>>&& promise)
 {
     event.onResponse([promise = WTFMove(promise), event = Ref { event }] (auto&& result) mutable {
@@ -168,7 +185,7 @@
     Vector<uint8_t> myClientECDHPublicKey { static_cast<const uint8_t*>(clientECDHPublicKey.data()), clientECDHPublicKey.byteLength() };
     Vector<uint8_t> myAuth { static_cast<const uint8_t*>(auth.data()), auth.byteLength() };
 
-    return PushSubscription::create(WTFMove(myEndpoint), expirationTime, WTFMove(myServerVAPIDPublicKey), WTFMove(myClientECDHPublicKey), WTFMove(myAuth));
+    return PushSubscription::create(PushSubscriptionData { WTFMove(myEndpoint), expirationTime, WTFMove(myServerVAPIDPublicKey), WTFMove(myClientECDHPublicKey), WTFMove(myAuth) });
 }
 
 } // namespace WebCore

Modified: trunk/Source/WebCore/testing/ServiceWorkerInternals.h (286043 => 286044)


--- trunk/Source/WebCore/testing/ServiceWorkerInternals.h	2021-11-19 03:12:56 UTC (rev 286043)
+++ trunk/Source/WebCore/testing/ServiceWorkerInternals.h	2021-11-19 04:18:12 UTC (rev 286044)
@@ -56,6 +56,7 @@
     Ref<FetchResponse> createOpaqueWithBlobBodyResponse(ScriptExecutionContext&);
 
     void schedulePushEvent(const String&, RefPtr<DeferredPromise>&&);
+    void schedulePushSubscriptionChangeEvent(PushSubscription* newSubscription, PushSubscription* oldSubscription);
     Vector<String> fetchResponseHeaderList(FetchResponse&);
 
     String processName() const;

Modified: trunk/Source/WebCore/testing/ServiceWorkerInternals.idl (286043 => 286044)


--- trunk/Source/WebCore/testing/ServiceWorkerInternals.idl	2021-11-19 03:12:56 UTC (rev 286043)
+++ trunk/Source/WebCore/testing/ServiceWorkerInternals.idl	2021-11-19 04:18:12 UTC (rev 286044)
@@ -39,6 +39,7 @@
     sequence<ByteString> fetchResponseHeaderList(FetchResponse response);
 
     Promise<boolean> schedulePushEvent(optional DOMString data);
+    undefined schedulePushSubscriptionChangeEvent(PushSubscription? newSubscription, PushSubscription? oldSubscription);
 
     readonly attribute DOMString processName;
     readonly attribute boolean isThrottleable;

Modified: trunk/Source/WebCore/workers/service/ServiceWorkerContainer.cpp (286043 => 286044)


--- trunk/Source/WebCore/workers/service/ServiceWorkerContainer.cpp	2021-11-19 03:12:56 UTC (rev 286043)
+++ trunk/Source/WebCore/workers/service/ServiceWorkerContainer.cpp	2021-11-19 04:18:12 UTC (rev 286044)
@@ -552,11 +552,6 @@
     m_registrations.remove(registration.identifier());
 }
 
-static Ref<PushSubscription> createPushSubscriptionFromData(Ref<ServiceWorkerRegistration> registration, PushSubscriptionData&& data)
-{
-    return PushSubscription::create(WTFMove(registration), WTFMove(data.endpoint), data.expirationTime, WTFMove(data.serverVAPIDPublicKey), WTFMove(data.clientECDHPublicKey), WTFMove(data.sharedAuthenticationSecret));
-}
-
 void ServiceWorkerContainer::subscribeToPushService(ServiceWorkerRegistration& registration, const Vector<uint8_t>& applicationServerKey, DOMPromiseDeferred<IDLInterface<PushSubscription>>&& promise)
 {
     ensureSWClientConnection().subscribeToPushService(registration.identifier(), applicationServerKey, [protectedRegistration = Ref { registration }, promise = WTFMove(promise)](auto&& result) mutable {
@@ -565,7 +560,7 @@
             return;
         }
         
-        promise.resolve(createPushSubscriptionFromData(WTFMove(protectedRegistration), result.releaseReturnValue()));
+        promise.resolve(PushSubscription::create(result.releaseReturnValue(), WTFMove(protectedRegistration)));
     });
 }
 
@@ -590,7 +585,7 @@
             return;
         }
 
-        promise.resolve(createPushSubscriptionFromData(WTFMove(protectedRegistration), WTFMove(*optionalPushSubscriptionData)).ptr());
+        promise.resolve(PushSubscription::create(WTFMove(*optionalPushSubscriptionData), WTFMove(protectedRegistration)).ptr());
     });
 }
 

Modified: trunk/Source/WebCore/workers/service/ServiceWorkerRegistration.h (286043 => 286044)


--- trunk/Source/WebCore/workers/service/ServiceWorkerRegistration.h	2021-11-19 03:12:56 UTC (rev 286043)
+++ trunk/Source/WebCore/workers/service/ServiceWorkerRegistration.h	2021-11-19 04:18:12 UTC (rev 286044)
@@ -45,11 +45,11 @@
 class ServiceWorkerContainer;
 
 class ServiceWorkerRegistration final : public RefCounted<ServiceWorkerRegistration>, public Supplementable<ServiceWorkerRegistration>, public EventTargetWithInlineData, public ActiveDOMObject {
-    WTF_MAKE_ISO_ALLOCATED(ServiceWorkerRegistration);
+    WTF_MAKE_ISO_ALLOCATED_EXPORT(ServiceWorkerRegistration, WEBCORE_EXPORT);
 public:
     static Ref<ServiceWorkerRegistration> getOrCreate(ScriptExecutionContext&, Ref<ServiceWorkerContainer>&&, ServiceWorkerRegistrationData&&);
 
-    ~ServiceWorkerRegistration();
+    WEBCORE_EXPORT ~ServiceWorkerRegistration();
 
     ServiceWorkerRegistrationIdentifier identifier() const { return m_registrationData.identifier; }
 

Modified: trunk/Source/WebCore/workers/service/context/SWContextManager.cpp (286043 => 286044)


--- trunk/Source/WebCore/workers/service/context/SWContextManager.cpp	2021-11-19 03:12:56 UTC (rev 286043)
+++ trunk/Source/WebCore/workers/service/context/SWContextManager.cpp	2021-11-19 04:18:12 UTC (rev 286044)
@@ -119,7 +119,16 @@
     serviceWorker->firePushEvent(WTFMove(data), WTFMove(callback));
 }
 
+void SWContextManager::firePushSubscriptionChangeEvent(ServiceWorkerIdentifier identifier, std::optional<PushSubscriptionData>&& newSubscriptionData, std::optional<PushSubscriptionData>&& oldSubscriptionData)
+{
+    auto* serviceWorker = m_workerMap.get(identifier);
+    if (!serviceWorker)
+        return;
 
+    serviceWorker->firePushSubscriptionChangeEvent(WTFMove(newSubscriptionData), WTFMove(oldSubscriptionData));
+}
+
+
 void SWContextManager::terminateWorker(ServiceWorkerIdentifier identifier, Seconds timeout, Function<void()>&& completionHandler)
 {
     auto serviceWorker = m_workerMap.take(identifier);

Modified: trunk/Source/WebCore/workers/service/context/SWContextManager.h (286043 => 286044)


--- trunk/Source/WebCore/workers/service/context/SWContextManager.h	2021-11-19 03:12:56 UTC (rev 286043)
+++ trunk/Source/WebCore/workers/service/context/SWContextManager.h	2021-11-19 04:18:12 UTC (rev 286044)
@@ -28,6 +28,7 @@
 #if ENABLE(SERVICE_WORKER)
 
 #include "ExceptionOr.h"
+#include "PushSubscriptionData.h"
 #include "ServiceWorkerClientData.h"
 #include "ServiceWorkerClientQueryOptions.h"
 #include "ServiceWorkerIdentifier.h"
@@ -91,6 +92,7 @@
     WEBCORE_EXPORT void fireInstallEvent(ServiceWorkerIdentifier);
     WEBCORE_EXPORT void fireActivateEvent(ServiceWorkerIdentifier);
     WEBCORE_EXPORT void firePushEvent(ServiceWorkerIdentifier, std::optional<Vector<uint8_t>>&&, CompletionHandler<void(bool)>&&);
+    WEBCORE_EXPORT void firePushSubscriptionChangeEvent(ServiceWorkerIdentifier, std::optional<PushSubscriptionData>&& newSubscriptionData, std::optional<PushSubscriptionData>&& oldSubscriptionData);
 
     WEBCORE_EXPORT void terminateWorker(ServiceWorkerIdentifier, Seconds timeout, Function<void()>&&);
     WEBCORE_EXPORT void didSaveScriptsToDisk(ServiceWorkerIdentifier, ScriptBuffer&&, HashMap<URL, ScriptBuffer>&& importedScripts);

Modified: trunk/Source/WebCore/workers/service/context/ServiceWorkerThread.cpp (286043 => 286044)


--- trunk/Source/WebCore/workers/service/context/ServiceWorkerThread.cpp	2021-11-19 03:12:56 UTC (rev 286043)
+++ trunk/Source/WebCore/workers/service/context/ServiceWorkerThread.cpp	2021-11-19 04:18:12 UTC (rev 286044)
@@ -38,6 +38,8 @@
 #include "Logging.h"
 #include "PlatformStrategies.h"
 #include "PushEvent.h"
+#include "PushSubscription.h"
+#include "PushSubscriptionChangeEvent.h"
 #include "SWContextManager.h"
 #include "SecurityOrigin.h"
 #include "ServiceWorkerFetch.h"
@@ -235,6 +237,33 @@
     });
 }
 
+void ServiceWorkerThread::queueTaskToFirePushSubscriptionChangeEvent(std::optional<PushSubscriptionData>&& newSubscriptionData, std::optional<PushSubscriptionData>&& oldSubscriptionData)
+{
+    Ref serviceWorkerGlobalScope = downcast<ServiceWorkerGlobalScope>(*globalScope());
+    serviceWorkerGlobalScope->eventLoop().queueTask(TaskSource::DOMManipulation, [weakThis = WeakPtr { *this }, serviceWorkerGlobalScope, newSubscriptionData = WTFMove(newSubscriptionData), oldSubscriptionData = WTFMove(oldSubscriptionData)]() mutable {
+        RELEASE_LOG(ServiceWorker, "ServiceWorkerThread::queueTaskToFirePushSubscriptionChangeEvent firing event for worker %" PRIu64, serviceWorkerGlobalScope->thread().identifier().toUInt64());
+
+        RefPtr<PushSubscription> newSubscription;
+        RefPtr<PushSubscription> oldSubscription;
+
+        if (newSubscriptionData)
+            newSubscription = PushSubscription::create(WTFMove(*newSubscriptionData), &serviceWorkerGlobalScope->registration());
+        if (oldSubscriptionData)
+            oldSubscription = PushSubscription::create(WTFMove(*oldSubscriptionData));
+
+        auto pushSubscriptionChangeEvent = PushSubscriptionChangeEvent::create(eventNames().pushsubscriptionchangeEvent, { }, WTFMove(newSubscription), WTFMove(oldSubscription), ExtendableEvent::IsTrusted::Yes);
+        serviceWorkerGlobalScope->dispatchEvent(pushSubscriptionChangeEvent);
+
+        pushSubscriptionChangeEvent->whenAllExtendLifetimePromisesAreSettled([weakThis = WTFMove(weakThis)](auto&&) mutable {
+            callOnMainThread([weakThis = WTFMove(weakThis)] {
+                RELEASE_LOG(ServiceWorker, "ServiceWorkerThread::queueTaskToFirePushSubscriptionChangeEvent finishing for worker %llu", weakThis ? weakThis->identifier().toUInt64() : 0);
+                if (weakThis)
+                    weakThis->finishedFiringPushSubscriptionChangeEvent();
+            });
+        });
+    });
+}
+
 void ServiceWorkerThread::finishedEvaluatingScript()
 {
     ASSERT(globalScope()->isContextThread());
@@ -295,7 +324,7 @@
 void ServiceWorkerThread::heartBeatTimerFired()
 {
     if (!m_ongoingHeartBeatCheck) {
-        if (m_state == State::Installing || m_state == State::Activating || m_isHandlingFetchEvent || m_isHandlingPushEvent || m_messageEventCount)
+        if (m_state == State::Installing || m_state == State::Activating || m_isHandlingFetchEvent || m_isHandlingPushEvent || m_pushSubscriptionChangeEventCount || m_messageEventCount)
             startHeartBeatTimer();
         return;
     }
@@ -362,6 +391,18 @@
     --m_messageEventCount;
 }
 
+void ServiceWorkerThread::willPostTaskToFirePushSubscriptionChangeEvent()
+{
+    if (!m_pushSubscriptionChangeEventCount++)
+        startHeartBeatTimer();
+}
+
+void ServiceWorkerThread::finishedFiringPushSubscriptionChangeEvent()
+{
+    ASSERT(m_pushSubscriptionChangeEventCount);
+    --m_pushSubscriptionChangeEventCount;
+}
+
 } // namespace WebCore
 
 #endif // ENABLE(SERVICE_WORKER)

Modified: trunk/Source/WebCore/workers/service/context/ServiceWorkerThread.h (286043 => 286044)


--- trunk/Source/WebCore/workers/service/context/ServiceWorkerThread.h	2021-11-19 03:12:56 UTC (rev 286043)
+++ trunk/Source/WebCore/workers/service/context/ServiceWorkerThread.h	2021-11-19 04:18:12 UTC (rev 286044)
@@ -27,6 +27,7 @@
 
 #if ENABLE(SERVICE_WORKER)
 
+#include "PushSubscriptionData.h"
 #include "ScriptExecutionContextIdentifier.h"
 #include "ServiceWorkerContextData.h"
 #include "ServiceWorkerFetch.h"
@@ -61,6 +62,7 @@
     void willPostTaskToFireInstallEvent();
     void willPostTaskToFireActivateEvent();
     void willPostTaskToFireMessageEvent();
+    void willPostTaskToFirePushSubscriptionChangeEvent();
 
     void queueTaskToFireFetchEvent(Ref<ServiceWorkerFetch::Client>&&, std::optional<ScriptExecutionContextIdentifier>&&, ResourceRequest&&, String&& referrer, FetchOptions&&);
     void queueTaskToPostMessage(MessageWithMessagePorts&&, ServiceWorkerOrClientData&& sourceData);
@@ -67,6 +69,7 @@
     void queueTaskToFireInstallEvent();
     void queueTaskToFireActivateEvent();
     void queueTaskToFirePushEvent(std::optional<Vector<uint8_t>>&&, Function<void(bool)>&&);
+    void queueTaskToFirePushSubscriptionChangeEvent(std::optional<PushSubscriptionData>&& newSubscriptionData, std::optional<PushSubscriptionData>&& oldSubscriptionData);
 
     ServiceWorkerIdentifier identifier() const { return m_serviceWorkerIdentifier; }
     std::optional<ServiceWorkerJobDataIdentifier> jobDataIdentifier() const { return m_jobDataIdentifier; }
@@ -90,6 +93,7 @@
     void finishedFiringInstallEvent(bool hasRejectedAnyPromise);
     void finishedFiringActivateEvent();
     void finishedFiringMessageEvent();
+    void finishedFiringPushSubscriptionChangeEvent();
     void finishedStarting();
 
     void startHeartBeatTimer();
@@ -105,6 +109,7 @@
 
     bool m_isHandlingFetchEvent { false };
     bool m_isHandlingPushEvent { false };
+    uint64_t m_pushSubscriptionChangeEventCount { 0 };
     uint64_t m_messageEventCount { 0 };
     enum class State { Idle, Starting, Installing, Activating };
     State m_state { State::Idle };

Modified: trunk/Source/WebCore/workers/service/context/ServiceWorkerThreadProxy.cpp (286043 => 286044)


--- trunk/Source/WebCore/workers/service/context/ServiceWorkerThreadProxy.cpp	2021-11-19 03:12:56 UTC (rev 286043)
+++ trunk/Source/WebCore/workers/service/context/ServiceWorkerThreadProxy.cpp	2021-11-19 04:18:12 UTC (rev 286044)
@@ -45,6 +45,7 @@
 #include "ServiceWorkerGlobalScope.h"
 #include "Settings.h"
 #include "WorkerGlobalScope.h"
+#include <wtf/CrossThreadCopier.h>
 #include <wtf/MainThread.h>
 #include <wtf/RunLoop.h>
 
@@ -320,6 +321,14 @@
         m_ongoingPushTasks.take(identifier)(false);
 }
 
+void ServiceWorkerThreadProxy::firePushSubscriptionChangeEvent(std::optional<PushSubscriptionData>&& newSubscriptionData, std::optional<PushSubscriptionData>&& oldSubscriptionData)
+{
+    thread().willPostTaskToFirePushSubscriptionChangeEvent();
+    thread().runLoop().postTask([this, protectedThis = Ref { *this }, newSubscriptionData = crossThreadCopy(WTFMove(newSubscriptionData)), oldSubscriptionData = crossThreadCopy(WTFMove(oldSubscriptionData))](auto&) mutable {
+        thread().queueTaskToFirePushSubscriptionChangeEvent(WTFMove(newSubscriptionData), WTFMove(oldSubscriptionData));
+    });
+}
+
 } // namespace WebCore
 
 #endif // ENABLE(SERVICE_WORKER)

Modified: trunk/Source/WebCore/workers/service/context/ServiceWorkerThreadProxy.h (286043 => 286044)


--- trunk/Source/WebCore/workers/service/context/ServiceWorkerThreadProxy.h	2021-11-19 03:12:56 UTC (rev 286043)
+++ trunk/Source/WebCore/workers/service/context/ServiceWorkerThreadProxy.h	2021-11-19 04:18:12 UTC (rev 286044)
@@ -31,6 +31,7 @@
 #include "Document.h"
 #include "FetchIdentifier.h"
 #include "Page.h"
+#include "PushSubscriptionData.h"
 #include "ServiceWorkerDebuggable.h"
 #include "ServiceWorkerIdentifier.h"
 #include "ServiceWorkerInspectorProxy.h"
@@ -81,6 +82,7 @@
     void fireInstallEvent();
     void fireActivateEvent();
     void firePushEvent(std::optional<Vector<uint8_t>>&&, CompletionHandler<void(bool)>&&);
+    void firePushSubscriptionChangeEvent(std::optional<PushSubscriptionData>&& newSubscriptionData, std::optional<PushSubscriptionData>&& oldSubscriptionData);
 
     void didSaveScriptsToDisk(ScriptBuffer&&, HashMap<URL, ScriptBuffer>&& importedScripts);
 
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to