From d76bdf3a58d61c6991feb85b741f3c52048fa253 Mon Sep 17 00:00:00 2001 From: Matthew Chen Date: Mon, 19 Nov 2018 14:28:28 -0500 Subject: [PATCH] Use attachment pointers to restore attachments from backup. --- Signal/src/util/Backup/OWSBackup.m | 5 ++++ Signal/src/util/Backup/OWSBackupExportJob.m | 12 ++++++++ .../src/Messages/Attachments/TSAttachment.h | 12 ++++---- .../src/Messages/Attachments/TSAttachment.m | 28 +++++++++++-------- .../Attachments/TSAttachmentPointer.h | 7 ++--- .../Attachments/TSAttachmentPointer.m | 20 ++++++------- .../src/Messages/OWSMessageSender.m | 2 +- 7 files changed, 54 insertions(+), 32 deletions(-) diff --git a/Signal/src/util/Backup/OWSBackup.m b/Signal/src/util/Backup/OWSBackup.m index b3288c510..e470f6a58 100644 --- a/Signal/src/util/Backup/OWSBackup.m +++ b/Signal/src/util/Backup/OWSBackup.m @@ -618,6 +618,11 @@ NS_ASSUME_NONNULL_BEGIN return completion(NO); } + if (![OWSFileSystem deleteFileIfExists:attachmentFilePath]) { + OWSLogError(@"Couldn't delete exist file at attachment path."); + return completion(NO); + } + NSError *error; BOOL success = [NSFileManager.defaultManager moveItemAtPath:decryptedFilePath toPath:attachmentFilePath error:&error]; diff --git a/Signal/src/util/Backup/OWSBackupExportJob.m b/Signal/src/util/Backup/OWSBackupExportJob.m index f3208051b..21c9f6e75 100644 --- a/Signal/src/util/Backup/OWSBackupExportJob.m +++ b/Signal/src/util/Backup/OWSBackupExportJob.m @@ -507,6 +507,17 @@ NS_ASSUME_NONNULL_BEGIN TSYapDatabaseObject *entity = object; count++; + if ([entity isKindOfClass:[TSAttachmentStream class]]) { + // Convert attachment streams to pointers, + // since we'll need to restore them. + TSAttachmentStream *attachmentStream + = (TSAttachmentStream *)entity; + TSAttachmentPointer *attachmentPointer = + [[TSAttachmentPointer alloc] + initForRestoreWithAttachmentStream:attachmentStream]; + entity = attachmentPointer; + } + if (![exportStream writeObject:entity entityType:entityType]) { *stop = YES; aborted = YES; @@ -536,6 +547,7 @@ NS_ASSUME_NONNULL_BEGIN [TSAttachment class], ^(id object) { if (![object isKindOfClass:[TSAttachmentStream class]]) { + // No need to backup the contents of attachment pointers. return NO; } TSAttachmentStream *attachmentStream = object; diff --git a/SignalServiceKit/src/Messages/Attachments/TSAttachment.h b/SignalServiceKit/src/Messages/Attachments/TSAttachment.h index dffa586f7..9e50d6c1d 100644 --- a/SignalServiceKit/src/Messages/Attachments/TSAttachment.h +++ b/SignalServiceKit/src/Messages/Attachments/TSAttachment.h @@ -6,6 +6,7 @@ NS_ASSUME_NONNULL_BEGIN +@class TSAttachmentPointer; @class TSMessage; typedef NS_ENUM(NSUInteger, TSAttachmentType) { @@ -64,10 +65,11 @@ typedef NS_ENUM(NSUInteger, TSAttachmentType) { // This constructor is used for new instances of TSAttachmentPointer, // i.e. undownloaded restoring attachments. -- (instancetype)initWithContentType:(NSString *)contentType - sourceFilename:(nullable NSString *)sourceFilename - caption:(nullable NSString *)caption - albumMessageId:(nullable NSString *)albumMessageId; +- (instancetype)initWithUniqueId:(NSString *)uniqueId + contentType:(NSString *)contentType + sourceFilename:(nullable NSString *)sourceFilename + caption:(nullable NSString *)caption + albumMessageId:(nullable NSString *)albumMessageId; // This constructor is used for new instances of TSAttachmentStream // that represent new, un-uploaded outgoing attachments. @@ -79,7 +81,7 @@ typedef NS_ENUM(NSUInteger, TSAttachmentType) { // This constructor is used for new instances of TSAttachmentStream // that represent downloaded incoming attachments. -- (instancetype)initWithPointer:(TSAttachment *)pointer; +- (instancetype)initWithPointer:(TSAttachmentPointer *)pointer; - (nullable instancetype)initWithCoder:(NSCoder *)coder; diff --git a/SignalServiceKit/src/Messages/Attachments/TSAttachment.m b/SignalServiceKit/src/Messages/Attachments/TSAttachment.m index 0ad173aba..3f7c1c22e 100644 --- a/SignalServiceKit/src/Messages/Attachments/TSAttachment.m +++ b/SignalServiceKit/src/Messages/Attachments/TSAttachment.m @@ -4,6 +4,7 @@ #import "TSAttachment.h" #import "MIMETypeUtil.h" +#import "TSAttachmentPointer.h" #import "TSMessage.h" #import #import @@ -67,11 +68,13 @@ NSUInteger const TSAttachmentSchemaVersion = 4; // This constructor is used for new instances of TSAttachmentPointer, // i.e. undownloaded restoring attachments. -- (instancetype)initWithContentType:(NSString *)contentType - sourceFilename:(nullable NSString *)sourceFilename - caption:(nullable NSString *)caption - albumMessageId:(nullable NSString *)albumMessageId +- (instancetype)initWithUniqueId:(NSString *)uniqueId + contentType:(NSString *)contentType + sourceFilename:(nullable NSString *)sourceFilename + caption:(nullable NSString *)caption + albumMessageId:(nullable NSString *)albumMessageId { + OWSAssertDebug(uniqueId.length > 0); if (contentType.length < 1) { OWSLogWarn(@"incoming attachment has invalid content type"); @@ -79,7 +82,8 @@ NSUInteger const TSAttachmentSchemaVersion = 4; } OWSAssertDebug(contentType.length > 0); - self = [super init]; + // Once saved, this AttachmentStream will replace the AttachmentPointer in the attachments collection. + self = [super initWithUniqueId:uniqueId]; if (!self) { return self; } @@ -128,13 +132,15 @@ NSUInteger const TSAttachmentSchemaVersion = 4; // This constructor is used for new instances of TSAttachmentStream // that represent downloaded incoming attachments. -- (instancetype)initWithPointer:(TSAttachment *)pointer +- (instancetype)initWithPointer:(TSAttachmentPointer *)pointer { - OWSAssertDebug(pointer.serverId > 0); - OWSAssertDebug(pointer.encryptionKey.length > 0); - if (pointer.byteCount <= 0) { - // This will fail with legacy iOS clients which don't upload attachment size. - OWSLogWarn(@"Missing pointer.byteCount for attachment with serverId: %lld", pointer.serverId); + if (!pointer.lazyRestoreFragment) { + OWSAssertDebug(pointer.serverId > 0); + OWSAssertDebug(pointer.encryptionKey.length > 0); + if (pointer.byteCount <= 0) { + // This will fail with legacy iOS clients which don't upload attachment size. + OWSLogWarn(@"Missing pointer.byteCount for attachment with serverId: %lld", pointer.serverId); + } } OWSAssertDebug(pointer.contentType.length > 0); diff --git a/SignalServiceKit/src/Messages/Attachments/TSAttachmentPointer.h b/SignalServiceKit/src/Messages/Attachments/TSAttachmentPointer.h index 9005d1326..156c88d7d 100644 --- a/SignalServiceKit/src/Messages/Attachments/TSAttachmentPointer.h +++ b/SignalServiceKit/src/Messages/Attachments/TSAttachmentPointer.h @@ -8,6 +8,7 @@ NS_ASSUME_NONNULL_BEGIN @class OWSBackupFragment; @class SSKProtoAttachmentPointer; +@class TSAttachmentStream; @class TSMessage; typedef NS_ENUM(NSUInteger, TSAttachmentPointerType) { @@ -49,11 +50,7 @@ typedef NS_ENUM(NSUInteger, TSAttachmentPointerState) { albumMessageId:(nullable NSString *)albumMessageId attachmentType:(TSAttachmentType)attachmentType NS_DESIGNATED_INITIALIZER; -- (instancetype)initForRestoreWithContentType:(NSString *)contentType - sourceFilename:(nullable NSString *)sourceFilename - caption:(nullable NSString *)caption - albumMessageId:(nullable NSString *)albumMessageId - attachmentType:(TSAttachmentType)attachmentType NS_DESIGNATED_INITIALIZER; +- (instancetype)initForRestoreWithAttachmentStream:(TSAttachmentStream *)attachmentStream NS_DESIGNATED_INITIALIZER; + (nullable TSAttachmentPointer *)attachmentPointerFromProto:(SSKProtoAttachmentPointer *)attachmentProto albumMessage:(nullable TSMessage *)message; diff --git a/SignalServiceKit/src/Messages/Attachments/TSAttachmentPointer.m b/SignalServiceKit/src/Messages/Attachments/TSAttachmentPointer.m index eca2a4666..49e62a349 100644 --- a/SignalServiceKit/src/Messages/Attachments/TSAttachmentPointer.m +++ b/SignalServiceKit/src/Messages/Attachments/TSAttachmentPointer.m @@ -4,6 +4,7 @@ #import "TSAttachmentPointer.h" #import "OWSBackupFragment.h" +#import "TSAttachmentStream.h" #import #import #import @@ -71,22 +72,21 @@ NS_ASSUME_NONNULL_BEGIN return self; } -- (instancetype)initForRestoreWithContentType:(NSString *)contentType - sourceFilename:(nullable NSString *)sourceFilename - caption:(nullable NSString *)caption - albumMessageId:(nullable NSString *)albumMessageId - attachmentType:(TSAttachmentType)attachmentType +- (instancetype)initForRestoreWithAttachmentStream:(TSAttachmentStream *)attachmentStream { - self = [super initWithContentType:contentType - sourceFilename:sourceFilename - caption:caption - albumMessageId:albumMessageId]; + OWSAssertDebug(attachmentStream); + + self = [super initWithUniqueId:attachmentStream.uniqueId + contentType:attachmentStream.contentType + sourceFilename:attachmentStream.sourceFilename + caption:attachmentStream.caption + albumMessageId:attachmentStream.albumMessageId]; if (!self) { return self; } _state = TSAttachmentPointerStateEnqueued; - self.attachmentType = attachmentType; + self.attachmentType = attachmentStream.attachmentType; _pointerType = TSAttachmentPointerTypeRestoring; return self; diff --git a/SignalServiceKit/src/Messages/OWSMessageSender.m b/SignalServiceKit/src/Messages/OWSMessageSender.m index e327b7f0b..d06c6aa5e 100644 --- a/SignalServiceKit/src/Messages/OWSMessageSender.m +++ b/SignalServiceKit/src/Messages/OWSMessageSender.m @@ -566,7 +566,7 @@ NSString *const OWSMessageSenderRateLimitedException = @"RateLimitedException"; } } else { // Neither a group nor contact thread? This should never happen. - OWSFailDebug(@"Unknown message type: %@", [message class]); + OWSLogError(@"Unknown message type: %@", [message class]); NSError *error = OWSErrorMakeFailedToSendOutgoingMessageError(); [error setIsRetryable:NO]; *errorHandle = error;