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.
This commit is contained in:
parent
7921734740
commit
b9ccee398e
2
External/iCloudStoreManager
vendored
2
External/iCloudStoreManager
vendored
@ -1 +1 @@
|
||||
Subproject commit a7b028ff80cd4768be686a9ef2067dfd31989ce0
|
||||
Subproject commit 8c7894a983f1c1e0795a6e3d5ee7a223a5e01a54
|
@ -153,7 +153,7 @@
|
||||
- (Class)classOfType:(MPElementType)type {
|
||||
|
||||
if (!type)
|
||||
return nil;
|
||||
Throw(@"No type given.");
|
||||
|
||||
switch (type) {
|
||||
case MPElementTypeGeneratedMaximum:
|
||||
|
@ -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) {
|
||||
|
@ -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;
|
||||
|
@ -1,5 +1,5 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||
<model name="" userDefinedModelVersionIdentifier="" type="com.apple.IDECoreDataModeler.DataModel" documentVersion="1.0" lastSavedToolsVersion="1487" systemVersion="12A269" minimumToolsVersion="Automatic" macOSVersion="Automatic" iOSVersion="Automatic">
|
||||
<model name="" userDefinedModelVersionIdentifier="" type="com.apple.IDECoreDataModeler.DataModel" documentVersion="1.0" lastSavedToolsVersion="1807" systemVersion="12A269" minimumToolsVersion="Automatic" macOSVersion="Automatic" iOSVersion="Automatic">
|
||||
<entity name="MPElementEntity" representedClassName="MPElementEntity" isAbstract="YES" syncable="YES">
|
||||
<attribute name="content" optional="YES" transient="YES" attributeType="Transformable" syncable="YES"/>
|
||||
<attribute name="lastUsed" attributeType="Date" indexed="YES" syncable="YES"/>
|
||||
@ -32,9 +32,9 @@
|
||||
<relationship name="elements" optional="YES" toMany="YES" deletionRule="Cascade" destinationEntity="MPElementEntity" inverseName="user" inverseEntity="MPElementEntity" syncable="YES"/>
|
||||
</entity>
|
||||
<elements>
|
||||
<element name="MPElementEntity" positionX="160" positionY="192" width="128" height="180"/>
|
||||
<element name="MPElementGeneratedEntity" positionX="160" positionY="192" width="128" height="60"/>
|
||||
<element name="MPElementStoredEntity" positionX="160" positionY="192" width="128" height="60"/>
|
||||
<element name="MPUserEntity" positionX="160" positionY="192" width="128" height="150"/>
|
||||
<element name="MPElementEntity" positionX="0" positionY="0" width="0" height="0"/>
|
||||
<element name="MPElementGeneratedEntity" positionX="0" positionY="0" width="0" height="0"/>
|
||||
<element name="MPElementStoredEntity" positionX="0" positionY="0" width="0" height="0"/>
|
||||
<element name="MPUserEntity" positionX="0" positionY="0" width="0" height="0"/>
|
||||
</elements>
|
||||
</model>
|
@ -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;
|
||||
}];
|
||||
|
@ -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);
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -6,7 +6,7 @@
|
||||
<array>
|
||||
<dict>
|
||||
<key>FooterText</key>
|
||||
<string>If you're experiencing problems, enabling this will send us details that can help diagnose and resolve them. Great care has been taken to guarantee no private information is ever sent.</string>
|
||||
<string>If you're experiencing problems, enabling this will send us details that can help diagnose and resolve them. You will remain completely anonymous amongst the other thousands of users. No sensitive information is ever sent.</string>
|
||||
<key>Title</key>
|
||||
<string></string>
|
||||
<key>Type</key>
|
||||
@ -48,7 +48,7 @@
|
||||
<key>Title</key>
|
||||
<string>Send Diagnostic Info</string>
|
||||
<key>Key</key>
|
||||
<string>sendInfo</string>
|
||||
<string>sendInfo</string>
|
||||
<key>DefaultValue</key>
|
||||
<false/>
|
||||
</dict>
|
||||
|
Loading…
Reference in New Issue
Block a user