From 7c9cd8964fb1eb77a200707a5382de7d229d6f35 Mon Sep 17 00:00:00 2001 From: Greyson Parrelli Date: Fri, 21 Mar 2025 15:09:45 -0400 Subject: [PATCH] Update attachment backfill proto. --- .../thoughtcrime/securesms/AppCapabilities.kt | 4 +- .../MultiDeviceAttachmentBackfillUpdateJob.kt | 41 +++++++++++-------- .../messages/SyncMessageProcessor.kt | 6 +-- .../api/account/AccountAttributes.kt | 3 +- .../src/main/protowire/SignalService.proto | 1 + 5 files changed, 32 insertions(+), 23 deletions(-) diff --git a/app/src/main/java/org/thoughtcrime/securesms/AppCapabilities.kt b/app/src/main/java/org/thoughtcrime/securesms/AppCapabilities.kt index 10b044c43b..66b90a83a6 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/AppCapabilities.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/AppCapabilities.kt @@ -1,5 +1,6 @@ package org.thoughtcrime.securesms +import org.thoughtcrime.securesms.util.RemoteConfig import org.whispersystems.signalservice.api.account.AccountAttributes object AppCapabilities { @@ -13,7 +14,8 @@ object AppCapabilities { storage = storageCapable, deleteSync = true, versionedExpirationTimer = true, - storageServiceEncryptionV2 = true + storageServiceEncryptionV2 = true, + attachmentBackfill = RemoteConfig.attachmentBackfillSync ) } } diff --git a/app/src/main/java/org/thoughtcrime/securesms/jobs/MultiDeviceAttachmentBackfillUpdateJob.kt b/app/src/main/java/org/thoughtcrime/securesms/jobs/MultiDeviceAttachmentBackfillUpdateJob.kt index da99583d88..eb50251994 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/jobs/MultiDeviceAttachmentBackfillUpdateJob.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/jobs/MultiDeviceAttachmentBackfillUpdateJob.kt @@ -13,6 +13,7 @@ import org.thoughtcrime.securesms.dependencies.AppDependencies import org.thoughtcrime.securesms.jobmanager.Job import org.thoughtcrime.securesms.jobmanager.impl.NetworkConstraint import org.thoughtcrime.securesms.jobs.protos.MultiDeviceAttachmentBackfillUpdateJobData +import org.thoughtcrime.securesms.util.MediaUtil import org.whispersystems.signalservice.api.crypto.UntrustedIdentityException import org.whispersystems.signalservice.api.messages.multidevice.SignalServiceSyncMessage import org.whispersystems.signalservice.api.push.exceptions.ServerRejectedException @@ -72,33 +73,25 @@ class MultiDeviceAttachmentBackfillUpdateJob( } override fun run(): Result { - val attachments = SignalDatabase.attachments.getAttachmentsForMessage(messageId).filterNot { it.quote }.sortedBy { it.displayOrder } - if (attachments.isEmpty()) { + val allAttachments = SignalDatabase.attachments.getAttachmentsForMessage(messageId) + val syncAttachments: List = allAttachments + .filterNot { it.quote || it.contentType == MediaUtil.LONG_TEXT } + .sortedBy { it.displayOrder } + val longTextAttachment: DatabaseAttachment? = allAttachments.firstOrNull { it.contentType == MediaUtil.LONG_TEXT } + + if (syncAttachments.isEmpty() && longTextAttachment == null) { Log.w(TAG, "Failed to find any attachments for the message! Sending a missing response.") MultiDeviceAttachmentBackfillMissingJob.enqueue(targetMessage, targetConversation) return Result.failure() } - val attachmentDatas = attachments.map { attachment -> - when { - attachment.hasData && !attachment.isInProgress && attachment.withinUploadThreshold() -> { - AttachmentData(attachment = attachment.toAttachmentPointer(context)) - } - !attachment.hasData || attachment.isPermanentlyFailed -> { - AttachmentData(status = AttachmentData.Status.TERMINAL_ERROR) - } - else -> { - AttachmentData(status = AttachmentData.Status.PENDING) - } - } - } - val syncMessage = SignalServiceSyncMessage.forAttachmentBackfillResponse( SyncMessage.AttachmentBackfillResponse( targetMessage = targetMessage, targetConversation = targetConversation, attachments = SyncMessage.AttachmentBackfillResponse.AttachmentDataList( - attachments = attachmentDatas + attachments = syncAttachments.map { it.toAttachmentData() }, + longText = longTextAttachment?.toAttachmentData() ) ) ) @@ -131,6 +124,20 @@ class MultiDeviceAttachmentBackfillUpdateJob( } } + private fun DatabaseAttachment.toAttachmentData(): AttachmentData { + return when { + this.hasData && !this.isInProgress && this.withinUploadThreshold() -> { + AttachmentData(attachment = this.toAttachmentPointer(context)) + } + !this.hasData || this.isPermanentlyFailed -> { + AttachmentData(status = AttachmentData.Status.TERMINAL_ERROR) + } + else -> { + AttachmentData(status = AttachmentData.Status.PENDING) + } + } + } + private fun DatabaseAttachment.withinUploadThreshold(): Boolean { return this.uploadTimestamp > 0 && System.currentTimeMillis() - this.uploadTimestamp < UPLOAD_THRESHOLD } diff --git a/app/src/main/java/org/thoughtcrime/securesms/messages/SyncMessageProcessor.kt b/app/src/main/java/org/thoughtcrime/securesms/messages/SyncMessageProcessor.kt index efd5313bd0..398d9bbd37 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/messages/SyncMessageProcessor.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/messages/SyncMessageProcessor.kt @@ -1711,10 +1711,8 @@ object SyncMessageProcessor { .enqueue() } - if (needsUpload.size != attachments.size) { - log(timestamp, "[AttachmentBackfillRequest] At least one attachment didn't need to be uploaded. Enqueuing update job immediately.") - MultiDeviceAttachmentBackfillUpdateJob.enqueue(request.targetMessage!!, request.targetConversation!!, messageId) - } + // Enqueueing an update immediately to tell the requesting device that the primary is online. + MultiDeviceAttachmentBackfillUpdateJob.enqueue(request.targetMessage!!, request.targetConversation!!, messageId) } private fun ConversationIdentifier.toRecipientId(): RecipientId? { diff --git a/libsignal-service/src/main/java/org/whispersystems/signalservice/api/account/AccountAttributes.kt b/libsignal-service/src/main/java/org/whispersystems/signalservice/api/account/AccountAttributes.kt index 31a2b97cc8..f5ab78febd 100644 --- a/libsignal-service/src/main/java/org/whispersystems/signalservice/api/account/AccountAttributes.kt +++ b/libsignal-service/src/main/java/org/whispersystems/signalservice/api/account/AccountAttributes.kt @@ -57,6 +57,7 @@ class AccountAttributes @JsonCreator constructor( @JsonProperty val storage: Boolean, @JsonProperty val deleteSync: Boolean, @JsonProperty val versionedExpirationTimer: Boolean, - @JsonProperty("ssre2") val storageServiceEncryptionV2: Boolean + @JsonProperty("ssre2") val storageServiceEncryptionV2: Boolean, + @JsonProperty val attachmentBackfill: Boolean ) } diff --git a/libsignal-service/src/main/protowire/SignalService.proto b/libsignal-service/src/main/protowire/SignalService.proto index 7b27a0ba59..a14dacae38 100644 --- a/libsignal-service/src/main/protowire/SignalService.proto +++ b/libsignal-service/src/main/protowire/SignalService.proto @@ -712,6 +712,7 @@ message SyncMessage { message AttachmentDataList { repeated AttachmentData attachments = 1; + optional AttachmentData longText = 2; } optional AddressableMessage targetMessage = 1;