Title: [292110] trunk
Revision
292110
Author
[email protected]
Date
2022-03-30 11:40:18 -0700 (Wed, 30 Mar 2022)

Log Message

Implement persistent notification handling
https://bugs.webkit.org/show_bug.cgi?id=238498

Reviewed by Brady Eidson.

Source/WebCore:

Before the patch, we were directly going from UIProcess to service worker process.
This works if the service worker is running but does not otherwise.
To make sure we now go to NetworkProcess.
To implement https://notifications.spec.whatwg.org/#persistent-notification,
we add a service worker registration URL to NotficationData.
We remove the notfication handling going through NotificationEvent and make it Document specific.
Instead, we go through ServiceWorkerThreadProxy.
Make sure SWServer treats notification events as functional events.
Covered by updated test.

* Headers.cmake:
* Modules/notifications/Notification.cpp:
(WebCore::Notification::create):
(WebCore::Notification::dispatchClickEvent):
(WebCore::Notification::dispatchCloseEvent):
(WebCore::Notification::data const):
* Modules/notifications/Notification.h:
* Modules/notifications/NotificationData.cpp:
(WebCore::NotificationData::isolatedCopy const):
(WebCore::NotificationData::isolatedCopy):
* Modules/notifications/NotificationData.h:
(WebCore::NotificationData::encode const):
(WebCore::NotificationData::decode):
* Modules/notifications/NotificationEvent.h:
* Modules/notifications/NotificationEventType.h: Added.
* WebCore.xcodeproj/project.pbxproj:
* workers/service/ServiceWorkerGlobalScope.cpp:
(WebCore::ServiceWorkerGlobalScope::postTaskToFireNotificationEvent): Deleted.
* workers/service/ServiceWorkerGlobalScope.h:
* workers/service/context/SWContextManager.cpp:
(WebCore::SWContextManager::fireNotificationEvent):
* workers/service/context/SWContextManager.h:
* workers/service/context/ServiceWorkerThread.cpp:
(WebCore::ServiceWorkerThread::queueTaskToFirePushSubscriptionChangeEvent):
(WebCore::ServiceWorkerThread::queueTaskToFireNotificationEvent):
(WebCore::ServiceWorkerThread::startFunctionalEventMonitoring):
(WebCore::ServiceWorkerThread::heartBeatTimerFired):
(WebCore::ServiceWorkerThread::startPushEventMonitoring): Deleted.
* workers/service/context/ServiceWorkerThread.h:
(WebCore::ServiceWorkerThread::stopFunctionalEventMonitoring):
(WebCore::ServiceWorkerThread::stopPushEventMonitoring): Deleted.
* workers/service/context/ServiceWorkerThreadProxy.cpp:
(WebCore::ServiceWorkerThreadProxy::~ServiceWorkerThreadProxy):
(WebCore::ServiceWorkerThreadProxy::firePushEvent):
(WebCore::ServiceWorkerThreadProxy::fireNotificationEvent):
* workers/service/context/ServiceWorkerThreadProxy.h:
* workers/service/server/SWServer.cpp:
(WebCore::SWServer::unregisterServiceWorkerClient):
(WebCore::SWServer::processPushMessage):
(WebCore::SWServer::processNotificationEvent):
* workers/service/server/SWServer.h:
* workers/service/server/SWServerToContextConnection.h:
* workers/service/server/SWServerWorker.cpp:
(WebCore::SWServerWorker::decrementFunctionalEventCounter):
(WebCore::SWServerWorker::terminateIfPossible):
(WebCore::SWServerWorker::decrementPushEventCounter): Deleted.
* workers/service/server/SWServerWorker.h:
(WebCore::SWServerWorker::incrementFunctionalEventCounter):
(WebCore::SWServerWorker::shouldContinue const):
(WebCore::SWServerWorker::incrementPushEventCounter): Deleted.

Source/WebKit:

When receiving an update for a notification, check if the notification is tied to a service worker registration.
If so, go to network process to fire a functional event, as per https://notifications.spec.whatwg.org/#activating-a-notification
and https://notifications.spec.whatwg.org/#ref-for-fire-a-service-worker-notification-eventâ‘ 
UIProcess sends the corresponding NotficationData to NetworkProcess.
NetworkProcess gets the service worker registration, runs the service worker as needed and fires the functional event.
Add IPC plumbing code to support this flow.

* NetworkProcess/NetworkProcess.cpp:
(WebKit::NetworkProcess::processNotificationEvent):
(WebKit::NetworkProcess::processPushMessage):
* NetworkProcess/NetworkProcess.h:
* NetworkProcess/NetworkProcess.messages.in:
* NetworkProcess/ServiceWorker/WebSWServerToContextConnection.cpp:
(WebKit::WebSWServerToContextConnection::firePushEvent):
(WebKit::WebSWServerToContextConnection::fireNotificationEvent):
* NetworkProcess/ServiceWorker/WebSWServerToContextConnection.h:
* UIProcess/Network/NetworkProcessProxy.cpp:
(WebKit::NetworkProcessProxy::processNotificationEvent):
* UIProcess/Network/NetworkProcessProxy.h:
* UIProcess/Notifications/WebNotification.cpp:
(WebKit::WebNotification::WebNotification):
* UIProcess/Notifications/WebNotification.h:
(WebKit::WebNotification::title const):
(WebKit::WebNotification::body const):
(WebKit::WebNotification::iconURL const):
(WebKit::WebNotification::tag const):
(WebKit::WebNotification::lang const):
(WebKit::WebNotification::dir const):
(WebKit::WebNotification::coreNotificationID const):
(WebKit::WebNotification::sessionID const):
(WebKit::WebNotification::data const):
(WebKit::WebNotification::isPersistentNotification const):
(WebKit::WebNotification::notificationID const):
* UIProcess/Notifications/WebNotificationManagerProxy.cpp:
(WebKit::dispatchDidClickNotification):
(WebKit::WebNotificationManagerProxy::providerDidCloseNotifications):
* WebProcess/Storage/WebSWContextManagerConnection.cpp:
(WebKit::WebSWContextManagerConnection::fireNotificationEvent):
* WebProcess/Storage/WebSWContextManagerConnection.h:
* WebProcess/Storage/WebSWContextManagerConnection.messages.in:

LayoutTests:

* http/tests/workers/service/shownotification-allowed.html:

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (292109 => 292110)


--- trunk/LayoutTests/ChangeLog	2022-03-30 18:39:39 UTC (rev 292109)
+++ trunk/LayoutTests/ChangeLog	2022-03-30 18:40:18 UTC (rev 292110)
@@ -1,3 +1,12 @@
+2022-03-30  Youenn Fablet  <[email protected]>
+
+        Implement persistent notification handling
+        https://bugs.webkit.org/show_bug.cgi?id=238498
+
+        Reviewed by Brady Eidson.
+
+        * http/tests/workers/service/shownotification-allowed.html:
+
 2022-03-30  Devin Rousso  <[email protected]>
 
         Unreviewed, fix test after r285521 and r271735

Modified: trunk/LayoutTests/http/tests/workers/service/shownotification-allowed.html (292109 => 292110)


--- trunk/LayoutTests/http/tests/workers/service/shownotification-allowed.html	2022-03-30 18:39:39 UTC (rev 292109)
+++ trunk/LayoutTests/http/tests/workers/service/shownotification-allowed.html	2022-03-30 18:40:18 UTC (rev 292110)
@@ -45,10 +45,16 @@
 var gotClicked = false;
 var gotClosed = false;
 
-navigator.serviceWorker.addEventListener('message', event => {
+navigator.serviceWorker.addEventListener('message', async event => {
     if (event.data == "showFailed") {
         failTheTest("Unexpectedly received the failed-to-show message");
     } else if (event.data == "shown") {
+        // We simulate a network process crash so that we make sure that a notification click ensures restarting a service worker
+        if (window.internals)
+            await internals.storeRegistrationsOnDisk();
+        if (window.testRunner)
+            testRunner.terminateNetworkProcess();
+
         if (testRunner)
             testRunner.simulateWebNotificationClickForServiceWorkerNotifications();
     } else if (event.data == "clicked") {

Modified: trunk/Source/WebCore/ChangeLog (292109 => 292110)


--- trunk/Source/WebCore/ChangeLog	2022-03-30 18:39:39 UTC (rev 292109)
+++ trunk/Source/WebCore/ChangeLog	2022-03-30 18:40:18 UTC (rev 292110)
@@ -1,3 +1,71 @@
+2022-03-30  Youenn Fablet  <[email protected]>
+
+        Implement persistent notification handling
+        https://bugs.webkit.org/show_bug.cgi?id=238498
+
+        Reviewed by Brady Eidson.
+
+        Before the patch, we were directly going from UIProcess to service worker process.
+        This works if the service worker is running but does not otherwise.
+        To make sure we now go to NetworkProcess.
+        To implement https://notifications.spec.whatwg.org/#persistent-notification,
+        we add a service worker registration URL to NotficationData.
+        We remove the notfication handling going through NotificationEvent and make it Document specific.
+        Instead, we go through ServiceWorkerThreadProxy.
+        Make sure SWServer treats notification events as functional events.
+        Covered by updated test.
+
+        * Headers.cmake:
+        * Modules/notifications/Notification.cpp:
+        (WebCore::Notification::create):
+        (WebCore::Notification::dispatchClickEvent):
+        (WebCore::Notification::dispatchCloseEvent):
+        (WebCore::Notification::data const):
+        * Modules/notifications/Notification.h:
+        * Modules/notifications/NotificationData.cpp:
+        (WebCore::NotificationData::isolatedCopy const):
+        (WebCore::NotificationData::isolatedCopy):
+        * Modules/notifications/NotificationData.h:
+        (WebCore::NotificationData::encode const):
+        (WebCore::NotificationData::decode):
+        * Modules/notifications/NotificationEvent.h:
+        * Modules/notifications/NotificationEventType.h: Added.
+        * WebCore.xcodeproj/project.pbxproj:
+        * workers/service/ServiceWorkerGlobalScope.cpp:
+        (WebCore::ServiceWorkerGlobalScope::postTaskToFireNotificationEvent): Deleted.
+        * workers/service/ServiceWorkerGlobalScope.h:
+        * workers/service/context/SWContextManager.cpp:
+        (WebCore::SWContextManager::fireNotificationEvent):
+        * workers/service/context/SWContextManager.h:
+        * workers/service/context/ServiceWorkerThread.cpp:
+        (WebCore::ServiceWorkerThread::queueTaskToFirePushSubscriptionChangeEvent):
+        (WebCore::ServiceWorkerThread::queueTaskToFireNotificationEvent):
+        (WebCore::ServiceWorkerThread::startFunctionalEventMonitoring):
+        (WebCore::ServiceWorkerThread::heartBeatTimerFired):
+        (WebCore::ServiceWorkerThread::startPushEventMonitoring): Deleted.
+        * workers/service/context/ServiceWorkerThread.h:
+        (WebCore::ServiceWorkerThread::stopFunctionalEventMonitoring):
+        (WebCore::ServiceWorkerThread::stopPushEventMonitoring): Deleted.
+        * workers/service/context/ServiceWorkerThreadProxy.cpp:
+        (WebCore::ServiceWorkerThreadProxy::~ServiceWorkerThreadProxy):
+        (WebCore::ServiceWorkerThreadProxy::firePushEvent):
+        (WebCore::ServiceWorkerThreadProxy::fireNotificationEvent):
+        * workers/service/context/ServiceWorkerThreadProxy.h:
+        * workers/service/server/SWServer.cpp:
+        (WebCore::SWServer::unregisterServiceWorkerClient):
+        (WebCore::SWServer::processPushMessage):
+        (WebCore::SWServer::processNotificationEvent):
+        * workers/service/server/SWServer.h:
+        * workers/service/server/SWServerToContextConnection.h:
+        * workers/service/server/SWServerWorker.cpp:
+        (WebCore::SWServerWorker::decrementFunctionalEventCounter):
+        (WebCore::SWServerWorker::terminateIfPossible):
+        (WebCore::SWServerWorker::decrementPushEventCounter): Deleted.
+        * workers/service/server/SWServerWorker.h:
+        (WebCore::SWServerWorker::incrementFunctionalEventCounter):
+        (WebCore::SWServerWorker::shouldContinue const):
+        (WebCore::SWServerWorker::incrementPushEventCounter): Deleted.
+
 2022-03-30  Carlos Alberto Lopez Perez  <[email protected]>
 
         [GTK][WPE] generate-bundle: self-contained bundle for the MiniBrowser that can work on any distro

Modified: trunk/Source/WebCore/Headers.cmake (292109 => 292110)


--- trunk/Source/WebCore/Headers.cmake	2022-03-30 18:39:39 UTC (rev 292109)
+++ trunk/Source/WebCore/Headers.cmake	2022-03-30 18:40:18 UTC (rev 292110)
@@ -291,6 +291,7 @@
     Modules/notifications/NotificationController.h
     Modules/notifications/NotificationData.h
     Modules/notifications/NotificationDirection.h
+    Modules/notifications/NotificationEventType.h
     Modules/notifications/NotificationPermission.h
     Modules/notifications/NotificationPermissionCallback.h
 

Modified: trunk/Source/WebCore/Modules/notifications/Notification.cpp (292109 => 292110)


--- trunk/Source/WebCore/Modules/notifications/Notification.cpp	2022-03-30 18:39:39 UTC (rev 292109)
+++ trunk/Source/WebCore/Modules/notifications/Notification.cpp	2022-03-30 18:40:18 UTC (rev 292110)
@@ -61,6 +61,15 @@
     return notification;
 }
 
+Ref<Notification> Notification::create(ScriptExecutionContext& context, NotificationData&& data)
+{
+    Options options { data.direction, WTFMove(data.language), WTFMove(data.body), WTFMove(data.tag), WTFMove(data.iconURL) };
+    auto notification = adoptRef(*new Notification(context, WTFMove(data.title), WTFMove(options)));
+    notification->suspendIfNeeded();
+    notification->m_relatedNotificationIdentifier = data.notificationID;
+    return notification;
+}
+
 Notification::Notification(ScriptExecutionContext& context, String&& title, Options&& options)
     : ActiveDOMObject(&context)
     , m_title(WTFMove(title).isolatedCopy())
@@ -132,6 +141,11 @@
     });
 }
 
+void Notification::markAsShown()
+{
+    m_state = Showing;
+}
+
 void Notification::show()
 {
     // prevent double-showing
@@ -224,37 +238,18 @@
 void Notification::dispatchClickEvent()
 {
     ASSERT(isMainThread());
-
-    switch (m_notificationSource) {
-    case NotificationSource::Document:
-        queueTaskKeepingObjectAlive(*this, TaskSource::UserInteraction, [this] {
-            WindowFocusAllowedIndicator windowFocusAllowed;
-            dispatchEvent(Event::create(eventNames().clickEvent, Event::CanBubble::No, Event::IsCancelable::No));
-        });
-        break;
-    case NotificationSource::ServiceWorker:
-        ServiceWorkerGlobalScope::ensureOnContextThread(m_contextIdentifier, [this, protectedThis = Ref { *this }](auto& context) {
-            downcast<ServiceWorkerGlobalScope>(context).postTaskToFireNotificationEvent(NotificationEventType::Click, *this, { });
-        });
-        break;
-    }
+    ASSERT(m_notificationSource == NotificationSource::Document);
+    queueTaskKeepingObjectAlive(*this, TaskSource::UserInteraction, [this] {
+        WindowFocusAllowedIndicator windowFocusAllowed;
+        dispatchEvent(Event::create(eventNames().clickEvent, Event::CanBubble::No, Event::IsCancelable::No));
+    });
 }
 
 void Notification::dispatchCloseEvent()
 {
     ASSERT(isMainThread());
-
-    switch (m_notificationSource) {
-    case NotificationSource::Document:
-        queueTaskToDispatchEvent(*this, TaskSource::UserInteraction, Event::create(eventNames().closeEvent, Event::CanBubble::No, Event::IsCancelable::No));
-        break;
-    case NotificationSource::ServiceWorker:
-        ServiceWorkerGlobalScope::ensureOnContextThread(m_contextIdentifier, [this, protectedThis = Ref { *this }](auto& context) {
-            downcast<ServiceWorkerGlobalScope>(context).postTaskToFireNotificationEvent(NotificationEventType::Close, *this, { });
-        });
-        break;
-    }
-
+    ASSERT(m_notificationSource == NotificationSource::Document);
+    queueTaskToDispatchEvent(*this, TaskSource::UserInteraction, Event::create(eventNames().closeEvent, Event::CanBubble::No, Event::IsCancelable::No));
     finalize();
 }
 
@@ -324,9 +319,15 @@
 
 NotificationData Notification::data() const
 {
-    auto sessionID = scriptExecutionContext()->sessionID();
+    auto& context = *scriptExecutionContext();
+    auto sessionID = context.sessionID();
     RELEASE_ASSERT(sessionID);
 
+    URL serviceWorkerRegistrationURL;
+#if ENABLE(SERVICE_WORKER)
+    if (is<ServiceWorkerGlobalScope>(context))
+        serviceWorkerRegistrationURL = downcast<ServiceWorkerGlobalScope>(context).registration().data().scopeURL;
+#endif
     return {
         m_title.isolatedCopy(),
         m_body.isolatedCopy(),
@@ -335,6 +336,7 @@
         m_lang,
         m_direction,
         scriptExecutionContext()->securityOrigin()->toString().isolatedCopy(),
+        WTFMove(serviceWorkerRegistrationURL).isolatedCopy(),
         identifier(),
         *sessionID,
     };

Modified: trunk/Source/WebCore/Modules/notifications/Notification.h (292109 => 292110)


--- trunk/Source/WebCore/Modules/notifications/Notification.h	2022-03-30 18:39:39 UTC (rev 292109)
+++ trunk/Source/WebCore/Modules/notifications/Notification.h	2022-03-30 18:40:18 UTC (rev 292110)
@@ -65,7 +65,8 @@
         String icon;
     };
     static Ref<Notification> create(ScriptExecutionContext&, String&& title, Options&&);
-    
+    static Ref<Notification> create(ScriptExecutionContext&, NotificationData&&);
+
     WEBCORE_EXPORT virtual ~Notification();
 
     void show();
@@ -99,6 +100,11 @@
     using ThreadSafeRefCounted::ref;
     using ThreadSafeRefCounted::deref;
 
+    void markAsShown();
+    void showSoon();
+
+    std::optional<UUID> relatedNotificationIdentifier() const { return m_relatedNotificationIdentifier; }
+
 private:
     Notification(ScriptExecutionContext&, String&& title, Options&&);
     Notification(const Notification&);
@@ -108,8 +114,6 @@
     NotificationClient* clientFromContext();
     EventTargetInterface eventTargetInterface() const final { return NotificationEventTargetInterfaceType; }
 
-    void showSoon();
-
     // ActiveDOMObject
     const char* activeDOMObjectName() const final;
     void suspend(ReasonForSuspension);
@@ -138,6 +142,7 @@
     };
     NotificationSource m_notificationSource;
     ScriptExecutionContextIdentifier m_contextIdentifier;
+    std::optional<UUID> m_relatedNotificationIdentifier;
 };
 
 } // namespace WebCore

Modified: trunk/Source/WebCore/Modules/notifications/NotificationData.cpp (292109 => 292110)


--- trunk/Source/WebCore/Modules/notifications/NotificationData.cpp	2022-03-30 18:39:39 UTC (rev 292109)
+++ trunk/Source/WebCore/Modules/notifications/NotificationData.cpp	2022-03-30 18:40:18 UTC (rev 292110)
@@ -28,4 +28,14 @@
 
 namespace WebCore {
 
+NotificationData NotificationData::isolatedCopy() const &
+{
+    return { title.isolatedCopy(), body.isolatedCopy(), iconURL.isolatedCopy(), tag.isolatedCopy(), language.isolatedCopy(), direction, originString.isolatedCopy(), serviceWorkerRegistrationURL.isolatedCopy(), notificationID, sourceSession };
+}
+
+NotificationData NotificationData::isolatedCopy() &&
+{
+    return { WTFMove(title).isolatedCopy(), WTFMove(body).isolatedCopy(), WTFMove(iconURL).isolatedCopy(), WTFMove(tag).isolatedCopy(), WTFMove(language).isolatedCopy(), direction, WTFMove(originString).isolatedCopy(), WTFMove(serviceWorkerRegistrationURL).isolatedCopy(), notificationID, sourceSession };
+}
+
 } // namespace WebCore

Modified: trunk/Source/WebCore/Modules/notifications/NotificationData.h (292109 => 292110)


--- trunk/Source/WebCore/Modules/notifications/NotificationData.h	2022-03-30 18:39:39 UTC (rev 292109)
+++ trunk/Source/WebCore/Modules/notifications/NotificationData.h	2022-03-30 18:40:18 UTC (rev 292110)
@@ -27,6 +27,7 @@
 
 #include <optional>
 #include <pal/SessionID.h>
+#include <wtf/URL.h>
 #include <wtf/UUID.h>
 #include <wtf/text/WTFString.h>
 
@@ -38,6 +39,9 @@
     template<class Encoder> void encode(Encoder&) const;
     template<class Decoder> static std::optional<NotificationData> decode(Decoder&);
 
+    NotificationData isolatedCopy() const &;
+    NotificationData isolatedCopy() &&;
+
     String title;
     String body;
     String iconURL;
@@ -45,6 +49,7 @@
     String language;
     WebCore::NotificationDirection direction;
     String originString;
+    URL serviceWorkerRegistrationURL;
     UUID notificationID;
     PAL::SessionID sourceSession;
 };
@@ -52,7 +57,7 @@
 template<class Encoder>
 void NotificationData::encode(Encoder& encoder) const
 {
-    encoder << title << body << iconURL << tag << language << direction << originString << notificationID << sourceSession;
+    encoder << title << body << iconURL << tag << language << direction << originString << serviceWorkerRegistrationURL << notificationID << sourceSession;
 }
 
 template<class Decoder>
@@ -93,6 +98,11 @@
     if (!originString)
         return std::nullopt;
 
+    std::optional<URL> serviceWorkerRegistrationURL;
+    decoder >> serviceWorkerRegistrationURL;
+    if (!serviceWorkerRegistrationURL)
+        return std::nullopt;
+
     std::optional<UUID> notificationID;
     decoder >> notificationID;
     if (!notificationID)
@@ -111,6 +121,7 @@
         WTFMove(*language),
         WTFMove(*direction),
         WTFMove(*originString),
+        WTFMove(*serviceWorkerRegistrationURL),
         WTFMove(*notificationID),
         WTFMove(*sourceSession),
     } };

Modified: trunk/Source/WebCore/Modules/notifications/NotificationEvent.h (292109 => 292110)


--- trunk/Source/WebCore/Modules/notifications/NotificationEvent.h	2022-03-30 18:39:39 UTC (rev 292109)
+++ trunk/Source/WebCore/Modules/notifications/NotificationEvent.h	2022-03-30 18:40:18 UTC (rev 292110)
@@ -30,14 +30,10 @@
 #include "ExtendableEvent.h"
 #include "ExtendableEventInit.h"
 #include "Notification.h"
+#include "NotificationEventType.h"
 
 namespace WebCore {
 
-enum class NotificationEventType : bool {
-    Click,
-    Close,
-};
-
 struct NotificationEventInit : ExtendableEventInit {
     RefPtr<Notification> notification;
     String action;

Copied: trunk/Source/WebCore/Modules/notifications/NotificationEventType.h (from rev 292109, trunk/Source/WebCore/Modules/notifications/NotificationData.cpp) (0 => 292110)


--- trunk/Source/WebCore/Modules/notifications/NotificationEventType.h	                        (rev 0)
+++ trunk/Source/WebCore/Modules/notifications/NotificationEventType.h	2022-03-30 18:40:18 UTC (rev 292110)
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2022 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include <wtf/EnumTraits.h>
+
+namespace WebCore {
+
+enum class NotificationEventType : bool {
+    Click,
+    Close,
+};
+
+} // namespace WebCore
+
+namespace WTF {
+
+template<> struct EnumTraits<WebCore::NotificationEventType> {
+    using values = EnumValues<
+        WebCore::NotificationEventType,
+        WebCore::NotificationEventType::Click,
+        WebCore::NotificationEventType::Close
+    >;
+};
+
+}

Modified: trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj (292109 => 292110)


--- trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj	2022-03-30 18:39:39 UTC (rev 292109)
+++ trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj	2022-03-30 18:40:18 UTC (rev 292110)
@@ -1074,6 +1074,7 @@
 		411223C52603567D00B0A0B6 /* DetachedRTCDataChannel.h in Headers */ = {isa = PBXBuildFile; fileRef = 411223C32603567C00B0A0B6 /* DetachedRTCDataChannel.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		4112B5431F9F9CA000E67875 /* ServiceWorkerThreadProxy.h in Headers */ = {isa = PBXBuildFile; fileRef = 4112B53F1F9F9C9B00E67875 /* ServiceWorkerThreadProxy.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		4114FE3225BEBD19009D9F20 /* RTCRtcpParameters.h in Headers */ = {isa = PBXBuildFile; fileRef = 4114FE2F25BEBD18009D9F20 /* RTCRtcpParameters.h */; };
+		41201F3727F2F74900D56CC2 /* NotificationEventType.h in Headers */ = {isa = PBXBuildFile; fileRef = 41201F3627F2F74600D56CC2 /* NotificationEventType.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		4123081B138C429700BCCFCA /* WebCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 93F19B1A08245E5A001E9ABC /* WebCore.framework */; };
 		41230913138C42FF00BCCFCA /* _javascript_Core.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F8216299029F4FB501000131 /* _javascript_Core.framework */; };
 		412827B227E4AC3C005ADDE2 /* VideoFrame.h in Headers */ = {isa = PBXBuildFile; fileRef = 7B5A3DAD27ABF8C4006C6F97 /* VideoFrame.h */; settings = {ATTRIBUTES = (Private, ); }; };
@@ -8585,6 +8586,7 @@
 		41189EF71AD8232800B90A0D /* ReadableStreamDefaultController.idl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = ReadableStreamDefaultController.idl; sourceTree = "<group>"; };
 		41189EF71AD8232800B93F64 /* ReadableByteStreamController.idl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = ReadableByteStreamController.idl; sourceTree = "<group>"; };
 		41189EF71AD8232800B95672 /* ReadableStreamBYOBRequest.idl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = ReadableStreamBYOBRequest.idl; sourceTree = "<group>"; };
+		41201F3627F2F74600D56CC2 /* NotificationEventType.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = NotificationEventType.h; sourceTree = "<group>"; };
 		41209E24257A2FBB00120ACA /* SFrameUtils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SFrameUtils.h; sourceTree = "<group>"; };
 		41209E26257A2FBB00120ACA /* SFrameUtils.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SFrameUtils.cpp; sourceTree = "<group>"; };
 		41209E91216D593C00A73A12 /* RTCCertificate.idl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = RTCCertificate.idl; sourceTree = "<group>"; };
@@ -20980,6 +20982,7 @@
 				510E2F2C276BE0C300809333 /* NotificationEvent.cpp */,
 				510E2F24276BB4EC00809333 /* NotificationEvent.h */,
 				510E2F22276BA9E800809333 /* NotificationEvent.idl */,
+				41201F3627F2F74600D56CC2 /* NotificationEventType.h */,
 				510E2F26276BC19F00809333 /* NotificationOptions.h */,
 				51E3AF0A276B05B7009B429D /* NotificationOptions.idl */,
 				7CC2DDF81EC9415A0027B774 /* NotificationPermission.h */,
@@ -36603,6 +36606,7 @@
 				51123E2F276940CA00F9D41B /* NotificationData.h in Headers */,
 				7CC2DE031ECA04A50027B774 /* NotificationDirection.h in Headers */,
 				510E2F25276BB4EC00809333 /* NotificationEvent.h in Headers */,
+				41201F3727F2F74900D56CC2 /* NotificationEventType.h in Headers */,
 				510E2F27276BC19F00809333 /* NotificationOptions.h in Headers */,
 				7CC2DDFB1EC9415A0027B774 /* NotificationPermission.h in Headers */,
 				31FE6DFA15004C2A0004EBC4 /* NotificationPermissionCallback.h in Headers */,

Modified: trunk/Source/WebCore/workers/service/ServiceWorkerGlobalScope.cpp (292109 => 292110)


--- trunk/Source/WebCore/workers/service/ServiceWorkerGlobalScope.cpp	2022-03-30 18:39:39 UTC (rev 292109)
+++ trunk/Source/WebCore/workers/service/ServiceWorkerGlobalScope.cpp	2022-03-30 18:40:18 UTC (rev 292110)
@@ -199,29 +199,6 @@
     }
 }
 
-#if ENABLE(NOTIFICATION_EVENT)
-void ServiceWorkerGlobalScope::postTaskToFireNotificationEvent(NotificationEventType eventType, Notification& notification, const String& action)
-{
-    thread().runLoop().postTaskForMode([eventType, protectedNotification = Ref { notification }, action = "" scope) {
-        scope.eventLoop().queueTask(TaskSource::DOMManipulation, [&scope, protectedScope = Ref { scope }, eventType, protectedNotification, action] {
-            AtomString eventName;
-            switch (eventType) {
-            case NotificationEventType::Click:
-                eventName = eventNames().notificationclickEvent;
-                downcast<ServiceWorkerGlobalScope>(scope).recordUserGesture();
-                break;
-            case NotificationEventType::Close:
-                eventName = eventNames().notificationcloseEvent;
-                break;
-            }
-
-            auto event = NotificationEvent::create(eventName, protectedNotification.ptr(), action, ExtendableEvent::IsTrusted::Yes);
-            downcast<ServiceWorkerGlobalScope>(scope).dispatchEvent(event);
-        });
-    }, WorkerRunLoop::defaultMode());
-}
-#endif
-
 void ServiceWorkerGlobalScope::recordUserGesture()
 {
     m_isProcessingUserGesture = true;

Modified: trunk/Source/WebCore/workers/service/ServiceWorkerGlobalScope.h (292109 => 292110)


--- trunk/Source/WebCore/workers/service/ServiceWorkerGlobalScope.h	2022-03-30 18:39:39 UTC (rev 292109)
+++ trunk/Source/WebCore/workers/service/ServiceWorkerGlobalScope.h	2022-03-30 18:40:18 UTC (rev 292110)
@@ -81,10 +81,6 @@
 
     WEBCORE_EXPORT Page* serviceWorkerPage();
 
-#if ENABLE(NOTIFICATION_EVENT)
-    void postTaskToFireNotificationEvent(NotificationEventType, Notification&, const String& action);
-#endif
-
     bool hasPendingSilentPushEvent() const { return m_hasPendingSilentPushEvent; }
     void setHasPendingSilentPushEvent(bool value) { m_hasPendingSilentPushEvent = value; }
 

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


--- trunk/Source/WebCore/workers/service/context/SWContextManager.cpp	2022-03-30 18:39:39 UTC (rev 292109)
+++ trunk/Source/WebCore/workers/service/context/SWContextManager.cpp	2022-03-30 18:40:18 UTC (rev 292110)
@@ -128,7 +128,15 @@
     serviceWorker->firePushSubscriptionChangeEvent(WTFMove(newSubscriptionData), WTFMove(oldSubscriptionData));
 }
 
+void SWContextManager::fireNotificationEvent(ServiceWorkerIdentifier identifier, NotificationData&& data, NotificationEventType eventType, CompletionHandler<void(bool)>&& callback)
+{
+    auto* serviceWorker = m_workerMap.get(identifier);
+    if (!serviceWorker)
+        return;
 
+    serviceWorker->fireNotificationEvent(WTFMove(data), eventType, WTFMove(callback));
+}
+
 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 (292109 => 292110)


--- trunk/Source/WebCore/workers/service/context/SWContextManager.h	2022-03-30 18:39:39 UTC (rev 292109)
+++ trunk/Source/WebCore/workers/service/context/SWContextManager.h	2022-03-30 18:40:18 UTC (rev 292110)
@@ -95,6 +95,7 @@
     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 fireNotificationEvent(ServiceWorkerIdentifier, NotificationData&&, NotificationEventType, CompletionHandler<void(bool)>&&);
 
     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 (292109 => 292110)


--- trunk/Source/WebCore/workers/service/context/ServiceWorkerThread.cpp	2022-03-30 18:39:39 UTC (rev 292109)
+++ trunk/Source/WebCore/workers/service/context/ServiceWorkerThread.cpp	2022-03-30 18:40:18 UTC (rev 292110)
@@ -36,6 +36,8 @@
 #include "JSDOMPromise.h"
 #include "LoaderStrategy.h"
 #include "Logging.h"
+#include "NotificationData.h"
+#include "NotificationEvent.h"
 #include "PlatformStrategies.h"
 #include "PushEvent.h"
 #include "PushSubscription.h"
@@ -250,8 +252,8 @@
 
 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 {
+    auto& serviceWorkerGlobalScope = downcast<ServiceWorkerGlobalScope>(*globalScope());
+    serviceWorkerGlobalScope.eventLoop().queueTask(TaskSource::DOMManipulation, [weakThis = WeakPtr { *this }, serviceWorkerGlobalScope = Ref { 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;
@@ -275,6 +277,45 @@
     });
 }
 
+#if ENABLE(NOTIFICATION_EVENT)
+void ServiceWorkerThread::queueTaskToFireNotificationEvent(NotificationData&& data, NotificationEventType eventType, Function<void(bool)>&& callback)
+{
+    auto& serviceWorkerGlobalScope = downcast<ServiceWorkerGlobalScope>(*globalScope());
+    serviceWorkerGlobalScope.eventLoop().queueTask(TaskSource::DOMManipulation, [weakThis = WeakPtr { *this }, serviceWorkerGlobalScope = Ref { serviceWorkerGlobalScope }, data = "" eventType, callback = WTFMove(callback)]() mutable {
+        RELEASE_LOG(ServiceWorker, "ServiceWorkerThread::queueTaskToFireNotificationEvent firing event for worker %" PRIu64, serviceWorkerGlobalScope->thread().identifier().toUInt64());
+
+        auto notification = Notification::create(serviceWorkerGlobalScope.get(), WTFMove(data));
+        AtomString eventName;
+        switch (eventType) {
+        case NotificationEventType::Click:
+            eventName = eventNames().notificationclickEvent;
+            notification->markAsShown();
+            serviceWorkerGlobalScope->recordUserGesture();
+            break;
+        case NotificationEventType::Close:
+            eventName = eventNames().notificationcloseEvent;
+            break;
+        }
+
+        auto notificationEvent = NotificationEvent::create(eventName, notification.ptr(), emptyString(), ExtendableEvent::IsTrusted::Yes);
+        serviceWorkerGlobalScope->dispatchEvent(notificationEvent);
+
+        notificationEvent->whenAllExtendLifetimePromisesAreSettled([serviceWorkerGlobalScope, callback = WTFMove(callback)](auto&& extendLifetimePromises) mutable {
+            bool success = true;
+            for (auto& promise : extendLifetimePromises) {
+                if (promise->status() == DOMPromise::Status::Rejected) {
+                    success = false;
+                    break;
+                }
+            }
+
+            RELEASE_LOG_ERROR_IF(!success, ServiceWorker, "ServiceWorkerThread::queueTaskToFireNotificationEvent failed to process notification event");
+            callback(success);
+        });
+    });
+}
+#endif
+
 void ServiceWorkerThread::finishedEvaluatingScript()
 {
     ASSERT(globalScope()->isContextThread());
@@ -311,9 +352,9 @@
     startHeartBeatTimer();
 }
 
-void ServiceWorkerThread::startPushEventMonitoring()
+void ServiceWorkerThread::startFunctionalEventMonitoring()
 {
-    m_isHandlingPushEvent = true;
+    m_isHandlingFunctionalEvent = true;
     startHeartBeatTimer();
 }
 
@@ -339,7 +380,7 @@
 void ServiceWorkerThread::heartBeatTimerFired()
 {
     if (!m_ongoingHeartBeatCheck) {
-        if (m_state == State::Installing || m_state == State::Activating || m_isHandlingFetchEvent || m_isHandlingPushEvent || m_pushSubscriptionChangeEventCount || m_messageEventCount)
+        if (m_state == State::Installing || m_state == State::Activating || m_isHandlingFetchEvent || m_isHandlingFunctionalEvent || m_pushSubscriptionChangeEventCount || m_messageEventCount)
             startHeartBeatTimer();
         return;
     }

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


--- trunk/Source/WebCore/workers/service/context/ServiceWorkerThread.h	2022-03-30 18:39:39 UTC (rev 292109)
+++ trunk/Source/WebCore/workers/service/context/ServiceWorkerThread.h	2022-03-30 18:40:18 UTC (rev 292110)
@@ -28,6 +28,7 @@
 #if ENABLE(SERVICE_WORKER)
 
 #include "NotificationClient.h"
+#include "NotificationEventType.h"
 #include "PushSubscriptionData.h"
 #include "ScriptExecutionContextIdentifier.h"
 #include "ServiceWorkerContextData.h"
@@ -47,6 +48,7 @@
 class SerializedScriptValue;
 class WorkerObjectProxy;
 struct MessageWithMessagePorts;
+struct NotificationData;
 
 class ServiceWorkerThread : public WorkerThread, public CanMakeWeakPtr<ServiceWorkerThread, WeakPtrFactoryInitialization::Eager> {
 public:
@@ -71,6 +73,9 @@
     void queueTaskToFireActivateEvent();
     void queueTaskToFirePushEvent(std::optional<Vector<uint8_t>>&&, Function<void(bool)>&&);
     void queueTaskToFirePushSubscriptionChangeEvent(std::optional<PushSubscriptionData>&& newSubscriptionData, std::optional<PushSubscriptionData>&& oldSubscriptionData);
+#if ENABLE(NOTIFICATION_EVENT)
+    void queueTaskToFireNotificationEvent(NotificationData&&, NotificationEventType, Function<void(bool)>&&);
+#endif
 
     ServiceWorkerIdentifier identifier() const { return m_serviceWorkerIdentifier; }
     std::optional<ServiceWorkerJobDataIdentifier> jobDataIdentifier() const { return m_jobDataIdentifier; }
@@ -78,8 +83,8 @@
 
     void startFetchEventMonitoring();
     void stopFetchEventMonitoring() { m_isHandlingFetchEvent = false; }
-    void startPushEventMonitoring();
-    void stopPushEventMonitoring() { m_isHandlingPushEvent = false; }
+    void startFunctionalEventMonitoring();
+    void stopFunctionalEventMonitoring() { m_isHandlingFunctionalEvent = false; }
 
 protected:
     Ref<WorkerGlobalScope> createWorkerGlobalScope(const WorkerParameters&, Ref<SecurityOrigin>&&, Ref<SecurityOrigin>&& topOrigin) final;
@@ -109,7 +114,7 @@
     bool m_doesHandleFetch { false };
 
     bool m_isHandlingFetchEvent { false };
-    bool m_isHandlingPushEvent { false };
+    bool m_isHandlingFunctionalEvent { false };
     uint64_t m_pushSubscriptionChangeEventCount { 0 };
     uint64_t m_messageEventCount { 0 };
     enum class State { Idle, Starting, Installing, Activating };

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


--- trunk/Source/WebCore/workers/service/context/ServiceWorkerThreadProxy.cpp	2022-03-30 18:39:39 UTC (rev 292109)
+++ trunk/Source/WebCore/workers/service/context/ServiceWorkerThreadProxy.cpp	2022-03-30 18:40:18 UTC (rev 292110)
@@ -92,8 +92,8 @@
     ASSERT(allServiceWorkerThreadProxies().contains(this));
     allServiceWorkerThreadProxies().remove(this);
 
-    auto pushTasks = WTFMove(m_ongoingPushTasks);
-    for (auto& callback : pushTasks.values())
+    auto functionalEventTasks = WTFMove(m_ongoingFunctionalEventTasks);
+    for (auto& callback : functionalEventTasks.values())
         callback(false);
 }
 
@@ -283,24 +283,24 @@
 
 void ServiceWorkerThreadProxy::firePushEvent(std::optional<Vector<uint8_t>>&& data, CompletionHandler<void(bool)>&& callback)
 {
-    if (m_ongoingPushTasks.isEmpty())
-        thread().startPushEventMonitoring();
+    if (m_ongoingFunctionalEventTasks.isEmpty())
+        thread().startFunctionalEventMonitoring();
 
-    auto identifier = ++m_pushTasksCounter;
-    ASSERT(!m_ongoingPushTasks.contains(identifier));
-    m_ongoingPushTasks.add(identifier, WTFMove(callback));
+    auto identifier = ++m_functionalEventTasksCounter;
+    ASSERT(!m_ongoingFunctionalEventTasks.contains(identifier));
+    m_ongoingFunctionalEventTasks.add(identifier, WTFMove(callback));
     bool isPosted = postTaskForModeToWorkerOrWorkletGlobalScope([this, protectedThis = Ref { *this }, identifier, data = "" mutable {
         thread().queueTaskToFirePushEvent(WTFMove(data), [this, protectedThis = WTFMove(protectedThis), identifier](bool result) mutable {
             callOnMainThread([this, protectedThis = WTFMove(protectedThis), identifier, result]() mutable {
-                if (auto callback = m_ongoingPushTasks.take(identifier))
+                if (auto callback = m_ongoingFunctionalEventTasks.take(identifier))
                     callback(result);
-                if (m_ongoingPushTasks.isEmpty())
-                    thread().stopPushEventMonitoring();
+                if (m_ongoingFunctionalEventTasks.isEmpty())
+                    thread().stopFunctionalEventMonitoring();
             });
         });
     }, WorkerRunLoop::defaultMode());
     if (!isPosted)
-        m_ongoingPushTasks.take(identifier)(false);
+        m_ongoingFunctionalEventTasks.take(identifier)(false);
 }
 
 void ServiceWorkerThreadProxy::firePushSubscriptionChangeEvent(std::optional<PushSubscriptionData>&& newSubscriptionData, std::optional<PushSubscriptionData>&& oldSubscriptionData)
@@ -311,6 +311,34 @@
     });
 }
 
+void ServiceWorkerThreadProxy::fireNotificationEvent(NotificationData&& data, NotificationEventType eventType, CompletionHandler<void(bool)>&& callback)
+{
+#if ENABLE(NOTIFICATION_EVENT)
+    if (m_ongoingFunctionalEventTasks.isEmpty())
+        thread().startFunctionalEventMonitoring();
+
+    auto identifier = ++m_functionalEventTasksCounter;
+    ASSERT(!m_ongoingFunctionalEventTasks.contains(identifier));
+    m_ongoingFunctionalEventTasks.add(identifier, WTFMove(callback));
+    bool isPosted = postTaskForModeToWorkerOrWorkletGlobalScope([this, protectedThis = Ref { *this }, identifier, data = "" eventType](auto&) mutable {
+        thread().queueTaskToFireNotificationEvent(WTFMove(data), eventType, [this, protectedThis = WTFMove(protectedThis), identifier](bool result) mutable {
+            callOnMainThread([this, protectedThis = WTFMove(protectedThis), identifier, result]() mutable {
+                if (auto callback = m_ongoingFunctionalEventTasks.take(identifier))
+                    callback(result);
+                if (m_ongoingFunctionalEventTasks.isEmpty())
+                    thread().stopFunctionalEventMonitoring();
+            });
+        });
+    }, WorkerRunLoop::defaultMode());
+    if (!isPosted)
+        m_ongoingFunctionalEventTasks.take(identifier)(false);
+#else
+    UNUSED_PARAM(data);
+    UNUSED_PARAM(eventType);
+    callback(false);
+#endif
+}
+
 } // namespace WebCore
 
 #endif // ENABLE(SERVICE_WORKER)

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


--- trunk/Source/WebCore/workers/service/context/ServiceWorkerThreadProxy.h	2022-03-30 18:39:39 UTC (rev 292109)
+++ trunk/Source/WebCore/workers/service/context/ServiceWorkerThreadProxy.h	2022-03-30 18:40:18 UTC (rev 292110)
@@ -85,6 +85,7 @@
     void fireActivateEvent();
     void firePushEvent(std::optional<Vector<uint8_t>>&&, CompletionHandler<void(bool)>&&);
     void firePushSubscriptionChangeEvent(std::optional<PushSubscriptionData>&& newSubscriptionData, std::optional<PushSubscriptionData>&& oldSubscriptionData);
+    void fireNotificationEvent(NotificationData&&, NotificationEventType, CompletionHandler<void(bool)>&&);
 
     void didSaveScriptsToDisk(ScriptBuffer&&, HashMap<URL, ScriptBuffer>&& importedScripts);
 
@@ -118,8 +119,8 @@
 
     ServiceWorkerInspectorProxy m_inspectorProxy;
     HashMap<std::pair<SWServerConnectionIdentifier, FetchIdentifier>, Ref<ServiceWorkerFetch::Client>> m_ongoingFetchTasks;
-    uint64_t m_pushTasksCounter { 0 };
-    HashMap<uint64_t, CompletionHandler<void(bool)>> m_ongoingPushTasks;
+    uint64_t m_functionalEventTasksCounter { 0 };
+    HashMap<uint64_t, CompletionHandler<void(bool)>> m_ongoingFunctionalEventTasks;
 };
 
 } // namespace WebKit

Modified: trunk/Source/WebCore/workers/service/server/SWServer.cpp (292109 => 292110)


--- trunk/Source/WebCore/workers/service/server/SWServer.cpp	2022-03-30 18:39:39 UTC (rev 292109)
+++ trunk/Source/WebCore/workers/service/server/SWServer.cpp	2022-03-30 18:40:18 UTC (rev 292110)
@@ -31,6 +31,7 @@
 #include "ExceptionCode.h"
 #include "ExceptionData.h"
 #include "Logging.h"
+#include "NotificationData.h"
 #include "RegistrationStore.h"
 #include "SWOriginStore.h"
 #include "SWServerJobQueue.h"
@@ -1049,7 +1050,7 @@
             if (removeContextConnectionIfPossible(clientRegistrableDomain) == ShouldDelayRemoval::Yes) {
                 auto iterator = m_clientIdentifiersPerOrigin.find(clientOrigin);
                 ASSERT(iterator != m_clientIdentifiersPerOrigin.end());
-                iterator->value.terminateServiceWorkersTimer->startOneShot(m_isProcessTerminationDelayEnabled ? defaultTerminationDelay : defaultPushMessageDuration);
+                iterator->value.terminateServiceWorkersTimer->startOneShot(m_isProcessTerminationDelayEnabled ? defaultTerminationDelay : defaultFunctionalEventDuration);
                 return;
             }
 
@@ -1303,15 +1304,15 @@
 
             auto serviceWorkerIdentifier = worker->identifier();
 
-            worker->incrementPushEventCounter();
+            worker->incrementFunctionalEventCounter();
             auto terminateWorkerTimer = makeUnique<Timer>([worker] {
                 RELEASE_LOG_ERROR(ServiceWorker, "Service worker is taking too much time to process a push event");
-                worker->decrementPushEventCounter();
+                worker->decrementFunctionalEventCounter();
             });
-            terminateWorkerTimer->startOneShot(weakThis && weakThis->m_isProcessTerminationDelayEnabled ? defaultTerminationDelay : defaultPushMessageDuration);
+            terminateWorkerTimer->startOneShot(weakThis && weakThis->m_isProcessTerminationDelayEnabled ? defaultTerminationDelay : defaultFunctionalEventDuration);
             connectionOrStatus.value()->firePushEvent(serviceWorkerIdentifier, data, [callback = WTFMove(callback), terminateWorkerTimer = WTFMove(terminateWorkerTimer), worker = WTFMove(worker)](bool succeeded) mutable {
                 if (terminateWorkerTimer->isActive()) {
-                    worker->decrementPushEventCounter();
+                    worker->decrementFunctionalEventCounter();
                     terminateWorkerTimer->stop();
                 }
 
@@ -1321,6 +1322,45 @@
     });
 }
 
+void SWServer::processNotificationEvent(NotificationData&& data, NotificationEventType type)
+{
+    whenImportIsCompletedIfNeeded([this, weakThis = WeakPtr { *this }, data = "" type]() mutable {
+        if (!weakThis)
+            return;
+
+        auto origin = SecurityOriginData::fromURL(data.serviceWorkerRegistrationURL);
+        ServiceWorkerRegistrationKey registrationKey { WTFMove(origin), URL { data.serviceWorkerRegistrationURL } };
+        auto registration = m_scopeToRegistrationMap.get(registrationKey);
+        if (!registration)
+            return;
+
+        auto* worker = registration->activeWorker();
+        if (!worker)
+            return;
+
+        fireFunctionalEvent(*registration, [worker = Ref { *worker }, weakThis = WTFMove(weakThis), data = "" type](auto&& connectionOrStatus) mutable {
+            if (!connectionOrStatus.has_value())
+                return;
+
+            auto serviceWorkerIdentifier = worker->identifier();
+
+            worker->incrementFunctionalEventCounter();
+            auto terminateWorkerTimer = makeUnique<Timer>([worker] {
+                RELEASE_LOG_ERROR(ServiceWorker, "Service worker is taking too much time to process a notification event");
+                worker->decrementFunctionalEventCounter();
+            });
+            terminateWorkerTimer->startOneShot(weakThis && weakThis->m_isProcessTerminationDelayEnabled ? defaultTerminationDelay : defaultFunctionalEventDuration);
+            connectionOrStatus.value()->fireNotificationEvent(serviceWorkerIdentifier, data, type, [terminateWorkerTimer = WTFMove(terminateWorkerTimer), worker = WTFMove(worker)](bool /* succeeded */) mutable {
+                // FIXME: if succeeded is false, should we implement a default action like opening a new page?
+                if (terminateWorkerTimer->isActive()) {
+                    worker->decrementFunctionalEventCounter();
+                    terminateWorkerTimer->stop();
+                }
+            });
+        });
+    });
+}
+
 // https://w3c.github.io/ServiceWorker/#fire-functional-event-algorithm, just for push right now.
 void SWServer::fireFunctionalEvent(SWServerRegistration& registration, CompletionHandler<void(Expected<SWServerToContextConnection*, ShouldSkipEvent>)>&& callback)
 {

Modified: trunk/Source/WebCore/workers/service/server/SWServer.h (292109 => 292110)


--- trunk/Source/WebCore/workers/service/server/SWServer.h	2022-03-30 18:39:39 UTC (rev 292109)
+++ trunk/Source/WebCore/workers/service/server/SWServer.h	2022-03-30 18:40:18 UTC (rev 292110)
@@ -58,10 +58,12 @@
 class SWServerRegistration;
 class SWServerToContextConnection;
 class Timer;
+enum class NotificationEventType : bool;
 enum class ServiceWorkerRegistrationState : uint8_t;
 enum class ServiceWorkerState : uint8_t;
 struct ExceptionData;
 struct MessageWithMessagePorts;
+struct NotificationData;
 struct ServiceWorkerClientQueryOptions;
 struct ServiceWorkerContextData;
 struct ServiceWorkerRegistrationData;
@@ -219,12 +221,13 @@
     WEBCORE_EXPORT void handleLowMemoryWarning();
 
     static constexpr Seconds defaultTerminationDelay = 10_s;
-    static constexpr Seconds defaultPushMessageDuration = 2_s;
+    static constexpr Seconds defaultFunctionalEventDuration = 2_s;
 
     LastNavigationWasAppInitiated clientIsAppInitiatedForRegistrableDomain(const RegistrableDomain&);
     bool shouldRunServiceWorkersOnMainThreadForTesting() const { return m_shouldRunServiceWorkersOnMainThreadForTesting; }
 
     WEBCORE_EXPORT void processPushMessage(std::optional<Vector<uint8_t>>&&, URL&&, CompletionHandler<void(bool)>&&);
+    WEBCORE_EXPORT void processNotificationEvent(NotificationData&&, NotificationEventType);
 
     enum class ShouldSkipEvent : bool { No, Yes };
     void fireFunctionalEvent(SWServerRegistration&, CompletionHandler<void(Expected<SWServerToContextConnection*, ShouldSkipEvent>)>&&);

Modified: trunk/Source/WebCore/workers/service/server/SWServerToContextConnection.h (292109 => 292110)


--- trunk/Source/WebCore/workers/service/server/SWServerToContextConnection.h	2022-03-30 18:39:39 UTC (rev 292109)
+++ trunk/Source/WebCore/workers/service/server/SWServerToContextConnection.h	2022-03-30 18:40:18 UTC (rev 292110)
@@ -28,6 +28,7 @@
 #if ENABLE(SERVICE_WORKER)
 
 #include "ExceptionData.h"
+#include "NotificationEventType.h"
 #include "PageIdentifier.h"
 #include "RegistrableDomain.h"
 #include "ScriptExecutionContextIdentifier.h"
@@ -39,6 +40,7 @@
 
 namespace WebCore {
 
+struct NotificationData;
 class SWServer;
 struct ServiceWorkerClientData;
 struct ServiceWorkerContextData;
@@ -65,7 +67,8 @@
     virtual void terminateWorker(ServiceWorkerIdentifier) = 0;
     virtual void didSaveScriptsToDisk(ServiceWorkerIdentifier, const ScriptBuffer&, const HashMap<URL, ScriptBuffer>& importedScripts) = 0;
     virtual void matchAllCompleted(uint64_t requestIdentifier, const Vector<ServiceWorkerClientData>&) = 0;
-    virtual void firePushEvent(ServiceWorkerIdentifier, const std::optional<Vector<uint8_t>>&, CompletionHandler<void(bool)>&& callback) = 0;
+    virtual void firePushEvent(ServiceWorkerIdentifier, const std::optional<Vector<uint8_t>>&, CompletionHandler<void(bool)>&&) = 0;
+    virtual void fireNotificationEvent(ServiceWorkerIdentifier, const NotificationData&, NotificationEventType, CompletionHandler<void(bool)>&&) = 0;
     virtual ProcessIdentifier webProcessIdentifier() const = 0;
 
     // Messages back from the SW host process

Modified: trunk/Source/WebCore/workers/service/server/SWServerWorker.cpp (292109 => 292110)


--- trunk/Source/WebCore/workers/service/server/SWServerWorker.cpp	2022-03-30 18:39:39 UTC (rev 292109)
+++ trunk/Source/WebCore/workers/service/server/SWServerWorker.cpp	2022-03-30 18:40:18 UTC (rev 292110)
@@ -397,10 +397,10 @@
     return m_registration->serviceWorkerPageIdentifier();
 }
 
-void SWServerWorker::decrementPushEventCounter()
+void SWServerWorker::decrementFunctionalEventCounter()
 {
-    ASSERT(m_pushEventCounter);
-    --m_pushEventCounter;
+    ASSERT(m_functionalEventCounter);
+    --m_functionalEventCounter;
     terminateIfPossible();
 }
 
@@ -412,7 +412,7 @@
 
 void SWServerWorker::terminateIfPossible()
 {
-    if (m_pushEventCounter || m_isInspected || !m_server || m_server->hasClientsWithOrigin(origin()))
+    if (m_functionalEventCounter || m_isInspected || !m_server || m_server->hasClientsWithOrigin(origin()))
         return;
 
     terminate();

Modified: trunk/Source/WebCore/workers/service/server/SWServerWorker.h (292109 => 292110)


--- trunk/Source/WebCore/workers/service/server/SWServerWorker.h	2022-03-30 18:39:39 UTC (rev 292109)
+++ trunk/Source/WebCore/workers/service/server/SWServerWorker.h	2022-03-30 18:40:18 UTC (rev 292110)
@@ -135,11 +135,11 @@
 
     WorkerThreadMode workerThreadMode() const;
 
-    void incrementPushEventCounter() { ++m_pushEventCounter; }
-    void decrementPushEventCounter();
+    void incrementFunctionalEventCounter() { ++m_functionalEventCounter; }
+    void decrementFunctionalEventCounter();
     void setAsInspected(bool);
 
-    bool shouldContinue() const { return !!m_pushEventCounter || m_isInspected; }
+    bool shouldContinue() const { return !!m_functionalEventCounter || m_isInspected; }
 
 private:
     SWServerWorker(SWServer&, SWServerRegistration&, const URL&, const ScriptBuffer&, const CertificateInfo&, const ContentSecurityPolicyResponseHeaders&, const CrossOriginEmbedderPolicy&, String&& referrerPolicy, WorkerType, ServiceWorkerIdentifier, HashMap<URL, ServiceWorkerContextData::ImportedScript>&&);
@@ -173,7 +173,7 @@
     Vector<CompletionHandler<void()>> m_terminationCallbacks;
     Timer m_terminationTimer;
     LastNavigationWasAppInitiated m_lastNavigationWasAppInitiated;
-    int m_pushEventCounter { 0 };
+    int m_functionalEventCounter { 0 };
     bool m_isInspected { false };
 };
 

Modified: trunk/Source/WebKit/ChangeLog (292109 => 292110)


--- trunk/Source/WebKit/ChangeLog	2022-03-30 18:39:39 UTC (rev 292109)
+++ trunk/Source/WebKit/ChangeLog	2022-03-30 18:40:18 UTC (rev 292110)
@@ -1,3 +1,51 @@
+2022-03-30  Youenn Fablet  <[email protected]>
+
+        Implement persistent notification handling
+        https://bugs.webkit.org/show_bug.cgi?id=238498
+
+        Reviewed by Brady Eidson.
+
+        When receiving an update for a notification, check if the notification is tied to a service worker registration.
+        If so, go to network process to fire a functional event, as per https://notifications.spec.whatwg.org/#activating-a-notification
+        and https://notifications.spec.whatwg.org/#ref-for-fire-a-service-worker-notification-eventâ‘ 
+        UIProcess sends the corresponding NotficationData to NetworkProcess.
+        NetworkProcess gets the service worker registration, runs the service worker as needed and fires the functional event.
+        Add IPC plumbing code to support this flow.
+
+        * NetworkProcess/NetworkProcess.cpp:
+        (WebKit::NetworkProcess::processNotificationEvent):
+        (WebKit::NetworkProcess::processPushMessage):
+        * NetworkProcess/NetworkProcess.h:
+        * NetworkProcess/NetworkProcess.messages.in:
+        * NetworkProcess/ServiceWorker/WebSWServerToContextConnection.cpp:
+        (WebKit::WebSWServerToContextConnection::firePushEvent):
+        (WebKit::WebSWServerToContextConnection::fireNotificationEvent):
+        * NetworkProcess/ServiceWorker/WebSWServerToContextConnection.h:
+        * UIProcess/Network/NetworkProcessProxy.cpp:
+        (WebKit::NetworkProcessProxy::processNotificationEvent):
+        * UIProcess/Network/NetworkProcessProxy.h:
+        * UIProcess/Notifications/WebNotification.cpp:
+        (WebKit::WebNotification::WebNotification):
+        * UIProcess/Notifications/WebNotification.h:
+        (WebKit::WebNotification::title const):
+        (WebKit::WebNotification::body const):
+        (WebKit::WebNotification::iconURL const):
+        (WebKit::WebNotification::tag const):
+        (WebKit::WebNotification::lang const):
+        (WebKit::WebNotification::dir const):
+        (WebKit::WebNotification::coreNotificationID const):
+        (WebKit::WebNotification::sessionID const):
+        (WebKit::WebNotification::data const):
+        (WebKit::WebNotification::isPersistentNotification const):
+        (WebKit::WebNotification::notificationID const):
+        * UIProcess/Notifications/WebNotificationManagerProxy.cpp:
+        (WebKit::dispatchDidClickNotification):
+        (WebKit::WebNotificationManagerProxy::providerDidCloseNotifications):
+        * WebProcess/Storage/WebSWContextManagerConnection.cpp:
+        (WebKit::WebSWContextManagerConnection::fireNotificationEvent):
+        * WebProcess/Storage/WebSWContextManagerConnection.h:
+        * WebProcess/Storage/WebSWContextManagerConnection.messages.in:
+
 2022-03-30  Chris Dumez  <[email protected]>
 
         Add HashTranslator for ASCIILiteral for faster lookup in HashMaps / HashSets

Modified: trunk/Source/WebKit/NetworkProcess/NetworkProcess.cpp (292109 => 292110)


--- trunk/Source/WebKit/NetworkProcess/NetworkProcess.cpp	2022-03-30 18:39:39 UTC (rev 292109)
+++ trunk/Source/WebKit/NetworkProcess/NetworkProcess.cpp	2022-03-30 18:40:18 UTC (rev 292110)
@@ -76,6 +76,7 @@
 #include <WebCore/MIMETypeRegistry.h>
 #include <WebCore/NetworkStateNotifier.h>
 #include <WebCore/NetworkStorageSession.h>
+#include <WebCore/NotificationData.h>
 #include <WebCore/ResourceRequest.h>
 #include <WebCore/RuntimeApplicationChecks.h>
 #include <WebCore/RuntimeEnabledFeatures.h>
@@ -2290,6 +2291,12 @@
 }
 
 #if ENABLE(SERVICE_WORKER)
+void NetworkProcess::processNotificationEvent(NotificationData&& data, NotificationEventType eventType)
+{
+    if (auto* session = networkSession(data.sourceSession))
+        session->ensureSWServer().processNotificationEvent(WTFMove(data), eventType);
+}
+
 #if ENABLE(BUILT_IN_NOTIFICATIONS)
 
 void NetworkProcess::getPendingPushMessages(PAL::SessionID sessionID, CompletionHandler<void(const Vector<WebPushMessage>&)>&& callback)

Modified: trunk/Source/WebKit/NetworkProcess/NetworkProcess.h (292109 => 292110)


--- trunk/Source/WebKit/NetworkProcess/NetworkProcess.h	2022-03-30 18:39:39 UTC (rev 292109)
+++ trunk/Source/WebKit/NetworkProcess/NetworkProcess.h	2022-03-30 18:40:18 UTC (rev 292110)
@@ -46,6 +46,7 @@
 #include <WebCore/DiagnosticLoggingClient.h>
 #include <WebCore/FetchIdentifier.h>
 #include <WebCore/MessagePortChannelRegistry.h>
+#include <WebCore/NotificationEventType.h>
 #include <WebCore/PageIdentifier.h>
 #include <WebCore/PrivateClickMeasurement.h>
 #include <WebCore/RegistrableDomain.h>
@@ -84,6 +85,7 @@
 class CurlProxySettings;
 class ProtectionSpace;
 class NetworkStorageSession;
+struct NotificationData;
 class ResourceError;
 class UserContentURLPattern;
 enum class HTTPCookieAcceptPolicy : uint8_t;
@@ -374,6 +376,7 @@
 #if ENABLE(SERVICE_WORKER)
     void getPendingPushMessages(PAL::SessionID, CompletionHandler<void(const Vector<WebPushMessage>&)>&&);
     void processPushMessage(PAL::SessionID, WebPushMessage&&, CompletionHandler<void(bool)>&&);
+    void processNotificationEvent(WebCore::NotificationData&&, WebCore::NotificationEventType);
 #endif
 
     void deletePushAndNotificationRegistration(PAL::SessionID, const WebCore::SecurityOriginData&, CompletionHandler<void(const String&)>&&);

Modified: trunk/Source/WebKit/NetworkProcess/NetworkProcess.messages.in (292109 => 292110)


--- trunk/Source/WebKit/NetworkProcess/NetworkProcess.messages.in	2022-03-30 18:39:39 UTC (rev 292109)
+++ trunk/Source/WebKit/NetworkProcess/NetworkProcess.messages.in	2022-03-30 18:40:18 UTC (rev 292110)
@@ -213,6 +213,7 @@
 #if ENABLE(SERVICE_WORKER)
     GetPendingPushMessages(PAL::SessionID sessionID) -> (Vector<WebKit::WebPushMessage> messages)
     ProcessPushMessage(PAL::SessionID sessionID, struct WebKit::WebPushMessage pushMessage) -> (bool didSucceed)
+    ProcessNotificationEvent(struct WebCore::NotificationData data, enum:bool WebCore::NotificationEventType eventType)
 #endif
     DeletePushAndNotificationRegistration(PAL::SessionID sessionID, struct WebCore::SecurityOriginData origin) -> (String errorMessage)
     GetOriginsWithPushAndNotificationPermissions(PAL::SessionID sessionID) -> (Vector<WebCore::SecurityOriginData> origins)

Modified: trunk/Source/WebKit/NetworkProcess/ServiceWorker/WebSWServerToContextConnection.cpp (292109 => 292110)


--- trunk/Source/WebKit/NetworkProcess/ServiceWorker/WebSWServerToContextConnection.cpp	2022-03-30 18:39:39 UTC (rev 292109)
+++ trunk/Source/WebKit/NetworkProcess/ServiceWorker/WebSWServerToContextConnection.cpp	2022-03-30 18:40:18 UTC (rev 292110)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2017 Apple Inc. All rights reserved.
+ * Copyright (C) 2017-2022 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -39,6 +39,7 @@
 #include "WebCoreArgumentCoders.h"
 #include "WebSWContextManagerConnectionMessages.h"
 #include "WebSWServerConnection.h"
+#include <WebCore/NotificationData.h>
 #include <WebCore/SWServer.h>
 #include <WebCore/ServiceWorkerContextData.h>
 
@@ -114,9 +115,9 @@
     send(Messages::WebSWContextManagerConnection::FireActivateEvent(serviceWorkerIdentifier));
 }
 
-void WebSWServerToContextConnection::firePushEvent(WebCore::ServiceWorkerIdentifier serviceWorkerIdentifier, const std::optional<Vector<uint8_t>>& data, CompletionHandler<void(bool)>&& callback)
+void WebSWServerToContextConnection::firePushEvent(ServiceWorkerIdentifier serviceWorkerIdentifier, const std::optional<Vector<uint8_t>>& data, CompletionHandler<void(bool)>&& callback)
 {
-    if (!m_processingPushEventsCount++)
+    if (!m_processingFunctionalEventCount++)
         m_connection.networkProcess().parentProcessConnection()->send(Messages::NetworkProcessProxy::StartServiceWorkerBackgroundProcessing { webProcessIdentifier() }, 0);
 
     std::optional<IPC::DataReference> ipcData;
@@ -123,12 +124,24 @@
     if (data)
         ipcData = IPC::DataReference { data->data(), data->size() };
     sendWithAsyncReply(Messages::WebSWContextManagerConnection::FirePushEvent(serviceWorkerIdentifier, ipcData), [weakThis = WeakPtr { *this }, callback = WTFMove(callback)](bool wasProcessed) mutable {
-        if (weakThis && !--weakThis->m_processingPushEventsCount)
+        if (weakThis && !--weakThis->m_processingFunctionalEventCount)
             weakThis->m_connection.networkProcess().parentProcessConnection()->send(Messages::NetworkProcessProxy::EndServiceWorkerBackgroundProcessing { weakThis->webProcessIdentifier() }, 0);
         callback(wasProcessed);
     });
 }
 
+void WebSWServerToContextConnection::fireNotificationEvent(ServiceWorkerIdentifier serviceWorkerIdentifier, const NotificationData& data, NotificationEventType eventType, CompletionHandler<void(bool)>&& callback)
+{
+    if (!m_processingFunctionalEventCount++)
+        m_connection.networkProcess().parentProcessConnection()->send(Messages::NetworkProcessProxy::StartServiceWorkerBackgroundProcessing { webProcessIdentifier() }, 0);
+
+    sendWithAsyncReply(Messages::WebSWContextManagerConnection::FireNotificationEvent { serviceWorkerIdentifier, data, eventType }, [weakThis = WeakPtr { *this }, callback = WTFMove(callback)](bool wasProcessed) mutable {
+        if (weakThis && !--weakThis->m_processingFunctionalEventCount)
+            weakThis->m_connection.networkProcess().parentProcessConnection()->send(Messages::NetworkProcessProxy::EndServiceWorkerBackgroundProcessing { weakThis->webProcessIdentifier() }, 0);
+        callback(wasProcessed);
+    });
+}
+
 void WebSWServerToContextConnection::terminateWorker(ServiceWorkerIdentifier serviceWorkerIdentifier)
 {
     send(Messages::WebSWContextManagerConnection::TerminateWorker(serviceWorkerIdentifier));

Modified: trunk/Source/WebKit/NetworkProcess/ServiceWorker/WebSWServerToContextConnection.h (292109 => 292110)


--- trunk/Source/WebKit/NetworkProcess/ServiceWorker/WebSWServerToContextConnection.h	2022-03-30 18:39:39 UTC (rev 292109)
+++ trunk/Source/WebKit/NetworkProcess/ServiceWorker/WebSWServerToContextConnection.h	2022-03-30 18:40:18 UTC (rev 292110)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2017 Apple Inc. All rights reserved.
+ * Copyright (C) 2017-2022 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -97,6 +97,7 @@
     void didSaveScriptsToDisk(WebCore::ServiceWorkerIdentifier, const WebCore::ScriptBuffer&, const HashMap<URL, WebCore::ScriptBuffer>& importedScripts) final;
     void matchAllCompleted(uint64_t requestIdentifier, const Vector<WebCore::ServiceWorkerClientData>&) final;
     void firePushEvent(WebCore::ServiceWorkerIdentifier, const std::optional<Vector<uint8_t>>&, CompletionHandler<void(bool)>&&) final;
+    void fireNotificationEvent(WebCore::ServiceWorkerIdentifier, const WebCore::NotificationData&, WebCore::NotificationEventType, CompletionHandler<void(bool)>&&) final;
     void close() final;
     void focus(WebCore::ScriptExecutionContextIdentifier, CompletionHandler<void(std::optional<WebCore::ServiceWorkerClientData>&&)>&&);
 
@@ -111,7 +112,7 @@
     HashMap<WebCore::FetchIdentifier, WeakPtr<ServiceWorkerDownloadTask>> m_ongoingDownloads;
     bool m_isThrottleable { true };
     WebPageProxyIdentifier m_webPageProxyID;
-    size_t m_processingPushEventsCount { 0 };
+    size_t m_processingFunctionalEventCount { 0 };
 }; // class WebSWServerToContextConnection
 
 } // namespace WebKit

Modified: trunk/Source/WebKit/UIProcess/Network/NetworkProcessProxy.cpp (292109 => 292110)


--- trunk/Source/WebKit/UIProcess/Network/NetworkProcessProxy.cpp	2022-03-30 18:39:39 UTC (rev 292109)
+++ trunk/Source/WebKit/UIProcess/Network/NetworkProcessProxy.cpp	2022-03-30 18:40:18 UTC (rev 292110)
@@ -1763,6 +1763,11 @@
 {
     sendWithAsyncReply(Messages::NetworkProcess::ProcessPushMessage { sessionID, pushMessage }, WTFMove(callback));
 }
+
+void NetworkProcessProxy::processNotificationEvent(const NotificationData& data, NotificationEventType eventType)
+{
+    send(Messages::NetworkProcess::ProcessNotificationEvent { data, eventType }, 0);
+}
 #endif // ENABLE(SERVICE_WORKER)
 
 void NetworkProcessProxy::deletePushAndNotificationRegistration(PAL::SessionID sessionID, const SecurityOriginData& origin, CompletionHandler<void(const String&)>&& callback)

Modified: trunk/Source/WebKit/UIProcess/Network/NetworkProcessProxy.h (292109 => 292110)


--- trunk/Source/WebKit/UIProcess/Network/NetworkProcessProxy.h	2022-03-30 18:39:39 UTC (rev 292109)
+++ trunk/Source/WebKit/UIProcess/Network/NetworkProcessProxy.h	2022-03-30 18:40:18 UTC (rev 292110)
@@ -41,6 +41,7 @@
 #include "WebsiteDataStore.h"
 #include <WebCore/CrossSiteNavigationDataTransfer.h>
 #include <WebCore/FrameIdentifier.h>
+#include <WebCore/NotificationEventType.h>
 #include <WebCore/RegistrableDomain.h>
 #include <memory>
 #include <wtf/Deque.h>
@@ -72,13 +73,14 @@
 class SharedBuffer;
 class ProtectionSpace;
 class ResourceRequest;
+class SecurityOrigin;
 enum class ShouldSample : bool;
 enum class StorageAccessPromptWasShown : bool;
 enum class StorageAccessWasGranted : bool;
 enum class StoredCredentialsPolicy : uint8_t;
-class SecurityOrigin;
+struct ClientOrigin;
+struct NotificationData;
 struct SecurityOriginData;
-struct ClientOrigin;
 }
 
 namespace WebKit {
@@ -284,6 +286,7 @@
 #if ENABLE(SERVICE_WORKER)
     void getPendingPushMessages(PAL::SessionID, CompletionHandler<void(const Vector<WebPushMessage>&)>&&);
     void processPushMessage(PAL::SessionID, const WebPushMessage&, CompletionHandler<void(bool wasProcessed)>&&);
+    void processNotificationEvent(const WebCore::NotificationData&, WebCore::NotificationEventType);
 #endif
 
     void deletePushAndNotificationRegistration(PAL::SessionID, const WebCore::SecurityOriginData&, CompletionHandler<void(const String&)>&&);

Modified: trunk/Source/WebKit/UIProcess/Notifications/WebNotification.cpp (292109 => 292110)


--- trunk/Source/WebKit/UIProcess/Notifications/WebNotification.cpp	2022-03-30 18:39:39 UTC (rev 292109)
+++ trunk/Source/WebKit/UIProcess/Notifications/WebNotification.cpp	2022-03-30 18:40:18 UTC (rev 292110)
@@ -31,14 +31,8 @@
 namespace WebKit {
 
 WebNotification::WebNotification(const WebCore::NotificationData& data, WebPageProxyIdentifier pageIdentifier, IPC::Connection& sourceConnection)
-    : m_title(data.title)
-    , m_body(data.body)
-    , m_iconURL(data.iconURL)
-    , m_tag(data.tag)
-    , m_lang(data.language)
-    , m_dir(data.direction)
+    : m_data(data)
     , m_origin(API::SecurityOrigin::createFromString(data.originString))
-    , m_coreNotificationID(data.notificationID)
     , m_pageIdentifier(pageIdentifier)
     , m_sourceConnection(sourceConnection)
 {

Modified: trunk/Source/WebKit/UIProcess/Notifications/WebNotification.h (292109 => 292110)


--- trunk/Source/WebKit/UIProcess/Notifications/WebNotification.h	2022-03-30 18:39:39 UTC (rev 292109)
+++ trunk/Source/WebKit/UIProcess/Notifications/WebNotification.h	2022-03-30 18:40:18 UTC (rev 292110)
@@ -29,6 +29,7 @@
 #include "APISecurityOrigin.h"
 #include "Connection.h"
 #include "WebPageProxyIdentifier.h"
+#include <WebCore/NotificationData.h>
 #include <wtf/Identified.h>
 #include <wtf/RefPtr.h>
 #include <wtf/text/WTFString.h>
@@ -47,17 +48,22 @@
         return adoptRef(*new WebNotification(data, pageIdentifier, sourceConnection));
     }
 
-    const String& title() const { return m_title; }
-    const String& body() const { return m_body; }
-    const String& iconURL() const { return m_iconURL; }
-    const String& tag() const { return m_tag; }
-    const String& lang() const { return m_lang; }
-    WebCore::NotificationDirection dir() const { return m_dir; }
+    const String& title() const { return m_data.title; }
+    const String& body() const { return m_data.body; }
+    const String& iconURL() const { return m_data.iconURL; }
+    const String& tag() const { return m_data.tag; }
+    const String& lang() const { return m_data.language; }
+    WebCore::NotificationDirection dir() const { return m_data.direction; }
+    const UUID& coreNotificationID() const { return m_data.notificationID; }
+    PAL::SessionID sessionID() const { return m_data.sourceSession; }
+
+    const WebCore::NotificationData& data() const { return m_data; }
+    bool isPersistentNotification() const { return !m_data.serviceWorkerRegistrationURL.isEmpty(); }
+
     const API::SecurityOrigin* origin() const { return m_origin.get(); }
     API::SecurityOrigin* origin() { return m_origin.get(); }
 
     uint64_t notificationID() const { return identifier(); }
-    const UUID& coreNotificationID() const { return m_coreNotificationID; }
 
     WebPageProxyIdentifier pageIdentifier() const { return m_pageIdentifier; }
     IPC::Connection* sourceConnection() const { return m_sourceConnection.get(); }
@@ -65,15 +71,8 @@
 private:
     WebNotification(const WebCore::NotificationData&, WebPageProxyIdentifier, IPC::Connection&);
 
-    String m_title;
-    String m_body;
-    String m_iconURL;
-    String m_tag;
-    String m_lang;
-    WebCore::NotificationDirection m_dir;
+    WebCore::NotificationData m_data;
     RefPtr<API::SecurityOrigin> m_origin;
-    UUID m_coreNotificationID;
-
     WebPageProxyIdentifier m_pageIdentifier;
     WeakPtr<IPC::Connection> m_sourceConnection;
 };

Modified: trunk/Source/WebKit/UIProcess/Notifications/WebNotificationManagerProxy.cpp (292109 => 292110)


--- trunk/Source/WebKit/UIProcess/Notifications/WebNotificationManagerProxy.cpp	2022-03-30 18:39:39 UTC (rev 292109)
+++ trunk/Source/WebKit/UIProcess/Notifications/WebNotificationManagerProxy.cpp	2022-03-30 18:40:18 UTC (rev 292110)
@@ -186,11 +186,16 @@
     if (!notification)
         return;
 
-    auto* connection = notification->sourceConnection();
-    if (!connection)
+#if ENABLE(SERVICE_WORKER)
+    if (notification->isPersistentNotification()) {
+        if (auto* dataStore = WebsiteDataStore::existingDataStoreForSessionID(notification->sessionID()))
+            dataStore->networkProcess().processNotificationEvent(notification->data(), NotificationEventType::Click);
         return;
+    }
+#endif
 
-    connection->send(Messages::WebNotificationManager::DidClickNotification(notification->coreNotificationID()), 0);
+    if (auto* connection = notification->sourceConnection())
+        connection->send(Messages::WebNotificationManager::DidClickNotification(notification->coreNotificationID()), 0);
 }
 
 void WebNotificationManagerProxy::providerDidClickNotification(uint64_t globalNotificationID)
@@ -242,6 +247,14 @@
         if (!notification)
             continue;
 
+#if ENABLE(SERVICE_WORKER)
+        if (notification->isPersistentNotification()) {
+            if (auto* dataStore = WebsiteDataStore::existingDataStoreForSessionID(notification->sessionID()))
+                dataStore->networkProcess().processNotificationEvent(notification->data(), NotificationEventType::Close);
+            return;
+        }
+#endif
+
         m_globalNotificationMap.remove(notification->notificationID());
         closedNotifications.append(WTFMove(notification));
     }

Modified: trunk/Source/WebKit/WebProcess/Notifications/WebNotificationManager.cpp (292109 => 292110)


--- trunk/Source/WebKit/WebProcess/Notifications/WebNotificationManager.cpp	2022-03-30 18:39:39 UTC (rev 292109)
+++ trunk/Source/WebKit/WebProcess/Notifications/WebNotificationManager.cpp	2022-03-30 18:40:18 UTC (rev 292110)
@@ -174,12 +174,17 @@
     ASSERT(isMainRunLoop());
 
 #if ENABLE(NOTIFICATIONS)
-    auto mappedNotification = m_notificationIDMap.get(notification.identifier());
-    if (!mappedNotification)
-        return;
-    ASSERT(mappedNotification == &notification);
+    auto identifier = notification.identifier();
+    auto mappedNotification = m_notificationIDMap.get(identifier);
+    if (!mappedNotification) {
+        auto relatedIdentifier = notification.relatedNotificationIdentifier();
+        if (!relatedIdentifier)
+            return;
+        identifier = *relatedIdentifier;
+    } else
+        ASSERT(mappedNotification == &notification);
 
-    if (!sendNotificationMessage(Messages::NotificationManagerMessageHandler::CancelNotification(notification.identifier()), notification, page))
+    if (!sendNotificationMessage(Messages::NotificationManagerMessageHandler::CancelNotification(identifier), notification, page))
         return;
 #else
     UNUSED_PARAM(notification);
@@ -194,12 +199,17 @@
 #if ENABLE(NOTIFICATIONS)
     Ref protectedNotification { notification };
 
-    auto takenNotification = m_notificationIDMap.take(notification.identifier());
-    if (!takenNotification)
-        return;
-    ASSERT(takenNotification == &notification);
+    auto identifier = notification.identifier();
+    auto takenNotification = m_notificationIDMap.take(identifier);
+    if (!takenNotification) {
+        auto relatedIdentifier = notification.relatedNotificationIdentifier();
+        if (!relatedIdentifier)
+            return;
+        identifier = *relatedIdentifier;
+    } else
+        ASSERT(takenNotification == &notification);
 
-    sendNotificationMessage(Messages::NotificationManagerMessageHandler::DidDestroyNotification(notification.identifier()), notification, page);
+    sendNotificationMessage(Messages::NotificationManagerMessageHandler::DidDestroyNotification(identifier), notification, page);
 #else
     UNUSED_PARAM(notification);
     UNUSED_PARAM(page);

Modified: trunk/Source/WebKit/WebProcess/Storage/WebSWContextManagerConnection.cpp (292109 => 292110)


--- trunk/Source/WebKit/WebProcess/Storage/WebSWContextManagerConnection.cpp	2022-03-30 18:39:39 UTC (rev 292109)
+++ trunk/Source/WebKit/WebProcess/Storage/WebSWContextManagerConnection.cpp	2022-03-30 18:40:18 UTC (rev 292110)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2017 Apple Inc. All rights reserved.
+ * Copyright (C) 2017-2022 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -267,6 +267,11 @@
     SWContextManager::singleton().firePushEvent(identifier, WTFMove(data), WTFMove(callback));
 }
 
+void WebSWContextManagerConnection::fireNotificationEvent(ServiceWorkerIdentifier identifier, NotificationData&& data, NotificationEventType eventType, CompletionHandler<void(bool)>&& callback)
+{
+    SWContextManager::singleton().fireNotificationEvent(identifier, WTFMove(data), eventType, WTFMove(callback));
+}
+
 void WebSWContextManagerConnection::terminateWorker(ServiceWorkerIdentifier identifier)
 {
     SWContextManager::singleton().terminateWorker(identifier, SWContextManager::workerTerminationTimeout, nullptr);

Modified: trunk/Source/WebKit/WebProcess/Storage/WebSWContextManagerConnection.h (292109 => 292110)


--- trunk/Source/WebKit/WebProcess/Storage/WebSWContextManagerConnection.h	2022-03-30 18:39:39 UTC (rev 292109)
+++ trunk/Source/WebKit/WebProcess/Storage/WebSWContextManagerConnection.h	2022-03-30 18:40:18 UTC (rev 292110)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2017 Apple Inc. All rights reserved.
+ * Copyright (C) 2017-2022 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -101,6 +101,7 @@
     void fireInstallEvent(WebCore::ServiceWorkerIdentifier);
     void fireActivateEvent(WebCore::ServiceWorkerIdentifier);
     void firePushEvent(WebCore::ServiceWorkerIdentifier, const std::optional<IPC::DataReference>&, CompletionHandler<void(bool)>&&);
+    void fireNotificationEvent(WebCore::ServiceWorkerIdentifier, WebCore::NotificationData&&, WebCore::NotificationEventType, CompletionHandler<void(bool)>&&);
     void terminateWorker(WebCore::ServiceWorkerIdentifier);
 #if ENABLE(SHAREABLE_RESOURCE) && PLATFORM(COCOA)
     void didSaveScriptsToDisk(WebCore::ServiceWorkerIdentifier, WebCore::ScriptBuffer&&, HashMap<URL, WebCore::ScriptBuffer>&& importedScripts);

Modified: trunk/Source/WebKit/WebProcess/Storage/WebSWContextManagerConnection.messages.in (292109 => 292110)


--- trunk/Source/WebKit/WebProcess/Storage/WebSWContextManagerConnection.messages.in	2022-03-30 18:39:39 UTC (rev 292109)
+++ trunk/Source/WebKit/WebProcess/Storage/WebSWContextManagerConnection.messages.in	2022-03-30 18:40:18 UTC (rev 292110)
@@ -1,4 +1,4 @@
-# Copyright (C) 2017 Apple Inc. All rights reserved.
+# Copyright (C) 2017-2022 Apple Inc. All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
 # modification, are permitted provided that the following conditions
@@ -32,6 +32,7 @@
     FireInstallEvent(WebCore::ServiceWorkerIdentifier identifier)
     FireActivateEvent(WebCore::ServiceWorkerIdentifier identifier)
     FirePushEvent(WebCore::ServiceWorkerIdentifier identifier, std::optional<IPC::DataReference> data) -> (bool result)
+    FireNotificationEvent(WebCore::ServiceWorkerIdentifier identifier, struct WebCore::NotificationData data, enum:bool WebCore::NotificationEventType type) -> (bool result)
 
     TerminateWorker(WebCore::ServiceWorkerIdentifier identifier)
 #if ENABLE(SHAREABLE_RESOURCE) && PLATFORM(COCOA)
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to