Ignore local profile restore failures.

pull/1/head
Matthew Chen 7 years ago
parent c3704931ec
commit 0a4f004935

@ -141,14 +141,17 @@ NSString *const kOWSBackup_ImportDatabaseKeySpec = @"kOWSBackup_ImportDatabaseKe
// These items should be downloaded immediately. // These items should be downloaded immediately.
NSMutableArray<OWSBackupFragment *> *allItems = [NSMutableArray new]; NSMutableArray<OWSBackupFragment *> *allItems = [NSMutableArray new];
[allItems addObjectsFromArray:self.databaseItems]; [allItems addObjectsFromArray:self.databaseItems];
if (self.manifest.localProfileAvatarItem) {
[allItems addObject:self.manifest.localProfileAvatarItem];
}
// Make a copy of the blockingItems before we add // Make a copy of the blockingItems before we add
// the attachment items. // the optional items.
NSArray<OWSBackupFragment *> *blockingItems = [allItems copy]; NSArray<OWSBackupFragment *> *blockingItems = [allItems copy];
// Local profile avatars are optional in the sense that if their
// download fails, we want to proceed with the import.
if (self.manifest.localProfileAvatarItem) {
[allItems addObject:self.manifest.localProfileAvatarItem];
}
// Attachment items can be downloaded later; // Attachment items can be downloaded later;
// they will can be lazy-restored. // they will can be lazy-restored.
[allItems addObjectsFromArray:self.attachmentsItems]; [allItems addObjectsFromArray:self.attachmentsItems];
@ -224,13 +227,35 @@ NSString *const kOWSBackup_ImportDatabaseKeySpec = @"kOWSBackup_ImportDatabaseKe
AnyPromise *promise = [AnyPromise promiseWithValue:@(1)]; AnyPromise *promise = [AnyPromise promiseWithValue:@(1)];
for (OWSBackupFragment *item in items) { for (OWSBackupFragment *item in items) {
promise = promise.thenInBackground(^{ promise = promise
CGFloat progress = (recordCount > 0 ? ((recordCount - items.count) / (CGFloat)recordCount) : 0.f); .thenInBackground(^{
[self updateProgressWithDescription:NSLocalizedString(@"BACKUP_IMPORT_PHASE_DOWNLOAD", CGFloat progress
@"Indicates that the backup import data is being downloaded.") = (recordCount > 0 ? ((recordCount - items.count) / (CGFloat)recordCount) : 0.f);
progress:@(progress)]; [self updateProgressWithDescription:
}); NSLocalizedString(@"BACKUP_IMPORT_PHASE_DOWNLOAD",
@"Indicates that the backup import data is being downloaded.")
progress:@(progress)];
})
.thenInBackground(^{
return [self downloadFileFromCloud:item ignoreErrors:NO];
});
}
return promise;
}
- (AnyPromise *)downloadFileFromCloud:(OWSBackupFragment *)item ignoreErrors:(BOOL)ignoreErrors
{
OWSAssertDebug(item);
OWSLogVerbose(@"");
if (self.isComplete) {
// Job was aborted.
return [AnyPromise promiseWithValue:OWSBackupErrorWithDescription(@"Backup import no longer active.")];
}
return [AnyPromise promiseWithResolverBlock:^(PMKResolver resolve) {
// TODO: Use a predictable file path so that multiple "import backup" attempts // TODO: Use a predictable file path so that multiple "import backup" attempts
// will leverage successful file downloads from previous attempts. // will leverage successful file downloads from previous attempts.
// //
@ -243,23 +268,51 @@ NSString *const kOWSBackup_ImportDatabaseKeySpec = @"kOWSBackup_ImportDatabaseKe
item.downloadFilePath = tempFilePath; item.downloadFilePath = tempFilePath;
continue; return resolve(@(1));
} }
[OWSBackupAPI downloadFileFromCloudObjcWithRecordName:item.recordName
toFileUrl:[NSURL fileURLWithPath:tempFilePath]]
.thenInBackground(^{
[OWSFileSystem protectFileOrFolderAtPath:tempFilePath];
item.downloadFilePath = tempFilePath;
resolve(@(1));
})
.catchInBackground(^(NSError *error) {
if (ignoreErrors) {
resolve(@(1));
} else {
resolve(error);
}
});
}];
}
- (AnyPromise *)restoreLocalProfile
{
OWSLogVerbose(@"");
if (self.isComplete) {
// Job was aborted.
return [AnyPromise promiseWithValue:OWSBackupErrorWithDescription(@"Backup import no longer active.")];
}
AnyPromise *promise = [AnyPromise promiseWithValue:@(1)];
if (self.manifest.localProfileAvatarItem) {
promise = promise.thenInBackground(^{ promise = promise.thenInBackground(^{
return [OWSBackupAPI downloadFileFromCloudObjcWithRecordName:item.recordName return [self downloadFileFromCloud:self.manifest.localProfileAvatarItem ignoreErrors:YES];
toFileUrl:[NSURL fileURLWithPath:tempFilePath]]
.thenInBackground(^{
[OWSFileSystem protectFileOrFolderAtPath:tempFilePath];
item.downloadFilePath = tempFilePath;
});
}); });
} }
promise = promise.thenInBackground(^{
return [self applyLocalProfile];
});
return promise; return promise;
} }
- (AnyPromise *)restoreLocalProfile - (AnyPromise *)applyLocalProfile
{ {
OWSLogVerbose(@""); OWSLogVerbose(@"");
@ -269,52 +322,60 @@ NSString *const kOWSBackup_ImportDatabaseKeySpec = @"kOWSBackup_ImportDatabaseKe
} }
NSString *_Nullable localProfileName = self.manifest.localProfileName; NSString *_Nullable localProfileName = self.manifest.localProfileName;
UIImage *_Nullable localProfileAvatar = nil; UIImage *_Nullable localProfileAvatar = [self tryToLoadLocalProfileAvatar];
if (self.manifest.localProfileAvatarItem) { OWSLogVerbose(@"local profile name: %@, avatar: %d", localProfileName, localProfileAvatar != nil);
OWSBackupFragment *item = self.manifest.localProfileAvatarItem;
if (item.recordName.length < 1) {
OWSLogError(@"item was not downloaded.");
// Ignore errors related to local profile.
return [AnyPromise promiseWithValue:@(1)];
}
@autoreleasepool { if (localProfileName.length < 1 && !localProfileAvatar) {
NSData *_Nullable data = return [AnyPromise promiseWithValue:@(1)];
[self.backupIO decryptFileAsData:item.downloadFilePath encryptionKey:item.encryptionKey]; }
if (!data) {
OWSLogError(@"could not decrypt local profile avatar."); return [AnyPromise promiseWithResolverBlock:^(PMKResolver resolve) {
// Ignore errors related to local profile. [self.profileManager updateLocalProfileName:localProfileName
return [AnyPromise promiseWithValue:@(1)]; avatarImage:localProfileAvatar
success:^{
resolve(@(1));
} }
// TODO: Verify that we're not compressing the profile avatar data. failure:^{
UIImage *_Nullable image = [UIImage imageWithData:data];
if (!image) {
OWSLogError(@"could not decrypt local profile avatar.");
// Ignore errors related to local profile. // Ignore errors related to local profile.
return [AnyPromise promiseWithValue:@(1)]; resolve(@(1));
} }];
localProfileAvatar = image; }];
} }
}
OWSLogVerbose(@"local profile name: %@, avatar: %d", localProfileName, localProfileAvatar != nil); - (nullable UIImage *)tryToLoadLocalProfileAvatar
{
if (!self.manifest.localProfileAvatarItem) {
return nil;
}
if (!self.manifest.localProfileAvatarItem.downloadFilePath) {
// Download of the avatar failed.
// We can safely ignore errors related to local profile.
OWSLogError(@"local profile avatar was not downloaded.");
return nil;
}
OWSBackupFragment *item = self.manifest.localProfileAvatarItem;
if (item.recordName.length < 1) {
OWSFailDebug(@"item missing record name.");
return nil;
}
if (localProfileName.length > 0 || localProfileAvatar) { @autoreleasepool {
AnyPromise *promise = [AnyPromise promiseWithResolverBlock:^(PMKResolver resolve) { NSData *_Nullable data =
[self.profileManager updateLocalProfileName:localProfileName [self.backupIO decryptFileAsData:item.downloadFilePath encryptionKey:item.encryptionKey];
avatarImage:localProfileAvatar if (!data) {
success:^{ OWSLogError(@"could not decrypt local profile avatar.");
resolve(@(1)); // Ignore errors related to local profile.
} return nil;
failure:^{ }
// Ignore errors related to local profile. // TODO: Verify that we're not compressing the profile avatar data.
resolve(@(1)); UIImage *_Nullable image = [UIImage imageWithData:data];
}]; if (!image) {
}]; OWSLogError(@"could not decrypt local profile avatar.");
return promise; // Ignore errors related to local profile.
} else { return nil;
return [AnyPromise promiseWithValue:@(1)]; }
return image;
} }
} }

Loading…
Cancel
Save