From 7d8f780d60617ba44f794d54f0e0d72cd8f5130a Mon Sep 17 00:00:00 2001 From: Greyson Parrelli Date: Tue, 27 Jul 2021 13:52:49 -0400 Subject: [PATCH] Clean up bookkeeping around threads. --- .../expire/ExpireTimerSettingsRepository.kt | 2 +- .../conversation/ConversationActivity.java | 4 +--- .../securesms/database/MmsDatabase.java | 6 ++--- .../securesms/database/SmsDatabase.java | 12 +++++----- .../securesms/database/SmsMigrator.java | 4 ++-- .../securesms/database/ThreadDatabase.java | 12 +++++----- .../database/helpers/SQLCipherOpenHelper.java | 8 ++++++- .../loaders/RecipientMediaLoader.java | 2 +- .../securesms/groups/GroupManagerV1.java | 8 +++---- .../securesms/groups/GroupManagerV2.java | 2 +- .../groups/GroupV1MessageProcessor.java | 2 +- .../groups/GroupsV1MigrationUtil.java | 2 +- .../v2/processing/GroupsV2StateProcessor.java | 4 ++-- .../invites/InviteReminderModel.java | 2 +- .../messages/MessageContentProcessor.java | 24 +++++++++---------- .../messages/MessageDecryptionUtil.java | 4 ++-- .../migrations/ApplicationMigrations.java | 7 +++++- .../securesms/recipients/RecipientUtil.java | 24 +++++++++++-------- .../service/webrtc/SignalCallManager.java | 2 +- .../securesms/sms/MessageSender.java | 6 ++--- .../securesms/util/CommunicationActions.java | 6 ++--- .../securesms/util/ConversationUtil.java | 4 ++-- .../securesms/util/IdentityUtil.java | 4 ++-- 23 files changed, 81 insertions(+), 70 deletions(-) diff --git a/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/privacy/expire/ExpireTimerSettingsRepository.kt b/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/privacy/expire/ExpireTimerSettingsRepository.kt index 85af24ef04..37878a692b 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/privacy/expire/ExpireTimerSettingsRepository.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/components/settings/app/privacy/expire/ExpireTimerSettingsRepository.kt @@ -48,6 +48,6 @@ class ExpireTimerSettingsRepository(val context: Context) { private fun getThreadId(recipientId: RecipientId): Long { val threadDatabase: ThreadDatabase = DatabaseFactory.getThreadDatabase(context) val recipient: Recipient = Recipient.resolved(recipientId) - return threadDatabase.getThreadIdFor(recipient) + return threadDatabase.getOrCreateThreadIdFor(recipient) } } diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationActivity.java b/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationActivity.java index 4c0f017ff4..658daf55e9 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationActivity.java +++ b/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationActivity.java @@ -25,7 +25,6 @@ import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.content.pm.ActivityInfo; -import android.content.pm.ShortcutManager; import android.content.res.Configuration; import android.graphics.Bitmap; import android.graphics.Color; @@ -87,7 +86,6 @@ import com.bumptech.glide.load.engine.DiskCacheStrategy; import com.bumptech.glide.request.target.CustomTarget; import com.bumptech.glide.request.transition.Transition; import com.google.android.material.button.MaterialButton; -import com.google.android.material.dialog.MaterialAlertDialogBuilder; import org.greenrobot.eventbus.EventBus; import org.greenrobot.eventbus.Subscribe; @@ -2650,7 +2648,7 @@ public class ConversationActivity extends PassphraseRequiredActivity long threadId = params[0]; if (drafts.size() > 0) { - if (threadId == -1) threadId = threadDatabase.getThreadIdFor(getRecipient(), thisDistributionType); + if (threadId == -1) threadId = threadDatabase.getOrCreateThreadIdFor(getRecipient(), thisDistributionType); draftDatabase.replaceDrafts(threadId, drafts); threadDatabase.updateSnippet(threadId, drafts.getSnippet(ConversationActivity.this), diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/MmsDatabase.java b/app/src/main/java/org/thoughtcrime/securesms/database/MmsDatabase.java index a474520912..fc16d2745a 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/MmsDatabase.java +++ b/app/src/main/java/org/thoughtcrime/securesms/database/MmsDatabase.java @@ -697,10 +697,10 @@ public class MmsDatabase extends MessageDatabase { if (retrieved.getGroupId() != null) { RecipientId groupRecipientId = DatabaseFactory.getRecipientDatabase(context).getOrInsertFromPossiblyMigratedGroupId(retrieved.getGroupId()); Recipient groupRecipients = Recipient.resolved(groupRecipientId); - return DatabaseFactory.getThreadDatabase(context).getThreadIdFor(groupRecipients); + return DatabaseFactory.getThreadDatabase(context).getOrCreateThreadIdFor(groupRecipients); } else { Recipient sender = Recipient.resolved(retrieved.getFrom()); - return DatabaseFactory.getThreadDatabase(context).getThreadIdFor(sender); + return DatabaseFactory.getThreadDatabase(context).getOrCreateThreadIdFor(sender); } } @@ -709,7 +709,7 @@ public class MmsDatabase extends MessageDatabase { ? Util.toIsoString(notification.getFrom().getTextString()) : ""; Recipient recipient = Recipient.external(context, fromString); - return DatabaseFactory.getThreadDatabase(context).getThreadIdFor(recipient); + return DatabaseFactory.getThreadDatabase(context).getOrCreateThreadIdFor(recipient); } private Cursor rawQuery(@NonNull String where, @Nullable String[] arguments) { diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/SmsDatabase.java b/app/src/main/java/org/thoughtcrime/securesms/database/SmsDatabase.java index 638dc7136f..053c9e8e09 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/SmsDatabase.java +++ b/app/src/main/java/org/thoughtcrime/securesms/database/SmsDatabase.java @@ -741,7 +741,7 @@ public class SmsDatabase extends MessageDatabase { { SQLiteDatabase db = databaseHelper.getWritableDatabase(); Recipient recipient = Recipient.resolved(groupRecipientId); - long threadId = DatabaseFactory.getThreadDatabase(context).getThreadIdFor(recipient); + long threadId = DatabaseFactory.getThreadDatabase(context).getOrCreateThreadIdFor(recipient); boolean peerEraIdSameAsPrevious = updatePreviousGroupCall(threadId, peekGroupCallEraId, peekJoinedUuids, isCallFull); try { @@ -803,7 +803,7 @@ public class SmsDatabase extends MessageDatabase { Recipient recipient = Recipient.resolved(groupRecipientId); - threadId = DatabaseFactory.getThreadDatabase(context).getThreadIdFor(recipient); + threadId = DatabaseFactory.getThreadDatabase(context).getOrCreateThreadIdFor(recipient); String where = TYPE + " = ? AND " + THREAD_ID + " = ?"; String[] args = SqlUtil.buildArgs(Types.GROUP_CALL_TYPE, threadId); @@ -908,7 +908,7 @@ public class SmsDatabase extends MessageDatabase { private @NonNull Pair insertCallLog(@NonNull RecipientId recipientId, long type, boolean unread, long timestamp) { Recipient recipient = Recipient.resolved(recipientId); - long threadId = DatabaseFactory.getThreadDatabase(context).getThreadIdFor(recipient); + long threadId = DatabaseFactory.getThreadDatabase(context).getOrCreateThreadIdFor(recipient); ContentValues values = new ContentValues(6); values.put(RECIPIENT_ID, recipientId.serialize()); @@ -1108,8 +1108,8 @@ public class SmsDatabase extends MessageDatabase { long threadId; - if (groupRecipient == null) threadId = DatabaseFactory.getThreadDatabase(context).getThreadIdFor(recipient); - else threadId = DatabaseFactory.getThreadDatabase(context).getThreadIdFor(groupRecipient); + if (groupRecipient == null) threadId = DatabaseFactory.getThreadDatabase(context).getOrCreateThreadIdFor(recipient); + else threadId = DatabaseFactory.getThreadDatabase(context).getOrCreateThreadIdFor(groupRecipient); ContentValues values = new ContentValues(); values.put(RECIPIENT_ID, message.getSender().serialize()); @@ -1170,7 +1170,7 @@ public class SmsDatabase extends MessageDatabase { @Override public @NonNull InsertResult insertChatSessionRefreshedMessage(@NonNull RecipientId recipientId, long senderDeviceId, long sentTimestamp) { SQLiteDatabase db = databaseHelper.getWritableDatabase(); - long threadId = DatabaseFactory.getThreadDatabase(context).getThreadIdFor(Recipient.resolved(recipientId)); + long threadId = DatabaseFactory.getThreadDatabase(context).getOrCreateThreadIdFor(Recipient.resolved(recipientId)); long type = Types.SECURE_MESSAGE_BIT | Types.PUSH_MESSAGE_BIT; type = type & (Types.TOTAL_MASK - Types.ENCRYPTION_MASK) | Types.ENCRYPTION_REMOTE_FAILED_BIT; diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/SmsMigrator.java b/app/src/main/java/org/thoughtcrime/securesms/database/SmsMigrator.java index 63e14d8028..ef4dac9308 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/SmsMigrator.java +++ b/app/src/main/java/org/thoughtcrime/securesms/database/SmsMigrator.java @@ -225,7 +225,7 @@ public class SmsMigrator { if (ourRecipients != null) { if (ourRecipients.size() == 1) { - long ourThreadId = threadDatabase.getThreadIdFor(ourRecipients.iterator().next()); + long ourThreadId = threadDatabase.getOrCreateThreadIdFor(ourRecipients.iterator().next()); migrateConversation(context, listener, progress, theirThreadId, ourThreadId); } else if (ourRecipients.size() > 1) { ourRecipients.add(Recipient.self()); @@ -235,7 +235,7 @@ public class SmsMigrator { GroupId.Mms ourGroupId = DatabaseFactory.getGroupDatabase(context).getOrCreateMmsGroupForMembers(recipientIds); RecipientId ourGroupRecipientId = DatabaseFactory.getRecipientDatabase(context).getOrInsertFromGroupId(ourGroupId); Recipient ourGroupRecipient = Recipient.resolved(ourGroupRecipientId); - long ourThreadId = threadDatabase.getThreadIdFor(ourGroupRecipient, ThreadDatabase.DistributionTypes.CONVERSATION); + long ourThreadId = threadDatabase.getOrCreateThreadIdFor(ourGroupRecipient, ThreadDatabase.DistributionTypes.CONVERSATION); migrateConversation(context, listener, progress, theirThreadId, ourThreadId); } diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/ThreadDatabase.java b/app/src/main/java/org/thoughtcrime/securesms/database/ThreadDatabase.java index 6cbb91a591..cd327c9c1e 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/ThreadDatabase.java +++ b/app/src/main/java/org/thoughtcrime/securesms/database/ThreadDatabase.java @@ -371,7 +371,7 @@ public class ThreadDatabase extends Database { } public boolean hasCalledSince(@NonNull Recipient recipient, long timestamp) { - return hasReceivedAnyCallsSince(getThreadIdFor(recipient), timestamp); + return hasReceivedAnyCallsSince(getOrCreateThreadIdFor(recipient), timestamp); } public boolean hasReceivedAnyCallsSince(long threadId, long timestamp) { @@ -1035,15 +1035,15 @@ public class ThreadDatabase extends Database { return candidateId; } } else { - return getThreadIdFor(recipient, distributionType); + return getOrCreateThreadIdFor(recipient, distributionType); } } - public long getThreadIdFor(@NonNull Recipient recipient) { - return getThreadIdFor(recipient, DistributionTypes.DEFAULT); + public long getOrCreateThreadIdFor(@NonNull Recipient recipient) { + return getOrCreateThreadIdFor(recipient, DistributionTypes.DEFAULT); } - public long getThreadIdFor(@NonNull Recipient recipient, int distributionType) { + public long getOrCreateThreadIdFor(@NonNull Recipient recipient, int distributionType) { Long threadId = getThreadIdFor(recipient.getId()); if (threadId != null) { return threadId; @@ -1260,7 +1260,7 @@ public class ThreadDatabase extends Database { } public @NonNull ThreadRecord getThreadRecordFor(@NonNull Recipient recipient) { - return Objects.requireNonNull(getThreadRecord(getThreadIdFor(recipient))); + return Objects.requireNonNull(getThreadRecord(getOrCreateThreadIdFor(recipient))); } public @NonNull Set getAllThreadRecipients() { diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/helpers/SQLCipherOpenHelper.java b/app/src/main/java/org/thoughtcrime/securesms/database/helpers/SQLCipherOpenHelper.java index 4653c9730e..c25b6afdd1 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/helpers/SQLCipherOpenHelper.java +++ b/app/src/main/java/org/thoughtcrime/securesms/database/helpers/SQLCipherOpenHelper.java @@ -209,8 +209,9 @@ public class SQLCipherOpenHelper extends SQLiteOpenHelper implements SignalDatab private static final int MMS_AUTOINCREMENT = 109; private static final int ABANDONED_ATTACHMENT_CLEANUP = 110; private static final int AVATAR_PICKER = 111; + private static final int THREAD_CLEANUP = 112; - private static final int DATABASE_VERSION = 111; + private static final int DATABASE_VERSION = 112; private static final String DATABASE_NAME = "signal.db"; private final Context context; @@ -1955,6 +1956,11 @@ public class SQLCipherOpenHelper extends SQLiteOpenHelper implements SignalDatab } } + if (oldVersion < THREAD_CLEANUP) { + db.delete("mms", "thread_id NOT IN (SELECT _id FROM thread)", null); + db.delete("part", "mid != -8675309 AND mid NOT IN (SELECT _id FROM mms)", null); + } + db.setTransactionSuccessful(); } finally { db.endTransaction(); diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/loaders/RecipientMediaLoader.java b/app/src/main/java/org/thoughtcrime/securesms/database/loaders/RecipientMediaLoader.java index 3e3e85c008..b991d2110e 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/loaders/RecipientMediaLoader.java +++ b/app/src/main/java/org/thoughtcrime/securesms/database/loaders/RecipientMediaLoader.java @@ -36,7 +36,7 @@ public final class RecipientMediaLoader extends MediaLoader { if (recipientId == null || recipientId.isUnknown()) return null; long threadId = DatabaseFactory.getThreadDatabase(getContext()) - .getThreadIdFor(Recipient.resolved(recipientId)); + .getOrCreateThreadIdFor(Recipient.resolved(recipientId)); return ThreadMediaLoader.createThreadMediaCursor(context, threadId, mediaType, sorting); } diff --git a/app/src/main/java/org/thoughtcrime/securesms/groups/GroupManagerV1.java b/app/src/main/java/org/thoughtcrime/securesms/groups/GroupManagerV1.java index f09f6729d7..9760459d28 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/groups/GroupManagerV1.java +++ b/app/src/main/java/org/thoughtcrime/securesms/groups/GroupManagerV1.java @@ -80,7 +80,7 @@ final class GroupManagerV1 { } groupDatabase.onAvatarUpdated(groupId, avatarBytes != null); - long threadId = DatabaseFactory.getThreadDatabase(context).getThreadIdFor(groupRecipient, ThreadDatabase.DistributionTypes.CONVERSATION); + long threadId = DatabaseFactory.getThreadDatabase(context).getOrCreateThreadIdFor(groupRecipient, ThreadDatabase.DistributionTypes.CONVERSATION); return new GroupActionResult(groupRecipient, threadId, memberIds.size() - 1, Collections.emptyList()); } } @@ -112,7 +112,7 @@ final class GroupManagerV1 { return sendGroupUpdate(context, groupIdV1, memberAddresses, name, avatarBytes, newMemberCount); } else { Recipient groupRecipient = Recipient.resolved(groupRecipientId); - long threadId = DatabaseFactory.getThreadDatabase(context).getThreadIdFor(groupRecipient); + long threadId = DatabaseFactory.getThreadDatabase(context).getOrCreateThreadIdFor(groupRecipient); return new GroupActionResult(groupRecipient, threadId, newMemberCount, Collections.emptyList()); } } @@ -125,7 +125,7 @@ final class GroupManagerV1 { GroupDatabase groupDatabase = DatabaseFactory.getGroupDatabase(context); RecipientId groupRecipientId = DatabaseFactory.getRecipientDatabase(context).getOrInsertFromGroupId(groupId); Recipient groupRecipient = Recipient.resolved(groupRecipientId); - long threadId = DatabaseFactory.getThreadDatabase(context).getThreadIdFor(groupRecipient); + long threadId = DatabaseFactory.getThreadDatabase(context).getOrCreateThreadIdFor(groupRecipient); groupDatabase.updateTitle(groupId, name); groupDatabase.onAvatarUpdated(groupId, avatarBytes != null); @@ -197,7 +197,7 @@ final class GroupManagerV1 { RecipientDatabase recipientDatabase = DatabaseFactory.getRecipientDatabase(context); ThreadDatabase threadDatabase = DatabaseFactory.getThreadDatabase(context); Recipient recipient = Recipient.externalGroupExact(context, groupId); - long threadId = threadDatabase.getThreadIdFor(recipient); + long threadId = threadDatabase.getOrCreateThreadIdFor(recipient); recipientDatabase.setExpireMessages(recipient.getId(), expirationTime); OutgoingExpirationUpdateMessage outgoingMessage = new OutgoingExpirationUpdateMessage(recipient, System.currentTimeMillis(), expirationTime * 1000L); diff --git a/app/src/main/java/org/thoughtcrime/securesms/groups/GroupManagerV2.java b/app/src/main/java/org/thoughtcrime/securesms/groups/GroupManagerV2.java index 4c39a03775..fcfb2a0513 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/groups/GroupManagerV2.java +++ b/app/src/main/java/org/thoughtcrime/securesms/groups/GroupManagerV2.java @@ -561,7 +561,7 @@ final class GroupManagerV2 { if (GroupChangeUtil.changeIsEmpty(change.build())) { Log.i(TAG, "Change is empty after conflict resolution"); Recipient groupRecipient = Recipient.externalGroupExact(context, groupId); - long threadId = DatabaseFactory.getThreadDatabase(context).getThreadIdFor(groupRecipient); + long threadId = DatabaseFactory.getThreadDatabase(context).getOrCreateThreadIdFor(groupRecipient); return new GroupManager.GroupActionResult(groupRecipient, threadId, 0, Collections.emptyList()); } diff --git a/app/src/main/java/org/thoughtcrime/securesms/groups/GroupV1MessageProcessor.java b/app/src/main/java/org/thoughtcrime/securesms/groups/GroupV1MessageProcessor.java index 3e6c5ac47f..2da41ee9dc 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/groups/GroupV1MessageProcessor.java +++ b/app/src/main/java/org/thoughtcrime/securesms/groups/GroupV1MessageProcessor.java @@ -239,7 +239,7 @@ public final class GroupV1MessageProcessor { RecipientId recipientId = DatabaseFactory.getRecipientDatabase(context).getOrInsertFromGroupId(GroupId.v1orThrow(group.getGroupId())); Recipient recipient = Recipient.resolved(recipientId); OutgoingGroupUpdateMessage outgoingMessage = new OutgoingGroupUpdateMessage(recipient, storage, null, content.getTimestamp(), 0, false, null, Collections.emptyList(), Collections.emptyList(), Collections.emptyList()); - long threadId = DatabaseFactory.getThreadDatabase(context).getThreadIdFor(recipient); + long threadId = DatabaseFactory.getThreadDatabase(context).getOrCreateThreadIdFor(recipient); long messageId = mmsDatabase.insertMessageOutbox(outgoingMessage, threadId, false, null); mmsDatabase.markAsSent(messageId, true); diff --git a/app/src/main/java/org/thoughtcrime/securesms/groups/GroupsV1MigrationUtil.java b/app/src/main/java/org/thoughtcrime/securesms/groups/GroupsV1MigrationUtil.java index 11b85771d0..b33c01df51 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/groups/GroupsV1MigrationUtil.java +++ b/app/src/main/java/org/thoughtcrime/securesms/groups/GroupsV1MigrationUtil.java @@ -152,7 +152,7 @@ public final class GroupsV1MigrationUtil { } Recipient recipient = Recipient.externalGroupExact(context, gv1Id); - long threadId = DatabaseFactory.getThreadDatabase(context).getThreadIdFor(recipient); + long threadId = DatabaseFactory.getThreadDatabase(context).getOrCreateThreadIdFor(recipient); performLocalMigration(context, gv1Id, threadId, recipient); Log.i(TAG, "Migration complete! (" + gv1Id + ", " + threadId + ", " + recipient.getId() + ")", new Throwable()); 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 735af59cea..1394425d82 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 @@ -311,7 +311,7 @@ public final class GroupsV2StateProcessor { try { MessageDatabase mmsDatabase = DatabaseFactory.getMmsDatabase(context); - long threadId = DatabaseFactory.getThreadDatabase(context).getThreadIdFor(groupRecipient); + long threadId = DatabaseFactory.getThreadDatabase(context).getOrCreateThreadIdFor(groupRecipient); long id = mmsDatabase.insertMessageOutbox(leaveMessage, threadId, false, null); mmsDatabase.markAsSent(id, true); } catch (MmsException e) { @@ -511,7 +511,7 @@ public final class GroupsV2StateProcessor { RecipientId recipientId = recipientDatabase.getOrInsertFromGroupId(groupId); Recipient recipient = Recipient.resolved(recipientId); OutgoingGroupUpdateMessage outgoingMessage = new OutgoingGroupUpdateMessage(recipient, decryptedGroupV2Context, null, timestamp, 0, false, null, Collections.emptyList(), Collections.emptyList(), Collections.emptyList()); - long threadId = DatabaseFactory.getThreadDatabase(context).getThreadIdFor(recipient); + long threadId = DatabaseFactory.getThreadDatabase(context).getOrCreateThreadIdFor(recipient); long messageId = mmsDatabase.insertMessageOutbox(outgoingMessage, threadId, false, null); mmsDatabase.markAsSent(messageId, true); diff --git a/app/src/main/java/org/thoughtcrime/securesms/invites/InviteReminderModel.java b/app/src/main/java/org/thoughtcrime/securesms/invites/InviteReminderModel.java index 928f80bfdc..4e59b51dee 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/invites/InviteReminderModel.java +++ b/app/src/main/java/org/thoughtcrime/securesms/invites/InviteReminderModel.java @@ -50,7 +50,7 @@ public final class InviteReminderModel { } ThreadDatabase threadDatabase = DatabaseFactory.getThreadDatabase(context); - long threadId = threadDatabase.getThreadIdFor(recipient); + long threadId = threadDatabase.getOrCreateThreadIdFor(recipient); MmsSmsDatabase mmsSmsDatabase = DatabaseFactory.getMmsSmsDatabase(context); int conversationCount = mmsSmsDatabase.getInsecureSentCount(threadId); diff --git a/app/src/main/java/org/thoughtcrime/securesms/messages/MessageContentProcessor.java b/app/src/main/java/org/thoughtcrime/securesms/messages/MessageContentProcessor.java index 7bcfacb607..2a2287fad8 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/messages/MessageContentProcessor.java +++ b/app/src/main/java/org/thoughtcrime/securesms/messages/MessageContentProcessor.java @@ -121,11 +121,9 @@ import org.thoughtcrime.securesms.util.TextSecurePreferences; import org.thoughtcrime.securesms.util.Util; import org.whispersystems.libsignal.SignalProtocolAddress; import org.whispersystems.libsignal.protocol.DecryptionErrorMessage; -import org.whispersystems.libsignal.protocol.SenderKeyDistributionMessage; import org.whispersystems.libsignal.state.SessionStore; import org.whispersystems.libsignal.util.Pair; import org.whispersystems.libsignal.util.guava.Optional; -import org.whispersystems.signalservice.api.SignalServiceMessageSender; import org.whispersystems.signalservice.api.messages.SignalServiceAttachment; import org.whispersystems.signalservice.api.messages.SignalServiceContent; import org.whispersystems.signalservice.api.messages.SignalServiceDataMessage; @@ -288,7 +286,7 @@ public final class MessageContentProcessor { } else if (!threadRecipient.isGroup()) { Log.i(TAG, "Message was to a 1:1. Ensuring this user has our profile key."); ApplicationDependencies.getJobManager().startChain(new RefreshAttributesJob(false)) - .then(ProfileKeySendJob.create(context, DatabaseFactory.getThreadDatabase(context).getThreadIdFor(threadRecipient), true)) + .then(ProfileKeySendJob.create(context, DatabaseFactory.getThreadDatabase(context).getOrCreateThreadIdFor(threadRecipient), true)) .enqueue(); } } @@ -693,7 +691,7 @@ public final class MessageContentProcessor { OutgoingTextMessage outgoingTextMessage = new OutgoingTextMessage(recipient, "", -1); OutgoingEndSessionMessage outgoingEndSessionMessage = new OutgoingEndSessionMessage(outgoingTextMessage); - long threadId = DatabaseFactory.getThreadDatabase(context).getThreadIdFor(recipient); + long threadId = DatabaseFactory.getThreadDatabase(context).getOrCreateThreadIdFor(recipient); if (!recipient.isGroup()) { SessionStore sessionStore = new TextSecureSessionStore(context); @@ -968,7 +966,7 @@ public final class MessageContentProcessor { return; } - long threadId = threadDatabase.getThreadIdFor(recipient); + long threadId = threadDatabase.getOrCreateThreadIdFor(recipient); switch (response.getType()) { case ACCEPT: @@ -1054,7 +1052,7 @@ public final class MessageContentProcessor { threadId = gv1ThreadId == null ? -1 : gv1ThreadId; } else if (message.getMessage().isGroupV2Update()) { handleSynchronizeSentGv2Update(content, message); - threadId = DatabaseFactory.getThreadDatabase(context).getThreadIdFor(getSyncMessageDestination(message)); + threadId = DatabaseFactory.getThreadDatabase(context).getOrCreateThreadIdFor(getSyncMessageDestination(message)); } else if (Build.VERSION.SDK_INT > 19 && message.getMessage().getGroupCallUpdate().isPresent()) { handleGroupCallUpdateMessage(content, message.getMessage(), GroupUtil.idFromGroupContext(message.getMessage().getGroupContext()), senderRecipient); } else if (message.getMessage().isEmptyGroupV2Message()) { @@ -1063,7 +1061,7 @@ public final class MessageContentProcessor { threadId = handleSynchronizeSentExpirationUpdate(message); } else if (message.getMessage().getReaction().isPresent()) { handleReaction(content, message.getMessage(), senderRecipient); - threadId = DatabaseFactory.getThreadDatabase(context).getThreadIdFor(getSyncMessageDestination(message)); + threadId = DatabaseFactory.getThreadDatabase(context).getOrCreateThreadIdFor(getSyncMessageDestination(message)); } else if (message.getMessage().getRemoteDelete().isPresent()) { handleRemoteDelete(content, message.getMessage(), senderRecipient); } else if (message.getMessage().getAttachments().isPresent() || message.getMessage().getQuote().isPresent() || message.getMessage().getPreviews().isPresent() || message.getMessage().getSticker().isPresent() || message.getMessage().isViewOnce() || message.getMessage().getMentions().isPresent()) { @@ -1300,7 +1298,7 @@ public final class MessageContentProcessor { message.getTimestamp(), message.getMessage().getExpiresInSeconds() * 1000L); - long threadId = DatabaseFactory.getThreadDatabase(context).getThreadIdFor(recipient); + long threadId = DatabaseFactory.getThreadDatabase(context).getOrCreateThreadIdFor(recipient); long messageId = database.insertMessageOutbox(expirationUpdateMessage, threadId, false, null); database.markAsSent(messageId, true); @@ -1345,7 +1343,7 @@ public final class MessageContentProcessor { handleSynchronizeSentExpirationUpdate(message); } - long threadId = DatabaseFactory.getThreadDatabase(context).getThreadIdFor(recipients); + long threadId = DatabaseFactory.getThreadDatabase(context).getOrCreateThreadIdFor(recipients); database.beginTransaction(); @@ -1499,7 +1497,7 @@ public final class MessageContentProcessor { handleSynchronizeSentExpirationUpdate(message); } - long threadId = DatabaseFactory.getThreadDatabase(context).getThreadIdFor(recipient); + long threadId = DatabaseFactory.getThreadDatabase(context).getOrCreateThreadIdFor(recipient); boolean isGroup = recipient.isGroup(); MessageDatabase database; @@ -1747,9 +1745,9 @@ public final class MessageContentProcessor { Recipient groupRecipient = Recipient.externalPossiblyMigratedGroup(context, groupId); - threadId = DatabaseFactory.getThreadDatabase(context).getThreadIdFor(groupRecipient); + threadId = DatabaseFactory.getThreadDatabase(context).getOrCreateThreadIdFor(groupRecipient); } else { - threadId = DatabaseFactory.getThreadDatabase(context).getThreadIdFor(senderRecipient); + threadId = DatabaseFactory.getThreadDatabase(context).getOrCreateThreadIdFor(senderRecipient); } if (threadId <= 0) { @@ -2096,7 +2094,7 @@ public final class MessageContentProcessor { } private void notifyTypingStoppedFromIncomingMessage(@NonNull Recipient senderRecipient, @NonNull Recipient conversationRecipient, int device) { - long threadId = DatabaseFactory.getThreadDatabase(context).getThreadIdFor(conversationRecipient); + long threadId = DatabaseFactory.getThreadDatabase(context).getOrCreateThreadIdFor(conversationRecipient); if (threadId > 0 && TextSecurePreferences.isTypingIndicatorsEnabled(context)) { Log.d(TAG, "Typing stopped on thread " + threadId + " due to an incoming message."); diff --git a/app/src/main/java/org/thoughtcrime/securesms/messages/MessageDecryptionUtil.java b/app/src/main/java/org/thoughtcrime/securesms/messages/MessageDecryptionUtil.java index 4caae04355..24ef9b4ccb 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/messages/MessageDecryptionUtil.java +++ b/app/src/main/java/org/thoughtcrime/securesms/messages/MessageDecryptionUtil.java @@ -146,9 +146,9 @@ public final class MessageDecryptionUtil { if (groupId.isPresent()) { Recipient groupRecipient = Recipient.externalPossiblyMigratedGroup(context, groupId.get()); - threadId = DatabaseFactory.getThreadDatabase(context).getThreadIdFor(groupRecipient); + threadId = DatabaseFactory.getThreadDatabase(context).getOrCreateThreadIdFor(groupRecipient); } else { - threadId = DatabaseFactory.getThreadDatabase(context).getThreadIdFor(sender); + threadId = DatabaseFactory.getThreadDatabase(context).getOrCreateThreadIdFor(sender); } switch (contentHint) { diff --git a/app/src/main/java/org/thoughtcrime/securesms/migrations/ApplicationMigrations.java b/app/src/main/java/org/thoughtcrime/securesms/migrations/ApplicationMigrations.java index 94704727a2..93f0000916 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/migrations/ApplicationMigrations.java +++ b/app/src/main/java/org/thoughtcrime/securesms/migrations/ApplicationMigrations.java @@ -79,9 +79,10 @@ public class ApplicationMigrations { static final int DB_AUTOINCREMENT = 37; static final int ATTACHMENT_CLEANUP = 38; static final int LOG_CLEANUP = 39; + static final int ATTACHMENT_CLEANUP_2 = 40; } - public static final int CURRENT_VERSION = 39; + public static final int CURRENT_VERSION = 40; /** * This *must* be called after the {@link JobManager} has been instantiated, but *before* the call @@ -347,6 +348,10 @@ public class ApplicationMigrations { jobs.put(Version.LOG_CLEANUP, new DeleteDeprecatedLogsMigrationJob()); } + if (lastSeenVersion < Version.ATTACHMENT_CLEANUP_2) { + jobs.put(Version.ATTACHMENT_CLEANUP_2, new AttachmentCleanupMigrationJob()); + } + return jobs; } diff --git a/app/src/main/java/org/thoughtcrime/securesms/recipients/RecipientUtil.java b/app/src/main/java/org/thoughtcrime/securesms/recipients/RecipientUtil.java index 7a4e703654..aa18dbdbb6 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/recipients/RecipientUtil.java +++ b/app/src/main/java/org/thoughtcrime/securesms/recipients/RecipientUtil.java @@ -218,7 +218,7 @@ public class RecipientUtil { return true; } - long threadId = DatabaseFactory.getThreadDatabase(context).getThreadIdFor(threadRecipient); + Long threadId = DatabaseFactory.getThreadDatabase(context).getThreadIdFor(threadRecipient.getId()); return isMessageRequestAccepted(context, threadId, threadRecipient); } @@ -232,7 +232,7 @@ public class RecipientUtil { return true; } - long threadId = DatabaseFactory.getThreadDatabase(context).getThreadIdFor(threadRecipient); + Long threadId = DatabaseFactory.getThreadDatabase(context).getThreadIdFor(threadRecipient.getId()); return isCallRequestAccepted(context, threadId, threadRecipient); } @@ -240,9 +240,9 @@ public class RecipientUtil { * @return True if a conversation existed before we enabled message requests, otherwise false. */ @WorkerThread - public static boolean isPreMessageRequestThread(@NonNull Context context, long threadId) { + public static boolean isPreMessageRequestThread(@NonNull Context context, @Nullable Long threadId) { long beforeTime = SignalStore.misc().getMessageRequestEnableTime(); - return DatabaseFactory.getMmsSmsDatabase(context).getConversationCount(threadId, beforeTime) > 0; + return threadId != null && DatabaseFactory.getMmsSmsDatabase(context).getConversationCount(threadId, beforeTime) > 0; } @WorkerThread @@ -301,14 +301,14 @@ public class RecipientUtil { if (threadId == -1 || !DatabaseFactory.getMmsSmsDatabase(context).hasMeaningfulMessage(threadId)) { DatabaseFactory.getRecipientDatabase(context).setExpireMessages(recipient.getId(), defaultTimer); OutgoingExpirationUpdateMessage outgoingMessage = new OutgoingExpirationUpdateMessage(recipient, System.currentTimeMillis(), defaultTimer * 1000L); - MessageSender.send(context, outgoingMessage, DatabaseFactory.getThreadDatabase(context).getThreadIdFor(recipient), false, null); + MessageSender.send(context, outgoingMessage, DatabaseFactory.getThreadDatabase(context).getOrCreateThreadIdFor(recipient), false, null); return true; } return false; } @WorkerThread - private static boolean isMessageRequestAccepted(@NonNull Context context, long threadId, @NonNull Recipient threadRecipient) { + private static boolean isMessageRequestAccepted(@NonNull Context context, @Nullable Long threadId, @NonNull Recipient threadRecipient) { return threadRecipient.isSelf() || threadRecipient.isProfileSharing() || threadRecipient.isSystemContact() || @@ -320,7 +320,7 @@ public class RecipientUtil { } @WorkerThread - private static boolean isCallRequestAccepted(@NonNull Context context, long threadId, @NonNull Recipient threadRecipient) { + private static boolean isCallRequestAccepted(@NonNull Context context, @Nullable Long threadId, @NonNull Recipient threadRecipient) { return threadRecipient.isProfileSharing() || threadRecipient.isSystemContact() || hasSentMessageInThread(context, threadId) || @@ -328,12 +328,16 @@ public class RecipientUtil { } @WorkerThread - public static boolean hasSentMessageInThread(@NonNull Context context, long threadId) { - return DatabaseFactory.getMmsSmsDatabase(context).getOutgoingSecureConversationCount(threadId) != 0; + public static boolean hasSentMessageInThread(@NonNull Context context, @Nullable Long threadId) { + return threadId != null && DatabaseFactory.getMmsSmsDatabase(context).getOutgoingSecureConversationCount(threadId) != 0; } @WorkerThread - private static boolean noSecureMessagesAndNoCallsInThread(@NonNull Context context, long threadId) { + private static boolean noSecureMessagesAndNoCallsInThread(@NonNull Context context, @Nullable Long threadId) { + if (threadId == null) { + return true; + } + return DatabaseFactory.getMmsSmsDatabase(context).getSecureConversationCount(threadId) == 0 && !DatabaseFactory.getThreadDatabase(context).hasReceivedAnyCallsSince(threadId, 0); } diff --git a/app/src/main/java/org/thoughtcrime/securesms/service/webrtc/SignalCallManager.java b/app/src/main/java/org/thoughtcrime/securesms/service/webrtc/SignalCallManager.java index d6b4145243..ca24382c68 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/service/webrtc/SignalCallManager.java +++ b/app/src/main/java/org/thoughtcrime/securesms/service/webrtc/SignalCallManager.java @@ -287,7 +287,7 @@ public final class SignalCallManager implements CallManager.Observer, GroupCall. .toList(); callManager.peekGroupCall(SignalStore.internalValues().groupCallingServer(), credential.getTokenBytes().toByteArray(), members, peekInfo -> { - long threadId = DatabaseFactory.getThreadDatabase(context).getThreadIdFor(group); + long threadId = DatabaseFactory.getThreadDatabase(context).getOrCreateThreadIdFor(group); DatabaseFactory.getSmsDatabase(context) .updatePreviousGroupCall(threadId, diff --git a/app/src/main/java/org/thoughtcrime/securesms/sms/MessageSender.java b/app/src/main/java/org/thoughtcrime/securesms/sms/MessageSender.java index 80d27587e7..002e18c529 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/sms/MessageSender.java +++ b/app/src/main/java/org/thoughtcrime/securesms/sms/MessageSender.java @@ -162,7 +162,7 @@ public class MessageSender { long allocatedThreadId; if (threadId == -1) { - allocatedThreadId = threadDatabase.getThreadIdFor(message.getRecipient(), message.getDistributionType()); + allocatedThreadId = threadDatabase.getOrCreateThreadIdFor(message.getRecipient(), message.getDistributionType()); } else { allocatedThreadId = threadId; } @@ -205,7 +205,7 @@ public class MessageSender { mmsDatabase.beginTransaction(); try { OutgoingSecureMediaMessage primaryMessage = messages.get(0); - long primaryThreadId = threadDatabase.getThreadIdFor(primaryMessage.getRecipient(), primaryMessage.getDistributionType()); + long primaryThreadId = threadDatabase.getOrCreateThreadIdFor(primaryMessage.getRecipient(), primaryMessage.getDistributionType()); long primaryMessageId = mmsDatabase.insertMessageOutbox(applyUniversalExpireTimerIfNecessary(context, primaryMessage.getRecipient(), primaryMessage, primaryThreadId), primaryThreadId, false, @@ -226,7 +226,7 @@ public class MessageSender { } for (OutgoingSecureMediaMessage secondaryMessage : secondaryMessages) { - long allocatedThreadId = threadDatabase.getThreadIdFor(secondaryMessage.getRecipient(), secondaryMessage.getDistributionType()); + long allocatedThreadId = threadDatabase.getOrCreateThreadIdFor(secondaryMessage.getRecipient(), secondaryMessage.getDistributionType()); long messageId = mmsDatabase.insertMessageOutbox(applyUniversalExpireTimerIfNecessary(context, secondaryMessage.getRecipient(), secondaryMessage, allocatedThreadId), allocatedThreadId, false, diff --git a/app/src/main/java/org/thoughtcrime/securesms/util/CommunicationActions.java b/app/src/main/java/org/thoughtcrime/securesms/util/CommunicationActions.java index f57ad4b6ac..7e1aff467f 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/util/CommunicationActions.java +++ b/app/src/main/java/org/thoughtcrime/securesms/util/CommunicationActions.java @@ -101,12 +101,12 @@ public class CommunicationActions { new AsyncTask() { @Override protected Long doInBackground(Void... voids) { - return DatabaseFactory.getThreadDatabase(context).getThreadIdFor(recipient); + return DatabaseFactory.getThreadDatabase(context).getThreadIdFor(recipient.getId()); } @Override - protected void onPostExecute(Long threadId) { - ConversationIntents.Builder builder = ConversationIntents.createBuilder(context, recipient.getId(), threadId); + protected void onPostExecute(@Nullable Long threadId) { + ConversationIntents.Builder builder = ConversationIntents.createBuilder(context, recipient.getId(), threadId != null ? threadId : -1); if (!TextUtils.isEmpty(text)) { builder.withDraftText(text); } diff --git a/app/src/main/java/org/thoughtcrime/securesms/util/ConversationUtil.java b/app/src/main/java/org/thoughtcrime/securesms/util/ConversationUtil.java index 1ed0205bc2..fbd72da106 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/util/ConversationUtil.java +++ b/app/src/main/java/org/thoughtcrime/securesms/util/ConversationUtil.java @@ -193,13 +193,13 @@ public final class ConversationUtil { { Recipient resolved = recipient.resolve(); Person[] persons = buildPersons(context, resolved); - long threadId = DatabaseFactory.getThreadDatabase(context).getThreadIdFor(resolved); + Long threadId = DatabaseFactory.getThreadDatabase(context).getThreadIdFor(resolved.getId()); String shortName = resolved.isSelf() ? context.getString(R.string.note_to_self) : resolved.getShortDisplayName(context); String longName = resolved.isSelf() ? context.getString(R.string.note_to_self) : resolved.getDisplayName(context); return new ShortcutInfoCompat.Builder(context, getShortcutId(resolved)) .setLongLived(true) - .setIntent(ConversationIntents.createBuilder(context, resolved.getId(), threadId).build()) + .setIntent(ConversationIntents.createBuilder(context, resolved.getId(), threadId != null ? threadId : -1).build()) .setShortLabel(shortName) .setLongLabel(longName) .setIcon(AvatarUtil.getIconCompatForShortcut(context, resolved)) 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 e6ca8bd856..d3f881e38b 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/util/IdentityUtil.java +++ b/app/src/main/java/org/thoughtcrime/securesms/util/IdentityUtil.java @@ -83,7 +83,7 @@ public final class IdentityUtil { } else { RecipientId recipientId = DatabaseFactory.getRecipientDatabase(context).getOrInsertFromGroupId(groupRecord.getId()); Recipient groupRecipient = Recipient.resolved(recipientId); - long threadId = DatabaseFactory.getThreadDatabase(context).getThreadIdFor(groupRecipient); + long threadId = DatabaseFactory.getThreadDatabase(context).getOrCreateThreadIdFor(groupRecipient); OutgoingTextMessage outgoing ; if (verified) outgoing = new OutgoingIdentityVerifiedMessage(recipient); @@ -108,7 +108,7 @@ public final class IdentityUtil { if (verified) outgoing = new OutgoingIdentityVerifiedMessage(recipient); else outgoing = new OutgoingIdentityDefaultMessage(recipient); - long threadId = DatabaseFactory.getThreadDatabase(context).getThreadIdFor(recipient); + long threadId = DatabaseFactory.getThreadDatabase(context).getOrCreateThreadIdFor(recipient); Log.i(TAG, "Inserting verified outbox..."); DatabaseFactory.getSmsDatabase(context).insertMessageOutbox(threadId, outgoing, false, time, null);