Skip to content

Commit 2383985

Browse files
authored
Apple privacy manifest (#581)
* Add privacy manifests * Use bundle version instead of bundle file modification date * Remove isPreLeanplumInstall check since it uses file timestamp APIs * Add manifest to pods resources * Remove no longer used file timestamp APIs * Move xcprivacy in bundle, set correct targets * Remove Precise location The app can specify reduced location or add precise in their app's manifest
1 parent cbe610b commit 2383985

File tree

13 files changed

+158
-74
lines changed

13 files changed

+158
-74
lines changed

Leanplum-iOS-Location.podspec

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ Pod::Spec.new do |s|
1212
s.requires_arc = true
1313
s.source = { :git => 'https://github.com/Leanplum/Leanplum-iOS-SDK.git', :tag => s.version.to_s}
1414
s.source_files = 'LeanplumSDKLocation/LeanplumSDKLocation/Classes/**/*'
15+
s.resources = 'LeanplumSDKLocation/LeanplumSDKLocation/*.{cer,xcprivacy}'
1516
s.frameworks = 'CoreLocation'
1617
s.documentation_url = 'https://docs.leanplum.com/'
1718
s.dependency 'Leanplum-iOS-SDK', "~> 6.0"

Leanplum-iOS-LocationAndBeacons.podspec

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ Pod::Spec.new do |s|
1212
s.requires_arc = true
1313
s.source = { :git => 'https://github.com/Leanplum/Leanplum-iOS-SDK.git', :tag => s.version.to_s}
1414
s.source_files = 'LeanplumSDKLocation/LeanplumSDKLocation/Classes/**/*'
15+
s.resources = 'LeanplumSDKLocation/LeanplumSDKLocation/*.{cer,xcprivacy}'
1516
s.frameworks = 'CoreLocation'
1617
s.documentation_url = 'https://docs.leanplum.com/'
1718
s.dependency 'Leanplum-iOS-SDK', "~> 6.0"

LeanplumSDK/LeanplumSDK.xcodeproj/project.pbxproj

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
archiveVersion = 1;
44
classes = {
55
};
6-
objectVersion = 51;
6+
objectVersion = 54;
77
objects = {
88

99
/* Begin PBXBuildFile section */
@@ -409,6 +409,7 @@
409409
6AD978582774F3F000A7C6C6 /* NotificationsProxy+Utilities.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6AD978562774F3F000A7C6C6 /* NotificationsProxy+Utilities.swift */; };
410410
6ADC90C72807461F00CE42C7 /* Dictionary+ValueKeyPath.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6ADC90C62807461F00CE42C7 /* Dictionary+ValueKeyPath.swift */; };
411411
6ADC90C82807461F00CE42C7 /* Dictionary+ValueKeyPath.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6ADC90C62807461F00CE42C7 /* Dictionary+ValueKeyPath.swift */; };
412+
6B00F6962BBC459C000B1E26 /* PrivacyInfo.xcprivacy in Resources */ = {isa = PBXBuildFile; fileRef = 6B00F6082BB5B220000B1E26 /* PrivacyInfo.xcprivacy */; };
412413
6B7B6E8C2B6A7A5400820306 /* Leanplum_WebSocket+Utils.h in Headers */ = {isa = PBXBuildFile; fileRef = 6B7B6E8A2B6A7A5400820306 /* Leanplum_WebSocket+Utils.h */; settings = {ATTRIBUTES = (Public, ); }; };
413414
6B7B6E8D2B6A7A5400820306 /* Leanplum_WebSocket+Utils.h in Headers */ = {isa = PBXBuildFile; fileRef = 6B7B6E8A2B6A7A5400820306 /* Leanplum_WebSocket+Utils.h */; settings = {ATTRIBUTES = (Public, ); }; };
414415
6B7B6E8E2B6A7A5400820306 /* Leanplum_WebSocket+Utils.m in Sources */ = {isa = PBXBuildFile; fileRef = 6B7B6E8B2B6A7A5400820306 /* Leanplum_WebSocket+Utils.m */; };
@@ -662,6 +663,7 @@
662663
6AD978532774F2F700A7C6C6 /* NotificationsProxy+iOS9.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NotificationsProxy+iOS9.swift"; sourceTree = "<group>"; };
663664
6AD978562774F3F000A7C6C6 /* NotificationsProxy+Utilities.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NotificationsProxy+Utilities.swift"; sourceTree = "<group>"; };
664665
6ADC90C62807461F00CE42C7 /* Dictionary+ValueKeyPath.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Dictionary+ValueKeyPath.swift"; sourceTree = "<group>"; };
666+
6B00F6082BB5B220000B1E26 /* PrivacyInfo.xcprivacy */ = {isa = PBXFileReference; lastKnownFileType = text.xml; path = PrivacyInfo.xcprivacy; sourceTree = "<group>"; };
665667
6B7B6E8A2B6A7A5400820306 /* Leanplum_WebSocket+Utils.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Leanplum_WebSocket+Utils.h"; sourceTree = "<group>"; };
666668
6B7B6E8B2B6A7A5400820306 /* Leanplum_WebSocket+Utils.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "Leanplum_WebSocket+Utils.m"; sourceTree = "<group>"; };
667669
6C2FB1913D58B5EF901363C9 /* Pods_Leanplum.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Leanplum.framework; sourceTree = BUILT_PRODUCTS_DIR; };
@@ -1094,6 +1096,7 @@
10941096
075AAEFA26848059007CA1BD /* Resources */ = {
10951097
isa = PBXGroup;
10961098
children = (
1099+
6B00F6082BB5B220000B1E26 /* PrivacyInfo.xcprivacy */,
10971100
075AAEE026847EE0007CA1BD /* Assets.xcassets */,
10981101
075AAEE326847EE0007CA1BD /* Interstitial.storyboard */,
10991102
075AAEE126847EE0007CA1BD /* Popup.storyboard */,
@@ -1559,6 +1562,7 @@
15591562
isa = PBXResourcesBuildPhase;
15601563
buildActionMask = 2147483647;
15611564
files = (
1565+
6B00F6962BBC459C000B1E26 /* PrivacyInfo.xcprivacy in Resources */,
15621566
075AAEF326847FEA007CA1BD /* Interstitial.storyboard in Resources */,
15631567
075AAEF226847FEA007CA1BD /* Assets.xcassets in Resources */,
15641568
075AAEF426847FEA007CA1BD /* WebInterstitial.storyboard in Resources */,

LeanplumSDK/LeanplumSDK/Classes/Internal/LPConstants.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,6 @@ OBJC_EXPORT NSString *LEANPLUM_DEFAULTS_PUSH_TOKEN_KEY;
115115
OBJC_EXPORT NSString *LEANPLUM_DEFAULTS_USER_NOTIFICATION_SETTINGS_KEY;
116116
OBJC_EXPORT NSString *LEANPLUM_DEFAULTS_REGION_STATE_KEY;
117117
OBJC_EXPORT NSString *LEANPLUM_DEFAULTS_ATTRIBUTES_KEY;
118-
OBJC_EXPORT NSString *LEANPLUM_DEFAULTS_PRE_LEANPLUM_INSTALL_KEY;
119118
OBJC_EXPORT NSString *LEANPLUM_DEFAULTS_SDK_VERSION;
120119
OBJC_EXPORT NSString *LEANPLUM_DEFAULTS_INBOX_KEY;
121120
OBJC_EXPORT NSString *LEANPLUM_DEFAULTS_APP_VERSION_KEY;

LeanplumSDK/LeanplumSDK/Classes/Internal/LPConstants.m

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,6 @@ - (id)init {
7676
NSString *LEANPLUM_DEFAULTS_PUSH_TOKEN_KEY = @"__leanplum_push_token_%@-%@-%@";
7777
NSString *LEANPLUM_DEFAULTS_USER_NOTIFICATION_SETTINGS_KEY = @"__leanplum_user_notification_%@-%@-%@";
7878
NSString *LEANPLUM_DEFAULTS_REGION_STATE_KEY = @"__leanplum_region_state";
79-
NSString *LEANPLUM_DEFAULTS_PRE_LEANPLUM_INSTALL_KEY = @"__leanplum_pre_leanplum_install";
8079
NSString *LEANPLUM_DEFAULTS_SDK_VERSION = @"__leanplum_version";
8180
NSString *LEANPLUM_DEFAULTS_INBOX_KEY = @"__leanplum_newsfeed";
8281
NSString *LEANPLUM_DEFAULTS_APP_VERSION_KEY = @"leanplum_savedAppVersionKey";

LeanplumSDK/LeanplumSDK/Classes/Internal/Leanplum.m

Lines changed: 0 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -1031,11 +1031,6 @@ + (NSDictionary *)setupStartParameters:(NSDictionary *)attributes
10311031
params[LP_PARAM_DEV_MODE] = @(YES);
10321032
}
10331033

1034-
NSDictionary *timeParams = [self initializePreLeanplumInstall];
1035-
if (timeParams) {
1036-
[params addEntriesFromDictionary:timeParams];
1037-
}
1038-
10391034
// Get the current Inbox messages on the device.
10401035
params[LP_PARAM_INBOX_MESSAGES] = [self.inbox messagesIds];
10411036

@@ -1122,41 +1117,6 @@ + (void)addUIApplicationObservers
11221117
}];
11231118
}
11241119

1125-
// On first run with Leanplum, determine if this app was previously installed without Leanplum.
1126-
// This is useful for detecting if the user may have already rejected notifications.
1127-
+ (NSDictionary *)initializePreLeanplumInstall
1128-
{
1129-
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
1130-
if ([[[defaults dictionaryRepresentation] allKeys]
1131-
containsObject:LEANPLUM_DEFAULTS_PRE_LEANPLUM_INSTALL_KEY]) {
1132-
return nil;
1133-
} else {
1134-
NSFileManager *fileManager = [NSFileManager defaultManager];
1135-
NSURL *urlToDocumentsFolder = [[fileManager URLsForDirectory:NSDocumentDirectory
1136-
inDomains:NSUserDomainMask] lastObject];
1137-
__autoreleasing NSError *error;
1138-
NSDate *installDate =
1139-
[[fileManager attributesOfItemAtPath:urlToDocumentsFolder.path error:&error]
1140-
objectForKey:NSFileCreationDate];
1141-
NSString *pathToInfoPlist = [[NSBundle mainBundle] pathForResource:@"Info" ofType:@"plist"];
1142-
NSString *pathToAppBundle = [pathToInfoPlist stringByDeletingLastPathComponent];
1143-
NSDate *updateDate = [[fileManager attributesOfItemAtPath:pathToAppBundle error:&error]
1144-
objectForKey:NSFileModificationDate];
1145-
1146-
// Considered pre-Leanplum install if its been more than a day (86400 seconds) since
1147-
// install.
1148-
NSTimeInterval secondsBetween = [updateDate timeIntervalSinceDate:installDate];
1149-
[[NSUserDefaults standardUserDefaults] setBool:(secondsBetween > 86400)
1150-
forKey:LEANPLUM_DEFAULTS_PRE_LEANPLUM_INSTALL_KEY];
1151-
return @{
1152-
LP_PARAM_INSTALL_DATE:
1153-
[NSString stringWithFormat:@"%f", [installDate timeIntervalSince1970]],
1154-
LP_PARAM_UPDATE_DATE:
1155-
[NSString stringWithFormat:@"%f", [updateDate timeIntervalSince1970]]
1156-
};
1157-
}
1158-
}
1159-
11601120
// If the app has already accepted notifications, register for this instance of the app and trigger
11611121
// sending push tokens to server.
11621122
+ (void)maybeRegisterForNotifications
@@ -2412,19 +2372,6 @@ + (LeanplumPushSetupBlock)pushSetupBlock
24122372
return nil;
24132373
}
24142374

2415-
+ (BOOL)isPreLeanplumInstall
2416-
{
2417-
LP_TRY
2418-
if (![LPInternalState sharedState].calledStart) {
2419-
[self throwError:@"[Leanplum start] must be called before calling isPreLeanplumInstall"];
2420-
return NO;
2421-
}
2422-
return [[NSUserDefaults standardUserDefaults]
2423-
boolForKey:LEANPLUM_DEFAULTS_PRE_LEANPLUM_INSTALL_KEY];
2424-
LP_END_TRY
2425-
return NO;
2426-
}
2427-
24282375
+ (NSString *)appVersion
24292376
{
24302377
NSString *versionName = [LPInternalState sharedState].appVersion;

LeanplumSDK/LeanplumSDK/Classes/Leanplum.h

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -726,12 +726,6 @@ __attribute__((deprecated("Use [Leanplum setTestModeEnabled:YES] instead.")));
726726
*/
727727
+ (nullable LeanplumPushSetupBlock)pushSetupBlock;
728728

729-
/**
730-
* Returns YES if the app existed on the device more than a day previous to a version built with
731-
* Leanplum was installed.
732-
*/
733-
+ (BOOL)isPreLeanplumInstall;
734-
735729
/**
736730
* Returns the app version used by Leanplum.
737731
*/

LeanplumSDK/LeanplumSDK/Classes/Managers/LPFileManager.m

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -376,13 +376,10 @@ + (BOOL)isNewerLocally:(NSDictionary *)localAttributes orRemotely:(NSDictionary
376376

377377
+ (NSString *)bundleVersion
378378
{
379-
NSFileManager *fm = [NSFileManager defaultManager];
380-
381-
NSString *path = [[NSBundle mainBundle] resourcePath];
382-
NSDictionary *attrs = [fm attributesOfItemAtPath:path error:nil];
383-
NSString *current = [attrs[NSFileModificationDate] description];
384-
385-
return current;
379+
NSString *currentVersion = [[[NSBundle mainBundle] infoDictionary]
380+
objectForKey:@"CFBundleVersion"];
381+
382+
return currentVersion;
386383
}
387384

388385
/**

LeanplumSDK/LeanplumSDK/Classes/MessageTemplates/LPPushMessageTemplate.m

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,7 @@ @implementation LPPushMessageTemplate
1515

1616
-(BOOL)shouldShowPushMessage
1717
{
18-
if ([Leanplum isPreLeanplumInstall]) {
19-
LPLog(LPDebug, @"'Ask to ask' conservatively falls back to just 'ask' for pre-Leanplum installs");
20-
[self showNativePushPrompt];
21-
return NO;
22-
} else if ([self isPushEnabled]) {
18+
if ([self isPushEnabled]) {
2319
LPLog(LPDebug, @"Pushes already enabled");
2420
return NO;
2521
} else if ([self hasDisabledAskToAsk]) {
Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3+
<plist version="1.0">
4+
<dict>
5+
<key>NSPrivacyAccessedAPITypes</key>
6+
<array>
7+
<dict>
8+
<key>NSPrivacyAccessedAPIType</key>
9+
<string>NSPrivacyAccessedAPICategoryUserDefaults</string>
10+
<key>NSPrivacyAccessedAPITypeReasons</key>
11+
<array>
12+
<string>CA92.1</string>
13+
</array>
14+
</dict>
15+
</array>
16+
<key>NSPrivacyCollectedDataTypes</key>
17+
<array>
18+
<dict>
19+
<key>NSPrivacyCollectedDataType</key>
20+
<string>NSPrivacyCollectedDataTypePerformanceData</string>
21+
<key>NSPrivacyCollectedDataTypeLinked</key>
22+
<true/>
23+
<key>NSPrivacyCollectedDataTypeTracking</key>
24+
<false/>
25+
<key>NSPrivacyCollectedDataTypePurposes</key>
26+
<array>
27+
<string>NSPrivacyCollectedDataTypePurposeAppFunctionality</string>
28+
</array>
29+
</dict>
30+
<dict>
31+
<key>NSPrivacyCollectedDataType</key>
32+
<string>NSPrivacyCollectedDataTypeCrashData</string>
33+
<key>NSPrivacyCollectedDataTypeLinked</key>
34+
<true/>
35+
<key>NSPrivacyCollectedDataTypeTracking</key>
36+
<false/>
37+
<key>NSPrivacyCollectedDataTypePurposes</key>
38+
<array>
39+
<string>NSPrivacyCollectedDataTypePurposeAppFunctionality</string>
40+
</array>
41+
</dict>
42+
<dict>
43+
<key>NSPrivacyCollectedDataType</key>
44+
<string>NSPrivacyCollectedDataTypeProductInteraction</string>
45+
<key>NSPrivacyCollectedDataTypeLinked</key>
46+
<true/>
47+
<key>NSPrivacyCollectedDataTypeTracking</key>
48+
<false/>
49+
<key>NSPrivacyCollectedDataTypePurposes</key>
50+
<array>
51+
<string>NSPrivacyCollectedDataTypePurposeAnalytics</string>
52+
<string>NSPrivacyCollectedDataTypePurposeProductPersonalization</string>
53+
</array>
54+
</dict>
55+
<dict>
56+
<key>NSPrivacyCollectedDataType</key>
57+
<string>NSPrivacyCollectedDataTypeDeviceID</string>
58+
<key>NSPrivacyCollectedDataTypeLinked</key>
59+
<true/>
60+
<key>NSPrivacyCollectedDataTypeTracking</key>
61+
<false/>
62+
<key>NSPrivacyCollectedDataTypePurposes</key>
63+
<array>
64+
<string>NSPrivacyCollectedDataTypePurposeProductPersonalization</string>
65+
<string>NSPrivacyCollectedDataTypePurposeAnalytics</string>
66+
</array>
67+
</dict>
68+
<dict>
69+
<key>NSPrivacyCollectedDataType</key>
70+
<string>NSPrivacyCollectedDataTypeUserID</string>
71+
<key>NSPrivacyCollectedDataTypeLinked</key>
72+
<true/>
73+
<key>NSPrivacyCollectedDataTypeTracking</key>
74+
<false/>
75+
<key>NSPrivacyCollectedDataTypePurposes</key>
76+
<array>
77+
<string>NSPrivacyCollectedDataTypePurposeAnalytics</string>
78+
<string>NSPrivacyCollectedDataTypePurposeProductPersonalization</string>
79+
</array>
80+
</dict>
81+
<dict>
82+
<key>NSPrivacyCollectedDataType</key>
83+
<string>NSPrivacyCollectedDataTypeCoarseLocation</string>
84+
<key>NSPrivacyCollectedDataTypeLinked</key>
85+
<true/>
86+
<key>NSPrivacyCollectedDataTypeTracking</key>
87+
<false/>
88+
<key>NSPrivacyCollectedDataTypePurposes</key>
89+
<array>
90+
<string>NSPrivacyCollectedDataTypePurposeProductPersonalization</string>
91+
<string>NSPrivacyCollectedDataTypePurposeAnalytics</string>
92+
</array>
93+
</dict>
94+
</array>
95+
<key>NSPrivacyTracking</key>
96+
<false/>
97+
</dict>
98+
</plist>

0 commit comments

Comments
 (0)