Skip to content

Commit

Permalink
Merge pull request #605 from Simperium/develop
Browse files Browse the repository at this point in the history
Simperium Mk 1.1.0
  • Loading branch information
jleandroperez committed Nov 6, 2020
2 parents e10b721 + 82554ea commit 9e09db6
Show file tree
Hide file tree
Showing 5 changed files with 102 additions and 18 deletions.
8 changes: 4 additions & 4 deletions Simperium.xcodeproj/project.pbxproj
Expand Up @@ -2099,7 +2099,7 @@
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
IPHONEOS_DEPLOYMENT_TARGET = 11.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
MARKETING_VERSION = 1.0.0;
MARKETING_VERSION = 1.1.0;
MTL_ENABLE_DEBUG_INFO = YES;
PRODUCT_BUNDLE_IDENTIFIER = com.automattic.simperium;
PRODUCT_NAME = Simperium;
Expand Down Expand Up @@ -2150,7 +2150,7 @@
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
IPHONEOS_DEPLOYMENT_TARGET = 11.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
MARKETING_VERSION = 1.0.0;
MARKETING_VERSION = 1.1.0;
MTL_ENABLE_DEBUG_INFO = NO;
PRODUCT_BUNDLE_IDENTIFIER = com.automattic.simperium;
PRODUCT_NAME = Simperium;
Expand Down Expand Up @@ -2207,7 +2207,7 @@
IPHONEOS_DEPLOYMENT_TARGET = 11.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
MACOSX_DEPLOYMENT_TARGET = 10.13;
MARKETING_VERSION = 1.0.0;
MARKETING_VERSION = 1.1.0;
MTL_ENABLE_DEBUG_INFO = YES;
PRODUCT_BUNDLE_IDENTIFIER = com.automattic.simperium;
PRODUCT_NAME = Simperium;
Expand Down Expand Up @@ -2259,7 +2259,7 @@
IPHONEOS_DEPLOYMENT_TARGET = 11.0;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
MACOSX_DEPLOYMENT_TARGET = 10.13;
MARKETING_VERSION = 1.0.0;
MARKETING_VERSION = 1.1.0;
MTL_ENABLE_DEBUG_INFO = NO;
PRODUCT_BUNDLE_IDENTIFIER = com.automattic.simperium;
PRODUCT_NAME = Simperium;
Expand Down
2 changes: 1 addition & 1 deletion Simperium/SPEnvironment.m
Expand Up @@ -30,7 +30,7 @@
#endif

// TODO: Update this automatically via a script that looks at current git tag
NSString* const SPLibraryVersion = @"1.0.0";
NSString* const SPLibraryVersion = @"1.1.0";

/// SSL Pinning
///
Expand Down
26 changes: 26 additions & 0 deletions Simperium/SPPersistentMutableDictionary.h
Expand Up @@ -16,13 +16,39 @@

@interface SPPersistentMutableDictionary : NSObject

/// The Dictionary's Label is used to define the Persistent Store identifier. Different labels will map to different persistent databases.
///
@property (nonatomic, strong, readonly) NSString *label;

/// Specifies the Supported Types
/// - Note: All classes specified here must conform to NSSecureCoding
///
@property (nonatomic, strong, readwrite) NSSet<Class> *supportedObjectTypes;

/// Indicates if the stored `Supported Object Types` should be required to conform to NSCoding. Defaults to YES
/// - Important: Only used for Unit Testing purposes!
///
@property (nonatomic, assign, readwrite) BOOL requiringSecureCoding;


/// Returns the total number of stored entities
///
- (NSInteger)count;

/// Indicates if there's an object associated ot the specified Key
///
- (BOOL)containsObjectForKey:(id)aKey;

/// Returns an object associated to the specified Key. Note that the resulting Object Type will be constrained by the `supportedObjectTypes` collection
///
- (id)objectForKey:(NSString*)aKey;

/// Stores the specified Object. Please note that the Object's Type must be specified by the `supportedObjectTypes` collection
///
- (void)setObject:(id)anObject forKey:(NSString*)aKey;

/// Persists the internal stack
///
- (BOOL)save;

- (NSArray*)allKeys;
Expand Down
52 changes: 40 additions & 12 deletions Simperium/SPPersistentMutableDictionary.m
Expand Up @@ -47,7 +47,13 @@ - (instancetype)initWithLabel:(NSString *)label {
self = [super init];
if (self) {
self.label = label;
self.cache = [[NSCache alloc] init];
self.cache = [NSCache new];
self.requiringSecureCoding = YES;
self.supportedObjectTypes = [NSSet setWithArray:@[
[NSDictionary class],
[NSArray class],
[NSString class]
]];
}

return self;
Expand Down Expand Up @@ -111,7 +117,9 @@ - (id)objectForKey:(id)aKey {
// Unarchive
id archivedValue = [object valueForKey:SPDictionaryEntityValue];
if (archivedValue) {
value = [NSKeyedUnarchiver unarchiveObjectWithData:archivedValue];
value = [NSKeyedUnarchiver unarchivedObjectOfClasses:self.supportedObjectTypes
fromData:archivedValue
error:nil];
}
}
}];
Expand All @@ -131,6 +139,8 @@ - (void)setObject:(id)anObject forKey:(NSString*)aKey {
return;
}

NSAssert([self canStoreObject:anObject], @"Unsupported Object Type");

[self.managedObjectContext performBlock:^{

NSError *error = nil;
Expand All @@ -146,9 +156,11 @@ - (void)setObject:(id)anObject forKey:(NSString*)aKey {
change = [NSEntityDescription insertNewObjectForEntityForName:SPDictionaryEntityName inManagedObjectContext:self.managedObjectContext];
[change setValue:aKey forKey:SPDictionaryEntityKey];
}

// Wrap up the value
id archivedValue = [NSKeyedArchiver archivedDataWithRootObject:anObject];
id archivedValue = [NSKeyedArchiver archivedDataWithRootObject:anObject
requiringSecureCoding:self.requiringSecureCoding
error:nil];
[change setValue:archivedValue forKey:SPDictionaryEntityValue];
}];

Expand Down Expand Up @@ -245,12 +257,12 @@ - (NSManagedObjectModel *)managedObjectModel {

// Dynamic Attributes
NSAttributeDescription *keyAttribute = [[NSAttributeDescription alloc] init];
keyAttribute.name = @"key";
keyAttribute.name = SPDictionaryEntityKey;
keyAttribute.attributeType = NSStringAttributeType;
keyAttribute.optional = NO;

NSAttributeDescription *valueAttribute = [[NSAttributeDescription alloc] init];
valueAttribute.name = @"value";
valueAttribute.name = SPDictionaryEntityValue;
valueAttribute.attributeType = NSBinaryDataAttributeType;
valueAttribute.optional = NO;

Expand Down Expand Up @@ -434,7 +446,7 @@ - (NSFetchRequest *)requestForEntityWithKey:(id)aKey {
}

- (NSArray *)loadObjectsProperty:(NSString*)property unarchive:(BOOL)unarchive {
NSMutableArray *keys = [NSMutableArray array];
NSMutableArray *output = [NSMutableArray array];

[self.managedObjectContext performBlockAndWait:^{

Expand All @@ -450,15 +462,31 @@ - (NSArray *)loadObjectsProperty:(NSString*)property unarchive:(BOOL)unarchive {
continue;
}

if (unarchive) {
[keys addObject:[NSKeyedUnarchiver unarchiveObjectWithData:value]];
} else {
[keys addObject:value];
if (!unarchive) {
[output addObject:value];
continue;;
}

id decodedValue = [NSKeyedUnarchiver unarchivedObjectOfClasses:self.supportedObjectTypes
fromData:value
error:nil];
if (decodedValue) {
[output addObject:decodedValue];
}
}
}];

return keys;
return output;
}

- (BOOL)canStoreObject:(id)anObject {
for (Class supportedClass in self.supportedObjectTypes) {
if ([anObject isKindOfClass:supportedClass]) {
return YES;
}
}

return NO;
}

@end
32 changes: 31 additions & 1 deletion SimperiumTests/SPPersistentMutableDictionaryTests.m
Expand Up @@ -176,12 +176,34 @@ - (void)testStressReopeningMutableDictionaryInBackground {
[self waitForExpectationsWithTimeout:SPStressTimeout handler:nil];
}

- (void)testDictionaryStoredWithSecureCodingCanBeLoadedByDictionaryWithoutSecureCoding {
NSString *label = [NSString sp_makeUUID];
SPPersistentMutableDictionary *insecureStorage = [SPPersistentMutableDictionary loadDictionaryWithLabel:label];
insecureStorage.requiringSecureCoding = NO;

NSDictionary *samples = [self sampleKeyValues];
for (NSString *key in samples.allKeys) {
[insecureStorage setObject:samples[key] forKey:key];
}

[insecureStorage save];

SPPersistentMutableDictionary *secureStorage = [SPPersistentMutableDictionary loadDictionaryWithLabel:label];
insecureStorage.requiringSecureCoding = YES;
for (NSString *key in samples.allKeys) {
id retrievedValue = [secureStorage objectForKey:key];
id expectedValue = samples[key];

XCTAssertTrue([retrievedValue isEqual:expectedValue]);
}
}


#pragma mark ====================================================================================
#pragma mark Helpers
#pragma mark ====================================================================================

- (NSDictionary*)randomContentObject {
- (NSDictionary *)randomContentObject {
NSMutableDictionary *random = [NSMutableDictionary dictionary];

for (NSInteger i = 0; ++i <= SPMetadataIterations; ) {
Expand All @@ -191,4 +213,12 @@ - (NSDictionary*)randomContentObject {
return random;
}

- (NSDictionary *)sampleKeyValues {
return @{
@"1" : @"YO! Yosemite!",
@"2" : @{ @1234: @"567" },
@"3" : @[ @1, @"2" ]
};
}

@end

0 comments on commit 9e09db6

Please sign in to comment.