Title: [292158] trunk
Revision
292158
Author
n...@apple.com
Date
2022-03-31 08:08:16 -0700 (Thu, 31 Mar 2022)

Log Message

Remove push subscriptions when permissions are reset
https://bugs.webkit.org/show_bug.cgi?id=238068

Reviewed by Youenn Fablet.

Source/WebKit:

When the notification permission for an origin is reset (i.e. is in the prompt state), we
should delete any push subscriptions associated with that origin. We do this by having the
providerDidRemoveNotificationPolicies API call deletePushAndNotificationRegistration in
webpushd.

We also do this when processing a push message, since it's possible for the state to get out
of sync due to the number of processes involved. For instance, removing the policy from
System Preferences rather than the browser's notification preference pane can result in the
providerDidRemoveNotificationPolicies call in the browser to be delayed or dropped.

Note that we don't delete the subscription if the permission is simply toggled off (i.e. the
permission is in the Denied state). In that case, the user can easily toggle the permission
back on. We want the subscription object to stay the same after the preference is toggled
back on so that the server can still send pushes to that push endpoint. In a future patch
we'll add subscriptions in this state to the ignored topics list in webpushd, which will
prevent pushes for those subscriptions from being delivered to the device without actually
unsubscribing.

* NetworkProcess/NetworkProcess.cpp:
(WebKit::NetworkProcess::processPushMessage):
* NetworkProcess/NetworkProcess.h:
* NetworkProcess/NetworkProcess.messages.in:
* UIProcess/Network/NetworkProcessProxy.cpp:
(WebKit::NetworkProcessProxy::processPushMessage):
* UIProcess/Notifications/WebNotificationManagerProxy.cpp:
(WebKit::removePushSubscriptionsForOrigins):
(WebKit::WebNotificationManagerProxy::providerDidRemoveNotificationPolicies):
* webpushd/WebPushDaemon.mm:
(WebPushD::Daemon::deletePushAndNotificationRegistration):

Tools:

Add a test to make sure push subscriptions are removed when the notification policy for a
website is reset.

Also fixed an issue with a PushAPI test that didn't properly register for notification permissions.

* TestWebKitAPI/TestNotificationProvider.cpp:
(TestWebKitAPI::TestNotificationProvider::TestNotificationProvider):
(TestWebKitAPI::TestNotificationProvider::notificationPermissions const):
(TestWebKitAPI::TestNotificationProvider::setPermission):
(TestWebKitAPI::TestNotificationProvider::resetPermission):
* TestWebKitAPI/TestNotificationProvider.h:
* TestWebKitAPI/Tests/WebKitCocoa/PushAPI.mm:
* TestWebKitAPI/Tests/WebKitCocoa/WebPushDaemon.mm:

LayoutTests:

Fix an issue with a layout test that didn't register for notification permissions.

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

Modified Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (292157 => 292158)


--- trunk/LayoutTests/ChangeLog	2022-03-31 13:56:29 UTC (rev 292157)
+++ trunk/LayoutTests/ChangeLog	2022-03-31 15:08:16 UTC (rev 292158)
@@ -1,3 +1,14 @@
+2022-03-31  Ben Nham  <n...@apple.com>
+
+        Remove push subscriptions when permissions are reset
+        https://bugs.webkit.org/show_bug.cgi?id=238068
+
+        Reviewed by Youenn Fablet.
+
+        Fix an issue with a layout test that didn't register for notification permissions.
+
+        * http/wpt/service-workers/service-worker-spinning-push.https.html:
+
 2022-03-31  Alan Bujtas  <za...@apple.com>
 
         [CSS contain] Containment disables the special handling of the HTML body element for overflow viewport propagation [part2]

Modified: trunk/LayoutTests/http/wpt/service-workers/service-worker-spinning-push.https.html (292157 => 292158)


--- trunk/LayoutTests/http/wpt/service-workers/service-worker-spinning-push.https.html	2022-03-31 13:56:29 UTC (rev 292157)
+++ trunk/LayoutTests/http/wpt/service-workers/service-worker-spinning-push.https.html	2022-03-31 15:08:16 UTC (rev 292158)
@@ -7,6 +7,9 @@
 </head>
 <body>
 <script>
+if (window.testRunner)
+    testRunner.grantWebNotificationPermission(window.origin);
+
 promise_test(async (test) => {
     const registration = await navigator.serviceWorker.register("service-worker-spinning-worker.js", { scope : "spin-push" });
     const worker = registration.installing;

Modified: trunk/Source/WebKit/ChangeLog (292157 => 292158)


--- trunk/Source/WebKit/ChangeLog	2022-03-31 13:56:29 UTC (rev 292157)
+++ trunk/Source/WebKit/ChangeLog	2022-03-31 15:08:16 UTC (rev 292158)
@@ -1,3 +1,40 @@
+2022-03-31  Ben Nham  <n...@apple.com>
+
+        Remove push subscriptions when permissions are reset
+        https://bugs.webkit.org/show_bug.cgi?id=238068
+
+        Reviewed by Youenn Fablet.
+
+        When the notification permission for an origin is reset (i.e. is in the prompt state), we
+        should delete any push subscriptions associated with that origin. We do this by having the
+        providerDidRemoveNotificationPolicies API call deletePushAndNotificationRegistration in
+        webpushd.
+
+        We also do this when processing a push message, since it's possible for the state to get out
+        of sync due to the number of processes involved. For instance, removing the policy from
+        System Preferences rather than the browser's notification preference pane can result in the
+        providerDidRemoveNotificationPolicies call in the browser to be delayed or dropped.
+
+        Note that we don't delete the subscription if the permission is simply toggled off (i.e. the
+        permission is in the Denied state). In that case, the user can easily toggle the permission
+        back on. We want the subscription object to stay the same after the preference is toggled
+        back on so that the server can still send pushes to that push endpoint. In a future patch
+        we'll add subscriptions in this state to the ignored topics list in webpushd, which will
+        prevent pushes for those subscriptions from being delivered to the device without actually
+        unsubscribing.
+
+        * NetworkProcess/NetworkProcess.cpp:
+        (WebKit::NetworkProcess::processPushMessage):
+        * NetworkProcess/NetworkProcess.h:
+        * NetworkProcess/NetworkProcess.messages.in:
+        * UIProcess/Network/NetworkProcessProxy.cpp:
+        (WebKit::NetworkProcessProxy::processPushMessage):
+        * UIProcess/Notifications/WebNotificationManagerProxy.cpp:
+        (WebKit::removePushSubscriptionsForOrigins):
+        (WebKit::WebNotificationManagerProxy::providerDidRemoveNotificationPolicies):
+        * webpushd/WebPushDaemon.mm:
+        (WebPushD::Daemon::deletePushAndNotificationRegistration):
+
 2022-03-31  Alex Christensen  <achristen...@webkit.org>
 
         Remove EXPERIMENTAL_FEATURES flag on Cocoa platforms

Modified: trunk/Source/WebKit/NetworkProcess/NetworkProcess.cpp (292157 => 292158)


--- trunk/Source/WebKit/NetworkProcess/NetworkProcess.cpp	2022-03-31 13:56:29 UTC (rev 292157)
+++ trunk/Source/WebKit/NetworkProcess/NetworkProcess.cpp	2022-03-31 15:08:16 UTC (rev 292158)
@@ -2309,11 +2309,29 @@
         LOG(Notifications, "NetworkProcess could not find session for ID %llu to get pending push messages", sessionID.toUInt64());
 }
 
-void NetworkProcess::processPushMessage(PAL::SessionID sessionID, WebPushMessage&& pushMessage, CompletionHandler<void(bool)>&& callback)
+void NetworkProcess::processPushMessage(PAL::SessionID sessionID, WebPushMessage&& pushMessage, PushPermissionState permissionState, CompletionHandler<void(bool)>&& callback)
 {
     if (auto* session = networkSession(sessionID)) {
         LOG(Push, "Networking process handling a push message from UI process in session %llu", sessionID.toUInt64());
         auto origin = SecurityOriginData::fromURL(pushMessage.registrationURL);
+
+        if (permissionState == PushPermissionState::Prompt) {
+            RELEASE_LOG(Push, "Push message from %" PRIVATE_LOG_STRING " won't be processed since permission is in the prompt state; removing push subscription", origin.toString().utf8().data());
+            session->notificationManager().removePushSubscriptionsForOrigin(SecurityOriginData { origin }, [callback = WTFMove(callback)](auto&&) mutable {
+                callback(false);
+                return;
+            });
+            return;
+        }
+
+        if (permissionState == PushPermissionState::Denied) {
+            RELEASE_LOG(Push, "Push message from %" PRIVATE_LOG_STRING " won't be processed since permission is in the denied state", origin.toString().utf8().data());
+            // FIXME: move topic to ignore list in webpushd if permission is denied.
+            callback(false);
+            return;
+        }
+
+        ASSERT(permissionState == PushPermissionState::Granted);
         session->ensureSWServer().processPushMessage(WTFMove(pushMessage.pushData), WTFMove(pushMessage.registrationURL), [this, protectedThis = Ref { *this }, sessionID, origin = WTFMove(origin), callback = WTFMove(callback)](bool result) mutable {
             NetworkSession* session;
             if (!result && (session = networkSession(sessionID))) {
@@ -2336,7 +2354,7 @@
     callback({ });
 }
 
-void NetworkProcess::processPushMessage(PAL::SessionID, WebPushMessage&&, CompletionHandler<void(bool)>&& callback)
+void NetworkProcess::processPushMessage(PAL::SessionID, WebPushMessage&&, PushPermissionState, CompletionHandler<void(bool)>&& callback)
 {
     callback(false);
 }

Modified: trunk/Source/WebKit/NetworkProcess/NetworkProcess.h (292157 => 292158)


--- trunk/Source/WebKit/NetworkProcess/NetworkProcess.h	2022-03-31 13:56:29 UTC (rev 292157)
+++ trunk/Source/WebKit/NetworkProcess/NetworkProcess.h	2022-03-31 15:08:16 UTC (rev 292158)
@@ -49,6 +49,7 @@
 #include <WebCore/NotificationEventType.h>
 #include <WebCore/PageIdentifier.h>
 #include <WebCore/PrivateClickMeasurement.h>
+#include <WebCore/PushPermissionState.h>
 #include <WebCore/RegistrableDomain.h>
 #include <WebCore/ServiceWorkerIdentifier.h>
 #include <WebCore/ServiceWorkerTypes.h>
@@ -375,7 +376,7 @@
 
 #if ENABLE(SERVICE_WORKER)
     void getPendingPushMessages(PAL::SessionID, CompletionHandler<void(const Vector<WebPushMessage>&)>&&);
-    void processPushMessage(PAL::SessionID, WebPushMessage&&, CompletionHandler<void(bool)>&&);
+    void processPushMessage(PAL::SessionID, WebPushMessage&&, WebCore::PushPermissionState, CompletionHandler<void(bool)>&&);
     void processNotificationEvent(WebCore::NotificationData&&, WebCore::NotificationEventType);
 #endif
 

Modified: trunk/Source/WebKit/NetworkProcess/NetworkProcess.messages.in (292157 => 292158)


--- trunk/Source/WebKit/NetworkProcess/NetworkProcess.messages.in	2022-03-31 13:56:29 UTC (rev 292157)
+++ trunk/Source/WebKit/NetworkProcess/NetworkProcess.messages.in	2022-03-31 15:08:16 UTC (rev 292158)
@@ -212,7 +212,7 @@
 
 #if ENABLE(SERVICE_WORKER)
     GetPendingPushMessages(PAL::SessionID sessionID) -> (Vector<WebKit::WebPushMessage> messages)
-    ProcessPushMessage(PAL::SessionID sessionID, struct WebKit::WebPushMessage pushMessage) -> (bool didSucceed)
+    ProcessPushMessage(PAL::SessionID sessionID, struct WebKit::WebPushMessage pushMessage, enum:uint8_t WebCore::PushPermissionState pushPermissionState) -> (bool didSucceed)
     ProcessNotificationEvent(struct WebCore::NotificationData data, enum:bool WebCore::NotificationEventType eventType)
 #endif
     DeletePushAndNotificationRegistration(PAL::SessionID sessionID, struct WebCore::SecurityOriginData origin) -> (String errorMessage)

Modified: trunk/Source/WebKit/UIProcess/Network/NetworkProcessProxy.cpp (292157 => 292158)


--- trunk/Source/WebKit/UIProcess/Network/NetworkProcessProxy.cpp	2022-03-31 13:56:29 UTC (rev 292157)
+++ trunk/Source/WebKit/UIProcess/Network/NetworkProcessProxy.cpp	2022-03-31 15:08:16 UTC (rev 292158)
@@ -50,6 +50,7 @@
 #include "StorageAccessStatus.h"
 #include "WebCompiledContentRuleList.h"
 #include "WebCookieManagerProxy.h"
+#include "WebNotificationManagerProxy.h"
 #include "WebPageMessages.h"
 #include "WebPageProxy.h"
 #include "WebProcessMessages.h"
@@ -62,6 +63,7 @@
 #include "WebsiteDataStoreClient.h"
 #include "WebsiteDataStoreParameters.h"
 #include <WebCore/ClientOrigin.h>
+#include <WebCore/PushPermissionState.h>
 #include <WebCore/RegistrableDomain.h>
 #include <WebCore/ResourceError.h>
 #include <wtf/CallbackAggregator.h>
@@ -1761,7 +1763,19 @@
 
 void NetworkProcessProxy::processPushMessage(PAL::SessionID sessionID, const WebPushMessage& pushMessage, CompletionHandler<void(bool wasProcessed)>&& callback)
 {
-    sendWithAsyncReply(Messages::NetworkProcess::ProcessPushMessage { sessionID, pushMessage }, WTFMove(callback));
+    auto permission = PushPermissionState::Prompt;
+    auto permissions = WebNotificationManagerProxy::sharedServiceWorkerManager().notificationPermissions();
+    auto origin = SecurityOriginData::fromURL(pushMessage.registrationURL).toString();
+
+    if (auto it = permissions.find(origin); it != permissions.end())
+        permission = it->value ? PushPermissionState::Granted : PushPermissionState::Denied;
+
+    if (permission == PushPermissionState::Denied) {
+        callback(false);
+        return;
+    }
+
+    sendWithAsyncReply(Messages::NetworkProcess::ProcessPushMessage { sessionID, pushMessage, permission }, WTFMove(callback));
 }
 
 void NetworkProcessProxy::processNotificationEvent(const NotificationData& data, NotificationEventType eventType)

Modified: trunk/Source/WebKit/UIProcess/Notifications/WebNotificationManagerProxy.cpp (292157 => 292158)


--- trunk/Source/WebKit/UIProcess/Notifications/WebNotificationManagerProxy.cpp	2022-03-31 13:56:29 UTC (rev 292157)
+++ trunk/Source/WebKit/UIProcess/Notifications/WebNotificationManagerProxy.cpp	2022-03-31 15:08:16 UTC (rev 292158)
@@ -34,7 +34,9 @@
 #include "WebPageProxy.h"
 #include "WebProcessPool.h"
 #include "WebProcessProxy.h"
+#include "WebsiteDataStore.h"
 #include <WebCore/NotificationData.h>
+#include <WebCore/SecurityOriginData.h>
 
 namespace WebKit {
 using namespace WebCore;
@@ -280,25 +282,69 @@
     processPool()->sendToAllProcesses(Messages::WebNotificationManager::DidUpdateNotificationDecision(origin->securityOrigin().toString(), allowed));
 }
 
-void WebNotificationManagerProxy::providerDidRemoveNotificationPolicies(API::Array* origins)
+static void removePushSubscriptionsForOrigins(const Vector<WebCore::SecurityOriginData>& origins)
 {
-    if (!processPool())
+    RefPtr<NetworkProcessProxy> networkProcess;
+    auto sessionID = PAL::SessionID::defaultSessionID();
+
+    WebsiteDataStore::forEachWebsiteDataStore([&networkProcess, &sessionID](WebsiteDataStore& dataStore) {
+        if (!networkProcess && dataStore.isPersistent()) {
+            networkProcess = &dataStore.networkProcess();
+            sessionID = dataStore.sessionID();
+        }
+    });
+
+    if (!networkProcess)
         return;
 
+    for (auto& origin : origins)
+        networkProcess->deletePushAndNotificationRegistration(sessionID, origin, [originString = origin.toString()](auto&&) { });
+}
+
+static Vector<WebCore::SecurityOriginData> apiArrayToSecurityOrigins(API::Array* origins)
+{
+    if (!origins)
+        return { };
+
+    Vector<WebCore::SecurityOriginData> securityOrigins;
     size_t size = origins->size();
-    if (!size)
-        return;
-    
+    securityOrigins.reserveInitialCapacity(size);
+
+    for (size_t i = 0; i < size; ++i)
+        securityOrigins.uncheckedAppend(origins->at<API::SecurityOrigin>(i)->securityOrigin());
+
+    return securityOrigins;
+}
+
+static Vector<String> apiArrayToSecurityOriginStrings(API::Array* origins)
+{
+    if (!origins)
+        return { };
+
     Vector<String> originStrings;
+    size_t size = origins->size();
     originStrings.reserveInitialCapacity(size);
+
     for (size_t i = 0; i < size; ++i)
         originStrings.uncheckedAppend(origins->at<API::SecurityOrigin>(i)->securityOrigin().toString());
 
-    WebProcessPool::sendToAllRemoteWorkerProcesses(Messages::WebNotificationManager::DidRemoveNotificationDecisions(originStrings));
+    return originStrings;
+}
 
-    if (!processPool())
+void WebNotificationManagerProxy::providerDidRemoveNotificationPolicies(API::Array* origins)
+{
+    size_t size = origins->size();
+    if (!size)
         return;
-    processPool()->sendToAllProcesses(Messages::WebNotificationManager::DidRemoveNotificationDecisions(originStrings));
+
+    if (this == &sharedServiceWorkerManager()) {
+        removePushSubscriptionsForOrigins(apiArrayToSecurityOrigins(origins));
+        WebProcessPool::sendToAllRemoteWorkerProcesses(Messages::WebNotificationManager::DidRemoveNotificationDecisions(apiArrayToSecurityOriginStrings(origins)));
+        return;
+    }
+
+    if (processPool())
+        processPool()->sendToAllProcesses(Messages::WebNotificationManager::DidRemoveNotificationDecisions(apiArrayToSecurityOriginStrings(origins)));
 }
 
 } // namespace WebKit

Modified: trunk/Source/WebKit/webpushd/WebPushDaemon.mm (292157 => 292158)


--- trunk/Source/WebKit/webpushd/WebPushDaemon.mm	2022-03-31 13:56:29 UTC (rev 292157)
+++ trunk/Source/WebKit/webpushd/WebPushDaemon.mm	2022-03-31 15:08:16 UTC (rev 292158)
@@ -499,7 +499,18 @@
         return;
     }
 
-    connection->enqueueAppBundleRequest(makeUnique<AppBundleDeletionRequest>(*connection, originString, WTFMove(replySender)));
+    connection->enqueueAppBundleRequest(makeUnique<AppBundleDeletionRequest>(*connection, originString, [this, originString = String { originString }, replySender = WTFMove(replySender), bundleIdentifier = connection->hostAppCodeSigningIdentifier()](auto result) mutable {
+        runAfterStartingPushService([this, bundleIdentifier = WTFMove(bundleIdentifier), originString = WTFMove(originString), replySender = WTFMove(replySender), result]() mutable {
+            if (!m_pushService) {
+                replySender(result);
+                return;
+            }
+
+            m_pushService->removeRecordsForBundleIdentifierAndOrigin(bundleIdentifier, originString, [replySender = WTFMove(replySender), result](auto&&) mutable {
+                replySender(result);
+            });
+        });
+    }));
 }
 
 void Daemon::setDebugModeIsEnabled(ClientConnection* clientConnection, bool enabled)

Modified: trunk/Tools/ChangeLog (292157 => 292158)


--- trunk/Tools/ChangeLog	2022-03-31 13:56:29 UTC (rev 292157)
+++ trunk/Tools/ChangeLog	2022-03-31 15:08:16 UTC (rev 292158)
@@ -1,3 +1,24 @@
+2022-03-31  Ben Nham  <n...@apple.com>
+
+        Remove push subscriptions when permissions are reset
+        https://bugs.webkit.org/show_bug.cgi?id=238068
+
+        Reviewed by Youenn Fablet.
+
+        Add a test to make sure push subscriptions are removed when the notification policy for a
+        website is reset.
+
+        Also fixed an issue with a PushAPI test that didn't properly register for notification permissions.
+
+        * TestWebKitAPI/TestNotificationProvider.cpp:
+        (TestWebKitAPI::TestNotificationProvider::TestNotificationProvider):
+        (TestWebKitAPI::TestNotificationProvider::notificationPermissions const):
+        (TestWebKitAPI::TestNotificationProvider::setPermission):
+        (TestWebKitAPI::TestNotificationProvider::resetPermission):
+        * TestWebKitAPI/TestNotificationProvider.h:
+        * TestWebKitAPI/Tests/WebKitCocoa/PushAPI.mm:
+        * TestWebKitAPI/Tests/WebKitCocoa/WebPushDaemon.mm:
+
 2022-03-31  Chris Dumez  <cdu...@apple.com>
 
         Drop bad adoptNS() in NetworkProcess.LaunchOnlyWhenNecessary

Modified: trunk/Tools/TestWebKitAPI/TestNotificationProvider.cpp (292157 => 292158)


--- trunk/Tools/TestWebKitAPI/TestNotificationProvider.cpp	2022-03-31 13:56:29 UTC (rev 292157)
+++ trunk/Tools/TestWebKitAPI/TestNotificationProvider.cpp	2022-03-31 15:08:16 UTC (rev 292158)
@@ -27,6 +27,8 @@
 #include "TestNotificationProvider.h"
 
 #include "WTFStringUtilities.h"
+#include <WebKit/WKArray.h>
+#include <WebKit/WKMutableDictionary.h>
 #include <WebKit/WKNotificationManager.h>
 #include <WebKit/WKNumber.h>
 #include <WebKit/WKSecurityOriginRef.h>
@@ -42,7 +44,6 @@
 
 TestNotificationProvider::TestNotificationProvider(Vector<WKNotificationManagerRef>&& managers)
     : m_managers(WTFMove(managers))
-    , m_permissions(adoptWK(WKMutableDictionaryCreate()))
 {
     m_provider = {
         { 0, this },
@@ -67,19 +68,39 @@
 
 WKDictionaryRef TestNotificationProvider::notificationPermissions() const
 {
-    WKRetain(m_permissions.get());
-    return m_permissions.get();
+    auto permissions = WKMutableDictionaryCreate();
+
+    for (auto& [origin, allowed] : m_permissions) {
+        auto wkOriginString = adoptWK(WKStringCreateWithUTF8CString(origin.utf8().data()));
+        auto wkAllowed = adoptWK(WKBooleanCreate(allowed));
+        WKDictionarySetItem(permissions, wkOriginString.get(), wkAllowed.get());
+    }
+
+    return permissions;
 }
 
 void TestNotificationProvider::setPermission(const String& origin, bool allowed)
 {
-    auto wkAllowed = adoptWK(WKBooleanCreate(allowed));
+    m_permissions.set(origin, allowed);
+
     auto wkOriginString = adoptWK(WKStringCreateWithUTF8CString(origin.utf8().data()));
-    WKDictionarySetItem(m_permissions.get(), wkOriginString.get(), wkAllowed.get());
+    auto wkOrigin = adoptWK(WKSecurityOriginCreateFromString(wkOriginString.get()));
 
-    auto wkOrigin = adoptWK(WKSecurityOriginCreateFromString(wkOriginString.get()));
     for (auto& manager : m_managers)
         WKNotificationManagerProviderDidUpdateNotificationPolicy(manager, wkOrigin.get(), allowed);
 }
 
+void TestNotificationProvider::resetPermission(const String& origin)
+{
+    m_permissions.remove(origin);
+
+    auto wkOriginString = adoptWK(WKStringCreateWithUTF8CString(origin.utf8().data()));
+    auto wkOrigin = adoptWK(WKSecurityOriginCreateFromString(wkOriginString.get()));
+    auto wkOriginTypeRef = static_cast<WKTypeRef>(wkOrigin.get());
+    auto wkOriginArray = adoptWK(WKArrayCreate(&wkOriginTypeRef, 1));
+
+    for (auto& manager : m_managers)
+        WKNotificationManagerProviderDidRemoveNotificationPolicies(manager, wkOriginArray.get());
+}
+
 } // namespace TestWebKitAPI

Modified: trunk/Tools/TestWebKitAPI/TestNotificationProvider.h (292157 => 292158)


--- trunk/Tools/TestWebKitAPI/TestNotificationProvider.h	2022-03-31 13:56:29 UTC (rev 292157)
+++ trunk/Tools/TestWebKitAPI/TestNotificationProvider.h	2022-03-31 15:08:16 UTC (rev 292158)
@@ -25,11 +25,11 @@
 
 #pragma once
 
-#include <WebKit/WKMutableDictionary.h>
 #include <WebKit/WKNotificationManager.h>
 #include <WebKit/WKNotificationProvider.h>
 #include <WebKit/WKRetainPtr.h>
 #include <wtf/FastMalloc.h>
+#include <wtf/HashMap.h>
 #include <wtf/Vector.h>
 
 namespace TestWebKitAPI {
@@ -42,10 +42,11 @@
 
     WKDictionaryRef notificationPermissions() const;
     void setPermission(const String& origin, bool allowed);
+    void resetPermission(const String& origin);
 
 private:
     Vector<WKNotificationManagerRef> m_managers;
-    WKRetainPtr<WKMutableDictionaryRef> m_permissions;
+    HashMap<String, bool> m_permissions;
     WKNotificationProviderV0 m_provider;
 };
 

Modified: trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/PushAPI.mm (292157 => 292158)


--- trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/PushAPI.mm	2022-03-31 13:56:29 UTC (rev 292157)
+++ trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/PushAPI.mm	2022-03-31 15:08:16 UTC (rev 292158)
@@ -336,6 +336,9 @@
     configuration.get().websiteDataStore = dataStore.get();
     clearWebsiteDataStore([configuration websiteDataStore]);
 
+    auto provider = TestWebKitAPI::TestNotificationProvider({ [[configuration processPool] _notificationManagerForTesting], WKNotificationManagerGetSharedServiceWorkerNotificationManager() });
+    provider.setPermission(server.origin(), true);
+
     auto messageHandler = adoptNS([[PushAPIMessageHandlerWithExpectedMessage alloc] init]);
     [[configuration userContentController] addScriptMessageHandler:messageHandler.get() name:@"sw"];
 

Modified: trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/WebPushDaemon.mm (292157 => 292158)


--- trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/WebPushDaemon.mm	2022-03-31 13:56:29 UTC (rev 292157)
+++ trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/WebPushDaemon.mm	2022-03-31 15:08:16 UTC (rev 292158)
@@ -869,6 +869,56 @@
     ASSERT_FALSE(hasPushSubscription());
 }
 
+TEST_F(WebPushDTest, UnsubscribesOnPermissionReset)
+{
+    static const char* source = R"HTML(
+    <script src=""
+    <script>
+    navigator.serviceWorker.register('/sw.js').then(async () => {
+        const registration = await navigator.serviceWorker.ready;
+        let result = null;
+        try {
+            let subscription = await registration.pushManager.subscribe({
+                userVisibleOnly: true,
+                applicationServerKey: VALID_SERVER_KEY
+            });
+            result = "Subscribed";
+        } catch (e) {
+            result = "Error: " + e;
+        }
+        window.webkit.messageHandlers.note.postMessage(result);
+    });
+    </script>
+    )HTML";
+
+    __block RetainPtr<id> result = nil;
+    __block bool done = false;
+    [m_notificationMessageHandler setMessageHandler:^(id message) {
+        result = message;
+        done = true;
+    }];
+
+    loadRequest(source, "");
+    TestWebKitAPI::Util::run(&done);
+
+    ASSERT_TRUE([result isEqualToString:@"Subscribed"]);
+    ASSERT_TRUE(hasPushSubscription());
+
+    m_notificationProvider->resetPermission(m_server->origin());
+
+    bool isSubscribed = true;
+    TestWebKitAPI::Util::waitForConditionWithLogging([this, &isSubscribed] {
+        isSubscribed = hasPushSubscription();
+        if (!isSubscribed)
+            return true;
+
+        sleep(1);
+        return false;
+    }, 5, @"Timed out waiting for push subscription to be removed.");
+
+    ASSERT_FALSE(isSubscribed);
+}
+
 #if ENABLE(INSTALL_COORDINATION_BUNDLES)
 #if USE(APPLE_INTERNAL_SDK)
 static void deleteAllRegistrationsForDataStore(WKWebsiteDataStore *dataStore)
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to