⚠ Archived content — this site is no longer maintained.   Current WebKit documentation is at docs.webkit.org.

Changeset 286044 in webkit


Ignore:
Timestamp:
Nov 18, 2021, 8:18:12 PM (5 years ago)
Author:
Ben Nham
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:
Location:
trunk
Files:
4 added
26 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r286021 r286044  
     12021-11-18  Ben Nham  <nham@apple.com>
     2
     3        Add support for onpushsubscriptionchange event handler
     4        https://bugs.webkit.org/show_bug.cgi?id=233088
     5
     6        Reviewed by Youenn Fablet.
     7
     8         - Modified the pushsubscriptionchange test to send a real event to the service worker.
     9         - Modified the service worker spinning tests to test for guarding against infinite loops in
     10           the push and pushsubscriptionchange event handlers.
     11
     12        Note that the existing spinning tests are marked as flaky on ios-wk2. We do the same here
     13        since the test passes locally but is flaky in EWS.
     14
     15        * http/wpt/push-api/pushSubscriptionChangeEvent.any.js:
     16        (promise_test):
     17        (assertSubscriptionsAreEqual):
     18        (test): Deleted.
     19        (promise_test.async newSubscription): Deleted.
     20        (promise_test.async return): Deleted.
     21        * http/wpt/push-api/pushSubscriptionChangeEvent.any.serviceworker-expected.txt:
     22        * http/wpt/service-workers/resources/routines.js:
     23        (async sendSyncMessage):
     24        * http/wpt/service-workers/service-worker-spinning-push.https-expected.txt: Added.
     25        * http/wpt/service-workers/service-worker-spinning-push.https.html: Added.
     26        * http/wpt/service-workers/service-worker-spinning-pushsubscriptionchange.https-expected.txt: Added.
     27        * http/wpt/service-workers/service-worker-spinning-pushsubscriptionchange.https.html: Added.
     28        * http/wpt/service-workers/service-worker-spinning-worker.js:
     29        (respondToPendingEvent):
     30        (pushTest):
     31        * platform/ios-simulator-wk2/TestExpectations:
     32
    1332021-11-18  Wenson Hsieh  <wenson_hsieh@apple.com>
    234
  • trunk/LayoutTests/http/wpt/push-api/pushSubscriptionChangeEvent.any.js

    r285564 r286044  
    33// META: script=constants.js
    44
    5 test(() => {
    6     let event = new PushSubscriptionChangeEvent("pushsubscriptionchange");
    7     assert_equals(event.newSubscription, null, "new");
    8     assert_equals(event.oldSubscription, null, "old");
    9 }, "PushSubscriptionChangeEvent without data");
    10 
    11 test(() => {
    12     let event = new PushSubscriptionChangeEvent("pushsubscriptionchange", { newSubscription: null, oldSubscription: null });
    13     assert_equals(event.newSubscription, null, "new");
    14     assert_equals(event.oldSubscription, null, "old");
    15 }, "PushSubscriptionChangeEvent without subscriptions");
     5let activatePromise = new Promise(resolve => self.onactivate = resolve);
     6promise_test(() => {
     7   return activatePromise;
     8}, "wait for active service worker");
    169
    1710let newSubscription = null;
    1811let oldSubscription = null;
    1912
    20 let activatePromise = new Promise(resolve => self.onactivate = resolve);
    21 promise_test(async () => {
    22    return activatePromise;
    23 }, "wait for active service worker");
     13function assertSubscriptionsAreEqual(a, b, reason)
     14{
     15    if (!a || !b)
     16        assert_equals(a, b, reason);
     17    else
     18        assert_equals(JSON.stringify(a.toJSON()), JSON.stringify(b.toJSON()), reason);
     19}
    2420
    25 promise_test(async() => {
     21promise_test(() => {
    2622    newSubscription = self.internals.createPushSubscription(ENDPOINT, EXPIRATION_TIME, VALID_SERVER_KEY, CLIENT_KEY_1, AUTH);
    2723    oldSubscription = self.internals.createPushSubscription(ENDPOINT, EXPIRATION_TIME, VALID_SERVER_KEY, CLIENT_KEY_2, AUTH);
     
    3329}, "create subscriptions");
    3430
    35 test(() => {
    36     let event = new PushSubscriptionChangeEvent("pushsubscriptionchange", { newSubscription });
    37     assert_equals(event.newSubscription, newSubscription, "new");
    38     assert_equals(event.oldSubscription, null, "old");
     31promise_test(async() => {
     32    self.internals.schedulePushSubscriptionChangeEvent(null, null);
     33    let event = await new Promise(resolve => self.onpushsubscriptionchange = resolve);
     34    assertSubscriptionsAreEqual(event.newSubscription, null, "new");
     35    assertSubscriptionsAreEqual(event.oldSubscription, null, "old");
     36}, "PushSubscriptionChangeEvent without subscriptions");
     37
     38promise_test(async() => {
     39    self.internals.schedulePushSubscriptionChangeEvent(newSubscription, null);
     40    let event = await new Promise(resolve => self.onpushsubscriptionchange = resolve);
     41    assertSubscriptionsAreEqual(event.newSubscription, newSubscription, "new");
     42    assertSubscriptionsAreEqual(event.oldSubscription, null, "old");
    3943}, "PushSubscriptionChangeEvent with new subscription");
    4044
    41 test(() => {
    42     let event = new PushSubscriptionChangeEvent("pushsubscriptionchange", { oldSubscription });
    43     assert_equals(event.newSubscription, null, "new");
    44     assert_equals(event.oldSubscription, oldSubscription, "old");
     45promise_test(async() => {
     46    self.internals.schedulePushSubscriptionChangeEvent(null, oldSubscription);
     47    let event = await new Promise(resolve => self.onpushsubscriptionchange = resolve);
     48    assertSubscriptionsAreEqual(event.newSubscription, null, "new");
     49    assertSubscriptionsAreEqual(event.oldSubscription, oldSubscription, "old");
    4550}, "PushSubscriptionChangeEvent with old subscription");
    4651
    47 test(() => {
    48     let event = new PushSubscriptionChangeEvent("pushsubscriptionchange", { newSubscription, oldSubscription });
    49     assert_equals(event.newSubscription, newSubscription, "new");
    50     assert_equals(event.oldSubscription, oldSubscription, "old");
     52promise_test(async() => {
     53    self.internals.schedulePushSubscriptionChangeEvent(newSubscription, oldSubscription);
     54    let event = await new Promise(resolve => self.onpushsubscriptionchange = resolve);
     55    assertSubscriptionsAreEqual(event.newSubscription, newSubscription, "new");
     56    assertSubscriptionsAreEqual(event.oldSubscription, oldSubscription, "old");
    5157}, "PushSubscriptionChangeEvent with new and old subscription");
  • trunk/LayoutTests/http/wpt/push-api/pushSubscriptionChangeEvent.any.serviceworker-expected.txt

    r285564 r286044  
    11
    2 PASS PushSubscriptionChangeEvent without data
    3 PASS PushSubscriptionChangeEvent without subscriptions
    42PASS wait for active service worker
    53PASS create subscriptions
     4PASS PushSubscriptionChangeEvent without subscriptions
    65PASS PushSubscriptionChangeEvent with new subscription
    76PASS PushSubscriptionChangeEvent with old subscription
  • trunk/LayoutTests/http/wpt/service-workers/resources/routines.js

    r259859 r286044  
    2929}
    3030
     31async function sendSyncMessage(worker, messageName, timeout)
     32{
     33    if (!window.internals)
     34        return Promise.reject("requires internals");
     35
     36    const channel = new MessageChannel();
     37    const receivedMessage = new Promise(resolve => channel.port1.onmessage = resolve);
     38    const timedOut = new Promise((resolve, reject) => setTimeout(reject, timeout || 5000));
     39    worker.postMessage(messageName, [channel.port2]);
     40    return Promise.race([receivedMessage, timedOut]);
     41}
     42
    3143async function waitForServiceWorkerNoLongerRunning(worker)
    3244{
  • trunk/LayoutTests/http/wpt/service-workers/service-worker-spinning-worker.js

    r253898 r286044  
     1let pendingEvent = null;
     2
     3function respondToPendingEvent()
     4{
     5    if (!pendingEvent)
     6        return;
     7
     8    pendingEvent.ports[0].postMessage('received');
     9    pendingEvent = null;
     10}
     11
    112if (self.registration.scope.includes("spin-run"))
    213    while(true) { };
     
    2031function messageTest(event)
    2132{
     33    switch (event.data) {
     34    case "push":
     35        self.internals.schedulePushEvent("test");
     36        pendingEvent = event;
     37        return;
     38    case "pushsubscriptionchange":
     39        self.internals.schedulePushSubscriptionChangeEvent(null, null);
     40        pendingEvent = event;
     41        return;
     42    }
     43
    2244    if (self.registration.scope.includes("spin-message"))
    2345        while(true) { };
     
    3557}
    3658
     59function pushTest(event)
     60{
     61    respondToPendingEvent();
     62
     63    if (self.registration.scope.includes("spin-push"))
     64        while(true) { };
     65    if (self.registration.scope.includes("spin-after-push"))
     66        self.setTimeout(() => { while(true) { }; }, 0);
     67}
     68
     69function pushSubscriptionChangeTest(event)
     70{
     71    respondToPendingEvent();
     72
     73    if (self.registration.scope.includes("spin-pushsubscriptionchange"))
     74        while(true) { };
     75    if (self.registration.scope.includes("spin-after-pushsubscriptionchange"))
     76        self.setTimeout(() => { while(true) { }; }, 0);
     77}
    3778
    3879self.addEventListener("install", installTest);
     
    4081self.addEventListener("message", messageTest);
    4182self.addEventListener("fetch", fetchTest);
     83self.addEventListener("push", pushTest);
     84self.addEventListener("pushsubscriptionchange", pushSubscriptionChangeTest);
  • trunk/LayoutTests/imported/w3c/ChangeLog

    r286002 r286044  
     12021-11-18  Ben Nham  <nham@apple.com>
     2
     3        Add support for onpushsubscriptionchange event handler
     4        https://bugs.webkit.org/show_bug.cgi?id=233088
     5
     6        Reviewed by Youenn Fablet.
     7
     8        Rebaseline test results since we now support onpushsubscriptionchange.
     9
     10        * web-platform-tests/push-api/idlharness.https.any.serviceworker-expected.txt:
     11
    1122021-11-18  Martin Robinson  <mrobinson@webkit.org>
    213
  • trunk/LayoutTests/imported/w3c/web-platform-tests/push-api/idlharness.https.any.serviceworker-expected.txt

    r285564 r286044  
    8181PASS ServiceWorkerRegistration interface: registration must inherit property "pushManager" with the proper type
    8282PASS ServiceWorkerGlobalScope interface: attribute onpush
    83 FAIL ServiceWorkerGlobalScope interface: attribute onpushsubscriptionchange assert_own_property: The global object must have a property "onpushsubscriptionchange" expected property "onpushsubscriptionchange" missing
     83PASS ServiceWorkerGlobalScope interface: attribute onpushsubscriptionchange
    8484PASS ServiceWorkerGlobalScope interface: self must inherit property "onpush" with the proper type
    85 FAIL ServiceWorkerGlobalScope interface: self must inherit property "onpushsubscriptionchange" with the proper type assert_own_property: expected property "onpushsubscriptionchange" missing
     85PASS ServiceWorkerGlobalScope interface: self must inherit property "onpushsubscriptionchange" with the proper type
    8686
  • trunk/LayoutTests/platform/ios-simulator-wk2/TestExpectations

    r285554 r286044  
    137137webkit.org/b/217669 http/wpt/service-workers/service-worker-spinning-install.https.html [ Pass Timeout Failure ]
    138138webkit.org/b/217669 http/wpt/service-workers/service-worker-spinning-message.https.html [ Pass Timeout Failure ]
     139webkit.org/b/217669 http/wpt/service-workers/service-worker-spinning-push.https.html [ Pass Timeout Failure ]
     140webkit.org/b/217669 http/wpt/service-workers/service-worker-spinning-pushsubscriptionchange.https.html [ Pass Timeout Failure ]
    139141
    140142webkit.org/b/217687 accessibility/aria-current.html [ Pass Timeout ]
  • trunk/Source/WebCore/ChangeLog

    r286042 r286044  
     12021-11-18  Ben Nham  <nham@apple.com>
     2
     3        Add support for onpushsubscriptionchange event handler
     4        https://bugs.webkit.org/show_bug.cgi?id=233088
     5
     6        Reviewed by Youenn Fablet.
     7
     8        This adds the ability to send a pushsubscriptionchange event to the appropriate handler on
     9        ServiceWorkerGlobalScope. I didn't implement a completion handler for the event (as we do
     10        for the push event) since it's not required by the standard and I don't think we'd use it.
     11        We only plan on firing this event the first time you visit an origin after we deregister a
     12        PushSubscription for receiving too many silent pushes.
     13
     14        Tests: http/wpt/service-workers/service-worker-spinning-push.https.html
     15               http/wpt/service-workers/service-worker-spinning-pushsubscriptionchange.https.html
     16
     17        * Modules/push-api/PushSubscription.cpp:
     18        (WebCore::PushSubscription::PushSubscription):
     19        (WebCore::PushSubscription::data const):
     20        (WebCore::PushSubscription::endpoint const):
     21        (WebCore::PushSubscription::expirationTime const):
     22        (WebCore::PushSubscription::options const):
     23        (WebCore::PushSubscription::clientECDHPublicKey const):
     24        (WebCore::PushSubscription::sharedAuthenticationSecret const):
     25        (WebCore::PushSubscription::getKey const):
     26        (WebCore::PushSubscription::toJSON const):
     27        * Modules/push-api/PushSubscription.h:
     28        * Modules/push-api/ServiceWorkerGlobalScope+PushAPI.idl:
     29        * bindings/js/WebCoreBuiltinNames.h:
     30        * dom/EventNames.h:
     31        * testing/Internals.cpp:
     32        (WebCore::Internals::createPushSubscription):
     33        * testing/ServiceWorkerInternals.cpp:
     34        (WebCore::ServiceWorkerInternals::schedulePushSubscriptionChangeEvent):
     35        (WebCore::ServiceWorkerInternals::createPushSubscription):
     36        * testing/ServiceWorkerInternals.h:
     37        * testing/ServiceWorkerInternals.idl:
     38        * workers/service/ServiceWorkerContainer.cpp:
     39        (WebCore::ServiceWorkerContainer::subscribeToPushService):
     40        (WebCore::ServiceWorkerContainer::getPushSubscription):
     41        (WebCore::createPushSubscriptionFromData): Deleted.
     42        * workers/service/ServiceWorkerRegistration.h:
     43        * workers/service/context/SWContextManager.cpp:
     44        (WebCore::SWContextManager::firePushSubscriptionChangeEvent):
     45        * workers/service/context/SWContextManager.h:
     46        * workers/service/context/ServiceWorkerThread.cpp:
     47        (WebCore::ServiceWorkerThread::queueTaskToFirePushSubscriptionChangeEvent):
     48        (WebCore::ServiceWorkerThread::heartBeatTimerFired):
     49        (WebCore::ServiceWorkerThread::willPostTaskToFirePushSubscriptionChangeEvent):
     50        (WebCore::ServiceWorkerThread::finishedFiringPushSubscriptionChangeEvent):
     51        * workers/service/context/ServiceWorkerThread.h:
     52        * workers/service/context/ServiceWorkerThreadProxy.cpp:
     53        (WebCore::ServiceWorkerThreadProxy::firePushSubscriptionChangeEvent):
     54        * workers/service/context/ServiceWorkerThreadProxy.h:
     55
    1562021-11-18  Mark Lam  <mark.lam@apple.com>
    257
  • trunk/Source/WebCore/Modules/push-api/PushSubscription.cpp

    r285564 r286044  
    4141WTF_MAKE_ISO_ALLOCATED_IMPL(PushSubscription);
    4242
    43 PushSubscription::PushSubscription(String&& endpoint, std::optional<EpochTimeStamp> expirationTime, Vector<uint8_t>&& serverVAPIDPublicKey, Vector<uint8_t>&& clientECDHPublicKey, Vector<uint8_t>&& sharedAuthenticationSecret)
    44     : m_endpoint(WTFMove(endpoint))
    45     , m_expirationTime(expirationTime)
    46     , m_options(PushSubscriptionOptions::create(WTFMove(serverVAPIDPublicKey)))
    47     , m_clientECDHPublicKey(WTFMove(clientECDHPublicKey))
    48     , m_sharedAuthenticationSecret(WTFMove(sharedAuthenticationSecret))
    49 {
    50 }
    51 
    52 PushSubscription::PushSubscription(Ref<ServiceWorkerRegistration>&& registration, String&& endpoint, std::optional<EpochTimeStamp> expirationTime, Vector<uint8_t>&& serverVAPIDPublicKey, Vector<uint8_t>&& clientECDHPublicKey, Vector<uint8_t>&& sharedAuthenticationSecret)
    53     : m_serviceWorkerRegistration(WTFMove(registration))
    54     , m_endpoint(WTFMove(endpoint))
    55     , m_expirationTime(expirationTime)
    56     , m_options(PushSubscriptionOptions::create(WTFMove(serverVAPIDPublicKey)))
    57     , m_clientECDHPublicKey(WTFMove(clientECDHPublicKey))
    58     , m_sharedAuthenticationSecret(WTFMove(sharedAuthenticationSecret))
     43PushSubscription::PushSubscription(PushSubscriptionData&& data, RefPtr<ServiceWorkerRegistration>&& registration)
     44    : m_data(WTFMove(data))
     45    , m_serviceWorkerRegistration(WTFMove(registration))
    5946{
    6047}
     
    6249PushSubscription::~PushSubscription() = default;
    6350
     51const PushSubscriptionData& PushSubscription::data() const
     52{
     53    return m_data;
     54}
     55
    6456const String& PushSubscription::endpoint() const
    6557{
    66     return m_endpoint;
     58    return m_data.endpoint;
    6759}
    6860
    6961std::optional<EpochTimeStamp> PushSubscription::expirationTime() const
    7062{
    71     return m_expirationTime;
     63    return m_data.expirationTime;
    7264}
    7365
    7466PushSubscriptionOptions& PushSubscription::options() const
    7567{
    76     return m_options;
     68    if (!m_options) {
     69        auto key = m_data.serverVAPIDPublicKey;
     70        m_options = PushSubscriptionOptions::create(WTFMove(key));
     71    }
     72
     73    return *m_options;
     74}
     75
     76const Vector<uint8_t>& PushSubscription::clientECDHPublicKey() const
     77{
     78    return m_data.clientECDHPublicKey;
     79}
     80
     81const Vector<uint8_t>& PushSubscription::sharedAuthenticationSecret() const
     82{
     83    return m_data.sharedAuthenticationSecret;
    7784}
    7885
    7986ExceptionOr<RefPtr<JSC::ArrayBuffer>> PushSubscription::getKey(PushEncryptionKeyName name) const
    8087{
    81     const Vector<uint8_t> *source = nullptr;
     88    const Vector<uint8_t>* source = nullptr;
    8289
    8390    switch (name) {
    8491    case PushEncryptionKeyName::P256dh:
    85         source = &m_clientECDHPublicKey;
     92        source = &clientECDHPublicKey();
    8693        break;
    8794    case PushEncryptionKeyName::Auth:
    88         source = &m_sharedAuthenticationSecret;
     95        source = &sharedAuthenticationSecret();
    8996        break;
    9097    default:
     
    113120{
    114121    return PushSubscriptionJSON {
    115         m_endpoint,
    116         m_expirationTime,
     122        endpoint(),
     123        expirationTime(),
    117124        Vector<KeyValuePair<String, String>> {
    118             { "p256dh"_s, base64URLEncodeToString(m_clientECDHPublicKey) },
    119             { "auth"_s, base64URLEncodeToString(m_sharedAuthenticationSecret) }
     125            { "p256dh"_s, base64URLEncodeToString(clientECDHPublicKey()) },
     126            { "auth"_s, base64URLEncodeToString(sharedAuthenticationSecret()) }
    120127        }
    121128    };
  • trunk/Source/WebCore/Modules/push-api/PushSubscription.h

    r285564 r286044  
    3232#include "JSDOMPromiseDeferred.h"
    3333#include "PushEncryptionKeyName.h"
     34#include "PushSubscriptionData.h"
    3435#include "PushSubscriptionJSON.h"
    3536
     
    5253    WEBCORE_EXPORT ~PushSubscription();
    5354
     55    WEBCORE_EXPORT const PushSubscriptionData& data() const;
     56
    5457    const String& endpoint() const;
    5558    std::optional<EpochTimeStamp> expirationTime() const;
    5659    PushSubscriptionOptions& options() const;
     60    const Vector<uint8_t>& clientECDHPublicKey() const;
     61    const Vector<uint8_t>& sharedAuthenticationSecret() const;
     62
    5763    ExceptionOr<RefPtr<JSC::ArrayBuffer>> getKey(PushEncryptionKeyName) const;
    5864    void unsubscribe(ScriptExecutionContext&, DOMPromiseDeferred<IDLBoolean>&&);
     
    6167
    6268private:
    63     WEBCORE_EXPORT PushSubscription(String&& endpoint, std::optional<EpochTimeStamp> expirationTime, Vector<uint8_t>&& serverVAPIDPublicKey, Vector<uint8_t>&& clientECDHPublicKey, Vector<uint8_t>&& auth);
    64     PushSubscription(Ref<ServiceWorkerRegistration>&&, String&& endpoint, std::optional<EpochTimeStamp> expirationTime, Vector<uint8_t>&& serverVAPIDPublicKey, Vector<uint8_t>&& clientECDHPublicKey, Vector<uint8_t>&& auth);
     69    WEBCORE_EXPORT explicit PushSubscription(PushSubscriptionData&&, RefPtr<ServiceWorkerRegistration>&& = nullptr);
    6570
     71    PushSubscriptionData m_data;
    6672    RefPtr<ServiceWorkerRegistration> m_serviceWorkerRegistration;
    67     String m_endpoint;
    68     std::optional<EpochTimeStamp> m_expirationTime;
    69     Ref<PushSubscriptionOptions> m_options;
    70     Vector<uint8_t> m_clientECDHPublicKey;
    71     Vector<uint8_t> m_sharedAuthenticationSecret;
     73    mutable RefPtr<PushSubscriptionOptions> m_options;
    7274};
    7375
  • trunk/Source/WebCore/Modules/push-api/ServiceWorkerGlobalScope+PushAPI.idl

    r285867 r286044  
    2828] partial interface ServiceWorkerGlobalScope {
    2929    attribute EventHandler onpush;
     30    attribute EventHandler onpushsubscriptionchange;
    3031};
  • trunk/Source/WebCore/bindings/js/WebCoreBuiltinNames.h

    r285731 r286044  
    454454    macro(mediaStreamTrackConstraints) \
    455455    macro(onpush) \
     456    macro(onpushsubscriptionchange) \
    456457    macro(onrtctransform) \
    457458    macro(ontouchcancel) \
  • trunk/Source/WebCore/dom/EventNames.h

    r283438 r286044  
    223223    macro(progress) \
    224224    macro(push) \
     225    macro(pushsubscriptionchange) \
    225226    macro(ratechange) \
    226227    macro(readystatechange) \
  • trunk/Source/WebCore/testing/Internals.cpp

    r286021 r286044  
    166166#include "PseudoElement.h"
    167167#include "PushSubscription.h"
     168#include "PushSubscriptionData.h"
    168169#include "RTCRtpSFrameTransform.h"
    169170#include "Range.h"
     
    195196#include "ServiceWorker.h"
    196197#include "ServiceWorkerProvider.h"
     198#include "ServiceWorkerRegistration.h"
    197199#include "ServiceWorkerRegistrationData.h"
    198200#include "Settings.h"
     
    65956597    Vector<uint8_t> myAuth { static_cast<const uint8_t*>(auth.data()), auth.byteLength() };
    65966598
    6597     return PushSubscription::create(WTFMove(myEndpoint), expirationTime, WTFMove(myServerVAPIDPublicKey), WTFMove(myClientECDHPublicKey), WTFMove(myAuth));
     6599    return PushSubscription::create(PushSubscriptionData { WTFMove(myEndpoint), expirationTime, WTFMove(myServerVAPIDPublicKey), WTFMove(myClientECDHPublicKey), WTFMove(myAuth) });
    65986600}
    65996601#endif
  • trunk/Source/WebCore/testing/ServiceWorkerInternals.cpp

    r285564 r286044  
    3232#include "JSFetchResponse.h"
    3333#include "PushSubscription.h"
     34#include "PushSubscriptionData.h"
    3435#include "SWContextManager.h"
     36#include "ServiceWorkerRegistration.h"
    3537#include <wtf/ProcessID.h>
    3638
     
    8082            }
    8183        });
     84    });
     85}
     86
     87void ServiceWorkerInternals::schedulePushSubscriptionChangeEvent(PushSubscription* newSubscription, PushSubscription* oldSubscription)
     88{
     89    std::optional<PushSubscriptionData> newSubscriptionData;
     90    std::optional<PushSubscriptionData> oldSubscriptionData;
     91
     92    if (newSubscription)
     93        newSubscriptionData = newSubscription->data().isolatedCopy();
     94    if (oldSubscription)
     95        oldSubscriptionData = oldSubscription->data().isolatedCopy();
     96
     97    callOnMainThread([identifier = m_identifier, newSubscriptionData = WTFMove(newSubscriptionData), oldSubscriptionData = WTFMove(oldSubscriptionData)]() mutable {
     98        SWContextManager::singleton().firePushSubscriptionChangeEvent(identifier, WTFMove(newSubscriptionData), WTFMove(oldSubscriptionData));
    8299    });
    83100}
     
    169186    Vector<uint8_t> myAuth { static_cast<const uint8_t*>(auth.data()), auth.byteLength() };
    170187
    171     return PushSubscription::create(WTFMove(myEndpoint), expirationTime, WTFMove(myServerVAPIDPublicKey), WTFMove(myClientECDHPublicKey), WTFMove(myAuth));
     188    return PushSubscription::create(PushSubscriptionData { WTFMove(myEndpoint), expirationTime, WTFMove(myServerVAPIDPublicKey), WTFMove(myClientECDHPublicKey), WTFMove(myAuth) });
    172189}
    173190
  • trunk/Source/WebCore/testing/ServiceWorkerInternals.h

    r285564 r286044  
    5757
    5858    void schedulePushEvent(const String&, RefPtr<DeferredPromise>&&);
     59    void schedulePushSubscriptionChangeEvent(PushSubscription* newSubscription, PushSubscription* oldSubscription);
    5960    Vector<String> fetchResponseHeaderList(FetchResponse&);
    6061
  • trunk/Source/WebCore/testing/ServiceWorkerInternals.idl

    r285564 r286044  
    4040
    4141    Promise<boolean> schedulePushEvent(optional DOMString data);
     42    undefined schedulePushSubscriptionChangeEvent(PushSubscription? newSubscription, PushSubscription? oldSubscription);
    4243
    4344    readonly attribute DOMString processName;
  • trunk/Source/WebCore/workers/service/ServiceWorkerContainer.cpp

    r286012 r286044  
    553553}
    554554
    555 static Ref<PushSubscription> createPushSubscriptionFromData(Ref<ServiceWorkerRegistration> registration, PushSubscriptionData&& data)
    556 {
    557     return PushSubscription::create(WTFMove(registration), WTFMove(data.endpoint), data.expirationTime, WTFMove(data.serverVAPIDPublicKey), WTFMove(data.clientECDHPublicKey), WTFMove(data.sharedAuthenticationSecret));
    558 }
    559 
    560555void ServiceWorkerContainer::subscribeToPushService(ServiceWorkerRegistration& registration, const Vector<uint8_t>& applicationServerKey, DOMPromiseDeferred<IDLInterface<PushSubscription>>&& promise)
    561556{
     
    566561        }
    567562       
    568         promise.resolve(createPushSubscriptionFromData(WTFMove(protectedRegistration), result.releaseReturnValue()));
     563        promise.resolve(PushSubscription::create(result.releaseReturnValue(), WTFMove(protectedRegistration)));
    569564    });
    570565}
     
    591586        }
    592587
    593         promise.resolve(createPushSubscriptionFromData(WTFMove(protectedRegistration), WTFMove(*optionalPushSubscriptionData)).ptr());
     588        promise.resolve(PushSubscription::create(WTFMove(*optionalPushSubscriptionData), WTFMove(protectedRegistration)).ptr());
    594589    });
    595590}
  • trunk/Source/WebCore/workers/service/ServiceWorkerRegistration.h

    r285564 r286044  
    4646
    4747class ServiceWorkerRegistration final : public RefCounted<ServiceWorkerRegistration>, public Supplementable<ServiceWorkerRegistration>, public EventTargetWithInlineData, public ActiveDOMObject {
    48     WTF_MAKE_ISO_ALLOCATED(ServiceWorkerRegistration);
     48    WTF_MAKE_ISO_ALLOCATED_EXPORT(ServiceWorkerRegistration, WEBCORE_EXPORT);
    4949public:
    5050    static Ref<ServiceWorkerRegistration> getOrCreate(ScriptExecutionContext&, Ref<ServiceWorkerContainer>&&, ServiceWorkerRegistrationData&&);
    5151
    52     ~ServiceWorkerRegistration();
     52    WEBCORE_EXPORT ~ServiceWorkerRegistration();
    5353
    5454    ServiceWorkerRegistrationIdentifier identifier() const { return m_registrationData.identifier; }
  • trunk/Source/WebCore/workers/service/context/SWContextManager.cpp

    r286012 r286044  
    120120}
    121121
     122void SWContextManager::firePushSubscriptionChangeEvent(ServiceWorkerIdentifier identifier, std::optional<PushSubscriptionData>&& newSubscriptionData, std::optional<PushSubscriptionData>&& oldSubscriptionData)
     123{
     124    auto* serviceWorker = m_workerMap.get(identifier);
     125    if (!serviceWorker)
     126        return;
     127
     128    serviceWorker->firePushSubscriptionChangeEvent(WTFMove(newSubscriptionData), WTFMove(oldSubscriptionData));
     129}
     130
    122131
    123132void SWContextManager::terminateWorker(ServiceWorkerIdentifier identifier, Seconds timeout, Function<void()>&& completionHandler)
  • trunk/Source/WebCore/workers/service/context/SWContextManager.h

    r286012 r286044  
    2929
    3030#include "ExceptionOr.h"
     31#include "PushSubscriptionData.h"
    3132#include "ServiceWorkerClientData.h"
    3233#include "ServiceWorkerClientQueryOptions.h"
     
    9293    WEBCORE_EXPORT void fireActivateEvent(ServiceWorkerIdentifier);
    9394    WEBCORE_EXPORT void firePushEvent(ServiceWorkerIdentifier, std::optional<Vector<uint8_t>>&&, CompletionHandler<void(bool)>&&);
     95    WEBCORE_EXPORT void firePushSubscriptionChangeEvent(ServiceWorkerIdentifier, std::optional<PushSubscriptionData>&& newSubscriptionData, std::optional<PushSubscriptionData>&& oldSubscriptionData);
    9496
    9597    WEBCORE_EXPORT void terminateWorker(ServiceWorkerIdentifier, Seconds timeout, Function<void()>&&);
  • trunk/Source/WebCore/workers/service/context/ServiceWorkerThread.cpp

    r286012 r286044  
    3939#include "PlatformStrategies.h"
    4040#include "PushEvent.h"
     41#include "PushSubscription.h"
     42#include "PushSubscriptionChangeEvent.h"
    4143#include "SWContextManager.h"
    4244#include "SecurityOrigin.h"
     
    236238}
    237239
     240void ServiceWorkerThread::queueTaskToFirePushSubscriptionChangeEvent(std::optional<PushSubscriptionData>&& newSubscriptionData, std::optional<PushSubscriptionData>&& oldSubscriptionData)
     241{
     242    Ref serviceWorkerGlobalScope = downcast<ServiceWorkerGlobalScope>(*globalScope());
     243    serviceWorkerGlobalScope->eventLoop().queueTask(TaskSource::DOMManipulation, [weakThis = WeakPtr { *this }, serviceWorkerGlobalScope, newSubscriptionData = WTFMove(newSubscriptionData), oldSubscriptionData = WTFMove(oldSubscriptionData)]() mutable {
     244        RELEASE_LOG(ServiceWorker, "ServiceWorkerThread::queueTaskToFirePushSubscriptionChangeEvent firing event for worker %" PRIu64, serviceWorkerGlobalScope->thread().identifier().toUInt64());
     245
     246        RefPtr<PushSubscription> newSubscription;
     247        RefPtr<PushSubscription> oldSubscription;
     248
     249        if (newSubscriptionData)
     250            newSubscription = PushSubscription::create(WTFMove(*newSubscriptionData), &serviceWorkerGlobalScope->registration());
     251        if (oldSubscriptionData)
     252            oldSubscription = PushSubscription::create(WTFMove(*oldSubscriptionData));
     253
     254        auto pushSubscriptionChangeEvent = PushSubscriptionChangeEvent::create(eventNames().pushsubscriptionchangeEvent, { }, WTFMove(newSubscription), WTFMove(oldSubscription), ExtendableEvent::IsTrusted::Yes);
     255        serviceWorkerGlobalScope->dispatchEvent(pushSubscriptionChangeEvent);
     256
     257        pushSubscriptionChangeEvent->whenAllExtendLifetimePromisesAreSettled([weakThis = WTFMove(weakThis)](auto&&) mutable {
     258            callOnMainThread([weakThis = WTFMove(weakThis)] {
     259                RELEASE_LOG(ServiceWorker, "ServiceWorkerThread::queueTaskToFirePushSubscriptionChangeEvent finishing for worker %llu", weakThis ? weakThis->identifier().toUInt64() : 0);
     260                if (weakThis)
     261                    weakThis->finishedFiringPushSubscriptionChangeEvent();
     262            });
     263        });
     264    });
     265}
     266
    238267void ServiceWorkerThread::finishedEvaluatingScript()
    239268{
     
    296325{
    297326    if (!m_ongoingHeartBeatCheck) {
    298         if (m_state == State::Installing || m_state == State::Activating || m_isHandlingFetchEvent || m_isHandlingPushEvent || m_messageEventCount)
     327        if (m_state == State::Installing || m_state == State::Activating || m_isHandlingFetchEvent || m_isHandlingPushEvent || m_pushSubscriptionChangeEventCount || m_messageEventCount)
    299328            startHeartBeatTimer();
    300329        return;
     
    363392}
    364393
     394void ServiceWorkerThread::willPostTaskToFirePushSubscriptionChangeEvent()
     395{
     396    if (!m_pushSubscriptionChangeEventCount++)
     397        startHeartBeatTimer();
     398}
     399
     400void ServiceWorkerThread::finishedFiringPushSubscriptionChangeEvent()
     401{
     402    ASSERT(m_pushSubscriptionChangeEventCount);
     403    --m_pushSubscriptionChangeEventCount;
     404}
     405
    365406} // namespace WebCore
    366407
  • trunk/Source/WebCore/workers/service/context/ServiceWorkerThread.h

    r286012 r286044  
    2828#if ENABLE(SERVICE_WORKER)
    2929
     30#include "PushSubscriptionData.h"
    3031#include "ScriptExecutionContextIdentifier.h"
    3132#include "ServiceWorkerContextData.h"
     
    6263    void willPostTaskToFireActivateEvent();
    6364    void willPostTaskToFireMessageEvent();
     65    void willPostTaskToFirePushSubscriptionChangeEvent();
    6466
    6567    void queueTaskToFireFetchEvent(Ref<ServiceWorkerFetch::Client>&&, std::optional<ScriptExecutionContextIdentifier>&&, ResourceRequest&&, String&& referrer, FetchOptions&&);
     
    6870    void queueTaskToFireActivateEvent();
    6971    void queueTaskToFirePushEvent(std::optional<Vector<uint8_t>>&&, Function<void(bool)>&&);
     72    void queueTaskToFirePushSubscriptionChangeEvent(std::optional<PushSubscriptionData>&& newSubscriptionData, std::optional<PushSubscriptionData>&& oldSubscriptionData);
    7073
    7174    ServiceWorkerIdentifier identifier() const { return m_serviceWorkerIdentifier; }
     
    9194    void finishedFiringActivateEvent();
    9295    void finishedFiringMessageEvent();
     96    void finishedFiringPushSubscriptionChangeEvent();
    9397    void finishedStarting();
    9498
     
    106110    bool m_isHandlingFetchEvent { false };
    107111    bool m_isHandlingPushEvent { false };
     112    uint64_t m_pushSubscriptionChangeEventCount { 0 };
    108113    uint64_t m_messageEventCount { 0 };
    109114    enum class State { Idle, Starting, Installing, Activating };
  • trunk/Source/WebCore/workers/service/context/ServiceWorkerThreadProxy.cpp

    r286012 r286044  
    4646#include "Settings.h"
    4747#include "WorkerGlobalScope.h"
     48#include <wtf/CrossThreadCopier.h>
    4849#include <wtf/MainThread.h>
    4950#include <wtf/RunLoop.h>
     
    321322}
    322323
     324void ServiceWorkerThreadProxy::firePushSubscriptionChangeEvent(std::optional<PushSubscriptionData>&& newSubscriptionData, std::optional<PushSubscriptionData>&& oldSubscriptionData)
     325{
     326    thread().willPostTaskToFirePushSubscriptionChangeEvent();
     327    thread().runLoop().postTask([this, protectedThis = Ref { *this }, newSubscriptionData = crossThreadCopy(WTFMove(newSubscriptionData)), oldSubscriptionData = crossThreadCopy(WTFMove(oldSubscriptionData))](auto&) mutable {
     328        thread().queueTaskToFirePushSubscriptionChangeEvent(WTFMove(newSubscriptionData), WTFMove(oldSubscriptionData));
     329    });
     330}
     331
    323332} // namespace WebCore
    324333
  • trunk/Source/WebCore/workers/service/context/ServiceWorkerThreadProxy.h

    r286012 r286044  
    3232#include "FetchIdentifier.h"
    3333#include "Page.h"
     34#include "PushSubscriptionData.h"
    3435#include "ServiceWorkerDebuggable.h"
    3536#include "ServiceWorkerIdentifier.h"
     
    8283    void fireActivateEvent();
    8384    void firePushEvent(std::optional<Vector<uint8_t>>&&, CompletionHandler<void(bool)>&&);
     85    void firePushSubscriptionChangeEvent(std::optional<PushSubscriptionData>&& newSubscriptionData, std::optional<PushSubscriptionData>&& oldSubscriptionData);
    8486
    8587    void didSaveScriptsToDisk(ScriptBuffer&&, HashMap<URL, ScriptBuffer>&& importedScripts);
Note: See TracChangeset for help on using the changeset viewer.