diff --git a/Signal/src/Jobs/ConversationConfigurationSyncOperation.swift b/Signal/src/Jobs/ConversationConfigurationSyncOperation.swift index 6c7681073..db6e27879 100644 --- a/Signal/src/Jobs/ConversationConfigurationSyncOperation.swift +++ b/Signal/src/Jobs/ConversationConfigurationSyncOperation.swift @@ -68,6 +68,7 @@ class ConversationConfigurationSyncOperation: OWSOperation { self.dbConnection.readWrite { transaction in let messageData: Data = syncMessage.buildPlainTextAttachmentData(with: transaction) dataSource = DataSourceValue.dataSource(withSyncMessageData: messageData) + dataSource?.setShouldDeleteOnDeallocation() } guard let attachmentDataSource = dataSource else { @@ -89,6 +90,7 @@ class ConversationConfigurationSyncOperation: OWSOperation { self.dbConnection.read { transaction in let messageData: Data = syncMessage.buildPlainTextAttachmentData(with: transaction) dataSource = DataSourceValue.dataSource(withSyncMessageData: messageData) + dataSource?.setShouldDeleteOnDeallocation() } guard let attachmentDataSource = dataSource else { diff --git a/Signal/src/Jobs/MultiDeviceProfileKeyUpdateJob.swift b/Signal/src/Jobs/MultiDeviceProfileKeyUpdateJob.swift index c8f3df93e..81d33798e 100644 --- a/Signal/src/Jobs/MultiDeviceProfileKeyUpdateJob.swift +++ b/Signal/src/Jobs/MultiDeviceProfileKeyUpdateJob.swift @@ -51,6 +51,7 @@ import SignalMessaging var dataSource: DataSource? = nil self.editingDatabaseConnection.readWrite { transaction in dataSource = DataSourceValue.dataSource(withSyncMessageData: syncContactsMessage.buildPlainTextAttachmentData(with: transaction)) + dataSource?.setShouldDeleteOnDeallocation() } guard let attachmentDataSource = dataSource else { diff --git a/Signal/src/ViewControllers/ConversationView/ConversationViewController.m b/Signal/src/ViewControllers/ConversationView/ConversationViewController.m index 0aafdd920..3eca21e07 100644 --- a/Signal/src/ViewControllers/ConversationView/ConversationViewController.m +++ b/Signal/src/ViewControllers/ConversationView/ConversationViewController.m @@ -3948,9 +3948,9 @@ typedef enum : NSUInteger { if (newGroupModel.groupImage) { NSData *data = UIImagePNGRepresentation(newGroupModel.groupImage); DataSource *_Nullable dataSource = [DataSourceValue dataSourceWithData:data fileExtension:@"png"]; - [self.messageSender enqueueAttachment:dataSource + [dataSource setShouldDeleteOnDeallocation]; + [self.messageSender enqueueTemporaryAttachment:dataSource contentType:OWSMimeTypeImagePng - sourceFilename:nil inMessage:message success:^{ DDLogDebug(@"%@ Successfully sent group update with avatar", self.logTag); diff --git a/Signal/src/ViewControllers/DebugUI/DebugUISyncMessages.m b/Signal/src/ViewControllers/DebugUI/DebugUISyncMessages.m index 3cf600cef..c8159e032 100644 --- a/Signal/src/ViewControllers/DebugUI/DebugUISyncMessages.m +++ b/Signal/src/ViewControllers/DebugUI/DebugUISyncMessages.m @@ -104,6 +104,7 @@ NS_ASSUME_NONNULL_BEGIN dataSource = [DataSourceValue dataSourceWithSyncMessageData:[syncContactsMessage buildPlainTextAttachmentDataWithTransaction:transaction]]; + [dataSource setShouldDeleteOnDeallocation]; }]; [self.messageSender enqueueTemporaryAttachment:dataSource @@ -124,6 +125,7 @@ NS_ASSUME_NONNULL_BEGIN [self.dbConnection readWithBlock:^(YapDatabaseReadTransaction *transaction) { dataSource = [DataSourceValue dataSourceWithSyncMessageData:[syncGroupsMessage buildPlainTextAttachmentDataWithTransaction:transaction]]; + [dataSource setShouldDeleteOnDeallocation]; }]; [self.messageSender enqueueTemporaryAttachment:dataSource contentType:OWSMimeTypeApplicationOctetStream diff --git a/Signal/src/ViewControllers/NewGroupViewController.m b/Signal/src/ViewControllers/NewGroupViewController.m index 901ea951e..ed6bc9b39 100644 --- a/Signal/src/ViewControllers/NewGroupViewController.m +++ b/Signal/src/ViewControllers/NewGroupViewController.m @@ -490,12 +490,12 @@ const NSUInteger kNewGroupViewControllerAvatarWidth = 68; NSData *data = UIImagePNGRepresentation(model.groupImage); DataSource *_Nullable dataSource = [DataSourceValue dataSourceWithData:data fileExtension:@"png"]; - [self.messageSender enqueueAttachment:dataSource - contentType:OWSMimeTypeImagePng - sourceFilename:nil - inMessage:message - success:successHandler - failure:failureHandler]; + [dataSource setShouldDeleteOnDeallocation]; + [self.messageSender enqueueTemporaryAttachment:dataSource + contentType:OWSMimeTypeImagePng + inMessage:message + success:successHandler + failure:failureHandler]; } else { [self.messageSender enqueueMessage:message success:successHandler failure:failureHandler]; } diff --git a/SignalMessaging/contacts/OWSContactsSyncing.m b/SignalMessaging/contacts/OWSContactsSyncing.m index f2285ab09..77ff77376 100644 --- a/SignalMessaging/contacts/OWSContactsSyncing.m +++ b/SignalMessaging/contacts/OWSContactsSyncing.m @@ -126,7 +126,7 @@ NSString *const kOWSPrimaryStorageOWSContactsSyncingLastMessageKey __block NSData *messageData; __block NSData *lastMessageData; - [self.editingDatabaseConnection readWithBlock:^(YapDatabaseReadTransaction *_Nonnull transaction) { + [self.editingDatabaseConnection readWithBlock:^(YapDatabaseReadTransaction *transaction) { messageData = [syncContactsMessage buildPlainTextAttachmentDataWithTransaction:transaction]; lastMessageData = [transaction objectForKey:kOWSPrimaryStorageOWSContactsSyncingLastMessageKey inCollection:kOWSPrimaryStorageOWSContactsSyncingCollection]; @@ -140,6 +140,7 @@ NSString *const kOWSPrimaryStorageOWSContactsSyncingLastMessageKey self.isRequestInFlight = YES; DataSource *dataSource = [DataSourceValue dataSourceWithSyncMessageData:messageData]; + [dataSource setShouldDeleteOnDeallocation]; [self.messageSender enqueueTemporaryAttachment:dataSource contentType:OWSMimeTypeApplicationOctetStream inMessage:syncContactsMessage diff --git a/SignalServiceKit/src/Messages/Interactions/TSOutgoingMessage.m b/SignalServiceKit/src/Messages/Interactions/TSOutgoingMessage.m index 24259c7b7..53e81b7bf 100644 --- a/SignalServiceKit/src/Messages/Interactions/TSOutgoingMessage.m +++ b/SignalServiceKit/src/Messages/Interactions/TSOutgoingMessage.m @@ -354,6 +354,41 @@ NSString *NSStringForOutgoingMessageRecipientState(OWSOutgoingMessageRecipientSt return self; } +- (void)dealloc +{ + [self cleanUpTemporaryAttachmentsIfNecessary]; +} + +// Each message has the responsibility for eagerly cleaning up its attachments. +// Normally this is done in [TSMessage removeWithTransaction], but that doesn't +// apply for "transient", unsaved messages (i.e. shouldBeSaved == NO). These +// messages should clean up their attachments upon deallocation. +- (void)cleanUpTemporaryAttachmentsIfNecessary +{ + if (self.shouldBeSaved) { + // Message in not transient; no need to clean up attachments. + return; + } + NSArray *_Nullable attachmentIds = self.attachmentIds; + if (attachmentIds.count < 1) { + return; + } + [self.dbReadWriteConnection asyncReadWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) { + for (NSString *attachmentId in attachmentIds) { + // We need to fetch each attachment, since [TSAttachment removeWithTransaction:] does important work. + TSAttachment *_Nullable attachment = + [TSAttachment fetchObjectWithUniqueID:attachmentId transaction:transaction]; + if (!attachment) { + OWSCFail(@"%@ couldn't load interaction's attachment for deletion.", TSOutgoingMessage.logTag); + continue; + } + [attachment removeWithTransaction:transaction]; + }; + }]; +} + +#pragma mark - + - (TSOutgoingMessageState)messageState { TSOutgoingMessageState newMessageState = diff --git a/SignalServiceKit/src/Messages/OWSMessageManager.m b/SignalServiceKit/src/Messages/OWSMessageManager.m index 7becd7cf5..ec91be68f 100644 --- a/SignalServiceKit/src/Messages/OWSMessageManager.m +++ b/SignalServiceKit/src/Messages/OWSMessageManager.m @@ -658,6 +658,7 @@ NS_ASSUME_NONNULL_BEGIN DataSource *dataSource = [DataSourceValue dataSourceWithSyncMessageData:[syncContactsMessage buildPlainTextAttachmentDataWithTransaction:transaction]]; + [dataSource setShouldDeleteOnDeallocation]; [self.messageSender enqueueTemporaryAttachment:dataSource contentType:OWSMimeTypeApplicationOctetStream inMessage:syncContactsMessage @@ -674,6 +675,7 @@ NS_ASSUME_NONNULL_BEGIN DataSource *dataSource = [DataSourceValue dataSourceWithSyncMessageData:[syncGroupsMessage buildPlainTextAttachmentDataWithTransaction:transaction]]; + [dataSource setShouldDeleteOnDeallocation]; [self.messageSender enqueueTemporaryAttachment:dataSource contentType:OWSMimeTypeApplicationOctetStream inMessage:syncGroupsMessage @@ -825,9 +827,9 @@ NS_ASSUME_NONNULL_BEGIN if (gThread.groupModel.groupImage) { NSData *data = UIImagePNGRepresentation(gThread.groupModel.groupImage); DataSource *_Nullable dataSource = [DataSourceValue dataSourceWithData:data fileExtension:@"png"]; - [self.messageSender enqueueAttachment:dataSource + [dataSource setShouldDeleteOnDeallocation]; + [self.messageSender enqueueTemporaryAttachment:dataSource contentType:OWSMimeTypeImagePng - sourceFilename:nil inMessage:message success:^{ DDLogDebug(@"%@ Successfully sent group update with avatar", self.logTag); diff --git a/SignalServiceKit/src/Util/DataSource.m b/SignalServiceKit/src/Util/DataSource.m index df21acf9f..82dd3964b 100755 --- a/SignalServiceKit/src/Util/DataSource.m +++ b/SignalServiceKit/src/Util/DataSource.m @@ -102,7 +102,7 @@ NS_ASSUME_NONNULL_BEGIN @property (nonatomic) NSString *fileExtension; // This property is lazy-populated. -@property (nonatomic) NSString *cachedFilePath; +@property (nonatomic, nullable) NSString *cachedFilePath; @end @@ -113,7 +113,7 @@ NS_ASSUME_NONNULL_BEGIN - (void)dealloc { if (self.shouldDeleteOnDeallocation) { - NSString *filePath = self.cachedFilePath; + NSString *_Nullable filePath = self.cachedFilePath; if (filePath) { dispatch_async(dispatch_get_main_queue(), ^{ NSError *error;