From 6b3f41d67570529ca96fcc920eb5370e4d63e51b Mon Sep 17 00:00:00 2001 From: Greyson Parrelli Date: Wed, 25 Oct 2023 09:52:10 -0700 Subject: [PATCH] Merge IncomingTextMessages into IncomingMessage. --- .../conversation/ConversationItemPreviewer.kt | 6 +- .../securesms/database/MmsHelper.kt | 4 +- .../database/MmsTableTest_stories.kt | 16 +- .../RecipientTableTest_getAndPossiblyMerge.kt | 28 +- ...est_collapseJoinRequestEventsIfPossible.kt | 26 +- .../securesms/util/MessageTableTestUtils.kt | 2 - .../contacts/sync/ContactDiscovery.kt | 4 +- .../securesms/database/MessageTable.kt | 274 ++++------------ .../securesms/database/MessageType.kt | 49 +++ .../securesms/database/MessageTypes.java | 12 +- .../v2/processing/GroupsV2StateProcessor.java | 26 +- .../messages/DataMessageProcessor.kt | 101 +++--- .../messages/EditMessageProcessor.kt | 32 +- .../messages/MessageContentProcessor.kt | 30 +- .../messages/StoryMessageProcessor.kt | 4 +- .../securesms/mms/IncomingMediaMessage.kt | 145 --------- .../securesms/mms/IncomingMessage.kt | 114 +++++++ .../releasechannel/ReleaseChannel.kt | 4 +- .../sms/IncomingEncryptedMessage.java | 13 - .../sms/IncomingEndSessionMessage.java | 17 - .../sms/IncomingGroupUpdateMessage.java | 55 ---- .../sms/IncomingIdentityDefaultMessage.java | 15 - .../sms/IncomingIdentityUpdateMessage.java | 14 - .../sms/IncomingIdentityVerifiedMessage.java | 15 - .../securesms/sms/IncomingJoinedMessage.java | 24 -- .../securesms/sms/IncomingTextMessage.java | 294 ------------------ .../securesms/util/IdentityUtil.java | 49 +-- .../MessageBitmaskColumnTransformer.kt | 4 - .../securesms/database/TestSms.kt | 39 ++- 29 files changed, 410 insertions(+), 1006 deletions(-) create mode 100644 app/src/main/java/org/thoughtcrime/securesms/database/MessageType.kt delete mode 100644 app/src/main/java/org/thoughtcrime/securesms/mms/IncomingMediaMessage.kt create mode 100644 app/src/main/java/org/thoughtcrime/securesms/mms/IncomingMessage.kt delete mode 100644 app/src/main/java/org/thoughtcrime/securesms/sms/IncomingEncryptedMessage.java delete mode 100644 app/src/main/java/org/thoughtcrime/securesms/sms/IncomingEndSessionMessage.java delete mode 100644 app/src/main/java/org/thoughtcrime/securesms/sms/IncomingGroupUpdateMessage.java delete mode 100644 app/src/main/java/org/thoughtcrime/securesms/sms/IncomingIdentityDefaultMessage.java delete mode 100644 app/src/main/java/org/thoughtcrime/securesms/sms/IncomingIdentityUpdateMessage.java delete mode 100644 app/src/main/java/org/thoughtcrime/securesms/sms/IncomingIdentityVerifiedMessage.java delete mode 100644 app/src/main/java/org/thoughtcrime/securesms/sms/IncomingJoinedMessage.java delete mode 100644 app/src/main/java/org/thoughtcrime/securesms/sms/IncomingTextMessage.java diff --git a/app/src/androidTest/java/org/thoughtcrime/securesms/conversation/ConversationItemPreviewer.kt b/app/src/androidTest/java/org/thoughtcrime/securesms/conversation/ConversationItemPreviewer.kt index a33f1fe14a..6343515836 100644 --- a/app/src/androidTest/java/org/thoughtcrime/securesms/conversation/ConversationItemPreviewer.kt +++ b/app/src/androidTest/java/org/thoughtcrime/securesms/conversation/ConversationItemPreviewer.kt @@ -10,7 +10,7 @@ import org.signal.core.util.ThreadUtil import org.thoughtcrime.securesms.attachments.PointerAttachment import org.thoughtcrime.securesms.conversation.v2.ConversationActivity import org.thoughtcrime.securesms.database.SignalDatabase -import org.thoughtcrime.securesms.mms.IncomingMediaMessage +import org.thoughtcrime.securesms.mms.IncomingMessage import org.thoughtcrime.securesms.mms.OutgoingMessage import org.thoughtcrime.securesms.profiles.ProfileName import org.thoughtcrime.securesms.recipients.Recipient @@ -64,7 +64,7 @@ class ConversationItemPreviewer { attachment() } - val message = IncomingMediaMessage( + val message = IncomingMessage( from = other.id, body = body, sentTimeMillis = System.currentTimeMillis(), @@ -83,7 +83,7 @@ class ConversationItemPreviewer { attachment() } - val message = IncomingMediaMessage( + val message = IncomingMessage( from = other.id, body = body, sentTimeMillis = System.currentTimeMillis(), diff --git a/app/src/androidTest/java/org/thoughtcrime/securesms/database/MmsHelper.kt b/app/src/androidTest/java/org/thoughtcrime/securesms/database/MmsHelper.kt index c9112586d4..06990810e5 100644 --- a/app/src/androidTest/java/org/thoughtcrime/securesms/database/MmsHelper.kt +++ b/app/src/androidTest/java/org/thoughtcrime/securesms/database/MmsHelper.kt @@ -3,7 +3,7 @@ package org.thoughtcrime.securesms.database import org.thoughtcrime.securesms.database.model.ParentStoryId import org.thoughtcrime.securesms.database.model.StoryType import org.thoughtcrime.securesms.database.model.databaseprotos.GiftBadge -import org.thoughtcrime.securesms.mms.IncomingMediaMessage +import org.thoughtcrime.securesms.mms.IncomingMessage import org.thoughtcrime.securesms.mms.OutgoingMessage import org.thoughtcrime.securesms.recipients.Recipient import java.util.Optional @@ -55,7 +55,7 @@ object MmsHelper { } fun insert( - message: IncomingMediaMessage, + message: IncomingMessage, threadId: Long ): Optional { return SignalDatabase.messages.insertMessageInbox(message, threadId) diff --git a/app/src/androidTest/java/org/thoughtcrime/securesms/database/MmsTableTest_stories.kt b/app/src/androidTest/java/org/thoughtcrime/securesms/database/MmsTableTest_stories.kt index 4c863af0e2..6209ef891a 100644 --- a/app/src/androidTest/java/org/thoughtcrime/securesms/database/MmsTableTest_stories.kt +++ b/app/src/androidTest/java/org/thoughtcrime/securesms/database/MmsTableTest_stories.kt @@ -13,7 +13,7 @@ import org.thoughtcrime.securesms.database.model.DistributionListId import org.thoughtcrime.securesms.database.model.ParentStoryId import org.thoughtcrime.securesms.database.model.StoryType import org.thoughtcrime.securesms.keyvalue.SignalStore -import org.thoughtcrime.securesms.mms.IncomingMediaMessage +import org.thoughtcrime.securesms.mms.IncomingMessage import org.thoughtcrime.securesms.recipients.Recipient import org.thoughtcrime.securesms.recipients.RecipientId import org.whispersystems.signalservice.api.push.ServiceId.ACI @@ -73,7 +73,7 @@ class MmsTableTest_stories { ) MmsHelper.insert( - IncomingMediaMessage( + IncomingMessage( from = sender, sentTimeMillis = 2, serverTimeMillis = 2, @@ -95,7 +95,7 @@ class MmsTableTest_stories { // GIVEN val sender = recipients[0] val messageId = MmsHelper.insert( - IncomingMediaMessage( + IncomingMessage( from = sender, sentTimeMillis = 2, serverTimeMillis = 2, @@ -122,7 +122,7 @@ class MmsTableTest_stories { // GIVEN val messageIds = recipients.take(5).map { MmsHelper.insert( - IncomingMediaMessage( + IncomingMessage( from = it, sentTimeMillis = 2, serverTimeMillis = 2, @@ -154,7 +154,7 @@ class MmsTableTest_stories { val unviewedIds: List = (0 until 5).map { Thread.sleep(5) MmsHelper.insert( - IncomingMediaMessage( + IncomingMessage( from = recipients[it], sentTimeMillis = System.currentTimeMillis(), serverTimeMillis = 2, @@ -168,7 +168,7 @@ class MmsTableTest_stories { val viewedIds: List = (0 until 5).map { Thread.sleep(5) MmsHelper.insert( - IncomingMediaMessage( + IncomingMessage( from = recipients[it], sentTimeMillis = System.currentTimeMillis(), serverTimeMillis = 2, @@ -213,7 +213,7 @@ class MmsTableTest_stories { fun givenNoOutgoingStories_whenICheckIsOutgoingStoryAlreadyInDatabase_thenIExpectFalse() { // GIVEN MmsHelper.insert( - IncomingMediaMessage( + IncomingMessage( from = recipients[0], sentTimeMillis = 200, serverTimeMillis = 2, @@ -321,7 +321,7 @@ class MmsTableTest_stories { ) MmsHelper.insert( - IncomingMediaMessage( + IncomingMessage( from = myStory.id, sentTimeMillis = 201, serverTimeMillis = 201, diff --git a/app/src/androidTest/java/org/thoughtcrime/securesms/database/RecipientTableTest_getAndPossiblyMerge.kt b/app/src/androidTest/java/org/thoughtcrime/securesms/database/RecipientTableTest_getAndPossiblyMerge.kt index a3e95c7fec..fef38a95e5 100644 --- a/app/src/androidTest/java/org/thoughtcrime/securesms/database/RecipientTableTest_getAndPossiblyMerge.kt +++ b/app/src/androidTest/java/org/thoughtcrime/securesms/database/RecipientTableTest_getAndPossiblyMerge.kt @@ -17,6 +17,7 @@ import org.junit.runner.RunWith import org.signal.core.util.Base64 import org.signal.core.util.SqlUtil import org.signal.core.util.exists +import org.signal.core.util.orNull import org.signal.core.util.requireLong import org.signal.core.util.requireNonNullString import org.signal.core.util.select @@ -35,11 +36,10 @@ import org.thoughtcrime.securesms.database.model.databaseprotos.ThreadMergeEvent import org.thoughtcrime.securesms.dependencies.ApplicationDependencies import org.thoughtcrime.securesms.groups.GroupId import org.thoughtcrime.securesms.keyvalue.SignalStore -import org.thoughtcrime.securesms.mms.IncomingMediaMessage +import org.thoughtcrime.securesms.mms.IncomingMessage import org.thoughtcrime.securesms.notifications.profiles.NotificationProfile import org.thoughtcrime.securesms.recipients.Recipient import org.thoughtcrime.securesms.recipients.RecipientId -import org.thoughtcrime.securesms.sms.IncomingTextMessage import org.thoughtcrime.securesms.util.FeatureFlags import org.thoughtcrime.securesms.util.FeatureFlagsAccessor import org.thoughtcrime.securesms.util.Util @@ -947,12 +947,28 @@ class RecipientTableTest_getAndPossiblyMerge { MatcherAssert.assertThat("Distribution list should have updated $recipientIdE164 to $recipientIdAci", updatedList.members, Matchers.containsInAnyOrder(recipientIdAci, recipientIdAciB)) } - private fun smsMessage(sender: RecipientId, time: Long = 0, body: String = "", groupId: Optional = Optional.empty()): IncomingTextMessage { - return IncomingTextMessage(sender, 1, time, time, time, body, groupId, 0, true, null) + private fun smsMessage(sender: RecipientId, time: Long = 0, body: String = "", groupId: Optional = Optional.empty()): IncomingMessage { + return IncomingMessage( + from = sender, + sentTimeMillis = time, + serverTimeMillis = time, + receivedTimeMillis = time, + body = body, + groupId = groupId.orNull(), + isUnidentified = true + ) } - private fun mmsMessage(sender: RecipientId, time: Long = 0, body: String = "", groupId: Optional = Optional.empty()): IncomingMediaMessage { - return IncomingMediaMessage(sender, groupId, body, time, time, time, emptyList(), 0, 0, false, false, true, Optional.empty(), false, false) + private fun mmsMessage(sender: RecipientId, time: Long = 0, body: String = "", groupId: Optional = Optional.empty()): IncomingMessage { + return IncomingMessage( + from = sender, + groupId = groupId.orNull(), + body = body, + sentTimeMillis = time, + receivedTimeMillis = time, + serverTimeMillis = time, + isUnidentified = true + ) } private fun identityKey(value: Byte): IdentityKey { diff --git a/app/src/androidTest/java/org/thoughtcrime/securesms/database/SmsDatabaseTest_collapseJoinRequestEventsIfPossible.kt b/app/src/androidTest/java/org/thoughtcrime/securesms/database/SmsDatabaseTest_collapseJoinRequestEventsIfPossible.kt index d1e1080799..14da9e5314 100644 --- a/app/src/androidTest/java/org/thoughtcrime/securesms/database/SmsDatabaseTest_collapseJoinRequestEventsIfPossible.kt +++ b/app/src/androidTest/java/org/thoughtcrime/securesms/database/SmsDatabaseTest_collapseJoinRequestEventsIfPossible.kt @@ -18,12 +18,10 @@ import org.thoughtcrime.securesms.database.model.databaseprotos.groupChange import org.thoughtcrime.securesms.database.model.databaseprotos.groupContext import org.thoughtcrime.securesms.groups.GroupId import org.thoughtcrime.securesms.keyvalue.SignalStore +import org.thoughtcrime.securesms.mms.IncomingMessage import org.thoughtcrime.securesms.recipients.RecipientId -import org.thoughtcrime.securesms.sms.IncomingGroupUpdateMessage -import org.thoughtcrime.securesms.sms.IncomingTextMessage import org.whispersystems.signalservice.api.push.ServiceId.ACI import org.whispersystems.signalservice.api.push.ServiceId.PNI -import java.util.Optional import java.util.UUID @Suppress("ClassName", "TestFunctionName") @@ -272,13 +270,27 @@ class SmsDatabaseTest_collapseJoinRequestEventsIfPossible { assertThat("latest message should be deleted", sms.getMessageRecordOrNull(latestMessage.messageId), nullValue()) } - private fun smsMessage(sender: RecipientId, body: String? = ""): IncomingTextMessage { + private fun smsMessage(sender: RecipientId, body: String? = ""): IncomingMessage { wallClock++ - return IncomingTextMessage(sender, 1, wallClock, wallClock, wallClock, body, Optional.of(groupId), 0, true, null) + return IncomingMessage( + from = sender, + sentTimeMillis = wallClock, + serverTimeMillis = wallClock, + receivedTimeMillis = wallClock, + body = body, + groupId = groupId, + isUnidentified = true + ) } - private fun groupUpdateMessage(sender: RecipientId, groupContext: DecryptedGroupV2Context): IncomingGroupUpdateMessage { - return IncomingGroupUpdateMessage(smsMessage(sender, null), groupContext) + private fun groupUpdateMessage(sender: RecipientId, groupContext: DecryptedGroupV2Context): IncomingMessage { + wallClock++ + return IncomingMessage.groupUpdate( + from = sender, + timestamp = wallClock, + groupId = groupId, + groupContext = groupContext + ) } companion object { diff --git a/app/src/androidTest/java/org/thoughtcrime/securesms/util/MessageTableTestUtils.kt b/app/src/androidTest/java/org/thoughtcrime/securesms/util/MessageTableTestUtils.kt index 70dba1df2d..53c7afa7e6 100644 --- a/app/src/androidTest/java/org/thoughtcrime/securesms/util/MessageTableTestUtils.kt +++ b/app/src/androidTest/java/org/thoughtcrime/securesms/util/MessageTableTestUtils.kt @@ -38,10 +38,8 @@ object MessageTableTestUtils { isKeyExchangeType:${type and MessageTypes.KEY_EXCHANGE_BIT != 0L} isIdentityVerified:${type and MessageTypes.KEY_EXCHANGE_IDENTITY_VERIFIED_BIT != 0L} isIdentityDefault:${type and MessageTypes.KEY_EXCHANGE_IDENTITY_DEFAULT_BIT != 0L} - isCorruptedKeyExchange:${type and MessageTypes.KEY_EXCHANGE_CORRUPTED_BIT != 0L} isInvalidVersionKeyExchange:${type and MessageTypes.KEY_EXCHANGE_INVALID_VERSION_BIT != 0L} isBundleKeyExchange:${type and MessageTypes.KEY_EXCHANGE_BUNDLE_BIT != 0L} - isContentBundleKeyExchange:${type and MessageTypes.KEY_EXCHANGE_CONTENT_FORMAT != 0L} isIdentityUpdate:${type and MessageTypes.KEY_EXCHANGE_IDENTITY_UPDATE_BIT != 0L} isRateLimited:${type and MessageTypes.MESSAGE_RATE_LIMITED_BIT != 0L} isExpirationTimerUpdate:${type and MessageTypes.EXPIRATION_TIMER_UPDATE_BIT != 0L} diff --git a/app/src/main/java/org/thoughtcrime/securesms/contacts/sync/ContactDiscovery.kt b/app/src/main/java/org/thoughtcrime/securesms/contacts/sync/ContactDiscovery.kt index dc4c240822..117a40179b 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/contacts/sync/ContactDiscovery.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/contacts/sync/ContactDiscovery.kt @@ -15,6 +15,7 @@ import org.thoughtcrime.securesms.database.SignalDatabase import org.thoughtcrime.securesms.dependencies.ApplicationDependencies import org.thoughtcrime.securesms.jobs.SyncSystemContactLinksJob import org.thoughtcrime.securesms.keyvalue.SignalStore +import org.thoughtcrime.securesms.mms.IncomingMessage import org.thoughtcrime.securesms.notifications.NotificationChannels import org.thoughtcrime.securesms.notifications.v2.ConversationId import org.thoughtcrime.securesms.permissions.Permissions @@ -23,7 +24,6 @@ import org.thoughtcrime.securesms.profiles.ProfileName import org.thoughtcrime.securesms.recipients.Recipient import org.thoughtcrime.securesms.recipients.RecipientId import org.thoughtcrime.securesms.registration.RegistrationUtil -import org.thoughtcrime.securesms.sms.IncomingJoinedMessage import org.thoughtcrime.securesms.storage.StorageSyncHelper import org.thoughtcrime.securesms.util.FeatureFlags import org.thoughtcrime.securesms.util.TextSecurePreferences @@ -197,7 +197,7 @@ object ContactDiscovery { Recipient.resolvedList(newUserIds) .filter { !it.isSelf && it.hasAUserSetDisplayName(context) && !hasSession(it.id) } - .map { IncomingJoinedMessage(it.id) } + .map { IncomingMessage.contactJoined(it.id, System.currentTimeMillis()) } .map { SignalDatabase.messages.insertMessageInbox(it) } .filter { it.isPresent } .map { it.get() } diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/MessageTable.kt b/app/src/main/java/org/thoughtcrime/securesms/database/MessageTable.kt index 97e4052049..7449119a6a 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/MessageTable.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/database/MessageTable.kt @@ -56,6 +56,7 @@ import org.signal.core.util.requireLongOrNull import org.signal.core.util.requireNonNullString import org.signal.core.util.requireString import org.signal.core.util.select +import org.signal.core.util.toInt import org.signal.core.util.toOptional import org.signal.core.util.toSingleLine import org.signal.core.util.update @@ -118,7 +119,7 @@ import org.thoughtcrime.securesms.jobs.ThreadUpdateJob import org.thoughtcrime.securesms.jobs.TrimThreadJob import org.thoughtcrime.securesms.keyvalue.SignalStore import org.thoughtcrime.securesms.linkpreview.LinkPreview -import org.thoughtcrime.securesms.mms.IncomingMediaMessage +import org.thoughtcrime.securesms.mms.IncomingMessage import org.thoughtcrime.securesms.mms.MessageGroupContext import org.thoughtcrime.securesms.mms.MmsException import org.thoughtcrime.securesms.mms.OutgoingMessage @@ -129,8 +130,7 @@ import org.thoughtcrime.securesms.recipients.Recipient import org.thoughtcrime.securesms.recipients.RecipientId import org.thoughtcrime.securesms.revealable.ViewOnceExpirationInfo import org.thoughtcrime.securesms.revealable.ViewOnceUtil -import org.thoughtcrime.securesms.sms.IncomingGroupUpdateMessage -import org.thoughtcrime.securesms.sms.IncomingTextMessage +import org.thoughtcrime.securesms.sms.GroupV2UpdateMessageUtil import org.thoughtcrime.securesms.stories.Stories.isFeatureEnabled import org.thoughtcrime.securesms.util.FeatureFlags import org.thoughtcrime.securesms.util.JsonUtils @@ -591,22 +591,10 @@ open class MessageTable(context: Context?, databaseHelper: SignalDatabase) : Dat .run() } - fun markAsEndSession(id: Long) { - updateTypeBitmask(id, MessageTypes.KEY_EXCHANGE_MASK, MessageTypes.END_SESSION_BIT) - } - fun markAsInvalidVersionKeyExchange(id: Long) { updateTypeBitmask(id, 0, MessageTypes.KEY_EXCHANGE_INVALID_VERSION_BIT) } - fun markAsDecryptFailed(id: Long) { - updateTypeBitmask(id, MessageTypes.ENCRYPTION_MASK, MessageTypes.ENCRYPTION_REMOTE_FAILED_BIT) - } - - fun markAsNoSession(id: Long) { - updateTypeBitmask(id, MessageTypes.ENCRYPTION_MASK, MessageTypes.ENCRYPTION_REMOTE_NO_SESSION_BIT) - } - fun markAsUnsupportedProtocolVersion(id: Long) { updateTypeBitmask(id, MessageTypes.BASE_TYPE_MASK, MessageTypes.UNSUPPORTED_MESSAGE_TYPE) } @@ -619,10 +607,6 @@ open class MessageTable(context: Context?, databaseHelper: SignalDatabase) : Dat updateTypeBitmask(id, MessageTypes.ENCRYPTION_MASK, MessageTypes.ENCRYPTION_REMOTE_LEGACY_BIT) } - fun markAsMissedCall(id: Long, isVideoOffer: Boolean) { - updateTypeBitmask(id, MessageTypes.TOTAL_MASK, if (isVideoOffer) MessageTypes.MISSED_VIDEO_CALL_TYPE else MessageTypes.MISSED_AUDIO_CALL_TYPE) - } - fun markSmsStatus(id: Long, status: Int) { Log.i(TAG, "Updating ID: $id to status: $status") @@ -982,132 +966,8 @@ open class MessageTable(context: Context?, databaseHelper: SignalDatabase) : Dat } } - @JvmOverloads - fun insertMessageInbox(message: IncomingTextMessage, editedMessage: MediaMmsMessageRecord? = null, notifyObservers: Boolean = true): Optional { - var type = MessageTypes.BASE_INBOX_TYPE - var tryToCollapseJoinRequestEvents = false - - if (message.isJoined) { - type = type and MessageTypes.TOTAL_MASK - MessageTypes.BASE_TYPE_MASK or MessageTypes.JOINED_TYPE - } else if (message.isPreKeyBundle) { - type = type or (MessageTypes.KEY_EXCHANGE_BIT or MessageTypes.KEY_EXCHANGE_BUNDLE_BIT) - } else if (message.isSecureMessage) { - type = type or MessageTypes.SECURE_MESSAGE_BIT - } else if (message.isGroup) { - val incomingGroupUpdateMessage = message as IncomingGroupUpdateMessage - type = type or MessageTypes.SECURE_MESSAGE_BIT - if (incomingGroupUpdateMessage.isGroupV2) { - type = type or (MessageTypes.GROUP_V2_BIT or MessageTypes.GROUP_UPDATE_BIT) - if (incomingGroupUpdateMessage.isJustAGroupLeave) { - type = type or MessageTypes.GROUP_LEAVE_BIT - } else if (incomingGroupUpdateMessage.isCancelJoinRequest) { - tryToCollapseJoinRequestEvents = true - } - } else if (incomingGroupUpdateMessage.isUpdate) { - type = type or MessageTypes.GROUP_UPDATE_BIT - } else if (incomingGroupUpdateMessage.isQuit) { - type = type or MessageTypes.GROUP_LEAVE_BIT - } - } else if (message.isEndSession) { - type = type or MessageTypes.SECURE_MESSAGE_BIT - type = type or MessageTypes.END_SESSION_BIT - } - - if (message.isPush) { - type = type or MessageTypes.PUSH_MESSAGE_BIT - } - - if (message.isIdentityUpdate) { - type = type or MessageTypes.KEY_EXCHANGE_IDENTITY_UPDATE_BIT - } - - if (message.isContentPreKeyBundle) { - type = type or MessageTypes.KEY_EXCHANGE_CONTENT_FORMAT - } - - if (message.isIdentityVerified) { - type = type or MessageTypes.KEY_EXCHANGE_IDENTITY_VERIFIED_BIT - } else if (message.isIdentityDefault) { - type = type or MessageTypes.KEY_EXCHANGE_IDENTITY_DEFAULT_BIT - } - - val silent = message.isIdentityUpdate || - message.isIdentityVerified || - message.isIdentityDefault || - message.isJustAGroupLeave || type and MessageTypes.GROUP_UPDATE_BIT > 0 - - val unread = !silent && ( - message.isSecureMessage || - message.isGroup || - message.isPreKeyBundle || - Util.isDefaultSmsProvider(context) - ) - - val threadId: Long = if (message.groupId == null) threads.getOrCreateThreadIdFor(message.authorId, false) else threads.getOrCreateThreadIdFor(RecipientId.from(message.groupId!!), true) - - if (tryToCollapseJoinRequestEvents) { - val result = collapseJoinRequestEventsIfPossible(threadId, message as IncomingGroupUpdateMessage) - if (result.isPresent) { - return result - } - } - - val values = ContentValues() - values.put(FROM_RECIPIENT_ID, message.authorId.serialize()) - values.put(FROM_DEVICE_ID, message.authorDeviceId) - values.put(TO_RECIPIENT_ID, Recipient.self().id.serialize()) - values.put(DATE_RECEIVED, message.receivedTimestampMillis) - values.put(DATE_SENT, message.sentTimestampMillis) - values.put(DATE_SERVER, message.serverTimestampMillis) - values.put(READ, if (unread) 0 else 1) - values.put(SMS_SUBSCRIPTION_ID, message.subscriptionId) - values.put(EXPIRES_IN, message.expiresIn) - values.put(UNIDENTIFIED, message.isUnidentified) - values.put(BODY, message.messageBody) - values.put(TYPE, type) - values.put(THREAD_ID, threadId) - values.put(SERVER_GUID, message.serverGuid) - - if (editedMessage != null) { - values.put(ORIGINAL_MESSAGE_ID, editedMessage.getOriginalOrOwnMessageId().id) - } else { - values.putNull(ORIGINAL_MESSAGE_ID) - } - - val messageId: Long = writableDatabase.withinTransaction { - val id = writableDatabase.insert(TABLE_NAME, null, values) - - if (id < 0) { - Log.w(TAG, "Failed to insert text message (${message.sentTimestampMillis}, ${message.authorId}, ThreadId::$threadId)! Likely a duplicate.") - } else { - if (unread && editedMessage == null) { - threads.incrementUnread(threadId, 1, 0) - } - } - - id - } - - if (messageId < 0) { - return Optional.empty() - } - - threads.markAsActiveEarly(threadId) - - if (!silent) { - ThreadUpdateJob.enqueue(threadId) - TrimThreadJob.enqueueAsync(threadId) - } - - if (notifyObservers) { - notifyConversationListeners(threadId) - } - - return Optional.of(InsertResult(messageId, threadId)) - } - - fun insertEditMessageInbox(threadId: Long, mediaMessage: IncomingMediaMessage, targetMessage: MediaMmsMessageRecord): Optional { - val insertResult = insertMessageInbox(retrieved = mediaMessage, candidateThreadId = threadId, editedMessage = targetMessage, notifyObservers = false) + fun insertEditMessageInbox(mediaMessage: IncomingMessage, targetMessage: MediaMmsMessageRecord): Optional { + val insertResult = insertMessageInbox(retrieved = mediaMessage, editedMessage = targetMessage, notifyObservers = false) if (insertResult.isPresent) { val (messageId) = insertResult.get() @@ -1129,29 +989,6 @@ open class MessageTable(context: Context?, databaseHelper: SignalDatabase) : Dat return insertResult } - fun insertEditMessageInbox(textMessage: IncomingTextMessage, targetMessage: MediaMmsMessageRecord): Optional { - val insertResult = insertMessageInbox(message = textMessage, editedMessage = targetMessage, notifyObservers = false) - - if (insertResult.isPresent) { - val (messageId) = insertResult.get() - - if (targetMessage.expireStarted > 0) { - markExpireStarted(messageId, targetMessage.expireStarted) - } - - writableDatabase.update(TABLE_NAME) - .values(LATEST_REVISION_ID to messageId) - .where("$ID_WHERE OR $LATEST_REVISION_ID = ?", targetMessage.id, targetMessage.id) - .run() - - reactions.moveReactionsToNewMessage(newMessageId = messageId, previousId = targetMessage.id) - - notifyConversationListeners(targetMessage.threadId) - } - - return insertResult - } - fun insertProfileNameChangeMessages(recipient: Recipient, newProfileName: String, previousProfileName: String) { writableDatabase.withinTransaction { db -> val groupRecords = groups.getGroupsContainingMember(recipient.id, false) @@ -1890,13 +1727,13 @@ open class MessageTable(context: Context?, databaseHelper: SignalDatabase) : Dat .readToSingleLong(-1) } - private fun getThreadIdFor(retrieved: IncomingMediaMessage): Long { + private fun getThreadIdFor(retrieved: IncomingMessage): Long { return if (retrieved.groupId != null) { val groupRecipientId = recipients.getOrInsertFromPossiblyMigratedGroupId(retrieved.groupId) val groupRecipients = Recipient.resolved(groupRecipientId) threads.getOrCreateThreadIdFor(groupRecipients) } else { - val sender = Recipient.resolved(retrieved.from!!) + val sender = Recipient.resolved(retrieved.from) threads.getOrCreateThreadIdFor(sender) } } @@ -2586,8 +2423,8 @@ open class MessageTable(context: Context?, databaseHelper: SignalDatabase) : Dat @JvmOverloads @Throws(MmsException::class) fun insertMessageInbox( - retrieved: IncomingMediaMessage, - candidateThreadId: Long, + retrieved: IncomingMessage, + candidateThreadId: Long = -1, editedMessage: MediaMmsMessageRecord? = null, notifyObservers: Boolean = true ): Optional { @@ -2599,10 +2436,25 @@ open class MessageTable(context: Context?, databaseHelper: SignalDatabase) : Dat candidateThreadId } + if (retrieved.type == MessageType.GROUP_UPDATE && retrieved.groupContext?.let { GroupV2UpdateMessageUtil.isJoinRequestCancel(it) } == true) { + val result = collapseJoinRequestEventsIfPossible(threadId, retrieved) + if (result.isPresent) { + Log.d(TAG, "[insertMessageInbox] Collapsed join request events.") + return result + } + } + + val silent = MessageTypes.isGroupUpdate(type) || + retrieved.type == MessageType.IDENTITY_DEFAULT || + retrieved.type == MessageType.IDENTITY_VERIFIED || + retrieved.type == MessageType.IDENTITY_UPDATE + + val read = silent || retrieved.isExpirationUpdate + val contentValues = contentValuesOf( DATE_SENT to retrieved.sentTimeMillis, DATE_SERVER to retrieved.serverTimeMillis, - FROM_RECIPIENT_ID to retrieved.from!!.serialize(), + FROM_RECIPIENT_ID to retrieved.from.serialize(), TO_RECIPIENT_ID to Recipient.self().id.serialize(), TYPE to type, MMS_MESSAGE_TYPE to PduHeaders.MESSAGE_TYPE_RETRIEVE_CONF, @@ -2614,7 +2466,7 @@ open class MessageTable(context: Context?, databaseHelper: SignalDatabase) : Dat VIEW_ONCE to if (retrieved.isViewOnce) 1 else 0, STORY_TYPE to retrieved.storyType.code, PARENT_STORY_ID to if (retrieved.parentStoryId != null) retrieved.parentStoryId.serialize() else 0, - READ to if (MessageTypes.isGroupUpdate(type) || retrieved.isExpirationUpdate) 1 else 0, + READ to read.toInt(), UNIDENTIFIED to retrieved.isUnidentified, SERVER_GUID to retrieved.serverGuid, LATEST_REVISION_ID to null, @@ -2655,7 +2507,7 @@ open class MessageTable(context: Context?, databaseHelper: SignalDatabase) : Dat messageRanges = retrieved.messageRanges, contentValues = contentValues, insertListener = null, - updateThread = retrieved.storyType === StoryType.NONE, + updateThread = retrieved.storyType === StoryType.NONE && !silent, unarchive = true ) @@ -3596,7 +3448,7 @@ open class MessageTable(context: Context?, databaseHelper: SignalDatabase) : Dat } @VisibleForTesting - fun collapseJoinRequestEventsIfPossible(threadId: Long, message: IncomingGroupUpdateMessage): Optional { + fun collapseJoinRequestEventsIfPossible(threadId: Long, message: IncomingMessage): Optional { var result: InsertResult? = null writableDatabase.withinTransaction { db -> @@ -3604,21 +3456,22 @@ open class MessageTable(context: Context?, databaseHelper: SignalDatabase) : Dat val latestMessage = reader.getNext() if (latestMessage != null && latestMessage.isGroupV2) { - val changeEditor: Optional = message.changeEditor + val changeEditor: Optional = message.groupContext?.let { GroupV2UpdateMessageUtil.getChangeEditor(it) } ?: Optional.empty() if (changeEditor.isPresent && latestMessage.isGroupV2JoinRequest(changeEditor.get())) { val secondLatestMessage = reader.getNext() val id: Long val encodedBody: String + val changeRevision: Int = message.groupContext?.let { GroupV2UpdateMessageUtil.getChangeRevision(it) } ?: -1 if (secondLatestMessage != null && secondLatestMessage.isGroupV2JoinRequest(changeEditor.get())) { id = secondLatestMessage.id - encodedBody = MessageRecord.createNewContextWithAppendedDeleteJoinRequest(secondLatestMessage, message.changeRevision, changeEditor.get().toByteString()) + encodedBody = MessageRecord.createNewContextWithAppendedDeleteJoinRequest(secondLatestMessage, changeRevision, changeEditor.get().toByteString()) deleteMessage(latestMessage.id) } else { id = latestMessage.id - encodedBody = MessageRecord.createNewContextWithAppendedDeleteJoinRequest(latestMessage, message.changeRevision, changeEditor.get().toByteString()) + encodedBody = MessageRecord.createNewContextWithAppendedDeleteJoinRequest(latestMessage, changeRevision, changeEditor.get().toByteString()) } db.update(TABLE_NAME) @@ -4827,56 +4680,37 @@ open class MessageTable(context: Context?, databaseHelper: SignalDatabase) : Dat } /** - * Determines the database type bitmask for theh inbound message. + * Determines the database type bitmask for the inbound message. */ @Throws(MmsException::class) - private fun IncomingMediaMessage.toMessageType(): Long { - var type = MessageTypes.BASE_INBOX_TYPE or MessageTypes.SECURE_MESSAGE_BIT - var hasSpecialType = false - - if (this.isPushMessage) { - type = type or MessageTypes.PUSH_MESSAGE_BIT - } - - if (this.isExpirationUpdate) { - type = type or MessageTypes.EXPIRATION_TIMER_UPDATE_BIT - } - - if (this.isStoryReaction) { - type = type or MessageTypes.SPECIAL_TYPE_STORY_REACTION - hasSpecialType = true - } + private fun IncomingMessage.toMessageType(): Long { + var type = MessageTypes.BASE_INBOX_TYPE or MessageTypes.SECURE_MESSAGE_BIT or MessageTypes.PUSH_MESSAGE_BIT if (this.giftBadge != null) { - if (hasSpecialType) { - throw MmsException("Cannot insert message with multiple special types.") - } type = type or MessageTypes.SPECIAL_TYPE_GIFT_BADGE - hasSpecialType = true } - if (this.isPaymentsNotification) { - if (hasSpecialType) { - throw MmsException("Cannot insert message with multiple special types.") - } - type = type or MessageTypes.SPECIAL_TYPE_PAYMENTS_NOTIFICATION - hasSpecialType = true - } + type = type or when (this.type) { + MessageType.NORMAL -> 0 + MessageType.EXPIRATION_UPDATE -> MessageTypes.EXPIRATION_TIMER_UPDATE_BIT + MessageType.STORY_REACTION -> MessageTypes.SPECIAL_TYPE_STORY_REACTION + MessageType.PAYMENTS_NOTIFICATION -> MessageTypes.SPECIAL_TYPE_PAYMENTS_NOTIFICATION + MessageType.ACTIVATE_PAYMENTS_REQUEST -> MessageTypes.SPECIAL_TYPE_PAYMENTS_ACTIVATE_REQUEST + MessageType.PAYMENTS_ACTIVATED -> MessageTypes.SPECIAL_TYPE_PAYMENTS_ACTIVATED + MessageType.CONTACT_JOINED -> MessageTypes.JOINED_TYPE + MessageType.IDENTITY_UPDATE -> MessageTypes.KEY_EXCHANGE_IDENTITY_UPDATE_BIT + MessageType.IDENTITY_VERIFIED -> MessageTypes.KEY_EXCHANGE_IDENTITY_VERIFIED_BIT + MessageType.IDENTITY_DEFAULT -> MessageTypes.KEY_EXCHANGE_IDENTITY_DEFAULT_BIT + MessageType.END_SESSION -> MessageTypes.END_SESSION_BIT + MessageType.GROUP_UPDATE -> { + val isOnlyGroupLeave = this.groupContext?.let { GroupV2UpdateMessageUtil.isJustAGroupLeave(it) } ?: false - if (this.isActivatePaymentsRequest) { - if (hasSpecialType) { - throw MmsException("Cannot insert message with multiple special types.") + if (isOnlyGroupLeave) { + MessageTypes.GROUP_V2_BIT or MessageTypes.GROUP_UPDATE_BIT or MessageTypes.GROUP_LEAVE_BIT + } else { + MessageTypes.GROUP_V2_BIT or MessageTypes.GROUP_UPDATE_BIT + } } - type = type or MessageTypes.SPECIAL_TYPE_PAYMENTS_ACTIVATE_REQUEST - hasSpecialType = true - } - - if (this.isPaymentsActivated) { - if (hasSpecialType) { - throw MmsException("Cannot insert message with multiple special types.") - } - type = type or MessageTypes.SPECIAL_TYPE_PAYMENTS_ACTIVATED - hasSpecialType = true } return type diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/MessageType.kt b/app/src/main/java/org/thoughtcrime/securesms/database/MessageType.kt new file mode 100644 index 0000000000..1a95231616 --- /dev/null +++ b/app/src/main/java/org/thoughtcrime/securesms/database/MessageType.kt @@ -0,0 +1,49 @@ +/* + * Copyright 2023 Signal Messenger, LLC + * SPDX-License-Identifier: AGPL-3.0-only + */ + +package org.thoughtcrime.securesms.database + +/** + * Describes what type of message something is. This serves as an abstraction layer over the bitmasks + * in [MessageTypes]. Currently only used for [org.thoughtcrime.securesms.mms.IncomingMessage], + * but will hopefully be used more widely in the future. + */ +enum class MessageType { + /** A typical message with no special typing */ + NORMAL, + + /** A mobilecoin payment */ + PAYMENTS_NOTIFICATION, + + /** A request to activate mobilecoin payments */ + ACTIVATE_PAYMENTS_REQUEST, + + /** Mobilecoin payments have been activated (in response to a [ACTIVATE_PAYMENTS_REQUEST] */ + PAYMENTS_ACTIVATED, + + /** An emoji reaction to a story */ + STORY_REACTION, + + /** The chat's expiration timer has been updated */ + EXPIRATION_UPDATE, + + /** A new contact has joined Signal */ + CONTACT_JOINED, + + /** Any update to a group */ + GROUP_UPDATE, + + /** A user's identity/safety number has changed */ + IDENTITY_UPDATE, + + /** You verified a user's identity/safety number */ + IDENTITY_VERIFIED, + + /** You unverified a user's identity/safety number, resetting it to the default state */ + IDENTITY_DEFAULT, + + /** A manual session reset. This is no longer used and is only here for handling possible inbound/sync messages. */ + END_SESSION +} diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/MessageTypes.java b/app/src/main/java/org/thoughtcrime/securesms/database/MessageTypes.java index c77f76d13a..d1ff8aead8 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/MessageTypes.java +++ b/app/src/main/java/org/thoughtcrime/securesms/database/MessageTypes.java @@ -78,11 +78,11 @@ public interface MessageTypes { long KEY_EXCHANGE_BIT = 0x8000; long KEY_EXCHANGE_IDENTITY_VERIFIED_BIT = 0x4000; long KEY_EXCHANGE_IDENTITY_DEFAULT_BIT = 0x2000; - long KEY_EXCHANGE_CORRUPTED_BIT = 0x1000; +// long KEY_EXCHANGE_CORRUPTED_BIT = 0x1000; long KEY_EXCHANGE_INVALID_VERSION_BIT = 0x800; long KEY_EXCHANGE_BUNDLE_BIT = 0x400; long KEY_EXCHANGE_IDENTITY_UPDATE_BIT = 0x200; - long KEY_EXCHANGE_CONTENT_FORMAT = 0x100; +// long KEY_EXCHANGE_CONTENT_FORMAT = 0x100; // Secure Message Information long SECURE_MESSAGE_BIT = 0x800000; @@ -236,10 +236,6 @@ public interface MessageTypes { return (type & KEY_EXCHANGE_IDENTITY_DEFAULT_BIT) != 0; } - static boolean isCorruptedKeyExchange(long type) { - return (type & KEY_EXCHANGE_CORRUPTED_BIT) != 0; - } - static boolean isInvalidVersionKeyExchange(long type) { return (type & KEY_EXCHANGE_INVALID_VERSION_BIT) != 0; } @@ -248,10 +244,6 @@ public interface MessageTypes { return (type & KEY_EXCHANGE_BUNDLE_BIT) != 0; } - static boolean isContentBundleKeyExchange(long type) { - return (type & KEY_EXCHANGE_CONTENT_FORMAT) != 0; - } - static boolean isIdentityUpdate(long type) { return (type & KEY_EXCHANGE_IDENTITY_UPDATE_BIT) != 0; } diff --git a/app/src/main/java/org/thoughtcrime/securesms/groups/v2/processing/GroupsV2StateProcessor.java b/app/src/main/java/org/thoughtcrime/securesms/groups/v2/processing/GroupsV2StateProcessor.java index 5cf726bde4..748e42a420 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/groups/v2/processing/GroupsV2StateProcessor.java +++ b/app/src/main/java/org/thoughtcrime/securesms/groups/v2/processing/GroupsV2StateProcessor.java @@ -39,12 +39,11 @@ import org.thoughtcrime.securesms.jobs.LeaveGroupV2Job; import org.thoughtcrime.securesms.jobs.RequestGroupV2InfoJob; import org.thoughtcrime.securesms.jobs.RetrieveProfileJob; import org.thoughtcrime.securesms.keyvalue.SignalStore; +import org.thoughtcrime.securesms.mms.IncomingMessage; import org.thoughtcrime.securesms.mms.MmsException; import org.thoughtcrime.securesms.mms.OutgoingMessage; import org.thoughtcrime.securesms.recipients.Recipient; import org.thoughtcrime.securesms.recipients.RecipientId; -import org.thoughtcrime.securesms.sms.IncomingGroupUpdateMessage; -import org.thoughtcrime.securesms.sms.IncomingTextMessage; import org.whispersystems.signalservice.api.groupsv2.DecryptedGroupHistoryEntry; import org.whispersystems.signalservice.api.groupsv2.DecryptedGroupUtil; import org.whispersystems.signalservice.api.groupsv2.GroupChangeReconstruct; @@ -801,19 +800,22 @@ public class GroupsV2StateProcessor { mmsDatabase.markAsSent(messageId, true); threadTable.update(threadId, false, false); } catch (MmsException e) { - Log.w(TAG, e); + Log.w(TAG, "Failed to insert outgoing update message!", e); } } else { - MessageTable smsDatabase = SignalDatabase.messages(); - RecipientId sender = RecipientId.from(editor.get()); - IncomingTextMessage incoming = new IncomingTextMessage(sender, -1, timestamp, timestamp, timestamp, "", Optional.of(groupId), 0, false, null); - IncomingGroupUpdateMessage groupMessage = new IncomingGroupUpdateMessage(incoming, decryptedGroupV2Context); - Optional insertResult = smsDatabase.insertMessageInbox(groupMessage); + try { + MessageTable smsDatabase = SignalDatabase.messages(); + RecipientId sender = RecipientId.from(editor.get()); + IncomingMessage groupMessage = IncomingMessage.groupUpdate(sender, timestamp, groupId, decryptedGroupV2Context); + Optional insertResult = smsDatabase.insertMessageInbox(groupMessage); - if (insertResult.isPresent()) { - SignalDatabase.threads().update(insertResult.get().getThreadId(), false, false); - } else { - Log.w(TAG, "Could not insert update message"); + if (insertResult.isPresent()) { + SignalDatabase.threads().update(insertResult.get().getThreadId(), false, false); + } else { + Log.w(TAG, "Could not insert update message"); + } + } catch (MmsException e) { + Log.w(TAG, "Failed to insert incoming update message!", e); } } } diff --git a/app/src/main/java/org/thoughtcrime/securesms/messages/DataMessageProcessor.kt b/app/src/main/java/org/thoughtcrime/securesms/messages/DataMessageProcessor.kt index 727de079cc..2ce7f04196 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/messages/DataMessageProcessor.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/messages/DataMessageProcessor.kt @@ -25,6 +25,7 @@ import org.thoughtcrime.securesms.crypto.ProfileKeyUtil import org.thoughtcrime.securesms.crypto.SecurityEvent import org.thoughtcrime.securesms.database.AttachmentTable import org.thoughtcrime.securesms.database.MessageTable.InsertResult +import org.thoughtcrime.securesms.database.MessageType import org.thoughtcrime.securesms.database.NoSuchMessageException import org.thoughtcrime.securesms.database.PaymentTable.PublicKeyConflictException import org.thoughtcrime.securesms.database.SignalDatabase @@ -75,7 +76,7 @@ import org.thoughtcrime.securesms.messages.SignalServiceProtoUtil.isPaymentActiv import org.thoughtcrime.securesms.messages.SignalServiceProtoUtil.isStoryReaction import org.thoughtcrime.securesms.messages.SignalServiceProtoUtil.toPointer import org.thoughtcrime.securesms.messages.SignalServiceProtoUtil.toPointersWithinLimit -import org.thoughtcrime.securesms.mms.IncomingMediaMessage +import org.thoughtcrime.securesms.mms.IncomingMessage import org.thoughtcrime.securesms.mms.MmsException import org.thoughtcrime.securesms.mms.QuoteModel import org.thoughtcrime.securesms.mms.StickerSlide @@ -84,9 +85,6 @@ import org.thoughtcrime.securesms.recipients.Recipient import org.thoughtcrime.securesms.recipients.Recipient.HiddenState import org.thoughtcrime.securesms.recipients.RecipientId import org.thoughtcrime.securesms.recipients.RecipientUtil -import org.thoughtcrime.securesms.sms.IncomingEncryptedMessage -import org.thoughtcrime.securesms.sms.IncomingEndSessionMessage -import org.thoughtcrime.securesms.sms.IncomingTextMessage import org.thoughtcrime.securesms.stickers.StickerLocator import org.thoughtcrime.securesms.storage.StorageSyncHelper import org.thoughtcrime.securesms.util.EarlyMessageCacheEntry @@ -100,7 +98,7 @@ import org.whispersystems.signalservice.api.crypto.EnvelopeMetadata import org.whispersystems.signalservice.api.payments.Money import org.whispersystems.signalservice.api.push.ServiceId import org.whispersystems.signalservice.api.push.ServiceId.ACI -import org.whispersystems.signalservice.api.util.OptionalUtil.asOptional +import org.whispersystems.signalservice.api.util.Preconditions import org.whispersystems.signalservice.internal.push.BodyRange import org.whispersystems.signalservice.internal.push.Content import org.whispersystems.signalservice.internal.push.DataMessage @@ -143,7 +141,7 @@ object DataMessageProcessor { var messageId: MessageId? = null when { - message.isInvalid -> handleInvalidMessage(context, senderRecipient.id, metadata.sourceDeviceId, groupId, envelope.timestamp!!) + message.isInvalid -> handleInvalidMessage(context, senderRecipient.id, groupId, envelope.timestamp!!) message.isEndSession -> messageId = handleEndSessionMessage(context, senderRecipient.id, envelope, metadata) message.isExpirationUpdate -> messageId = handleExpirationUpdate(envelope, metadata, senderRecipient.id, threadRecipient.id, groupId, message.expireTimerDuration, receivedTime, false) message.isStoryReaction -> messageId = handleStoryReaction(context, envelope, metadata, message, senderRecipient.id, groupId) @@ -244,13 +242,12 @@ object DataMessageProcessor { private fun handleInvalidMessage( context: Context, sender: RecipientId, - senderDevice: Int, groupId: GroupId?, timestamp: Long ) { log(timestamp, "Invalid message.") - val insertResult: InsertResult? = insertPlaceholder(sender, senderDevice, timestamp, groupId) + val insertResult: InsertResult? = insertPlaceholder(sender, timestamp, groupId) if (insertResult != null) { SignalDatabase.messages.markAsInvalidMessage(insertResult.messageId) ApplicationDependencies.getMessageNotifier().updateNotification(context, ConversationId.forConversation(insertResult.threadId)) @@ -265,20 +262,17 @@ object DataMessageProcessor { ): MessageId? { log(envelope.timestamp!!, "End session message.") - val incomingTextMessage = IncomingTextMessage( - senderRecipientId, - metadata.sourceDeviceId, - envelope.timestamp!!, - envelope.serverTimestamp!!, - System.currentTimeMillis(), - "", - Optional.empty(), - 0, - metadata.sealedSender, - envelope.serverGuid + val incomingMessage = IncomingMessage( + from = senderRecipientId, + sentTimeMillis = envelope.timestamp!!, + serverTimeMillis = envelope.serverTimestamp!!, + receivedTimeMillis = System.currentTimeMillis(), + isUnidentified = metadata.sealedSender, + serverGuid = envelope.serverGuid, + type = MessageType.END_SESSION ) - val insertResult: InsertResult? = SignalDatabase.messages.insertMessageInbox(IncomingEndSessionMessage(incomingTextMessage)).orNull() + val insertResult: InsertResult? = SignalDatabase.messages.insertMessageInbox(incomingMessage).orNull() return if (insertResult != null) { ApplicationDependencies.getProtocolStore().aci().deleteAllSessions(metadata.sourceServiceId.toString()) @@ -318,7 +312,7 @@ object DataMessageProcessor { } try { - val mediaMessage = IncomingMediaMessage( + val mediaMessage = IncomingMessage( from = senderRecipientId, sentTimeMillis = envelope.timestamp!! - if (sideEffect) 1 else 0, serverTimeMillis = envelope.serverTimestamp!!, @@ -418,7 +412,7 @@ object DataMessageProcessor { return null } - val mediaMessage = IncomingMediaMessage( + val mediaMessage = IncomingMessage( from = senderRecipientId, sentTimeMillis = envelope.timestamp!!, serverTimeMillis = envelope.serverTimestamp!!, @@ -582,8 +576,10 @@ object DataMessageProcessor { isPaymentsActivated: Boolean ): MessageId? { log(envelope.timestamp!!, "Payment activation request: $isActivatePaymentsRequest activated: $isPaymentsActivated") + Preconditions.checkArgument(isActivatePaymentsRequest || isPaymentsActivated) + try { - val mediaMessage = IncomingMediaMessage( + val mediaMessage = IncomingMessage( from = senderRecipientId, sentTimeMillis = envelope.timestamp!!, serverTimeMillis = envelope.serverTimestamp!!, @@ -591,8 +587,7 @@ object DataMessageProcessor { expiresIn = message.expireTimerDuration.inWholeMilliseconds, isUnidentified = metadata.sealedSender, serverGuid = envelope.serverGuid, - isActivatePaymentsRequest = isActivatePaymentsRequest, - isPaymentsActivated = isPaymentsActivated + type = if (isActivatePaymentsRequest) MessageType.ACTIVATE_PAYMENTS_REQUEST else MessageType.PAYMENTS_ACTIVATED ) val insertResult: InsertResult? = SignalDatabase.messages.insertMessageInbox(mediaMessage, -1).orNull() @@ -638,7 +633,7 @@ object DataMessageProcessor { true ) - val mediaMessage = IncomingMediaMessage( + val mediaMessage = IncomingMessage( from = senderRecipientId, body = uuid.toString(), sentTimeMillis = envelope.timestamp!!, @@ -648,7 +643,7 @@ object DataMessageProcessor { isUnidentified = metadata.sealedSender, serverGuid = envelope.serverGuid, isPushMessage = true, - isPaymentsNotification = true + type = MessageType.PAYMENTS_NOTIFICATION ) val insertResult: InsertResult? = SignalDatabase.messages.insertMessageInbox(mediaMessage, -1).orNull() @@ -750,7 +745,7 @@ object DataMessageProcessor { val bodyRanges: BodyRangeList? = message.bodyRanges.filter { it.mentionAci == null }.toList().toBodyRangeList() - val mediaMessage = IncomingMediaMessage( + val mediaMessage = IncomingMessage( from = senderRecipient.id, sentTimeMillis = envelope.timestamp!!, serverTimeMillis = envelope.serverTimestamp!!, @@ -818,7 +813,7 @@ object DataMessageProcessor { .build() val insertResult: InsertResult? = try { - val mediaMessage = IncomingMediaMessage( + val mediaMessage = IncomingMessage( from = senderRecipient.id, sentTimeMillis = envelope.timestamp!!, serverTimeMillis = envelope.serverTimestamp!!, @@ -874,7 +869,7 @@ object DataMessageProcessor { handlePossibleExpirationUpdate(envelope, metadata, senderRecipient.id, threadRecipient, groupId, message.expireTimerDuration, receivedTime) - val mediaMessage = IncomingMediaMessage( + val mediaMessage = IncomingMessage( from = senderRecipient.id, sentTimeMillis = envelope.timestamp!!, serverTimeMillis = envelope.serverTimestamp!!, @@ -956,20 +951,19 @@ object DataMessageProcessor { notifyTypingStoppedFromIncomingMessage(context, senderRecipient, threadRecipient.id, metadata.sourceDeviceId) - val textMessage = IncomingTextMessage( - senderRecipient.id, - metadata.sourceDeviceId, - envelope.timestamp!!, - envelope.serverTimestamp!!, - receivedTime, - body, - Optional.ofNullable(groupId), - message.expireTimerDuration.inWholeMilliseconds, - metadata.sealedSender, - envelope.serverGuid + val textMessage = IncomingMessage( + from = senderRecipient.id, + sentTimeMillis = envelope.timestamp!!, + serverTimeMillis = envelope.serverTimestamp!!, + receivedTimeMillis = receivedTime, + body = body, + groupId = groupId, + expiresIn = message.expireTimerDuration.inWholeMilliseconds, + isUnidentified = metadata.sealedSender, + serverGuid = envelope.serverGuid ) - val insertResult: InsertResult? = SignalDatabase.messages.insertMessageInbox(IncomingEncryptedMessage(textMessage, body)).orNull() + val insertResult: InsertResult? = SignalDatabase.messages.insertMessageInbox(textMessage).orNull() localMetrics?.onInsertedTextMessage() return if (insertResult != null) { @@ -1031,20 +1025,17 @@ object DataMessageProcessor { } } - private fun insertPlaceholder(sender: RecipientId, senderDevice: Int, timestamp: Long, groupId: GroupId?): InsertResult? { - val textMessage = IncomingTextMessage( - sender, - senderDevice, - timestamp, - -1, - System.currentTimeMillis(), - "", - groupId.asOptional(), - 0, - false, - null + private fun insertPlaceholder(sender: RecipientId, timestamp: Long, groupId: GroupId?): InsertResult? { + val textMessage = IncomingMessage( + from = sender, + sentTimeMillis = timestamp, + serverTimeMillis = -1, + receivedTimeMillis = System.currentTimeMillis(), + body = "", + groupId = groupId ) - return SignalDatabase.messages.insertMessageInbox(IncomingEncryptedMessage(textMessage, "")).orNull() + + return SignalDatabase.messages.insertMessageInbox(textMessage).orNull() } fun getValidatedQuote(context: Context, timestamp: Long, message: DataMessage): QuoteModel? { diff --git a/app/src/main/java/org/thoughtcrime/securesms/messages/EditMessageProcessor.kt b/app/src/main/java/org/thoughtcrime/securesms/messages/EditMessageProcessor.kt index 856c8974fa..e99d0742b7 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/messages/EditMessageProcessor.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/messages/EditMessageProcessor.kt @@ -19,13 +19,11 @@ import org.thoughtcrime.securesms.messages.MessageContentProcessor.Companion.war import org.thoughtcrime.securesms.messages.SignalServiceProtoUtil.groupId import org.thoughtcrime.securesms.messages.SignalServiceProtoUtil.isMediaMessage import org.thoughtcrime.securesms.messages.SignalServiceProtoUtil.toPointersWithinLimit -import org.thoughtcrime.securesms.mms.IncomingMediaMessage +import org.thoughtcrime.securesms.mms.IncomingMessage import org.thoughtcrime.securesms.mms.QuoteModel import org.thoughtcrime.securesms.notifications.v2.ConversationId.Companion.forConversation import org.thoughtcrime.securesms.recipients.Recipient import org.thoughtcrime.securesms.recipients.RecipientId -import org.thoughtcrime.securesms.sms.IncomingEncryptedMessage -import org.thoughtcrime.securesms.sms.IncomingTextMessage import org.thoughtcrime.securesms.util.EarlyMessageCacheEntry import org.thoughtcrime.securesms.util.MediaUtil import org.thoughtcrime.securesms.util.MessageConstraintsUtil @@ -35,7 +33,6 @@ import org.whispersystems.signalservice.api.crypto.EnvelopeMetadata import org.whispersystems.signalservice.internal.push.Content import org.whispersystems.signalservice.internal.push.DataMessage import org.whispersystems.signalservice.internal.push.Envelope -import java.util.Optional object EditMessageProcessor { fun process( @@ -142,7 +139,7 @@ object EditMessageProcessor { attachments.filter { MediaUtil.SlideType.LONG_TEXT == MediaUtil.getSlideTypeFromContentType(it.contentType) } - val mediaMessage = IncomingMediaMessage( + val mediaMessage = IncomingMessage( from = senderRecipientId, sentTimeMillis = message.timestamp!!, serverTimeMillis = envelope.serverTimestamp!!, @@ -162,7 +159,7 @@ object EditMessageProcessor { isPushMessage = true ) - val insertResult = SignalDatabase.messages.insertEditMessageInbox(-1, mediaMessage, targetMessage).orNull() + val insertResult = SignalDatabase.messages.insertEditMessageInbox(mediaMessage, targetMessage).orNull() if (insertResult?.insertedAttachments != null) { SignalDatabase.runPostSuccessfulTransaction { val downloadJobs: List = insertResult.insertedAttachments.mapNotNull { (_, attachmentId) -> @@ -182,21 +179,18 @@ object EditMessageProcessor { message: DataMessage, targetMessage: MediaMmsMessageRecord ): InsertResult? { - var textMessage = IncomingTextMessage( - senderRecipientId, - metadata.sourceDeviceId, - envelope.timestamp!!, - envelope.timestamp!!, - targetMessage.dateReceived, - message.body, - Optional.ofNullable(groupId), - targetMessage.expiresIn, - metadata.sealedSender, - envelope.serverGuid + val textMessage = IncomingMessage( + from = senderRecipientId, + sentTimeMillis = envelope.timestamp!!, + serverTimeMillis = envelope.timestamp!!, + receivedTimeMillis = targetMessage.dateReceived, + body = message.body, + groupId = groupId, + expiresIn = targetMessage.expiresIn, + isUnidentified = metadata.sealedSender, + serverGuid = envelope.serverGuid ) - textMessage = IncomingEncryptedMessage(textMessage, message.body) - return SignalDatabase.messages.insertEditMessageInbox(textMessage, targetMessage).orNull() } } diff --git a/app/src/main/java/org/thoughtcrime/securesms/messages/MessageContentProcessor.kt b/app/src/main/java/org/thoughtcrime/securesms/messages/MessageContentProcessor.kt index 738dd23cdd..514d3bb710 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/messages/MessageContentProcessor.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/messages/MessageContentProcessor.kt @@ -37,11 +37,10 @@ import org.thoughtcrime.securesms.messages.SignalServiceProtoUtil.isMediaMessage import org.thoughtcrime.securesms.messages.SignalServiceProtoUtil.isValid import org.thoughtcrime.securesms.messages.SignalServiceProtoUtil.signedGroupChange import org.thoughtcrime.securesms.messages.SignalServiceProtoUtil.toDecryptionErrorMessage +import org.thoughtcrime.securesms.mms.IncomingMessage import org.thoughtcrime.securesms.notifications.v2.ConversationId import org.thoughtcrime.securesms.recipients.Recipient import org.thoughtcrime.securesms.recipients.RecipientId -import org.thoughtcrime.securesms.sms.IncomingEncryptedMessage -import org.thoughtcrime.securesms.sms.IncomingTextMessage import org.thoughtcrime.securesms.util.EarlyMessageCacheEntry import org.thoughtcrime.securesms.util.FeatureFlags import org.thoughtcrime.securesms.util.SignalLocalMetrics @@ -295,23 +294,18 @@ open class MessageContentProcessor(private val context: Context) { } } - private fun insertErrorMessage(context: Context, sender: Recipient, senderDevice: Int, timestamp: Long, groupId: Optional, marker: (Long) -> Unit) { - val textMessage = IncomingTextMessage( - sender.id, - senderDevice, - timestamp, - -1, - System.currentTimeMillis(), - "", - groupId, - 0, - false, - null + private fun insertErrorMessage(context: Context, sender: Recipient, timestamp: Long, groupId: Optional, marker: (Long) -> Unit) { + val textMessage = IncomingMessage( + from = sender.id, + sentTimeMillis = timestamp, + serverTimeMillis = -1, + receivedTimeMillis = System.currentTimeMillis(), + groupId = groupId.orNull() ) SignalDatabase .messages - .insertMessageInbox(IncomingEncryptedMessage(textMessage, "")) + .insertMessageInbox(textMessage) .ifPresent { marker(it.messageId) ApplicationDependencies.getMessageNotifier().updateNotification(context, ConversationId.forConversation(it.threadId)) @@ -374,21 +368,21 @@ open class MessageContentProcessor(private val context: Context) { MessageState.INVALID_VERSION -> { warn(timestamp, "Handling invalid version.") - insertErrorMessage(context, sender, exceptionMetadata.senderDevice, timestamp, exceptionMetadata.groupId.toOptional()) { messageId -> + insertErrorMessage(context, sender, timestamp, exceptionMetadata.groupId.toOptional()) { messageId -> SignalDatabase.messages.markAsInvalidVersionKeyExchange(messageId) } } MessageState.LEGACY_MESSAGE -> { warn(timestamp, "Handling legacy message.") - insertErrorMessage(context, sender, exceptionMetadata.senderDevice, timestamp, exceptionMetadata.groupId.toOptional()) { messageId -> + insertErrorMessage(context, sender, timestamp, exceptionMetadata.groupId.toOptional()) { messageId -> SignalDatabase.messages.markAsLegacyVersion(messageId) } } MessageState.UNSUPPORTED_DATA_MESSAGE -> { warn(timestamp, "Handling unsupported data message.") - insertErrorMessage(context, sender, exceptionMetadata.senderDevice, timestamp, exceptionMetadata.groupId.toOptional()) { messageId -> + insertErrorMessage(context, sender, timestamp, exceptionMetadata.groupId.toOptional()) { messageId -> SignalDatabase.messages.markAsUnsupportedProtocolVersion(messageId) } } diff --git a/app/src/main/java/org/thoughtcrime/securesms/messages/StoryMessageProcessor.kt b/app/src/main/java/org/thoughtcrime/securesms/messages/StoryMessageProcessor.kt index fe4fcf0383..9b62943485 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/messages/StoryMessageProcessor.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/messages/StoryMessageProcessor.kt @@ -14,7 +14,7 @@ import org.thoughtcrime.securesms.messages.MessageContentProcessor.Companion.log import org.thoughtcrime.securesms.messages.MessageContentProcessor.Companion.warn import org.thoughtcrime.securesms.messages.SignalServiceProtoUtil.groupId import org.thoughtcrime.securesms.messages.SignalServiceProtoUtil.toPointer -import org.thoughtcrime.securesms.mms.IncomingMediaMessage +import org.thoughtcrime.securesms.mms.IncomingMessage import org.thoughtcrime.securesms.mms.MmsException import org.thoughtcrime.securesms.recipients.Recipient import org.thoughtcrime.securesms.stories.Stories @@ -58,7 +58,7 @@ object StoryMessageProcessor { StoryType.withoutReplies(isTextStory = storyMessage.textAttachment != null) } - val mediaMessage = IncomingMediaMessage( + val mediaMessage = IncomingMessage( from = senderRecipient.id, sentTimeMillis = envelope.timestamp!!, serverTimeMillis = envelope.serverTimestamp!!, diff --git a/app/src/main/java/org/thoughtcrime/securesms/mms/IncomingMediaMessage.kt b/app/src/main/java/org/thoughtcrime/securesms/mms/IncomingMediaMessage.kt deleted file mode 100644 index f915f0c4aa..0000000000 --- a/app/src/main/java/org/thoughtcrime/securesms/mms/IncomingMediaMessage.kt +++ /dev/null @@ -1,145 +0,0 @@ -package org.thoughtcrime.securesms.mms - -import org.thoughtcrime.securesms.attachments.Attachment -import org.thoughtcrime.securesms.attachments.PointerAttachment -import org.thoughtcrime.securesms.contactshare.Contact -import org.thoughtcrime.securesms.database.model.Mention -import org.thoughtcrime.securesms.database.model.ParentStoryId -import org.thoughtcrime.securesms.database.model.StoryType -import org.thoughtcrime.securesms.database.model.databaseprotos.BodyRangeList -import org.thoughtcrime.securesms.database.model.databaseprotos.GiftBadge -import org.thoughtcrime.securesms.groups.GroupId -import org.thoughtcrime.securesms.linkpreview.LinkPreview -import org.thoughtcrime.securesms.recipients.RecipientId -import org.whispersystems.signalservice.api.messages.SignalServiceAttachment -import org.whispersystems.signalservice.api.messages.SignalServiceGroupV2 -import java.util.Optional - -class IncomingMediaMessage( - val from: RecipientId?, - val groupId: GroupId? = null, - val body: String? = null, - val isPushMessage: Boolean = false, - val storyType: StoryType = StoryType.NONE, - val parentStoryId: ParentStoryId? = null, - val isStoryReaction: Boolean = false, - val sentTimeMillis: Long, - val serverTimeMillis: Long, - val receivedTimeMillis: Long, - val subscriptionId: Int = -1, - val expiresIn: Long = 0, - val isExpirationUpdate: Boolean = false, - val quote: QuoteModel? = null, - val isUnidentified: Boolean = false, - val isViewOnce: Boolean = false, - val serverGuid: String? = null, - val messageRanges: BodyRangeList? = null, - attachments: List = emptyList(), - sharedContacts: List = emptyList(), - linkPreviews: List = emptyList(), - mentions: List = emptyList(), - val giftBadge: GiftBadge? = null, - val isPaymentsNotification: Boolean = false, - val isActivatePaymentsRequest: Boolean = false, - val isPaymentsActivated: Boolean = false -) { - - val attachments: List = ArrayList(attachments) - val sharedContacts: List = ArrayList(sharedContacts) - val linkPreviews: List = ArrayList(linkPreviews) - val mentions: List = ArrayList(mentions) - - val isGroupMessage: Boolean = groupId != null - - constructor( - from: RecipientId?, - groupId: Optional, - body: String?, - sentTimeMillis: Long, - serverTimeMillis: Long, - receivedTimeMillis: Long, - attachments: List?, - subscriptionId: Int, - expiresIn: Long, - expirationUpdate: Boolean, - viewOnce: Boolean, - unidentified: Boolean, - sharedContacts: Optional>, - activatePaymentsRequest: Boolean, - paymentsActivated: Boolean - ) : this( - from = from, - groupId = groupId.orElse(null), - body = body, - isPushMessage = false, - sentTimeMillis = sentTimeMillis, - serverTimeMillis = serverTimeMillis, - receivedTimeMillis = receivedTimeMillis, - subscriptionId = subscriptionId, - expiresIn = expiresIn, - isExpirationUpdate = expirationUpdate, - quote = null, - isUnidentified = unidentified, - isViewOnce = viewOnce, - serverGuid = null, - attachments = attachments?.let { ArrayList(it) } ?: emptyList(), - sharedContacts = ArrayList(sharedContacts.orElse(emptyList())), - isActivatePaymentsRequest = activatePaymentsRequest, - isPaymentsActivated = paymentsActivated - ) - - @JvmOverloads - constructor( - from: RecipientId?, - sentTimeMillis: Long, - serverTimeMillis: Long, - receivedTimeMillis: Long, - storyType: StoryType, - parentStoryId: ParentStoryId?, - isStoryReaction: Boolean, - subscriptionId: Int, - expiresIn: Long, - expirationUpdate: Boolean, - viewOnce: Boolean, - unidentified: Boolean, - body: Optional, - group: Optional, - attachments: Optional>, - quote: Optional, - sharedContacts: Optional>, - linkPreviews: Optional>, - mentions: Optional>, - sticker: Optional, - serverGuid: String?, - giftBadge: GiftBadge?, - activatePaymentsRequest: Boolean, - paymentsActivated: Boolean, - messageRanges: BodyRangeList? = null - ) : this( - from = from, - groupId = if (group.isPresent) GroupId.v2(group.get().masterKey) else null, - body = body.orElse(null), - isPushMessage = true, - storyType = storyType, - parentStoryId = parentStoryId, - isStoryReaction = isStoryReaction, - sentTimeMillis = sentTimeMillis, - serverTimeMillis = serverTimeMillis, - receivedTimeMillis = receivedTimeMillis, - subscriptionId = subscriptionId, - expiresIn = expiresIn, - isExpirationUpdate = expirationUpdate, - quote = quote.orElse(null), - isUnidentified = unidentified, - isViewOnce = viewOnce, - serverGuid = serverGuid, - attachments = PointerAttachment.forPointers(attachments).apply { if (sticker.isPresent) add(sticker.get()) }, - sharedContacts = sharedContacts.orElse(emptyList()), - linkPreviews = linkPreviews.orElse(emptyList()), - mentions = mentions.orElse(emptyList()), - giftBadge = giftBadge, - isActivatePaymentsRequest = activatePaymentsRequest, - isPaymentsActivated = paymentsActivated, - messageRanges = messageRanges - ) -} diff --git a/app/src/main/java/org/thoughtcrime/securesms/mms/IncomingMessage.kt b/app/src/main/java/org/thoughtcrime/securesms/mms/IncomingMessage.kt new file mode 100644 index 0000000000..3af8216173 --- /dev/null +++ b/app/src/main/java/org/thoughtcrime/securesms/mms/IncomingMessage.kt @@ -0,0 +1,114 @@ +package org.thoughtcrime.securesms.mms + +import org.thoughtcrime.securesms.attachments.Attachment +import org.thoughtcrime.securesms.contactshare.Contact +import org.thoughtcrime.securesms.database.MessageType +import org.thoughtcrime.securesms.database.model.Mention +import org.thoughtcrime.securesms.database.model.ParentStoryId +import org.thoughtcrime.securesms.database.model.StoryType +import org.thoughtcrime.securesms.database.model.databaseprotos.BodyRangeList +import org.thoughtcrime.securesms.database.model.databaseprotos.DecryptedGroupV2Context +import org.thoughtcrime.securesms.database.model.databaseprotos.GiftBadge +import org.thoughtcrime.securesms.groups.GroupId +import org.thoughtcrime.securesms.linkpreview.LinkPreview +import org.thoughtcrime.securesms.recipients.RecipientId + +class IncomingMessage( + val from: RecipientId, + val groupId: GroupId? = null, + val groupContext: MessageGroupContext? = null, + val body: String? = null, + val isPushMessage: Boolean = false, + val storyType: StoryType = StoryType.NONE, + val parentStoryId: ParentStoryId? = null, + val isStoryReaction: Boolean = false, + val sentTimeMillis: Long, + val serverTimeMillis: Long, + val receivedTimeMillis: Long, + val subscriptionId: Int = -1, + val expiresIn: Long = 0, + val isExpirationUpdate: Boolean = false, + val quote: QuoteModel? = null, + val isUnidentified: Boolean = false, + val isViewOnce: Boolean = false, + val serverGuid: String? = null, + val messageRanges: BodyRangeList? = null, + attachments: List = emptyList(), + sharedContacts: List = emptyList(), + linkPreviews: List = emptyList(), + mentions: List = emptyList(), + val giftBadge: GiftBadge? = null, + val type: MessageType = MessageType.NORMAL +) { + + val attachments: List = ArrayList(attachments) + val sharedContacts: List = ArrayList(sharedContacts) + val linkPreviews: List = ArrayList(linkPreviews) + val mentions: List = ArrayList(mentions) + + val isGroupMessage: Boolean = groupId != null + + companion object { + @JvmStatic + fun identityUpdate(from: RecipientId, sentTimestamp: Long, groupId: GroupId?): IncomingMessage { + return IncomingMessage( + from = from, + sentTimeMillis = sentTimestamp, + serverTimeMillis = -1, + receivedTimeMillis = sentTimestamp, + groupId = groupId, + type = MessageType.IDENTITY_UPDATE + ) + } + + @JvmStatic + fun identityVerified(from: RecipientId, sentTimestamp: Long, groupId: GroupId?): IncomingMessage { + return IncomingMessage( + from = from, + sentTimeMillis = sentTimestamp, + serverTimeMillis = -1, + receivedTimeMillis = sentTimestamp, + groupId = groupId, + type = MessageType.IDENTITY_VERIFIED + ) + } + + @JvmStatic + fun identityDefault(from: RecipientId, sentTimestamp: Long, groupId: GroupId?): IncomingMessage { + return IncomingMessage( + from = from, + sentTimeMillis = sentTimestamp, + serverTimeMillis = -1, + receivedTimeMillis = sentTimestamp, + groupId = groupId, + type = MessageType.IDENTITY_DEFAULT + ) + } + + fun contactJoined(from: RecipientId, currentTime: Long): IncomingMessage { + return IncomingMessage( + from = from, + sentTimeMillis = currentTime, + serverTimeMillis = -1, + receivedTimeMillis = currentTime, + type = MessageType.CONTACT_JOINED + ) + } + + @JvmStatic + fun groupUpdate(from: RecipientId, timestamp: Long, groupId: GroupId, groupContext: DecryptedGroupV2Context): IncomingMessage { + val messageGroupContext = MessageGroupContext(groupContext) + + return IncomingMessage( + from = from, + sentTimeMillis = timestamp, + receivedTimeMillis = timestamp, + serverTimeMillis = timestamp, + groupId = groupId, + groupContext = messageGroupContext, + body = messageGroupContext.encodedGroupContext, + type = MessageType.GROUP_UPDATE + ) + } + } +} diff --git a/app/src/main/java/org/thoughtcrime/securesms/releasechannel/ReleaseChannel.kt b/app/src/main/java/org/thoughtcrime/securesms/releasechannel/ReleaseChannel.kt index 454808edb4..2508a48feb 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/releasechannel/ReleaseChannel.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/releasechannel/ReleaseChannel.kt @@ -5,7 +5,7 @@ import org.thoughtcrime.securesms.database.MessageTable import org.thoughtcrime.securesms.database.SignalDatabase import org.thoughtcrime.securesms.database.model.StoryType import org.thoughtcrime.securesms.database.model.databaseprotos.BodyRangeList -import org.thoughtcrime.securesms.mms.IncomingMediaMessage +import org.thoughtcrime.securesms.mms.IncomingMessage import org.thoughtcrime.securesms.recipients.RecipientId import org.thoughtcrime.securesms.util.MediaUtil import org.whispersystems.signalservice.api.messages.SignalServiceAttachment @@ -60,7 +60,7 @@ object ReleaseChannel { Optional.empty() } - val message = IncomingMediaMessage( + val message = IncomingMessage( from = recipientId, sentTimeMillis = System.currentTimeMillis(), serverTimeMillis = System.currentTimeMillis(), diff --git a/app/src/main/java/org/thoughtcrime/securesms/sms/IncomingEncryptedMessage.java b/app/src/main/java/org/thoughtcrime/securesms/sms/IncomingEncryptedMessage.java deleted file mode 100644 index 66586a68b9..0000000000 --- a/app/src/main/java/org/thoughtcrime/securesms/sms/IncomingEncryptedMessage.java +++ /dev/null @@ -1,13 +0,0 @@ -package org.thoughtcrime.securesms.sms; - -public class IncomingEncryptedMessage extends IncomingTextMessage { - - public IncomingEncryptedMessage(IncomingTextMessage base, String newBody) { - super(base, newBody); - } - - @Override - public boolean isSecureMessage() { - return true; - } -} diff --git a/app/src/main/java/org/thoughtcrime/securesms/sms/IncomingEndSessionMessage.java b/app/src/main/java/org/thoughtcrime/securesms/sms/IncomingEndSessionMessage.java deleted file mode 100644 index c870ed44f6..0000000000 --- a/app/src/main/java/org/thoughtcrime/securesms/sms/IncomingEndSessionMessage.java +++ /dev/null @@ -1,17 +0,0 @@ -package org.thoughtcrime.securesms.sms; - -public class IncomingEndSessionMessage extends IncomingTextMessage { - - public IncomingEndSessionMessage(IncomingTextMessage base) { - this(base, base.getMessageBody()); - } - - public IncomingEndSessionMessage(IncomingTextMessage base, String newBody) { - super(base, newBody); - } - - @Override - public boolean isEndSession() { - return true; - } -} diff --git a/app/src/main/java/org/thoughtcrime/securesms/sms/IncomingGroupUpdateMessage.java b/app/src/main/java/org/thoughtcrime/securesms/sms/IncomingGroupUpdateMessage.java deleted file mode 100644 index d9836cca68..0000000000 --- a/app/src/main/java/org/thoughtcrime/securesms/sms/IncomingGroupUpdateMessage.java +++ /dev/null @@ -1,55 +0,0 @@ -package org.thoughtcrime.securesms.sms; - -import org.thoughtcrime.securesms.database.model.databaseprotos.DecryptedGroupV2Context; -import org.thoughtcrime.securesms.mms.MessageGroupContext; -import org.whispersystems.signalservice.api.push.ServiceId; - -import java.util.Optional; - -public final class IncomingGroupUpdateMessage extends IncomingTextMessage { - - private final MessageGroupContext groupContext; - - public IncomingGroupUpdateMessage(IncomingTextMessage base, DecryptedGroupV2Context groupV2Context) { - this(base, new MessageGroupContext(groupV2Context)); - } - - public IncomingGroupUpdateMessage(IncomingTextMessage base, MessageGroupContext groupContext) { - super(base, groupContext.getEncodedGroupContext()); - this.groupContext = groupContext; - } - - @Override - public boolean isGroup() { - return true; - } - - public boolean isUpdate() { - return GroupV2UpdateMessageUtil.isUpdate(groupContext) || groupContext.requireGroupV1Properties().isUpdate(); - } - - public boolean isGroupV2() { - return GroupV2UpdateMessageUtil.isGroupV2(groupContext); - } - - public boolean isQuit() { - return !isGroupV2() && groupContext.requireGroupV1Properties().isQuit(); - } - - @Override - public boolean isJustAGroupLeave() { - return GroupV2UpdateMessageUtil.isJustAGroupLeave(groupContext); - } - - public boolean isCancelJoinRequest() { - return GroupV2UpdateMessageUtil.isJoinRequestCancel(groupContext); - } - - public int getChangeRevision() { - return GroupV2UpdateMessageUtil.getChangeRevision(groupContext); - } - - public Optional getChangeEditor() { - return GroupV2UpdateMessageUtil.getChangeEditor(groupContext); - } -} diff --git a/app/src/main/java/org/thoughtcrime/securesms/sms/IncomingIdentityDefaultMessage.java b/app/src/main/java/org/thoughtcrime/securesms/sms/IncomingIdentityDefaultMessage.java deleted file mode 100644 index fc9c75e752..0000000000 --- a/app/src/main/java/org/thoughtcrime/securesms/sms/IncomingIdentityDefaultMessage.java +++ /dev/null @@ -1,15 +0,0 @@ -package org.thoughtcrime.securesms.sms; - - -public class IncomingIdentityDefaultMessage extends IncomingTextMessage { - - public IncomingIdentityDefaultMessage(IncomingTextMessage base) { - super(base, ""); - } - - @Override - public boolean isIdentityDefault() { - return true; - } - -} diff --git a/app/src/main/java/org/thoughtcrime/securesms/sms/IncomingIdentityUpdateMessage.java b/app/src/main/java/org/thoughtcrime/securesms/sms/IncomingIdentityUpdateMessage.java deleted file mode 100644 index c1f1d79e19..0000000000 --- a/app/src/main/java/org/thoughtcrime/securesms/sms/IncomingIdentityUpdateMessage.java +++ /dev/null @@ -1,14 +0,0 @@ -package org.thoughtcrime.securesms.sms; - -public class IncomingIdentityUpdateMessage extends IncomingTextMessage { - - public IncomingIdentityUpdateMessage(IncomingTextMessage base) { - super(base, ""); - } - - @Override - public boolean isIdentityUpdate() { - return true; - } - -} diff --git a/app/src/main/java/org/thoughtcrime/securesms/sms/IncomingIdentityVerifiedMessage.java b/app/src/main/java/org/thoughtcrime/securesms/sms/IncomingIdentityVerifiedMessage.java deleted file mode 100644 index 23a5d51900..0000000000 --- a/app/src/main/java/org/thoughtcrime/securesms/sms/IncomingIdentityVerifiedMessage.java +++ /dev/null @@ -1,15 +0,0 @@ -package org.thoughtcrime.securesms.sms; - - -public class IncomingIdentityVerifiedMessage extends IncomingTextMessage { - - public IncomingIdentityVerifiedMessage(IncomingTextMessage base) { - super(base, ""); - } - - @Override - public boolean isIdentityVerified() { - return true; - } - -} diff --git a/app/src/main/java/org/thoughtcrime/securesms/sms/IncomingJoinedMessage.java b/app/src/main/java/org/thoughtcrime/securesms/sms/IncomingJoinedMessage.java deleted file mode 100644 index 93e68a3822..0000000000 --- a/app/src/main/java/org/thoughtcrime/securesms/sms/IncomingJoinedMessage.java +++ /dev/null @@ -1,24 +0,0 @@ -package org.thoughtcrime.securesms.sms; - -import org.thoughtcrime.securesms.recipients.RecipientId; - -import java.util.Optional; - - -public class IncomingJoinedMessage extends IncomingTextMessage { - - public IncomingJoinedMessage(RecipientId sender) { - super(sender, 1, System.currentTimeMillis(), -1, System.currentTimeMillis(), null, Optional.empty(), 0, false, null); - } - - @Override - public boolean isJoined() { - return true; - } - - @Override - public boolean isSecureMessage() { - return true; - } - -} diff --git a/app/src/main/java/org/thoughtcrime/securesms/sms/IncomingTextMessage.java b/app/src/main/java/org/thoughtcrime/securesms/sms/IncomingTextMessage.java deleted file mode 100644 index ee24084145..0000000000 --- a/app/src/main/java/org/thoughtcrime/securesms/sms/IncomingTextMessage.java +++ /dev/null @@ -1,294 +0,0 @@ -package org.thoughtcrime.securesms.sms; - -import android.os.Parcel; -import android.os.Parcelable; -import android.telephony.SmsMessage; - -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; - -import org.signal.core.util.logging.Log; -import org.thoughtcrime.securesms.groups.GroupId; -import org.thoughtcrime.securesms.recipients.RecipientId; -import org.whispersystems.signalservice.api.push.SignalServiceAddress; - -import java.util.List; -import java.util.Optional; - -public class IncomingTextMessage implements Parcelable { - - public static final Parcelable.Creator CREATOR = new Parcelable.Creator() { - @Override - public IncomingTextMessage createFromParcel(Parcel in) { - return new IncomingTextMessage(in); - } - - @Override - public IncomingTextMessage[] newArray(int size) { - return new IncomingTextMessage[size]; - } - }; - private static final String TAG = Log.tag(IncomingTextMessage.class); - - private final String message; - private final RecipientId authorId; - private final int senderDeviceId; - private final int protocol; - private final String serviceCenterAddress; - private final boolean replyPathPresent; - private final String pseudoSubject; - private final long sentTimestampMillis; - private final long serverTimestampMillis; - private final long receivedTimestampMillis; - @Nullable private final GroupId groupId; - private final boolean push; - private final int subscriptionId; - private final long expiresInMillis; - private final boolean unidentified; - @Nullable private final String serverGuid; - - public IncomingTextMessage(@NonNull RecipientId authorId, @NonNull SmsMessage message, int subscriptionId) { - this.message = message.getDisplayMessageBody(); - this.authorId = authorId; - this.senderDeviceId = SignalServiceAddress.DEFAULT_DEVICE_ID; - this.protocol = message.getProtocolIdentifier(); - this.serviceCenterAddress = message.getServiceCenterAddress(); - this.replyPathPresent = message.isReplyPathPresent(); - this.pseudoSubject = message.getPseudoSubject(); - this.sentTimestampMillis = message.getTimestampMillis(); - this.serverTimestampMillis = -1; - this.receivedTimestampMillis = System.currentTimeMillis(); - this.subscriptionId = subscriptionId; - this.expiresInMillis = 0; - this.groupId = null; - this.push = false; - this.unidentified = false; - this.serverGuid = null; - } - - public IncomingTextMessage(@NonNull RecipientId authorId, - int senderDeviceId, - long sentTimestampMillis, - long serverTimestampMillis, - long receivedTimestampMillis, - String encodedBody, - Optional groupId, - long expiresInMillis, - boolean unidentified, - String serverGuid) - { - this.message = encodedBody; - this.authorId = authorId; - this.senderDeviceId = senderDeviceId; - this.protocol = 31337; - this.serviceCenterAddress = "GCM"; - this.replyPathPresent = true; - this.pseudoSubject = ""; - this.sentTimestampMillis = sentTimestampMillis; - this.serverTimestampMillis = serverTimestampMillis; - this.receivedTimestampMillis = receivedTimestampMillis; - this.push = true; - this.subscriptionId = -1; - this.expiresInMillis = expiresInMillis; - this.unidentified = unidentified; - this.groupId = groupId.orElse(null); - this.serverGuid = serverGuid; - } - - public IncomingTextMessage(Parcel in) { - this.message = in.readString(); - this.authorId = in.readParcelable(IncomingTextMessage.class.getClassLoader()); - this.senderDeviceId = in.readInt(); - this.protocol = in.readInt(); - this.serviceCenterAddress = in.readString(); - this.replyPathPresent = (in.readInt() == 1); - this.pseudoSubject = in.readString(); - this.sentTimestampMillis = in.readLong(); - this.serverTimestampMillis = in.readLong(); - this.receivedTimestampMillis = in.readLong(); - this.groupId = GroupId.parseNullableOrThrow(in.readString()); - this.push = (in.readInt() == 1); - this.subscriptionId = in.readInt(); - this.expiresInMillis = in.readLong(); - this.unidentified = in.readInt() == 1; - this.serverGuid = in.readString(); - } - - public IncomingTextMessage(IncomingTextMessage base, String newBody) { - this.message = newBody; - this.authorId = base.getAuthorId(); - this.senderDeviceId = base.getAuthorDeviceId(); - this.protocol = base.getProtocol(); - this.serviceCenterAddress = base.getServiceCenterAddress(); - this.replyPathPresent = base.isReplyPathPresent(); - this.pseudoSubject = base.getPseudoSubject(); - this.sentTimestampMillis = base.getSentTimestampMillis(); - this.serverTimestampMillis = base.getServerTimestampMillis(); - this.receivedTimestampMillis = base.getReceivedTimestampMillis(); - this.groupId = base.getGroupId(); - this.push = base.isPush(); - this.subscriptionId = base.getSubscriptionId(); - this.expiresInMillis = base.getExpiresIn(); - this.unidentified = base.isUnidentified(); - this.serverGuid = base.getServerGuid(); - } - - public IncomingTextMessage(List fragments) { - StringBuilder body = new StringBuilder(); - - for (IncomingTextMessage message : fragments) { - body.append(message.getMessageBody()); - } - - this.message = body.toString(); - this.authorId = fragments.get(0).getAuthorId(); - this.senderDeviceId = fragments.get(0).getAuthorDeviceId(); - this.protocol = fragments.get(0).getProtocol(); - this.serviceCenterAddress = fragments.get(0).getServiceCenterAddress(); - this.replyPathPresent = fragments.get(0).isReplyPathPresent(); - this.pseudoSubject = fragments.get(0).getPseudoSubject(); - this.sentTimestampMillis = fragments.get(0).getSentTimestampMillis(); - this.serverTimestampMillis = fragments.get(0).getServerTimestampMillis(); - this.receivedTimestampMillis = fragments.get(0).getReceivedTimestampMillis(); - this.groupId = fragments.get(0).getGroupId(); - this.push = fragments.get(0).isPush(); - this.subscriptionId = fragments.get(0).getSubscriptionId(); - this.expiresInMillis = fragments.get(0).getExpiresIn(); - this.unidentified = fragments.get(0).isUnidentified(); - this.serverGuid = fragments.get(0).getServerGuid(); - } - - public int getSubscriptionId() { - return subscriptionId; - } - - public long getExpiresIn() { - return expiresInMillis; - } - - public long getSentTimestampMillis() { - return sentTimestampMillis; - } - - public long getServerTimestampMillis() { - return serverTimestampMillis; - } - - public long getReceivedTimestampMillis() { - return receivedTimestampMillis; - } - - public String getPseudoSubject() { - return pseudoSubject; - } - - public String getMessageBody() { - return message; - } - - public RecipientId getAuthorId() { - return authorId; - } - - public int getAuthorDeviceId() { - return senderDeviceId; - } - - public int getProtocol() { - return protocol; - } - - public String getServiceCenterAddress() { - return serviceCenterAddress; - } - - public boolean isReplyPathPresent() { - return replyPathPresent; - } - - public boolean isSecureMessage() { - return false; - } - - public boolean isPreKeyBundle() { - return isLegacyPreKeyBundle() || isContentPreKeyBundle(); - } - - public boolean isLegacyPreKeyBundle() { - return false; - } - - public boolean isContentPreKeyBundle() { - return false; - } - - public boolean isEndSession() { - return false; - } - - public boolean isPush() { - return push; - } - - public @Nullable GroupId getGroupId() { - return groupId; - } - - public boolean isGroup() { - return false; - } - - public boolean isJoined() { - return false; - } - - public boolean isIdentityUpdate() { - return false; - } - - public boolean isIdentityVerified() { - return false; - } - - public boolean isIdentityDefault() { - return false; - } - - /** - * @return True iff the message is only a group leave of a single member. - */ - public boolean isJustAGroupLeave() { - return false; - } - - public boolean isUnidentified() { - return unidentified; - } - - public @Nullable String getServerGuid() { - return serverGuid; - } - - @Override - public int describeContents() { - return 0; - } - - @Override - public void writeToParcel(Parcel out, int flags) { - out.writeString(message); - out.writeParcelable(authorId, flags); - out.writeInt(senderDeviceId); - out.writeInt(protocol); - out.writeString(serviceCenterAddress); - out.writeInt(replyPathPresent ? 1 : 0); - out.writeString(pseudoSubject); - out.writeLong(sentTimestampMillis); - out.writeString(groupId == null ? null : groupId.toString()); - out.writeInt(push ? 1 : 0); - out.writeInt(subscriptionId); - out.writeLong(expiresInMillis); - out.writeInt(unidentified ? 1 : 0); - out.writeString(serverGuid); - } -} diff --git a/app/src/main/java/org/thoughtcrime/securesms/util/IdentityUtil.java b/app/src/main/java/org/thoughtcrime/securesms/util/IdentityUtil.java index a575a01626..61e06c0960 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/util/IdentityUtil.java +++ b/app/src/main/java/org/thoughtcrime/securesms/util/IdentityUtil.java @@ -25,15 +25,12 @@ import org.thoughtcrime.securesms.database.SignalDatabase; import org.thoughtcrime.securesms.database.model.GroupRecord; import org.thoughtcrime.securesms.database.model.IdentityRecord; import org.thoughtcrime.securesms.dependencies.ApplicationDependencies; +import org.thoughtcrime.securesms.mms.IncomingMessage; import org.thoughtcrime.securesms.mms.MmsException; import org.thoughtcrime.securesms.mms.OutgoingMessage; import org.thoughtcrime.securesms.notifications.v2.ConversationId; import org.thoughtcrime.securesms.recipients.Recipient; import org.thoughtcrime.securesms.recipients.RecipientId; -import org.thoughtcrime.securesms.sms.IncomingIdentityDefaultMessage; -import org.thoughtcrime.securesms.sms.IncomingIdentityUpdateMessage; -import org.thoughtcrime.securesms.sms.IncomingIdentityVerifiedMessage; -import org.thoughtcrime.securesms.sms.IncomingTextMessage; import org.thoughtcrime.securesms.util.concurrent.ListenableFuture; import org.thoughtcrime.securesms.util.concurrent.SettableFuture; import org.whispersystems.signalservice.api.SignalSessionLock; @@ -76,12 +73,14 @@ public final class IdentityUtil { if (groupRecord.getMembers().contains(recipient.getId()) && groupRecord.isActive() && !groupRecord.isMms()) { if (remote) { - IncomingTextMessage incoming = new IncomingTextMessage(recipient.getId(), 1, time, -1, time, null, Optional.of(groupRecord.getId()), 0, false, null); + IncomingMessage incoming = verified ? IncomingMessage.identityVerified(recipient.getId(), time, groupRecord.getId()) + : IncomingMessage.identityDefault(recipient.getId(), time, groupRecord.getId()); - if (verified) incoming = new IncomingIdentityVerifiedMessage(incoming); - else incoming = new IncomingIdentityDefaultMessage(incoming); - - smsDatabase.insertMessageInbox(incoming); + try { + smsDatabase.insertMessageInbox(incoming); + } catch (MmsException e) { + throw new AssertionError(e); + } } else { RecipientId recipientId = SignalDatabase.recipients().getOrInsertFromGroupId(groupRecord.getId()); Recipient groupRecipient = Recipient.resolved(recipientId); @@ -106,12 +105,14 @@ public final class IdentityUtil { } if (remote) { - IncomingTextMessage incoming = new IncomingTextMessage(recipient.getId(), 1, time, -1, time, null, Optional.empty(), 0, false, null); + IncomingMessage incoming = verified ? IncomingMessage.identityVerified(recipient.getId(), time, null) + : IncomingMessage.identityDefault(recipient.getId(), time, null); - if (verified) incoming = new IncomingIdentityVerifiedMessage(incoming); - else incoming = new IncomingIdentityDefaultMessage(incoming); - - smsDatabase.insertMessageInbox(incoming); + try { + smsDatabase.insertMessageInbox(incoming); + } catch (MmsException e) { + throw new AssertionError(e); + } } else { OutgoingMessage outgoing; if (verified) { @@ -144,21 +145,25 @@ public final class IdentityUtil { while ((groupRecord = reader.getNext()) != null) { if (groupRecord.getMembers().contains(recipientId) && groupRecord.isActive()) { - IncomingTextMessage incoming = new IncomingTextMessage(recipientId, 1, time, time, time, null, Optional.of(groupRecord.getId()), 0, false, null); - IncomingIdentityUpdateMessage groupUpdate = new IncomingIdentityUpdateMessage(incoming); - + IncomingMessage groupUpdate = IncomingMessage.identityUpdate(recipientId, time, groupRecord.getId()); smsDatabase.insertMessageInbox(groupUpdate); } } + } catch (MmsException e) { + throw new AssertionError(e); } - IncomingTextMessage incoming = new IncomingTextMessage(recipientId, 1, time, -1, time, null, Optional.empty(), 0, false, null); - IncomingIdentityUpdateMessage individualUpdate = new IncomingIdentityUpdateMessage(incoming); - Optional insertResult = smsDatabase.insertMessageInbox(individualUpdate); + try { + IncomingMessage individualUpdate = IncomingMessage.identityUpdate(recipientId, time, null); + Optional insertResult = smsDatabase.insertMessageInbox(individualUpdate); - if (insertResult.isPresent()) { - ApplicationDependencies.getMessageNotifier().updateNotification(context, ConversationId.forConversation(insertResult.get().getThreadId())); + if (insertResult.isPresent()) { + ApplicationDependencies.getMessageNotifier().updateNotification(context, ConversationId.forConversation(insertResult.get().getThreadId())); + } + } catch (MmsException e) { + throw new AssertionError(e); } + } public static void saveIdentity(String user, IdentityKey identityKey) { diff --git a/app/src/spinner/java/org/thoughtcrime/securesms/database/MessageBitmaskColumnTransformer.kt b/app/src/spinner/java/org/thoughtcrime/securesms/database/MessageBitmaskColumnTransformer.kt index 4cb6bbee1a..50678e6eec 100644 --- a/app/src/spinner/java/org/thoughtcrime/securesms/database/MessageBitmaskColumnTransformer.kt +++ b/app/src/spinner/java/org/thoughtcrime/securesms/database/MessageBitmaskColumnTransformer.kt @@ -35,8 +35,6 @@ import org.thoughtcrime.securesms.database.MessageTypes.INVALID_MESSAGE_TYPE import org.thoughtcrime.securesms.database.MessageTypes.JOINED_TYPE import org.thoughtcrime.securesms.database.MessageTypes.KEY_EXCHANGE_BIT import org.thoughtcrime.securesms.database.MessageTypes.KEY_EXCHANGE_BUNDLE_BIT -import org.thoughtcrime.securesms.database.MessageTypes.KEY_EXCHANGE_CONTENT_FORMAT -import org.thoughtcrime.securesms.database.MessageTypes.KEY_EXCHANGE_CORRUPTED_BIT import org.thoughtcrime.securesms.database.MessageTypes.KEY_EXCHANGE_IDENTITY_DEFAULT_BIT import org.thoughtcrime.securesms.database.MessageTypes.KEY_EXCHANGE_IDENTITY_UPDATE_BIT import org.thoughtcrime.securesms.database.MessageTypes.KEY_EXCHANGE_IDENTITY_VERIFIED_BIT @@ -100,10 +98,8 @@ object MessageBitmaskColumnTransformer : ColumnTransformer { isKeyExchangeType:${type and KEY_EXCHANGE_BIT != 0L} isIdentityVerified:${type and KEY_EXCHANGE_IDENTITY_VERIFIED_BIT != 0L} isIdentityDefault:${type and KEY_EXCHANGE_IDENTITY_DEFAULT_BIT != 0L} - isCorruptedKeyExchange:${type and KEY_EXCHANGE_CORRUPTED_BIT != 0L} isInvalidVersionKeyExchange:${type and KEY_EXCHANGE_INVALID_VERSION_BIT != 0L} isBundleKeyExchange:${type and KEY_EXCHANGE_BUNDLE_BIT != 0L} - isContentBundleKeyExchange:${type and KEY_EXCHANGE_CONTENT_FORMAT != 0L} isIdentityUpdate:${type and KEY_EXCHANGE_IDENTITY_UPDATE_BIT != 0L} isRateLimited:${type and MESSAGE_RATE_LIMITED_BIT != 0L} isExpirationTimerUpdate:${type and EXPIRATION_TIMER_UPDATE_BIT != 0L} diff --git a/app/src/test/java/org/thoughtcrime/securesms/database/TestSms.kt b/app/src/test/java/org/thoughtcrime/securesms/database/TestSms.kt index 1e9e301eb3..cc4d8fe6a0 100644 --- a/app/src/test/java/org/thoughtcrime/securesms/database/TestSms.kt +++ b/app/src/test/java/org/thoughtcrime/securesms/database/TestSms.kt @@ -1,9 +1,10 @@ package org.thoughtcrime.securesms.database import android.content.ContentValues +import org.signal.core.util.orNull import org.thoughtcrime.securesms.groups.GroupId +import org.thoughtcrime.securesms.mms.IncomingMessage import org.thoughtcrime.securesms.recipients.RecipientId -import org.thoughtcrime.securesms.sms.IncomingTextMessage import java.util.Optional import java.util.UUID import android.database.sqlite.SQLiteDatabase as AndroidSQLiteDatabase @@ -29,17 +30,16 @@ object TestSms { unread: Boolean = false, threadId: Long = 1 ): Long { - val message = IncomingTextMessage( - sender, - senderDeviceId, - sentTimestampMillis, - serverTimestampMillis, - receivedTimestampMillis, - encodedBody, - groupId, - expiresInMillis, - unidentified, - serverGuid + val message = IncomingMessage( + from = sender, + sentTimeMillis = sentTimestampMillis, + serverTimeMillis = serverTimestampMillis, + receivedTimeMillis = receivedTimestampMillis, + body = encodedBody, + groupId = groupId.orNull(), + expiresIn = expiresInMillis, + isUnidentified = unidentified, + serverGuid = serverGuid ) return insert( @@ -53,23 +53,22 @@ object TestSms { fun insert( db: AndroidSQLiteDatabase, - message: IncomingTextMessage, + message: IncomingMessage, type: Long = MessageTypes.BASE_INBOX_TYPE, unread: Boolean = false, threadId: Long = 1 ): Long { val values = ContentValues().apply { - put(MessageTable.FROM_RECIPIENT_ID, message.authorId.serialize()) - put(MessageTable.FROM_DEVICE_ID, message.authorDeviceId) - put(MessageTable.TO_RECIPIENT_ID, message.authorId.serialize()) - put(MessageTable.DATE_RECEIVED, message.receivedTimestampMillis) - put(MessageTable.DATE_SENT, message.sentTimestampMillis) - put(MessageTable.DATE_SERVER, message.serverTimestampMillis) + put(MessageTable.FROM_RECIPIENT_ID, message.from.serialize()) + put(MessageTable.TO_RECIPIENT_ID, message.from.serialize()) + put(MessageTable.DATE_RECEIVED, message.receivedTimeMillis) + put(MessageTable.DATE_SENT, message.sentTimeMillis) + put(MessageTable.DATE_SERVER, message.serverTimeMillis) put(MessageTable.READ, if (unread) 0 else 1) put(MessageTable.SMS_SUBSCRIPTION_ID, message.subscriptionId) put(MessageTable.EXPIRES_IN, message.expiresIn) put(MessageTable.UNIDENTIFIED, message.isUnidentified) - put(MessageTable.BODY, message.messageBody) + put(MessageTable.BODY, message.body) put(MessageTable.TYPE, type) put(MessageTable.THREAD_ID, threadId) put(MessageTable.SERVER_GUID, message.serverGuid)