Skip to content

Commit

Permalink
use none-deprecated archive functions when possible
Browse files Browse the repository at this point in the history
  • Loading branch information
ShiCheng-Lu committed Sep 25, 2024
1 parent d2c2928 commit 7e87e5e
Show file tree
Hide file tree
Showing 10 changed files with 267 additions and 11 deletions.
2 changes: 1 addition & 1 deletion RadarSDK.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -376,7 +376,6 @@
children = (
9679F4A027CD8D0600800797 /* CLLocation+Radar.h */,
9679F4A227CD8DE200800797 /* CLLocation+Radar.m */,
53CCD782275E579800F79CC8 /* RadarLogBuffer.m */,
);
name = Util;
sourceTree = "<group>";
Expand Down Expand Up @@ -497,6 +496,7 @@
96A5A11527ADA02E007B960B /* RadarLog.h */,
96A5A11427ADA02E007B960B /* RadarLog.m */,
96A5A11627ADA02E007B960B /* RadarLogBuffer.h */,
53CCD782275E579800F79CC8 /* RadarLogBuffer.m */,
DD236D66230A0D6700EB88F9 /* RadarLogger.h */,
DD236D67230A0D6700EB88F9 /* RadarLogger.m */,
9683FD6127B36C26009EBB6B /* RadarMeta.h */,
Expand Down
2 changes: 1 addition & 1 deletion RadarSDK/RadarLog.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
/**
Represents a debug log.
*/
@interface RadarLog : NSObject <NSCoding>
@interface RadarLog : NSObject <NSSecureCoding>

/**
The levels for debug logs.
Expand Down
4 changes: 4 additions & 0 deletions RadarSDK/RadarLog.m
Original file line number Diff line number Diff line change
Expand Up @@ -130,4 +130,8 @@ - (void)encodeWithCoder:(NSCoder *)coder {
[coder encodeObject:_createdAt forKey:@"createdAt"];
}

+ (BOOL)supportsSecureCoding {
return YES;
}

@end
17 changes: 15 additions & 2 deletions RadarSDK/RadarLogBuffer.m
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,13 @@ - (void)persistLogs {
for (NSString *file in files) {
NSString *filePath = [self.logFileDir stringByAppendingPathComponent:file];
NSData *fileData = [self.fileHandler readFileAtPath:filePath];
RadarLog *log = [NSKeyedUnarchiver unarchiveObjectWithData:fileData];
RadarLog *log;
if (@available(iOS 11.0, *)) {
log = [NSKeyedUnarchiver unarchivedObjectOfClasses:[NSSet setWithObjects:[NSString class], [RadarLog class], [NSDate class], nil] fromData:fileData error:nil];
} else {
log = [NSKeyedUnarchiver unarchiveObjectWithData:fileData];
}

if (log && log.message) {
[logs addObject:log];
}
Expand All @@ -122,7 +128,14 @@ - (void)persistLogs {

- (void)writeToFileStorage:(NSArray <RadarLog *> *)logs {
for (RadarLog *log in logs) {
NSData *logData = [NSKeyedArchiver archivedDataWithRootObject:log];

NSData *logData;
if (@available(iOS 11.0, *)) {
logData = [NSKeyedArchiver archivedDataWithRootObject:log requiringSecureCoding:YES error:nil];
} else {
logData = [NSKeyedArchiver archivedDataWithRootObject:log];
}

NSTimeInterval unixTimestamp = [log.createdAt timeIntervalSince1970];
// logs may be created in the same millisecond, so we append a counter to the end of the timestamp to "tiebreak"
NSString *unixTimestampString = [NSString stringWithFormat:@"%lld_%04d", (long long)unixTimestamp, fileCounter++];
Expand Down
2 changes: 1 addition & 1 deletion RadarSDK/RadarReplay.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

#import "Radar.h"

@interface RadarReplay : NSObject <NSCoding>
@interface RadarReplay : NSObject <NSSecureCoding>

@property (nonnull, copy, nonatomic, readonly) NSDictionary *replayParams;

Expand Down
4 changes: 4 additions & 0 deletions RadarSDK/RadarReplay.m
Original file line number Diff line number Diff line change
Expand Up @@ -57,4 +57,8 @@ - (NSUInteger)hash {
return [self.replayParams hash];
}

+ (BOOL)supportsSecureCoding {
return YES;
}

@end
27 changes: 23 additions & 4 deletions RadarSDK/RadarReplayBuffer.m
Original file line number Diff line number Diff line change
Expand Up @@ -59,9 +59,17 @@ - (void)writeNewReplayToBuffer:(NSMutableDictionary *)replayParams {
[prunedBuffer addObject:mutableReplayBuffer[i]];
}
}
replaysData = [NSKeyedArchiver archivedDataWithRootObject:prunedBuffer];
if (@available(iOS 11.0, *)) {
replaysData = [NSKeyedArchiver archivedDataWithRootObject:prunedBuffer requiringSecureCoding:true error:nil];
} else {
replaysData = [NSKeyedArchiver archivedDataWithRootObject:prunedBuffer];
}
} else {
replaysData = [NSKeyedArchiver archivedDataWithRootObject:mutableReplayBuffer];
if (@available(iOS 11.0, *)) {
replaysData = [NSKeyedArchiver archivedDataWithRootObject:mutableReplayBuffer requiringSecureCoding:true error:nil];
} else {
replaysData = [NSKeyedArchiver archivedDataWithRootObject:mutableReplayBuffer];
}
}

[[NSUserDefaults standardUserDefaults] setObject:replaysData forKey:@"radar-replays"];
Expand Down Expand Up @@ -150,14 +158,25 @@ - (void)removeReplaysFromBuffer:(NSArray<RadarReplay *> *)replays {
[mutableReplayBuffer removeObjectsInArray:replays];

// persist the updated buffer
NSData *replaysData = [NSKeyedArchiver archivedDataWithRootObject:mutableReplayBuffer];
NSData *replaysData;
if (@available(iOS 11.0, *)) {
replaysData = [NSKeyedArchiver archivedDataWithRootObject:mutableReplayBuffer requiringSecureCoding:true error:nil];
} else {
replaysData = [NSKeyedArchiver archivedDataWithRootObject:mutableReplayBuffer];
}
[[NSUserDefaults standardUserDefaults] setObject:replaysData forKey:@"radar-replays"];
}

- (void)loadReplaysFromPersistentStore {
NSData *replaysData = [[NSUserDefaults standardUserDefaults] objectForKey:@"radar-replays"];
if (replaysData) {
NSArray *replays = [NSKeyedUnarchiver unarchiveObjectWithData:replaysData];
NSArray *replays;
if (@available(iOS 11.0, *)) {
NSSet *allowedClasses = [NSSet setWithObjects:[NSArray class], [RadarReplay class], [NSDictionary class], [NSString class], [NSNumber class], nil];
replays = [NSKeyedUnarchiver unarchivedObjectOfClasses:allowedClasses fromData:replaysData error:nil];
} else {
replays = [NSKeyedUnarchiver unarchiveObjectWithData:replaysData];
}
[[RadarLogger sharedInstance] logWithLevel:RadarLogLevelDebug message:[NSString stringWithFormat:@"Loaded replays | length = %lu", (unsigned long)[replays count]]];
mutableReplayBuffer = [NSMutableArray arrayWithArray:replays];
}
Expand Down
21 changes: 19 additions & 2 deletions RadarSDKTests/RadarSDKTests.m
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
#import "RadarTestUtils.h"
#import "RadarTripOptions.h"
#import "RadarFileStorage.h"

#import "RadarReplayBuffer.h"

@interface RadarSDKTests : XCTestCase

Expand All @@ -30,6 +30,7 @@ @interface RadarSDKTests : XCTestCase
@property (nonatomic, strong) RadarFileStorage *fileSystem;
@property (nonatomic, strong) NSString *testFilePath;
@property (nonatomic, strong) RadarLogBuffer *logBuffer;
@property (nonatomic, strong) RadarReplayBuffer *replayBuffer;
@end

@implementation RadarSDKTests
Expand Down Expand Up @@ -299,7 +300,7 @@ - (void)setUp {
self.testFilePath = [NSTemporaryDirectory() stringByAppendingPathComponent:@"testfile"];
[[RadarLogBuffer sharedInstance]clearBuffer];
[[RadarLogBuffer sharedInstance]setPersistentLogFeatureFlag:YES];

[[RadarReplayBuffer sharedInstance]clearBuffer];
}

- (void)tearDown {
Expand Down Expand Up @@ -1489,6 +1490,22 @@ - (void)test_RadarLogBuffer_purge {
[[RadarLogBuffer sharedInstance]clearBuffer];
}

- (void)test_RadarReplayBuffer_writeAndRead {
RadarSdkConfiguration *sdkConfiguration = [RadarSettings sdkConfiguration];
sdkConfiguration.usePersistence = true;
[RadarSettings setSdkConfiguration:sdkConfiguration];

CLLocation *location = [[CLLocation alloc] initWithLatitude:0.1 longitude:0.1];
NSMutableDictionary * params = [RadarTestUtils createTrackParamWithLocation:location stopped:YES foreground:YES source:RadarLocationSourceGeofenceEnter replayed:YES beacons:[NSArray arrayWithObject:[RadarBeacon alloc]] verified:YES attestationString:@"attestationString" keyId:@"keyID" attestationError:@"attestationError" encrypted:YES expectedCountryCode:@"CountryCode" expectedStateCode:@"StateCode"];

[[RadarReplayBuffer sharedInstance] writeNewReplayToBuffer:params];
[[RadarReplayBuffer sharedInstance] setValue:NULL forKey:@"mutableReplayBuffer"];
[[RadarReplayBuffer sharedInstance] loadReplaysFromPersistentStore];
NSMutableArray<RadarReplay *> *mutableReplayBuffer = [[RadarReplayBuffer sharedInstance] valueForKey:@"mutableReplayBuffer"];
XCTAssertEqual(mutableReplayBuffer.count, 1);
XCTAssertEqualObjects(mutableReplayBuffer.firstObject.replayParams, params);
}

- (void)test_RadarSdkConfiguration {
RadarSdkConfiguration *sdkConfiguration = [[RadarSdkConfiguration alloc] initWithDict:@{
@"logLevel": @"warning",
Expand Down
22 changes: 22 additions & 0 deletions RadarSDKTests/RadarTestUtils.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,34 @@

#import <Foundation/Foundation.h>

#import "CLLocation+Radar.h"
#import "RadarLocationManager.h"
#import "RadarSettings.h"
#import "RadarState.h"
#import "RadarUtils.h"
#import "RadarTripOptions.h"
#import "RadarVerificationManager.h"

NS_ASSUME_NONNULL_BEGIN

@interface RadarTestUtils : NSObject

+ (NSDictionary *)jsonDictionaryFromResource:(NSString *)resource;

+ (NSMutableDictionary *)createTrackParamWithLocation:(CLLocation *_Nonnull)location
stopped:(BOOL)stopped
foreground:(BOOL)foreground
source:(RadarLocationSource)source
replayed:(BOOL)replayed
beacons:(NSArray<RadarBeacon *> *_Nullable)beacons
verified:(BOOL)verified
attestationString:(NSString *_Nullable)attestationString
keyId:(NSString *_Nullable)keyId
attestationError:(NSString *_Nullable)attestationError
encrypted:(BOOL)encrypted
expectedCountryCode:(NSString * _Nullable)expectedCountryCode
expectedStateCode:(NSString * _Nullable)expectedStateCode;

@end

NS_ASSUME_NONNULL_END
177 changes: 177 additions & 0 deletions RadarSDKTests/RadarTestutils.m
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,181 @@ + (NSDictionary *)jsonDictionaryFromResource:(NSString *)resource {
return jsonDict;
}

+ (NSMutableDictionary *)createTrackParamWithLocation:(CLLocation *_Nonnull)location
stopped:(BOOL)stopped
foreground:(BOOL)foreground
source:(RadarLocationSource)source
replayed:(BOOL)replayed
beacons:(NSArray<RadarBeacon *> *_Nullable)beacons
verified:(BOOL)verified
attestationString:(NSString *_Nullable)attestationString
keyId:(NSString *_Nullable)keyId
attestationError:(NSString *_Nullable)attestationError
encrypted:(BOOL)encrypted
expectedCountryCode:(NSString * _Nullable)expectedCountryCode
expectedStateCode:(NSString * _Nullable)expectedStateCode{
NSMutableDictionary *params = [NSMutableDictionary new];
BOOL anonymous = [RadarSettings anonymousTrackingEnabled];
params[@"anonymous"] = @(anonymous);
if (anonymous) {
params[@"deviceId"] = @"anonymous";
params[@"geofenceIds"] = [RadarState geofenceIds];
params[@"placeId"] = [RadarState placeId];
params[@"regionIds"] = [RadarState regionIds];
params[@"beaconIds"] = [RadarState beaconIds];
} else {
params[@"id"] = [RadarSettings _id];
params[@"installId"] = [RadarSettings installId];
params[@"userId"] = [RadarSettings userId];
params[@"deviceId"] = [RadarUtils deviceId];
params[@"description"] = [RadarSettings __description];
params[@"metadata"] = [RadarSettings metadata];
NSString *sessionId = [RadarSettings sessionId];
if (sessionId) {
params[@"sessionId"] = sessionId;
}
}
params[@"latitude"] = @(location.coordinate.latitude);
params[@"longitude"] = @(location.coordinate.longitude);
CLLocationAccuracy accuracy = location.horizontalAccuracy;
if (accuracy <= 0) {
accuracy = 1;
}
params[@"accuracy"] = @(accuracy);
params[@"altitude"] = @(location.altitude);
params[@"verticalAccuracy"] = @(location.verticalAccuracy);
params[@"speed"] = @(location.speed);
params[@"speedAccuracy"] = @(location.speedAccuracy);
params[@"course"] = @(location.course);
if (@available(iOS 13.4, *)) {
params[@"courseAccuracy"] = @(location.courseAccuracy);
}
if (location.floor) {
params[@"floorLevel"] = @(location.floor.level);
}
long nowMs = (long)([NSDate date].timeIntervalSince1970 * 1000);
if (!foreground) {
long timeInMs = (long)(location.timestamp.timeIntervalSince1970 * 1000);
params[@"updatedAtMsDiff"] = @(nowMs - timeInMs);
}
params[@"foreground"] = @(foreground);
params[@"stopped"] = @(stopped);
params[@"replayed"] = @(replayed);
params[@"deviceType"] = [RadarUtils deviceType];
params[@"deviceMake"] = [RadarUtils deviceMake];
params[@"sdkVersion"] = [RadarUtils sdkVersion];
params[@"deviceModel"] = [RadarUtils deviceModel];
params[@"deviceOS"] = [RadarUtils deviceOS];
params[@"country"] = [RadarUtils country];
params[@"timeZoneOffset"] = [RadarUtils timeZoneOffset];
params[@"source"] = [Radar stringForLocationSource:source];
if ([RadarSettings xPlatform]) {
params[@"xPlatformType"] = [RadarSettings xPlatformSDKType];
params[@"xPlatformSDKVersion"] = [RadarSettings xPlatformSDKVersion];
} else {
params[@"xPlatformType"] = @"Native";
}
NSMutableArray<NSString *> *fraudFailureReasons = [NSMutableArray new];
if (@available(iOS 15.0, *)) {
CLLocationSourceInformation *sourceInformation = location.sourceInformation;
if (sourceInformation) {
if (sourceInformation.isSimulatedBySoftware) {
params[@"mocked"] = @(YES);
[fraudFailureReasons addObject:@"fraud_mocked_from_mock_provider"];
}
if (sourceInformation.isProducedByAccessory) {
[fraudFailureReasons addObject:@"fraud_mocked_produced_by_accessory"];
}
}
}

RadarTripOptions *tripOptions = Radar.getTripOptions;

if (tripOptions) {
NSMutableDictionary *tripParams = [NSMutableDictionary new];
tripParams[@"version"] = @("2");
[tripParams setValue:tripOptions.externalId forKey:@"externalId"];
[tripParams setValue:tripOptions.metadata forKey:@"metadata"];
[tripParams setValue:tripOptions.destinationGeofenceTag forKey:@"destinationGeofenceTag"];
[tripParams setValue:tripOptions.destinationGeofenceExternalId forKey:@"destinationGeofenceExternalId"];
[tripParams setValue:[Radar stringForMode:tripOptions.mode] forKey:@"mode"];
params[@"tripOptions"] = tripParams;
}

RadarTrackingOptions *options = [Radar getTrackingOptions];
if (options.syncGeofences) {
params[@"nearbyGeofences"] = @(YES);
}
if (beacons) {
params[@"beacons"] = [RadarBeacon arrayForBeacons:beacons];
}
NSString *locationAuthorization = [RadarUtils locationAuthorization];
if (locationAuthorization) {
params[@"locationAuthorization"] = locationAuthorization;
}
NSString *locationAccuracyAuthorization = [RadarUtils locationAccuracyAuthorization];
if (locationAccuracyAuthorization) {
params[@"locationAccuracyAuthorization"] = locationAccuracyAuthorization;
}
params[@"notificationAuthorization"] = [RadarState notificationPermissionGranted] ? @"true" : @"false";

params[@"trackingOptions"] = [options dictionaryValue];

BOOL usingRemoteTrackingOptions = RadarSettings.tracking && RadarSettings.remoteTrackingOptions;
params[@"usingRemoteTrackingOptions"] = @(usingRemoteTrackingOptions);

params[@"verified"] = @(verified);
if (verified) {
params[@"attestationString"] = attestationString;
params[@"keyId"] = keyId;
params[@"attestationError"] = attestationError;
params[@"encrypted"] = @(encrypted);
BOOL jailbroken = [[RadarVerificationManager sharedInstance] isJailbroken];
params[@"compromised"] = @(jailbroken);
if (jailbroken) {
[fraudFailureReasons addObject:@"fraud_compromised_jailbroken"];
}
if (expectedCountryCode) {
params[@"expectedCountryCode"] = expectedCountryCode;
}
if (expectedStateCode) {
params[@"expectedStateCode"] = expectedStateCode;
}
}
params[@"appId"] = [[NSBundle mainBundle] bundleIdentifier];
RadarSdkConfiguration *sdkConfiguration = [RadarSettings sdkConfiguration];
if (sdkConfiguration.useLocationMetadata) {
NSMutableDictionary *locationMetadata = [NSMutableDictionary new];
locationMetadata[@"motionActivityData"] = [RadarState lastMotionActivityData];
locationMetadata[@"heading"] = [RadarState lastHeadingData];
locationMetadata[@"speed"] = @(location.speed);
locationMetadata[@"speedAccuracy"] = @(location.speedAccuracy);
locationMetadata[@"course"] = @(location.course);

if (@available(iOS 13.4, *)) {
locationMetadata[@"courseAccuracy"] = @(location.courseAccuracy);
}

locationMetadata[@"battery"] = @([[UIDevice currentDevice] batteryLevel]);
locationMetadata[@"altitude"] = @(location.altitude);

if (@available(iOS 15, *)) {
locationMetadata[@"ellipsoidalAltitude"] = @(location.ellipsoidalAltitude);
locationMetadata[@"isProducedByAccessory"] = @([location.sourceInformation isProducedByAccessory]);
locationMetadata[@"isSimulatedBySoftware"] = @([location.sourceInformation isSimulatedBySoftware]);
}
locationMetadata[@"floor"] = @([location.floor level]);

params[@"locationMetadata"] = locationMetadata;
}

params[@"fraudFailureReasons"] = fraudFailureReasons;

// added after API call fail
params[@"replayed"] = @(YES);
params[@"updatedAtMs"] = @(nowMs);

return params;
}

@end

0 comments on commit 7e87e5e

Please sign in to comment.