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);
+}