From d70bfe561424e18a2c2a065fe79e40de39c410ff Mon Sep 17 00:00:00 2001 From: charles Date: Thu, 8 Dec 2022 13:38:53 +1100 Subject: [PATCH] Add pre-release config flag and client version detection --- .../conversation/v2/ConversationActivityV2.kt | 3 +- .../securesms/database/RecipientDatabase.java | 10 ++++++ .../securesms/database/Storage.kt | 5 +++ .../libsession/database/StorageProtocol.kt | 1 + .../messaging/jobs/DisappearingMessagesJob.kt | 2 ++ .../messages/ExpirationConfiguration.kt | 3 ++ .../messages/control/ExpirationTimerUpdate.kt | 12 +++---- .../ReceivedMessageHandler.kt | 5 ++- .../utilities/recipients/Recipient.java | 31 +++++++++++++++++++ 9 files changed, 62 insertions(+), 10 deletions(-) diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/ConversationActivityV2.kt b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/ConversationActivityV2.kt index 922781594a..9635bd4d72 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/ConversationActivityV2.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/ConversationActivityV2.kt @@ -53,6 +53,7 @@ import org.session.libsession.messaging.MessagingModuleConfiguration import org.session.libsession.messaging.contacts.Contact import org.session.libsession.messaging.mentions.Mention import org.session.libsession.messaging.mentions.MentionsManager +import org.session.libsession.messaging.messages.ExpirationConfiguration import org.session.libsession.messaging.messages.control.DataExtractionNotification import org.session.libsession.messaging.messages.signal.OutgoingMediaMessage import org.session.libsession.messaging.messages.signal.OutgoingTextMessage @@ -570,7 +571,7 @@ class ConversationActivityV2 : PassphraseRequiredActionBarActivity(), InputBarDe private fun setUpOutdatedClientBanner() { val recipient = viewModel.recipient ?: return - if (recipient.expireMessages == 0) { return } + if (recipient.expireMessages == 0 || !ExpirationConfiguration.isNewConfigEnabled) { return } binding?.outdatedBannerTextView?.text = resources.getString(R.string.activity_conversation_outdated_client_banner_text, recipient.name) binding?.outdatedBanner?.isVisible = true diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/RecipientDatabase.java b/app/src/main/java/org/thoughtcrime/securesms/database/RecipientDatabase.java index 3ffceee958..0e97ac3188 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/RecipientDatabase.java +++ b/app/src/main/java/org/thoughtcrime/securesms/database/RecipientDatabase.java @@ -13,6 +13,7 @@ import com.annimon.stream.Stream; import net.sqlcipher.database.SQLiteDatabase; +import org.jetbrains.annotations.NotNull; import org.session.libsession.utilities.Address; import org.session.libsession.utilities.MaterialColor; import org.session.libsession.utilities.Util; @@ -47,6 +48,7 @@ public class RecipientDatabase extends Database { private static final String SEEN_INVITE_REMINDER = "seen_invite_reminder"; private static final String DEFAULT_SUBSCRIPTION_ID = "default_subscription_id"; static final String EXPIRE_MESSAGES = "expire_messages"; + private static final String DISAPPEARING_STATE = "disappearing_state"; private static final String REGISTERED = "registered"; private static final String PROFILE_KEY = "profile_key"; private static final String SYSTEM_DISPLAY_NAME = "system_display_name"; @@ -415,6 +417,14 @@ public class RecipientDatabase extends Database { return returnList; } + public void setDisappearingState(@NotNull Recipient recipient, @NotNull Recipient.DisappearingState disappearingState) { + ContentValues values = new ContentValues(); + values.put(DISAPPEARING_STATE, disappearingState.getId()); + updateOrInsert(recipient.getAddress(), values); + recipient.resolve().setDisappearingState(disappearingState); + notifyRecipientListeners(); + } + public static class RecipientReader implements Closeable { private final Context context; diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/Storage.kt b/app/src/main/java/org/thoughtcrime/securesms/database/Storage.kt index 72bcd186e9..f56028968d 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/Storage.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/database/Storage.kt @@ -4,6 +4,7 @@ import android.content.Context import android.net.Uri import org.session.libsession.database.StorageProtocol import org.session.libsession.messaging.BlindedIdMapping +import org.session.libsession.messaging.MessagingModuleConfiguration import org.session.libsession.messaging.calls.CallMessageType import org.session.libsession.messaging.contacts.Contact import org.session.libsession.messaging.jobs.AttachmentUploadJob @@ -974,4 +975,8 @@ class Storage(context: Context, helper: SQLCipherOpenHelper) : Database(context, return emptyList() } + override fun updateDisappearingState(address: String, disappearingState: Recipient.DisappearingState) { + val recipient = Recipient.from(MessagingModuleConfiguration.shared.context, fromSerialized(address), false) + DatabaseComponent.get(context).recipientDatabase().setDisappearingState(recipient, disappearingState); + } } \ No newline at end of file diff --git a/libsession/src/main/java/org/session/libsession/database/StorageProtocol.kt b/libsession/src/main/java/org/session/libsession/database/StorageProtocol.kt index be6a9473e5..4c7293b675 100644 --- a/libsession/src/main/java/org/session/libsession/database/StorageProtocol.kt +++ b/libsession/src/main/java/org/session/libsession/database/StorageProtocol.kt @@ -202,4 +202,5 @@ interface StorageProtocol { fun getExpirationConfiguration(threadId: Long): ExpirationConfiguration? fun addExpirationConfiguration(config: ExpirationConfiguration) fun getExpiringMessages(messageIds: LongArray): List> + fun updateDisappearingState(address: String, disappearingState: Recipient.DisappearingState) } diff --git a/libsession/src/main/java/org/session/libsession/messaging/jobs/DisappearingMessagesJob.kt b/libsession/src/main/java/org/session/libsession/messaging/jobs/DisappearingMessagesJob.kt index 21106feddc..420fcda0ab 100644 --- a/libsession/src/main/java/org/session/libsession/messaging/jobs/DisappearingMessagesJob.kt +++ b/libsession/src/main/java/org/session/libsession/messaging/jobs/DisappearingMessagesJob.kt @@ -1,6 +1,7 @@ package org.session.libsession.messaging.jobs import org.session.libsession.messaging.MessagingModuleConfiguration +import org.session.libsession.messaging.messages.ExpirationConfiguration import org.session.libsession.messaging.messages.control.SyncedExpiriesMessage import org.session.libsession.messaging.messages.control.SyncedExpiry import org.session.libsession.messaging.sending_receiving.MessageSender @@ -16,6 +17,7 @@ class DisappearingMessagesJob(val messageIds: LongArray = longArrayOf(), val sta override val maxFailureCount: Int = 1 override fun execute() { + if (!ExpirationConfiguration.isNewConfigEnabled) return val userPublicKey = MessagingModuleConfiguration.shared.storage.getUserPublicKey() ?: return val module = MessagingModuleConfiguration.shared try { diff --git a/libsession/src/main/java/org/session/libsession/messaging/messages/ExpirationConfiguration.kt b/libsession/src/main/java/org/session/libsession/messaging/messages/ExpirationConfiguration.kt index b1b80f1fbf..4e1f184a5e 100644 --- a/libsession/src/main/java/org/session/libsession/messaging/messages/ExpirationConfiguration.kt +++ b/libsession/src/main/java/org/session/libsession/messaging/messages/ExpirationConfiguration.kt @@ -9,4 +9,7 @@ class ExpirationConfiguration( val updatedTimestampMs: Long = 0 ) { val isEnabled = durationSeconds > 0 + companion object { + val isNewConfigEnabled = System.currentTimeMillis() > 1_671_062_400_000 // 15/12/2022 + } } \ No newline at end of file diff --git a/libsession/src/main/java/org/session/libsession/messaging/messages/control/ExpirationTimerUpdate.kt b/libsession/src/main/java/org/session/libsession/messaging/messages/control/ExpirationTimerUpdate.kt index ea2da00e60..e06b1fcb9b 100644 --- a/libsession/src/main/java/org/session/libsession/messaging/messages/control/ExpirationTimerUpdate.kt +++ b/libsession/src/main/java/org/session/libsession/messaging/messages/control/ExpirationTimerUpdate.kt @@ -1,6 +1,7 @@ package org.session.libsession.messaging.messages.control import org.session.libsession.messaging.MessagingModuleConfiguration +import org.session.libsession.messaging.messages.ExpirationConfiguration import org.session.libsession.messaging.messages.visible.VisibleMessage import org.session.libsignal.utilities.Log import org.session.libsignal.protos.SignalServiceProtos @@ -17,7 +18,7 @@ class ExpirationTimerUpdate() : ControlMessage() { override fun isValid(): Boolean { if (!super.isValid()) return false - return duration != null + return duration != null || ExpirationConfiguration.isNewConfigEnabled } companion object { @@ -28,7 +29,7 @@ class ExpirationTimerUpdate() : ControlMessage() { val isExpirationTimerUpdate = dataMessageProto.flags.and(SignalServiceProtos.DataMessage.Flags.EXPIRATION_TIMER_UPDATE_VALUE) != 0 if (!isExpirationTimerUpdate) return null val syncTarget = dataMessageProto.syncTarget - val duration = dataMessageProto.expireTimer + val duration = if (proto.hasExpirationTimer()) proto.expirationTimer else dataMessageProto.expireTimer return ExpirationTimerUpdate(syncTarget, duration) } } @@ -44,14 +45,9 @@ class ExpirationTimerUpdate() : ControlMessage() { } override fun toProto(): SignalServiceProtos.Content? { - val duration = duration - if (duration == null) { - Log.w(TAG, "Couldn't construct expiration timer update proto from: $this") - return null - } val dataMessageProto = SignalServiceProtos.DataMessage.newBuilder() dataMessageProto.flags = SignalServiceProtos.DataMessage.Flags.EXPIRATION_TIMER_UPDATE_VALUE - dataMessageProto.expireTimer = duration + duration?.let { dataMessageProto.expireTimer = it } // Sync target if (syncTarget != null) { dataMessageProto.syncTarget = syncTarget diff --git a/libsession/src/main/java/org/session/libsession/messaging/sending_receiving/ReceivedMessageHandler.kt b/libsession/src/main/java/org/session/libsession/messaging/sending_receiving/ReceivedMessageHandler.kt index 0b8e01df9e..61dbead5da 100644 --- a/libsession/src/main/java/org/session/libsession/messaging/sending_receiving/ReceivedMessageHandler.kt +++ b/libsession/src/main/java/org/session/libsession/messaging/sending_receiving/ReceivedMessageHandler.kt @@ -39,6 +39,7 @@ import org.session.libsession.utilities.ProfileKeyUtil import org.session.libsession.utilities.SSKEnvironment import org.session.libsession.utilities.TextSecurePreferences import org.session.libsession.utilities.recipients.Recipient +import org.session.libsession.utilities.recipients.Recipient.DisappearingState import org.session.libsignal.crypto.ecc.DjbECPrivateKey import org.session.libsignal.crypto.ecc.DjbECPublicKey import org.session.libsignal.crypto.ecc.ECKeyPair @@ -83,8 +84,10 @@ fun MessageReceiver.handle(message: Message, proto: SignalServiceProtos.Content, } fun updateExpirationConfigurationIfNeeded(message: Message, proto: SignalServiceProtos.Content, openGroupID: String?) { - if (!proto.hasLastDisappearingMessageChangeTimestamp()) return val storage = MessagingModuleConfiguration.shared.storage + val disappearingState = if (proto.hasExpirationTimer()) DisappearingState.UPDATED else DisappearingState.LEGACY + storage.updateDisappearingState(message.sender!!, disappearingState) + if (!proto.hasLastDisappearingMessageChangeTimestamp() || !ExpirationConfiguration.isNewConfigEnabled) return val threadID = storage.getOrCreateThreadIdFor(message.sender!!, message.groupPublicKey, openGroupID) if (threadID <= 0) return val localConfig = storage.getExpirationConfiguration(threadID) diff --git a/libsession/src/main/java/org/session/libsession/utilities/recipients/Recipient.java b/libsession/src/main/java/org/session/libsession/utilities/recipients/Recipient.java index a7fa75dd2b..997b3a2d2e 100644 --- a/libsession/src/main/java/org/session/libsession/utilities/recipients/Recipient.java +++ b/libsession/src/main/java/org/session/libsession/utilities/recipients/Recipient.java @@ -86,6 +86,7 @@ public class Recipient implements RecipientModifiedListener { private boolean blocked = false; private boolean approved = false; private boolean approvedMe = false; + private DisappearingState disappearingState = DisappearingState.LEGACY; private VibrateState messageVibrate = VibrateState.DEFAULT; private VibrateState callVibrate = VibrateState.DEFAULT; private int expireMessages = 0; @@ -653,6 +654,18 @@ public class Recipient implements RecipientModifiedListener { notifyListeners(); } + public synchronized DisappearingState getDisappearingState() { + return disappearingState; + } + + public void setDisappearingState(DisappearingState disappearingState) { + synchronized (this) { + this.disappearingState = disappearingState; + } + + notifyListeners(); + } + public synchronized RegisteredState getRegistered() { if (isPushGroupRecipient()) return RegisteredState.REGISTERED; @@ -787,6 +800,24 @@ public class Recipient implements RecipientModifiedListener { } } + public enum DisappearingState { + LEGACY(0), UPDATED(1); + + private final int id; + + DisappearingState(int id) { + this.id = id; + } + + public int getId() { + return id; + } + + public static DisappearingState fromId(int id) { + return values()[id]; + } + } + public enum RegisteredState { UNKNOWN(0), REGISTERED(1), NOT_REGISTERED(2);