Title: [290146] trunk
Revision
290146
Author
beid...@apple.com
Date
2022-02-18 11:01:21 -0800 (Fri, 18 Feb 2022)

Log Message

Add an InstallCoordination webpushd backend
https://bugs.webkit.org/show_bug.cgi?id=233714

Reviewed by Alex Christensen.

Source/WebCore/PAL:

Expose "toHexString" so we can SHA256 an arbitrary string to a hex representation.

* pal/crypto/CryptoDigest.h:
* pal/crypto/commoncrypto/CryptoDigestCommonCrypto.cpp:
(PAL::CryptoDigest::toHexString):

Source/WebKit:

Covered by API tests.

This patch lets the iOS build create a placeholder app bundle to represent a registration using InstallCoordination.

* Configurations/webpushd.xcconfig:
* WebKit.xcodeproj/project.pbxproj:

* webpushd/AppBundleRequest.mm:
(WebPushD::AppBundleRequest::start): Use the ICAppBundle implementation when appropriate.

* webpushd/ICAppBundle.h: Copied from Source/WebKit/webpushd/PushAppBundle.h.
(WebPushD::ICAppBundle::create):

* webpushd/ICAppBundle.mm: Added.
(-[WebAppInstallCoordinatorObserver initWithICAppBundle:]):
(-[WebAppInstallCoordinatorObserver coordinatorDidCompleteSuccessfully:forApplicationRecord:]):
(-[WebAppInstallCoordinatorObserver coordinator:canceledWithReason:client:]):
(WebPushD::broadcastDebugMessage):
(WebPushD::ICAppBundle::ICAppBundle):
(WebPushD::encodeOriginStringForBundleIdentifier):
(WebPushD::originStringFromEncodedBundleIdentifier):
(WebPushD::bundlePrefixForHostAppIdentifier):
(WebPushD::bundleNameForOriginStringAndHostAppIdentifier):
(WebPushD::ICAppBundle::getOriginsWithRegistrations):
(WebPushD::ICAppBundle::getBundleIdentifier):
(WebPushD::ICAppBundle::checkForExistingBundle):
(WebPushD::ICAppBundle::deleteExistingBundle):
(WebPushD::ICAppBundle::didDeleteExistingBundleWithError):
(WebPushD::ICAppBundle::stop):
(WebPushD::ICAppBundle::createBundle):
(WebPushD::ICAppBundle::bundleCreationSucceeded):
(WebPushD::ICAppBundle::bundleCreationFailed):

* webpushd/InstallCoordinationSPI.h: Added.
* webpushd/LaunchServicesSPI.h: Copied from Source/WebKit/webpushd/PushAppBundle.h.
* webpushd/PushAppBundle.h:

* webpushd/WebPushDaemon.mm:
(WebPushD::Daemon::getOriginsWithPushAndNotificationPermissions): Use the ICAppBundle implementation when appropriate.

Source/WTF:

* wtf/PlatformEnableCocoa.h:

Tools:

* TestWebKitAPI/Tests/WebKitCocoa/WebPushDaemon.mm:

WebKitLibraries:

* WebKitPrivateFrameworkStubs/iOS/15/InstallCoordination.framework/InstallCoordination.tbd: Added.

Modified Paths

Added Paths

Diff

Modified: trunk/Source/WTF/ChangeLog (290145 => 290146)


--- trunk/Source/WTF/ChangeLog	2022-02-18 18:59:32 UTC (rev 290145)
+++ trunk/Source/WTF/ChangeLog	2022-02-18 19:01:21 UTC (rev 290146)
@@ -1,3 +1,12 @@
+2022-02-18  Brady Eidson  <beid...@apple.com>
+
+        Add an InstallCoordination webpushd backend
+        https://bugs.webkit.org/show_bug.cgi?id=233714
+
+        Reviewed by Alex Christensen.
+
+        * wtf/PlatformEnableCocoa.h:
+
 2022-02-17  Matt Woodrow  <mattwood...@apple.com>
 
         Enable subgrid by default.

Modified: trunk/Source/WTF/wtf/PlatformEnableCocoa.h (290145 => 290146)


--- trunk/Source/WTF/wtf/PlatformEnableCocoa.h	2022-02-18 18:59:32 UTC (rev 290145)
+++ trunk/Source/WTF/wtf/PlatformEnableCocoa.h	2022-02-18 19:01:21 UTC (rev 290146)
@@ -143,6 +143,10 @@
 #define ENABLE_BUILT_IN_NOTIFICATIONS 1
 #endif
 
+#if !defined(ENABLE_INSTALL_COORDINATION_BUNDLES) && PLATFORM(IOS)
+#define ENABLE_INSTALL_COORDINATION_BUNDLES 1
+#endif
+
 #if !defined(ENABLE_CACHE_PARTITIONING)
 #define ENABLE_CACHE_PARTITIONING 1
 #endif

Modified: trunk/Source/WebCore/PAL/ChangeLog (290145 => 290146)


--- trunk/Source/WebCore/PAL/ChangeLog	2022-02-18 18:59:32 UTC (rev 290145)
+++ trunk/Source/WebCore/PAL/ChangeLog	2022-02-18 19:01:21 UTC (rev 290146)
@@ -1,3 +1,16 @@
+2022-02-18  Brady Eidson  <beid...@apple.com>
+
+        Add an InstallCoordination webpushd backend
+        https://bugs.webkit.org/show_bug.cgi?id=233714
+
+        Reviewed by Alex Christensen.
+
+        Expose "toHexString" so we can SHA256 an arbitrary string to a hex representation.
+
+        * pal/crypto/CryptoDigest.h:
+        * pal/crypto/commoncrypto/CryptoDigestCommonCrypto.cpp:
+        (PAL::CryptoDigest::toHexString):
+
 2022-02-18  Saam Barati  <sbar...@apple.com>
 
         Add LC_SOURCE_VERSION to compile targets

Modified: trunk/Source/WebCore/PAL/pal/crypto/CryptoDigest.h (290145 => 290146)


--- trunk/Source/WebCore/PAL/pal/crypto/CryptoDigest.h	2022-02-18 18:59:32 UTC (rev 290145)
+++ trunk/Source/WebCore/PAL/pal/crypto/CryptoDigest.h	2022-02-18 19:01:21 UTC (rev 290146)
@@ -27,6 +27,7 @@
 
 #include <wtf/Noncopyable.h>
 #include <wtf/Vector.h>
+#include <wtf/text/WTFString.h>
 
 namespace PAL {
 
@@ -47,6 +48,7 @@
 
     PAL_EXPORT void addBytes(const void* input, size_t length);
     PAL_EXPORT Vector<uint8_t> computeHash();
+    PAL_EXPORT String toHexString();
 
 private:
     CryptoDigest();

Modified: trunk/Source/WebCore/PAL/pal/crypto/commoncrypto/CryptoDigestCommonCrypto.cpp (290145 => 290146)


--- trunk/Source/WebCore/PAL/pal/crypto/commoncrypto/CryptoDigestCommonCrypto.cpp	2022-02-18 18:59:32 UTC (rev 290145)
+++ trunk/Source/WebCore/PAL/pal/crypto/commoncrypto/CryptoDigestCommonCrypto.cpp	2022-02-18 19:01:21 UTC (rev 290146)
@@ -182,4 +182,19 @@
     return result;
 }
 
+String CryptoDigest::toHexString()
+{
+    auto hash = computeHash();
+
+    char* start = 0;
+    unsigned hashLength = hash.size();
+    CString result = CString::newUninitialized(hashLength * 2, start);
+    char* buffer = start;
+    for (size_t i = 0; i < hashLength; ++i) {
+        snprintf(buffer, 3, "%02X", hash.at(i));
+        buffer += 2;
+    }
+    return String::fromUTF8(result);
+}
+
 } // namespace PAL

Modified: trunk/Source/WebKit/ChangeLog (290145 => 290146)


--- trunk/Source/WebKit/ChangeLog	2022-02-18 18:59:32 UTC (rev 290145)
+++ trunk/Source/WebKit/ChangeLog	2022-02-18 19:01:21 UTC (rev 290146)
@@ -1,3 +1,50 @@
+2022-02-18  Brady Eidson  <beid...@apple.com>
+
+        Add an InstallCoordination webpushd backend
+        https://bugs.webkit.org/show_bug.cgi?id=233714
+
+        Reviewed by Alex Christensen.
+
+        Covered by API tests.
+        
+        This patch lets the iOS build create a placeholder app bundle to represent a registration using InstallCoordination.
+        
+        * Configurations/webpushd.xcconfig:
+        * WebKit.xcodeproj/project.pbxproj:
+        
+        * webpushd/AppBundleRequest.mm:
+        (WebPushD::AppBundleRequest::start): Use the ICAppBundle implementation when appropriate.
+        
+        * webpushd/ICAppBundle.h: Copied from Source/WebKit/webpushd/PushAppBundle.h.
+        (WebPushD::ICAppBundle::create):
+        
+        * webpushd/ICAppBundle.mm: Added.
+        (-[WebAppInstallCoordinatorObserver initWithICAppBundle:]):
+        (-[WebAppInstallCoordinatorObserver coordinatorDidCompleteSuccessfully:forApplicationRecord:]):
+        (-[WebAppInstallCoordinatorObserver coordinator:canceledWithReason:client:]):
+        (WebPushD::broadcastDebugMessage):
+        (WebPushD::ICAppBundle::ICAppBundle):
+        (WebPushD::encodeOriginStringForBundleIdentifier):
+        (WebPushD::originStringFromEncodedBundleIdentifier):
+        (WebPushD::bundlePrefixForHostAppIdentifier):
+        (WebPushD::bundleNameForOriginStringAndHostAppIdentifier):
+        (WebPushD::ICAppBundle::getOriginsWithRegistrations):
+        (WebPushD::ICAppBundle::getBundleIdentifier):
+        (WebPushD::ICAppBundle::checkForExistingBundle):
+        (WebPushD::ICAppBundle::deleteExistingBundle):
+        (WebPushD::ICAppBundle::didDeleteExistingBundleWithError):
+        (WebPushD::ICAppBundle::stop):
+        (WebPushD::ICAppBundle::createBundle):
+        (WebPushD::ICAppBundle::bundleCreationSucceeded):
+        (WebPushD::ICAppBundle::bundleCreationFailed):
+        
+        * webpushd/InstallCoordinationSPI.h: Added.
+        * webpushd/LaunchServicesSPI.h: Copied from Source/WebKit/webpushd/PushAppBundle.h.
+        * webpushd/PushAppBundle.h:
+        
+        * webpushd/WebPushDaemon.mm:
+        (WebPushD::Daemon::getOriginsWithPushAndNotificationPermissions): Use the ICAppBundle implementation when appropriate.
+
 2022-02-18  Gavin Phillips  <gavi...@apple.com>
 
         Change domain used to hold whether CaptivePortalMode is active

Modified: trunk/Source/WebKit/Configurations/WebKit.xcconfig (290145 => 290146)


--- trunk/Source/WebKit/Configurations/WebKit.xcconfig	2022-02-18 18:59:32 UTC (rev 290145)
+++ trunk/Source/WebKit/Configurations/WebKit.xcconfig	2022-02-18 19:01:21 UTC (rev 290146)
@@ -152,8 +152,12 @@
 WK_LIBNETWORKEXTENSION_LDFLAGS_macosx = -weak_library /usr/lib/libnetworkextension.dylib;
 WK_LIBNETWORKEXTENSION_LDFLAGS_tvos = ;
 
-FRAMEWORK_AND_LIBRARY_LDFLAGS = -lobjc -framework CFNetwork -framework CoreAudio -framework CoreFoundation -framework CoreGraphics -framework CoreText -framework Foundation -framework ImageIO -framework IOKit -framework IOSurface -framework WebKitLegacy -lnetwork -framework Metal $(WK_ACCESSIBILITY_LDFLAGS) $(WK_APPKIT_LDFLAGS) $(WK_BACKBOARD_SERVICES_LDFLAGS) $(WK_RUNNINGBOARD_SERVICES_LDFLAGS) $(WK_AUTHKIT_LDFLAGS) $(WK_CARBON_LDFLAGS) $(WK_CONTACTS_LDFLAGS) $(WK_CORE_PREDICTION_LDFLAGS) $(WK_CORE_SERVICES_LDFLAGS) $(WK_GRAPHICS_SERVICES_LDFLAGS) $(WK_LIBNETWORKEXTENSION_LDFLAGS) $(WK_LIBSANDBOX_LDFLAGS) $(WK_LIBWEBRTC_LDFLAGS) $(WK_MOBILE_CORE_SERVICES_LDFLAGS) $(WK_MOBILE_GESTALT_LDFLAGS) $(WK_PDFKIT_LDFLAGS) $(WK_PROTOTYPE_TOOLS_LDFLAGS) $(WK_SAFE_BROWSING_LDFLAGS) $(WK_SECURITY_INTERFACE_LDFLAGS) $(WK_UIKIT_LDFLAGS) $(WK_UNIFORM_TYPE_IDENTIFIERS_LDFLAGS) $(WK_URL_FORMATTING_LDFLAGS) $(WK_WEBINSPECTORUI_LDFLAGS) $(WK_COORDINATOR_LDFLAGS);
+WK_INSTALL_COORDINATION_LDFLAGS = $(WK_INSTALL_COORDINATION_LDFLAGS_$(WK_PLATFORM_NAME));
+WK_INSTALL_COORDINATION_LDFLAGS_iphoneos = -framework InstallCoordination;
+WK_INSTALL_COORDINATION_LDFLAGS_iphonesimulator = $(WK_INSTALL_COORDINATION_LDFLAGS_iphoneos)
 
+FRAMEWORK_AND_LIBRARY_LDFLAGS = -lobjc -framework CFNetwork -framework CoreAudio -framework CoreFoundation -framework CoreGraphics -framework CoreText -framework Foundation -framework ImageIO -framework IOKit -framework IOSurface -framework WebKitLegacy -lnetwork -framework Metal $(WK_ACCESSIBILITY_LDFLAGS) $(WK_APPKIT_LDFLAGS) $(WK_BACKBOARD_SERVICES_LDFLAGS) $(WK_RUNNINGBOARD_SERVICES_LDFLAGS) $(WK_AUTHKIT_LDFLAGS) $(WK_CARBON_LDFLAGS) $(WK_CONTACTS_LDFLAGS) $(WK_CORE_PREDICTION_LDFLAGS) $(WK_CORE_SERVICES_LDFLAGS) $(WK_GRAPHICS_SERVICES_LDFLAGS) $(WK_LIBNETWORKEXTENSION_LDFLAGS) $(WK_LIBSANDBOX_LDFLAGS) $(WK_LIBWEBRTC_LDFLAGS) $(WK_MOBILE_CORE_SERVICES_LDFLAGS) $(WK_MOBILE_GESTALT_LDFLAGS) $(WK_PDFKIT_LDFLAGS) $(WK_PROTOTYPE_TOOLS_LDFLAGS) $(WK_SAFE_BROWSING_LDFLAGS) $(WK_SECURITY_INTERFACE_LDFLAGS) $(WK_UIKIT_LDFLAGS) $(WK_UNIFORM_TYPE_IDENTIFIERS_LDFLAGS) $(WK_URL_FORMATTING_LDFLAGS) $(WK_WEBINSPECTORUI_LDFLAGS) $(WK_COORDINATOR_LDFLAGS) $(WK_INSTALL_COORDINATION_LD
 FLAGS);
+
 // Prevent C++ standard library basic_stringstream, operator new, delete and their related exception types from being exported as weak symbols.
 UNEXPORTED_SYMBOL_LDFLAGS = -Wl,-unexported_symbol -Wl,__ZTISt9bad_alloc -Wl,-unexported_symbol -Wl,__ZTISt9exception -Wl,-unexported_symbol -Wl,__ZTSSt9bad_alloc -Wl,-unexported_symbol -Wl,__ZTSSt9exception -Wl,-unexported_symbol -Wl,__ZdlPvS_ -Wl,-unexported_symbol -Wl,__ZnwmPv -Wl,-unexported_symbol -Wl,__Znwm -Wl,-unexported_symbol -Wl,__ZTVNSt3__117bad_function_callE -Wl,-unexported_symbol -Wl,__ZTCNSt3__118basic_stringstreamIcNS_11char_traitsIcEENS_9allocatorIcEEEE0_NS_13basic_istreamIcS2_EE -Wl,-unexported_symbol -Wl,__ZTCNSt3__118basic_stringstreamIcNS_11char_traitsIcEENS_9allocatorIcEEEE0_NS_14basic_iostreamIcS2_EE -Wl,-unexported_symbol -Wl,__ZTCNSt3__118basic_stringstreamIcNS_11char_traitsIcEENS_9allocatorIcEEEE16_NS_13basic_ostreamIcS2_EE -Wl,-unexported_symbol -Wl,__ZTTNSt3__118basic_stringstreamIcNS_11char_traitsIcEENS_9allocatorIcEEEE -Wl,-unexported_symbol -Wl,__ZTVNSt3__115basic_stringbufIcNS_11char_traitsIcEENS_9allocatorIcEEEE -Wl,-unexport
 ed_symbol -Wl,__ZTVNSt3__118basic_stringstreamIcNS_11char_traitsIcEENS_9allocatorIcEEEE -Wl,-unexported_symbol -Wl,__ZTCNSt3__118basic_stringstreamIcNS_11char_traitsIcEENS_9allocatorIcEEEE8_NS_13basic_ostreamIcS2_EE;
 

Modified: trunk/Source/WebKit/NetworkProcess/Notifications/NetworkNotificationManager.cpp (290145 => 290146)


--- trunk/Source/WebKit/NetworkProcess/Notifications/NetworkNotificationManager.cpp	2022-02-18 18:59:32 UTC (rev 290145)
+++ trunk/Source/WebKit/NetworkProcess/Notifications/NetworkNotificationManager.cpp	2022-02-18 19:01:21 UTC (rev 290146)
@@ -70,6 +70,7 @@
 
 void NetworkNotificationManager::requestSystemNotificationPermission(const String& originString, CompletionHandler<void(bool)>&& completionHandler)
 {
+    LOG(Push, "Network process passing permission request to webpushd");
     sendMessageWithReply<WebPushD::MessageType::RequestSystemNotificationPermission>(WTFMove(completionHandler), originString);
 }
 

Modified: trunk/Source/WebKit/UIProcess/Cocoa/UIDelegate.mm (290145 => 290146)


--- trunk/Source/WebKit/UIProcess/Cocoa/UIDelegate.mm	2022-02-18 18:59:32 UTC (rev 290145)
+++ trunk/Source/WebKit/UIProcess/Cocoa/UIDelegate.mm	2022-02-18 19:01:21 UTC (rev 290146)
@@ -667,6 +667,7 @@
         if (checker->completionHandlerHasBeenCalled())
             return;
         checker->didCallCompletionHandler();
+
         completionHandler(result);
     }).get()];
 }

Modified: trunk/Source/WebKit/WebKit.xcodeproj/project.pbxproj (290145 => 290146)


--- trunk/Source/WebKit/WebKit.xcodeproj/project.pbxproj	2022-02-18 18:59:32 UTC (rev 290145)
+++ trunk/Source/WebKit/WebKit.xcodeproj/project.pbxproj	2022-02-18 19:01:21 UTC (rev 290146)
@@ -1059,6 +1059,12 @@
 		51DD9F2816367DA2001578E9 /* NetworkConnectionToWebProcessMessageReceiver.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 51DD9F2616367DA2001578E9 /* NetworkConnectionToWebProcessMessageReceiver.cpp */; };
 		51DD9F2916367DA2001578E9 /* NetworkConnectionToWebProcessMessages.h in Headers */ = {isa = PBXBuildFile; fileRef = 51DD9F2716367DA2001578E9 /* NetworkConnectionToWebProcessMessages.h */; };
 		51E351CB180F2CCC00E53BE9 /* IDBUtilities.h in Headers */ = {isa = PBXBuildFile; fileRef = 51E351C9180F2CCC00E53BE9 /* IDBUtilities.h */; };
+		51E9049527BCB3C900929E7E /* ICAppBundle.h in Headers */ = {isa = PBXBuildFile; fileRef = 51E9049327BCB3C600929E7E /* ICAppBundle.h */; };
+		51E9049727BCB3D900929E7E /* ICAppBundle.mm in Sources */ = {isa = PBXBuildFile; fileRef = 51E9049427BCB3C800929E7E /* ICAppBundle.mm */; };
+		51E9049A27BCB9D400929E7E /* LaunchServicesSPI.h in Headers */ = {isa = PBXBuildFile; fileRef = 51E9049827BCB9D100929E7E /* LaunchServicesSPI.h */; };
+		51E9049B27BCB9D400929E7E /* LaunchServicesSPI.h in Headers */ = {isa = PBXBuildFile; fileRef = 51E9049827BCB9D100929E7E /* LaunchServicesSPI.h */; };
+		51E9049C27BCB9D400929E7E /* InstallCoordinationSPI.h in Headers */ = {isa = PBXBuildFile; fileRef = 51E9049927BCB9D300929E7E /* InstallCoordinationSPI.h */; };
+		51E9049D27BCB9D400929E7E /* InstallCoordinationSPI.h in Headers */ = {isa = PBXBuildFile; fileRef = 51E9049927BCB9D300929E7E /* InstallCoordinationSPI.h */; };
 		51EFC1CF1524E62500C9A938 /* WKBundleDOMWindowExtension.h in Headers */ = {isa = PBXBuildFile; fileRef = 51FA2D541521118600C1BA0B /* WKBundleDOMWindowExtension.h */; settings = {ATTRIBUTES = (Private, ); }; };
 		51F060E01654317F00F3281B /* WebResourceLoaderMessages.h in Headers */ = {isa = PBXBuildFile; fileRef = 51F060DE1654317500F3281B /* WebResourceLoaderMessages.h */; };
 		51F060E11654318500F3281B /* WebResourceLoaderMessageReceiver.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 51F060DD1654317500F3281B /* WebResourceLoaderMessageReceiver.cpp */; };
@@ -4598,6 +4604,10 @@
 		51E351C9180F2CCC00E53BE9 /* IDBUtilities.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IDBUtilities.h; sourceTree = "<group>"; };
 		51E399051D6F54C5009C8831 /* UIGamepadProviderCocoa.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = UIGamepadProviderCocoa.mm; sourceTree = "<group>"; };
 		51E8B68D1E712873001B7132 /* WebURLSchemeTask.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WebURLSchemeTask.cpp; sourceTree = "<group>"; };
+		51E9049327BCB3C600929E7E /* ICAppBundle.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ICAppBundle.h; sourceTree = "<group>"; };
+		51E9049427BCB3C800929E7E /* ICAppBundle.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ICAppBundle.mm; sourceTree = "<group>"; };
+		51E9049827BCB9D100929E7E /* LaunchServicesSPI.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LaunchServicesSPI.h; sourceTree = "<group>"; };
+		51E9049927BCB9D300929E7E /* InstallCoordinationSPI.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = InstallCoordinationSPI.h; sourceTree = "<group>"; };
 		51E949961D761CC700EC9EB9 /* UIGamepadProviderIOS.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = UIGamepadProviderIOS.mm; sourceTree = "<group>"; };
 		51F060DD1654317500F3281B /* WebResourceLoaderMessageReceiver.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = WebResourceLoaderMessageReceiver.cpp; path = DerivedSources/WebKit/WebResourceLoaderMessageReceiver.cpp; sourceTree = BUILT_PRODUCTS_DIR; };
 		51F060DD1654317500F3281C /* LibWebRTCNetworkMessageReceiver.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = LibWebRTCNetworkMessageReceiver.cpp; path = DerivedSources/WebKit/LibWebRTCNetworkMessageReceiver.cpp; sourceTree = BUILT_PRODUCTS_DIR; };
@@ -10218,6 +10228,10 @@
 				EBA8D3AC27A5E33E00CB7900 /* ApplePushServiceConnection.mm */,
 				EB0D312E275AE13300863D8F /* com.apple.webkit.webpushd.ios.plist */,
 				EB0D312D275AE13300863D8F /* com.apple.webkit.webpushd.mac.plist */,
+				51E9049327BCB3C600929E7E /* ICAppBundle.h */,
+				51E9049427BCB3C800929E7E /* ICAppBundle.mm */,
+				51E9049927BCB9D300929E7E /* InstallCoordinationSPI.h */,
+				51E9049827BCB9D100929E7E /* LaunchServicesSPI.h */,
 				51F7BB75274498BB00C45A72 /* MockAppBundleForTesting.h */,
 				51F7BB74274498BA00C45A72 /* MockAppBundleForTesting.mm */,
 				5160E95C274C2A0300567388 /* MockAppBundleRegistry.h */,
@@ -12822,6 +12836,9 @@
 			isa = PBXHeadersBuildPhase;
 			buildActionMask = 2147483647;
 			files = (
+				51E9049B27BCB9D400929E7E /* LaunchServicesSPI.h in Headers */,
+				51E9049527BCB3C900929E7E /* ICAppBundle.h in Headers */,
+				51E9049D27BCB9D400929E7E /* InstallCoordinationSPI.h in Headers */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
@@ -13356,6 +13373,7 @@
 				3754D5451B3A29FD003A4C7F /* NSInvocationSPI.h in Headers */,
 				41DD72AB2682167300A90C71 /* NWSPI.h in Headers */,
 				BC8ACA1316670D89004C1941 /* ObjCObjectGraph.h in Headers */,
+				51E9049A27BCB9D400929E7E /* LaunchServicesSPI.h in Headers */,
 				93085DCA26E29775000EC6A7 /* OriginStorageManager.h in Headers */,
 				F4EB4AFD269CD7F300D297AE /* OSStateSPI.h in Headers */,
 				7CF47FFB17275C57008ACB91 /* PageBanner.h in Headers */,
@@ -13569,6 +13587,7 @@
 				1AF05D8714688348008B1E81 /* TiledCoreAnimationDrawingAreaProxy.h in Headers */,
 				F48570A32644BEC500C05F71 /* Timeout.h in Headers */,
 				2F8336861FA139DF00C6E080 /* TouchBarMenuData.h in Headers */,
+				51E9049C27BCB9D400929E7E /* InstallCoordinationSPI.h in Headers */,
 				46BEB6E322FBB21A00269867 /* TransientLocalStorageNamespace.h in Headers */,
 				57EB2E3A21E1983E00B89CDF /* U2fAuthenticator.h in Headers */,
 				1AFE436618B6C081009C7A48 /* UIDelegate.h in Headers */,
@@ -15654,6 +15673,7 @@
 				07E19EFB23D401F10094FFB4 /* MediaPlayerPrivateRemoteMessageReceiver.cpp in Sources */,
 				1DF29E64257F37A3003C28AF /* MediaSourcePrivateRemoteMessageReceiver.cpp in Sources */,
 				9B4790912531563200EC11AB /* MessageArgumentDescriptions.cpp in Sources */,
+				51E9049727BCB3D900929E7E /* ICAppBundle.mm in Sources */,
 				517B5F84275E97B6002DC22D /* MockAppBundleForTesting.mm in Sources */,
 				517B5F86275E97B6002DC22D /* MockAppBundleRegistry.mm in Sources */,
 				EBA8D3B627A5E33F00CB7900 /* MockPushServiceConnection.mm in Sources */,

Modified: trunk/Source/WebKit/webpushd/AppBundleRequest.mm (290145 => 290146)


--- trunk/Source/WebKit/webpushd/AppBundleRequest.mm	2022-02-18 18:59:32 UTC (rev 290145)
+++ trunk/Source/WebKit/webpushd/AppBundleRequest.mm	2022-02-18 19:01:21 UTC (rev 290146)
@@ -26,6 +26,7 @@
 #import "config.h"
 #import "AppBundleRequest.h"
 
+#import "ICAppBundle.h"
 #import "MockAppBundleForTesting.h"
 #import "WebPushDaemon.h"
 #import <_javascript_Core/ConsoleTypes.h>
@@ -54,8 +55,12 @@
     if (m_connection->useMockBundlesForTesting())
         m_appBundle = MockAppBundleForTesting::create(m_originString, m_connection->hostAppCodeSigningIdentifier(), *this);
     else {
+#if ENABLE(INSTALL_COORDINATION_BUNDLES)
+        m_appBundle = ICAppBundle::create(*m_connection, m_originString, *this);
+#else
         m_connection->broadcastDebugMessage("Client is trying to initiate app bundle request without having configured mock app bundles for testing. About to crash...");
         RELEASE_ASSERT_NOT_REACHED();
+#endif
     }
 
     startInternal();

Added: trunk/Source/WebKit/webpushd/ICAppBundle.h (0 => 290146)


--- trunk/Source/WebKit/webpushd/ICAppBundle.h	                        (rev 0)
+++ trunk/Source/WebKit/webpushd/ICAppBundle.h	2022-02-18 19:01:21 UTC (rev 290146)
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2022 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.
+ */
+
+#if ENABLE(INSTALL_COORDINATION_BUNDLES)
+
+#import "InstallCoordinationSPI.h"
+#import "PushAppBundle.h"
+#import <wtf/RetainPtr.h>
+#import <wtf/WeakPtr.h>
+#import <wtf/text/WTFString.h>
+
+@class NSError;
+@class _WKAppInstallCoordinatorObserver;
+
+namespace WebPushD {
+
+class ClientConnection;
+
+class ICAppBundle : public PushAppBundle, public CanMakeWeakPtr<ICAppBundle> {
+    WTF_MAKE_FAST_ALLOCATED;
+public:
+    static Ref<ICAppBundle> create(ClientConnection& connection, const String& originString, PushAppBundleClient& client)
+    {
+        return adoptRef(*new ICAppBundle(connection, originString, client));
+    }
+
+    void bundleCreationSucceeded();
+    void bundleCreationFailed(NSError *);
+
+    static void getOriginsWithRegistrations(ClientConnection&, CompletionHandler<void(const Vector<String>&)>&&);
+
+private:
+    ICAppBundle(ClientConnection&, const String& originString, PushAppBundleClient&);
+
+    const String& getBundleIdentifier();
+
+    void checkForExistingBundle() final;
+    void deleteExistingBundle() final;
+    void createBundle() final;
+    void stop() final;
+
+    void didDeleteExistingBundleWithError(NSError *);
+
+    RetainPtr<IXRestoringDemotedAppInstallCoordinator> m_appInstallCoordinator;
+    RetainPtr<_WKAppInstallCoordinatorObserver> m_appInstallObserver;
+
+    String m_originString;
+    RefPtr<ClientConnection> m_clientConnection;
+
+    String m_bundleIdentifier;
+};
+
+} // namespace WebPushD
+
+#endif // ENABLE(INSTALL_COORDINATION_BUNDLES)

Added: trunk/Source/WebKit/webpushd/ICAppBundle.mm (0 => 290146)


--- trunk/Source/WebKit/webpushd/ICAppBundle.mm	                        (rev 0)
+++ trunk/Source/WebKit/webpushd/ICAppBundle.mm	2022-02-18 19:01:21 UTC (rev 290146)
@@ -0,0 +1,321 @@
+/*
+ * Copyright (C) 2022 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 "ICAppBundle.h"
+
+#if ENABLE(INSTALL_COORDINATION_BUNDLES)
+
+#import "AppBundleRequest.h"
+#import "LaunchServicesSPI.h"
+#import "PushClientConnection.h"
+#import "WebPushDaemon.h"
+#import <_javascript_Core/ConsoleTypes.h>
+#import <pal/crypto/CryptoDigest.h>
+#import <wtf/MainThread.h>
+#import <wtf/text/Base64.h>
+#import <wtf/text/StringBuilder.h>
+
+NSString *pushBundleAppManagementDomain = @"com.apple.WebKit.PushBundles";
+
+@interface _WKAppInstallCoordinatorObserver : NSObject <IXAppInstallCoordinatorObserver>
+- (instancetype)initWithICAppBundle:(WebPushD::ICAppBundle&)icAppBundle;
+@property WeakPtr<WebPushD::ICAppBundle> bundle;
+@end
+
+@implementation _WKAppInstallCoordinatorObserver
+
+- (instancetype)initWithICAppBundle:(WebPushD::ICAppBundle&)icAppBundle
+{
+    if (!(self = [super init]))
+        return nil;
+
+    _bundle = icAppBundle;
+
+    return self;
+}
+
+- (void)coordinatorDidCompleteSuccessfully:(nonnull IXAppInstallCoordinator *)coordinator forApplicationRecord:(nullable LSApplicationRecord *)appRecord
+{
+    callOnMainRunLoop([self, protectedSelf = RetainPtr<id>(self)] {
+        if (_bundle)
+            _bundle->bundleCreationSucceeded();
+    });
+}
+
+- (void)coordinator:(nonnull IXAppInstallCoordinator *)coordinator canceledWithReason:(nonnull NSError *)cancelReason client:(IXClientIdentifier)client
+{
+    callOnMainRunLoop([self, protectedSelf = RetainPtr<id>(self), protectedCancelReason = RetainPtr<NSError>(cancelReason)] {
+        if (_bundle)
+            _bundle->bundleCreationFailed(protectedCancelReason.get());
+    });
+}
+
+@end
+
+using PAL::CryptoDigest;
+
+namespace WebPushD {
+
+static void broadcastDebugMessage(const String& message)
+{
+    Daemon::singleton().broadcastDebugMessage(JSC::MessageLevel::Info, makeString("ICAppBundle: ", message));
+}
+
+ICAppBundle::ICAppBundle(ClientConnection& clientConnection, const String& originString, PushAppBundleClient& client)
+    : PushAppBundle(client)
+    , m_originString(originString)
+    , m_clientConnection(&clientConnection)
+{
+}
+
+static String encodeOriginStringForBundleIdentifier(const String& input)
+{
+    // Bundle identifiers have exactly 64 valid characters.
+    // a-z, A-Z, 0-9, '-', and '.'
+    // Base64 URL encoding uses '-' and '_' for the final 2 characters
+    // For our bundle identifier, we'll Base64 URL encode then replace '_' with '.'
+    // We also get rid of the typical '=' padding for base64 encoding.
+
+    auto base64 = base64URLEncodeToVector(input.utf8());
+    for (size_t i = 0; i < base64.size(); ++i) {
+        if (base64[i] == '_')
+            base64[i] = '.';
+    }
+
+    size_t numberEqualSigns = 0;
+    if (base64.size() >= 1 && base64.last() == '=')
+        ++numberEqualSigns;
+    if (base64.size() >= 2 && base64[base64.size() - 2] == '=')
+        ++numberEqualSigns;
+
+    return String::fromUTF8(base64.data(), base64.size() - numberEqualSigns);
+}
+
+static String originStringFromEncodedBundleIdentifier(const String& input)
+{
+    auto utf8 = input.utf8();
+    auto buffer = utf8.mutableData();
+    for (size_t i = 0; i < utf8.length(); ++i) {
+        if (buffer[i] == '.')
+            buffer[i] = '_';
+    }
+
+    auto decoded = base64URLDecode(buffer, utf8.length());
+    if (!decoded)
+        return { };
+
+    return String::fromUTF8(decoded->data(), decoded->size());
+}
+
+static String bundlePrefixForHostAppIdentifier(const String& hostAppIdentifier)
+{
+    auto appDigest = PAL::CryptoDigest::create(CryptoDigest::Algorithm::SHA_256);
+    auto utf8Identifier = hostAppIdentifier.utf8();
+    appDigest->addBytes(utf8Identifier.data(), utf8Identifier.length());
+
+    return makeString("com.apple.WebKit.PushBundle.", appDigest->toHexString(), ".");
+}
+
+static String bundleNameForOriginStringAndHostAppIdentifier(const String& originString, const String& hostAppIdentifier)
+{
+    // FIXME: Once we can store the origin string within the app bundle, hash the origin string as well.
+    // For now we base64 encode it to make a valid bundle identifier that carries the information.
+    return makeString(bundlePrefixForHostAppIdentifier(hostAppIdentifier), encodeOriginStringForBundleIdentifier(originString));
+}
+
+void ICAppBundle::getOriginsWithRegistrations(ClientConnection& connection, CompletionHandler<void(const Vector<String>&)>&& completionHandler)
+{
+    Vector<String> results;
+
+    RetainPtr<NSString> bundleIdentifierPrefix = (NSString *)bundlePrefixForHostAppIdentifier(connection.hostAppCodeSigningIdentifier());
+
+    LSEnumerator<LSApplicationRecord *> *enumerator = [LSApplicationRecord enumeratorWithOptions:LSApplicationEnumerationOptionsEnumeratePlaceholders];
+    for (LSApplicationRecord *record = [enumerator nextObject]; record; record = [enumerator nextObject]) {
+        if (![record.managementDomain isEqualToString:pushBundleAppManagementDomain])
+            continue;
+
+        if (![record.bundleIdentifier hasPrefix:bundleIdentifierPrefix.get()])
+            continue;
+
+        // FIXME: For now we store the origin string in the bundle identifier base64 encoded
+        // Once we store it in the bundle itself, we'll hash the origin string in the bundle identifier and extract it from the bundle
+
+        NSArray *components = [record.bundleIdentifier componentsSeparatedByString:bundleIdentifierPrefix.get()];
+        ASSERT(components.count >= 2);
+
+        auto originString = originStringFromEncodedBundleIdentifier(components[1]);
+        if (originString.isEmpty())
+            continue;
+
+        results.append(originString);
+    }
+    
+    completionHandler(results);
+}
+
+const String& ICAppBundle::getBundleIdentifier()
+{
+    if (m_bundleIdentifier.isEmpty() && m_clientConnection)
+        m_bundleIdentifier = bundleNameForOriginStringAndHostAppIdentifier(m_originString, m_clientConnection->hostAppCodeSigningIdentifier());
+
+    return m_bundleIdentifier;
+}
+
+void ICAppBundle::checkForExistingBundle()
+{
+    NSError *error = nil;
+    RetainPtr<LSApplicationRecord> appRecord = adoptNS([[LSApplicationRecord alloc] initWithBundleIdentifier:(NSString *)getBundleIdentifier() allowPlaceholder:YES error:&error]);
+
+    if (m_client)
+        m_client->didCheckForExistingBundle(*this, appRecord ? PushAppBundleExists::Yes : PushAppBundleExists::No);
+}
+
+void ICAppBundle::deleteExistingBundle()
+{
+    [IXAppInstallCoordinator uninstallAppWithBundleID:(NSString *)getBundleIdentifier() requestUserConfirmation:NO completion:[this, protectedThis = Ref { *this }] (NSError *error) {
+        callOnMainRunLoop([this, protectedThis = Ref { *this }, error = RetainPtr<NSError>(error)] {
+            didDeleteExistingBundleWithError(error.get());
+        });
+    }];
+}
+
+void ICAppBundle::didDeleteExistingBundleWithError(NSError *error)
+{
+    if (error)
+        broadcastDebugMessage(makeString("Error deleting existing bundle: ", String([error description])));
+
+    if (m_client)
+        m_client->didDeleteExistingBundleWithError(*this, error);
+}
+
+void ICAppBundle::stop()
+{
+    m_appInstallCoordinator.get().observer = nil;
+    m_appInstallCoordinator = nil;
+    m_appInstallObserver = nil;
+}
+
+void ICAppBundle::createBundle()
+{
+    RetainPtr<NSString> bundleIdentifier = (NSString *)getBundleIdentifier();
+
+    // Cancel any previous install coordinator that might've been left hanging in a partially finished state
+    NSError *error = nil;
+    [IXAppInstallCoordinator cancelCoordinatorForAppWithBundleID:bundleIdentifier.get() withReason:[NSError errorWithDomain:@"WKErrorDomain" code:1 userInfo:nil] client:IXClientIdentifierAppliedFor error:&error];
+
+    BOOL created = NO;
+    error = nil;
+    m_appInstallCoordinator = [IXRestoringDemotedAppInstallCoordinator coordinatorForAppWithBundleID:bundleIdentifier.get() withClientID:IXClientIdentifierAppliedFor createIfNotExisting:YES created:&created error:&error];
+
+    if (!m_appInstallCoordinator || error) {
+        broadcastDebugMessage(makeString("Unable to create install coordinatior for app bundle identifier ", String(bundleIdentifier.get())));
+        bundleCreationFailed(error);
+        return;
+    }
+
+    if (!created) {
+        broadcastDebugMessage(makeString("Existing install coordinatior for app bundle identifier ", String(bundleIdentifier.get()), " was found. This is unexpected."));
+        bundleCreationFailed(error);
+        return;
+    }
+
+    m_appInstallObserver = adoptNS([[_WKAppInstallCoordinatorObserver alloc] initWithICAppBundle:*this]);
+    m_appInstallCoordinator.get().observer = m_appInstallObserver.get();
+
+    RetainPtr<IXPlaceholder> placeholder = adoptNS([[IXPlaceholder alloc] initAppPlaceholderWithBundleName:(NSString *)m_originString bundleID:bundleIdentifier.get() installType:LSInstallTypeIntentionalDowngrade client:IXClientIdentifierAppliedFor]);
+
+    RetainPtr<IXPlaceholderAttributes> placeholderAttributes = adoptNS([IXPlaceholderAttributes new]);
+    placeholderAttributes.get().launchProhibited = YES;
+
+    [placeholder setPlaceholderAttributes:placeholderAttributes.get() error:&error];
+    if (error) {
+        broadcastDebugMessage(makeString("Unable to set placeholder attributes for bundle ", String(bundleIdentifier.get()), " Error: ", String([error description])));
+        bundleCreationFailed(error);
+        return;
+    }
+
+    NSDictionary *entitlementsDictionary = @{
+        @"com.apple.private.usernotifications.bundle-identifiers": bundleIdentifier.get(),
+        @"com.apple.private.usernotifications.notification-simulator": @YES,
+        @"com.apple.developer.app-management-domain": pushBundleAppManagementDomain
+    };
+    RetainPtr<IXPromisedInMemoryDictionary> entitlementsPromise = adoptNS([[IXPromisedInMemoryDictionary alloc] initWithName:[NSString stringWithFormat:@"Entitlements Promise for %@", bundleIdentifier.get()] client:IXClientIdentifierAppliedFor dictionary:entitlementsDictionary]);
+
+    if (!entitlementsPromise) {
+        broadcastDebugMessage(makeString("Unable to create placeholder entitlements promise for bundle ", String(bundleIdentifier.get())));
+        bundleCreationFailed(error);
+        return;
+    }
+
+    error = nil;
+    if (![placeholder setEntitlementsPromise:entitlementsPromise.get() error:&error] || error) {
+        broadcastDebugMessage(makeString("Failed to set placeholder entitlements promise for bundle ", String(bundleIdentifier.get()), " Error: ", String([error description])));
+        bundleCreationFailed(error);
+        return;
+    }
+
+    BOOL result = [placeholder setConfigurationCompleteWithError:&error];
+    if (!result || error) {
+        broadcastDebugMessage(makeString("Failed to set placeholder entitlements promise complete for bundle ", String(bundleIdentifier.get()), " Error: ", String([error description])));
+        bundleCreationFailed(error);
+        return;
+    }
+
+    [m_appInstallCoordinator setPlaceholderPromise:placeholder.get() error:&error];
+    if (error) {
+        broadcastDebugMessage(makeString("Failed to set placeholder promise for bundle ", String(bundleIdentifier.get()), " Error: ", String([error description])));
+        bundleCreationFailed(error);
+        return;
+    }
+
+    RetainPtr<IXPromisedOutOfBandTransfer> dataPromise = adoptNS([[IXPromisedOutOfBandTransfer alloc] initWithName:@"Empty user data promise" client:IXClientIdentifierAppliedFor diskSpaceNeeded:0]);
+    dataPromise.get().percentComplete = 1.0;
+    dataPromise.get().complete = YES;
+
+    [m_appInstallCoordinator setUserDataPromise:dataPromise.get() error:&error];
+    if (error) {
+        broadcastDebugMessage(makeString("Failed to set user data promise for bundle ", String(bundleIdentifier.get()), " Error: ", String([error description])));
+        bundleCreationFailed(error);
+        return;
+    }
+}
+
+void ICAppBundle::bundleCreationSucceeded()
+{
+    if (m_client)
+        m_client->didCreateAppBundle(*this, PushAppBundleCreationResult::Success);
+
+}
+
+void ICAppBundle::bundleCreationFailed(NSError *error)
+{
+    if (m_client)
+        m_client->didCreateAppBundle(*this, PushAppBundleCreationResult::Failure);
+}
+
+} // namespace WebPushD
+
+#endif // ENABLE(INSTALL_COORDINATION_BUNDLES)

Added: trunk/Source/WebKit/webpushd/InstallCoordinationSPI.h (0 => 290146)


--- trunk/Source/WebKit/webpushd/InstallCoordinationSPI.h	                        (rev 0)
+++ trunk/Source/WebKit/webpushd/InstallCoordinationSPI.h	2022-02-18 19:01:21 UTC (rev 290146)
@@ -0,0 +1,110 @@
+/*
+ * Copyright (C) 2022 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.
+ */
+
+#if PLATFORM(IOS)
+#if USE(APPLE_INTERNAL_SDK)
+
+#import <InstallCoordination/IXAppInstallCoordinator.h>
+#import <InstallCoordination/InstallCoordination.h>
+
+#else
+
+#include "LaunchServicesSPI.h"
+
+NS_ASSUME_NONNULL_BEGIN
+
+typedef enum : NSUInteger {
+} IXCoordinatorProgressPhase;
+
+typedef enum : NSUInteger {
+    IXAppInstallCoordinatorPlaceholderPromise = 1,
+} IXAppInstallCoordinatorPromiseIdentifier;
+
+typedef enum : NSUInteger {
+    IXClientIdentifierAppliedFor = 19,
+} IXClientIdentifier;
+
+@class LSApplicationRecord;
+@class IXAppInstallCoordinator;
+@class IXPlaceholder;
+@class IXPromisedOutOfBandTransfer;
+
+@protocol IXAppInstallCoordinatorObserver <NSObject>
+@optional
+- (void)coordinatorDidRegisterForObservation:(nonnull IXAppInstallCoordinator *)coordinator;
+- (void)coordinatorShouldPrioritize:(nonnull IXAppInstallCoordinator *)coordinator;
+- (void)coordinatorShouldResume:(nonnull IXAppInstallCoordinator *)coordinator;
+- (void)coordinatorShouldPause:(nonnull IXAppInstallCoordinator *)coordinator;
+- (void)coordinator:(nonnull IXAppInstallCoordinator *)coordinator didUpdateProgress:(double)percentComplete forPhase:(IXCoordinatorProgressPhase)phase overallProgress:(double)overallProgress;
+- (void)coordinatorDidCompleteSuccessfully:(nonnull IXAppInstallCoordinator *)coordinator forApplicationRecord:(nullable LSApplicationRecord *)appRecord;
+- (void)coordinatorDidInstallPlaceholder:(nonnull IXAppInstallCoordinator *)coordinator forApplicationRecord:(nullable LSApplicationRecord *)placeholderRecord;
+- (void)coordinator:(nonnull IXAppInstallCoordinator *)coordinator canceledWithReason:(nonnull NSError *)cancelReason client:(IXClientIdentifier)client;
+@end
+
+typedef void (^IXAppInstallCoordinatorErrorCompletion)(NSError * _Nullable error);
+
+@interface IXAppInstallCoordinator
++ (void)uninstallAppWithBundleID:(NSString *)bundleID requestUserConfirmation:(BOOL)requestUserConfirmation completion:(IXAppInstallCoordinatorErrorCompletion)completion;
++ (BOOL)cancelCoordinatorForAppWithBundleID:(NSString *)bundleID withReason:(NSError *)cancelReason client:(IXClientIdentifier)client error:(NSError **)out_error;
++ (instancetype)coordinatorForAppWithBundleID:(NSString *)bundleID withClientID:(IXClientIdentifier)identity createIfNotExisting:(BOOL)create created:(BOOL *)out_created error:(NSError **)out_error;
+@property (nonatomic, nullable, weak) id<IXAppInstallCoordinatorObserver> observer;
+- (BOOL)setPlaceholderPromise:(IXPlaceholder *)placeholderPromise error:(NSError **)out_error;
+- (BOOL)setUserDataPromise:(IXPromisedOutOfBandTransfer *)userData error:(NSError **)out_error;
+@end
+
+@interface IXRestoringDemotedAppInstallCoordinator : IXAppInstallCoordinator
+@end
+
+@interface IXOwnedDataPromise : NSObject
+@end
+
+@interface IXPromisedInMemoryDictionary : IXOwnedDataPromise
+- (instancetype)initWithName:(NSString *)name client:(IXClientIdentifier)identity dictionary:(NSDictionary *)dictionary;
+@end
+
+@interface IXPlaceholderAttributes : NSObject
+@property (nonatomic) BOOL launchProhibited;
+@end
+
+@interface IXPlaceholder : NSObject
+- (instancetype)initAppPlaceholderWithBundleName:(NSString *)name bundleID:(NSString *)bundleID installType:(LSInstallType)installType client:(IXClientIdentifier)identity NS_DESIGNATED_INITIALIZER;
+- (BOOL)setPlaceholderAttributes:(nonnull IXPlaceholderAttributes *)attributes error:(NSError **)out_error;
+- (BOOL)setEntitlementsPromise:(nonnull IXOwnedDataPromise *)entitlements error:(NSError * __autoreleasing _Nullable * _Nullable)out_error;
+- (BOOL)setConfigurationCompleteWithError:(NSError **)out_error;
+@end
+
+@interface IXOpaqueDataPromise : NSObject
+@end
+
+@interface IXPromisedOutOfBandTransfer : IXOpaqueDataPromise
+@property (nonatomic) BOOL complete;
+@property (nonatomic) double percentComplete;
+- (instancetype)initWithName:(NSString *)name client:(IXClientIdentifier)identity diskSpaceNeeded:(uint64_t)totalBytes;
+@end
+
+NS_ASSUME_NONNULL_END
+
+#endif // USE(APPLE_INTERNAL_SDK)
+#endif // PLATFORM(IOS)

Copied: trunk/Source/WebKit/webpushd/LaunchServicesSPI.h (from rev 290145, trunk/Source/WebKit/webpushd/PushAppBundle.h) (0 => 290146)


--- trunk/Source/WebKit/webpushd/LaunchServicesSPI.h	                        (rev 0)
+++ trunk/Source/WebKit/webpushd/LaunchServicesSPI.h	2022-02-18 19:01:21 UTC (rev 290146)
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2022 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.
+ */
+
+#if PLATFORM(IOS)
+#if USE(APPLE_INTERNAL_SDK)
+
+// This space intentionally left blank
+
+#else
+
+NS_ASSUME_NONNULL_BEGIN
+
+typedef NS_ENUM(NSUInteger, LSInstallType) {
+    LSInstallTypeIntentionalDowngrade = 8
+};
+
+@interface LSRecord : NSObject
+@end
+
+@interface LSBundleRecord : LSRecord
+@property (readonly, nullable) NSString *bundleIdentifier;
+@end
+
+@interface LSApplicationRecord : LSBundleRecord
+@property (readonly) BOOL placeholder;
+@property (readonly) NSString *managementDomain;
+
+- (instancetype)initWithBundleIdentifier:(NSString *)bundleIdentifier allowPlaceholder:(BOOL)allowPlaceholder error:(NSError **)outError;
+@end
+
+@interface LSEnumerator<__covariant ObjectType> : NSEnumerator<ObjectType>
+@end
+
+typedef NS_OPTIONS(uint64_t, LSApplicationEnumerationOptions) {
+    LSApplicationEnumerationOptionsEnumeratePlaceholders = (1 << 6)
+};
+
+@interface LSApplicationRecord (Enumeration)
++ (LSEnumerator<LSApplicationRecord *> *)enumeratorWithOptions:(LSApplicationEnumerationOptions)options;
+@end
+
+NS_ASSUME_NONNULL_END
+
+#endif // USE(APPLE_INTERNAL_SDK)
+#endif // PLATFORM(IOS)

Modified: trunk/Source/WebKit/webpushd/PushAppBundle.h (290145 => 290146)


--- trunk/Source/WebKit/webpushd/PushAppBundle.h	2022-02-18 18:59:32 UTC (rev 290145)
+++ trunk/Source/WebKit/webpushd/PushAppBundle.h	2022-02-18 19:01:21 UTC (rev 290146)
@@ -25,7 +25,7 @@
 
 #pragma once
 
-#include <wtf/RefCounted.h>
+#include <wtf/ThreadSafeRefCounted.h>
 
 @class NSError;
 
@@ -52,7 +52,7 @@
     virtual void didCreateAppBundle(PushAppBundle&, PushAppBundleCreationResult) = 0;
 };
 
-class PushAppBundle : public RefCounted<PushAppBundle> {
+class PushAppBundle : public ThreadSafeRefCounted<PushAppBundle> {
 public:
     virtual ~PushAppBundle();
     void detachFromClient();

Modified: trunk/Source/WebKit/webpushd/WebPushDaemon.mm (290145 => 290146)


--- trunk/Source/WebKit/webpushd/WebPushDaemon.mm	2022-02-18 18:59:32 UTC (rev 290145)
+++ trunk/Source/WebKit/webpushd/WebPushDaemon.mm	2022-02-18 19:01:21 UTC (rev 290146)
@@ -31,6 +31,7 @@
 #import "DaemonEncoder.h"
 #import "DaemonUtilities.h"
 #import "HandleMessage.h"
+#import "ICAppBundle.h"
 #import "MockAppBundleRegistry.h"
 
 #import <WebCore/PushPermissionState.h>
@@ -441,8 +442,11 @@
         return;
     }
 
-    // FIXME: This will need platform-specific implementations for real world bundles once implemented.
-    replySender({ });
+#if ENABLE(INSTALL_COORDINATION_BUNDLES)
+    ICAppBundle::getOriginsWithRegistrations(*connection, WTFMove(replySender));
+#else
+    RELEASE_ASSERT_NOT_REACHED();
+#endif
 }
 
 void Daemon::deletePushAndNotificationRegistration(ClientConnection* connection, const String& originString, CompletionHandler<void(const String&)>&& replySender)

Modified: trunk/Tools/ChangeLog (290145 => 290146)


--- trunk/Tools/ChangeLog	2022-02-18 18:59:32 UTC (rev 290145)
+++ trunk/Tools/ChangeLog	2022-02-18 19:01:21 UTC (rev 290146)
@@ -1,3 +1,12 @@
+2022-02-18  Brady Eidson  <beid...@apple.com>
+
+        Add an InstallCoordination webpushd backend
+        https://bugs.webkit.org/show_bug.cgi?id=233714
+
+        Reviewed by Alex Christensen.
+
+        * TestWebKitAPI/Tests/WebKitCocoa/WebPushDaemon.mm:
+
 2022-02-07  Jonathan Bedard  <jbed...@apple.com>
 
         [EWS] Trigger Mac builders on pull-requests

Modified: trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/WebPushDaemon.mm (290145 => 290146)


--- trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/WebPushDaemon.mm	2022-02-18 18:59:32 UTC (rev 290145)
+++ trunk/Tools/TestWebKitAPI/Tests/WebKitCocoa/WebPushDaemon.mm	2022-02-18 19:01:21 UTC (rev 290146)
@@ -707,6 +707,100 @@
     ASSERT_TRUE([obj isEqual:expected]);
 }
 
+#if ENABLE(INSTALL_COORDINATION_BUNDLES)
+#if USE(APPLE_INTERNAL_SDK)
+static void deleteAllRegistrationsForDataStore(WKWebsiteDataStore *dataStore)
+{
+    __block bool originOperationDone = false;
+    __block RetainPtr<NSSet<WKSecurityOrigin *>> originSet;
+    [dataStore _getOriginsWithPushAndNotificationPermissions:^(NSSet<WKSecurityOrigin *> *origins) {
+        originSet = origins;
+        originOperationDone = true;
+    }];
+    TestWebKitAPI::Util::run(&originOperationDone);
+
+    if (![originSet count])
+        return;
+
+    __block size_t deletedOrigins = 0;
+    originOperationDone = false;
+    for (WKSecurityOrigin *origin in originSet.get()) {
+        [dataStore _deletePushAndNotificationRegistration:origin completionHandler:^(NSError *error) {
+            EXPECT_FALSE(!!error);
+            if (++deletedOrigins == [originSet count])
+                originOperationDone = true;
+        }];
+    }
+    TestWebKitAPI::Util::run(&originOperationDone);
+
+    originOperationDone = false;
+    [dataStore _getOriginsWithPushAndNotificationPermissions:^(NSSet<WKSecurityOrigin *> *origins) {
+        EXPECT_EQ([origins count], 0u);
+        originOperationDone = true;
+    }];
+    TestWebKitAPI::Util::run(&originOperationDone);
+
+}
+
+TEST(WebPushD, InstallCoordinationBundles)
+{
+    NSURL *tempDirectory = setUpTestWebPushD();
+
+    auto dataStoreConfiguration = adoptNS([_WKWebsiteDataStoreConfiguration new]);
+    dataStoreConfiguration.get().webPushMachServiceName = @"org.webkit.webpushtestdaemon.service";
+    auto dataStore = adoptNS([[WKWebsiteDataStore alloc] _initWithConfiguration:dataStoreConfiguration.get()]);
+
+    deleteAllRegistrationsForDataStore(dataStore.get());
+
+    auto configuration = adoptNS([[WKWebViewConfiguration alloc] init]);
+    configuration.get().websiteDataStore = dataStore.get();
+    [configuration.get().preferences _setNotificationsEnabled:YES];
+    for (_WKExperimentalFeature *feature in [WKPreferences _experimentalFeatures]) {
+        if ([feature.key isEqualToString:@"BuiltInNotificationsEnabled"])
+            [[configuration preferences] _setEnabled:YES forFeature:feature];
+    }
+
+    auto handler = adoptNS([[TestURLSchemeHandler alloc] init]);
+    [configuration setURLSchemeHandler:handler.get() forURLScheme:@"testing"];
+
+    [handler setStartURLSchemeTaskHandler:^(WKWebView *, id<WKURLSchemeTask> task) {
+        auto response = adoptNS([[NSURLResponse alloc] initWithURL:task.request.URL MIMEType:@"text/html" expectedContentLength:0 textEncodingName:nil]);
+        [task didReceiveResponse:response.get()];
+        [task didReceiveData:[NSData dataWithBytes:mainBytes length:strlen(mainBytes)]];
+        [task didFinish];
+    }];
+
+    auto webView = adoptNS([[TestWKWebView alloc] initWithFrame:CGRectMake(0, 0, 800, 600) configuration:configuration.get()]);
+    auto uiDelegate = adoptNS([[NotificationPermissionDelegate alloc] init]);
+    [webView setUIDelegate:uiDelegate.get()];
+
+    [webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"testing://main/index.html"]]];
+    TestWebKitAPI::Util::run(&alertReceived);
+
+    alertReceived = false;
+    [webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"testing://secondary/index.html"]]];
+    TestWebKitAPI::Util::run(&alertReceived);
+
+    static bool originOperationDone = false;
+    static RetainPtr<NSSet<WKSecurityOrigin *>> origins;
+    [dataStore _getOriginsWithPushAndNotificationPermissions:^(NSSet<WKSecurityOrigin *> *rawOrigins) {
+        EXPECT_EQ([rawOrigins count], 2u);
+        origins = rawOrigins;
+        originOperationDone = true;
+    }];
+    TestWebKitAPI::Util::run(&originOperationDone);
+
+    for (WKSecurityOrigin *origin in origins.get()) {
+        EXPECT_TRUE([origin.protocol isEqualToString:@"testing"]);
+        EXPECT_TRUE([origin.host isEqualToString:@"main"] || [origin.host isEqualToString:@"secondary"]);
+    }
+
+    deleteAllRegistrationsForDataStore(dataStore.get());
+    cleanUpTestWebPushD(tempDirectory);
+}
+#endif // #if USE(APPLE_INTERNAL_SDK)
+#endif // ENABLE(INSTALL_COORDINATION_BUNDLES)
+
 } // namespace TestWebKitAPI
 
 #endif // PLATFORM(MAC) || PLATFORM(IOS)

Modified: trunk/WebKitLibraries/ChangeLog (290145 => 290146)


--- trunk/WebKitLibraries/ChangeLog	2022-02-18 18:59:32 UTC (rev 290145)
+++ trunk/WebKitLibraries/ChangeLog	2022-02-18 19:01:21 UTC (rev 290146)
@@ -1,3 +1,12 @@
+2022-02-18  Brady Eidson  <beid...@apple.com>
+
+        Add an InstallCoordination webpushd backend
+        https://bugs.webkit.org/show_bug.cgi?id=233714
+
+        Reviewed by Alex Christensen.
+
+        * WebKitPrivateFrameworkStubs/iOS/15/InstallCoordination.framework/InstallCoordination.tbd: Added.
+
 2022-02-03  Robert Jenner  <jen...@apple.com>
 
         Unreviewed, reverting r288902.

Added: trunk/WebKitLibraries/WebKitPrivateFrameworkStubs/iOS/15/InstallCoordination.framework/InstallCoordination.tbd (0 => 290146)


--- trunk/WebKitLibraries/WebKitPrivateFrameworkStubs/iOS/15/InstallCoordination.framework/InstallCoordination.tbd	                        (rev 0)
+++ trunk/WebKitLibraries/WebKitPrivateFrameworkStubs/iOS/15/InstallCoordination.framework/InstallCoordination.tbd	2022-02-18 19:01:21 UTC (rev 290146)
@@ -0,0 +1,8 @@
+--- !tapi-tbd-v3
+archs:           [ x86_64, arm64, arm64e ]
+install-name:    '/System/Library/PrivateFrameworks/InstallCoordination.framework/InstallCoordination'
+platform: ios
+exports:
+  - archs:           [ x86_64, arm64, arm64e ]
+    objc-classes:    [ IXAppInstallCoordinator, IXOpaqueDataPromise, IXOwnedDataPromise, IXPlaceholder, IXPlaceholderAttributes, IXPromisedInMemoryDictionary, IXPromisedOutOfBandTransfer, IXRestoringDemotedAppInstallCoordinator ]
+...
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to