From 4d6d31d6241a68bcf7ec2247eba1c2455e9b8332 Mon Sep 17 00:00:00 2001 From: Greyson Parrelli Date: Thu, 18 May 2023 21:19:04 -0400 Subject: [PATCH] Make attachment count/size remote configurable. --- .../securesms/jobs/AttachmentDownloadJob.java | 13 +++++++++--- .../mediasend/v2/MediaSelectionState.kt | 3 ++- .../messages/SignalServiceProtoUtil.kt | 5 ++--- .../securesms/sharing/v2/ShareRepository.kt | 4 ++-- .../securesms/util/FeatureFlags.java | 20 +++++++++++++++++-- 5 files changed, 34 insertions(+), 11 deletions(-) diff --git a/app/src/main/java/org/thoughtcrime/securesms/jobs/AttachmentDownloadJob.java b/app/src/main/java/org/thoughtcrime/securesms/jobs/AttachmentDownloadJob.java index 6838965e18..b53272f5e8 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/jobs/AttachmentDownloadJob.java +++ b/app/src/main/java/org/thoughtcrime/securesms/jobs/AttachmentDownloadJob.java @@ -30,6 +30,8 @@ import org.thoughtcrime.securesms.s3.S3; import org.thoughtcrime.securesms.transport.RetryLaterException; import org.thoughtcrime.securesms.util.AttachmentUtil; import org.thoughtcrime.securesms.util.Base64; +import org.thoughtcrime.securesms.util.ByteUnit; +import org.thoughtcrime.securesms.util.FeatureFlags; import org.thoughtcrime.securesms.util.Util; import org.whispersystems.signalservice.api.SignalServiceMessageReceiver; import org.whispersystems.signalservice.api.messages.SignalServiceAttachmentPointer; @@ -54,8 +56,10 @@ public final class AttachmentDownloadJob extends BaseJob { public static final String KEY = "AttachmentDownloadJob"; - private static final int MAX_ATTACHMENT_SIZE = 150 * 1024 * 1024; - private static final String TAG = Log.tag(AttachmentDownloadJob.class); + private static final String TAG = Log.tag(AttachmentDownloadJob.class); + + /** A little extra allowed size to account for any adjustments made by other clients */ + private static final int MAX_ATTACHMENT_SIZE_BUFFER = 25 * 1024 * 1024; private static final String KEY_MESSAGE_ID = "message_id"; private static final String KEY_PART_ROW_ID = "part_row_id"; @@ -191,7 +195,10 @@ public final class AttachmentDownloadJob extends BaseJob { try { SignalServiceMessageReceiver messageReceiver = ApplicationDependencies.getSignalServiceMessageReceiver(); SignalServiceAttachmentPointer pointer = createAttachmentPointer(attachment); - InputStream stream = messageReceiver.retrieveAttachment(pointer, attachmentFile, MAX_ATTACHMENT_SIZE, (total, progress) -> EventBus.getDefault().postSticky(new PartProgressEvent(attachment, PartProgressEvent.Type.NETWORK, total, progress))); + InputStream stream = messageReceiver.retrieveAttachment(pointer, + attachmentFile, + ByteUnit.MEGABYTES.toBytes(FeatureFlags.maxAttachmentSizeMb()) + MAX_ATTACHMENT_SIZE_BUFFER, + (total, progress) -> EventBus.getDefault().postSticky(new PartProgressEvent(attachment, PartProgressEvent.Type.NETWORK, total, progress))); database.insertAttachmentsForPlaceholder(messageId, attachmentId, stream); } catch (RangeException e) { diff --git a/app/src/main/java/org/thoughtcrime/securesms/mediasend/v2/MediaSelectionState.kt b/app/src/main/java/org/thoughtcrime/securesms/mediasend/v2/MediaSelectionState.kt index 0e2982748b..65703b5cbc 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/mediasend/v2/MediaSelectionState.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/mediasend/v2/MediaSelectionState.kt @@ -8,6 +8,7 @@ import org.thoughtcrime.securesms.mediasend.MediaSendConstants import org.thoughtcrime.securesms.mms.SentMediaQuality import org.thoughtcrime.securesms.recipients.Recipient import org.thoughtcrime.securesms.stories.Stories +import org.thoughtcrime.securesms.util.FeatureFlags data class MediaSelectionState( val sendType: MessageSendType, @@ -31,7 +32,7 @@ data class MediaSelectionState( val maxSelection = if (sendType.usesSmsTransport) { MediaSendConstants.MAX_SMS } else { - MediaSendConstants.MAX_PUSH + FeatureFlags.maxAttachmentCount() } val canSend = !isSent && selectedMedia.isNotEmpty() diff --git a/app/src/main/java/org/thoughtcrime/securesms/messages/SignalServiceProtoUtil.kt b/app/src/main/java/org/thoughtcrime/securesms/messages/SignalServiceProtoUtil.kt index ccb039ac3d..0113c362a4 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/messages/SignalServiceProtoUtil.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/messages/SignalServiceProtoUtil.kt @@ -10,6 +10,7 @@ import org.thoughtcrime.securesms.attachments.PointerAttachment import org.thoughtcrime.securesms.database.model.StoryType import org.thoughtcrime.securesms.groups.GroupId import org.thoughtcrime.securesms.stickers.StickerLocator +import org.thoughtcrime.securesms.util.FeatureFlags import org.thoughtcrime.securesms.util.MediaUtil import org.whispersystems.signalservice.api.InvalidMessageStructureException import org.whispersystems.signalservice.api.crypto.EnvelopeMetadata @@ -31,8 +32,6 @@ private val ByteString.isNotEmpty: Boolean object SignalServiceProtoUtil { - const val MAX_ALLOWED_ATTACHMENTS = 100 - /** Contains some user data that affects the conversation */ val DataMessage.hasRenderableContent: Boolean get() { @@ -161,7 +160,7 @@ object SignalServiceProtoUtil { } fun List.toPointersWithinLimit(): List { - return mapNotNull { it.toPointer() }.take(MAX_ALLOWED_ATTACHMENTS) + return mapNotNull { it.toPointer() }.take(FeatureFlags.maxAttachmentCount()) } fun AttachmentPointer.toPointer(stickerLocator: StickerLocator? = null): Attachment? { diff --git a/app/src/main/java/org/thoughtcrime/securesms/sharing/v2/ShareRepository.kt b/app/src/main/java/org/thoughtcrime/securesms/sharing/v2/ShareRepository.kt index 1bef440312..3461245a51 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/sharing/v2/ShareRepository.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/sharing/v2/ShareRepository.kt @@ -17,9 +17,9 @@ import org.thoughtcrime.securesms.attachments.UriAttachment import org.thoughtcrime.securesms.conversation.MessageSendType import org.thoughtcrime.securesms.keyvalue.SignalStore import org.thoughtcrime.securesms.mediasend.Media -import org.thoughtcrime.securesms.mediasend.MediaSendConstants import org.thoughtcrime.securesms.mms.MediaConstraints import org.thoughtcrime.securesms.providers.BlobProvider +import org.thoughtcrime.securesms.util.FeatureFlags import org.thoughtcrime.securesms.util.MediaUtil import org.thoughtcrime.securesms.util.UriUtil import org.thoughtcrime.securesms.util.Util @@ -91,7 +91,7 @@ class ShareRepository(context: Context) { } val media: List = mimeTypes.toList() - .take(MediaSendConstants.MAX_PUSH) + .take(FeatureFlags.maxAttachmentCount()) .map { (uri, mimeType) -> val stream: InputStream = try { appContext.contentResolver.openInputStream(uri) diff --git a/app/src/main/java/org/thoughtcrime/securesms/util/FeatureFlags.java b/app/src/main/java/org/thoughtcrime/securesms/util/FeatureFlags.java index ae9467c32d..f48c4533b0 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/util/FeatureFlags.java +++ b/app/src/main/java/org/thoughtcrime/securesms/util/FeatureFlags.java @@ -108,6 +108,8 @@ public final class FeatureFlags { private static final String EDIT_MESSAGE_RECEIVE = "android.editMessage.receive"; private static final String EDIT_MESSAGE_SEND = "android.editMessage.send"; private static final String CALL_DELETE_SYNC = "android.calling.deleteSync"; + private static final String MAX_ATTACHMENT_COUNT = "android.attachments.maxCount"; + private static final String MAX_ATTACHMENT_SIZE_MB = "android.attachments.maxSize"; /** * We will only store remote values for flags in this set. If you want a flag to be controllable @@ -166,7 +168,9 @@ public final class FeatureFlags { TEXT_FORMATTING, ANY_ADDRESS_PORTS_KILL_SWITCH, EDIT_MESSAGE_RECEIVE, - EDIT_MESSAGE_SEND + EDIT_MESSAGE_SEND, + MAX_ATTACHMENT_COUNT, + MAX_ATTACHMENT_SIZE_MB ); @VisibleForTesting @@ -233,7 +237,9 @@ public final class FeatureFlags { CDS_HARD_LIMIT, TEXT_FORMATTING, EDIT_MESSAGE_RECEIVE, - EDIT_MESSAGE_SEND + EDIT_MESSAGE_SEND, + MAX_ATTACHMENT_COUNT, + MAX_ATTACHMENT_SIZE_MB ); /** @@ -609,6 +615,16 @@ public final class FeatureFlags { return getBoolean(CALL_DELETE_SYNC, false); } + /** Maximum number of attachments allowed to be sent/received. */ + public static int maxAttachmentCount() { + return getInteger(MAX_ATTACHMENT_COUNT, 32); + } + + /** Maximum attachment size, in mebibytes. */ + public static int maxAttachmentSizeMb() { + return getInteger(MAX_ATTACHMENT_SIZE_MB, 100); + } + /** Only for rendering debug info. */ public static synchronized @NonNull Map getMemoryValues() { return new TreeMap<>(REMOTE_VALUES);