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
= (recordCount > 0 ? ((recordCount - items.count) / (CGFloat)recordCount) : 0.f);
[self updateProgressWithDescription:
NSLocalizedString(@"BACKUP_IMPORT_PHASE_DOWNLOAD",
@"Indicates that the backup import data is being downloaded.") @"Indicates that the backup import data is being downloaded.")
progress:@(progress)]; 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));
} }
promise = promise.thenInBackground(^{ [OWSBackupAPI downloadFileFromCloudObjcWithRecordName:item.recordName
return [OWSBackupAPI downloadFileFromCloudObjcWithRecordName:item.recordName
toFileUrl:[NSURL fileURLWithPath:tempFilePath]] toFileUrl:[NSURL fileURLWithPath:tempFilePath]]
.thenInBackground(^{ .thenInBackground(^{
[OWSFileSystem protectFileOrFolderAtPath:tempFilePath]; [OWSFileSystem protectFileOrFolderAtPath:tempFilePath];
item.downloadFilePath = 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(^{
return [self downloadFileFromCloud:self.manifest.localProfileAvatarItem ignoreErrors:YES];
}); });
} }
promise = promise.thenInBackground(^{
return [self applyLocalProfile];
});
return promise; return promise;
} }
- (AnyPromise *)restoreLocalProfile - (AnyPromise *)applyLocalProfile
{ {
OWSLogVerbose(@""); OWSLogVerbose(@"");
@ -269,14 +322,42 @@ 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);
if (localProfileName.length < 1 && !localProfileAvatar) {
return [AnyPromise promiseWithValue:@(1)];
}
return [AnyPromise promiseWithResolverBlock:^(PMKResolver resolve) {
[self.profileManager updateLocalProfileName:localProfileName
avatarImage:localProfileAvatar
success:^{
resolve(@(1));
}
failure:^{
// Ignore errors related to local profile.
resolve(@(1));
}];
}];
}
- (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; OWSBackupFragment *item = self.manifest.localProfileAvatarItem;
if (item.recordName.length < 1) { if (item.recordName.length < 1) {
OWSLogError(@"item was not downloaded."); OWSFailDebug(@"item missing record name.");
// Ignore errors related to local profile. return nil;
return [AnyPromise promiseWithValue:@(1)];
} }
@autoreleasepool { @autoreleasepool {
@ -285,36 +366,16 @@ NSString *const kOWSBackup_ImportDatabaseKeySpec = @"kOWSBackup_ImportDatabaseKe
if (!data) { if (!data) {
OWSLogError(@"could not decrypt local profile avatar."); OWSLogError(@"could not decrypt local profile avatar.");
// Ignore errors related to local profile. // Ignore errors related to local profile.
return [AnyPromise promiseWithValue:@(1)]; return nil;
} }
// TODO: Verify that we're not compressing the profile avatar data. // TODO: Verify that we're not compressing the profile avatar data.
UIImage *_Nullable image = [UIImage imageWithData:data]; UIImage *_Nullable image = [UIImage imageWithData:data];
if (!image) { if (!image) {
OWSLogError(@"could not decrypt local profile avatar."); OWSLogError(@"could not decrypt local profile avatar.");
// Ignore errors related to local profile. // Ignore errors related to local profile.
return [AnyPromise promiseWithValue:@(1)]; return nil;
}
localProfileAvatar = image;
}
} }
return image;
OWSLogVerbose(@"local profile name: %@, avatar: %d", localProfileName, localProfileAvatar != nil);
if (localProfileName.length > 0 || localProfileAvatar) {
AnyPromise *promise = [AnyPromise promiseWithResolverBlock:^(PMKResolver resolve) {
[self.profileManager updateLocalProfileName:localProfileName
avatarImage:localProfileAvatar
success:^{
resolve(@(1));
}
failure:^{
// Ignore errors related to local profile.
resolve(@(1));
}];
}];
return promise;
} else {
return [AnyPromise promiseWithValue:@(1)];
} }
} }

Loading…
Cancel
Save