diff --git a/ts/signal.ts b/ts/signal.ts index e1f5890854..857f64ffdb 100644 --- a/ts/signal.ts +++ b/ts/signal.ts @@ -247,6 +247,7 @@ export function initializeMigrations({ getImageDimensions, makeImageThumbnail, makeVideoScreenshot, + deleteOnDisk, logger, }), processNewSticker: (stickerData: Uint8Array) => @@ -282,6 +283,7 @@ export function initializeMigrations({ maxVersion, getAbsoluteStickerPath, writeNewStickerData, + deleteOnDisk, }); }, writeMessageAttachments: MessageType.createAttachmentDataWriter({ diff --git a/ts/test-node/types/Message2_test.ts b/ts/test-node/types/Message2_test.ts index 36d524e1fb..17d740a4dc 100644 --- a/ts/test-node/types/Message2_test.ts +++ b/ts/test-node/types/Message2_test.ts @@ -73,6 +73,7 @@ describe('Message', () => { writeNewAttachmentData: async (_data: Uint8Array) => 'fake-attachment-path', writeNewStickerData: async (_data: Uint8Array) => 'fake-sticker-path', + deleteOnDisk: async (_path: string) => undefined, ...props, }; } diff --git a/ts/types/Message2.ts b/ts/types/Message2.ts index e1e5ffac59..6e8c3987f2 100644 --- a/ts/types/Message2.ts +++ b/ts/types/Message2.ts @@ -72,6 +72,7 @@ export type ContextType = { revokeObjectUrl: (objectUrl: string) => void; writeNewAttachmentData: (data: Uint8Array) => Promise; writeNewStickerData: (data: Uint8Array) => Promise; + deleteOnDisk: (path: string) => Promise; }; type WriteExistingAttachmentDataType = ( @@ -373,7 +374,26 @@ const toVersion0 = async ( ) => initializeSchemaVersion({ message, logger: context.logger }); const toVersion1 = _withSchemaVersion({ schemaVersion: 1, - upgrade: _mapAttachments(autoOrientJPEG), + upgrade: _mapAttachments( + async ( + attachment: AttachmentType, + context, + options + ): Promise => { + const { deleteOnDisk } = context; + const rotatedAttachment = await autoOrientJPEG( + attachment, + context, + options + ); + + if (attachment.path) { + await deleteOnDisk(attachment.path); + } + + return rotatedAttachment; + } + ), }); const toVersion2 = _withSchemaVersion({ schemaVersion: 2, @@ -479,6 +499,7 @@ export const upgradeSchema = async ( makeImageThumbnail, makeVideoScreenshot, writeNewStickerData, + deleteOnDisk, logger, maxVersion = CURRENT_SCHEMA_VERSION, }: ContextType @@ -516,6 +537,9 @@ export const upgradeSchema = async ( if (!isFunction(writeNewStickerData)) { throw new TypeError('context.writeNewStickerData is required'); } + if (!isFunction(deleteOnDisk)) { + throw new TypeError('context.deleteOnDisk is required'); + } let message = rawMessage; for (let index = 0, max = VERSIONS.length; index < max; index += 1) { @@ -539,6 +563,7 @@ export const upgradeSchema = async ( getAbsoluteStickerPath, getRegionCode, writeNewStickerData, + deleteOnDisk, }); } @@ -557,6 +582,7 @@ export const processNewAttachment = async ( getImageDimensions, makeImageThumbnail, makeVideoScreenshot, + deleteOnDisk, logger, }: Pick< ContextType, @@ -568,6 +594,7 @@ export const processNewAttachment = async ( | 'makeImageThumbnail' | 'makeVideoScreenshot' | 'logger' + | 'deleteOnDisk' > ): Promise => { if (!isFunction(writeNewAttachmentData)) { @@ -612,6 +639,10 @@ export const processNewAttachment = async ( writeNewAttachmentData, logger, }); + + if (attachment.path) { + await deleteOnDisk(attachment.path); + } } const finalAttachment = await captureDimensionsAndScreenshot( diff --git a/ts/util/attachments.ts b/ts/util/attachments.ts index 89484d5f97..0775cc8288 100644 --- a/ts/util/attachments.ts +++ b/ts/util/attachments.ts @@ -78,10 +78,14 @@ export async function autoOrientJPEG( // retain it but due to reports of data loss, we don’t want to overburden IndexedDB // by potentially doubling stored image data. // See: https://github.com/signalapp/Signal-Desktop/issues/1589 + // We also clear out the attachment path because we're changing + // the attachment data so it no longer matches the old path. + // Path and data should always be in agreement. const xcodedAttachment = { ...attachment, data: new Uint8Array(xcodedDataArrayBuffer), size: xcodedDataArrayBuffer.byteLength, + path: undefined, }; return xcodedAttachment;