From f3ecc0bf73aaed88c97f7fb3603f6357146dff69 Mon Sep 17 00:00:00 2001 From: Phillip Pan Date: Tue, 2 Apr 2024 21:38:52 -0700 Subject: [PATCH] add privacy manifest to pod install Summary: Changelog: [iOS][Added] this creates the RN privacy manifest in the ios build step if user has not created one yet. the reasons have been added for the following APIs: NSPrivacyAccessedAPICategoryFileTimestamp - C617.1: We use fstat and stat in a few places in the C++ layer. We use these to read information about the JavaScript files in RN. NSPrivacyAccessedAPICategoryUserDefaults - CA92.1: We access NSUserDefaults in a few places. 1) To store RTL preferences 2) As part of caching server URLs for developer mode 3) A generic native module that wraps NSUserDefaults NSPrivacyAccessedAPICategorySystemBootTime - 35F9.1: Best guess reason from RR API pulled in by boost Reviewed By: cipolleschi Differential Revision: D53687232 fbshipit-source-id: 6dffb1a6013f8f29438a49752e47ed75c13f4a5c --- .../react-native/scripts/cocoapods/utils.rb | 38 +++++++++++++++++++ .../react-native/scripts/react_native_pods.rb | 1 + packages/rn-tester/PrivacyInfo.xcprivacy | 37 ++++++++++++++++++ .../RNTesterPods.xcodeproj/project.pbxproj | 26 +++++++++++++ 4 files changed, 102 insertions(+) create mode 100644 packages/rn-tester/PrivacyInfo.xcprivacy diff --git a/packages/react-native/scripts/cocoapods/utils.rb b/packages/react-native/scripts/cocoapods/utils.rb index 6507f8ba8caecb..2ced5a363b2e3a 100644 --- a/packages/react-native/scripts/cocoapods/utils.rb +++ b/packages/react-native/scripts/cocoapods/utils.rb @@ -505,6 +505,44 @@ def self.set_imagemanager_search_path(target_installation_result) ]) end + def self.get_privacy_manifest_paths_from(user_project) + privacy_manifests = user_project + .files + .select { |p| + p.path&.end_with?('PrivacyInfo.xcprivacy') + } + return privacy_manifests + end + + def self.add_privacy_manifest_if_needed(installer) + user_project = installer.aggregate_targets + .map{ |t| t.user_project } + .first + privacy_manifest = self.get_privacy_manifest_paths_from(user_project).first + if privacy_manifest.nil? + file_timestamp_reason = { + "NSPrivacyAccessedAPIType" => "NSPrivacyAccessedAPICategoryFileTimestamp", + "NSPrivacyAccessedAPITypeReasons" => ["C617.1"], + } + user_defaults_reason = { + "NSPrivacyAccessedAPIType" => "NSPrivacyAccessedAPICategoryUserDefaults", + "NSPrivacyAccessedAPITypeReasons" => ["CA92.1"], + } + boot_time_reason = { + "NSPrivacyAccessedAPIType" => "NSPrivacyAccessedAPICategorySystemBootTime", + "NSPrivacyAccessedAPITypeReasons" => ["35F9.1"], + } + privacy_manifest = { + "NSPrivacyCollectedDataTypes" => [], + "NSPrivacyTracking" => false, + "NSPrivacyAccessedAPITypes" => [file_timestamp_reason, user_defaults_reason, boot_time_reason] + } + path = File.join(user_project.path.parent, "PrivacyInfo.xcprivacy") + Xcodeproj::Plist.write_to_path(privacy_manifest, path) + Pod::UI.puts "Your app does not have a privacy manifest! A template has been generated containing Required Reasons API usage in the core React Native library. Please add the PrivacyInfo.xcprivacy file to your project and complete data use, tracking and any additional required reasons your app is using according to Apple's guidance: https://developer.apple.com/.../privacy_manifest_files. Then, you will need to manually add this file to your project in Xcode.".red + end + end + def self.react_native_pods return [ "DoubleConversion", diff --git a/packages/react-native/scripts/react_native_pods.rb b/packages/react-native/scripts/react_native_pods.rb index b95bd4f7ebf60e..9247b1a1692f3a 100644 --- a/packages/react-native/scripts/react_native_pods.rb +++ b/packages/react-native/scripts/react_native_pods.rb @@ -249,6 +249,7 @@ def react_native_post_install( ReactNativePodsUtils.apply_xcode_15_patch(installer) ReactNativePodsUtils.updateIphoneOSDeploymentTarget(installer) ReactNativePodsUtils.fix_flipper_for_xcode_15_3(installer) + ReactNativePodsUtils.add_privacy_manifest_if_needed(installer) NewArchitectureHelper.set_clang_cxx_language_standard_if_needed(installer) is_new_arch_enabled = ENV['RCT_NEW_ARCH_ENABLED'] == "1" diff --git a/packages/rn-tester/PrivacyInfo.xcprivacy b/packages/rn-tester/PrivacyInfo.xcprivacy new file mode 100644 index 00000000000000..41b8317f0652b9 --- /dev/null +++ b/packages/rn-tester/PrivacyInfo.xcprivacy @@ -0,0 +1,37 @@ + + + + + NSPrivacyAccessedAPITypes + + + NSPrivacyAccessedAPIType + NSPrivacyAccessedAPICategoryFileTimestamp + NSPrivacyAccessedAPITypeReasons + + C617.1 + + + + NSPrivacyAccessedAPIType + NSPrivacyAccessedAPICategoryUserDefaults + NSPrivacyAccessedAPITypeReasons + + CA92.1 + + + + NSPrivacyAccessedAPIType + NSPrivacyAccessedAPICategorySystemBootTime + NSPrivacyAccessedAPITypeReasons + + 35F9.1 + + + + NSPrivacyCollectedDataTypes + + NSPrivacyTracking + + + diff --git a/packages/rn-tester/RNTesterPods.xcodeproj/project.pbxproj b/packages/rn-tester/RNTesterPods.xcodeproj/project.pbxproj index 9ac91708689321..7b4c0c68129d72 100644 --- a/packages/rn-tester/RNTesterPods.xcodeproj/project.pbxproj +++ b/packages/rn-tester/RNTesterPods.xcodeproj/project.pbxproj @@ -59,6 +59,7 @@ E7DB216622B2F3EC005AC45F /* RCTRootViewIntegrationTests.m in Sources */ = {isa = PBXBuildFile; fileRef = E7DB216122B2F3EC005AC45F /* RCTRootViewIntegrationTests.m */; }; E7DB216722B2F69F005AC45F /* JavaScriptCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E7DB213022B2C649005AC45F /* JavaScriptCore.framework */; }; E7DB218C22B41FCD005AC45F /* XCTest.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E7DB218B22B41FCD005AC45F /* XCTest.framework */; }; + F0D621C32BBB9E38005960AC /* PrivacyInfo.xcprivacy in Resources */ = {isa = PBXBuildFile; fileRef = F0D621C22BBB9E38005960AC /* PrivacyInfo.xcprivacy */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -179,6 +180,7 @@ E7DB216022B2F3EC005AC45F /* RNTesterSnapshotTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RNTesterSnapshotTests.m; sourceTree = ""; }; E7DB216122B2F3EC005AC45F /* RCTRootViewIntegrationTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTRootViewIntegrationTests.m; sourceTree = ""; }; E7DB218B22B41FCD005AC45F /* XCTest.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = XCTest.framework; sourceTree = DEVELOPER_DIR; }; + F0D621C22BBB9E38005960AC /* PrivacyInfo.xcprivacy */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; path = PrivacyInfo.xcprivacy; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -226,6 +228,7 @@ isa = PBXGroup; children = ( 0CC3BE1A25DDB68A0033CAEB /* RNTester.entitlements */, + F0D621C22BBB9E38005960AC /* PrivacyInfo.xcprivacy */, AC474BFB29BBD4A1002BDAED /* RNTester.xctestplan */, E771AEEA22B44E3100EA1189 /* Info.plist */, 13B07FAF1A68108700A75B9A /* AppDelegate.h */, @@ -515,6 +518,7 @@ files = ( 2DDEF0101F84BF7B00DBDF73 /* Images.xcassets in Resources */, 8145AE06241172D900A3F8DA /* LaunchScreen.storyboard in Resources */, + F0D621C32BBB9E38005960AC /* PrivacyInfo.xcprivacy in Resources */, 3D2AFAF51D646CF80089D1A3 /* legacy_image@2x.png in Resources */, ); runOnlyForDeploymentPostprocessing = 0; @@ -962,6 +966,17 @@ GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_LABEL = YES; GCC_WARN_UNUSED_VARIABLE = YES; + HEADER_SEARCH_PATHS = ( + "$(inherited)", + "${PODS_CONFIGURATION_BUILD_DIR}/ReactCommon-Samples/ReactCommon_Samples.framework/Headers", + "${PODS_CONFIGURATION_BUILD_DIR}/ReactCommon/ReactCommon.framework/Headers/react/nativemodule/core", + "${PODS_CONFIGURATION_BUILD_DIR}/ReactCommon-Samples/ReactCommon_Samples.framework/Headers/platform/ios", + "${PODS_CONFIGURATION_BUILD_DIR}/React-Fabric/React_Fabric.framework/Headers/react/renderer/components/view/platform/cxx", + "${PODS_CONFIGURATION_BUILD_DIR}/React-NativeModulesApple/React_NativeModulesApple.framework/Headers", + "${PODS_CONFIGURATION_BUILD_DIR}/React-graphics/React_graphics.framework/Headers/react/renderer/graphics/platform/ios", + "${PODS_CONFIGURATION_BUILD_DIR}/ReactCommon/ReactCommon.framework/Headers", + "${PODS_CONFIGURATION_BUILD_DIR}/React-graphics/React_graphics.framework/Headers", + ); IPHONEOS_DEPLOYMENT_TARGET = 12.4; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; @@ -1051,6 +1066,17 @@ GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_LABEL = YES; GCC_WARN_UNUSED_VARIABLE = YES; + HEADER_SEARCH_PATHS = ( + "$(inherited)", + "${PODS_CONFIGURATION_BUILD_DIR}/ReactCommon-Samples/ReactCommon_Samples.framework/Headers", + "${PODS_CONFIGURATION_BUILD_DIR}/ReactCommon/ReactCommon.framework/Headers/react/nativemodule/core", + "${PODS_CONFIGURATION_BUILD_DIR}/ReactCommon-Samples/ReactCommon_Samples.framework/Headers/platform/ios", + "${PODS_CONFIGURATION_BUILD_DIR}/React-Fabric/React_Fabric.framework/Headers/react/renderer/components/view/platform/cxx", + "${PODS_CONFIGURATION_BUILD_DIR}/React-NativeModulesApple/React_NativeModulesApple.framework/Headers", + "${PODS_CONFIGURATION_BUILD_DIR}/React-graphics/React_graphics.framework/Headers/react/renderer/graphics/platform/ios", + "${PODS_CONFIGURATION_BUILD_DIR}/ReactCommon/ReactCommon.framework/Headers", + "${PODS_CONFIGURATION_BUILD_DIR}/React-graphics/React_graphics.framework/Headers", + ); IPHONEOS_DEPLOYMENT_TARGET = 12.4; MTL_ENABLE_DEBUG_INFO = NO; OTHER_CFLAGS = (