From b9ccee398e04bfd2a900edcb5a5d5d2917a7f690 Mon Sep 17 00:00:00 2001 From: Maarten Billemont Date: Fri, 24 Aug 2012 10:12:15 +0200 Subject: [PATCH] Fixed a few crashes. [UPDATED] A nil type is never OK. Crash early if it is so. [UPDATED] Set crashlytics identifiers using its userIdentifier and userName property for good metadata. [FIXED] Make sure the MOC has a PSC with stores when returning it. [FIXED] Don't reset the store for just any open error! Only if it's actually incompatible. [IMPROVED] Remove timestamps from Crashlytics and TestFlight logs, they already provide them. [FIXED] Avoid crashes in some odd cases where there's no type set. --- External/iCloudStoreManager | 2 +- MasterPassword/MPAlgorithmV0.m | 2 +- MasterPassword/MPAppDelegate_Key.m | 3 +- MasterPassword/MPAppDelegate_Store.m | 79 ++- .../MasterPassword 3.xcdatamodel/contents | 10 +- MasterPassword/iOS/MPAppDelegate.m | 17 +- MasterPassword/iOS/MPSearchDelegate.m | 5 + .../iOS/MainStoryboard_iPhone.storyboard | 551 +++++++++--------- MasterPassword/iOS/Settings.bundle/Root.plist | 4 +- 9 files changed, 351 insertions(+), 322 deletions(-) diff --git a/External/iCloudStoreManager b/External/iCloudStoreManager index a7b028ff..8c7894a9 160000 --- a/External/iCloudStoreManager +++ b/External/iCloudStoreManager @@ -1 +1 @@ -Subproject commit a7b028ff80cd4768be686a9ef2067dfd31989ce0 +Subproject commit 8c7894a983f1c1e0795a6e3d5ee7a223a5e01a54 diff --git a/MasterPassword/MPAlgorithmV0.m b/MasterPassword/MPAlgorithmV0.m index 40763c7f..015c3b8a 100644 --- a/MasterPassword/MPAlgorithmV0.m +++ b/MasterPassword/MPAlgorithmV0.m @@ -153,7 +153,7 @@ - (Class)classOfType:(MPElementType)type { if (!type) - return nil; + Throw(@"No type given."); switch (type) { case MPElementTypeGeneratedMaximum: diff --git a/MasterPassword/MPAppDelegate_Key.m b/MasterPassword/MPAppDelegate_Key.m index 45b02955..deda78d5 100644 --- a/MasterPassword/MPAppDelegate_Key.m +++ b/MasterPassword/MPAppDelegate_Key.m @@ -148,7 +148,8 @@ static NSDictionary *keyQuery(MPUserEntity *user) { @try { if ([[MPiOSConfig get].sendInfo boolValue]) { [TestFlight addCustomEnvironmentInformation:user.userID forKey:@"username"]; - [[Crashlytics sharedInstance] setObjectValue:user.userID forKey:@"username"]; + [Crashlytics setObjectValue:user.userID forKey:@"username"]; + [Crashlytics setUserName:user.userID]; } } @catch (id exception) { diff --git a/MasterPassword/MPAppDelegate_Store.m b/MasterPassword/MPAppDelegate_Store.m index 90563ea2..89c91b47 100644 --- a/MasterPassword/MPAppDelegate_Store.m +++ b/MasterPassword/MPAppDelegate_Store.m @@ -29,8 +29,7 @@ if (managedObjectModel) return managedObjectModel; - NSURL *modelURL = [[NSBundle mainBundle] URLForResource:@"MasterPassword" withExtension:@"momd"]; - return managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL]; + return managedObjectModel = [NSManagedObjectModel mergedModelFromBundles:nil]; } - (NSManagedObjectContext *)managedObjectContextIfReady { @@ -39,15 +38,21 @@ return nil; static NSManagedObjectContext *managedObjectContext = nil; - if (managedObjectContext) - return managedObjectContext; + if (!managedObjectContext) { + managedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType]; + [managedObjectContext performBlockAndWait:^{ + managedObjectContext.mergePolicy = NSMergeByPropertyObjectTrumpMergePolicy; + managedObjectContext.undoManager = [NSUndoManager new]; + }]; + } - managedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType]; - [managedObjectContext performBlockAndWait:^{ - managedObjectContext.mergePolicy = NSMergeByPropertyObjectTrumpMergePolicy; - managedObjectContext.persistentStoreCoordinator = [self storeManager].persistentStoreCoordinator; - managedObjectContext.undoManager = [NSUndoManager new]; - }]; + if (![managedObjectContext.persistentStoreCoordinator.persistentStores count]) + [managedObjectContext performBlockAndWait:^{ + managedObjectContext.persistentStoreCoordinator = [self storeManager].persistentStoreCoordinator; + }]; + + if (![self storeManager].isReady) + return nil; return managedObjectContext; } @@ -62,7 +67,9 @@ localStoreURL:[[self applicationFilesDirectory] URLByAppendingPathComponent:@"MasterPassword.sqlite"] containerIdentifier:@"HL3Q45LX9N.com.lyndir.lhunath.MasterPassword.shared" #if TARGET_OS_IPHONE - additionalStoreOptions:@{NSPersistentStoreFileProtectionKey: NSFileProtectionComplete} + additionalStoreOptions:@{ + NSPersistentStoreFileProtectionKey: NSFileProtectionComplete + } #else additionalStoreOptions:nil #endif @@ -132,8 +139,9 @@ #ifdef TESTFLIGHT_SDK_VERSION [TestFlight passCheckpoint:iCloudEnabled? MPCheckpointCloudEnabled: MPCheckpointCloudDisabled]; #endif - [[LocalyticsSession sharedLocalyticsSession] tagEvent:MPCheckpointCloud - attributes:@{@"enabled": iCloudEnabled? @"YES": @"NO"}]; + [[LocalyticsSession sharedLocalyticsSession] tagEvent:MPCheckpointCloud attributes:@{ + @"enabled": iCloudEnabled? @"YES": @"NO" + }]; [MPConfig get].iCloud = @(iCloudEnabled); } @@ -154,27 +162,39 @@ case UbiquityStoreManagerErrorCauseClearStore: break; case UbiquityStoreManagerErrorCauseOpenLocalStore: { - wrn(@"Local store could not be opened, resetting it."); + wrn(@"Local store could not be opened: %@", error); + + if (error.code == NSMigrationMissingSourceModelError) { + wrn(@"Resetting the local store."); #ifdef TESTFLIGHT_SDK_VERSION - [TestFlight passCheckpoint:MPCheckpointLocalStoreIncompatible]; + [TestFlight passCheckpoint:MPCheckpointLocalStoreIncompatible]; #endif - [[LocalyticsSession sharedLocalyticsSession] tagEvent:MPCheckpointLocalStoreIncompatible attributes:nil]; - manager.hardResetEnabled = YES; - [manager hardResetLocalStorage]; + [[LocalyticsSession sharedLocalyticsSession] tagEvent:MPCheckpointLocalStoreIncompatible attributes:nil]; + manager.hardResetEnabled = YES; + [manager hardResetLocalStorage]; - Throw(@"Local store was reset, application must be restarted to use it."); + Throw(@"Local store was reset, application must be restarted to use it."); + } else + // Try again. + [self storeManager].persistentStoreCoordinator; } case UbiquityStoreManagerErrorCauseOpenCloudStore: { - wrn(@"iCloud store could not be opened, resetting it."); + wrn(@"iCloud store could not be opened: %@", error); + + if (error.code == NSMigrationMissingSourceModelError) { + wrn(@"Resetting the iCloud store."); #ifdef TESTFLIGHT_SDK_VERSION - [TestFlight passCheckpoint:MPCheckpointCloudStoreIncompatible]; + [TestFlight passCheckpoint:MPCheckpointCloudStoreIncompatible]; #endif - [[LocalyticsSession sharedLocalyticsSession] tagEvent:MPCheckpointCloudStoreIncompatible attributes:nil]; - manager.hardResetEnabled = YES; - [manager hardResetCloudStorage]; - break; + [[LocalyticsSession sharedLocalyticsSession] tagEvent:MPCheckpointCloudStoreIncompatible attributes:nil]; + manager.hardResetEnabled = YES; + [manager hardResetCloudStorage]; + break; + } else + // Try again. + [self storeManager].persistentStoreCoordinator; } } } @@ -366,8 +386,9 @@ // Create new site. __block MPImportResult result = MPImportResultSuccess; [self.managedObjectContextIfReady performBlockAndWait:^{ - MPElementEntity *element = [NSEntityDescription insertNewObjectForEntityForName:[MPAlgorithmForVersion(version) classNameOfType:type] - inManagedObjectContext:self.managedObjectContextIfReady]; + MPElementEntity *element = [NSEntityDescription insertNewObjectForEntityForName:[MPAlgorithmForVersion( + version) classNameOfType:type] + inManagedObjectContext:self.managedObjectContextIfReady]; element.name = name; element.user = user; element.type = type; @@ -384,11 +405,11 @@ result = MPImportResultInvalidPassword; return; } - + [element importProtectedContent:exportContent protectedByKey:importKey usingKey:userKey]; } } - + dbg(@"Created Element: %@", [element debugDescription]); }]; if (result != MPImportResultSuccess) diff --git a/MasterPassword/MasterPassword.xcdatamodeld/MasterPassword 3.xcdatamodel/contents b/MasterPassword/MasterPassword.xcdatamodeld/MasterPassword 3.xcdatamodel/contents index a724b37a..822228c6 100644 --- a/MasterPassword/MasterPassword.xcdatamodeld/MasterPassword 3.xcdatamodel/contents +++ b/MasterPassword/MasterPassword.xcdatamodeld/MasterPassword 3.xcdatamodel/contents @@ -1,5 +1,5 @@ - + @@ -32,9 +32,9 @@ - - - - + + + + \ No newline at end of file diff --git a/MasterPassword/iOS/MPAppDelegate.m b/MasterPassword/iOS/MPAppDelegate.m index 8c440612..7249d631 100644 --- a/MasterPassword/iOS/MPAppDelegate.m +++ b/MasterPassword/iOS/MPAppDelegate.m @@ -54,9 +54,10 @@ NSString *testFlightToken = [self testFlightToken]; if ([testFlightToken length]) { inf(@"Initializing TestFlight"); - [TestFlight addCustomEnvironmentInformation:@"Anonymous" forKey:@"username"]; [TestFlight setDeviceIdentifier:[(id)[UIDevice currentDevice] uniqueIdentifier]]; -// [TestFlight setDeviceIdentifier:[PearlKeyChain deviceIdentifier]]; + //[TestFlight setDeviceIdentifier[PearlKeyChain deviceIdentifier]]; + [TestFlight addCustomEnvironmentInformation:@"Anonymous" forKey:@"username"]; + [TestFlight addCustomEnvironmentInformation:[PearlKeyChain deviceIdentifier] forKey:@"deviceIdentifier"]; [TestFlight setOptions:[NSDictionary dictionaryWithObjectsAndKeys: [NSNumber numberWithBool:NO], @"logToConsole", [NSNumber numberWithBool:NO], @"logToSTDERR", @@ -68,7 +69,7 @@ level = PearlLogLevelInfo; if (message.level >= level) - TFLog(@"%@", message); + TFLog(@"%@", [message messageDescription]); return YES; }]; @@ -87,16 +88,18 @@ #if defined (DEBUG) || defined (ADHOC) [Crashlytics sharedInstance].debugMode = YES; #endif - [[Crashlytics sharedInstance] setObjectValue:@"Anonymous" forKey:@"username"]; - [[Crashlytics sharedInstance] setObjectValue:[PearlKeyChain deviceIdentifier] forKey:@"deviceIdentifier"]; - [Crashlytics startWithAPIKey:crashlyticsAPIKey afterDelay:0]; + [Crashlytics setUserIdentifier:[PearlKeyChain deviceIdentifier]]; + [Crashlytics setObjectValue:[PearlKeyChain deviceIdentifier] forKey:@"deviceIdentifier"]; + [Crashlytics setUserName:@"Anonymous"]; + [Crashlytics setObjectValue:@"Anonymous" forKey:@"username"]; + [Crashlytics startWithAPIKey:crashlyticsAPIKey]; [[PearlLogger get] registerListener:^BOOL(PearlLogMessage *message) { PearlLogLevel level = PearlLogLevelWarn; if ([[MPiOSConfig get].sendInfo boolValue]) level = PearlLogLevelInfo; if (message.level >= level) - CLSLog(@"%@", message); + CLSLog(@"%@", [message messageDescription]); return YES; }]; diff --git a/MasterPassword/iOS/MPSearchDelegate.m b/MasterPassword/iOS/MPSearchDelegate.m index cb0d068b..5d30c0e0 100644 --- a/MasterPassword/iOS/MPSearchDelegate.m +++ b/MasterPassword/iOS/MPSearchDelegate.m @@ -357,6 +357,11 @@ [self.fetchedResultsController.managedObjectContext performBlock:^{ MPElementType type = [MPAppDelegate get].activeUser.defaultType; + if (!type) { + // Really shouldn't happen, but a few people crashed on this anyway. Uhh. Data store corruption? Old bugs? + type = [MPAppDelegate get].activeUser.defaultType = MPElementTypeGeneratedLong; + } + MPElementEntity *element = [NSEntityDescription insertNewObjectForEntityForName:[MPAlgorithmDefault classNameOfType:type] inManagedObjectContext:self.fetchedResultsController.managedObjectContext]; assert([MPAppDelegate get].activeUser); diff --git a/MasterPassword/iOS/MainStoryboard_iPhone.storyboard b/MasterPassword/iOS/MainStoryboard_iPhone.storyboard index 1a9999b1..48662911 100644 --- a/MasterPassword/iOS/MainStoryboard_iPhone.storyboard +++ b/MasterPassword/iOS/MainStoryboard_iPhone.storyboard @@ -1,8 +1,7 @@ - + - - + @@ -28,23 +27,23 @@ - @@ -63,21 +62,21 @@ -