From ec76372e4de0e6f3e7f9e67bb1c3e4d31527006b Mon Sep 17 00:00:00 2001 From: Greyson Parrelli Date: Tue, 28 Oct 2025 16:34:17 -0400 Subject: [PATCH] Fix potential thread conflict in backup import. --- .../thoughtcrime/securesms/backup/v2/ArchiveErrorCases.kt | 8 ++++++++ .../securesms/backup/v2/importer/ChatArchiveImporter.kt | 8 +++++++- .../securesms/backup/v2/processor/ChatArchiveProcessor.kt | 8 +++++++- 3 files changed, 22 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/org/thoughtcrime/securesms/backup/v2/ArchiveErrorCases.kt b/app/src/main/java/org/thoughtcrime/securesms/backup/v2/ArchiveErrorCases.kt index 0fc531b459..c7446693c8 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/backup/v2/ArchiveErrorCases.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/backup/v2/ArchiveErrorCases.kt @@ -235,6 +235,14 @@ object ImportSkips { return log(0, "Failed to parse notificationProfileId for the provided notification profile.") } + fun failedToCreateChat(): String { + return log(0, "Failed to create a Chat. Likely a duplicate recipient was found. Keeping pre-existing data and skipping data in this frame.") + } + + fun missingChatRecipient(chatId: Long): String { + return log(0, "Missing recipient for chat $chatId") + } + private fun log(sentTimestamp: Long, message: String): String { return "[SKIP][$sentTimestamp] $message" } diff --git a/app/src/main/java/org/thoughtcrime/securesms/backup/v2/importer/ChatArchiveImporter.kt b/app/src/main/java/org/thoughtcrime/securesms/backup/v2/importer/ChatArchiveImporter.kt index a420c4f164..28b0642eaf 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/backup/v2/importer/ChatArchiveImporter.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/backup/v2/importer/ChatArchiveImporter.kt @@ -28,7 +28,8 @@ import kotlin.time.Duration.Companion.milliseconds * Handles the importing of [Chat] models into the local database. */ object ChatArchiveImporter { - fun import(chat: Chat, recipientId: RecipientId, importState: ImportState): Long { + + fun import(chat: Chat, recipientId: RecipientId, importState: ImportState): Long? { val chatColor = chat.style?.toLocal(importState) val wallpaperAttachmentId: AttachmentId? = chat.style?.wallpaperPhoto?.let { filePointer -> @@ -49,6 +50,11 @@ object ChatArchiveImporter { ThreadTable.ACTIVE to 1 ) .run() + .takeIf { it > 0L } + + if (threadId == null) { + return null + } SignalDatabase.writableDatabase .update( diff --git a/app/src/main/java/org/thoughtcrime/securesms/backup/v2/processor/ChatArchiveProcessor.kt b/app/src/main/java/org/thoughtcrime/securesms/backup/v2/processor/ChatArchiveProcessor.kt index cb7236c0a1..aa137d1f93 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/backup/v2/processor/ChatArchiveProcessor.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/backup/v2/processor/ChatArchiveProcessor.kt @@ -7,6 +7,7 @@ package org.thoughtcrime.securesms.backup.v2.processor import org.signal.core.util.logging.Log import org.thoughtcrime.securesms.backup.v2.ExportState +import org.thoughtcrime.securesms.backup.v2.ImportSkips import org.thoughtcrime.securesms.backup.v2.ImportState import org.thoughtcrime.securesms.backup.v2.database.getThreadsForBackup import org.thoughtcrime.securesms.backup.v2.importer.ChatArchiveImporter @@ -39,11 +40,16 @@ object ChatArchiveProcessor { fun import(chat: Chat, importState: ImportState) { val recipientId: RecipientId? = importState.remoteToLocalRecipientId[chat.recipientId] if (recipientId == null) { - Log.w(TAG, "Missing recipient for chat ${chat.id}") + Log.w(TAG, ImportSkips.missingChatRecipient(chat.id)) return } val threadId = ChatArchiveImporter.import(chat, recipientId, importState) + if (threadId == null) { + Log.w(TAG, ImportSkips.failedToCreateChat()) + return + } + importState.chatIdToLocalRecipientId[chat.id] = recipientId importState.chatIdToLocalThreadId[chat.id] = threadId importState.chatIdToBackupRecipientId[chat.id] = chat.recipientId