diff --git a/Signal/src/util/Backup/OWSBackup.h b/Signal/src/util/Backup/OWSBackup.h index 058e9a355..459c7ec54 100644 --- a/Signal/src/util/Backup/OWSBackup.h +++ b/Signal/src/util/Backup/OWSBackup.h @@ -7,6 +7,7 @@ NS_ASSUME_NONNULL_BEGIN extern NSString *const NSNotificationNameBackupStateDidChange; typedef void (^OWSBackupBoolBlock)(BOOL value); +typedef void (^OWSBackupStringListBlock)(NSArray *value); typedef void (^OWSBackupErrorBlock)(NSError *error); typedef NS_ENUM(NSUInteger, OWSBackupState) { @@ -66,6 +67,8 @@ NSString *NSStringForBackupImportState(OWSBackupState state); @property (nonatomic, readonly, nullable) NSString *backupImportDescription; @property (nonatomic, readonly, nullable) NSNumber *backupImportProgress; +- (void)allRecipientIdsWithManifestsInCloud:(OWSBackupStringListBlock)success failure:(OWSBackupErrorBlock)failure; + - (void)checkCanImportBackup:(OWSBackupBoolBlock)success failure:(OWSBackupErrorBlock)failure; // TODO: After a successful import, we should enable backup and diff --git a/Signal/src/util/Backup/OWSBackup.m b/Signal/src/util/Backup/OWSBackup.m index 308d0a4dd..ad90e4233 100644 --- a/Signal/src/util/Backup/OWSBackup.m +++ b/Signal/src/util/Backup/OWSBackup.m @@ -373,6 +373,25 @@ NSString *NSStringForBackupImportState(OWSBackupState state) #pragma mark - Backup Import +- (void)allRecipientIdsWithManifestsInCloud:(OWSBackupStringListBlock)success failure:(OWSBackupErrorBlock)failure +{ + OWSAssertIsOnMainThread(); + + OWSLogInfo(@""); + + [OWSBackupAPI + allRecipientIdsWithManifestsInCloudWithSuccess:^(NSArray *recipientIds) { + dispatch_async(dispatch_get_main_queue(), ^{ + success(recipientIds); + }); + } + failure:^(NSError *error) { + dispatch_async(dispatch_get_main_queue(), ^{ + failure(error); + }); + }]; +} + - (void)checkCanImportBackup:(OWSBackupBoolBlock)success failure:(OWSBackupErrorBlock)failure { OWSAssertIsOnMainThread(); diff --git a/Signal/src/util/Backup/OWSBackupAPI.swift b/Signal/src/util/Backup/OWSBackupAPI.swift index 8138f05d0..121680c5a 100644 --- a/Signal/src/util/Backup/OWSBackupAPI.swift +++ b/Signal/src/util/Backup/OWSBackupAPI.swift @@ -19,6 +19,7 @@ import CloudKit // // TODO: Change the record types when we ship to production. static let signalBackupRecordType = "signalBackup" + static let manifestRecordNameSuffix = "manifest" static let payloadKey = "payload" static let maxRetries = 5 @@ -84,11 +85,15 @@ import CloudKit // backups can reuse the same record. @objc public class func recordNameForManifest(recipientId: String) -> String { - return "\(recordNamePrefix(forRecipientId: recipientId))manifest" + return "\(recordNamePrefix(forRecipientId: recipientId))\(manifestRecordNameSuffix)" + } + + private class func isManifest(recordName: String) -> Bool { + return recordName.hasSuffix(manifestRecordNameSuffix) } private class func recordNamePrefix(forRecipientId recipientId: String) -> String { - return "\(recipientId)-" + return "\(recipientId)-" } private class func recipientId(forRecordName recordName: String) -> String? { @@ -413,43 +418,68 @@ import CloudKit } @objc - public class func fetchAllRecordNames(recipientId: String, - success: @escaping ([String]) -> Void, - failure: @escaping (Error) -> Void) { + public class func allRecipientIdsWithManifestsInCloud(success: @escaping ([String]) -> Void, + failure: @escaping (Error) -> Void) { + + let processResults = { (recordNames: [String]) in + DispatchQueue.global().async { + let manifestRecordNames = recordNames.filter({ (recordName) -> Bool in + self.isManifest(recordName: recordName) + }) + let recipientIds = self.recipientIds(forRecordNames: manifestRecordNames) + success(recipientIds) + } + } let query = CKQuery(recordType: signalBackupRecordType, predicate: NSPredicate(value: true)) // Fetch the first page of results for this query. - fetchAllRecordNamesStep(recipientId: recipientId, + fetchAllRecordNamesStep(recipientId: nil, query: query, previousRecordNames: [String](), cursor: nil, remainingRetries: maxRetries, - success: success, + success: processResults, failure: failure) } @objc - public class func fetchAllBackupRecipientIds(success: @escaping ([String]) -> Void, - failure: @escaping (Error) -> Void) { - - let processResults = { (recordNames: [String]) in - DispatchQueue.global().async { - let recipientIds = self.recipientIds(forRecordNames: recordNames) - success(recipientIds) - } - } + public class func fetchAllRecordNames(recipientId: String, + success: @escaping ([String]) -> Void, + failure: @escaping (Error) -> Void) { let query = CKQuery(recordType: signalBackupRecordType, predicate: NSPredicate(value: true)) // Fetch the first page of results for this query. - fetchAllRecordNamesStep(recipientId: nil, + fetchAllRecordNamesStep(recipientId: recipientId, query: query, previousRecordNames: [String](), cursor: nil, remainingRetries: maxRetries, - success: processResults, + success: success, failure: failure) } +// @objc +// public class func fetchAllBackupRecipientIds(success: @escaping ([String]) -> Void, +// failure: @escaping (Error) -> Void) { +// +// let processResults = { (recordNames: [String]) in +// DispatchQueue.global().async { +// let recipientIds = self.recipientIds(forRecordNames: recordNames) +// success(recipientIds) +// } +// } +// +// let query = CKQuery(recordType: signalBackupRecordType, predicate: NSPredicate(value: true)) +// // Fetch the first page of results for this query. +// fetchAllRecordNamesStep(recipientId: nil, +// query: query, +// previousRecordNames: [String](), +// cursor: nil, +// remainingRetries: maxRetries, +// success: processResults, +// failure: failure) +// } + private class func fetchAllRecordNamesStep(recipientId: String?, query: CKQuery, previousRecordNames: [String],