Title: [292207] trunk
Revision
292207
Author
you...@apple.com
Date
2022-04-01 01:03:27 -0700 (Fri, 01 Apr 2022)

Log Message

Persistent notifications should work in document scopes as well as service worker global scopes
https://bugs.webkit.org/show_bug.cgi?id=238601

Reviewed by Brady Eidson.

Source/WebCore:

Add a m_serviceWorkerRegistrationURL in Notification to identify whether a notfication is persistent or not.
Set that field when creating a notification from NotificationData or from ServiceWorkerRegistration::showNotification.

Test: http/tests/workers/service/shownotification-allowed-document.html

* Modules/notifications/Notification.cpp:
(WebCore::Notification::create):
(WebCore::Notification::data const):
* Modules/notifications/Notification.h:
* workers/service/ServiceWorkerRegistration.cpp:
(WebCore::ServiceWorkerRegistration::showNotification):

Source/WebKit:

In case of notification message coming from a WebPage, check whether the notification is persistent or not.
If persistent, go to ServiceWorkerNotificationHandler, otherwise use the current code path through WebPageProxy.

* UIProcess/Notifications/ServiceWorkerNotificationHandler.h:
* UIProcess/Notifications/WebNotificationManagerMessageHandler.cpp:
(WebKit::WebNotificationManagerMessageHandler::showNotification):
(WebKit::WebNotificationManagerMessageHandler::cancelNotification):
(WebKit::WebNotificationManagerMessageHandler::clearNotifications):
(WebKit::WebNotificationManagerMessageHandler::didDestroyNotification):

LayoutTests:

* http/tests/workers/service/shownotification-allowed-document-expected.txt: Added.
* http/tests/workers/service/shownotification-allowed-document.html: Added.

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (292206 => 292207)


--- trunk/LayoutTests/ChangeLog	2022-04-01 07:11:30 UTC (rev 292206)
+++ trunk/LayoutTests/ChangeLog	2022-04-01 08:03:27 UTC (rev 292207)
@@ -1,3 +1,13 @@
+2022-04-01  Youenn Fablet  <you...@apple.com>
+
+        Persistent notifications should work in document scopes as well as service worker global scopes
+        https://bugs.webkit.org/show_bug.cgi?id=238601
+
+        Reviewed by Brady Eidson.
+
+        * http/tests/workers/service/shownotification-allowed-document-expected.txt: Added.
+        * http/tests/workers/service/shownotification-allowed-document.html: Added.
+
 2022-03-31  Said Abou-Hallawa  <s...@apple.com>
 
         [GPU Process] [iOS] Vertical text is incorrectly displaced

Added: trunk/LayoutTests/http/tests/workers/service/shownotification-allowed-document-expected.txt (0 => 292207)


--- trunk/LayoutTests/http/tests/workers/service/shownotification-allowed-document-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/http/tests/workers/service/shownotification-allowed-document-expected.txt	2022-04-01 08:03:27 UTC (rev 292207)
@@ -0,0 +1,12 @@
+This tests that a notification shown by a service worker registration in a document can be clicked and closed, with those actions being observable by the service worker
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS Notification.permission is "granted"
+PASS gotClicked is false
+PASS gotClosed is false
+PASS gotClicked is true
+PASS gotClosed is false
+PASS Close has been observed
+

Added: trunk/LayoutTests/http/tests/workers/service/shownotification-allowed-document.html (0 => 292207)


--- trunk/LayoutTests/http/tests/workers/service/shownotification-allowed-document.html	                        (rev 0)
+++ trunk/LayoutTests/http/tests/workers/service/shownotification-allowed-document.html	2022-04-01 08:03:27 UTC (rev 292207)
@@ -0,0 +1,75 @@
+<head>
+<script src=""
+<script src=""
+<script>
+
+function failTheTest(msg)
+{
+    testFailed(msg);
+    if (testRunner)
+        testRunner.notifyDone();
+}
+
+if (window.testRunner) {
+    testRunner.waitUntilDone();
+    testRunner.grantWebNotificationPermission(testURL);
+    setTimeout("failTheTest('timed out')", 15000);
+}
+
+description("This tests that a notification shown by a service worker registration in a document can be clicked and closed, with those actions being observable by the service worker");
+
+shouldBeEqualToString("Notification.permission", "granted");
+
+async function registerServiceWorker() {
+    var registration = await navigator.serviceWorker.register('resources/shownotification-worker.js');
+
+    if (!registration)
+        return testFailed("No registration");
+
+    if (registration.active) {
+        registration.active.postMessage("Start");
+        return;
+    }
+
+    var installingWorker = registration.installing;
+    if (!installingWorker)
+        failTheTest("No active *or* installing worker");
+
+    installingWorker.addEventListener("statechange", async () => {
+        if (installingWorker.state === "activated") {
+            await registration.showNotification("This is a notification", { body: "body", tag: "tag" });
+            if (window.testRunner)
+                testRunner.simulateWebNotificationClickForServiceWorkerNotifications();
+        }
+    });
+}
+
+var gotClicked = false;
+var gotClosed = false;
+
+navigator.serviceWorker.addEventListener('message', async event => {
+    if (event.data == "showFailed") {
+        failTheTest("Unexpectedly received the failed-to-show message");
+    } else if (event.data == "clicked") {
+        shouldBeFalse("gotClicked");
+        shouldBeFalse("gotClosed");
+        gotClicked = true;
+    } else if (event.data == "closed") {
+        shouldBeTrue("gotClicked")
+        shouldBeFalse("gotClosed")
+        gotClosed = true;
+    } else {
+        testFailed("Message received: " + event.data);
+    }
+
+    if (gotClosed) {
+        testPassed("Close has been observed");
+        if (window.testRunner)
+            testRunner.notifyDone();
+    }
+});
+
+</script>
+</head>
+<body _onload_="registerServiceWorker()">
+</body>

Modified: trunk/Source/WebCore/ChangeLog (292206 => 292207)


--- trunk/Source/WebCore/ChangeLog	2022-04-01 07:11:30 UTC (rev 292206)
+++ trunk/Source/WebCore/ChangeLog	2022-04-01 08:03:27 UTC (rev 292207)
@@ -1,3 +1,22 @@
+2022-04-01  Youenn Fablet  <you...@apple.com>
+
+        Persistent notifications should work in document scopes as well as service worker global scopes
+        https://bugs.webkit.org/show_bug.cgi?id=238601
+
+        Reviewed by Brady Eidson.
+
+        Add a m_serviceWorkerRegistrationURL in Notification to identify whether a notfication is persistent or not.
+        Set that field when creating a notification from NotificationData or from ServiceWorkerRegistration::showNotification.
+
+        Test: http/tests/workers/service/shownotification-allowed-document.html
+
+        * Modules/notifications/Notification.cpp:
+        (WebCore::Notification::create):
+        (WebCore::Notification::data const):
+        * Modules/notifications/Notification.h:
+        * workers/service/ServiceWorkerRegistration.cpp:
+        (WebCore::ServiceWorkerRegistration::showNotification):
+
 2022-03-31  Wenson Hsieh  <wenson_hs...@apple.com>
 
         Add a heuristic to identify and extract the prominent video element in element fullscreen

Modified: trunk/Source/WebCore/Modules/notifications/Notification.cpp (292206 => 292207)


--- trunk/Source/WebCore/Modules/notifications/Notification.cpp	2022-04-01 07:11:30 UTC (rev 292206)
+++ trunk/Source/WebCore/Modules/notifications/Notification.cpp	2022-04-01 08:03:27 UTC (rev 292207)
@@ -53,9 +53,10 @@
 
 WTF_MAKE_ISO_ALLOCATED_IMPL(Notification);
 
-Ref<Notification> Notification::create(ScriptExecutionContext& context, String&& title, Options&& options)
+Ref<Notification> Notification::create(ScriptExecutionContext& context, String&& title, Options&& options, const URL& serviceWorkerRegistrationURL)
 {
     auto notification = adoptRef(*new Notification(context, WTFMove(title), WTFMove(options)));
+    notification->m_serviceWorkerRegistrationURL = serviceWorkerRegistrationURL;
     notification->suspendIfNeeded();
     notification->showSoon();
     return notification;
@@ -67,6 +68,7 @@
     auto notification = adoptRef(*new Notification(context, WTFMove(data.title), WTFMove(options)));
     notification->suspendIfNeeded();
     notification->m_relatedNotificationIdentifier = data.notificationID;
+    notification->m_serviceWorkerRegistrationURL = WTFMove(data.serviceWorkerRegistrationURL);
     return notification;
 }
 
@@ -323,11 +325,6 @@
     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(),
@@ -336,7 +333,7 @@
         m_lang,
         m_direction,
         scriptExecutionContext()->securityOrigin()->toString().isolatedCopy(),
-        WTFMove(serviceWorkerRegistrationURL).isolatedCopy(),
+        m_serviceWorkerRegistrationURL.isolatedCopy(),
         identifier(),
         *sessionID,
     };

Modified: trunk/Source/WebCore/Modules/notifications/Notification.h (292206 => 292207)


--- trunk/Source/WebCore/Modules/notifications/Notification.h	2022-04-01 07:11:30 UTC (rev 292206)
+++ trunk/Source/WebCore/Modules/notifications/Notification.h	2022-04-01 08:03:27 UTC (rev 292207)
@@ -64,7 +64,7 @@
         String tag;
         String icon;
     };
-    static Ref<Notification> create(ScriptExecutionContext&, String&& title, Options&&);
+    static Ref<Notification> create(ScriptExecutionContext&, String&& title, Options&&, const URL& serviceWorkerRegistrationURL = { });
     static Ref<Notification> create(ScriptExecutionContext&, NotificationData&&);
 
     WEBCORE_EXPORT virtual ~Notification();
@@ -143,6 +143,7 @@
     NotificationSource m_notificationSource;
     ScriptExecutionContextIdentifier m_contextIdentifier;
     std::optional<UUID> m_relatedNotificationIdentifier;
+    URL m_serviceWorkerRegistrationURL;
 };
 
 } // namespace WebCore

Modified: trunk/Source/WebCore/workers/service/ServiceWorkerRegistration.cpp (292206 => 292207)


--- trunk/Source/WebCore/workers/service/ServiceWorkerRegistration.cpp	2022-04-01 07:11:30 UTC (rev 292206)
+++ trunk/Source/WebCore/workers/service/ServiceWorkerRegistration.cpp	2022-04-01 08:03:27 UTC (rev 292207)
@@ -292,7 +292,7 @@
 
     // The Notification is kept alive by virtue of being show()'n soon.
     // FIXME: When implementing getNotifications(), store this Notification in the registration's notification list.
-    auto notification = Notification::create(context, WTFMove(title), WTFMove(options));
+    auto notification = Notification::create(context, WTFMove(title), WTFMove(options), m_registrationData.scopeURL);
 
     context.eventLoop().queueTask(TaskSource::DOMManipulation, [promise = WTFMove(promise)]() mutable {
         promise.resolve();

Modified: trunk/Source/WebKit/ChangeLog (292206 => 292207)


--- trunk/Source/WebKit/ChangeLog	2022-04-01 07:11:30 UTC (rev 292206)
+++ trunk/Source/WebKit/ChangeLog	2022-04-01 08:03:27 UTC (rev 292207)
@@ -1,3 +1,20 @@
+2022-04-01  Youenn Fablet  <you...@apple.com>
+
+        Persistent notifications should work in document scopes as well as service worker global scopes
+        https://bugs.webkit.org/show_bug.cgi?id=238601
+
+        Reviewed by Brady Eidson.
+
+        In case of notification message coming from a WebPage, check whether the notification is persistent or not.
+        If persistent, go to ServiceWorkerNotificationHandler, otherwise use the current code path through WebPageProxy.
+
+        * UIProcess/Notifications/ServiceWorkerNotificationHandler.h:
+        * UIProcess/Notifications/WebNotificationManagerMessageHandler.cpp:
+        (WebKit::WebNotificationManagerMessageHandler::showNotification):
+        (WebKit::WebNotificationManagerMessageHandler::cancelNotification):
+        (WebKit::WebNotificationManagerMessageHandler::clearNotifications):
+        (WebKit::WebNotificationManagerMessageHandler::didDestroyNotification):
+
 2022-03-31  Wenson Hsieh  <wenson_hs...@apple.com>
 
         Add a heuristic to identify and extract the prominent video element in element fullscreen

Modified: trunk/Source/WebKit/UIProcess/Notifications/ServiceWorkerNotificationHandler.h (292206 => 292207)


--- trunk/Source/WebKit/UIProcess/Notifications/ServiceWorkerNotificationHandler.h	2022-04-01 07:11:30 UTC (rev 292206)
+++ trunk/Source/WebKit/UIProcess/Notifications/ServiceWorkerNotificationHandler.h	2022-04-01 08:03:27 UTC (rev 292207)
@@ -38,15 +38,18 @@
 public:
     static ServiceWorkerNotificationHandler& singleton();
 
-private:
-    explicit ServiceWorkerNotificationHandler() = default;
-
-    void requestSystemNotificationPermission(const String&, CompletionHandler<void(bool)>&&) final;
     void showNotification(IPC::Connection&, const WebCore::NotificationData&) final;
     void cancelNotification(const UUID& notificationID) final;
     void clearNotifications(const Vector<UUID>& notificationIDs) final;
     void didDestroyNotification(const UUID& notificationID) final;
 
+    bool handlesNotification(UUID value) const { return m_notificationToSessionMap.contains(value); }
+
+private:
+    explicit ServiceWorkerNotificationHandler() = default;
+
+    void requestSystemNotificationPermission(const String&, CompletionHandler<void(bool)>&&) final;
+
     WebsiteDataStore* dataStoreForNotificationID(const UUID&);
 
     HashMap<UUID, PAL::SessionID> m_notificationToSessionMap;

Modified: trunk/Source/WebKit/UIProcess/Notifications/WebNotificationManagerMessageHandler.cpp (292206 => 292207)


--- trunk/Source/WebKit/UIProcess/Notifications/WebNotificationManagerMessageHandler.cpp	2022-04-01 07:11:30 UTC (rev 292206)
+++ trunk/Source/WebKit/UIProcess/Notifications/WebNotificationManagerMessageHandler.cpp	2022-04-01 08:03:27 UTC (rev 292207)
@@ -26,6 +26,7 @@
 #include "config.h"
 #include "WebNotificationManagerMessageHandler.h"
 
+#include "ServiceWorkerNotificationHandler.h"
 #include "WebPageProxy.h"
 
 namespace WebKit {
@@ -42,21 +43,50 @@
 
 void WebNotificationManagerMessageHandler::showNotification(IPC::Connection& connection, const WebCore::NotificationData& data)
 {
+    if (!data.serviceWorkerRegistrationURL.isEmpty()) {
+        ServiceWorkerNotificationHandler::singleton().showNotification(connection, data);
+        return;
+    }
     m_webPageProxy.showNotification(connection, data);
 }
 
 void WebNotificationManagerMessageHandler::cancelNotification(const UUID& notificationID)
 {
+    auto& serviceWorkerNotificationHandler = ServiceWorkerNotificationHandler::singleton();
+    if (serviceWorkerNotificationHandler.handlesNotification(notificationID)) {
+        serviceWorkerNotificationHandler.cancelNotification(notificationID);
+        return;
+    }
     m_webPageProxy.cancelNotification(notificationID);
 }
 
 void WebNotificationManagerMessageHandler::clearNotifications(const Vector<UUID>& notificationIDs)
 {
-    m_webPageProxy.clearNotifications(notificationIDs);
+    auto& serviceWorkerNotificationHandler = ServiceWorkerNotificationHandler::singleton();
+
+    Vector<UUID> persistentNotifications;
+    Vector<UUID> pageNotifications;
+    persistentNotifications.reserveInitialCapacity(notificationIDs.size());
+    pageNotifications.reserveInitialCapacity(notificationIDs.size());
+    for (auto& notificationID : notificationIDs) {
+        if (serviceWorkerNotificationHandler.handlesNotification(notificationID))
+            persistentNotifications.uncheckedAppend(notificationID);
+        else
+            pageNotifications.uncheckedAppend(notificationID);
+    }
+    if (!persistentNotifications.isEmpty())
+        serviceWorkerNotificationHandler.clearNotifications(persistentNotifications);
+    if (!pageNotifications.isEmpty())
+        m_webPageProxy.clearNotifications(pageNotifications);
 }
 
 void WebNotificationManagerMessageHandler::didDestroyNotification(const UUID& notificationID)
 {
+    auto& serviceWorkerNotificationHandler = ServiceWorkerNotificationHandler::singleton();
+    if (serviceWorkerNotificationHandler.handlesNotification(notificationID)) {
+        serviceWorkerNotificationHandler.didDestroyNotification(notificationID);
+        return;
+    }
     m_webPageProxy.didDestroyNotification(notificationID);
 }
 
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to