diff --git a/ts/jobs/AttachmentDownloadManager.ts b/ts/jobs/AttachmentDownloadManager.ts index 2b7c002642..dcaebc9a4f 100644 --- a/ts/jobs/AttachmentDownloadManager.ts +++ b/ts/jobs/AttachmentDownloadManager.ts @@ -1,6 +1,6 @@ // Copyright 2024 Signal Messenger, LLC // SPDX-License-Identifier: AGPL-3.0-only -import { debounce, noop, omit } from 'lodash'; +import { noop, omit, throttle } from 'lodash'; import * as durations from '../util/durations'; import * as log from '../logging/log'; @@ -46,7 +46,10 @@ import { import type { MIMEType } from '../types/MIME'; import { AttachmentDownloadSource } from '../sql/Interface'; import { drop } from '../util/drop'; -import { getAttachmentCiphertextLength } from '../AttachmentCrypto'; +import { + getAttachmentCiphertextLength, + type ReencryptedAttachmentV2, +} from '../AttachmentCrypto'; import { safeParsePartial } from '../util/schemas'; import { createBatcher } from '../util/batcher'; @@ -522,11 +525,15 @@ export async function runDownloadAttachmentJobInner({ try { let totalDownloaded = 0; + let downloadedAttachment: ReencryptedAttachmentV2 | undefined; const onSizeUpdate = async (totalBytes: number) => { if (abortSignal.aborted) { return; } + if (downloadedAttachment) { + return; + } totalDownloaded = Math.min(totalBytes, attachment.size); await addAttachmentToMessage( @@ -537,18 +544,18 @@ export async function runDownloadAttachmentJobInner({ ); }; - const downloaded = await dependencies.downloadAttachment({ + downloadedAttachment = await dependencies.downloadAttachment({ attachment, options: { variant: AttachmentVariant.Default, - onSizeUpdate: debounce(onSizeUpdate, 200), + onSizeUpdate: throttle(onSizeUpdate, 200), abortSignal, }, }); const upgradedAttachment = await dependencies.processNewAttachment({ ...omit(attachment, ['error', 'pending', 'downloadPath']), - ...downloaded, + ...downloadedAttachment, }); await addAttachmentToMessage(messageId, upgradedAttachment, logId, { diff --git a/ts/messageModifiers/AttachmentDownloads.ts b/ts/messageModifiers/AttachmentDownloads.ts index 548da44dad..7ab071fc87 100644 --- a/ts/messageModifiers/AttachmentDownloads.ts +++ b/ts/messageModifiers/AttachmentDownloads.ts @@ -5,7 +5,7 @@ import * as Bytes from '../Bytes'; import type { AttachmentDownloadJobTypeType } from '../types/AttachmentDownload'; import type { AttachmentType } from '../types/Attachment'; -import { getAttachmentSignature, isDownloaded } from '../types/Attachment'; +import { getAttachmentSignatureSafe, isDownloaded } from '../types/Attachment'; import { __DEPRECATED$getMessageById } from '../messages/getMessageById'; export async function addAttachmentToMessage( @@ -21,7 +21,10 @@ export async function addAttachmentToMessage( return; } - const attachmentSignature = getAttachmentSignature(attachment); + const attachmentSignature = getAttachmentSignatureSafe(attachment); + if (!attachmentSignature) { + log.error(`${logPrefix}: Attachment did not have valid signature (digest)`); + } if (type === 'long-message') { let handledAnywhere = false; @@ -45,7 +48,8 @@ export async function addAttachmentToMessage( } // This attachment isn't destined for this edit if ( - getAttachmentSignature(edit.bodyAttachment) !== attachmentSignature + getAttachmentSignatureSafe(edit.bodyAttachment) !== + attachmentSignature ) { return edit; } @@ -79,7 +83,8 @@ export async function addAttachmentToMessage( return; } if ( - getAttachmentSignature(existingBodyAttachment) !== attachmentSignature + getAttachmentSignatureSafe(existingBodyAttachment) !== + attachmentSignature ) { return; } @@ -116,7 +121,7 @@ export async function addAttachmentToMessage( return existing; } - if (attachmentSignature !== getAttachmentSignature(existing)) { + if (attachmentSignature !== getAttachmentSignatureSafe(existing)) { return existing; } @@ -322,7 +327,7 @@ export async function addAttachmentToMessage( message.set({ sticker: { ...sticker, - data: attachment, + data: sticker.data ? maybeReplaceAttachment(sticker.data) : attachment, }, }); return; diff --git a/ts/types/Attachment.ts b/ts/types/Attachment.ts index 9188aa5b5a..a0fa58a32e 100644 --- a/ts/types/Attachment.ts +++ b/ts/types/Attachment.ts @@ -1105,6 +1105,16 @@ export function getAttachmentSignature(attachment: AttachmentType): string { return attachment.digest; } +export function getAttachmentSignatureSafe( + attachment: AttachmentType +): string | undefined { + try { + return getAttachmentSignature(attachment); + } catch { + return undefined; + } +} + type RequiredPropertiesForDecryption = 'key' | 'digest'; type RequiredPropertiesForReencryption = 'path' | 'key' | 'digest' | 'iv'; diff --git a/ts/util/queueAttachmentDownloads.ts b/ts/util/queueAttachmentDownloads.ts index 43c7604b6a..3ecefec84a 100644 --- a/ts/util/queueAttachmentDownloads.ts +++ b/ts/util/queueAttachmentDownloads.ts @@ -21,7 +21,7 @@ import type { } from '../model-types.d'; import * as Errors from '../types/errors'; import { - getAttachmentSignature, + getAttachmentSignatureSafe, isDownloading, isDownloaded, } from '../types/Attachment'; @@ -44,16 +44,6 @@ export type MessageAttachmentsDownloadedType = { sticker?: StickerType; }; -function getAttachmentSignatureSafe( - attachment: AttachmentType -): string | undefined { - try { - return getAttachmentSignature(attachment); - } catch { - return undefined; - } -} - function getLogger(source: AttachmentDownloadSource) { const verbose = source !== AttachmentDownloadSource.BACKUP_IMPORT; const log = verbose ? logger : { ...logger, info: () => null };