From 9f0d6c1f3935637aa86546cc0643676f0b34af41 Mon Sep 17 00:00:00 2001 From: Sihui Liu Date: Thu, 5 Sep 2024 10:14:10 -0700 Subject: [PATCH] Add SPI for connecting to webpushd https://bugs.webkit.org/show_bug.cgi?id=279142 rdar://135297138 Reviewed by Ben Nham. This will make it easier to test webpushd functionalities. Tests: WebPushD.WKWebPushDaemonConnectionRequestPushPermission WebPushD.WKWebPushDaemonConnectionPushSubscription * Source/WebKit/Shared/API/APIObject.h: * Source/WebKit/Shared/API/Cocoa/WebKitPrivate.h: * Source/WebKit/Shared/Cocoa/APIObject.mm: (API::Object::newObject): * Source/WebKit/Sources.txt: * Source/WebKit/SourcesCocoa.txt: * Source/WebKit/UIProcess/API/APIWebPushDaemonConnection.cpp: Added. (API::WebPushDaemonConnection::WebPushDaemonConnection): (API::WebPushDaemonConnection::getPushPermissionState): (API::WebPushDaemonConnection::requestPushPermission): (API::WebPushDaemonConnection::setAppBadge): (API::WebPushDaemonConnection::subscribeToPushService): (API::WebPushDaemonConnection::unsubscribeFromPushService): (API::WebPushDaemonConnection::getPushSubscription): (API::WebPushDaemonConnection::getNextPendingPushMessage): * Source/WebKit/UIProcess/API/APIWebPushDaemonConnection.h: Added. * Source/WebKit/UIProcess/API/APIWebPushMessage.h: Copied from Source/WebKit/Shared/API/Cocoa/WebKitPrivate.h. * Source/WebKit/UIProcess/API/APIWebPushSubscriptionData.h: Copied from Source/WebKit/Shared/API/Cocoa/WebKitPrivate.h. * Source/WebKit/UIProcess/API/Cocoa/_WKWebPushDaemonConnection.h: Added. * Source/WebKit/UIProcess/API/Cocoa/_WKWebPushDaemonConnection.mm: Added. (-[_WKWebPushDaemonConnectionConfiguration init]): (-[_WKWebPushDaemonConnection initWithConfiguration:]): (toWKPermissionsState): (-[_WKWebPushDaemonConnection getPushPermissionStateForOrigin:completionHandler:]): (-[_WKWebPushDaemonConnection requestPushPermissionForOrigin:completionHandler:]): (-[_WKWebPushDaemonConnection setAppBadge:origin:]): (-[_WKWebPushDaemonConnection subscribeToPushServiceForScope:applicationServerKey:completionHandler:]): (-[_WKWebPushDaemonConnection unsubscribeFromPushServiceForScope:completionHandler:]): (-[_WKWebPushDaemonConnection getSubscriptionForScope:completionHandler:]): (-[_WKWebPushDaemonConnection getNextPendingPushMessage:]): (-[_WKWebPushDaemonConnection _apiObject]): * Source/WebKit/UIProcess/API/Cocoa/_WKWebPushDaemonConnectionInternal.h: Copied from Source/WebKit/Shared/API/Cocoa/WebKitPrivate.h. * Source/WebKit/UIProcess/API/Cocoa/_WKWebPushMessage.h: Copied from Source/WebKit/Shared/API/Cocoa/WebKitPrivate.h. * Source/WebKit/UIProcess/API/Cocoa/_WKWebPushMessage.mm: Copied from Source/WebKit/Shared/API/Cocoa/WebKitPrivate.h. (-[_WKWebPushMessage dealloc]): (-[_WKWebPushMessage data]): (-[_WKWebPushMessage scope]): (-[_WKWebPushMessage partition]): (-[_WKWebPushMessage _apiObject]): * Source/WebKit/UIProcess/API/Cocoa/_WKWebPushMessageInternal.h: Copied from Source/WebKit/Shared/API/Cocoa/WebKitPrivate.h. * Source/WebKit/UIProcess/API/Cocoa/_WKWebPushSubscriptionData.h: Copied from Source/WebKit/Shared/API/Cocoa/WebKitPrivate.h. * Source/WebKit/UIProcess/API/Cocoa/_WKWebPushSubscriptionData.mm: Copied from Source/WebKit/Shared/API/Cocoa/WebKitPrivate.h. (-[_WKWebPushSubscriptionData dealloc]): (-[_WKWebPushSubscriptionData endpoint]): (-[_WKWebPushSubscriptionData applicationServerKey]): (-[_WKWebPushSubscriptionData authenticationSecret]): (-[_WKWebPushSubscriptionData ecdhPublicKey]): (-[_WKWebPushSubscriptionData _apiObject]): * Source/WebKit/UIProcess/API/Cocoa/_WKWebPushSubscriptionDataInternal.h: Copied from Source/WebKit/Shared/API/Cocoa/WebKitPrivate.h. * Source/WebKit/UIProcess/API/ios/WKWebViewTestingIOS.mm: * Source/WebKit/WebKit.xcodeproj/project.pbxproj: * Tools/TestWebKitAPI/Tests/WebKitCocoa/WebPushDaemon.mm: (TestWebKitAPI::(WebPushD, WKWebPushDaemonConnectionRequestPushPermission)): (TestWebKitAPI::(WebPushD, WKWebPushDaemonConnectionPushSubscription)): Canonical link: https://commits.webkit.org/283218@main --- Source/WebKit/Shared/API/APIObject.h | 3 + .../WebKit/Shared/API/Cocoa/WebKitPrivate.h | 3 + Source/WebKit/Shared/Cocoa/APIObject.mm | 15 ++ Source/WebKit/Sources.txt | 1 + Source/WebKit/SourcesCocoa.txt | 3 + .../API/APIWebPushDaemonConnection.cpp | 106 ++++++++++++ .../API/APIWebPushDaemonConnection.h | 64 +++++++ .../WebKit/UIProcess/API/APIWebPushMessage.h | 51 ++++++ .../API/APIWebPushSubscriptionData.h | 52 ++++++ .../API/Cocoa/_WKWebPushDaemonConnection.h | 67 ++++++++ .../API/Cocoa/_WKWebPushDaemonConnection.mm | 158 ++++++++++++++++++ .../_WKWebPushDaemonConnectionInternal.h | 42 +++++ .../UIProcess/API/Cocoa/_WKWebPushMessage.h | 42 +++++ .../UIProcess/API/Cocoa/_WKWebPushMessage.mm | 67 ++++++++ .../API/Cocoa/_WKWebPushMessageInternal.h | 42 +++++ .../API/Cocoa/_WKWebPushSubscriptionData.h | 43 +++++ .../API/Cocoa/_WKWebPushSubscriptionData.mm | 65 +++++++ .../_WKWebPushSubscriptionDataInternal.h | 42 +++++ .../UIProcess/API/ios/WKWebViewTestingIOS.mm | 1 + .../WebKit/WebKit.xcodeproj/project.pbxproj | 32 ++++ .../Tests/WebKitCocoa/WebPushDaemon.mm | 84 ++++++++++ 21 files changed, 983 insertions(+) create mode 100644 Source/WebKit/UIProcess/API/APIWebPushDaemonConnection.cpp create mode 100644 Source/WebKit/UIProcess/API/APIWebPushDaemonConnection.h create mode 100644 Source/WebKit/UIProcess/API/APIWebPushMessage.h create mode 100644 Source/WebKit/UIProcess/API/APIWebPushSubscriptionData.h create mode 100644 Source/WebKit/UIProcess/API/Cocoa/_WKWebPushDaemonConnection.h create mode 100644 Source/WebKit/UIProcess/API/Cocoa/_WKWebPushDaemonConnection.mm create mode 100644 Source/WebKit/UIProcess/API/Cocoa/_WKWebPushDaemonConnectionInternal.h create mode 100644 Source/WebKit/UIProcess/API/Cocoa/_WKWebPushMessage.h create mode 100644 Source/WebKit/UIProcess/API/Cocoa/_WKWebPushMessage.mm create mode 100644 Source/WebKit/UIProcess/API/Cocoa/_WKWebPushMessageInternal.h create mode 100644 Source/WebKit/UIProcess/API/Cocoa/_WKWebPushSubscriptionData.h create mode 100644 Source/WebKit/UIProcess/API/Cocoa/_WKWebPushSubscriptionData.mm create mode 100644 Source/WebKit/UIProcess/API/Cocoa/_WKWebPushSubscriptionDataInternal.h diff --git a/Source/WebKit/Shared/API/APIObject.h b/Source/WebKit/Shared/API/APIObject.h index b210c8cbe5906..4cdce82b6194e 100644 --- a/Source/WebKit/Shared/API/APIObject.h +++ b/Source/WebKit/Shared/API/APIObject.h @@ -190,6 +190,9 @@ class Object #endif #endif WebResourceLoadStatisticsManager, + WebPushDaemonConnection, + WebPushMessage, + WebPushSubscriptionData, WebsiteDataRecord, WebsiteDataStore, WebsiteDataStoreConfiguration, diff --git a/Source/WebKit/Shared/API/Cocoa/WebKitPrivate.h b/Source/WebKit/Shared/API/Cocoa/WebKitPrivate.h index a16bb3462ce6e..9ffb71b38db7c 100644 --- a/Source/WebKit/Shared/API/Cocoa/WebKitPrivate.h +++ b/Source/WebKit/Shared/API/Cocoa/WebKitPrivate.h @@ -43,3 +43,6 @@ #import #import #import +#import +#import +#import diff --git a/Source/WebKit/Shared/Cocoa/APIObject.mm b/Source/WebKit/Shared/Cocoa/APIObject.mm index dcda0ef23dc35..2649d70d112d5 100644 --- a/Source/WebKit/Shared/Cocoa/APIObject.mm +++ b/Source/WebKit/Shared/Cocoa/APIObject.mm @@ -96,6 +96,9 @@ #import "_WKVisitedLinkStoreInternal.h" #import "_WKWebAuthenticationAssertionResponseInternal.h" #import "_WKWebAuthenticationPanelInternal.h" +#import "_WKWebPushDaemonConnectionInternal.h" +#import "_WKWebPushMessageInternal.h" +#import "_WKWebPushSubscriptionDataInternal.h" #import "_WKWebsiteDataStoreConfigurationInternal.h" #if ENABLE(INSPECTOR_EXTENSIONS) @@ -446,6 +449,18 @@ #endif #endif // ENABLE(WK_WEB_EXTENSIONS) + case Type::WebPushDaemonConnection: + wrapper = [_WKWebPushDaemonConnection alloc]; + break; + + case Type::WebPushMessage: + wrapper = [_WKWebPushMessage alloc]; + break; + + case Type::WebPushSubscriptionData: + wrapper = [_WKWebPushSubscriptionData alloc]; + break; + case Type::WebsiteDataRecord: wrapper = [WKWebsiteDataRecord alloc]; break; diff --git a/Source/WebKit/Sources.txt b/Source/WebKit/Sources.txt index 540a53072d0ba..7e97dd2aa22ec 100644 --- a/Source/WebKit/Sources.txt +++ b/Source/WebKit/Sources.txt @@ -482,6 +482,7 @@ UIProcess/API/APIUserScript.cpp UIProcess/API/APIUserStyleSheet.cpp UIProcess/API/APIWebAuthenticationAssertionResponse.cpp UIProcess/API/APIWebAuthenticationPanel.cpp +UIProcess/API/APIWebPushDaemonConnection.cpp UIProcess/API/APIWebsitePolicies.cpp UIProcess/API/APIWindowFeatures.cpp diff --git a/Source/WebKit/SourcesCocoa.txt b/Source/WebKit/SourcesCocoa.txt index cafd3d9660fbf..42e072a017482 100644 --- a/Source/WebKit/SourcesCocoa.txt +++ b/Source/WebKit/SourcesCocoa.txt @@ -310,6 +310,9 @@ UIProcess/API/Cocoa/_WKUserStyleSheet.mm UIProcess/API/Cocoa/_WKVisitedLinkStore.mm UIProcess/API/Cocoa/_WKWebAuthenticationAssertionResponse.mm UIProcess/API/Cocoa/_WKWebAuthenticationPanel.mm +UIProcess/API/Cocoa/_WKWebPushDaemonConnection.mm +UIProcess/API/Cocoa/_WKWebPushMessage.mm +UIProcess/API/Cocoa/_WKWebPushSubscriptionData.mm UIProcess/API/Cocoa/_WKWebExtension.mm UIProcess/API/Cocoa/_WKWebPushAction.mm UIProcess/API/Cocoa/_WKWebsiteDataSize.mm diff --git a/Source/WebKit/UIProcess/API/APIWebPushDaemonConnection.cpp b/Source/WebKit/UIProcess/API/APIWebPushDaemonConnection.cpp new file mode 100644 index 0000000000000..69318a452b75f --- /dev/null +++ b/Source/WebKit/UIProcess/API/APIWebPushDaemonConnection.cpp @@ -0,0 +1,106 @@ +/* + * Copyright (C) 2024 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 "APIWebPushDaemonConnection.h" + +#include "MessageSenderInlines.h" +#include "PushClientConnectionMessages.h" +#include "WebPushMessage.h" +#include +#include +#include + +namespace API { + +WebPushDaemonConnection::WebPushDaemonConnection(const WTF::String& machServiceName, const WTF::String& partition, const WTF::String& bundleIdentifier) +#if ENABLE(WEB_PUSH_NOTIFICATIONS) + : m_connection(makeUniqueRef(machServiceName.utf8(), WebKit::WebPushD::WebPushDaemonConnectionConfiguration { { }, bundleIdentifier, partition, { } })) +#endif +{ +} + +void WebPushDaemonConnection::getPushPermissionState(const WTF::URL& scopeURL, CompletionHandler&& completionHandler) +{ +#if ENABLE(WEB_PUSH_NOTIFICATIONS) + m_connection->sendWithAsyncReplyWithoutUsingIPCConnection(Messages::PushClientConnection::GetPushPermissionState(SecurityOriginData::fromURL(scopeURL)), WTFMove(completionHandler)); +#else + completionHandler(WebCore::PushPermissionState::Denied); +#endif +} + +void WebPushDaemonConnection::requestPushPermission(const WTF::URL& scopeURL, CompletionHandler&& completionHandler) +{ +#if ENABLE(WEB_PUSH_NOTIFICATIONS) + m_connection->sendWithAsyncReplyWithoutUsingIPCConnection(Messages::PushClientConnection::RequestPushPermission(SecurityOriginData::fromURL(scopeURL)), WTFMove(completionHandler)); +#else + completionHandler(false); +#endif +} + +void WebPushDaemonConnection::setAppBadge(const WTF::URL& scopeURL, std::optional badge) +{ +#if ENABLE(WEB_PUSH_NOTIFICATIONS) + m_connection->sendWithoutUsingIPCConnection(Messages::PushClientConnection::SetAppBadge(SecurityOriginData::fromURL(scopeURL), badge)); +#endif +} + +void WebPushDaemonConnection::subscribeToPushService(const WTF::URL& scopeURL, const Vector& applicationServerKey, CompletionHandler&)>&& completionHandler) +{ +#if ENABLE(WEB_PUSH_NOTIFICATIONS) + m_connection->sendWithAsyncReplyWithoutUsingIPCConnection(Messages::PushClientConnection::SubscribeToPushService(scopeURL, applicationServerKey), WTFMove(completionHandler)); +#else + completionHandler(makeUnexpected(WebCore::ExceptionData { WebCore::ExceptionCode::UnknownError, "Cannot subscribe to push service"_s })); +#endif +} + +void WebPushDaemonConnection::unsubscribeFromPushService(const WTF::URL& scopeURL, CompletionHandler&)>&& completionHandler) +{ +#if ENABLE(WEB_PUSH_NOTIFICATIONS) + m_connection->sendWithAsyncReplyWithoutUsingIPCConnection(Messages::PushClientConnection::UnsubscribeFromPushService(scopeURL, std::nullopt), WTFMove(completionHandler)); +#else + completionHandler(false); +#endif +} + +void WebPushDaemonConnection::getPushSubscription(const WTF::URL& scopeURL, CompletionHandler, WebCore::ExceptionData>&)>&& completionHandler) +{ +#if ENABLE(WEB_PUSH_NOTIFICATIONS) + m_connection->sendWithAsyncReplyWithoutUsingIPCConnection(Messages::PushClientConnection::GetPushSubscription(WTFMove(scopeURL)), WTFMove(completionHandler)); +#else + completionHandler(std::optional { }); +#endif +} + +void WebPushDaemonConnection::getNextPendingPushMessage(CompletionHandler&)>&& completionHandler) +{ +#if ENABLE(WEB_PUSH_NOTIFICATIONS) + m_connection->sendWithAsyncReplyWithoutUsingIPCConnection(Messages::PushClientConnection::GetPendingPushMessage(), WTFMove(completionHandler)); +#else + completionHandler(std::nullopt); +#endif +} + +}; diff --git a/Source/WebKit/UIProcess/API/APIWebPushDaemonConnection.h b/Source/WebKit/UIProcess/API/APIWebPushDaemonConnection.h new file mode 100644 index 0000000000000..abf704a09a2b4 --- /dev/null +++ b/Source/WebKit/UIProcess/API/APIWebPushDaemonConnection.h @@ -0,0 +1,64 @@ +/* + * Copyright (C) 2024 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 "APIObject.h" +#include "WebPushDaemonConnection.h" + +namespace WebCore { +enum class PushPermissionState : uint8_t; +struct ExceptionData; +struct PushSubscriptionData; +} + +namespace WebKit { +namespace WebPushD { +class Connection; +} +struct WebPushMessage; +} + +namespace API { + +class WebPushDaemonConnection final : public ObjectImpl { +public: + WebPushDaemonConnection(const WTF::String& machServiceName, const WTF::String& partition, const WTF::String& bundleIdentifier); + + void getPushPermissionState(const WTF::URL&, CompletionHandler&&); + void requestPushPermission(const WTF::URL&, CompletionHandler&&); + void setAppBadge(const WTF::URL&, std::optional); + void subscribeToPushService(const WTF::URL&, const Vector& applicationServerKey, CompletionHandler&)>&&); + void unsubscribeFromPushService(const WTF::URL&, CompletionHandler&)>&&); + void getPushSubscription(const WTF::URL&, CompletionHandler, WebCore::ExceptionData>&)>&&); + void getNextPendingPushMessage(CompletionHandler&)>&&); + +private: +#if ENABLE(WEB_PUSH_NOTIFICATIONS) + UniqueRef m_connection; +#endif +}; + +} // namespace API diff --git a/Source/WebKit/UIProcess/API/APIWebPushMessage.h b/Source/WebKit/UIProcess/API/APIWebPushMessage.h new file mode 100644 index 0000000000000..6699c64cb53c5 --- /dev/null +++ b/Source/WebKit/UIProcess/API/APIWebPushMessage.h @@ -0,0 +1,51 @@ +/* + * Copyright (C) 2024 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 "APIObject.h" +#include "WebPushMessage.h" + +namespace API { + +class WebPushMessage final : public ObjectImpl { +public: + static Ref create(WebKit::WebPushMessage&& message) + { + return adoptRef(*new WebPushMessage(WTFMove(message))); + } + + explicit WebPushMessage(WebKit::WebPushMessage&& message) + : m_message(WTFMove(message)) { } + + std::optional> data() const { return m_message.pushData; }; + WTF::URL scope() const { return m_message.registrationURL; } + WTF::String partition() const { return m_message.pushPartitionString; } + +private: + WebKit::WebPushMessage m_message; +}; + +} // namespace API diff --git a/Source/WebKit/UIProcess/API/APIWebPushSubscriptionData.h b/Source/WebKit/UIProcess/API/APIWebPushSubscriptionData.h new file mode 100644 index 0000000000000..b3dcf52750834 --- /dev/null +++ b/Source/WebKit/UIProcess/API/APIWebPushSubscriptionData.h @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2024 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 "APIObject.h" +#include + +namespace API { + +class WebPushSubscriptionData final : public ObjectImpl { +public: + static Ref create(WebCore::PushSubscriptionData&& data) + { + return adoptRef(*new WebPushSubscriptionData(WTFMove(data))); + } + + explicit WebPushSubscriptionData(WebCore::PushSubscriptionData&& data) + : m_data(WTFMove(data)) { } + + WTF::URL endpoint() const { return WTF::URL { m_data.endpoint }; } + Vector applicationServerKey() const { return m_data.serverVAPIDPublicKey; } + Vector clientECDHPublicKey() const { return m_data.clientECDHPublicKey; } + Vector sharedAuthenticationSecret() const { return m_data.sharedAuthenticationSecret; } + +private: + const WebCore::PushSubscriptionData m_data; +}; + +} // namespace API diff --git a/Source/WebKit/UIProcess/API/Cocoa/_WKWebPushDaemonConnection.h b/Source/WebKit/UIProcess/API/Cocoa/_WKWebPushDaemonConnection.h new file mode 100644 index 0000000000000..861598fdb3809 --- /dev/null +++ b/Source/WebKit/UIProcess/API/Cocoa/_WKWebPushDaemonConnection.h @@ -0,0 +1,67 @@ +/* + * Copyright (C) 2024 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 + +typedef NS_ENUM(NSInteger, _WKWebPushPermissionState) { + _WKWebPushPermissionStateDenied, + _WKWebPushPermissionStateGranted, + _WKWebPushPermissionStatePrompt, +}; + +@class _WKWebPushMessage; +@class _WKWebPushSubscriptionData; + +NS_ASSUME_NONNULL_BEGIN + +WK_EXTERN +@interface _WKWebPushDaemonConnectionConfiguration : NSObject + +- (instancetype)init; +@property (nonatomic, copy) NSString *machServiceName; +@property (nonatomic, copy) NSString *partition; +@property (nonatomic, copy) NSString *bundleIdentifier; + +@end + +WK_EXTERN +@interface _WKWebPushDaemonConnection : NSObject + ++ (instancetype)new NS_UNAVAILABLE; +- (instancetype)init NS_UNAVAILABLE; +- (instancetype)initWithConfiguration:(_WKWebPushDaemonConnectionConfiguration *)configuration; + +- (void)getPushPermissionStateForOrigin:(NSURL *)origin completionHandler:(void (^)(_WKWebPushPermissionState))completionHandler; +- (void)requestPushPermissionForOrigin:(NSURL *)origin completionHandler:(void (^)(BOOL))completionHandler; +- (void)setAppBadge:(NSUInteger *)badge origin:(NSURL *)origin; +- (void)subscribeToPushServiceForScope:(NSURL *)scopeURL applicationServerKey:(NSData *)key completionHandler:(void (^)(_WKWebPushSubscriptionData *, NSError *))completionHandler; +- (void)unsubscribeFromPushServiceForScope:(NSURL *)scopeURL completionHandler:(void (^)(BOOL unsubscribed, NSError *))completionHandler; +- (void)getSubscriptionForScope:(NSURL *)scopeURL completionHandler:(void (^)(_WKWebPushSubscriptionData *, NSError *))completionHandler; +- (void)getNextPendingPushMessage:(void (^)(_WKWebPushMessage *))completionHandler; + +@end + +NS_ASSUME_NONNULL_END diff --git a/Source/WebKit/UIProcess/API/Cocoa/_WKWebPushDaemonConnection.mm b/Source/WebKit/UIProcess/API/Cocoa/_WKWebPushDaemonConnection.mm new file mode 100644 index 0000000000000..fe0fd10b4b329 --- /dev/null +++ b/Source/WebKit/UIProcess/API/Cocoa/_WKWebPushDaemonConnection.mm @@ -0,0 +1,158 @@ +/* + * Copyright (C) 2024 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 "_WKWebPushDaemonConnectionInternal.h" + +#import "APIWebPushMessage.h" +#import "APIWebPushSubscriptionData.h" +#import "WKError.h" +#import "_WKWebPushSubscriptionDataInternal.h" +#import +#import +#import +#import +#import +#import + +@implementation _WKWebPushDaemonConnectionConfiguration + +- (instancetype)init +{ + self = [super init]; + if (!self) + return nil; + +#if ENABLE(RELOCATABLE_WEBPUSHD) + _machServiceName = @"com.apple.webkit.webpushd.relocatable.service"; +#else + _machServiceName = @"com.apple.webkit.webpushd.service"; +#endif + return self; +} + +@end + +@implementation _WKWebPushDaemonConnection + +- (instancetype)initWithConfiguration:(_WKWebPushDaemonConnectionConfiguration *)configuration +{ + if (!(self = [super init])) + return nil; + + API::Object::constructInWrapper(self, configuration.machServiceName, configuration.partition, configuration.bundleIdentifier); + + return self; +} + +static _WKWebPushPermissionState toWKPermissionsState(WebCore::PushPermissionState state) +{ + switch (state) { + case WebCore::PushPermissionState::Denied: + return _WKWebPushPermissionStateDenied; + case WebCore::PushPermissionState::Granted: + return _WKWebPushPermissionStateGranted; + case WebCore::PushPermissionState::Prompt: + return _WKWebPushPermissionStatePrompt; + } + + return _WKWebPushPermissionStateDenied; +} + +- (void)getPushPermissionStateForOrigin:(NSURL *)originURL completionHandler:(void (^)(_WKWebPushPermissionState))completionHandler +{ + _connection->getPushPermissionState(originURL, [completionHandlerCopy = makeBlockPtr(completionHandler)](auto result) { + completionHandlerCopy(toWKPermissionsState(result)); + }); +} + +- (void)requestPushPermissionForOrigin:(NSURL *)originURL completionHandler:(void (^)(BOOL))completionHandler +{ + _connection->requestPushPermission(originURL, [completionHandlerCopy = makeBlockPtr(completionHandler)] (bool result) { + completionHandlerCopy(result); + }); +} + +- (void)setAppBadge:(NSUInteger *)badge origin:(NSURL *)originURL +{ + std::optional badgeValue = badge ? std::optional { (uint64_t)badge } : std::nullopt; + _connection->setAppBadge(originURL, badgeValue); +} + +- (void)subscribeToPushServiceForScope:(NSURL *)scopeURL applicationServerKey:(NSData *)applicationServerKey completionHandler:(void (^)(_WKWebPushSubscriptionData *, NSError *))completionHandler +{ + auto key = makeVector(applicationServerKey); + _connection->subscribeToPushService(scopeURL, WTFMove(key), [completionHandlerCopy = makeBlockPtr(completionHandler)] (auto result) { + if (result) + return completionHandlerCopy(wrapper(API::WebPushSubscriptionData::create(WTFMove(result.value()))).get(), nil); + + // FIXME: This error can be used to create DOMException; we may consider adding a new value to WKErrorCode for it. + auto error = [NSError errorWithDomain:@"WKErrorDomain" code:WKErrorUnknown userInfo:@{ NSLocalizedDescriptionKey:result.error().message }]; + completionHandlerCopy(nil, error); + }); +} + +- (void)unsubscribeFromPushServiceForScope:(NSURL *)scopeURL completionHandler:(void (^)(BOOL unsubscribed, NSError *))completionHandler +{ + _connection->unsubscribeFromPushService(scopeURL, [completionHandlerCopy = makeBlockPtr(completionHandler)] (auto result) { + if (result) + return completionHandlerCopy(result.value(), nil); + + auto error = [NSError errorWithDomain:@"WKErrorDomain" code:WKErrorUnknown userInfo:@{ NSLocalizedDescriptionKey:result.error().message }]; + completionHandlerCopy(false, error); + }); +} + +- (void)getSubscriptionForScope:(NSURL *)scopeURL completionHandler:(void (^)(_WKWebPushSubscriptionData *, NSError *))completionHandler +{ + _connection->getPushSubscription(scopeURL, [completionHandlerCopy = makeBlockPtr(completionHandler)] (auto result) { + if (result) { + if (auto data = result.value()) + return completionHandlerCopy(wrapper(API::WebPushSubscriptionData::create(WTFMove(*data))).get(), nil); + + return completionHandlerCopy(nil, nil); + } + + auto error = [NSError errorWithDomain:@"WKErrorDomain" code:WKErrorUnknown userInfo:@{ NSLocalizedDescriptionKey:result.error().message }]; + completionHandlerCopy(nil, error); + }); +} + +- (void)getNextPendingPushMessage:(void (^)(_WKWebPushMessage *))completionHandler +{ + _connection->getNextPendingPushMessage([completionHandlerCopy = makeBlockPtr(completionHandler)] (auto result) { + if (!result) + return completionHandlerCopy(nil); + + return completionHandlerCopy(wrapper(API::WebPushMessage::create(WTFMove(result.value()))).get()); + }); +} + +- (API::Object&)_apiObject +{ + return *_connection; +} + +@end diff --git a/Source/WebKit/UIProcess/API/Cocoa/_WKWebPushDaemonConnectionInternal.h b/Source/WebKit/UIProcess/API/Cocoa/_WKWebPushDaemonConnectionInternal.h new file mode 100644 index 0000000000000..60aec8b1c93f8 --- /dev/null +++ b/Source/WebKit/UIProcess/API/Cocoa/_WKWebPushDaemonConnectionInternal.h @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2024 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 "APIWebPushDaemonConnection.h" +#import "WKObject.h" +#import "_WKWebPushDaemonConnection.h" + +namespace WebKit { + +template<> struct WrapperTraits { + using WrapperClass = _WKWebPushDaemonConnection; +}; + +} // namespace WebKit + +@interface _WKWebPushDaemonConnection () { +@package + API::ObjectStorage _connection; +} +@end diff --git a/Source/WebKit/UIProcess/API/Cocoa/_WKWebPushMessage.h b/Source/WebKit/UIProcess/API/Cocoa/_WKWebPushMessage.h new file mode 100644 index 0000000000000..1f2e3df88da3a --- /dev/null +++ b/Source/WebKit/UIProcess/API/Cocoa/_WKWebPushMessage.h @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2024 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 + +NS_ASSUME_NONNULL_BEGIN + +WK_EXTERN +@interface _WKWebPushMessage : NSObject + ++ (instancetype)new NS_UNAVAILABLE; +- (instancetype)init NS_UNAVAILABLE; + +@property (nonatomic, readonly) NSURL *scopeURL; +@property (nonatomic, readonly) NSData *data; +@property (nonatomic, readonly) NSString *partition; + +@end + +NS_ASSUME_NONNULL_END diff --git a/Source/WebKit/UIProcess/API/Cocoa/_WKWebPushMessage.mm b/Source/WebKit/UIProcess/API/Cocoa/_WKWebPushMessage.mm new file mode 100644 index 0000000000000..469617bd15d0b --- /dev/null +++ b/Source/WebKit/UIProcess/API/Cocoa/_WKWebPushMessage.mm @@ -0,0 +1,67 @@ +/* + * Copyright (C) 2024 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 "_WKWebPushMessageInternal.h" + +#import +#import + +@implementation _WKWebPushMessage + +- (void)dealloc +{ + if (WebCoreObjCScheduleDeallocateOnMainRunLoop(_WKWebPushMessage.class, self)) + return; + + _message->API::WebPushMessage::~WebPushMessage(); + [super dealloc]; +} + +- (NSData *)data +{ + if (auto messageData = _message->data()) + return toNSData(*messageData).get(); + + return nil; +} + +- (NSURL *)scope +{ + return _message->scope(); +} + +- (NSString *)partition +{ + return _message->partition(); +} + +- (API::Object&)_apiObject +{ + return *_message; +} + +@end + diff --git a/Source/WebKit/UIProcess/API/Cocoa/_WKWebPushMessageInternal.h b/Source/WebKit/UIProcess/API/Cocoa/_WKWebPushMessageInternal.h new file mode 100644 index 0000000000000..9debf59085565 --- /dev/null +++ b/Source/WebKit/UIProcess/API/Cocoa/_WKWebPushMessageInternal.h @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2024 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 "APIWebPushMessage.h" +#import "WKObject.h" +#import "_WKWebPushMessage.h" + +namespace WebKit { + +template<> struct WrapperTraits { + using WrapperClass = _WKWebPushMessage; +}; + +} // namespace WebKit + +@interface _WKWebPushMessage () { +@package + API::ObjectStorage _message; +} +@end diff --git a/Source/WebKit/UIProcess/API/Cocoa/_WKWebPushSubscriptionData.h b/Source/WebKit/UIProcess/API/Cocoa/_WKWebPushSubscriptionData.h new file mode 100644 index 0000000000000..8725ecb815f73 --- /dev/null +++ b/Source/WebKit/UIProcess/API/Cocoa/_WKWebPushSubscriptionData.h @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2024 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 + +NS_ASSUME_NONNULL_BEGIN + +WK_EXTERN +@interface _WKWebPushSubscriptionData : NSObject + ++ (instancetype)new NS_UNAVAILABLE; +- (instancetype)init NS_UNAVAILABLE; + +@property (nonatomic, readonly) NSURL *endpoint; +@property (nonatomic, readonly) NSData *applicationServerKey; +@property (nonatomic, readonly) NSData *authenticationSecret; +@property (nonatomic, readonly) NSData *ecdhPublicKey; + +@end + +NS_ASSUME_NONNULL_END diff --git a/Source/WebKit/UIProcess/API/Cocoa/_WKWebPushSubscriptionData.mm b/Source/WebKit/UIProcess/API/Cocoa/_WKWebPushSubscriptionData.mm new file mode 100644 index 0000000000000..c15543014c3b2 --- /dev/null +++ b/Source/WebKit/UIProcess/API/Cocoa/_WKWebPushSubscriptionData.mm @@ -0,0 +1,65 @@ +/* + * Copyright (C) 2024 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 "_WKWebPushSubscriptionDataInternal.h" + +@implementation _WKWebPushSubscriptionData + +- (void)dealloc +{ + if (WebCoreObjCScheduleDeallocateOnMainRunLoop(_WKWebPushSubscriptionData.class, self)) + return; + + _data->API::WebPushSubscriptionData::~WebPushSubscriptionData(); + [super dealloc]; +} + +- (NSURL *)endpoint +{ + return _data->endpoint(); +} + +- (NSData *)applicationServerKey +{ + return toNSData(_data->applicationServerKey()).get(); +} + +- (NSData *)authenticationSecret +{ + return toNSData(_data->sharedAuthenticationSecret()).get(); +} + +- (NSData *)ecdhPublicKey +{ + return toNSData(_data->clientECDHPublicKey()).get(); +} + +- (API::Object&)_apiObject +{ + return *_data; +} + +@end diff --git a/Source/WebKit/UIProcess/API/Cocoa/_WKWebPushSubscriptionDataInternal.h b/Source/WebKit/UIProcess/API/Cocoa/_WKWebPushSubscriptionDataInternal.h new file mode 100644 index 0000000000000..3a09d603b8570 --- /dev/null +++ b/Source/WebKit/UIProcess/API/Cocoa/_WKWebPushSubscriptionDataInternal.h @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2024 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 "APIWebPushSubscriptionData.h" +#import "WKObject.h" +#import "_WKWebPushSubscriptionData.h" + +namespace WebKit { + +template<> struct WrapperTraits { + using WrapperClass = _WKWebPushSubscriptionData; +}; + +} // namespace WebKit + +@interface _WKWebPushSubscriptionData () { +@package + API::ObjectStorage _data; +} +@end diff --git a/Source/WebKit/UIProcess/API/ios/WKWebViewTestingIOS.mm b/Source/WebKit/UIProcess/API/ios/WKWebViewTestingIOS.mm index 131705d66f367..26ee34b3f99cf 100644 --- a/Source/WebKit/UIProcess/API/ios/WKWebViewTestingIOS.mm +++ b/Source/WebKit/UIProcess/API/ios/WKWebViewTestingIOS.mm @@ -30,6 +30,7 @@ #import "RemoteLayerTreeDrawingAreaProxy.h" #import "RemoteLayerTreeViews.h" +#import "RemoteScrollingCoordinatorProxy.h" #import "SystemPreviewController.h" #import "UIKitSPI.h" #import "WKContentViewInteraction.h" diff --git a/Source/WebKit/WebKit.xcodeproj/project.pbxproj b/Source/WebKit/WebKit.xcodeproj/project.pbxproj index 990455b67b19d..6b0d9a45f1bd1 100644 --- a/Source/WebKit/WebKit.xcodeproj/project.pbxproj +++ b/Source/WebKit/WebKit.xcodeproj/project.pbxproj @@ -1065,6 +1065,9 @@ 37F623B812A57B6200E3FDF6 /* WKFindOptions.h in Headers */ = {isa = PBXBuildFile; fileRef = 37F623B712A57B6200E3FDF6 /* WKFindOptions.h */; settings = {ATTRIBUTES = (Private, ); }; }; 37FC19471850FBF2008CFA47 /* WKBrowsingContextLoadDelegatePrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = 37FC19461850FBF2008CFA47 /* WKBrowsingContextLoadDelegatePrivate.h */; settings = {ATTRIBUTES = (Private, ); }; }; 37FC194B18510D6A008CFA47 /* WKNSURLAuthenticationChallenge.h in Headers */ = {isa = PBXBuildFile; fileRef = 37FC194918510D6A008CFA47 /* WKNSURLAuthenticationChallenge.h */; }; + 3A05FCD62C89095B005EF8CB /* _WKWebPushDaemonConnection.h in Headers */ = {isa = PBXBuildFile; fileRef = 3A05FCCD2C890946005EF8CB /* _WKWebPushDaemonConnection.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 3A05FCD82C890974005EF8CB /* _WKWebPushMessage.h in Headers */ = {isa = PBXBuildFile; fileRef = 3A05FCD02C890946005EF8CB /* _WKWebPushMessage.h */; settings = {ATTRIBUTES = (Private, ); }; }; + 3A05FCDA2C8909A2005EF8CB /* _WKWebPushSubscriptionData.h in Headers */ = {isa = PBXBuildFile; fileRef = 3A05FCD32C890946005EF8CB /* _WKWebPushSubscriptionData.h */; settings = {ATTRIBUTES = (Private, ); }; }; 3A12CDBB29D4D30200D57EAE /* WebSWRegistrationStore.h in Headers */ = {isa = PBXBuildFile; fileRef = 3AC4C04529D35D1500402716 /* WebSWRegistrationStore.h */; }; 3A18A2EF2AFF004C00DB976C /* _WKArchiveConfiguration.h in Headers */ = {isa = PBXBuildFile; fileRef = 3A18A2EE2AFF004C00DB976C /* _WKArchiveConfiguration.h */; settings = {ATTRIBUTES = (Private, ); }; }; 3A18A2F52B02969900DB976C /* _WKArchiveExclusionRule.h in Headers */ = {isa = PBXBuildFile; fileRef = 3A18A2F32B02969800DB976C /* _WKArchiveExclusionRule.h */; settings = {ATTRIBUTES = (Private, ); }; }; @@ -5086,6 +5089,19 @@ 37FC19461850FBF2008CFA47 /* WKBrowsingContextLoadDelegatePrivate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WKBrowsingContextLoadDelegatePrivate.h; sourceTree = ""; }; 37FC194818510D6A008CFA47 /* WKNSURLAuthenticationChallenge.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = WKNSURLAuthenticationChallenge.mm; sourceTree = ""; }; 37FC194918510D6A008CFA47 /* WKNSURLAuthenticationChallenge.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WKNSURLAuthenticationChallenge.h; sourceTree = ""; }; + 3A05FCCD2C890946005EF8CB /* _WKWebPushDaemonConnection.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = _WKWebPushDaemonConnection.h; sourceTree = ""; }; + 3A05FCCE2C890946005EF8CB /* _WKWebPushDaemonConnection.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = _WKWebPushDaemonConnection.mm; sourceTree = ""; }; + 3A05FCCF2C890946005EF8CB /* _WKWebPushDaemonConnectionInternal.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = _WKWebPushDaemonConnectionInternal.h; sourceTree = ""; }; + 3A05FCD02C890946005EF8CB /* _WKWebPushMessage.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = _WKWebPushMessage.h; sourceTree = ""; }; + 3A05FCD12C890946005EF8CB /* _WKWebPushMessage.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = _WKWebPushMessage.mm; sourceTree = ""; }; + 3A05FCD22C890946005EF8CB /* _WKWebPushMessageInternal.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = _WKWebPushMessageInternal.h; sourceTree = ""; }; + 3A05FCD32C890946005EF8CB /* _WKWebPushSubscriptionData.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = _WKWebPushSubscriptionData.h; sourceTree = ""; }; + 3A05FCD42C890946005EF8CB /* _WKWebPushSubscriptionData.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = _WKWebPushSubscriptionData.mm; sourceTree = ""; }; + 3A05FCD52C890946005EF8CB /* _WKWebPushSubscriptionDataInternal.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = _WKWebPushSubscriptionDataInternal.h; sourceTree = ""; }; + 3A05FCDB2C8909D3005EF8CB /* APIWebPushDaemonConnection.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = APIWebPushDaemonConnection.h; sourceTree = ""; }; + 3A05FCDC2C8909D3005EF8CB /* APIWebPushDaemonConnection.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = APIWebPushDaemonConnection.cpp; sourceTree = ""; }; + 3A05FCDD2C8909D3005EF8CB /* APIWebPushMessage.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = APIWebPushMessage.h; sourceTree = ""; }; + 3A05FCDE2C8909D3005EF8CB /* APIWebPushSubscriptionData.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = APIWebPushSubscriptionData.h; sourceTree = ""; }; 3A18A2EE2AFF004C00DB976C /* _WKArchiveConfiguration.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = _WKArchiveConfiguration.h; sourceTree = ""; }; 3A18A2F02AFF006C00DB976C /* _WKArchiveConfiguration.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = _WKArchiveConfiguration.mm; sourceTree = ""; }; 3A18A2F22B02969800DB976C /* _WKArchiveExclusionRule.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = _WKArchiveExclusionRule.mm; sourceTree = ""; }; @@ -11551,6 +11567,15 @@ 51E0BD9B2C7471110048411B /* _WKWebPushAction.h */, 51E0BD9C2C7471110048411B /* _WKWebPushAction.mm */, 51909C5D2C801B5A009D2E0E /* _WKWebPushActionInternal.h */, + 3A05FCCD2C890946005EF8CB /* _WKWebPushDaemonConnection.h */, + 3A05FCCE2C890946005EF8CB /* _WKWebPushDaemonConnection.mm */, + 3A05FCCF2C890946005EF8CB /* _WKWebPushDaemonConnectionInternal.h */, + 3A05FCD02C890946005EF8CB /* _WKWebPushMessage.h */, + 3A05FCD12C890946005EF8CB /* _WKWebPushMessage.mm */, + 3A05FCD22C890946005EF8CB /* _WKWebPushMessageInternal.h */, + 3A05FCD32C890946005EF8CB /* _WKWebPushSubscriptionData.h */, + 3A05FCD42C890946005EF8CB /* _WKWebPushSubscriptionData.mm */, + 3A05FCD52C890946005EF8CB /* _WKWebPushSubscriptionDataInternal.h */, 1AE286761C7E76510069AC4F /* _WKWebsiteDataSize.h */, 1AE286751C7E76510069AC4F /* _WKWebsiteDataSize.mm */, 1AE2867F1C7F92BF0069AC4F /* _WKWebsiteDataSizeInternal.h */, @@ -14288,6 +14313,10 @@ 57EBE269234676C5008D8AF9 /* APIWebAuthenticationPanel.cpp */, 57EBE268234676C5008D8AF9 /* APIWebAuthenticationPanel.h */, 577FF7812346E81C004EDFB9 /* APIWebAuthenticationPanelClient.h */, + 3A05FCDC2C8909D3005EF8CB /* APIWebPushDaemonConnection.cpp */, + 3A05FCDB2C8909D3005EF8CB /* APIWebPushDaemonConnection.h */, + 3A05FCDD2C8909D3005EF8CB /* APIWebPushMessage.h */, + 3A05FCDE2C8909D3005EF8CB /* APIWebPushSubscriptionData.h */, 1AE286811C7F93860069AC4F /* APIWebsiteDataRecord.cpp */, 1AE286821C7F93860069AC4F /* APIWebsiteDataRecord.h */, 5C8DD37D1FE4501100F2A556 /* APIWebsitePolicies.cpp */, @@ -16124,6 +16153,9 @@ 1CC5CA7D2C5ACB8500DF3B94 /* _WKWebExtensionWindowCreationOptions.h in Headers */, 51E0BD9D2C74711A0048411B /* _WKWebPushAction.h in Headers */, 51909C5E2C801B5A009D2E0E /* _WKWebPushActionInternal.h in Headers */, + 3A05FCD62C89095B005EF8CB /* _WKWebPushDaemonConnection.h in Headers */, + 3A05FCD82C890974005EF8CB /* _WKWebPushMessage.h in Headers */, + 3A05FCDA2C8909A2005EF8CB /* _WKWebPushSubscriptionData.h in Headers */, 1AE286781C7E76510069AC4F /* _WKWebsiteDataSize.h in Headers */, 1AE286801C7F92C00069AC4F /* _WKWebsiteDataSizeInternal.h in Headers */, 5120C8351E5B74B90025B250 /* _WKWebsiteDataStoreConfiguration.h in Headers */, diff --git a/Tools/TestWebKitAPI/Tests/WebKitCocoa/WebPushDaemon.mm b/Tools/TestWebKitAPI/Tests/WebKitCocoa/WebPushDaemon.mm index 2bd393dca4112..15a3f2096f05a 100644 --- a/Tools/TestWebKitAPI/Tests/WebKitCocoa/WebPushDaemon.mm +++ b/Tools/TestWebKitAPI/Tests/WebKitCocoa/WebPushDaemon.mm @@ -49,6 +49,8 @@ #import #import #import +#import +#import #import #import #import @@ -2381,6 +2383,88 @@ static size_t expectedSuccessfulMessages() TestWebKitAPI::Util::run(&done); } +#if HAVE(FULL_FEATURED_USER_NOTIFICATIONS) + +TEST(WebPushD, WKWebPushDaemonConnectionRequestPushPermission) +{ + setUpTestWebPushD(); + + auto configuration = adoptNS([[_WKWebPushDaemonConnectionConfiguration alloc] init]); + configuration.get().machServiceName = @"org.webkit.webpushtestdaemon.service"; + auto connection = adoptNS([[_WKWebPushDaemonConnection alloc] initWithConfiguration:configuration.get()]); + auto url = adoptNS([[NSURL alloc] initWithString:@"https://webkit.org"]); + + __block bool done = false; + [connection getPushPermissionStateForOrigin:url.get() completionHandler:^(_WKWebPushPermissionState state) { + done = true; + EXPECT_EQ(state, _WKWebPushPermissionStatePrompt); + }]; + TestWebKitAPI::Util::run(&done); + + done = false; + [connection requestPushPermissionForOrigin:url.get() completionHandler:^(BOOL granted) { + done = true; + EXPECT_TRUE(granted); + }]; + TestWebKitAPI::Util::run(&done); + + done = false; + [connection getPushPermissionStateForOrigin:url.get() completionHandler:^(_WKWebPushPermissionState state) { + done = true; + EXPECT_EQ(state, _WKWebPushPermissionStateGranted); + }]; + TestWebKitAPI::Util::run(&done); +} + +TEST(WebPushD, WKWebPushDaemonConnectionPushSubscription) +{ + setUpTestWebPushD(); + + auto configuration = adoptNS([[_WKWebPushDaemonConnectionConfiguration alloc] init]); + configuration.get().machServiceName = @"org.webkit.webpushtestdaemon.service"; + // Bundle identifier is required for making push subscription. + configuration.get().bundleIdentifier = @"com.apple.WebKit.TestWebKitAPI"; + auto connection = adoptNS([[_WKWebPushDaemonConnection alloc] initWithConfiguration:configuration.get()]); + auto url = adoptNS([[NSURL alloc] initWithString:@"https://webkit.org/sw.js"]); + RetainPtr applicationServerKey = [NSData dataWithBytes:(const void *)validServerKey.characters() length:validServerKey.length()]; + + __block bool done = false; + [connection subscribeToPushServiceForScope:url.get() applicationServerKey:applicationServerKey.get() completionHandler:^(_WKWebPushSubscriptionData *subscription, NSError *error) { + EXPECT_NULL(error); + EXPECT_NOT_NULL(subscription); + EXPECT_WK_STREQ(@"https://webkit.org/push", subscription.endpoint.absoluteString); + done = true; + }]; + TestWebKitAPI::Util::run(&done); + + done = false; + [connection getSubscriptionForScope:url.get() completionHandler:^(_WKWebPushSubscriptionData *subscription, NSError *error) { + EXPECT_NULL(error); + EXPECT_NOT_NULL(subscription); + EXPECT_WK_STREQ(@"https://webkit.org/push", subscription.endpoint.absoluteString); + done = true; + }]; + TestWebKitAPI::Util::run(&done); + + done = false; + [connection unsubscribeFromPushServiceForScope:url.get() completionHandler:^(BOOL unsubscribed, NSError * error) { + EXPECT_NULL(error); + EXPECT_TRUE(unsubscribed); + done = true; + }]; + TestWebKitAPI::Util::run(&done); + + done = false; + [connection getSubscriptionForScope:url.get() completionHandler:^(_WKWebPushSubscriptionData *subscription, NSError *error) { + EXPECT_NULL(error); + EXPECT_NULL(subscription); + done = true; + }]; + TestWebKitAPI::Util::run(&done); +} + +#endif + class WebPushDPushNotificationEventTest : public WebPushDTest { public: WebPushDPushNotificationEventTest()