From d218e00bd3fd76ad69c216e4800d56cb81e0fbf4 Mon Sep 17 00:00:00 2001 From: Audric Ackermann Date: Thu, 5 Nov 2020 11:02:45 +1100 Subject: [PATCH] scale down avatars before upload to 512x512 --- js/background.js | 22 ++++++++++++++++++++-- ts/util/attachmentsUtil.ts | 21 ++++++++++++++------- 2 files changed, 34 insertions(+), 9 deletions(-) diff --git a/js/background.js b/js/background.js index 0790b5eb6..46aeea580 100644 --- a/js/background.js +++ b/js/background.js @@ -722,6 +722,24 @@ let profileKey = null; if (avatar) { const data = await readFile({ file: avatar }); + // Ensure that this file is either small enough or is resized to meet our + // requirements for attachments + const withBlob = await window.Signal.Util.AttachmentUtil.autoScale( + { + contentType: avatar.type, + file: new Blob([data.data], { + type: avatar.contentType, + }), + maxMeasurements: { + maxSize: 1000 * 1024, + maxHeight: 512, + maxWidth: 512, + }, + } + ); + const dataResized = await window.Signal.Types.Attachment.arrayBufferFromFile( + withBlob.file + ); // For simplicity we use the same attachment pointer that would send to // others, which means we need to wait for the database response. @@ -734,13 +752,13 @@ // Encrypt with a new key every time profileKey = libsignal.crypto.getRandomBytes(32); const encryptedData = await textsecure.crypto.encryptProfile( - data.data, + dataResized, profileKey ); const avatarPointer = await libsession.Utils.AttachmentUtils.uploadAvatar( { - ...data, + ...dataResized, data: encryptedData, size: encryptedData.byteLength, } diff --git a/ts/util/attachmentsUtil.ts b/ts/util/attachmentsUtil.ts index f8531f7b8..58b861176 100644 --- a/ts/util/attachmentsUtil.ts +++ b/ts/util/attachmentsUtil.ts @@ -1,10 +1,16 @@ import { StagedAttachmentType } from '../components/session/conversation/SessionCompositionBox'; import { SignalService } from '../protobuf'; -export async function autoScale( - attachment: T -): Promise { - const { contentType, file } = attachment; +export interface MaxScaleSize { + maxSize: number; + maxHeight: number; + maxWidth: number; +} + +export async function autoScale< + T extends { contentType: string; file: any; maxMeasurements?: MaxScaleSize } +>(attachment: T): Promise { + const { contentType, file, maxMeasurements } = attachment; if (contentType.split('/')[0] !== 'image' || contentType === 'image/tiff') { // nothing to do return Promise.resolve(attachment); @@ -17,9 +23,10 @@ export async function autoScale( img.onload = () => { URL.revokeObjectURL(url); - const maxSize = 6000 * 1024; - const maxHeight = 4096; - const maxWidth = 4096; + const maxSize = maxMeasurements?.maxSize || 6000 * 1024; + const maxHeight = maxMeasurements?.maxHeight || 4096; + const maxWidth = maxMeasurements?.maxWidth || 4096; + if ( img.naturalWidth <= maxWidth && img.naturalHeight <= maxHeight &&