Title: [283613] trunk
Revision
283613
Author
[email protected]
Date
2021-10-06 04:26:32 -0700 (Wed, 06 Oct 2021)

Log Message

Implement https://w3c.github.io/push-api/#receiving-a-push-message
https://bugs.webkit.org/show_bug.cgi?id=231070
<rdar://problem/83759574>

Reviewed by Chris Dumez.

Source/WebCore:

Implement firing a functional event and push message specialization.
Covered by API test.

* workers/service/server/SWServer.cpp:
* workers/service/server/SWServer.h:
* workers/service/server/SWServerToContextConnection.h:

Source/WebKit:

Add temporary SPI in WKWebsiteDataStore to allow pushing messages to service workers.
It takes a completion handler to check whether the message is acknowledged or not.
The service worker registration is identified by its scope for now.
A few additional things might need to be done:
- The case where the service worker is launched with no client.
- Handling of background assertions, especially if service worker has no client.
- Optimizations: skip events, optimization of network process launch by only loading the service worker registrations of an origin.

* NetworkProcess/NetworkProcess.cpp:
* NetworkProcess/NetworkProcess.h:
* NetworkProcess/NetworkProcess.messages.in:
* NetworkProcess/ServiceWorker/WebSWServerToContextConnection.cpp:
* NetworkProcess/ServiceWorker/WebSWServerToContextConnection.h:
* UIProcess/API/Cocoa/WKWebsiteDataStore.mm:
* UIProcess/API/Cocoa/WKWebsiteDataStorePrivate.h:
* UIProcess/Network/NetworkProcessProxy.cpp:
* UIProcess/Network/NetworkProcessProxy.h:
* WebProcess/Storage/WebSWContextManagerConnection.cpp:
* WebProcess/Storage/WebSWContextManagerConnection.h:
* WebProcess/Storage/WebSWContextManagerConnection.messages.in:

Tools:

* TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj:
* TestWebKitAPI/Tests/WebKitCocoa/PushAPI.mm: Added.

Modified Paths

Added Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (283612 => 283613)


--- trunk/Source/WebCore/ChangeLog	2021-10-06 10:33:28 UTC (rev 283612)
+++ trunk/Source/WebCore/ChangeLog	2021-10-06 11:26:32 UTC (rev 283613)
@@ -1,5 +1,20 @@
 2021-10-06  Youenn Fablet  <[email protected]>
 
+        Implement https://w3c.github.io/push-api/#receiving-a-push-message
+        https://bugs.webkit.org/show_bug.cgi?id=231070
+        <rdar://problem/83759574>
+
+        Reviewed by Chris Dumez.
+
+        Implement firing a functional event and push message specialization.
+        Covered by API test.
+
+        * workers/service/server/SWServer.cpp:
+        * workers/service/server/SWServer.h:
+        * workers/service/server/SWServerToContextConnection.h:
+
+2021-10-06  Youenn Fablet  <[email protected]>
+
         Simplify BaseAudioSharedUnit client management
         https://bugs.webkit.org/show_bug.cgi?id=231230
         <rdar://83884131>

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


--- trunk/Source/WebCore/workers/service/server/SWServer.cpp	2021-10-06 10:33:28 UTC (rev 283612)
+++ trunk/Source/WebCore/workers/service/server/SWServer.cpp	2021-10-06 11:26:32 UTC (rev 283613)
@@ -146,6 +146,14 @@
     m_importCompletedCallbacks.append(WTFMove(callback));
 }
 
+void SWServer::whenImportIsCompletedIfNeeded(CompletionHandler<void()>&& callback)
+{
+    if (m_importCompleted) {
+        callback();
+        return;
+    }
+    whenImportIsCompleted(WTFMove(callback));
+}
 
 void SWServer::registrationStoreDatabaseFailedToOpen()
 {
@@ -1185,6 +1193,80 @@
     scheduleJob(WTFMove(jobData));
 }
 
+void SWServer::processPushMessage(std::optional<Vector<uint8_t>>&& data, URL&& registrationURL, CompletionHandler<void(bool)>&& callback)
+{
+    whenImportIsCompletedIfNeeded([this, weakThis = makeWeakPtr(this), data = "" registrationURL = WTFMove(registrationURL), callback = WTFMove(callback)]() mutable {
+        if (!weakThis) {
+            callback(false);
+            return;
+        }
+        auto origin = SecurityOriginData::fromURL(registrationURL);
+        ServiceWorkerRegistrationKey registrationKey { WTFMove(origin), WTFMove(registrationURL) };
+        auto registration = m_scopeToRegistrationMap.get(registrationKey);
+        if (!registration) {
+            callback(true);
+            return;
+        }
+
+        auto* worker = registration->activeWorker();
+        if (!worker) {
+            callback(true);
+            return;
+        }
+
+        fireFunctionalEvent(*registration, [serviceWorkerIdentifier = worker->identifier(), data = "" callback = WTFMove(callback)](auto&& connectionOrStatus) mutable {
+            if (!connectionOrStatus.has_value()) {
+                callback(connectionOrStatus.error() == ShouldSkipEvent::Yes);
+                return;
+            }
+            connectionOrStatus.value()->firePushEvent(serviceWorkerIdentifier, data, WTFMove(callback));
+        });
+    });
+}
+
+// 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)
+{
+    auto* worker = registration.activeWorker();
+    if (!worker) {
+        callback(makeUnexpected(ShouldSkipEvent::Yes));
+        return;
+    }
+
+    // FIXME: we should check whether we can skip the event and if skipping do a soft-update.
+
+    worker->whenActivated([this, weakThis = makeWeakPtr(this), callback = WTFMove(callback), registrationIdentifier = registration.identifier(), serviceWorkerIdentifier = worker->identifier()](bool success) mutable {
+        if (!weakThis) {
+            callback(makeUnexpected(ShouldSkipEvent::No));
+            return;
+        }
+
+        if (!success) {
+            if (auto* registration = m_registrations.get(registrationIdentifier))
+                softUpdate(*registration);
+            callback(makeUnexpected(ShouldSkipEvent::No));
+            return;
+        }
+
+        auto* worker = workerByID(serviceWorkerIdentifier);
+        if (!worker) {
+            callback(makeUnexpected(ShouldSkipEvent::No));
+            return;
+        }
+
+        if (!worker->contextConnection())
+            createContextConnection(worker->registrableDomain(), worker->serviceWorkerPageIdentifier());
+
+        runServiceWorkerIfNecessary(serviceWorkerIdentifier, [callback = WTFMove(callback)](auto* contextConnection) mutable {
+            if (!contextConnection) {
+                callback(makeUnexpected(ShouldSkipEvent::No));
+                return;
+            }
+            callback(contextConnection);
+        });
+    });
+}
+
 } // namespace WebCore
 
 #endif // ENABLE(SERVICE_WORKER)

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


--- trunk/Source/WebCore/workers/service/server/SWServer.h	2021-10-06 10:33:28 UTC (rev 283612)
+++ trunk/Source/WebCore/workers/service/server/SWServer.h	2021-10-06 11:26:32 UTC (rev 283613)
@@ -221,6 +221,11 @@
     LastNavigationWasAppInitiated clientIsAppInitiatedForRegistrableDomain(const RegistrableDomain&);
     bool shouldRunServiceWorkersOnMainThreadForTesting() const { return m_shouldRunServiceWorkersOnMainThreadForTesting; }
 
+    WEBCORE_EXPORT void processPushMessage(std::optional<Vector<uint8_t>>&&, URL&&, CompletionHandler<void(bool)>&&);
+
+    enum class ShouldSkipEvent : bool { No, Yes };
+    void fireFunctionalEvent(SWServerRegistration&, CompletionHandler<void(Expected<SWServerToContextConnection*, ShouldSkipEvent>)>&&);
+
 private:
     void validateRegistrationDomain(WebCore::RegistrableDomain, ServiceWorkerJobType, CompletionHandler<void(bool)>&&);
 
@@ -247,6 +252,7 @@
     void contextConnectionCreated(SWServerToContextConnection&);
 
     void updateAppInitiatedValueForWorkers(const ClientOrigin&, LastNavigationWasAppInitiated);
+    void whenImportIsCompletedIfNeeded(CompletionHandler<void()>&&);
 
     HashMap<SWServerConnectionIdentifier, std::unique_ptr<Connection>> m_connections;
     HashMap<ServiceWorkerRegistrationKey, WeakPtr<SWServerRegistration>> m_scopeToRegistrationMap;

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


--- trunk/Source/WebCore/workers/service/server/SWServerToContextConnection.h	2021-10-06 10:33:28 UTC (rev 283612)
+++ trunk/Source/WebCore/workers/service/server/SWServerToContextConnection.h	2021-10-06 11:26:32 UTC (rev 283613)
@@ -60,6 +60,7 @@
     virtual void didSaveScriptsToDisk(ServiceWorkerIdentifier, const ScriptBuffer&, const HashMap<URL, ScriptBuffer>& importedScripts) = 0;
     virtual void findClientByIdentifierCompleted(uint64_t requestIdentifier, const std::optional<ServiceWorkerClientData>&, bool hasSecurityError) = 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;
 
     // Messages back from the SW host process
     WEBCORE_EXPORT void scriptContextFailedToStart(const std::optional<ServiceWorkerJobDataIdentifier>&, ServiceWorkerIdentifier, const String& message);

Modified: trunk/Source/WebKit/ChangeLog (283612 => 283613)


--- trunk/Source/WebKit/ChangeLog	2021-10-06 10:33:28 UTC (rev 283612)
+++ trunk/Source/WebKit/ChangeLog	2021-10-06 11:26:32 UTC (rev 283613)
@@ -1,3 +1,32 @@
+2021-10-06  Youenn Fablet  <[email protected]>
+
+        Implement https://w3c.github.io/push-api/#receiving-a-push-message
+        https://bugs.webkit.org/show_bug.cgi?id=231070
+        <rdar://problem/83759574>
+
+        Reviewed by Chris Dumez.
+
+        Add temporary SPI in WKWebsiteDataStore to allow pushing messages to service workers.
+        It takes a completion handler to check whether the message is acknowledged or not.
+        The service worker registration is identified by its scope for now.
+        A few additional things might need to be done:
+        - The case where the service worker is launched with no client.
+        - Handling of background assertions, especially if service worker has no client.
+        - Optimizations: skip events, optimization of network process launch by only loading the service worker registrations of an origin.
+
+        * NetworkProcess/NetworkProcess.cpp:
+        * NetworkProcess/NetworkProcess.h:
+        * NetworkProcess/NetworkProcess.messages.in:
+        * NetworkProcess/ServiceWorker/WebSWServerToContextConnection.cpp:
+        * NetworkProcess/ServiceWorker/WebSWServerToContextConnection.h:
+        * UIProcess/API/Cocoa/WKWebsiteDataStore.mm:
+        * UIProcess/API/Cocoa/WKWebsiteDataStorePrivate.h:
+        * UIProcess/Network/NetworkProcessProxy.cpp:
+        * UIProcess/Network/NetworkProcessProxy.h:
+        * WebProcess/Storage/WebSWContextManagerConnection.cpp:
+        * WebProcess/Storage/WebSWContextManagerConnection.h:
+        * WebProcess/Storage/WebSWContextManagerConnection.messages.in:
+
 2021-10-06  Jer Noble  <[email protected]>
 
         [Build-time perf] Forward declare JS TypedArrays

Modified: trunk/Source/WebKit/NetworkProcess/NetworkProcess.cpp (283612 => 283613)


--- trunk/Source/WebKit/NetworkProcess/NetworkProcess.cpp	2021-10-06 10:33:28 UTC (rev 283612)
+++ trunk/Source/WebKit/NetworkProcess/NetworkProcess.cpp	2021-10-06 11:26:32 UTC (rev 283613)
@@ -2516,6 +2516,14 @@
     if (addResult.isNewEntry)
         SandboxExtension::consumePermanently(handle);
 }
+
+void NetworkProcess::processPushMessage(PAL::SessionID sessionID, const std::optional<IPC::DataReference>& ipcData, URL&& registrationURL, CompletionHandler<void(bool)>&& callback)
+{
+    std::optional<Vector<uint8_t>> data;
+    if (ipcData)
+        data = "" { ipcData->data(), ipcData->size() };
+    swServerForSession(sessionID).processPushMessage(WTFMove(data), WTFMove(registrationURL), WTFMove(callback));
+}
 #endif // ENABLE(SERVICE_WORKER)
 
 void NetworkProcess::requestStorageSpace(PAL::SessionID sessionID, const ClientOrigin& origin, uint64_t quota, uint64_t currentSize, uint64_t spaceRequired, CompletionHandler<void(std::optional<uint64_t>)>&& callback)

Modified: trunk/Source/WebKit/NetworkProcess/NetworkProcess.h (283612 => 283613)


--- trunk/Source/WebKit/NetworkProcess/NetworkProcess.h	2021-10-06 10:33:28 UTC (rev 283612)
+++ trunk/Source/WebKit/NetworkProcess/NetworkProcess.h	2021-10-06 11:26:32 UTC (rev 283613)
@@ -396,6 +396,10 @@
 
     bool ftpEnabled() const { return m_ftpEnabled; }
 
+#if ENABLE(SERVICE_WORKER)
+    void processPushMessage(PAL::SessionID, const std::optional<IPC::DataReference>&, URL&&, CompletionHandler<void(bool)>&&);
+#endif
+
 private:
     void platformInitializeNetworkProcess(const NetworkProcessCreationParameters&);
 

Modified: trunk/Source/WebKit/NetworkProcess/NetworkProcess.messages.in (283612 => 283613)


--- trunk/Source/WebKit/NetworkProcess/NetworkProcess.messages.in	2021-10-06 10:33:28 UTC (rev 283612)
+++ trunk/Source/WebKit/NetworkProcess/NetworkProcess.messages.in	2021-10-06 11:26:32 UTC (rev 283613)
@@ -204,4 +204,8 @@
 #if ENABLE(CFPREFS_DIRECT_MODE)
     NotifyPreferencesChanged(String domain, String key, std::optional<String> encodedValue)
 #endif
+
+#if ENABLE(SERVICE_WORKER)
+    ProcessPushMessage(PAL::SessionID sessionID, std::optional<IPC::DataReference> data, URL registrationURL) -> (bool didSucceed) Async
+#endif
 }

Modified: trunk/Source/WebKit/NetworkProcess/ServiceWorker/WebSWServerToContextConnection.cpp (283612 => 283613)


--- trunk/Source/WebKit/NetworkProcess/ServiceWorker/WebSWServerToContextConnection.cpp	2021-10-06 10:33:28 UTC (rev 283612)
+++ trunk/Source/WebKit/NetworkProcess/ServiceWorker/WebSWServerToContextConnection.cpp	2021-10-06 11:26:32 UTC (rev 283613)
@@ -107,6 +107,14 @@
     send(Messages::WebSWContextManagerConnection::FireActivateEvent(serviceWorkerIdentifier));
 }
 
+void WebSWServerToContextConnection::firePushEvent(WebCore::ServiceWorkerIdentifier serviceWorkerIdentifier, const std::optional<Vector<uint8_t>>& data, CompletionHandler<void(bool)>&& callback)
+{
+    std::optional<IPC::DataReference> ipcData;
+    if (data)
+        ipcData = IPC::DataReference { data->data(), data->size() };
+    sendWithAsyncReply(Messages::WebSWContextManagerConnection::FirePushEvent(serviceWorkerIdentifier, ipcData), WTFMove(callback));
+}
+
 void WebSWServerToContextConnection::terminateWorker(ServiceWorkerIdentifier serviceWorkerIdentifier)
 {
     send(Messages::WebSWContextManagerConnection::TerminateWorker(serviceWorkerIdentifier));

Modified: trunk/Source/WebKit/NetworkProcess/ServiceWorker/WebSWServerToContextConnection.h (283612 => 283613)


--- trunk/Source/WebKit/NetworkProcess/ServiceWorker/WebSWServerToContextConnection.h	2021-10-06 10:33:28 UTC (rev 283612)
+++ trunk/Source/WebKit/NetworkProcess/ServiceWorker/WebSWServerToContextConnection.h	2021-10-06 11:26:32 UTC (rev 283613)
@@ -93,6 +93,7 @@
     void didSaveScriptsToDisk(WebCore::ServiceWorkerIdentifier, const WebCore::ScriptBuffer&, const HashMap<URL, WebCore::ScriptBuffer>& importedScripts) final;
     void findClientByIdentifierCompleted(uint64_t requestIdentifier, const std::optional<WebCore::ServiceWorkerClientData>&, bool hasSecurityError) 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 connectionIsNoLongerNeeded() final;
     void terminateDueToUnresponsiveness() final;

Modified: trunk/Source/WebKit/UIProcess/API/Cocoa/WKWebsiteDataStore.mm (283612 => 283613)


--- trunk/Source/WebKit/UIProcess/API/Cocoa/WKWebsiteDataStore.mm	2021-10-06 10:33:28 UTC (rev 283612)
+++ trunk/Source/WebKit/UIProcess/API/Cocoa/WKWebsiteDataStore.mm	2021-10-06 11:26:32 UTC (rev 283613)
@@ -753,4 +753,16 @@
     });
 }
 
+-(void)_processPushMessage:(NSData*) message registration:(NSURL *)registration completionHandler:(void(^)(bool wasProcessed))completionHandler
+{
+#if ENABLE(SERVICE_WORKER)
+    std::optional<Span<const uint8_t>> data;
+    if (message)
+        data = "" uint8_t> { reinterpret_cast<const uint8_t*>(message.bytes), message.length };
+    _websiteDataStore->networkProcess().processPushMessage(_websiteDataStore->sessionID(), data, registration, [completionHandler = makeBlockPtr(completionHandler)] (bool wasProcessed) {
+        completionHandler(wasProcessed);
+    });
+#endif
+}
+
 @end

Modified: trunk/Source/WebKit/UIProcess/API/Cocoa/WKWebsiteDataStorePrivate.h (283612 => 283613)


--- trunk/Source/WebKit/UIProcess/API/Cocoa/WKWebsiteDataStorePrivate.h	2021-10-06 10:33:28 UTC (rev 283612)
+++ trunk/Source/WebKit/UIProcess/API/Cocoa/WKWebsiteDataStorePrivate.h	2021-10-06 11:26:32 UTC (rev 283613)
@@ -106,6 +106,8 @@
 + (BOOL)_defaultNetworkProcessExists WK_API_AVAILABLE(macos(12.0), ios(15.0));
 - (void)_countNonDefaultSessionSets:(void(^)(size_t))completionHandler;
 
+-(void)_processPushMessage:(NSData*)data registration:(NSURL *)registration completionHandler:(void(^)(bool))completionHandler WK_API_AVAILABLE(macos(WK_MAC_TBA), ios(WK_IOS_TBA));
+
 @end
 
 NS_ASSUME_NONNULL_END

Modified: trunk/Source/WebKit/UIProcess/Network/NetworkProcessProxy.cpp (283612 => 283613)


--- trunk/Source/WebKit/UIProcess/Network/NetworkProcessProxy.cpp	2021-10-06 10:33:28 UTC (rev 283612)
+++ trunk/Source/WebKit/UIProcess/Network/NetworkProcessProxy.cpp	2021-10-06 11:26:32 UTC (rev 283613)
@@ -1631,6 +1631,16 @@
 }
 #endif
 
+#if ENABLE(SERVICE_WORKER)
+void NetworkProcessProxy::processPushMessage(PAL::SessionID sessionID, std::optional<Span<const uint8_t>> data, const URL& registrationURL, CompletionHandler<void(bool wasProcessed)>&& callback)
+{
+    std::optional<IPC::DataReference> ipcData;
+    if (data)
+        ipcData = IPC::DataReference { data->data(), data->size() };
+    sendWithAsyncReply(Messages::NetworkProcess::ProcessPushMessage { sessionID, ipcData, registrationURL }, WTFMove(callback));
+}
+#endif // ENABLE(SERVICE_WORKER)
+
 } // namespace WebKit
 
 #undef MESSAGE_CHECK

Modified: trunk/Source/WebKit/UIProcess/Network/NetworkProcessProxy.h (283612 => 283613)


--- trunk/Source/WebKit/UIProcess/Network/NetworkProcessProxy.h	2021-10-06 10:33:28 UTC (rev 283612)
+++ trunk/Source/WebKit/UIProcess/Network/NetworkProcessProxy.h	2021-10-06 11:26:32 UTC (rev 283613)
@@ -271,6 +271,10 @@
     xpc_object_t xpcEndpointMessage() const { return m_endpointMessage.get(); }
 #endif
 
+#if ENABLE(SERVICE_WORKER)
+    void processPushMessage(PAL::SessionID, std::optional<Span<const uint8_t>>, const URL&, CompletionHandler<void(bool wasProcessed)>&&);
+#endif
+
 private:
     explicit NetworkProcessProxy();
 

Modified: trunk/Source/WebKit/WebProcess/Storage/WebSWContextManagerConnection.cpp (283612 => 283613)


--- trunk/Source/WebKit/WebProcess/Storage/WebSWContextManagerConnection.cpp	2021-10-06 10:33:28 UTC (rev 283612)
+++ trunk/Source/WebKit/WebProcess/Storage/WebSWContextManagerConnection.cpp	2021-10-06 11:26:32 UTC (rev 283613)
@@ -272,6 +272,14 @@
     SWContextManager::singleton().fireActivateEvent(identifier);
 }
 
+void WebSWContextManagerConnection::firePushEvent(ServiceWorkerIdentifier identifier, const std::optional<IPC::DataReference>& ipcData, CompletionHandler<void(bool)>&& callback)
+{
+    std::optional<Vector<uint8_t>> data;
+    if (ipcData)
+        data = "" { ipcData->data(), ipcData->size() };
+    SWContextManager::singleton().firePushEvent(identifier, WTFMove(data), WTFMove(callback));
+}
+
 void WebSWContextManagerConnection::terminateWorker(ServiceWorkerIdentifier identifier)
 {
     SWContextManager::singleton().terminateWorker(identifier, SWContextManager::workerTerminationTimeout, nullptr);

Modified: trunk/Source/WebKit/WebProcess/Storage/WebSWContextManagerConnection.h (283612 => 283613)


--- trunk/Source/WebKit/WebProcess/Storage/WebSWContextManagerConnection.h	2021-10-06 10:33:28 UTC (rev 283612)
+++ trunk/Source/WebKit/WebProcess/Storage/WebSWContextManagerConnection.h	2021-10-06 11:26:32 UTC (rev 283613)
@@ -28,6 +28,7 @@
 #if ENABLE(SERVICE_WORKER)
 
 #include "Connection.h"
+#include "DataReference.h"
 #include "IdentifierTypes.h"
 #include "MessageReceiver.h"
 #include "NavigatingToAppBoundDomain.h"
@@ -95,6 +96,7 @@
     void postMessageToServiceWorker(WebCore::ServiceWorkerIdentifier destinationIdentifier, WebCore::MessageWithMessagePorts&&, WebCore::ServiceWorkerOrClientData&& sourceData);
     void fireInstallEvent(WebCore::ServiceWorkerIdentifier);
     void fireActivateEvent(WebCore::ServiceWorkerIdentifier);
+    void firePushEvent(WebCore::ServiceWorkerIdentifier, const std::optional<IPC::DataReference>&, 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 (283612 => 283613)


--- trunk/Source/WebKit/WebProcess/Storage/WebSWContextManagerConnection.messages.in	2021-10-06 10:33:28 UTC (rev 283612)
+++ trunk/Source/WebKit/WebProcess/Storage/WebSWContextManagerConnection.messages.in	2021-10-06 11:26:32 UTC (rev 283613)
@@ -31,6 +31,8 @@
     PostMessageToServiceWorker(WebCore::ServiceWorkerIdentifier destinationIdentifier, struct WebCore::MessageWithMessagePorts message, WebCore::ServiceWorkerOrClientData sourceData)
     FireInstallEvent(WebCore::ServiceWorkerIdentifier identifier)
     FireActivateEvent(WebCore::ServiceWorkerIdentifier identifier)
+    FirePushEvent(WebCore::ServiceWorkerIdentifier identifier, std::optional<IPC::DataReference> data) -> (bool result) Async
+
     TerminateWorker(WebCore::ServiceWorkerIdentifier identifier)
 #if ENABLE(SHAREABLE_RESOURCE) && PLATFORM(COCOA)
     DidSaveScriptsToDisk(WebCore::ServiceWorkerIdentifier serviceWorkerIdentifier, WebCore::ScriptBuffer script, HashMap<URL, WebCore::ScriptBuffer> importedScripts);

Modified: trunk/Tools/ChangeLog (283612 => 283613)


--- trunk/Tools/ChangeLog	2021-10-06 10:33:28 UTC (rev 283612)
+++ trunk/Tools/ChangeLog	2021-10-06 11:26:32 UTC (rev 283613)
@@ -1,3 +1,14 @@
+2021-10-06  Youenn Fablet  <[email protected]>
+
+        Implement https://w3c.github.io/push-api/#receiving-a-push-message
+        https://bugs.webkit.org/show_bug.cgi?id=231070
+        <rdar://problem/83759574>
+
+        Reviewed by Chris Dumez.
+
+        * TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj:
+        * TestWebKitAPI/Tests/WebKitCocoa/PushAPI.mm: Added.
+
 2021-10-06  Carlos Garcia Campos  <[email protected]>
 
         Unreviewed. [GTK] Fix /webkit/WebKitAccessibility/accessible/state with ATSPI

Modified: trunk/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj (283612 => 283613)


--- trunk/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj	2021-10-06 10:33:28 UTC (rev 283612)
+++ trunk/Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj	2021-10-06 11:26:32 UTC (rev 283613)
@@ -260,6 +260,7 @@
 		4181C62D255A891100AEB0FF /* RTCRtpSFrameTransformerTests.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4181C62C255A891100AEB0FF /* RTCRtpSFrameTransformerTests.cpp */; };
 		41848F4424891879000E2588 /* open-window-with-file-url-with-host.html in Copy Resources */ = {isa = PBXBuildFile; fileRef = 41848F4324891815000E2588 /* open-window-with-file-url-with-host.html */; };
 		41882F0321010C0D002FF288 /* ProcessPreWarming.mm in Sources */ = {isa = PBXBuildFile; fileRef = 41882F0221010A70002FF288 /* ProcessPreWarming.mm */; };
+		418FCBD62707066100F96ECA /* PushAPI.mm in Sources */ = {isa = PBXBuildFile; fileRef = 418FCBD52707066100F96ECA /* PushAPI.mm */; };
 		41E67A8525D16E83007B0A4C /* STUNMessageParsingTest.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 41E67A8425D16E83007B0A4C /* STUNMessageParsingTest.cpp */; };
 		44077BB123144B5000179E2D /* DataDetectorsTestIOS.mm in Sources */ = {isa = PBXBuildFile; fileRef = 44077BB0231449D200179E2D /* DataDetectorsTestIOS.mm */; };
 		4433A396208044140091ED57 /* SynchronousTimeoutTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 4433A395208044130091ED57 /* SynchronousTimeoutTests.mm */; };
@@ -2100,6 +2101,7 @@
 		4181C62C255A891100AEB0FF /* RTCRtpSFrameTransformerTests.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RTCRtpSFrameTransformerTests.cpp; sourceTree = "<group>"; };
 		41848F4324891815000E2588 /* open-window-with-file-url-with-host.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = "open-window-with-file-url-with-host.html"; sourceTree = "<group>"; };
 		41882F0221010A70002FF288 /* ProcessPreWarming.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ProcessPreWarming.mm; sourceTree = "<group>"; };
+		418FCBD52707066100F96ECA /* PushAPI.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = PushAPI.mm; sourceTree = "<group>"; };
 		41973B5C1AF22875006C7B36 /* SharedBuffer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SharedBuffer.cpp; sourceTree = "<group>"; };
 		41BAF4E225AC9DB800D82F32 /* getUserMedia2.html */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.html; path = getUserMedia2.html; sourceTree = "<group>"; };
 		41E67A8425D16E83007B0A4C /* STUNMessageParsingTest.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = STUNMessageParsingTest.cpp; sourceTree = "<group>"; };
@@ -3603,6 +3605,7 @@
 				518C1152205B04F9001FF4AE /* ProcessSwapOnNavigation.mm */,
 				5798E2AF1CAF5C2800C5CBA0 /* ProvisionalURLNotChange.mm */,
 				5CFACF64226FD1FB0056C7D0 /* Proxy.mm */,
+				418FCBD52707066100F96ECA /* PushAPI.mm */,
 				A1C4FB6C1BACCE50003742D0 /* QuickLook.mm */,
 				2D2FE8D72315F06D00B2E9C9 /* ReloadWithDifferingInitialScale.mm */,
 				1A4F81D01BDFFDCF004E672E /* RemoteObjectRegistry.h */,
@@ -5778,6 +5781,7 @@
 				7C83E0C11D0A652F00FEBCF3 /* ProvisionalURLNotChange.mm in Sources */,
 				5CFACF65226FD2DC0056C7D0 /* Proxy.mm in Sources */,
 				041A1E34216FFDBC00789E0A /* PublicSuffix.cpp in Sources */,
+				418FCBD62707066100F96ECA /* PushAPI.mm in Sources */,
 				7C83E0C21D0A653500FEBCF3 /* QuickLook.mm in Sources */,
 				6B4E861C2220A5520022F389 /* RegistrableDomain.cpp in Sources */,
 				7CCE7F0D1A411AE600447C4C /* ReloadPageAfterCrash.cpp in Sources */,

Added: trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/PushAPI.mm (0 => 283613)


--- trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/PushAPI.mm	                        (rev 0)
+++ trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/PushAPI.mm	2021-10-06 11:26:32 UTC (rev 283613)
@@ -0,0 +1,152 @@
+/*
+ * Copyright (C) 2021 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.
+ */
+
+#import "config.h"
+
+#import "HTTPServer.h"
+#import "PlatformUtilities.h"
+#import "Test.h"
+#import "TestWKWebView.h"
+#import <WebKit/WKWebsiteDataStorePrivate.h>
+
+static bool done;
+static String expectedMessage;
+
+@interface PushAPIMessageHandlerWithExpectedMessage : NSObject <WKScriptMessageHandler>
+@end
+
+@implementation PushAPIMessageHandlerWithExpectedMessage
+- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message
+{
+    EXPECT_WK_STREQ(message.body, expectedMessage);
+    done = true;
+}
+@end
+
+// FIXME: Update the test to do subscription before pushing message.
+static const char* mainBytes = R"SWRESOURCE(
+<script>
+function log(msg)
+{
+    window.webkit.messageHandlers.sw.postMessage(msg);
+}
+
+const channel = new MessageChannel();
+channel.port1._onmessage_ = (event) => log(event.data);
+
+navigator.serviceWorker.register('/sw.js').then((registration) => {
+    if (registration.active) {
+        registration.active.postMessage({port: channel.port2}, [channel.port2]);
+        return;
+    }
+    worker = registration.installing;
+    worker.addEventListener('statechange', function() {
+        if (worker.state == 'activated')
+            worker.postMessage({port: channel.port2}, [channel.port2]);
+    });
+}).catch(function(error) {
+    log("Registration failed with: " + error);
+});
+</script>
+)SWRESOURCE";
+
+static const char* scriptBytes = R"SWRESOURCE(
+let port;
+self.addEventListener("message", (event) => {
+    port = event.data.port;
+    port.postMessage("Ready");
+});
+self.addEventListener("push", (event) => {
+    try {
+        if (!event.data) {
+            port.postMessage("Received: null data");
+            return;
+        }
+        const value = event.data.text();
+        port.postMessage("Received: " + value);
+        if (value != 'Sweet Potatoes')
+            event.waitUntil(Promise.reject('I want sweet potatoes'));
+    } catch (e) {
+        port.postMessage("Got exception " + e);
+    }
+});
+)SWRESOURCE";
+
+static bool pushMessageProcessed = false;
+static bool pushMessageSuccessful = false;
+TEST(PushAPI, firePushEvent)
+{
+    TestWebKitAPI::HTTPServer server({
+        { "/", { mainBytes } },
+        { "/sw.js", { {{ "Content-Type", "application/_javascript_" }}, scriptBytes } }
+    }, TestWebKitAPI::HTTPServer::Protocol::Http);
+
+    [WKWebsiteDataStore _allowWebsiteDataRecordsForAllOrigins];
+
+    auto configuration = adoptNS([[WKWebViewConfiguration alloc] init]);
+
+    auto messageHandler = adoptNS([[PushAPIMessageHandlerWithExpectedMessage alloc] init]);
+    [[configuration userContentController] addScriptMessageHandler:messageHandler.get() name:@"sw"];
+
+    [[configuration websiteDataStore] removeDataOfTypes:[WKWebsiteDataStore allWebsiteDataTypes] modifiedSince:[NSDate distantPast] completionHandler:^() {
+        done = true;
+    }];
+    TestWebKitAPI::Util::run(&done);
+    done = false;
+
+    expectedMessage = "Ready";
+    auto webView = adoptNS([[WKWebView alloc] initWithFrame:NSMakeRect(0, 0, 800, 600) configuration:configuration.get()]);
+    [webView loadRequest:server.request()];
+
+    TestWebKitAPI::Util::run(&done);
+
+    done = false;
+    pushMessageProcessed = false;
+    pushMessageSuccessful = false;
+    NSString *message = @"Sweet Potatoes";
+    expectedMessage = "Received: Sweet Potatoes";
+    [[configuration websiteDataStore] _processPushMessage:[message dataUsingEncoding:NSUTF8StringEncoding] registration:[server.request() URL] completionHandler:^(bool result) {
+        pushMessageSuccessful = result;
+        pushMessageProcessed = true;
+    }];
+    TestWebKitAPI::Util::run(&done);
+
+    TestWebKitAPI::Util::run(&pushMessageProcessed);
+    EXPECT_TRUE(pushMessageSuccessful);
+
+    done = false;
+    pushMessageProcessed = false;
+    pushMessageSuccessful = false;
+    message = @"Rotten Potatoes";
+    expectedMessage = "Received: Rotten Potatoes";
+    [[configuration websiteDataStore] _processPushMessage:[message dataUsingEncoding:NSUTF8StringEncoding] registration:[server.request() URL] completionHandler:^(bool result) {
+        pushMessageSuccessful = result;
+        pushMessageProcessed = true;
+    }];
+    TestWebKitAPI::Util::run(&done);
+
+    TestWebKitAPI::Util::run(&pushMessageProcessed);
+    EXPECT_FALSE(pushMessageSuccessful);
+}
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to