Title: [284887] trunk
Revision
284887
Author
beid...@apple.com
Date
2021-10-26 12:34:30 -0700 (Tue, 26 Oct 2021)

Log Message

Add helper classes and messaging infrastructure to launch webpushd and round trip a message to it
https://bugs.webkit.org/show_bug.cgi?id=232262

Reviewed by Alex Christensen.

Source/WebKit:

No new tests (No behavior change yet)

This patch:
- Adds classes representing the WebPushDaemon and connections to it
- Adds classes/constants/macros related to messaging that daemon
- Adds SPI for configuring a connect to that daemon
- Gets MiniBrowser closer to supporting built-in notifications
- Has way more commented out code than usual for a patch, but that enables a great stopping-point milestone

* NetworkProcess/Notifications/Cocoa/WebPushDaemonConnectionCocoa.mm: Added.
(WebKit::WebPushD::addVersionAndEncodedMessageToDictionary):
(WebKit::WebPushD::Connection::newConnectionWasInitialized const):
(WebKit::WebPushD::Connection::connectionReceivedEvent const):
(WebKit::WebPushD::Connection::dictionaryFromMessage const):

* NetworkProcess/Notifications/NetworkNotificationManager.cpp:
(WebKit::NetworkNotificationManager::NetworkNotificationManager):
(WebKit::NetworkNotificationManager::showNotification):
(WebKit::NetworkNotificationManager::cancelNotification):
(WebKit::NetworkNotificationManager::clearNotifications):
(WebKit::NetworkNotificationManager::didDestroyNotification):
(WebKit::NetworkNotificationManager::sendMessage const):
(WebKit::ReplyCaller<>::callReply):
(WebKit::ReplyCaller<String>::callReply):
(WebKit::NetworkNotificationManager::sendMessageWithReply const):
* NetworkProcess/Notifications/NetworkNotificationManager.h:
(WebKit::NetworkNotificationManager::networkSession const):

* NetworkProcess/Notifications/WebPushDaemonConnection.cpp: Copied from Source/WebKit/Platform/IPC/DaemonConnection.cpp.
(WebKit::WebPushD::Connection::Connection):
(WebKit::WebPushD::Connection::networkSession const):
* NetworkProcess/Notifications/WebPushDaemonConnection.h: Copied from Source/WebKit/NetworkProcess/Notifications/NetworkNotificationManager.h.

* NetworkProcess/mac/com.apple.WebKit.NetworkProcess.sb.in:

* Platform/IPC/DaemonConnection.cpp:
* Platform/IPC/DaemonConnection.h:
(WebKit::Daemon::ConnectionToMachService::machServiceName const):
* Platform/IPC/cocoa/DaemonConnectionCocoa.mm:

* Platform/Logging.h:

* Shared/WebPushDaemonConstants.h: Copied from Source/WebKit/Platform/IPC/DaemonConnection.cpp.
(WebKit::WebPushD::messageTypeSendsReply):

* UIProcess/WebsiteData/WebsiteDataStoreConfiguration.cpp:
(WebKit::WebsiteDataStoreConfiguration::copy const):

* webpushd/WebPushDaemon.h: Copied from Source/WebKit/NetworkProcess/Notifications/NetworkNotificationManager.h.
* webpushd/WebPushDaemon.mm: Copied from Source/WebKit/webpushd/WebPushDaemonMain.mm.
(WebPushD::MessageInfo::echoTwice::encodeReply):
(WebPushD::handleWebPushDMessageWithReply):
(WebPushD::Daemon::singleton):
(WebPushD::Daemon::connectionEventHandler):
(WebPushD::Daemon::connectionAdded):
(WebPushD::Daemon::connectionRemoved):
(WebPushD::CompletionHandler<void):
(WebPushD::Daemon::decodeAndHandleMessage):
(WebPushD::Daemon::echoTwice):

* webpushd/WebPushDaemonMain.mm:
(WebPushD::connectionEventHandler):
(WebPushD::connectionAdded):
(WebPushD::connectionRemoved):
(WebPushD::CompletionHandler<void): Deleted.
(WebPushD::echoTwice): Deleted.
(WebPushD::decodeMessageAndSendReply): Deleted.

* Sources.txt:
* SourcesCocoa.txt:
* WebKit.xcodeproj/project.pbxproj:

Tools:

* MiniBrowser/mac/AppDelegate.m:
(persistentDataStore):
* MiniBrowser/mac/WK2BrowserWindowController.m:
(-[WK2BrowserWindowController _webView:requestNotificationPermissionForSecurityOrigin:decisionHandler:]):

Modified Paths

Added Paths

Diff

Modified: trunk/Source/WebKit/ChangeLog (284886 => 284887)


--- trunk/Source/WebKit/ChangeLog	2021-10-26 18:57:31 UTC (rev 284886)
+++ trunk/Source/WebKit/ChangeLog	2021-10-26 19:34:30 UTC (rev 284887)
@@ -1,3 +1,82 @@
+2021-10-26  Brady Eidson  <beid...@apple.com>
+
+        Add helper classes and messaging infrastructure to launch webpushd and round trip a message to it
+        https://bugs.webkit.org/show_bug.cgi?id=232262
+
+        Reviewed by Alex Christensen.
+
+        No new tests (No behavior change yet)
+
+        This patch:
+        - Adds classes representing the WebPushDaemon and connections to it
+        - Adds classes/constants/macros related to messaging that daemon
+        - Adds SPI for configuring a connect to that daemon
+        - Gets MiniBrowser closer to supporting built-in notifications
+        - Has way more commented out code than usual for a patch, but that enables a great stopping-point milestone
+
+        * NetworkProcess/Notifications/Cocoa/WebPushDaemonConnectionCocoa.mm: Added.
+        (WebKit::WebPushD::addVersionAndEncodedMessageToDictionary):
+        (WebKit::WebPushD::Connection::newConnectionWasInitialized const):
+        (WebKit::WebPushD::Connection::connectionReceivedEvent const):
+        (WebKit::WebPushD::Connection::dictionaryFromMessage const):
+
+        * NetworkProcess/Notifications/NetworkNotificationManager.cpp:
+        (WebKit::NetworkNotificationManager::NetworkNotificationManager):
+        (WebKit::NetworkNotificationManager::showNotification):
+        (WebKit::NetworkNotificationManager::cancelNotification):
+        (WebKit::NetworkNotificationManager::clearNotifications):
+        (WebKit::NetworkNotificationManager::didDestroyNotification):
+        (WebKit::NetworkNotificationManager::sendMessage const):
+        (WebKit::ReplyCaller<>::callReply):
+        (WebKit::ReplyCaller<String>::callReply):
+        (WebKit::NetworkNotificationManager::sendMessageWithReply const):
+        * NetworkProcess/Notifications/NetworkNotificationManager.h:
+        (WebKit::NetworkNotificationManager::networkSession const):
+
+        * NetworkProcess/Notifications/WebPushDaemonConnection.cpp: Copied from Source/WebKit/Platform/IPC/DaemonConnection.cpp.
+        (WebKit::WebPushD::Connection::Connection):
+        (WebKit::WebPushD::Connection::networkSession const):
+        * NetworkProcess/Notifications/WebPushDaemonConnection.h: Copied from Source/WebKit/NetworkProcess/Notifications/NetworkNotificationManager.h.
+
+        * NetworkProcess/mac/com.apple.WebKit.NetworkProcess.sb.in:
+
+        * Platform/IPC/DaemonConnection.cpp:
+        * Platform/IPC/DaemonConnection.h:
+        (WebKit::Daemon::ConnectionToMachService::machServiceName const):
+        * Platform/IPC/cocoa/DaemonConnectionCocoa.mm:
+
+        * Platform/Logging.h:
+
+        * Shared/WebPushDaemonConstants.h: Copied from Source/WebKit/Platform/IPC/DaemonConnection.cpp.
+        (WebKit::WebPushD::messageTypeSendsReply):
+
+        * UIProcess/WebsiteData/WebsiteDataStoreConfiguration.cpp:
+        (WebKit::WebsiteDataStoreConfiguration::copy const):
+
+        * webpushd/WebPushDaemon.h: Copied from Source/WebKit/NetworkProcess/Notifications/NetworkNotificationManager.h.
+        * webpushd/WebPushDaemon.mm: Copied from Source/WebKit/webpushd/WebPushDaemonMain.mm.
+        (WebPushD::MessageInfo::echoTwice::encodeReply):
+        (WebPushD::handleWebPushDMessageWithReply):
+        (WebPushD::Daemon::singleton):
+        (WebPushD::Daemon::connectionEventHandler):
+        (WebPushD::Daemon::connectionAdded):
+        (WebPushD::Daemon::connectionRemoved):
+        (WebPushD::CompletionHandler<void):
+        (WebPushD::Daemon::decodeAndHandleMessage):
+        (WebPushD::Daemon::echoTwice):
+        
+        * webpushd/WebPushDaemonMain.mm:
+        (WebPushD::connectionEventHandler):
+        (WebPushD::connectionAdded):
+        (WebPushD::connectionRemoved):
+        (WebPushD::CompletionHandler<void): Deleted.
+        (WebPushD::echoTwice): Deleted.
+        (WebPushD::decodeMessageAndSendReply): Deleted.
+
+        * Sources.txt:
+        * SourcesCocoa.txt:
+        * WebKit.xcodeproj/project.pbxproj:
+        
 2021-10-26  Kate Cheney  <katherine_che...@apple.com>
 
         [ App Privacy Report ] Restoring a session after clearing the cache results in app initiated loads in Safari

Added: trunk/Source/WebKit/NetworkProcess/Notifications/Cocoa/WebPushDaemonConnectionCocoa.mm (0 => 284887)


--- trunk/Source/WebKit/NetworkProcess/Notifications/Cocoa/WebPushDaemonConnectionCocoa.mm	                        (rev 0)
+++ trunk/Source/WebKit/NetworkProcess/Notifications/Cocoa/WebPushDaemonConnectionCocoa.mm	2021-10-26 19:34:30 UTC (rev 284887)
@@ -0,0 +1,77 @@
+/*
+ * 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 "WebPushDaemonConnection.h"
+
+#if PLATFORM(COCOA) && ENABLE(BUILT_IN_NOTIFICATIONS)
+
+#import "DaemonEncoder.h"
+#import "DaemonUtilities.h"
+#import "WebPushDaemonConstants.h"
+#import <wtf/spi/darwin/XPCSPI.h>
+
+namespace WebKit::WebPushD { 
+
+using Daemon::EncodedMessage;
+
+static void addVersionAndEncodedMessageToDictionary(Vector<uint8_t>&& message, xpc_object_t dictionary)
+{
+    ASSERT(xpc_get_type(dictionary) == XPC_TYPE_DICTIONARY);
+    xpc_dictionary_set_uint64(dictionary, WebPushD::protocolVersionKey, WebPushD::protocolVersionValue);
+    xpc_dictionary_set_value(dictionary, WebPushD::protocolEncodedMessageKey, vectorToXPCData(WTFMove(message)).get());
+}
+
+void Connection::newConnectionWasInitialized() const
+{
+    ASSERT(m_connection);
+    if (networkSession().sessionID().isEphemeral())
+        return;
+
+    // FIXME: Track connection state
+}
+
+void Connection::connectionReceivedEvent(xpc_object_t request) const
+{
+    if (xpc_get_type(request) != XPC_TYPE_DICTIONARY)
+        return;
+    const char* debugMessage = xpc_dictionary_get_string(request, protocolDebugMessageKey);
+    if (!debugMessage)
+        return;
+    auto messageLevel = static_cast<JSC::MessageLevel>(xpc_dictionary_get_uint64(request, protocolDebugMessageLevelKey));
+    networkSession().networkProcess().broadcastConsoleMessage(networkSession().sessionID(), MessageSource::PrivateClickMeasurement, messageLevel, String::fromUTF8(debugMessage));
+}
+
+RetainPtr<xpc_object_t> Connection::dictionaryFromMessage(MessageType messageType, EncodedMessage&& message) const
+{
+    auto dictionary = adoptNS(xpc_dictionary_create(nullptr, nullptr, 0));
+    addVersionAndEncodedMessageToDictionary(WTFMove(message), dictionary.get());
+    xpc_dictionary_set_uint64(dictionary.get(), protocolMessageTypeKey, static_cast<uint64_t>(messageType));
+    return dictionary;
+}
+
+} // namespace WebKit::WebPushD
+
+#endif // PLATFORM(COCOA) && ENABLE(BUILT_IN_NOTIFICATIONS)

Modified: trunk/Source/WebKit/NetworkProcess/Notifications/NetworkNotificationManager.cpp (284886 => 284887)


--- trunk/Source/WebKit/NetworkProcess/Notifications/NetworkNotificationManager.cpp	2021-10-26 18:57:31 UTC (rev 284886)
+++ trunk/Source/WebKit/NetworkProcess/Notifications/NetworkNotificationManager.cpp	2021-10-26 19:34:30 UTC (rev 284887)
@@ -28,29 +28,94 @@
 
 #if ENABLE(BUILT_IN_NOTIFICATIONS)
 
+#include "DaemonDecoder.h"
+#include "DaemonEncoder.h"
+#include "NetworkSession.h"
+
 namespace WebKit {
 using namespace WebCore;
 
-NetworkNotificationManager::NetworkNotificationManager(NetworkSession& networkSession, const String&)
+NetworkNotificationManager::NetworkNotificationManager(NetworkSession& networkSession, const String& webPushMachServiceName)
     : m_networkSession(networkSession)
 {
+    if (!m_networkSession.sessionID().isEphemeral() && !webPushMachServiceName.isEmpty())
+        m_connection = makeUnique<WebPushD::Connection>(webPushMachServiceName.utf8(), *this);
 }
 
 void NetworkNotificationManager::showNotification(const String&, const String&, const String&, const String&, const String&, WebCore::NotificationDirection, const String&, uint64_t)
 {
+    if (!m_connection)
+        return;
+
+//     FIXME: While we don't normally land commented-out code in the tree,
+//     this is a nice bookmark for a development milestone; Roundtrip communication with webpushd
+//     Will make next development steps obvious.
+//
+//    CompletionHandler<void(String)>&& completionHandler = [] (String reply) {
+//        printf("Got reply: %s\n", reply.utf8().data());
+//    };
+//
+//    sendMessageWithReply<WebPushD::MessageType::EchoTwice>(WTFMove(completionHandler), String("FIXME: Do useful work here"));
 }
 
 void NetworkNotificationManager::cancelNotification(uint64_t)
 {
+    if (!m_connection)
+        return;
 }
 
 void NetworkNotificationManager::clearNotifications(const Vector<uint64_t>&)
 {
+    if (!m_connection)
+        return;
 }
 
 void NetworkNotificationManager::didDestroyNotification(uint64_t)
 {
+    if (!m_connection)
+        return;
 }
 
+
+template<WebPushD::MessageType messageType, typename... Args>
+void NetworkNotificationManager::sendMessage(Args&&... args) const
+{
+    RELEASE_ASSERT(m_connection);
+    Daemon::Encoder encoder;
+    encoder.encode(std::forward<Args>(args)...);
+    m_connection->send(messageType, encoder.takeBuffer());
+}
+
+template<typename... Args> struct ReplyCaller;
+template<> struct ReplyCaller<> {
+    static void callReply(Daemon::Decoder&& decoder, CompletionHandler<void()>&& completionHandler)
+    {
+        completionHandler();
+    }
+};
+template<> struct ReplyCaller<String> {
+    static void callReply(Daemon::Decoder&& decoder, CompletionHandler<void(String&&)>&& completionHandler)
+    {
+        std::optional<String> string;
+        decoder >> string;
+        if (!string)
+            return completionHandler({ });
+        completionHandler(WTFMove(*string));
+    }
+};
+
+template<WebPushD::MessageType messageType, typename... Args, typename... ReplyArgs>
+void NetworkNotificationManager::sendMessageWithReply(CompletionHandler<void(ReplyArgs...)>&& completionHandler, Args&&... args) const
+{
+    RELEASE_ASSERT(m_connection);
+
+    Daemon::Encoder encoder;
+    encoder.encode(std::forward<Args>(args)...);
+    m_connection->sendWithReply(messageType, encoder.takeBuffer(), [completionHandler = WTFMove(completionHandler)] (auto replyBuffer) mutable {
+        Daemon::Decoder decoder(WTFMove(replyBuffer));
+        ReplyCaller<ReplyArgs...>::callReply(WTFMove(decoder), WTFMove(completionHandler));
+    });
+}
+
 } // namespace WebKit
 #endif // ENABLE(BUILT_IN_NOTIFICATIONS)

Modified: trunk/Source/WebKit/NetworkProcess/Notifications/NetworkNotificationManager.h (284886 => 284887)


--- trunk/Source/WebKit/NetworkProcess/Notifications/NetworkNotificationManager.h	2021-10-26 18:57:31 UTC (rev 284886)
+++ trunk/Source/WebKit/NetworkProcess/Notifications/NetworkNotificationManager.h	2021-10-26 19:34:30 UTC (rev 284887)
@@ -28,16 +28,24 @@
 #if ENABLE(BUILT_IN_NOTIFICATIONS)
 
 #include "NotificationManagerMessageHandler.h"
+#include "WebPushDaemonConnection.h"
 #include <WebCore/NotificationDirection.h>
 #include <wtf/text/WTFString.h>
 
 namespace WebKit {
 
+namespace WebPushD {
+enum class MessageType : uint8_t;
+}
+
 class NetworkSession;
 
 class NetworkNotificationManager : public NotificationManagerMessageHandler {
     WTF_MAKE_FAST_ALLOCATED;
     friend class NetworkSession;
+public:
+    NetworkSession& networkSession() const { return m_networkSession; }
+
 private:
     NetworkNotificationManager(NetworkSession&, const String& webPushMachServiceName);
 
@@ -47,6 +55,12 @@
     void didDestroyNotification(uint64_t notificationID) final;
 
     NetworkSession& m_networkSession;
+    std::unique_ptr<WebPushD::Connection> m_connection;
+
+    template<WebPushD::MessageType messageType, typename... Args>
+    void sendMessage(Args&&...) const;
+    template<WebPushD::MessageType messageType, typename... Args, typename... ReplyArgs>
+    void sendMessageWithReply(CompletionHandler<void(ReplyArgs...)>&&, Args&&...) const;
 };
 
 } // namespace WebKit

Copied: trunk/Source/WebKit/NetworkProcess/Notifications/WebPushDaemonConnection.cpp (from rev 284886, trunk/Source/WebKit/NetworkProcess/Notifications/NetworkNotificationManager.cpp) (0 => 284887)


--- trunk/Source/WebKit/NetworkProcess/Notifications/WebPushDaemonConnection.cpp	                        (rev 0)
+++ trunk/Source/WebKit/NetworkProcess/Notifications/WebPushDaemonConnection.cpp	2021-10-26 19:34:30 UTC (rev 284887)
@@ -0,0 +1,51 @@
+/*
+ * 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.
+ */
+
+#include "config.h"
+#include "WebPushDaemonConnection.h"
+
+#if ENABLE(BUILT_IN_NOTIFICATIONS)
+
+#include "DaemonDecoder.h"
+#include "DaemonEncoder.h"
+#include "NetworkSession.h"
+
+namespace WebKit::WebPushD {
+
+Connection::Connection(CString&& machServiceName, NetworkNotificationManager& manager)
+    : Daemon::ConnectionToMachService<ConnectionTraits>(WTFMove(machServiceName))
+    , m_notificationManager(manager)
+{
+    LOG(Push, "Creating WebPushD connection to mach service: %s", this->machServiceName().data());
+}
+
+NetworkSession& Connection::networkSession() const
+{
+    return m_notificationManager.networkSession();
+}
+
+} // namespace WebKit::WebPushD
+
+#endif // ENABLE(BUILT_IN_NOTIFICATIONS)

Copied: trunk/Source/WebKit/NetworkProcess/Notifications/WebPushDaemonConnection.h (from rev 284886, trunk/Source/WebKit/NetworkProcess/Notifications/NetworkNotificationManager.h) (0 => 284887)


--- trunk/Source/WebKit/NetworkProcess/Notifications/WebPushDaemonConnection.h	                        (rev 0)
+++ trunk/Source/WebKit/NetworkProcess/Notifications/WebPushDaemonConnection.h	2021-10-26 19:34:30 UTC (rev 284887)
@@ -0,0 +1,74 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#if ENABLE(BUILT_IN_NOTIFICATIONS)
+
+#include "DaemonConnection.h"
+#include "WebPushDaemonConstants.h"
+
+namespace WebKit {
+
+class NetworkNotificationManager;
+class NetworkSession;
+
+namespace WebPushD {
+
+struct ConnectionTraits {
+    using MessageType = WebPushD::MessageType;
+    static constexpr const char* protocolVersionKey { WebPushD::protocolVersionKey };
+    static constexpr uint64_t protocolVersionValue { WebPushD::protocolVersionValue };
+    static constexpr const char* protocolEncodedMessageKey { WebPushD::protocolEncodedMessageKey };
+};
+
+class Connection : public Daemon::ConnectionToMachService<ConnectionTraits> {
+    WTF_MAKE_FAST_ALLOCATED;
+public:
+    Connection(CString&& machServiceName, NetworkNotificationManager&);
+
+private:
+    void newConnectionWasInitialized() const final;
+#if PLATFORM(COCOA)
+    RetainPtr<xpc_object_t> dictionaryFromMessage(MessageType, Daemon::EncodedMessage&&) const final;
+    void connectionReceivedEvent(xpc_object_t) const final;
+#endif
+    void sendDebugModeIsEnabledMessageIfNecessary() const;
+
+    NetworkSession& networkSession() const;
+
+    NetworkNotificationManager& m_notificationManager;
+
+    template<MessageType messageType, typename... Args>
+    void sendMessage(Args&&...) const;
+    template<MessageType messageType, typename... Args, typename... ReplyArgs>
+    void sendMessageWithReply(CompletionHandler<void(ReplyArgs...)>&&, Args&&...) const;
+};
+
+} // namespace WebPushD
+} // namespace WebKit
+
+#endif // ENABLE(BUILT_IN_NOTIFICATIONS)
+

Modified: trunk/Source/WebKit/NetworkProcess/WebSocketTask.h (284886 => 284887)


--- trunk/Source/WebKit/NetworkProcess/WebSocketTask.h	2021-10-26 18:57:31 UTC (rev 284886)
+++ trunk/Source/WebKit/NetworkProcess/WebSocketTask.h	2021-10-26 19:34:30 UTC (rev 284887)
@@ -31,6 +31,8 @@
 #include "WebSocketTaskSoup.h"
 #else
 
+#include "DataReference.h"
+
 namespace WebKit {
 
 struct SessionSet;

Modified: trunk/Source/WebKit/NetworkProcess/mac/com.apple.WebKit.NetworkProcess.sb.in (284886 => 284887)


--- trunk/Source/WebKit/NetworkProcess/mac/com.apple.WebKit.NetworkProcess.sb.in	2021-10-26 18:57:31 UTC (rev 284886)
+++ trunk/Source/WebKit/NetworkProcess/mac/com.apple.WebKit.NetworkProcess.sb.in	2021-10-26 19:34:30 UTC (rev 284887)
@@ -369,6 +369,9 @@
 (allow mach-lookup (with telemetry) (global-name "com.apple.webkit.adattributiond.service"))
 (allow mach-lookup (with telemetry) (global-name "org.webkit.pcmtestdaemon.service"))
 
+(allow mach-lookup (with telemetry) (global-name "com.apple.webkit.webpushd.service"))
+(allow mach-lookup (with telemetry) (global-name "org.webkit.webpushtestdaemon.service"))
+
 (with-filter (uid 0)
     (allow mach-lookup (with telemetry)
         (global-name "com.apple.DiskArbitration.diskarbitrationd")

Modified: trunk/Source/WebKit/Platform/IPC/DaemonConnection.cpp (284886 => 284887)


--- trunk/Source/WebKit/Platform/IPC/DaemonConnection.cpp	2021-10-26 18:57:31 UTC (rev 284886)
+++ trunk/Source/WebKit/Platform/IPC/DaemonConnection.cpp	2021-10-26 19:34:30 UTC (rev 284887)
@@ -27,6 +27,7 @@
 #include "DaemonConnection.h"
 
 #include "PrivateClickMeasurementConnection.h"
+#include "WebPushDaemonConnection.h"
 
 namespace WebKit {
 
@@ -47,8 +48,12 @@
 
 template class ConnectionToMachService<PCM::ConnectionTraits>;
 
+#if ENABLE(BUILT_IN_NOTIFICATIONS)
+template class ConnectionToMachService<WebPushD::ConnectionTraits>;
 #endif
 
+#endif // !PLATFORM(COCOA)
+
 } // namespace Daemon
 
 } // namespace WebKit

Modified: trunk/Source/WebKit/Platform/IPC/DaemonConnection.h (284886 => 284887)


--- trunk/Source/WebKit/Platform/IPC/DaemonConnection.h	2021-10-26 18:57:31 UTC (rev 284886)
+++ trunk/Source/WebKit/Platform/IPC/DaemonConnection.h	2021-10-26 19:34:30 UTC (rev 284887)
@@ -71,6 +71,8 @@
     virtual void connectionReceivedEvent(xpc_object_t) const = 0;
 #endif
 
+    const CString& machServiceName() const { return m_machServiceName; }
+
 private:
     void initializeConnectionIfNeeded() const;
 

Modified: trunk/Source/WebKit/Platform/IPC/cocoa/DaemonConnectionCocoa.mm (284886 => 284887)


--- trunk/Source/WebKit/Platform/IPC/cocoa/DaemonConnectionCocoa.mm	2021-10-26 18:57:31 UTC (rev 284886)
+++ trunk/Source/WebKit/Platform/IPC/cocoa/DaemonConnectionCocoa.mm	2021-10-26 19:34:30 UTC (rev 284887)
@@ -28,6 +28,7 @@
 
 #import "DaemonEncoder.h"
 #import "PrivateClickMeasurementConnection.h"
+#import "WebPushDaemonConnection.h"
 #import <wtf/BlockPtr.h>
 #import <wtf/RunLoop.h>
 
@@ -112,6 +113,10 @@
 
 template class ConnectionToMachService<PCM::ConnectionTraits>;
 
+#if ENABLE(BUILT_IN_NOTIFICATIONS)
+template class ConnectionToMachService<WebPushD::ConnectionTraits>;
+#endif
+
 } // namespace Daemon
 
 } // namespace WebKit

Modified: trunk/Source/WebKit/Platform/Logging.h (284886 => 284887)


--- trunk/Source/WebKit/Platform/Logging.h	2021-10-26 18:57:31 UTC (rev 284886)
+++ trunk/Source/WebKit/Platform/Logging.h	2021-10-26 19:34:30 UTC (rev 284887)
@@ -87,6 +87,7 @@
     M(ProcessSuspension) \
     M(ProcessSwapping) \
     M(ProximityNetworking) \
+    M(Push) \
     M(RemoteLayerTree) \
     M(Resize) \
     M(ResourceLoadStatistics) \

Copied: trunk/Source/WebKit/Shared/WebPushDaemonConstants.h (from rev 284886, trunk/Source/WebKit/Platform/IPC/DaemonConnection.cpp) (0 => 284887)


--- trunk/Source/WebKit/Shared/WebPushDaemonConstants.h	                        (rev 0)
+++ trunk/Source/WebKit/Shared/WebPushDaemonConstants.h	2021-10-26 19:34:30 UTC (rev 284887)
@@ -0,0 +1,52 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+namespace WebKit::WebPushD {
+
+constexpr const char* protocolVersionKey = "protocol version";
+constexpr uint64_t protocolVersionValue = 1;
+constexpr const char* protocolEncodedMessageKey = "encoded message";
+
+constexpr const char* protocolDebugMessageKey { "debug message" };
+constexpr const char* protocolDebugMessageLevelKey { "debug message level" };
+
+constexpr const char* protocolMessageTypeKey { "message type" };
+enum class MessageType : uint8_t {
+    EchoTwice = 1,
+};
+
+inline bool messageTypeSendsReply(MessageType messageType)
+{
+    switch (messageType) {
+    case MessageType::EchoTwice:
+        return true;
+    }
+    ASSERT_NOT_REACHED();
+    return false;
+}
+
+} // namespace WebKit::WebPushD

Modified: trunk/Source/WebKit/Sources.txt (284886 => 284887)


--- trunk/Source/WebKit/Sources.txt	2021-10-26 18:57:31 UTC (rev 284886)
+++ trunk/Source/WebKit/Sources.txt	2021-10-26 19:34:30 UTC (rev 284887)
@@ -98,6 +98,7 @@
 NetworkProcess/IndexedDB/WebIDBServer.cpp
 
 NetworkProcess/Notifications/NetworkNotificationManager.cpp
+NetworkProcess/Notifications/WebPushDaemonConnection.cpp
 
 NetworkProcess/PrivateClickMeasurement/PrivateClickMeasurementClientImpl.cpp
 NetworkProcess/PrivateClickMeasurement/PrivateClickMeasurementDatabase.cpp

Modified: trunk/Source/WebKit/SourcesCocoa.txt (284886 => 284887)


--- trunk/Source/WebKit/SourcesCocoa.txt	2021-10-26 18:57:31 UTC (rev 284886)
+++ trunk/Source/WebKit/SourcesCocoa.txt	2021-10-26 19:34:30 UTC (rev 284887)
@@ -41,6 +41,8 @@
 NetworkProcess/EntryPoint/Cocoa/Daemon/DaemonEntryPoint.mm
 NetworkProcess/EntryPoint/Cocoa/XPCService/NetworkServiceEntryPoint.mm
 
+NetworkProcess/Notifications/Cocoa/WebPushDaemonConnectionCocoa.mm
+
 NetworkProcess/PrivateClickMeasurement/cocoa/PrivateClickMeasurementConnectionCocoa.mm
 NetworkProcess/PrivateClickMeasurement/cocoa/PrivateClickMeasurementNetworkLoaderCocoa.mm
 NetworkProcess/PrivateClickMeasurement/cocoa/PrivateClickMeasurementXPCUtilities.mm

Modified: trunk/Source/WebKit/UIProcess/WebsiteData/WebsiteDataStoreConfiguration.cpp (284886 => 284887)


--- trunk/Source/WebKit/UIProcess/WebsiteData/WebsiteDataStoreConfiguration.cpp	2021-10-26 18:57:31 UTC (rev 284886)
+++ trunk/Source/WebKit/UIProcess/WebsiteData/WebsiteDataStoreConfiguration.cpp	2021-10-26 19:34:30 UTC (rev 284887)
@@ -105,6 +105,7 @@
     copy->m_enableInAppBrowserPrivacyForTesting = this->m_enableInAppBrowserPrivacyForTesting;
     copy->m_allowsHSTSWithUntrustedRootCertificate = this->m_allowsHSTSWithUntrustedRootCertificate;
     copy->m_pcmMachServiceName = this->m_pcmMachServiceName;
+    copy->m_webPushMachServiceName = this->m_webPushMachServiceName;
 #if PLATFORM(COCOA)
     if (m_proxyConfiguration)
         copy->m_proxyConfiguration = adoptCF(CFDictionaryCreateCopy(nullptr, this->m_proxyConfiguration.get()));

Modified: trunk/Source/WebKit/WebKit.xcodeproj/project.pbxproj (284886 => 284887)


--- trunk/Source/WebKit/WebKit.xcodeproj/project.pbxproj	2021-10-26 18:57:31 UTC (rev 284886)
+++ trunk/Source/WebKit/WebKit.xcodeproj/project.pbxproj	2021-10-26 19:34:30 UTC (rev 284887)
@@ -1035,6 +1035,10 @@
 		512935D81288D19400A4B695 /* WebContextMenuItem.h in Headers */ = {isa = PBXBuildFile; fileRef = 512935D61288D19400A4B695 /* WebContextMenuItem.h */; };
 		512935E41288D97800A4B695 /* InjectedBundlePageContextMenuClient.h in Headers */ = {isa = PBXBuildFile; fileRef = 512935E21288D97800A4B695 /* InjectedBundlePageContextMenuClient.h */; };
 		5129EB1223D0DE7B00AF1CD7 /* ContentWorldShared.h in Headers */ = {isa = PBXBuildFile; fileRef = 5129EB1123D0DE7800AF1CD7 /* ContentWorldShared.h */; };
+		512CD6982721EFC800F7F8EC /* WebPushDaemonConnection.h in Headers */ = {isa = PBXBuildFile; fileRef = 512CD6972721EFC300F7F8EC /* WebPushDaemonConnection.h */; };
+		512CD69A2721F0A900F7F8EC /* WebPushDaemonConstants.h in Headers */ = {isa = PBXBuildFile; fileRef = 512CD6992721F04900F7F8EC /* WebPushDaemonConstants.h */; };
+		512CD69F2723393A00F7F8EC /* WebPushDaemon.h in Headers */ = {isa = PBXBuildFile; fileRef = 512CD69D2723393A00F7F8EC /* WebPushDaemon.h */; };
+		512CD6A02723393A00F7F8EC /* WebPushDaemon.mm in Sources */ = {isa = PBXBuildFile; fileRef = 512CD69E2723393A00F7F8EC /* WebPushDaemon.mm */; };
 		512E34E5130B4D0500ABD19A /* WKApplicationCacheManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 517A33B4130B308C00F80CB5 /* WKApplicationCacheManager.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		512ECC3527196ADB00089B66 /* PrivateClickMeasurementConnection.h in Headers */ = {isa = PBXBuildFile; fileRef = 5CB930FE26E802160032B1C0 /* PrivateClickMeasurementConnection.h */; };
 		512F589712A8838800629530 /* AuthenticationChallengeProxy.h in Headers */ = {isa = PBXBuildFile; fileRef = 512F588F12A8838800629530 /* AuthenticationChallengeProxy.h */; };
@@ -1055,12 +1059,12 @@
 		513E462D1AD837560016234A /* WKSharingServicePickerDelegate.h in Headers */ = {isa = PBXBuildFile; fileRef = 513E462B1AD837560016234A /* WKSharingServicePickerDelegate.h */; };
 		513FFB91201459C6002596EA /* WebMessagePortChannelProvider.h in Headers */ = {isa = PBXBuildFile; fileRef = 513FFB8F201459C2002596EA /* WebMessagePortChannelProvider.h */; };
 		514129941C6428BB0059E714 /* WebIDBConnectionToServer.h in Headers */ = {isa = PBXBuildFile; fileRef = 514129921C6428100059E714 /* WebIDBConnectionToServer.h */; };
+		514526ED271E1647000467B6 /* NetworkNotificationManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 514526EB271E1626000467B6 /* NetworkNotificationManager.h */; };
 		514526FF271FB7EC000467B6 /* NotificationManagerMessageHandler.h in Headers */ = {isa = PBXBuildFile; fileRef = 514526FE271FB7E8000467B6 /* NotificationManagerMessageHandler.h */; };
 		51452703271FBA3A000467B6 /* NotificationManagerMessageHandlerMessageReceiver.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 51452702271FBA36000467B6 /* NotificationManagerMessageHandlerMessageReceiver.cpp */; };
 		51452704271FBA40000467B6 /* NotificationManagerMessageHandlerMessagesReplies.h in Headers */ = {isa = PBXBuildFile; fileRef = 51452700271FBA34000467B6 /* NotificationManagerMessageHandlerMessagesReplies.h */; };
 		51452705271FBA40000467B6 /* NotificationManagerMessageHandlerMessages.h in Headers */ = {isa = PBXBuildFile; fileRef = 51452701271FBA35000467B6 /* NotificationManagerMessageHandlerMessages.h */; };
 		51452708271FBEC6000467B6 /* WebNotificationManagerMessageHandler.h in Headers */ = {isa = PBXBuildFile; fileRef = 51452707271FBEC1000467B6 /* WebNotificationManagerMessageHandler.h */; };
-		514526ED271E1647000467B6 /* NetworkNotificationManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 514526EB271E1626000467B6 /* NetworkNotificationManager.h */; };
 		51489CC32370DBFA0044E68A /* WKFindResult.h in Headers */ = {isa = PBXBuildFile; fileRef = 51489CC12370DACC0044E68A /* WKFindResult.h */; settings = {ATTRIBUTES = (Public, ); }; };
 		51489CC7237237800044E68A /* WKFindResultInternal.h in Headers */ = {isa = PBXBuildFile; fileRef = 51489CC6237237780044E68A /* WKFindResultInternal.h */; };
 		514AB9F02360D2A900EDC396 /* WKFindConfiguration.h in Headers */ = {isa = PBXBuildFile; fileRef = 514AB9EF235FA59B00EDC396 /* WKFindConfiguration.h */; settings = {ATTRIBUTES = (Public, ); }; };
@@ -4133,6 +4137,12 @@
 		512935E11288D97800A4B695 /* InjectedBundlePageContextMenuClient.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = InjectedBundlePageContextMenuClient.cpp; sourceTree = "<group>"; };
 		512935E21288D97800A4B695 /* InjectedBundlePageContextMenuClient.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = InjectedBundlePageContextMenuClient.h; sourceTree = "<group>"; };
 		5129EB1123D0DE7800AF1CD7 /* ContentWorldShared.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ContentWorldShared.h; sourceTree = "<group>"; };
+		512CD6962721EFC200F7F8EC /* WebPushDaemonConnection.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WebPushDaemonConnection.cpp; sourceTree = "<group>"; };
+		512CD6972721EFC300F7F8EC /* WebPushDaemonConnection.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebPushDaemonConnection.h; sourceTree = "<group>"; };
+		512CD6992721F04900F7F8EC /* WebPushDaemonConstants.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebPushDaemonConstants.h; sourceTree = "<group>"; };
+		512CD69C27223A0800F7F8EC /* WebPushDaemonConnectionCocoa.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = WebPushDaemonConnectionCocoa.mm; sourceTree = "<group>"; };
+		512CD69D2723393A00F7F8EC /* WebPushDaemon.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebPushDaemon.h; sourceTree = "<group>"; };
+		512CD69E2723393A00F7F8EC /* WebPushDaemon.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = WebPushDaemon.mm; sourceTree = "<group>"; };
 		512F588E12A8838800629530 /* AuthenticationChallengeProxy.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = AuthenticationChallengeProxy.cpp; sourceTree = "<group>"; };
 		512F588F12A8838800629530 /* AuthenticationChallengeProxy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AuthenticationChallengeProxy.h; sourceTree = "<group>"; };
 		512F589012A8838800629530 /* AuthenticationDecisionListener.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = AuthenticationDecisionListener.cpp; sourceTree = "<group>"; };
@@ -4167,6 +4177,8 @@
 		514129921C6428100059E714 /* WebIDBConnectionToServer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebIDBConnectionToServer.h; sourceTree = "<group>"; };
 		5143B25E1DDCDFD10014FAC6 /* _WKIconLoadingDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = _WKIconLoadingDelegate.h; sourceTree = "<group>"; };
 		5143B2611DDD0DA00014FAC6 /* APIIconLoadingClient.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = APIIconLoadingClient.h; sourceTree = "<group>"; };
+		514526EB271E1626000467B6 /* NetworkNotificationManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NetworkNotificationManager.h; sourceTree = "<group>"; };
+		514526EC271E1627000467B6 /* NetworkNotificationManager.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = NetworkNotificationManager.cpp; sourceTree = "<group>"; };
 		514526FC271FB7E8000467B6 /* NotificationManagerMessageHandler.messages.in */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = NotificationManagerMessageHandler.messages.in; sourceTree = "<group>"; };
 		514526FE271FB7E8000467B6 /* NotificationManagerMessageHandler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NotificationManagerMessageHandler.h; sourceTree = "<group>"; };
 		51452700271FBA34000467B6 /* NotificationManagerMessageHandlerMessagesReplies.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NotificationManagerMessageHandlerMessagesReplies.h; sourceTree = "<group>"; };
@@ -4174,8 +4186,6 @@
 		51452702271FBA36000467B6 /* NotificationManagerMessageHandlerMessageReceiver.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = NotificationManagerMessageHandlerMessageReceiver.cpp; sourceTree = "<group>"; };
 		51452706271FBEC1000467B6 /* WebNotificationManagerMessageHandler.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WebNotificationManagerMessageHandler.cpp; sourceTree = "<group>"; };
 		51452707271FBEC1000467B6 /* WebNotificationManagerMessageHandler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebNotificationManagerMessageHandler.h; sourceTree = "<group>"; };
-		514526EB271E1626000467B6 /* NetworkNotificationManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NetworkNotificationManager.h; sourceTree = "<group>"; };
-		514526EC271E1627000467B6 /* NetworkNotificationManager.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = NetworkNotificationManager.cpp; sourceTree = "<group>"; };
 		51489CC12370DACC0044E68A /* WKFindResult.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WKFindResult.h; sourceTree = "<group>"; };
 		51489CC22370DACC0044E68A /* WKFindResult.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = WKFindResult.mm; sourceTree = "<group>"; };
 		51489CC6237237780044E68A /* WKFindResultInternal.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WKFindResultInternal.h; sourceTree = "<group>"; };
@@ -7138,6 +7148,7 @@
 				BC306823125A6B9400E71278 /* WebProcessCreationParameters.cpp */,
 				BC306822125A6B9400E71278 /* WebProcessCreationParameters.h */,
 				467E43E72243FF6D00B13924 /* WebProcessDataStoreParameters.h */,
+				512CD6992721F04900F7F8EC /* WebPushDaemonConstants.h */,
 				5C8DD37F1FE4519200F2A556 /* WebsiteAutoplayPolicy.h */,
 				5C8DD3811FE455CA00F2A556 /* WebsiteAutoplayQuirk.h */,
 				511F7D3F1EB1BCEE00E47B83 /* WebsiteDataStoreParameters.cpp */,
@@ -9035,6 +9046,14 @@
 			path = Databases;
 			sourceTree = "<group>";
 		};
+		512CD69B272239E400F7F8EC /* Cocoa */ = {
+			isa = PBXGroup;
+			children = (
+				512CD69C27223A0800F7F8EC /* WebPushDaemonConnectionCocoa.mm */,
+			);
+			path = Cocoa;
+			sourceTree = "<group>";
+		};
 		512F588D12A8836F00629530 /* Authentication */ = {
 			isa = PBXGroup;
 			children = (
@@ -9055,8 +9074,11 @@
 		514526EA271E1610000467B6 /* Notifications */ = {
 			isa = PBXGroup;
 			children = (
+				512CD69B272239E400F7F8EC /* Cocoa */,
 				514526EC271E1627000467B6 /* NetworkNotificationManager.cpp */,
 				514526EB271E1626000467B6 /* NetworkNotificationManager.h */,
+				512CD6962721EFC200F7F8EC /* WebPushDaemonConnection.cpp */,
+				512CD6972721EFC300F7F8EC /* WebPushDaemonConnection.h */,
 			);
 			path = Notifications;
 			sourceTree = "<group>";
@@ -9578,6 +9600,8 @@
 			children = (
 				5CBB6D4D271F67CC00FD1A5D /* com.apple.webkit.webpushd.plist */,
 				5C157A0B2717CA1C00ED5280 /* WebPushDaemonMain.mm */,
+				512CD69D2723393A00F7F8EC /* WebPushDaemon.h */,
+				512CD69E2723393A00F7F8EC /* WebPushDaemon.mm */,
 			);
 			path = webpushd;
 			sourceTree = "<group>";
@@ -12100,6 +12124,7 @@
 			buildActionMask = 2147483647;
 			files = (
 				5C1579FC2717AF5000ED5280 /* DaemonUtilities.h in Headers */,
+				512CD69F2723393A00F7F8EC /* WebPushDaemon.h in Headers */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
@@ -12818,6 +12843,7 @@
 				93AB9B4E257567E20098B10E /* SpeechRecognitionRemoteRealtimeMediaSource.h in Headers */,
 				93AB9B4D257567DC0098B10E /* SpeechRecognitionRemoteRealtimeMediaSourceManager.h in Headers */,
 				93D6B772254BB5190058DD3A /* SpeechRecognitionServer.h in Headers */,
+				512CD69A2721F0A900F7F8EC /* WebPushDaemonConstants.h in Headers */,
 				93D6B784254CCD0E0058DD3A /* SpeechRecognitionServerMessages.h in Headers */,
 				93D6B785254CCD430058DD3A /* SpeechRecognitionServerMessagesReplies.h in Headers */,
 				7A3FECA221F7C09700F267CD /* StorageAccessStatus.h in Headers */,
@@ -12905,6 +12931,7 @@
 				990D39F5243BE64800199388 /* WebAutomationDOMWindowObserver.h in Headers */,
 				9955A6EC1C7980C200EB6A93 /* WebAutomationSession.h in Headers */,
 				99C3AE2D1DADA6AD00AF5C16 /* WebAutomationSessionMacros.h in Headers */,
+				512CD6982721EFC800F7F8EC /* WebPushDaemonConnection.h in Headers */,
 				1C0A19581C90068F00FE0EBB /* WebAutomationSessionMessages.h in Headers */,
 				1C0A19471C8FF1A800FE0EBB /* WebAutomationSessionProxy.h in Headers */,
 				1C0A19541C8FFDFB00FE0EBB /* WebAutomationSessionProxyMessages.h in Headers */,
@@ -14660,6 +14687,7 @@
 			isa = PBXSourcesBuildPhase;
 			buildActionMask = 2147483647;
 			files = (
+				512CD6A02723393A00F7F8EC /* WebPushDaemon.mm in Sources */,
 				5C157A012717B7FB00ED5280 /* ArgumentCoders.cpp in Sources */,
 				5C1579FF2717B6D200ED5280 /* DaemonDecoder.cpp in Sources */,
 				5C1579FE2717B6C100ED5280 /* DaemonEncoder.cpp in Sources */,

Copied: trunk/Source/WebKit/webpushd/WebPushDaemon.h (from rev 284886, trunk/Source/WebKit/Platform/IPC/DaemonConnection.cpp) (0 => 284887)


--- trunk/Source/WebKit/webpushd/WebPushDaemon.h	                        (rev 0)
+++ trunk/Source/WebKit/webpushd/WebPushDaemon.h	2021-10-26 19:34:30 UTC (rev 284887)
@@ -0,0 +1,59 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#include "WebPushDaemonConstants.h"
+#include <wtf/Forward.h>
+#include <wtf/OSObjectPtr.h>
+#include <wtf/Span.h>
+#include <wtf/spi/darwin/XPCSPI.h>
+
+using WebKit::WebPushD::MessageType;
+
+namespace WebPushD {
+
+using EncodedMessage = Vector<uint8_t>;
+
+class Daemon {
+    friend class WTF::NeverDestroyed<Daemon>;
+public:
+    static Daemon& singleton();
+
+    void connectionEventHandler(xpc_object_t);
+    void connectionAdded(xpc_connection_t);
+    void connectionRemoved(xpc_connection_t);
+
+    // Message handlers
+    void echoTwice(const String&, CompletionHandler<void(const String&)>&& replySender);
+
+private:
+    Daemon() = default;
+
+    CompletionHandler<void(EncodedMessage&&)> createReplySender(MessageType, OSObjectPtr<xpc_object_t>&& request);
+    void decodeAndHandleMessage(MessageType, Span<const uint8_t> encodedMessage, CompletionHandler<void(EncodedMessage&&)>&&);
+};
+
+} // namespace WebPushD

Copied: trunk/Source/WebKit/webpushd/WebPushDaemon.mm (from rev 284886, trunk/Source/WebKit/webpushd/WebPushDaemonMain.mm) (0 => 284887)


--- trunk/Source/WebKit/webpushd/WebPushDaemon.mm	                        (rev 0)
+++ trunk/Source/WebKit/webpushd/WebPushDaemon.mm	2021-10-26 19:34:30 UTC (rev 284887)
@@ -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 "WebPushDaemon.h"
+
+#import "DaemonDecoder.h"
+#import "DaemonEncoder.h"
+#import "DaemonUtilities.h"
+#import "HandleMessage.h"
+#import "WebPushDaemonConstants.h"
+
+#import <wtf/CompletionHandler.h>
+#import <wtf/NeverDestroyed.h>
+#import <wtf/Span.h>
+
+using namespace WebKit::WebPushD;
+
+namespace WebPushD {
+
+namespace MessageInfo {
+
+#define FUNCTION(mf) struct mf { static constexpr auto MemberFunction = &WebPushD::Daemon::mf;
+#define ARGUMENTS(...) using ArgsTuple = std::tuple<__VA_ARGS__>;
+#define REPLY(...) using Reply = CompletionHandler<void(__VA_ARGS__)>; \
+    static WebPushD::EncodedMessage encodeReply(__VA_ARGS__);
+#define END };
+
+FUNCTION(echoTwice)
+ARGUMENTS(String)
+REPLY(String)
+END
+
+#undef FUNCTION
+#undef ARGUMENTS
+#undef REPLY
+#undef END
+
+WebPushD::EncodedMessage echoTwice::encodeReply(String reply)
+{
+    WebKit::Daemon::Encoder encoder;
+    encoder << reply;
+    return encoder.takeBuffer();
+}
+
+} // namespace MessageInfo
+
+template<typename Info>
+void handleWebPushDMessageWithReply(Span<const uint8_t> encodedMessage, CompletionHandler<void(WebPushD::EncodedMessage&&)>&& replySender)
+{
+    WebKit::Daemon::Decoder decoder(encodedMessage);
+
+    std::optional<typename Info::ArgsTuple> arguments;
+    decoder >> arguments;
+    if (UNLIKELY(!arguments))
+        return;
+
+    typename Info::Reply completionHandler { [replySender = WTFMove(replySender)] (auto&&... args) mutable {
+        replySender(Info::encodeReply(args...));
+    } };
+
+    IPC::callMemberFunction(WTFMove(*arguments), WTFMove(completionHandler), &WebPushD::Daemon::singleton(), Info::MemberFunction);
+}
+
+Daemon& Daemon::singleton()
+{
+    static NeverDestroyed<Daemon> daemon;
+    return daemon;
+}
+
+void Daemon::connectionEventHandler(xpc_object_t request)
+{
+    if (xpc_get_type(request) != XPC_TYPE_DICTIONARY)
+        return;
+    
+    if (xpc_dictionary_get_uint64(request, protocolVersionKey) != protocolVersionValue) {
+        NSLog(@"Received request that was not the current protocol version");
+        // FIXME: Cut off this connection
+        return;
+    }
+
+    auto messageType { static_cast<MessageType>(xpc_dictionary_get_uint64(request, protocolMessageTypeKey)) };
+    size_t dataSize { 0 };
+    const void* data = "" protocolEncodedMessageKey, &dataSize);
+    Span<const uint8_t> encodedMessage { static_cast<const uint8_t*>(data), dataSize };
+    
+    decodeAndHandleMessage(messageType, encodedMessage, createReplySender(messageType, request));
+}
+
+void Daemon::connectionAdded(xpc_connection_t)
+{
+    // FIXME: Track connections
+}
+
+void Daemon::connectionRemoved(xpc_connection_t)
+{
+    // FIXME: Track connections
+}
+
+CompletionHandler<void(EncodedMessage&&)> Daemon::createReplySender(MessageType messageType, OSObjectPtr<xpc_object_t>&& request)
+{
+    if (!messageTypeSendsReply(messageType))
+        return nullptr;
+
+    return [request = WTFMove(request)] (EncodedMessage&& message) {
+        auto reply = adoptNS(xpc_dictionary_create_reply(request.get()));
+        ASSERT(xpc_get_type(reply.get()) == XPC_TYPE_DICTIONARY);
+        xpc_dictionary_set_uint64(reply.get(), protocolVersionKey, protocolVersionValue);
+        xpc_dictionary_set_value(reply.get(), protocolEncodedMessageKey, WebKit::vectorToXPCData(WTFMove(message)).get());
+        xpc_connection_send_message(xpc_dictionary_get_remote_connection(request.get()), reply.get());
+    };
+}
+
+void Daemon::decodeAndHandleMessage(MessageType messageType, Span<const uint8_t> encodedMessage, CompletionHandler<void(EncodedMessage&&)>&& replySender)
+{
+    ASSERT(messageTypeSendsReply(messageType) == !!replySender);
+
+    switch (messageType) {
+    case MessageType::EchoTwice:
+        handleWebPushDMessageWithReply<MessageInfo::echoTwice>(encodedMessage, WTFMove(replySender));
+        break;
+    }
+}
+
+void Daemon::echoTwice(const String& message, CompletionHandler<void(const String&)>&& replySender)
+{
+    replySender(makeString(message, message));
+}
+
+} // namespace WebPushD

Modified: trunk/Source/WebKit/webpushd/WebPushDaemonMain.mm (284886 => 284887)


--- trunk/Source/WebKit/webpushd/WebPushDaemonMain.mm	2021-10-26 18:57:31 UTC (rev 284886)
+++ trunk/Source/WebKit/webpushd/WebPushDaemonMain.mm	2021-10-26 19:34:30 UTC (rev 284887)
@@ -28,77 +28,29 @@
 #import "DaemonDecoder.h"
 #import "DaemonEncoder.h"
 #import "DaemonUtilities.h"
+#import "WebPushDaemon.h"
 #import <Foundation/Foundation.h>
 #import <wtf/MainThread.h>
-#import <wtf/Span.h>
 #import <wtf/spi/darwin/XPCSPI.h>
 
+using WebKit::Daemon::EncodedMessage;
+using WebPushD::Daemon;
+
 namespace WebPushD {
 
-constexpr const char* protocolVersionKey = "protocol version";
-constexpr uint64_t protocolVersionValue = 1;
-constexpr const char* protocolMessageTypeKey = "message type";
-constexpr const char* protocolEncodedMessageKey = "encoded message";
-enum class MessageType : uint8_t {
-    EchoTwice = 1
-};
-
-static CompletionHandler<void(Vector<uint8_t>&&)> replySender(RetainPtr<xpc_object_t>&& request)
-{
-    return [request = WTFMove(request)] (Vector<uint8_t>&& message) {
-        auto reply = adoptNS(xpc_dictionary_create_reply(request.get()));
-        ASSERT(xpc_get_type(reply.get()) == XPC_TYPE_DICTIONARY);
-        xpc_dictionary_set_uint64(reply.get(), protocolVersionKey, protocolVersionValue);
-        xpc_dictionary_set_value(reply.get(), protocolEncodedMessageKey, WebKit::vectorToXPCData(WTFMove(message)).get());
-        xpc_connection_send_message(xpc_dictionary_get_remote_connection(request.get()), reply.get());
-    };
-}
-
-static void echoTwice(Span<const uint8_t> encodedMessage, CompletionHandler<void(Vector<uint8_t>&&)>&& replySender)
-{
-    WebKit::Daemon::Decoder decoder(encodedMessage);
-    std::optional<String> string;
-    decoder >> string;
-    if (!string)
-        return;
-
-    auto reply = makeString(*string, *string);
-    WebKit::Daemon::Encoder encoder;
-    encoder << reply;
-    replySender(encoder.takeBuffer());
-}
-
-static void decodeMessageAndSendReply(MessageType messageType, Span<const uint8_t> encodedMessage, CompletionHandler<void(Vector<uint8_t>&&)>&& replySender)
-{
-    switch (messageType) {
-    case MessageType::EchoTwice:
-        echoTwice(encodedMessage, WTFMove(replySender));
-        return;
-    }
-}
-
 static void connectionEventHandler(xpc_object_t request)
 {
-    if (xpc_get_type(request) != XPC_TYPE_DICTIONARY)
-        return;
-    if (xpc_dictionary_get_uint64(request, protocolVersionKey) != protocolVersionValue) {
-        NSLog(@"Received request that was not the current protocol version");
-        return;
-    }
-
-    auto messageType { static_cast<MessageType>(xpc_dictionary_get_uint64(request, protocolMessageTypeKey)) };
-    size_t dataSize { 0 };
-    const void* data = "" protocolEncodedMessageKey, &dataSize);
-    Span<const uint8_t> encodedMessage { static_cast<const uint8_t*>(data), dataSize };
-    decodeMessageAndSendReply(messageType, encodedMessage, replySender(request));
+    Daemon::singleton().connectionEventHandler(request);
 }
 
-static void connectionAdded(xpc_connection_t)
+static void connectionAdded(xpc_connection_t connection)
 {
+    Daemon::singleton().connectionAdded(connection);
 }
 
-static void connectionRemoved(xpc_connection_t)
+static void connectionRemoved(xpc_connection_t connection)
 {
+    Daemon::singleton().connectionRemoved(connection);
 }
 
 } // namespace WebPushD

Modified: trunk/Tools/ChangeLog (284886 => 284887)


--- trunk/Tools/ChangeLog	2021-10-26 18:57:31 UTC (rev 284886)
+++ trunk/Tools/ChangeLog	2021-10-26 19:34:30 UTC (rev 284887)
@@ -1,3 +1,15 @@
+2021-10-26  Brady Eidson  <beid...@apple.com>
+
+        Add helper classes and messaging infrastructure to launch webpushd and round trip a message to it
+        https://bugs.webkit.org/show_bug.cgi?id=232262
+
+        Reviewed by Alex Christensen.
+
+        * MiniBrowser/mac/AppDelegate.m:
+        (persistentDataStore):
+        * MiniBrowser/mac/WK2BrowserWindowController.m:
+        (-[WK2BrowserWindowController _webView:requestNotificationPermissionForSecurityOrigin:decisionHandler:]):
+
 2021-10-26  Simon Fraser  <simon.fra...@apple.com>
 
         The script should decide when an image diff cases, not ImageDiff

Modified: trunk/Tools/MiniBrowser/mac/AppDelegate.m (284886 => 284887)


--- trunk/Tools/MiniBrowser/mac/AppDelegate.m	2021-10-26 18:57:31 UTC (rev 284886)
+++ trunk/Tools/MiniBrowser/mac/AppDelegate.m	2021-10-26 19:34:30 UTC (rev 284887)
@@ -98,6 +98,11 @@
     if (!dataStore) {
         _WKWebsiteDataStoreConfiguration *configuration = [[[_WKWebsiteDataStoreConfiguration alloc] init] autorelease];
         configuration.networkCacheSpeculativeValidationEnabled = YES;
+
+        // FIXME: When built-in notifications are enabled, WebKit doesn't yet gracefully handle a missing webpushd service
+        // Until it does, uncomment this line when the service is known to be installed.
+        // [configuration setWebPushMachServiceName:@"org.webkit.webpushtestdaemon.service"];
+
         dataStore = [[WKWebsiteDataStore alloc] _initWithConfiguration:configuration];
     }
     

Modified: trunk/Tools/MiniBrowser/mac/WK2BrowserWindowController.m (284886 => 284887)


--- trunk/Tools/MiniBrowser/mac/WK2BrowserWindowController.m	2021-10-26 18:57:31 UTC (rev 284886)
+++ trunk/Tools/MiniBrowser/mac/WK2BrowserWindowController.m	2021-10-26 19:34:30 UTC (rev 284887)
@@ -212,6 +212,14 @@
     return 1;
 }
 
+- (void)_webView:(WKWebView *)webView requestNotificationPermissionForSecurityOrigin:(WKSecurityOrigin *)securityOrigin decisionHandler:(void (^)(BOOL))decisionHandler
+{
+    // For testing, grant notification permission to all origins.
+    // FIXME: Consider adding a dialog and in-memory permissions manager
+    NSLog(@"Granting notifications permission to origin %@", securityOrigin);
+    decisionHandler(YES);
+}
+
 - (IBAction)setViewScale:(id)sender
 {
     CGFloat scale = [self viewScaleForMenuItemTag:[sender tag]];
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to