Title: [286273] trunk
Revision
286273
Author
beid...@apple.com
Date
2021-11-29 16:20:57 -0800 (Mon, 29 Nov 2021)

Log Message

Make webpushd "fake registration for testing" much more complicated by adding a "mock app bundle" install
https://bugs.webkit.org/show_bug.cgi?id=233454

Reviewed by Alex Christensen.

Covered by API tests.

Before this patch, webpushd remembered "registrations" using a simple in-memory HashMap.

In the near future, registrations will actually be represented with a placeholder app bundle on disk.

The process of installing placeholders (and checking for existing ones) is complicated and asynchronous.

This patch shifts the in-memory testing implementation from a simple HashMap to a "complicated and asynchronous"
registration mechanism that simulates how app-bundle installs will work.

Once the "real" mechanisms are in place there will be much more in-depth testing that we can do.
For now, this is a "no behavior change" patch.

* NetworkProcess/Notifications/Cocoa/WebPushDaemonConnectionCocoa.mm:
(WebKit::WebPushD::Connection::connectionReceivedEvent const):
* UIProcess/API/Cocoa/WKUIDelegatePrivate.h:

* WebKit.xcodeproj/project.pbxproj:

"PushAppBundle" is an abstract base class for representing a placeholder application bundle for a registration.
Eventually there will be a native one for each platform that actually does system operations.
For now, the concrete implementation is the in-memory "Mock" app bundle.

* webpushd/PushAppBundle.h: Copied from Source/WebKit/webpushd/PushClientConnection.h.
* webpushd/PushAppBundle.mm: Copied from Source/WebKit/webpushd/PushClientConnection.h.
(WebPushD::PushAppBundleClient::~PushAppBundleClient):
(WebPushD::PushAppBundle::PushAppBundle):
(WebPushD::PushAppBundle::~PushAppBundle):
(WebPushD::PushAppBundle::detachFromClient):

An "AppBundleRequest" is a queable operation meant to do something with an "App bundle".
For now the operations are "create" and "delete"

* webpushd/AppBundleRequest.h: Added.
(WebPushD::AppBundleRequestImpl::AppBundleRequestImpl):
(WebPushD::AppBundleRequestImpl::~AppBundleRequestImpl):
(WebPushD::AppBundleRequestImpl::callCompletionHandlerAndCleanup):
(WebPushD::AppBundlePermissionsRequest::AppBundlePermissionsRequest):
(WebPushD::AppBundleDeletionRequest::AppBundleDeletionRequest):
* webpushd/AppBundleRequest.mm: Added.
(WebPushD::AppBundleRequest::AppBundleRequest):
(WebPushD::AppBundleRequest::~AppBundleRequest):
(WebPushD::AppBundleRequest::start):
(WebPushD::AppBundleRequest::cancel):
(WebPushD::AppBundleRequest::cleanupAfterCompletionHandler):
(WebPushD::AppBundlePermissionsRequest::startInternal):
(WebPushD::AppBundlePermissionsRequest::didCheckForExistingBundle):
(WebPushD::AppBundlePermissionsRequest::didCreateAppBundle):
(WebPushD::AppBundleDeletionRequest::startInternal):
(WebPushD::AppBundleDeletionRequest::didDeleteExistingBundleWithError):

* webpushd/MockAppBundleForTesting.h: Copied from Source/WebKit/webpushd/PushClientConnection.h.
(WebPushD::MockAppBundleForTesting::create):
* webpushd/MockAppBundleForTesting.mm: Added.
(WebPushD::MockAppBundleForTesting::MockAppBundleForTesting):
(WebPushD::MockAppBundleForTesting::~MockAppBundleForTesting):
(WebPushD::MockAppBundleForTesting::checkForExistingBundle):
(WebPushD::MockAppBundleForTesting::deleteExistingBundle):
(WebPushD::MockAppBundleForTesting::createBundle):
(WebPushD::MockAppBundleForTesting::stop):

* webpushd/MockAppBundleRegistry.h: Copied from Source/WebKit/webpushd/PushClientConnection.h.
* webpushd/MockAppBundleRegistry.mm: Added.
(WebPushD::MockAppBundleRegistry::singleton):
(WebPushD::MockAppBundleRegistry::getOriginsWithRegistrations):
(WebPushD::MockAppBundleRegistry::doesBundleExist):
(WebPushD::MockAppBundleRegistry::createBundle):
(WebPushD::MockAppBundleRegistry::deleteBundle):

* webpushd/PushClientConnection.h:
* webpushd/PushClientConnection.mm:
(WebPushD::ClientConnection::create):
(WebPushD::ClientConnection::enqueueAppBundleRequest):
(WebPushD::ClientConnection::maybeStartNextAppBundleRequest):
(WebPushD::ClientConnection::didCompleteAppBundleRequest):
(WebPushD::ClientConnection::connectionClosed):

* webpushd/WebPushDaemon.h:
* webpushd/WebPushDaemon.mm:
(WebPushD::Daemon::connectionAdded):
(WebPushD::Daemon::connectionRemoved):
(WebPushD::Daemon::requestSystemNotificationPermission):
(WebPushD::Daemon::getOriginsWithPushAndNotificationPermissions):
(WebPushD::Daemon::deletePushAndNotificationRegistration):

Modified Paths

Added Paths

Diff

Modified: trunk/Source/WebKit/ChangeLog (286272 => 286273)


--- trunk/Source/WebKit/ChangeLog	2021-11-30 00:20:30 UTC (rev 286272)
+++ trunk/Source/WebKit/ChangeLog	2021-11-30 00:20:57 UTC (rev 286273)
@@ -1,3 +1,96 @@
+2021-11-29  Brady Eidson  <beid...@apple.com>
+
+        Make webpushd "fake registration for testing" much more complicated by adding a "mock app bundle" install
+        https://bugs.webkit.org/show_bug.cgi?id=233454
+
+        Reviewed by Alex Christensen.
+
+        Covered by API tests.
+        
+        Before this patch, webpushd remembered "registrations" using a simple in-memory HashMap.
+        
+        In the near future, registrations will actually be represented with a placeholder app bundle on disk.
+        
+        The process of installing placeholders (and checking for existing ones) is complicated and asynchronous.
+        
+        This patch shifts the in-memory testing implementation from a simple HashMap to a "complicated and asynchronous"
+        registration mechanism that simulates how app-bundle installs will work.
+        
+        Once the "real" mechanisms are in place there will be much more in-depth testing that we can do.
+        For now, this is a "no behavior change" patch.
+
+        * NetworkProcess/Notifications/Cocoa/WebPushDaemonConnectionCocoa.mm:
+        (WebKit::WebPushD::Connection::connectionReceivedEvent const):
+        * UIProcess/API/Cocoa/WKUIDelegatePrivate.h:
+
+        * WebKit.xcodeproj/project.pbxproj:
+
+        "PushAppBundle" is an abstract base class for representing a placeholder application bundle for a registration.
+        Eventually there will be a native one for each platform that actually does system operations.
+        For now, the concrete implementation is the in-memory "Mock" app bundle.
+
+        * webpushd/PushAppBundle.h: Copied from Source/WebKit/webpushd/PushClientConnection.h.
+        * webpushd/PushAppBundle.mm: Copied from Source/WebKit/webpushd/PushClientConnection.h.
+        (WebPushD::PushAppBundleClient::~PushAppBundleClient):
+        (WebPushD::PushAppBundle::PushAppBundle):
+        (WebPushD::PushAppBundle::~PushAppBundle):
+        (WebPushD::PushAppBundle::detachFromClient):
+        
+        An "AppBundleRequest" is a queable operation meant to do something with an "App bundle".
+        For now the operations are "create" and "delete"
+        
+        * webpushd/AppBundleRequest.h: Added.
+        (WebPushD::AppBundleRequestImpl::AppBundleRequestImpl):
+        (WebPushD::AppBundleRequestImpl::~AppBundleRequestImpl):
+        (WebPushD::AppBundleRequestImpl::callCompletionHandlerAndCleanup):
+        (WebPushD::AppBundlePermissionsRequest::AppBundlePermissionsRequest):
+        (WebPushD::AppBundleDeletionRequest::AppBundleDeletionRequest):
+        * webpushd/AppBundleRequest.mm: Added.
+        (WebPushD::AppBundleRequest::AppBundleRequest):
+        (WebPushD::AppBundleRequest::~AppBundleRequest):
+        (WebPushD::AppBundleRequest::start):
+        (WebPushD::AppBundleRequest::cancel):
+        (WebPushD::AppBundleRequest::cleanupAfterCompletionHandler):
+        (WebPushD::AppBundlePermissionsRequest::startInternal):
+        (WebPushD::AppBundlePermissionsRequest::didCheckForExistingBundle):
+        (WebPushD::AppBundlePermissionsRequest::didCreateAppBundle):
+        (WebPushD::AppBundleDeletionRequest::startInternal):
+        (WebPushD::AppBundleDeletionRequest::didDeleteExistingBundleWithError):
+
+        * webpushd/MockAppBundleForTesting.h: Copied from Source/WebKit/webpushd/PushClientConnection.h.
+        (WebPushD::MockAppBundleForTesting::create):
+        * webpushd/MockAppBundleForTesting.mm: Added.
+        (WebPushD::MockAppBundleForTesting::MockAppBundleForTesting):
+        (WebPushD::MockAppBundleForTesting::~MockAppBundleForTesting):
+        (WebPushD::MockAppBundleForTesting::checkForExistingBundle):
+        (WebPushD::MockAppBundleForTesting::deleteExistingBundle):
+        (WebPushD::MockAppBundleForTesting::createBundle):
+        (WebPushD::MockAppBundleForTesting::stop):
+
+        * webpushd/MockAppBundleRegistry.h: Copied from Source/WebKit/webpushd/PushClientConnection.h.
+        * webpushd/MockAppBundleRegistry.mm: Added.
+        (WebPushD::MockAppBundleRegistry::singleton):
+        (WebPushD::MockAppBundleRegistry::getOriginsWithRegistrations):
+        (WebPushD::MockAppBundleRegistry::doesBundleExist):
+        (WebPushD::MockAppBundleRegistry::createBundle):
+        (WebPushD::MockAppBundleRegistry::deleteBundle):
+
+        * webpushd/PushClientConnection.h:
+        * webpushd/PushClientConnection.mm:
+        (WebPushD::ClientConnection::create):
+        (WebPushD::ClientConnection::enqueueAppBundleRequest):
+        (WebPushD::ClientConnection::maybeStartNextAppBundleRequest):
+        (WebPushD::ClientConnection::didCompleteAppBundleRequest):
+        (WebPushD::ClientConnection::connectionClosed):
+
+        * webpushd/WebPushDaemon.h:
+        * webpushd/WebPushDaemon.mm:
+        (WebPushD::Daemon::connectionAdded):
+        (WebPushD::Daemon::connectionRemoved):
+        (WebPushD::Daemon::requestSystemNotificationPermission):
+        (WebPushD::Daemon::getOriginsWithPushAndNotificationPermissions):
+        (WebPushD::Daemon::deletePushAndNotificationRegistration):
+
 2021-11-29  David Kilzer  <ddkil...@apple.com>
 
         Disable experimental web features on platforms without UI to enable them

Modified: trunk/Source/WebKit/NetworkProcess/Notifications/Cocoa/WebPushDaemonConnectionCocoa.mm (286272 => 286273)


--- trunk/Source/WebKit/NetworkProcess/Notifications/Cocoa/WebPushDaemonConnectionCocoa.mm	2021-11-30 00:20:30 UTC (rev 286272)
+++ trunk/Source/WebKit/NetworkProcess/Notifications/Cocoa/WebPushDaemonConnectionCocoa.mm	2021-11-30 00:20:57 UTC (rev 286273)
@@ -61,7 +61,7 @@
     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));
+    networkSession().networkProcess().broadcastConsoleMessage(networkSession().sessionID(), MessageSource::Other, messageLevel, String::fromUTF8(debugMessage));
 }
 
 RetainPtr<xpc_object_t> Connection::dictionaryFromMessage(MessageType messageType, EncodedMessage&& message) const

Modified: trunk/Source/WebKit/UIProcess/API/Cocoa/WKUIDelegatePrivate.h (286272 => 286273)


--- trunk/Source/WebKit/UIProcess/API/Cocoa/WKUIDelegatePrivate.h	2021-11-30 00:20:30 UTC (rev 286272)
+++ trunk/Source/WebKit/UIProcess/API/Cocoa/WKUIDelegatePrivate.h	2021-11-30 00:20:57 UTC (rev 286273)
@@ -159,7 +159,7 @@
 - (void)_webViewDidDisableInspectorBrowserDomain:(WKWebView *)webView WK_API_AVAILABLE(macos(12.0), ios(15.0));
 
 - (void)_webView:(WKWebView *)webView startXRSessionWithCompletionHandler:(void (^)(id))completionHandler WK_API_AVAILABLE(macos(12.0), ios(15.0));
-- (void)_webView:(WKWebView *)webView requestNotificationPermissionForSecurityOrigin:(WKSecurityOrigin *)securityOrigin decisionHandler:(void (^)(BOOL))decisionHandler WK_API_AVAILABLE(macos(10.13.4));
+- (void)_webView:(WKWebView *)webView requestNotificationPermissionForSecurityOrigin:(WKSecurityOrigin *)securityOrigin decisionHandler:(void (^)(BOOL))decisionHandler WK_API_AVAILABLE(macos(10.13.4), ios(WK_IOS_TBA));
 
 #if TARGET_OS_IPHONE
 

Modified: trunk/Source/WebKit/WebKit.xcodeproj/project.pbxproj (286272 => 286273)


--- trunk/Source/WebKit/WebKit.xcodeproj/project.pbxproj	2021-11-30 00:20:30 UTC (rev 286272)
+++ trunk/Source/WebKit/WebKit.xcodeproj/project.pbxproj	2021-11-30 00:20:57 UTC (rev 286273)
@@ -1005,6 +1005,12 @@
 		515BE1AB1D555AA000DD7C68 /* WebGamepad.h in Headers */ = {isa = PBXBuildFile; fileRef = 515BE1A01D550AB000DD7C68 /* WebGamepad.h */; };
 		515BE1B31D5902DD00DD7C68 /* GamepadData.h in Headers */ = {isa = PBXBuildFile; fileRef = 515BE1B01D59006900DD7C68 /* GamepadData.h */; };
 		515BE1B51D5917FF00DD7C68 /* UIGamepad.h in Headers */ = {isa = PBXBuildFile; fileRef = 515BE1AD1D555C5100DD7C68 /* UIGamepad.h */; };
+		5160E955274B887200567388 /* AppBundleRequest.mm in Sources */ = {isa = PBXBuildFile; fileRef = 5160E953274B887100567388 /* AppBundleRequest.mm */; };
+		5160E956274B887200567388 /* AppBundleRequest.h in Headers */ = {isa = PBXBuildFile; fileRef = 5160E954274B887100567388 /* AppBundleRequest.h */; };
+		5160E959274C0D8900567388 /* PushAppBundle.h in Headers */ = {isa = PBXBuildFile; fileRef = 5160E957274C0D8800567388 /* PushAppBundle.h */; };
+		5160E95A274C0D8900567388 /* PushAppBundle.mm in Sources */ = {isa = PBXBuildFile; fileRef = 5160E958274C0D8800567388 /* PushAppBundle.mm */; };
+		5160E95E274C2A0300567388 /* MockAppBundleRegistry.h in Headers */ = {isa = PBXBuildFile; fileRef = 5160E95C274C2A0300567388 /* MockAppBundleRegistry.h */; };
+		5160E960274C2A4000567388 /* MockAppBundleRegistry.mm in Sources */ = {isa = PBXBuildFile; fileRef = 5160E95F274C2A3F00567388 /* MockAppBundleRegistry.mm */; };
 		5163199416289A6000E22F00 /* NetworkProcessMessageReceiver.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 51ACC9341628064800342550 /* NetworkProcessMessageReceiver.cpp */; };
 		5163199516289A6300E22F00 /* NetworkProcessMessages.h in Headers */ = {isa = PBXBuildFile; fileRef = 51ACC9351628064800342550 /* NetworkProcessMessages.h */; };
 		516A4A5D120A2CCD00C05B7F /* APIError.h in Headers */ = {isa = PBXBuildFile; fileRef = 516A4A5B120A2CCD00C05B7F /* APIError.h */; };
@@ -1056,6 +1062,8 @@
 		51F060E11654318500F3282E /* NetworkRTCProviderMessageReceiver.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 51F060DD1654317500F3282E /* NetworkRTCProviderMessageReceiver.cpp */; };
 		51F060E11654318500F3282F /* WebMDNSRegisterMessageReceiver.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 51F060DD1654317500F3282F /* WebMDNSRegisterMessageReceiver.cpp */; };
 		51F060E11654318500F3283F /* NetworkMDNSRegisterMessageReceiver.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 51F060DD1654317500F3283F /* NetworkMDNSRegisterMessageReceiver.cpp */; };
+		51F7BB76274498BB00C45A72 /* MockAppBundleForTesting.mm in Sources */ = {isa = PBXBuildFile; fileRef = 51F7BB74274498BA00C45A72 /* MockAppBundleForTesting.mm */; };
+		51F7BB77274498BB00C45A72 /* MockAppBundleForTesting.h in Headers */ = {isa = PBXBuildFile; fileRef = 51F7BB75274498BB00C45A72 /* MockAppBundleForTesting.h */; };
 		51F7BB7B2744C50700C45A72 /* PushClientConnection.h in Headers */ = {isa = PBXBuildFile; fileRef = 51F7BB792744C50700C45A72 /* PushClientConnection.h */; };
 		51F7BB7C2744C50700C45A72 /* PushClientConnection.mm in Sources */ = {isa = PBXBuildFile; fileRef = 51F7BB7A2744C50700C45A72 /* PushClientConnection.mm */; };
 		51F7BB7D2745640400C45A72 /* CodeSigning.mm in Sources */ = {isa = PBXBuildFile; fileRef = CE11AD4F1CBC47F800681EE5 /* CodeSigning.mm */; };
@@ -4338,6 +4346,12 @@
 		515C415A207D74E000726E02 /* SuspendedPageProxy.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SuspendedPageProxy.cpp; sourceTree = "<group>"; };
 		515C415B207D74E100726E02 /* SuspendedPageProxy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SuspendedPageProxy.h; sourceTree = "<group>"; };
 		5160BFE013381DF900918999 /* LoggingFoundation.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = LoggingFoundation.mm; sourceTree = "<group>"; };
+		5160E953274B887100567388 /* AppBundleRequest.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = AppBundleRequest.mm; sourceTree = "<group>"; };
+		5160E954274B887100567388 /* AppBundleRequest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AppBundleRequest.h; sourceTree = "<group>"; };
+		5160E957274C0D8800567388 /* PushAppBundle.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PushAppBundle.h; sourceTree = "<group>"; };
+		5160E958274C0D8800567388 /* PushAppBundle.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = PushAppBundle.mm; sourceTree = "<group>"; };
+		5160E95C274C2A0300567388 /* MockAppBundleRegistry.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MockAppBundleRegistry.h; sourceTree = "<group>"; };
+		5160E95F274C2A3F00567388 /* MockAppBundleRegistry.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MockAppBundleRegistry.mm; sourceTree = "<group>"; };
 		5164C0941B05B757004F102A /* AuxiliaryProcess.messages.in */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = AuxiliaryProcess.messages.in; sourceTree = "<group>"; };
 		516A4A5B120A2CCD00C05B7F /* APIError.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = APIError.h; sourceTree = "<group>"; };
 		517A33B3130B308C00F80CB5 /* WKApplicationCacheManager.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WKApplicationCacheManager.cpp; sourceTree = "<group>"; };
@@ -4445,6 +4459,8 @@
 		51F060DD1654317500F3282F /* WebMDNSRegisterMessageReceiver.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = WebMDNSRegisterMessageReceiver.cpp; path = DerivedSources/WebKit2/WebMDNSRegisterMessageReceiver.cpp; sourceTree = BUILT_PRODUCTS_DIR; };
 		51F060DD1654317500F3283F /* NetworkMDNSRegisterMessageReceiver.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = NetworkMDNSRegisterMessageReceiver.cpp; path = DerivedSources/WebKit2/NetworkMDNSRegisterMessageReceiver.cpp; sourceTree = BUILT_PRODUCTS_DIR; };
 		51F060DE1654317500F3281B /* WebResourceLoaderMessages.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = WebResourceLoaderMessages.h; path = DerivedSources/WebKit2/WebResourceLoaderMessages.h; sourceTree = BUILT_PRODUCTS_DIR; };
+		51F7BB74274498BA00C45A72 /* MockAppBundleForTesting.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MockAppBundleForTesting.mm; sourceTree = "<group>"; };
+		51F7BB75274498BB00C45A72 /* MockAppBundleForTesting.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MockAppBundleForTesting.h; sourceTree = "<group>"; };
 		51F7BB792744C50700C45A72 /* PushClientConnection.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PushClientConnection.h; sourceTree = "<group>"; };
 		51F7BB7A2744C50700C45A72 /* PushClientConnection.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = PushClientConnection.mm; sourceTree = "<group>"; };
 		51F7BB7E274564A100C45A72 /* Security.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Security.framework; path = System/Library/Frameworks/Security.framework; sourceTree = SDKROOT; };
@@ -9858,6 +9874,14 @@
 			isa = PBXGroup;
 			children = (
 				5CBB6D4D271F67CC00FD1A5D /* com.apple.webkit.webpushd.plist */,
+				5160E954274B887100567388 /* AppBundleRequest.h */,
+				5160E953274B887100567388 /* AppBundleRequest.mm */,
+				51F7BB75274498BB00C45A72 /* MockAppBundleForTesting.h */,
+				51F7BB74274498BA00C45A72 /* MockAppBundleForTesting.mm */,
+				5160E95C274C2A0300567388 /* MockAppBundleRegistry.h */,
+				5160E95F274C2A3F00567388 /* MockAppBundleRegistry.mm */,
+				5160E957274C0D8800567388 /* PushAppBundle.h */,
+				5160E958274C0D8800567388 /* PushAppBundle.mm */,
 				51F7BB792744C50700C45A72 /* PushClientConnection.h */,
 				51F7BB7A2744C50700C45A72 /* PushClientConnection.mm */,
 				512CD69D2723393A00F7F8EC /* WebPushDaemon.h */,
@@ -12399,9 +12423,13 @@
 			isa = PBXHeadersBuildPhase;
 			buildActionMask = 2147483647;
 			files = (
+				5160E959274C0D8900567388 /* PushAppBundle.h in Headers */,
+				51F7BB7B2744C50700C45A72 /* PushClientConnection.h in Headers */,
+				5160E95E274C2A0300567388 /* MockAppBundleRegistry.h in Headers */,
 				5C1579FC2717AF5000ED5280 /* DaemonUtilities.h in Headers */,
-				51F7BB7B2744C50700C45A72 /* PushClientConnection.h in Headers */,
+				5160E956274B887200567388 /* AppBundleRequest.h in Headers */,
 				512CD69F2723393A00F7F8EC /* WebPushDaemon.h in Headers */,
+				51F7BB77274498BB00C45A72 /* MockAppBundleForTesting.h in Headers */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
@@ -14938,9 +14966,13 @@
 				5C157A012717B7FB00ED5280 /* ArgumentCoders.cpp in Sources */,
 				51F7BB7D2745640400C45A72 /* CodeSigning.mm in Sources */,
 				5C1579FF2717B6D200ED5280 /* DaemonDecoder.cpp in Sources */,
+				51F7BB76274498BB00C45A72 /* MockAppBundleForTesting.mm in Sources */,
+				5160E955274B887200567388 /* AppBundleRequest.mm in Sources */,
+				5160E95A274C0D8900567388 /* PushAppBundle.mm in Sources */,
+				5160E960274C2A4000567388 /* MockAppBundleRegistry.mm in Sources */,
+				51F7BB7C2744C50700C45A72 /* PushClientConnection.mm in Sources */,
 				5C1579FE2717B6C100ED5280 /* DaemonEncoder.cpp in Sources */,
 				5C1579FB2717AF5000ED5280 /* DaemonUtilities.mm in Sources */,
-				51F7BB7C2744C50700C45A72 /* PushClientConnection.mm in Sources */,
 				512CD6A02723393A00F7F8EC /* WebPushDaemon.mm in Sources */,
 				5C157A0C2717CA1D00ED5280 /* WebPushDaemonMain.mm in Sources */,
 			);

Added: trunk/Source/WebKit/webpushd/AppBundleRequest.h (0 => 286273)


--- trunk/Source/WebKit/webpushd/AppBundleRequest.h	                        (rev 0)
+++ trunk/Source/WebKit/webpushd/AppBundleRequest.h	2021-11-30 00:20:57 UTC (rev 286273)
@@ -0,0 +1,125 @@
+/*
+ * 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
+
+#import "PushAppBundle.h"
+#import "PushClientConnection.h"
+#import <wtf/CompletionHandler.h>
+#import <wtf/OSObjectPtr.h>
+#import <wtf/spi/darwin/XPCSPI.h>
+#import <wtf/text/WTFString.h>
+
+namespace WebPushD {
+
+class PushAppBundle;
+class ClientConnection;
+
+class AppBundleRequest : public PushAppBundleClient {
+    WTF_MAKE_FAST_ALLOCATED;
+public:
+    virtual ~AppBundleRequest();
+
+    virtual const char* transactionDescription() const = 0;
+
+    void start();
+    void cancel();
+
+protected:
+    AppBundleRequest(ClientConnection&, const String& originString);
+
+    void cleanupAfterCompletionHandler();
+
+    WeakPtr<ClientConnection> m_connection;
+    String m_originString;
+    RefPtr<PushAppBundle> m_appBundle;
+    OSObjectPtr<os_transaction_t> m_transaction;
+
+private:
+    virtual void startInternal() = 0;
+};
+
+template<typename CompletionType>
+class AppBundleRequestImpl : public AppBundleRequest {
+protected:
+    AppBundleRequestImpl(ClientConnection& connection, const String& originString, CompletionHandler<void(CompletionType)>&& completionHandler)
+        : AppBundleRequest(connection, originString)
+        , m_completionHandler(WTFMove(completionHandler))
+    {
+    }
+
+    virtual ~AppBundleRequestImpl()
+    {
+        ASSERT(!m_appBundle);
+    }
+
+    void callCompletionHandlerAndCleanup(CompletionType result)
+    {
+        ASSERT(m_completionHandler);
+        m_completionHandler(result);
+
+        cleanupAfterCompletionHandler();
+    }
+
+    virtual void startInternal() = 0;
+    virtual const char* transactionDescription() const = 0;
+
+private:
+    CompletionHandler<void(CompletionType)> m_completionHandler;
+};
+
+class AppBundlePermissionsRequest : public AppBundleRequestImpl<bool> {
+public:
+    AppBundlePermissionsRequest(ClientConnection& connection, const String& originString, CompletionHandler<void(bool)>&& completionHandler)
+        : AppBundleRequestImpl(connection, originString, WTFMove(completionHandler))
+    {
+    }
+
+private:
+    const char* transactionDescription() const final { return "WebPush Permissions Bundle Request"; }
+
+    void startInternal() final;
+    void didCheckForExistingBundle(PushAppBundle&, PushAppBundleExists) final;
+    void didDeleteExistingBundleWithError(PushAppBundle&, NSError *) final { RELEASE_ASSERT_NOT_REACHED(); }
+    void didCreateAppBundle(PushAppBundle&, PushAppBundleCreationResult) final;
+};
+
+class AppBundleDeletionRequest : public AppBundleRequestImpl<const String&> {
+public:
+    AppBundleDeletionRequest(ClientConnection& connection, const String& originString, CompletionHandler<void(const String&)>&& completionHandler)
+        : AppBundleRequestImpl(connection, originString,  WTFMove(completionHandler))
+    {
+    }
+
+private:
+    const char* transactionDescription() const final { return "WebPush Bundle Deletion Request"; }
+
+    void startInternal() final;
+    void didCheckForExistingBundle(PushAppBundle&, PushAppBundleExists) final  { RELEASE_ASSERT_NOT_REACHED(); }
+    void didDeleteExistingBundleWithError(PushAppBundle&, NSError *) final;
+    void didCreateAppBundle(PushAppBundle&, PushAppBundleCreationResult) final  { RELEASE_ASSERT_NOT_REACHED(); }
+};
+
+} // namespace WebPushD

Added: trunk/Source/WebKit/webpushd/AppBundleRequest.mm (0 => 286273)


--- trunk/Source/WebKit/webpushd/AppBundleRequest.mm	                        (rev 0)
+++ trunk/Source/WebKit/webpushd/AppBundleRequest.mm	2021-11-30 00:20:57 UTC (rev 286273)
@@ -0,0 +1,123 @@
+/*
+ * 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 "AppBundleRequest.h"
+
+#import "MockAppBundleForTesting.h"
+#import "WebPushDaemon.h"
+#import <_javascript_Core/ConsoleTypes.h>
+
+namespace WebPushD {
+
+AppBundleRequest::AppBundleRequest(ClientConnection& connection, const String& originString)
+    : m_connection(&connection)
+    , m_originString(originString)
+{
+}
+
+AppBundleRequest::~AppBundleRequest()
+{
+    ASSERT(!m_appBundle);
+}
+
+void AppBundleRequest::start()
+{
+    ASSERT(m_connection);
+
+    m_transaction = adoptOSObject(os_transaction_create(transactionDescription()));
+
+    m_appBundle = MockAppBundleForTesting::create(m_originString, m_connection->hostAppCodeSigningIdentifier(), *this);
+    startInternal();
+}
+
+void AppBundleRequest::cancel()
+{
+    ASSERT(m_connection);
+
+    if (m_appBundle) {
+        m_appBundle->stop();
+        m_appBundle = nullptr;
+    }
+}
+
+void AppBundleRequest::cleanupAfterCompletionHandler()
+{
+    if (m_appBundle) {
+        m_appBundle->detachFromClient();
+        m_appBundle = nullptr;
+    }
+
+    m_transaction = nullptr;
+
+    if (m_connection)
+        m_connection->didCompleteAppBundleRequest(*this);
+}
+
+// App bundle permissions
+
+void AppBundlePermissionsRequest::startInternal()
+{
+    m_appBundle->checkForExistingBundle();
+}
+
+void AppBundlePermissionsRequest::didCheckForExistingBundle(PushAppBundle& bundle, PushAppBundleExists exists)
+{
+    ASSERT_UNUSED(bundle, &bundle == m_appBundle.get());
+
+    if (exists == PushAppBundleExists::Yes)
+        return callCompletionHandlerAndCleanup(true);
+
+    m_appBundle->createBundle();
+}
+
+void AppBundlePermissionsRequest::didCreateAppBundle(PushAppBundle& bundle, PushAppBundleCreationResult result)
+{
+    ASSERT_UNUSED(bundle, &bundle == m_appBundle.get());
+
+    if (result == PushAppBundleCreationResult::Failure)
+        return callCompletionHandlerAndCleanup(false);
+
+    callCompletionHandlerAndCleanup(true);
+}
+
+// App bundle deletion
+
+void AppBundleDeletionRequest::startInternal()
+{
+    m_appBundle->deleteExistingBundle();
+}
+
+void AppBundleDeletionRequest::didDeleteExistingBundleWithError(PushAppBundle& bundle, NSError *error)
+{
+    ASSERT_UNUSED(bundle, &bundle == m_appBundle.get());
+
+    if (error)
+        Daemon::singleton().broadcastDebugMessage(MessageLevel::Info, makeString("Failed to delete app bundle: ", String([error description])));
+
+    callCompletionHandlerAndCleanup(error ? String([error description]) : "");
+}
+
+} // namespace WebPushD

Copied: trunk/Source/WebKit/webpushd/MockAppBundleForTesting.h (from rev 286272, trunk/Source/WebKit/webpushd/PushClientConnection.h) (0 => 286273)


--- trunk/Source/WebKit/webpushd/MockAppBundleForTesting.h	                        (rev 0)
+++ trunk/Source/WebKit/webpushd/MockAppBundleForTesting.h	2021-11-30 00:20:57 UTC (rev 286273)
@@ -0,0 +1,57 @@
+/*
+ * 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 "PushAppBundle.h"
+#include <wtf/Vector.h>
+#include <wtf/text/WTFString.h>
+
+namespace WebPushD {
+
+class MockAppBundleForTesting : public PushAppBundle {
+    WTF_MAKE_FAST_ALLOCATED;
+public:
+    static Ref<MockAppBundleForTesting> create(const String& originString, const String& hostAppBundleIdentifier, PushAppBundleClient& client)
+    {
+        return adoptRef(*new MockAppBundleForTesting(originString, hostAppBundleIdentifier, client));
+    }
+
+    ~MockAppBundleForTesting() final = default;
+
+private:
+    MockAppBundleForTesting(const String& originString, const String& hostAppBundleIdentifier, PushAppBundleClient&);
+
+    void checkForExistingBundle() final;
+    void deleteExistingBundle() final;
+    void createBundle() final;
+    void stop() final;
+
+    String m_originString;
+    String m_hostAppBundleIdentifier;
+};
+
+
+} // namespace WebPushD

Added: trunk/Source/WebKit/webpushd/MockAppBundleForTesting.mm (0 => 286273)


--- trunk/Source/WebKit/webpushd/MockAppBundleForTesting.mm	                        (rev 0)
+++ trunk/Source/WebKit/webpushd/MockAppBundleForTesting.mm	2021-11-30 00:20:57 UTC (rev 286273)
@@ -0,0 +1,72 @@
+/*
+ * 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 "MockAppBundleForTesting.h"
+
+#import "MockAppBundleRegistry.h"
+#import <wtf/MainThread.h>
+
+namespace WebPushD {
+
+MockAppBundleForTesting::MockAppBundleForTesting(const String& originString, const String& hostAppBundleIdentifier, PushAppBundleClient& client)
+    : PushAppBundle(client)
+    , m_originString(originString)
+    , m_hostAppBundleIdentifier(hostAppBundleIdentifier)
+{
+}
+
+void MockAppBundleForTesting::checkForExistingBundle()
+{
+    callOnMainRunLoop([protectedThis = Ref { *this }, this] {
+        bool exists = MockAppBundleRegistry::singleton().doesBundleExist(m_hostAppBundleIdentifier, m_originString);
+        if (m_client)
+            m_client->didCheckForExistingBundle(*this, exists ? PushAppBundleExists::Yes : PushAppBundleExists::No);
+    });
+}
+
+void MockAppBundleForTesting::deleteExistingBundle()
+{
+    callOnMainRunLoop([protectedThis = Ref { *this }, this] {
+        MockAppBundleRegistry::singleton().deleteBundle(m_hostAppBundleIdentifier, m_originString);
+        if (m_client)
+            m_client->didDeleteExistingBundleWithError(*this, nil);
+    });
+}
+
+void MockAppBundleForTesting::createBundle()
+{
+    callOnMainRunLoop([protectedThis = Ref { *this }, this] {
+        MockAppBundleRegistry::singleton().createBundle(m_hostAppBundleIdentifier, m_originString);
+        if (m_client)
+            m_client->didCreateAppBundle(*this, PushAppBundleCreationResult::Success);
+    });
+}
+
+void MockAppBundleForTesting::stop()
+{
+}
+
+} // namespace WebPushD

Copied: trunk/Source/WebKit/webpushd/MockAppBundleRegistry.h (from rev 286272, trunk/Source/WebKit/webpushd/PushClientConnection.h) (0 => 286273)


--- trunk/Source/WebKit/webpushd/MockAppBundleRegistry.h	                        (rev 0)
+++ trunk/Source/WebKit/webpushd/MockAppBundleRegistry.h	2021-11-30 00:20:57 UTC (rev 286273)
@@ -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
+
+#include <wtf/HashMap.h>
+#include <wtf/HashSet.h>
+#include <wtf/text/StringHash.h>
+#include <wtf/text/WTFString.h>
+
+namespace WebPushD {
+
+class MockAppBundleForTesting;
+
+class MockAppBundleRegistry {
+    friend class MockAppBundleForTesting;
+public:
+    static MockAppBundleRegistry& singleton();
+
+    Vector<String> getOriginsWithRegistrations(const String& hostAppBundleIdentifier);
+
+private:
+    bool doesBundleExist(const String& hostAppBundleIdentifier, const String& originString);
+    void createBundle(const String& hostAppBundleIdentifier, const String& originString);
+    void deleteBundle(const String& hostAppBundleIdentifier, const String& originString);
+
+    HashMap<String, HashSet<String>> m_registeredBundleMap;
+};
+
+} // namespace WebPushD

Added: trunk/Source/WebKit/webpushd/MockAppBundleRegistry.mm (0 => 286273)


--- trunk/Source/WebKit/webpushd/MockAppBundleRegistry.mm	                        (rev 0)
+++ trunk/Source/WebKit/webpushd/MockAppBundleRegistry.mm	2021-11-30 00:20:57 UTC (rev 286273)
@@ -0,0 +1,71 @@
+/*
+ * 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 "MockAppBundleRegistry.h"
+
+#import <wtf/NeverDestroyed.h>
+
+namespace WebPushD {
+
+MockAppBundleRegistry& MockAppBundleRegistry::singleton()
+{
+    static NeverDestroyed<MockAppBundleRegistry> registry;
+    return registry;
+}
+
+Vector<String> MockAppBundleRegistry::getOriginsWithRegistrations(const String& hostAppBundleIdentifier)
+{
+    Vector<String> results;
+    auto iterator = m_registeredBundleMap.find(hostAppBundleIdentifier);
+    if (iterator != m_registeredBundleMap.end())
+        results = copyToVector(iterator->value);
+    return results;
+}
+
+bool MockAppBundleRegistry::doesBundleExist(const String& hostAppBundleIdentifier, const String& originString)
+{
+    auto iterator = m_registeredBundleMap.find(hostAppBundleIdentifier);
+    return iterator != m_registeredBundleMap.end() && iterator->value.contains(originString);
+}
+
+void MockAppBundleRegistry::createBundle(const String& hostAppBundleIdentifier, const String& originString)
+{
+    m_registeredBundleMap.add(hostAppBundleIdentifier, HashSet<String> { }).iterator->value.add(originString);
+}
+
+void MockAppBundleRegistry::deleteBundle(const String& hostAppBundleIdentifier, const String& originString)
+{
+    auto iterator = m_registeredBundleMap.find(hostAppBundleIdentifier);
+    if (iterator == m_registeredBundleMap.end())
+        return;
+
+    iterator->value.remove(originString);
+
+    if (iterator->value.isEmpty())
+        m_registeredBundleMap.remove(iterator);
+}
+
+} // namespace WebPushD

Copied: trunk/Source/WebKit/webpushd/PushAppBundle.h (from rev 286272, trunk/Source/WebKit/webpushd/PushClientConnection.h) (0 => 286273)


--- trunk/Source/WebKit/webpushd/PushAppBundle.h	                        (rev 0)
+++ trunk/Source/WebKit/webpushd/PushAppBundle.h	2021-11-30 00:20:57 UTC (rev 286273)
@@ -0,0 +1,72 @@
+/*
+ * 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 <wtf/RefCounted.h>
+
+@class NSError;
+
+namespace WebPushD {
+
+enum class PushAppBundleExists : bool {
+    No,
+    Yes,
+};
+
+enum class PushAppBundleCreationResult : bool {
+    Failure,
+    Success,
+};
+
+class PushAppBundle;
+
+class PushAppBundleClient {
+public:
+    virtual ~PushAppBundleClient();
+
+    virtual void didCheckForExistingBundle(PushAppBundle&, PushAppBundleExists) = 0;
+    virtual void didDeleteExistingBundleWithError(PushAppBundle&, NSError *) = 0;
+    virtual void didCreateAppBundle(PushAppBundle&, PushAppBundleCreationResult) = 0;
+};
+
+class PushAppBundle : public RefCounted<PushAppBundle> {
+public:
+    virtual ~PushAppBundle();
+    void detachFromClient();
+
+    virtual void checkForExistingBundle() = 0;
+    virtual void deleteExistingBundle() = 0;
+    virtual void createBundle() = 0;
+    virtual void stop() = 0;
+
+protected:
+    PushAppBundle(PushAppBundleClient&);
+
+    PushAppBundleClient* m_client;
+};
+
+
+} // namespace WebPushD

Copied: trunk/Source/WebKit/webpushd/PushAppBundle.mm (from rev 286272, trunk/Source/WebKit/webpushd/PushClientConnection.h) (0 => 286273)


--- trunk/Source/WebKit/webpushd/PushAppBundle.mm	                        (rev 0)
+++ trunk/Source/WebKit/webpushd/PushAppBundle.mm	2021-11-30 00:20:57 UTC (rev 286273)
@@ -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.
+ */
+
+#import "config.h"
+#import "PushAppBundle.h"
+
+namespace WebPushD {
+
+PushAppBundleClient::~PushAppBundleClient()
+{
+}
+
+PushAppBundle::PushAppBundle(PushAppBundleClient& client)
+    : m_client(&client)
+{
+}
+
+PushAppBundle::~PushAppBundle()
+{
+    ASSERT(!m_client);
+}
+
+void PushAppBundle::detachFromClient()
+{
+    stop();
+    m_client = nullptr;
+}
+
+} // namespace WebPushD

Modified: trunk/Source/WebKit/webpushd/PushClientConnection.h (286272 => 286273)


--- trunk/Source/WebKit/webpushd/PushClientConnection.h	2021-11-30 00:20:30 UTC (rev 286272)
+++ trunk/Source/WebKit/webpushd/PushClientConnection.h	2021-11-30 00:20:57 UTC (rev 286273)
@@ -26,17 +26,22 @@
 #pragma once
 
 #include <optional>
+#include <wtf/Deque.h>
 #include <wtf/Forward.h>
 #include <wtf/OSObjectPtr.h>
+#include <wtf/RefCounted.h>
+#include <wtf/WeakPtr.h>
 #include <wtf/spi/darwin/XPCSPI.h>
 #include <wtf/text/WTFString.h>
 
 namespace WebPushD {
 
-class ClientConnection {
+class AppBundleRequest;
+
+class ClientConnection : public RefCounted<ClientConnection>, public CanMakeWeakPtr<ClientConnection> {
     WTF_MAKE_FAST_ALLOCATED;
 public:
-    ClientConnection(xpc_connection_t);
+    static Ref<ClientConnection> create(xpc_connection_t);
 
     bool hasHostAppAuditToken() const { return !!m_hostAppAuditToken; }
     void setHostAppAuditTokenData(const Vector<uint8_t>&);
@@ -47,7 +52,16 @@
     bool debugModeIsEnabled() const { return m_debugModeEnabled; }
     void setDebugModeIsEnabled(bool);
 
+    void enqueueAppBundleRequest(std::unique_ptr<AppBundleRequest>&&);
+    void didCompleteAppBundleRequest(AppBundleRequest&);
+
+    void connectionClosed();
+
 private:
+    ClientConnection(xpc_connection_t);
+
+    void maybeStartNextAppBundleRequest();
+    
     OSObjectPtr<xpc_connection_t> m_xpcConnection;
 
     std::optional<audit_token_t> m_hostAppAuditToken;
@@ -54,6 +68,9 @@
     std::optional<String> m_hostAppCodeSigningIdentifier;
     std::optional<bool> m_hostAppHasPushEntitlement;
 
+    Deque<std::unique_ptr<AppBundleRequest>> m_pendingBundleRequests;
+    std::unique_ptr<AppBundleRequest> m_currentBundleRequest;
+
     bool m_debugModeEnabled { false };
 };
 

Modified: trunk/Source/WebKit/webpushd/PushClientConnection.mm (286272 => 286273)


--- trunk/Source/WebKit/webpushd/PushClientConnection.mm	2021-11-30 00:20:30 UTC (rev 286272)
+++ trunk/Source/WebKit/webpushd/PushClientConnection.mm	2021-11-30 00:20:57 UTC (rev 286273)
@@ -26,6 +26,7 @@
 #import "config.h"
 #import "PushClientConnection.h"
 
+#import "AppBundleRequest.h"
 #import "CodeSigning.h"
 #import "WebPushDaemon.h"
 #import <_javascript_Core/ConsoleTypes.h>
@@ -34,6 +35,11 @@
 
 namespace WebPushD {
 
+Ref<ClientConnection> ClientConnection::create(xpc_connection_t connection)
+{
+    return adoptRef(*new ClientConnection(connection));
+}
+
 ClientConnection::ClientConnection(xpc_connection_t connection)
     : m_xpcConnection(connection)
 {
@@ -93,4 +99,49 @@
     Daemon::singleton().broadcastDebugMessage(MessageLevel::Info, message);
 }
 
+void ClientConnection::enqueueAppBundleRequest(std::unique_ptr<AppBundleRequest>&& request)
+{
+    RELEASE_ASSERT(m_xpcConnection);
+    m_pendingBundleRequests.append(WTFMove(request));
+    maybeStartNextAppBundleRequest();
+}
+
+void ClientConnection::maybeStartNextAppBundleRequest()
+{
+    RELEASE_ASSERT(m_xpcConnection);
+
+    if (m_currentBundleRequest || m_pendingBundleRequests.isEmpty())
+        return;
+
+    m_currentBundleRequest = m_pendingBundleRequests.takeFirst();
+    m_currentBundleRequest->start();
+}
+
+void ClientConnection::didCompleteAppBundleRequest(AppBundleRequest& request)
+{
+    // If our connection was closed there should be no in-progress bundle requests.
+    RELEASE_ASSERT(m_xpcConnection);
+
+    ASSERT(m_currentBundleRequest.get() == &request);
+    m_currentBundleRequest = nullptr;
+
+    maybeStartNextAppBundleRequest();
+}
+
+void ClientConnection::connectionClosed()
+{
+    RELEASE_ASSERT(m_xpcConnection);
+    m_xpcConnection = nullptr;
+
+    if (m_currentBundleRequest) {
+        m_currentBundleRequest->cancel();
+        m_currentBundleRequest = nullptr;
+    }
+
+    Deque<std::unique_ptr<AppBundleRequest>> pendingBundleRequests;
+    pendingBundleRequests.swap(m_pendingBundleRequests);
+    for (auto& requst : pendingBundleRequests)
+        requst->cancel();
+}
+
 } // namespace WebPushD

Modified: trunk/Source/WebKit/webpushd/WebPushDaemon.h (286272 => 286273)


--- trunk/Source/WebKit/webpushd/WebPushDaemon.h	2021-11-30 00:20:30 UTC (rev 286272)
+++ trunk/Source/WebKit/webpushd/WebPushDaemon.h	2021-11-30 00:20:57 UTC (rev 286273)
@@ -71,10 +71,7 @@
     bool canRegisterForNotifications(ClientConnection&);
 
     ClientConnection* toClientConnection(xpc_connection_t);
-
-    HashSet<String> m_inMemoryOriginStringsWithPermissionForTesting;
-
-    HashMap<xpc_connection_t, std::unique_ptr<ClientConnection>> m_connectionMap;
+    HashMap<xpc_connection_t, Ref<ClientConnection>> m_connectionMap;
 };
 
 } // namespace WebPushD

Modified: trunk/Source/WebKit/webpushd/WebPushDaemon.mm (286272 => 286273)


--- trunk/Source/WebKit/webpushd/WebPushDaemon.mm	2021-11-30 00:20:30 UTC (rev 286272)
+++ trunk/Source/WebKit/webpushd/WebPushDaemon.mm	2021-11-30 00:20:57 UTC (rev 286273)
@@ -26,10 +26,12 @@
 #import "config.h"
 #import "WebPushDaemon.h"
 
+#import "AppBundleRequest.h"
 #import "DaemonDecoder.h"
 #import "DaemonEncoder.h"
 #import "DaemonUtilities.h"
 #import "HandleMessage.h"
+#import "MockAppBundleRegistry.h"
 #import "WebPushDaemonConstants.h"
 
 #import <wtf/CompletionHandler.h>
@@ -180,13 +182,14 @@
 void Daemon::connectionAdded(xpc_connection_t connection)
 {
     RELEASE_ASSERT(!m_connectionMap.contains(connection));
-    m_connectionMap.set(connection, WTF::makeUnique<ClientConnection>(connection));
+    m_connectionMap.set(connection, ClientConnection::create(connection));
 }
 
 void Daemon::connectionRemoved(xpc_connection_t connection)
 {
     RELEASE_ASSERT(m_connectionMap.contains(connection));
-    m_connectionMap.remove(connection);
+    auto clientConnection = m_connectionMap.take(connection);
+    clientConnection->connectionClosed();
 }
 
 CompletionHandler<void(EncodedMessage&&)> Daemon::createReplySender(MessageType messageType, OSObjectPtr<xpc_object_t>&& request)
@@ -253,10 +256,7 @@
         return;
     }
 
-    // FIXME: This is for an API testing checkpoint
-    // Next step is actually perform a persistent permissions request on a per-platform basis
-    m_inMemoryOriginStringsWithPermissionForTesting.add(originString);
-    replySender(true);
+    connection->enqueueAppBundleRequest(makeUnique<AppBundlePermissionsRequest>(*connection, originString, WTFMove(replySender)));
 }
 
 void Daemon::getOriginsWithPushAndNotificationPermissions(ClientConnection* connection, CompletionHandler<void(const Vector<String>&)>&& replySender)
@@ -266,9 +266,8 @@
         return;
     }
 
-    // FIXME: This is for an API testing checkpoint
-    // Next step is actually gather persistent permissions from the system on a per-platform basis
-    replySender(copyToVector(m_inMemoryOriginStringsWithPermissionForTesting));
+    // FIXME: This will need platform-specific implementations for real world bundles once implemented.
+    replySender(MockAppBundleRegistry::singleton().getOriginsWithRegistrations(connection->hostAppCodeSigningIdentifier()));
 }
 
 void Daemon::deletePushAndNotificationRegistration(ClientConnection* connection, const String& originString, CompletionHandler<void(const String&)>&& replySender)
@@ -278,12 +277,7 @@
         return;
     }
 
-    // FIXME: This is for an API testing checkpoint
-    // Next step is actually delete any persistent permissions on a per-platform basis
-    if (m_inMemoryOriginStringsWithPermissionForTesting.remove(originString))
-        replySender("");
-    else
-        replySender(makeString("Origin ", originString, " not registered for push or notifications"));
+    connection->enqueueAppBundleRequest(makeUnique<AppBundleDeletionRequest>(*connection, originString, WTFMove(replySender)));
 }
 
 void Daemon::setHostAppAuditToken(ClientConnection* clientConnection, const Vector<uint8_t>& tokenData)

Modified: trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/WebPushDaemon.mm (286272 => 286273)


--- trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/WebPushDaemon.mm	2021-11-30 00:20:30 UTC (rev 286272)
+++ trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/WebPushDaemon.mm	2021-11-30 00:20:57 UTC (rev 286273)
@@ -158,7 +158,7 @@
 }
 
 // FIXME: Re-enable this test for Monterey+ once webkit.org/232857 is resolved.
-#if __MAC_OS_X_VERSION_MIN_REQUIRED < 110000 || __MAC_OS_X_VERSION_MIN_REQUIRED >= 120000
+#if PLATFORM(MAC) && (__MAC_OS_X_VERSION_MIN_REQUIRED < 110000 || __MAC_OS_X_VERSION_MIN_REQUIRED >= 120000)
 TEST(WebPushD, DISABLED_BasicCommunication)
 #else
 TEST(WebPushD, BasicCommunication)
@@ -255,7 +255,7 @@
 )WEBPUSHRESOURCE";
 
 // FIXME: Re-enable this test for Monterey+ once webkit.org/232857 is resolved.
-#if __MAC_OS_X_VERSION_MIN_REQUIRED < 110000 || __MAC_OS_X_VERSION_MIN_REQUIRED >= 120000
+#if PLATFORM(MAC) && (__MAC_OS_X_VERSION_MIN_REQUIRED < 110000 || __MAC_OS_X_VERSION_MIN_REQUIRED >= 120000)
 TEST(WebPushD, DISABLED_PermissionManagement)
 #else
 TEST(WebPushD, PermissionManagement)
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to