Backup local profile.

This commit is contained in:
Matthew Chen 2018-11-28 12:55:01 -05:00
parent 033044c1f5
commit d6ca969c62
7 changed files with 116 additions and 13 deletions

View File

@ -62,13 +62,13 @@ import PromiseKit
// We wouldn't want to overwrite previous images until the entire backup export is
// complete.
@objc
public class func saveEphemeralDatabaseFileToCloudObjc(recipientId: String,
public class func saveEphemeralFileToCloudObjc(recipientId: String,
fileUrl: URL) -> AnyPromise {
return AnyPromise(saveEphemeralDatabaseFileToCloud(recipientId: recipientId,
return AnyPromise(saveEphemeralFileToCloud(recipientId: recipientId,
fileUrl: fileUrl))
}
public class func saveEphemeralDatabaseFileToCloud(recipientId: String,
public class func saveEphemeralFileToCloud(recipientId: String,
fileUrl: URL) -> Promise<String> {
let recordName = "\(recordNamePrefix(forRecipientId: recipientId))ephemeralFile-\(NSUUID().uuidString)"
return saveFileToCloud(fileUrl: fileUrl,

View File

@ -308,6 +308,8 @@ NS_ASSUME_NONNULL_BEGIN
@property (nonatomic) NSMutableArray<OWSBackupExportItem *> *savedAttachmentItems;
@property (nonatomic, nullable) OWSBackupExportItem *localProfileAvatarItem;
@property (nonatomic, nullable) OWSBackupExportItem *manifestItem;
// If we are replacing an existing backup, we use some of its contents for continuity.
@ -335,6 +337,11 @@ NS_ASSUME_NONNULL_BEGIN
return AppEnvironment.shared.backup;
}
- (OWSProfileManager *)profileManager
{
return [OWSProfileManager sharedManager];
}
#pragma mark -
- (void)start
@ -722,6 +729,9 @@ NS_ASSUME_NONNULL_BEGIN
.thenInBackground(^{
return [self saveDatabaseFilesToCloud];
})
.thenInBackground(^{
return [self saveLocalProfileAvatarToCloud];
})
.thenInBackground(^{
return [self saveManifestFileToCloud];
});
@ -745,7 +755,7 @@ NS_ASSUME_NONNULL_BEGIN
}
return [OWSBackupAPI
saveEphemeralDatabaseFileToCloudObjcWithRecipientId:self.recipientId
saveEphemeralFileToCloudObjcWithRecipientId:self.recipientId
fileUrl:[NSURL fileURLWithPath:item.encryptedItem
.filePath]];
})
@ -876,6 +886,36 @@ NS_ASSUME_NONNULL_BEGIN
});
}
- (AnyPromise *)saveLocalProfileAvatarToCloud
{
if (self.isComplete) {
return [AnyPromise promiseWithValue:OWSBackupErrorWithDescription(@"Backup export no longer active.")];
}
NSData *_Nullable localProfileAvatarData = self.profileManager.localProfileAvatarData;
if (localProfileAvatarData.length < 1) {
// No profile avatar to backup.
return [AnyPromise promiseWithValue:@(1)];
}
OWSBackupEncryptedItem *_Nullable encryptedItem =
[self.backupIO encryptDataAsTempFile:localProfileAvatarData encryptionKey:self.delegate.backupEncryptionKey];
if (!encryptedItem) {
return [AnyPromise promiseWithValue:OWSBackupErrorWithDescription(@"Could not encrypt local profile avatar.")];
}
OWSBackupExportItem *exportItem = [OWSBackupExportItem new];
exportItem.encryptedItem = encryptedItem;
return [OWSBackupAPI saveEphemeralFileToCloudObjcWithRecipientId:self.recipientId
fileUrl:[NSURL fileURLWithPath:encryptedItem.filePath]]
.thenInBackground(^(NSString *recordName) {
exportItem.recordName = recordName;
self.localProfileAvatarItem = exportItem;
return [AnyPromise promiseWithValue:@(1)];
});
}
- (AnyPromise *)saveManifestFileToCloud
{
if (self.isComplete) {
@ -907,10 +947,19 @@ NS_ASSUME_NONNULL_BEGIN
OWSAssertDebug(self.jobTempDirPath.length > 0);
OWSAssertDebug(self.backupIO);
NSDictionary *json = @{
NSMutableDictionary *json = [@{
kOWSBackup_ManifestKey_DatabaseFiles : [self jsonForItems:self.savedDatabaseItems],
kOWSBackup_ManifestKey_AttachmentFiles : [self jsonForItems:self.savedAttachmentItems],
};
} mutableCopy];
NSString *_Nullable localProfileName = self.profileManager.localProfileName;
if (localProfileName.length > 0) {
json[kOWSBackup_ManifestKey_LocalProfileName] = localProfileName;
}
if (self.localProfileAvatarItem) {
json[kOWSBackup_ManifestKey_LocalProfileAvatar] = [self jsonForItems:@[ self.localProfileAvatarItem ]];
}
OWSLogVerbose(@"json: %@", json);

View File

@ -27,8 +27,7 @@ NSString *const kOWSBackup_ImportDatabaseKeySpec = @"kOWSBackup_ImportDatabaseKe
@property (nonatomic) OWSBackupIO *backupIO;
@property (nonatomic) NSArray<OWSBackupFragment *> *databaseItems;
@property (nonatomic) NSArray<OWSBackupFragment *> *attachmentsItems;
@property (nonatomic) OWSBackupManifestContents *manifest;
@end
@ -66,6 +65,20 @@ NSString *const kOWSBackup_ImportDatabaseKeySpec = @"kOWSBackup_ImportDatabaseKe
#pragma mark -
- (NSArray<OWSBackupFragment *> *)databaseItems
{
OWSAssertDebug(self.manifest);
return self.manifest.databaseItems;
}
- (NSArray<OWSBackupFragment *> *)attachmentsItems
{
OWSAssertDebug(self.manifest);
return self.manifest.attachmentsItems;
}
- (void)startAsync
{
OWSAssertIsOnMainThread();
@ -120,8 +133,7 @@ NSString *const kOWSBackup_ImportDatabaseKeySpec = @"kOWSBackup_ImportDatabaseKe
}
OWSCAssertDebug(manifest.databaseItems.count > 0);
OWSCAssertDebug(manifest.attachmentsItems);
strongSelf.databaseItems = manifest.databaseItems;
strongSelf.attachmentsItems = manifest.attachmentsItems;
strongSelf.manifest = manifest;
[strongSelf downloadAndProcessImport];
}
failure:^(NSError *manifestError) {

View File

@ -14,6 +14,8 @@ extern NSString *const kOWSBackup_ManifestKey_EncryptionKey;
extern NSString *const kOWSBackup_ManifestKey_RelativeFilePath;
extern NSString *const kOWSBackup_ManifestKey_AttachmentId;
extern NSString *const kOWSBackup_ManifestKey_DataSize;
extern NSString *const kOWSBackup_ManifestKey_LocalProfileAvatar;
extern NSString *const kOWSBackup_ManifestKey_LocalProfileName;
@class OWSBackupIO;
@class OWSBackupJob;
@ -28,6 +30,8 @@ typedef void (^OWSBackupJobManifestFailure)(NSError *error);
@property (nonatomic) NSArray<OWSBackupFragment *> *databaseItems;
@property (nonatomic) NSArray<OWSBackupFragment *> *attachmentsItems;
@property (nonatomic, nullable) OWSBackupFragment *localProfileAvatarItem;
@property (nonatomic, nullable) NSString *localProfileName;
@end

View File

@ -17,6 +17,8 @@ NSString *const kOWSBackup_ManifestKey_EncryptionKey = @"encryption_key";
NSString *const kOWSBackup_ManifestKey_RelativeFilePath = @"relative_file_path";
NSString *const kOWSBackup_ManifestKey_AttachmentId = @"attachment_id";
NSString *const kOWSBackup_ManifestKey_DataSize = @"data_size";
NSString *const kOWSBackup_ManifestKey_LocalProfileAvatar = @"local_profile_avatar";
NSString *const kOWSBackup_ManifestKey_LocalProfileName = @"local_profile_name";
NSString *const kOWSBackup_KeychainService = @"kOWSBackup_KeychainService";
@ -219,24 +221,50 @@ NSString *const kOWSBackup_KeychainService = @"kOWSBackup_KeychainService";
OWSLogVerbose(@"json: %@", json);
NSArray<OWSBackupFragment *> *_Nullable databaseItems =
[self parseItems:json key:kOWSBackup_ManifestKey_DatabaseFiles];
[self parseManifestItems:json key:kOWSBackup_ManifestKey_DatabaseFiles];
if (!databaseItems) {
return failure();
}
NSArray<OWSBackupFragment *> *_Nullable attachmentsItems =
[self parseItems:json key:kOWSBackup_ManifestKey_AttachmentFiles];
[self parseManifestItems:json key:kOWSBackup_ManifestKey_AttachmentFiles];
if (!attachmentsItems) {
return failure();
}
NSArray<OWSBackupFragment *> *_Nullable localProfileAvatarItems;
if ([self parseManifestItem:json key:kOWSBackup_ManifestKey_LocalProfileAvatar]) {
localProfileAvatarItems = [self parseManifestItems:json key:kOWSBackup_ManifestKey_LocalProfileAvatar];
}
NSString *_Nullable localProfileName = [self parseManifestItem:json key:kOWSBackup_ManifestKey_LocalProfileName];
OWSBackupManifestContents *contents = [OWSBackupManifestContents new];
contents.databaseItems = databaseItems;
contents.attachmentsItems = attachmentsItems;
contents.localProfileAvatarItem = localProfileAvatarItems.firstObject;
if ([localProfileName isKindOfClass:[NSString class]]) {
contents.localProfileName = localProfileName;
} else {
OWSFailDebug(@"Invalid localProfileName: %@", [localProfileName class]);
}
return success(contents);
}
- (nullable NSArray<OWSBackupFragment *> *)parseItems:(id)json key:(NSString *)key
- (nullable id)parseManifestItem:(id)json key:(NSString *)key
{
OWSAssertDebug(json);
OWSAssertDebug(key.length);
if (![json isKindOfClass:[NSDictionary class]]) {
OWSFailDebug(@"manifest has invalid data.");
return nil;
}
id _Nullable value = json[key];
return value;
}
- (nullable NSArray<OWSBackupFragment *> *)parseManifestItems:(id)json key:(NSString *)key
{
OWSAssertDebug(json);
OWSAssertDebug(key.length);

View File

@ -37,6 +37,7 @@ extern const NSUInteger kOWSProfileManager_MaxAvatarDiameter;
- (BOOL)hasLocalProfile;
- (nullable NSString *)localProfileName;
- (nullable UIImage *)localProfileAvatarImage;
- (nullable NSData *)localProfileAvatarData;
- (void)ensureLocalProfileCached;
// This method is used to update the "local profile" state on the client

View File

@ -217,6 +217,15 @@ typedef void (^ProfileManagerFailureBlock)(NSError *error);
return [self loadProfileAvatarWithFilename:self.localUserProfile.avatarFileName];
}
- (nullable NSData *)localProfileAvatarData
{
NSString *_Nullable filename = self.localUserProfile.avatarFileName;
if (filename.length < 1) {
return nil;
}
return [self loadProfileDataWithFilename:filename];
}
- (void)updateLocalProfileName:(nullable NSString *)profileName
avatarImage:(nullable UIImage *)avatarImage
success:(void (^)(void))successBlockParameter