diff --git a/Signal/src/ViewControllers/ConversationView/ConversationViewController.m b/Signal/src/ViewControllers/ConversationView/ConversationViewController.m index eff4e93ae..a3a70ecc3 100644 --- a/Signal/src/ViewControllers/ConversationView/ConversationViewController.m +++ b/Signal/src/ViewControllers/ConversationView/ConversationViewController.m @@ -3480,6 +3480,8 @@ typedef NS_ENUM(NSInteger, MessagesRangeSizeMode) { id _Nullable dataSource = [DataSourcePath dataSourceWithURL:compressedVideoUrl]; [dataSource setSourceFilename:filename]; + // Remove temporary file when complete. + [dataSource setShouldDeleteOnDeallocation]; SignalAttachment *attachment = [SignalAttachment attachmentWithDataSource:dataSource dataUTI:(NSString *)kUTTypeMPEG4]; @@ -3523,6 +3525,8 @@ typedef NS_ENUM(NSInteger, MessagesRangeSizeMode) { - (void)yapDatabaseModified:(NSNotification *)notification { + OWSAssert([NSThread isMainThread]); + // Currently, we update thread and message state every time // the database is modified. That doesn't seem optimal, but // in practice it's efficient enough. @@ -3642,6 +3646,8 @@ typedef NS_ENUM(NSInteger, MessagesRangeSizeMode) { } } completion:^(BOOL success) { + OWSAssert([NSThread isMainThread]); + if (!success) { [self resetContentAndLayout]; } @@ -3871,6 +3877,8 @@ typedef NS_ENUM(NSInteger, MessagesRangeSizeMode) { NSString *filename = [NSLocalizedString(@"VOICE_MESSAGE_FILE_NAME", @"Filename for voice messages.") stringByAppendingPathExtension:@"m4a"]; [dataSource setSourceFilename:filename]; + // Remove temporary file when complete. + [dataSource setShouldDeleteOnDeallocation]; SignalAttachment *attachment = [SignalAttachment voiceMessageAttachmentWithDataSource:dataSource dataUTI:(NSString *)kUTTypeMPEG4Audio]; if (!attachment || [attachment hasError]) { diff --git a/SignalServiceKit/src/Util/DataSource.h b/SignalServiceKit/src/Util/DataSource.h index 0d467231f..43d9f69dc 100755 --- a/SignalServiceKit/src/Util/DataSource.h +++ b/SignalServiceKit/src/Util/DataSource.h @@ -40,6 +40,10 @@ NS_ASSUME_NONNULL_BEGIN - (nullable NSString *)sourceFilename; - (void)setSourceFilename:(NSString *_Nullable)sourceFilename; +// If called, this data source will try to delete its on-disk contents +// when it is deallocated. +- (void)setShouldDeleteOnDeallocation; + @end #pragma mark - diff --git a/SignalServiceKit/src/Util/DataSource.m b/SignalServiceKit/src/Util/DataSource.m index 9ae66528a..ba6776ba4 100755 --- a/SignalServiceKit/src/Util/DataSource.m +++ b/SignalServiceKit/src/Util/DataSource.m @@ -18,12 +18,30 @@ NS_ASSUME_NONNULL_BEGIN @property (nonatomic, nullable) NSString *sourceFilename; +@property (nonatomic) BOOL shouldDeleteOnDeallocation; + @end #pragma mark - @implementation DataSourceValue +- (void)dealloc +{ + if (self.shouldDeleteOnDeallocation) { + NSString *filePath = self.cachedFilePath; + if (filePath) { + dispatch_async(dispatch_get_main_queue(), ^{ + NSError *error; + BOOL success = [[NSFileManager defaultManager] removeItemAtPath:filePath error:&error]; + if (!success || error) { + OWSCFail(@"DataSourceValue could not delete file: %@, %@", filePath, error); + } + }); + } + } +} + + (nullable id)dataSourceWithData:(NSData *)data fileExtension:(NSString *)fileExtension { OWSAssert(data); @@ -35,6 +53,8 @@ NS_ASSUME_NONNULL_BEGIN DataSourceValue *instance = [DataSourceValue new]; instance.dataValue = data; instance.fileExtension = fileExtension; + // Always try to clean up temp files created by this instance. + [instance setShouldDeleteOnDeallocation]; return instance; } @@ -89,7 +109,6 @@ NS_ASSUME_NONNULL_BEGIN NSString *dirPath = NSTemporaryDirectory(); NSString *fileName = [[[NSUUID UUID] UUIDString] stringByAppendingPathExtension:self.fileExtension]; NSString *filePath = [dirPath stringByAppendingPathComponent:fileName]; - DDLogError(@"%@ ---- writing data", self.tag); if ([self writeToPath:filePath]) { self.cachedFilePath = filePath; } else { @@ -131,6 +150,11 @@ NS_ASSUME_NONNULL_BEGIN } } +- (void)setShouldDeleteOnDeallocation +{ + self.shouldDeleteOnDeallocation = YES; +} + #pragma mark - Logging + (NSString *)tag @@ -157,12 +181,30 @@ NS_ASSUME_NONNULL_BEGIN @property (nonatomic, nullable) NSString *sourceFilename; +@property (nonatomic) BOOL shouldDeleteOnDeallocation; + @end #pragma mark - @implementation DataSourcePath +- (void)dealloc +{ + if (self.shouldDeleteOnDeallocation) { + NSString *filePath = self.filePath; + if (filePath) { + dispatch_async(dispatch_get_main_queue(), ^{ + NSError *error; + BOOL success = [[NSFileManager defaultManager] removeItemAtPath:filePath error:&error]; + if (!success || error) { + OWSCFail(@"DataSourcePath could not delete file: %@, %@", filePath, error); + } + }); + } + } +} + + (nullable id)dataSourceWithURL:(NSURL *)fileUrl; { OWSAssert(fileUrl); @@ -263,6 +305,11 @@ NS_ASSUME_NONNULL_BEGIN } } +- (void)setShouldDeleteOnDeallocation +{ + self.shouldDeleteOnDeallocation = YES; +} + #pragma mark - Logging + (NSString *)tag