From 7ca2420287d1aef89fa5652906be4af19728c4c7 Mon Sep 17 00:00:00 2001 From: Greyson Parrelli Date: Thu, 17 Feb 2022 15:55:54 -0500 Subject: [PATCH] Move from ACI to a generic ServiceId. --- app/build.gradle | 85 +++++----- .../database/RecipientDatabaseTest.kt | 89 +++++----- .../database/RecipientDatabaseTest_merges.kt | 10 +- .../ContactSelectionListFragment.java | 4 +- .../securesms/NewConversationActivity.java | 2 +- .../InternalConversationSettingsFragment.kt | 31 +--- .../webrtc/CallParticipantsState.kt | 4 +- .../contacts/sync/DirectoryHelper.java | 37 +++-- .../ConversationParentFragment.java | 8 +- .../conversation/ConversationUpdateItem.java | 8 +- .../error/SafetyNumberChangeRepository.java | 2 +- .../securesms/crypto/SenderKeyUtil.java | 4 +- .../storage/SignalBaseIdentityKeyStore.java | 28 ++-- .../storage/SignalServiceDataStoreImpl.java | 4 +- .../crypto/storage/TextSecurePreKeyStore.java | 6 +- .../storage/TextSecureSessionStore.java | 12 +- .../securesms/database/GroupDatabase.java | 28 ++-- .../securesms/database/MentionUtil.java | 5 +- .../database/OneTimePreKeyDatabase.kt | 14 +- .../securesms/database/RecipientDatabase.kt | 153 +++++++++--------- .../securesms/database/SenderKeyDatabase.java | 2 +- .../database/SenderKeySharedDatabase.java | 4 +- .../securesms/database/SessionDatabase.kt | 42 ++--- .../database/SignedPreKeyDatabase.kt | 18 +-- .../securesms/database/SmsDatabase.java | 8 +- .../securesms/database/ThreadDatabase.java | 2 +- .../model/GroupCallUpdateMessageFactory.java | 15 +- .../model/GroupsV2UpdateMessageProducer.java | 15 +- .../database/model/MessageRecord.java | 26 +-- .../database/model/RecipientRecord.kt | 4 +- .../database/model/UpdateDescription.java | 23 +-- .../securesms/groups/GroupManagerV2.java | 14 +- .../securesms/groups/GroupProtoUtil.java | 13 +- .../groups/GroupV1MessageProcessor.java | 4 +- .../groups/GroupsV1MigrationUtil.java | 2 +- .../groups/GroupsV2CapabilityChecker.java | 2 +- .../securesms/groups/LiveGroup.java | 3 +- .../PendingMemberInvitesRepository.java | 2 +- .../GroupsV1MigrationRepository.java | 2 +- .../groups/v2/GroupCandidateHelper.java | 9 +- .../v2/processing/GroupsV2StateProcessor.java | 18 +-- .../securesms/jobs/CreateSignedPreKeyJob.java | 15 +- .../jobs/MultiDeviceBlockedUpdateJob.java | 2 +- .../jobs/MultiDeviceContactSyncJob.kt | 2 +- .../MultiDeviceMessageRequestResponseJob.java | 4 +- .../MultiDeviceOutgoingPaymentSyncJob.java | 2 +- .../jobs/PushGroupSilentUpdateSendJob.java | 4 +- .../securesms/jobs/PushMediaSendJob.java | 7 +- .../securesms/jobs/PushSendJob.java | 7 +- .../securesms/jobs/PushTextSendJob.java | 3 +- .../securesms/jobs/RefreshPreKeysJob.java | 21 +-- .../securesms/jobs/ResendMessageJob.java | 2 +- .../securesms/jobs/RetrieveProfileJob.java | 16 +- .../securesms/jobs/RotateSignedPreKeyJob.java | 12 +- .../jobs/SenderKeyDistributionSendJob.java | 2 +- .../securesms/jobs/StorageSyncJob.java | 2 +- .../securesms/keyvalue/AccountValues.kt | 10 ++ .../securesms/messages/GroupSendUtil.java | 7 +- .../messages/MessageContentProcessor.java | 30 ++-- .../messages/MessageDecryptionUtil.java | 3 +- .../PniAccountInitializationMigrationJob.java | 3 +- .../securesms/mms/MessageGroupContext.java | 3 +- .../recipients/LiveRecipientCache.java | 6 +- .../securesms/recipients/Recipient.java | 96 +++++------ .../recipients/RecipientDetails.java | 13 +- .../securesms/recipients/RecipientId.java | 12 +- .../recipients/RecipientIdCache.java | 25 ++- .../securesms/recipients/RecipientUtil.java | 14 +- .../registration/RegistrationRepository.java | 13 +- .../service/webrtc/GroupActionProcessor.java | 2 +- .../webrtc/GroupConnectedActionProcessor.java | 6 +- .../webrtc/GroupPreJoinActionProcessor.java | 2 +- .../IncomingGroupCallActionProcessor.java | 2 +- .../service/webrtc/SignalCallManager.java | 2 +- .../storage/ContactRecordProcessor.java | 14 +- .../securesms/storage/StorageSyncModels.java | 9 +- .../storage/StorageSyncValidations.java | 2 +- .../securesms/util/BucketingUtil.java | 2 +- .../securesms/util/CommunicationActions.java | 2 +- .../securesms/util/IdentityUtil.java | 2 +- .../securesms/util/LocaleFeatureFlags.java | 4 +- .../securesms/util/ProfileUtil.java | 7 +- .../securesms/util/RecipientAccessList.kt | 12 +- .../securesms/util/UsernameUtil.java | 7 +- .../verify/VerifyDisplayFragment.java | 10 +- .../GroupsV2UpdateMessageProducerTest.java | 9 +- .../recipients/RecipientIdCacheTest.java | 2 +- .../storage/StorageSyncHelperTest.java | 4 +- .../api/SignalServiceAccountManager.java | 25 +-- .../api/SignalServiceDataStore.java | 4 +- .../api/SignalServiceMessageReceiver.java | 9 +- .../api/SignalServiceMessageSender.java | 52 +++--- .../api/crypto/SignalServiceCipher.java | 6 +- .../messages/SignalServiceDataMessage.java | 11 +- .../api/messages/SignalServiceEnvelope.java | 3 +- .../DeviceContactsOutputStream.java | 4 +- .../multidevice/SentTranscriptMessage.java | 23 +-- .../signalservice/api/push/ACI.java | 63 +------- .../api/push/AccountIdentifier.java | 30 ---- .../signalservice/api/push/PNI.java | 7 +- .../signalservice/api/push/ServiceId.java | 115 +++++++++++++ .../signalservice/api/push/ServiceIdType.java | 15 ++ .../api/push/SignalServiceAddress.java | 36 ++--- .../api/services/ProfileService.java | 14 +- .../api/storage/SignalAccountRecord.java | 3 +- .../api/storage/SignalContactRecord.java | 6 +- .../internal/push/PushServiceSocket.java | 21 +-- .../push/SendGroupMessageResponse.java | 6 +- ...ignalServiceAddressProtobufSerializer.java | 9 +- ...lServiceAddressProtobufSerializerTest.java | 5 +- 110 files changed, 841 insertions(+), 824 deletions(-) delete mode 100644 libsignal/service/src/main/java/org/whispersystems/signalservice/api/push/AccountIdentifier.java create mode 100644 libsignal/service/src/main/java/org/whispersystems/signalservice/api/push/ServiceId.java create mode 100644 libsignal/service/src/main/java/org/whispersystems/signalservice/api/push/ServiceIdType.java diff --git a/app/build.gradle b/app/build.gradle index 37888cb3e..3a97b16c6 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -117,6 +117,48 @@ android { } } + testOptions { + execution 'ANDROIDX_TEST_ORCHESTRATOR' + + unitTests { + includeAndroidResources = true + } + } + + lintOptions { + checkReleaseBuilds false + abortOnError true + baseline file("lint-baseline.xml") + disable "LintError" + } + + sourceSets { + test { + java.srcDirs += "$projectDir/src/testShared" + } + + androidTest { + java.srcDirs += "$projectDir/src/testShared" + } + } + + compileOptions { + coreLibraryDesugaringEnabled true + sourceCompatibility JAVA_VERSION + targetCompatibility JAVA_VERSION + } + + packagingOptions { + exclude 'LICENSE.txt' + exclude 'LICENSE' + exclude 'NOTICE' + exclude 'asm-license.txt' + exclude 'META-INF/LICENSE' + exclude 'META-INF/NOTICE' + exclude 'META-INF/proguard/androidx-annotations.pro' + } + + defaultConfig { versionCode canonicalVersionCode * postFixSize versionName canonicalVersionName @@ -190,36 +232,6 @@ android { testInstrumentationRunnerArguments clearPackageData: 'true' } - testOptions { - execution 'ANDROIDX_TEST_ORCHESTRATOR' - } - - sourceSets { - test { - java.srcDirs += "$projectDir/src/testShared" - } - - androidTest { - java.srcDirs += "$projectDir/src/testShared" - } - } - - compileOptions { - coreLibraryDesugaringEnabled true - sourceCompatibility JAVA_VERSION - targetCompatibility JAVA_VERSION - } - - packagingOptions { - exclude 'LICENSE.txt' - exclude 'LICENSE' - exclude 'NOTICE' - exclude 'asm-license.txt' - exclude 'META-INF/LICENSE' - exclude 'META-INF/NOTICE' - exclude 'META-INF/proguard/androidx-annotations.pro' - } - buildTypes { debug { if (keystores['debug'] != null) { @@ -371,19 +383,6 @@ android { variant.setIgnore(true) } } - - lintOptions { - checkReleaseBuilds false - abortOnError true - baseline file("lint-baseline.xml") - disable "LintError" - } - - testOptions { - unitTests { - includeAndroidResources = true - } - } } dependencies { diff --git a/app/src/androidTest/java/org/thoughtcrime/securesms/database/RecipientDatabaseTest.kt b/app/src/androidTest/java/org/thoughtcrime/securesms/database/RecipientDatabaseTest.kt index 06c61fbf6..df1cffcc1 100644 --- a/app/src/androidTest/java/org/thoughtcrime/securesms/database/RecipientDatabaseTest.kt +++ b/app/src/androidTest/java/org/thoughtcrime/securesms/database/RecipientDatabaseTest.kt @@ -4,7 +4,6 @@ import androidx.test.ext.junit.runners.AndroidJUnit4 import org.junit.Assert.assertEquals import org.junit.Assert.assertFalse import org.junit.Assert.assertNotEquals -import org.junit.Assert.assertNull import org.junit.Assert.assertTrue import org.junit.Before import org.junit.Test @@ -30,8 +29,8 @@ class RecipientDatabaseTest { private lateinit var recipientDatabase: RecipientDatabase - private val localAci = ACI.from(UUID.randomUUID()); - private val localPni = PNI.from(UUID.randomUUID()); + private val localAci = ACI.from(UUID.randomUUID()) + private val localPni = PNI.from(UUID.randomUUID()) @Before fun setup() { @@ -52,7 +51,7 @@ class RecipientDatabaseTest { val recipientId: RecipientId = recipientDatabase.getAndPossiblyMerge(ACI_A, null, true) val recipient = Recipient.resolved(recipientId) - assertEquals(ACI_A, recipient.requireAci()) + assertEquals(ACI_A, recipient.requireServiceId()) assertFalse(recipient.hasE164()) } @@ -62,7 +61,7 @@ class RecipientDatabaseTest { val recipientId: RecipientId = recipientDatabase.getAndPossiblyMerge(ACI_A, null, false) val recipient = Recipient.resolved(recipientId) - assertEquals(ACI_A, recipient.requireAci()) + assertEquals(ACI_A, recipient.requireServiceId()) assertFalse(recipient.hasE164()) } @@ -73,7 +72,7 @@ class RecipientDatabaseTest { val recipient = Recipient.resolved(recipientId) assertEquals(E164_A, recipient.requireE164()) - assertFalse(recipient.hasAci()) + assertFalse(recipient.hasServiceId()) } /** If all you have is an E164, you can just store that, regardless of trust level. */ @@ -83,7 +82,7 @@ class RecipientDatabaseTest { val recipient = Recipient.resolved(recipientId) assertEquals(E164_A, recipient.requireE164()) - assertFalse(recipient.hasAci()) + assertFalse(recipient.hasServiceId()) } /** With high trust, you can associate an ACI-e164 pair. */ @@ -92,7 +91,7 @@ class RecipientDatabaseTest { val recipientId: RecipientId = recipientDatabase.getAndPossiblyMerge(ACI_A, E164_A, true) val recipient = Recipient.resolved(recipientId) - assertEquals(ACI_A, recipient.requireAci()) + assertEquals(ACI_A, recipient.requireServiceId()) assertEquals(E164_A, recipient.requireE164()) } @@ -102,7 +101,7 @@ class RecipientDatabaseTest { val recipientId: RecipientId = recipientDatabase.getAndPossiblyMerge(ACI_A, E164_A, false) val recipient = Recipient.resolved(recipientId) - assertEquals(ACI_A, recipient.requireAci()) + assertEquals(ACI_A, recipient.requireServiceId()) assertFalse(recipient.hasE164()) } @@ -113,26 +112,26 @@ class RecipientDatabaseTest { /** With high trust, you can associate an e164 with an existing ACI. */ @Test fun getAndPossiblyMerge_aciMapsToExistingUserButE164DoesNot_aciAndE164_highTrust() { - val existingId: RecipientId = recipientDatabase.getOrInsertFromAci(ACI_A) + val existingId: RecipientId = recipientDatabase.getOrInsertFromServiceId(ACI_A) val retrievedId: RecipientId = recipientDatabase.getAndPossiblyMerge(ACI_A, E164_A, true) assertEquals(existingId, retrievedId) val retrievedRecipient = Recipient.resolved(retrievedId) - assertEquals(ACI_A, retrievedRecipient.requireAci()) + assertEquals(ACI_A, retrievedRecipient.requireServiceId()) assertEquals(E164_A, retrievedRecipient.requireE164()) } /** With low trust, you cannot associate an ACI-e164 pair, and therefore cannot store the e164. */ @Test fun getAndPossiblyMerge_aciMapsToExistingUserButE164DoesNot_aciAndE164_lowTrust() { - val existingId: RecipientId = recipientDatabase.getOrInsertFromAci(ACI_A) + val existingId: RecipientId = recipientDatabase.getOrInsertFromServiceId(ACI_A) val retrievedId: RecipientId = recipientDatabase.getAndPossiblyMerge(ACI_A, E164_A, false) assertEquals(existingId, retrievedId) val retrievedRecipient = Recipient.resolved(retrievedId) - assertEquals(ACI_A, retrievedRecipient.requireAci()) + assertEquals(ACI_A, retrievedRecipient.requireServiceId()) assertFalse(retrievedRecipient.hasE164()) } @@ -145,7 +144,7 @@ class RecipientDatabaseTest { assertEquals(existingId, retrievedId) val retrievedRecipient = Recipient.resolved(retrievedId) - assertEquals(ACI_A, retrievedRecipient.requireAci()) + assertEquals(ACI_A, retrievedRecipient.requireServiceId()) assertEquals(E164_B, retrievedRecipient.requireE164()) } @@ -158,7 +157,7 @@ class RecipientDatabaseTest { assertEquals(existingId, retrievedId) val retrievedRecipient = Recipient.resolved(retrievedId) - assertEquals(ACI_A, retrievedRecipient.requireAci()) + assertEquals(ACI_A, retrievedRecipient.requireServiceId()) assertEquals(E164_A, retrievedRecipient.requireE164()) } @@ -175,7 +174,7 @@ class RecipientDatabaseTest { assertEquals(existingId, retrievedId) val retrievedRecipient = Recipient.resolved(retrievedId) - assertEquals(ACI_A, retrievedRecipient.requireAci()) + assertEquals(ACI_A, retrievedRecipient.requireServiceId()) assertEquals(E164_A, retrievedRecipient.requireE164()) } @@ -188,12 +187,12 @@ class RecipientDatabaseTest { assertNotEquals(existingId, retrievedId) val retrievedRecipient = Recipient.resolved(retrievedId) - assertEquals(ACI_A, retrievedRecipient.requireAci()) + assertEquals(ACI_A, retrievedRecipient.requireServiceId()) assertFalse(retrievedRecipient.hasE164()) val existingRecipient = Recipient.resolved(existingId) assertEquals(E164_A, existingRecipient.requireE164()) - assertFalse(existingRecipient.hasAci()) + assertFalse(existingRecipient.hasServiceId()) } /** We never change the ACI of an existing row. New ACI = new person, regardless of trust. But high trust lets us take the e164 from the current holder. */ @@ -207,14 +206,12 @@ class RecipientDatabaseTest { assertNotEquals(existingId, retrievedId) val retrievedRecipient = Recipient.resolved(retrievedId) - assertEquals(ACI_B, retrievedRecipient.requireAci()) + assertEquals(ACI_B, retrievedRecipient.requireServiceId()) assertEquals(E164_A, retrievedRecipient.requireE164()) - assertEquals(PNI_A, retrievedRecipient.pni.get()) val existingRecipient = Recipient.resolved(existingId) - assertEquals(ACI_A, existingRecipient.requireAci()) + assertEquals(ACI_A, existingRecipient.requireServiceId()) assertFalse(existingRecipient.hasE164()) - assertNull(existingRecipient.pni.orNull()) } /** We never change the ACI of an existing row. New ACI = new person, regardless of trust. And low trust means we can’t take the e164. */ @@ -226,11 +223,11 @@ class RecipientDatabaseTest { assertNotEquals(existingId, retrievedId) val retrievedRecipient = Recipient.resolved(retrievedId) - assertEquals(ACI_B, retrievedRecipient.requireAci()) + assertEquals(ACI_B, retrievedRecipient.requireServiceId()) assertFalse(retrievedRecipient.hasE164()) val existingRecipient = Recipient.resolved(existingId) - assertEquals(ACI_A, existingRecipient.requireAci()) + assertEquals(ACI_A, existingRecipient.requireServiceId()) assertEquals(E164_A, existingRecipient.requireE164()) } @@ -249,11 +246,11 @@ class RecipientDatabaseTest { assertNotEquals(existingId, retrievedId) val retrievedRecipient = Recipient.resolved(retrievedId) - assertEquals(ACI_B, retrievedRecipient.requireAci()) + assertEquals(ACI_B, retrievedRecipient.requireServiceId()) assertFalse(retrievedRecipient.hasE164()) val existingRecipient = Recipient.resolved(existingId) - assertEquals(ACI_A, existingRecipient.requireAci()) + assertEquals(ACI_A, existingRecipient.requireServiceId()) assertEquals(E164_A, existingRecipient.requireE164()) } @@ -270,7 +267,7 @@ class RecipientDatabaseTest { assertEquals(existingId, retrievedId) val retrievedRecipient = Recipient.resolved(retrievedId) - assertEquals(ACI_A, retrievedRecipient.requireAci()) + assertEquals(ACI_A, retrievedRecipient.requireServiceId()) assertEquals(E164_A, retrievedRecipient.requireE164()) } @@ -287,7 +284,7 @@ class RecipientDatabaseTest { assertEquals(existingAciId, retrievedId) val retrievedRecipient = Recipient.resolved(retrievedId) - assertEquals(ACI_A, retrievedRecipient.requireAci()) + assertEquals(ACI_A, retrievedRecipient.requireServiceId()) assertEquals(E164_A, retrievedRecipient.requireE164()) val existingE164Recipient = Recipient.resolved(existingE164Id) @@ -310,7 +307,7 @@ class RecipientDatabaseTest { assertEquals(existingAciId, retrievedId) val retrievedRecipient = Recipient.resolved(retrievedId) - assertEquals(ACI_A, retrievedRecipient.requireAci()) + assertEquals(ACI_A, retrievedRecipient.requireServiceId()) assertEquals(E164_A, retrievedRecipient.requireE164()) val existingE164Recipient = Recipient.resolved(existingE164Id) @@ -323,19 +320,19 @@ class RecipientDatabaseTest { /** Low trust means you can’t merge. If you’re retrieving a user from the table with this data, prefer the ACI one. */ @Test fun getAndPossiblyMerge_bothAciAndE164MapToExistingUser_aciAndE164_lowTrust() { - val existingAciId: RecipientId = recipientDatabase.getOrInsertFromAci(ACI_A) + val existingAciId: RecipientId = recipientDatabase.getOrInsertFromServiceId(ACI_A) val existingE164Id: RecipientId = recipientDatabase.getOrInsertFromE164(E164_A) val retrievedId: RecipientId = recipientDatabase.getAndPossiblyMerge(ACI_A, E164_A, false) assertEquals(existingAciId, retrievedId) val retrievedRecipient = Recipient.resolved(retrievedId) - assertEquals(ACI_A, retrievedRecipient.requireAci()) + assertEquals(ACI_A, retrievedRecipient.requireServiceId()) assertFalse(retrievedRecipient.hasE164()) val existingE164Recipient = Recipient.resolved(existingE164Id) assertEquals(E164_A, existingE164Recipient.requireE164()) - assertFalse(existingE164Recipient.hasAci()) + assertFalse(existingE164Recipient.hasServiceId()) } /** Another high trust case. No new rules here, just a more complex scenario to show how different rules interact. */ @@ -351,11 +348,11 @@ class RecipientDatabaseTest { assertEquals(existingId1, retrievedId) val retrievedRecipient = Recipient.resolved(retrievedId) - assertEquals(ACI_A, retrievedRecipient.requireAci()) + assertEquals(ACI_A, retrievedRecipient.requireServiceId()) assertEquals(E164_A, retrievedRecipient.requireE164()) val existingRecipient2 = Recipient.resolved(existingId2) - assertEquals(ACI_B, existingRecipient2.requireAci()) + assertEquals(ACI_B, existingRecipient2.requireServiceId()) assertFalse(existingRecipient2.hasE164()) assert(changeNumberListener.numberChangeWasEnqueued) @@ -371,11 +368,11 @@ class RecipientDatabaseTest { assertEquals(existingId1, retrievedId) val retrievedRecipient = Recipient.resolved(retrievedId) - assertEquals(ACI_A, retrievedRecipient.requireAci()) + assertEquals(ACI_A, retrievedRecipient.requireServiceId()) assertEquals(E164_B, retrievedRecipient.requireE164()) val existingRecipient2 = Recipient.resolved(existingId2) - assertEquals(ACI_B, existingRecipient2.requireAci()) + assertEquals(ACI_B, existingRecipient2.requireServiceId()) assertEquals(E164_A, existingRecipient2.requireE164()) } @@ -392,7 +389,7 @@ class RecipientDatabaseTest { assertEquals(existingId1, retrievedId) val retrievedRecipient = Recipient.resolved(retrievedId) - assertEquals(ACI_A, retrievedRecipient.requireAci()) + assertEquals(ACI_A, retrievedRecipient.requireServiceId()) assertEquals(E164_A, retrievedRecipient.requireE164()) assertFalse(recipientDatabase.getByE164(E164_B).isPresent) @@ -417,11 +414,11 @@ class RecipientDatabaseTest { assertEquals(existingId2, retrievedId) val retrievedRecipient = Recipient.resolved(retrievedId) - assertEquals(ACI_A, retrievedRecipient.requireAci()) + assertEquals(ACI_A, retrievedRecipient.requireServiceId()) assertFalse(retrievedRecipient.hasE164()) val recipientWithId1 = Recipient.resolved(existingId1) - assertEquals(ACI_B, recipientWithId1.requireAci()) + assertEquals(ACI_B, recipientWithId1.requireServiceId()) assertEquals(E164_A, recipientWithId1.requireE164()) } @@ -440,7 +437,7 @@ class RecipientDatabaseTest { assertEquals(existingId, retrievedId) val retrievedRecipient = Recipient.resolved(retrievedId) - assertEquals(ACI_A, retrievedRecipient.requireAci()) + assertEquals(ACI_A, retrievedRecipient.requireServiceId()) assertEquals(E164_A, retrievedRecipient.requireE164()) } @@ -459,7 +456,7 @@ class RecipientDatabaseTest { assertEquals(existingId, retrievedId) val retrievedRecipient = Recipient.resolved(retrievedId) - assertEquals(ACI_A, retrievedRecipient.requireAci()) + assertEquals(ACI_A, retrievedRecipient.requireServiceId()) assertEquals(E164_B, retrievedRecipient.requireE164()) } @@ -475,7 +472,7 @@ class RecipientDatabaseTest { assertEquals(existingId, retrievedId) val retrievedRecipient = Recipient.resolved(retrievedId) - assertEquals(ACI_A, retrievedRecipient.requireAci()) + assertEquals(ACI_A, retrievedRecipient.requireServiceId()) assertEquals(E164_B, retrievedRecipient.requireE164()) changeNumberListener.waitForJobManager() @@ -506,18 +503,18 @@ class RecipientDatabaseTest { @Test fun createByUuidSanityCheck() { // GIVEN one recipient - val recipientId: RecipientId = recipientDatabase.getOrInsertFromAci(ACI_A) + val recipientId: RecipientId = recipientDatabase.getOrInsertFromServiceId(ACI_A) // WHEN I retrieve one by UUID - val possible: Optional = recipientDatabase.getByAci(ACI_A) + val possible: Optional = recipientDatabase.getByServiceId(ACI_A) // THEN I get it back, and it has the properties I expect assertTrue(possible.isPresent) assertEquals(recipientId, possible.get()) val recipient = Recipient.resolved(recipientId) - assertTrue(recipient.aci.isPresent) - assertEquals(ACI_A, recipient.aci.get()) + assertTrue(recipient.serviceId.isPresent) + assertEquals(ACI_A, recipient.serviceId.get()) } @Test(expected = IllegalArgumentException::class) diff --git a/app/src/androidTest/java/org/thoughtcrime/securesms/database/RecipientDatabaseTest_merges.kt b/app/src/androidTest/java/org/thoughtcrime/securesms/database/RecipientDatabaseTest_merges.kt index 7a0b13386..c9ec6bea0 100644 --- a/app/src/androidTest/java/org/thoughtcrime/securesms/database/RecipientDatabaseTest_merges.kt +++ b/app/src/androidTest/java/org/thoughtcrime/securesms/database/RecipientDatabaseTest_merges.kt @@ -53,8 +53,8 @@ class RecipientDatabaseTest_merges { private lateinit var reactionDatabase: ReactionDatabase private lateinit var notificationProfileDatabase: NotificationProfileDatabase - private val localAci = ACI.from(UUID.randomUUID()); - private val localPni = PNI.from(UUID.randomUUID()); + private val localAci = ACI.from(UUID.randomUUID()) + private val localPni = PNI.from(UUID.randomUUID()) @Before fun setup() { @@ -80,9 +80,9 @@ class RecipientDatabaseTest_merges { @Test fun getAndPossiblyMerge_general() { // Setup - val recipientIdAci: RecipientId = recipientDatabase.getOrInsertFromAci(ACI_A) + val recipientIdAci: RecipientId = recipientDatabase.getOrInsertFromServiceId(ACI_A) val recipientIdE164: RecipientId = recipientDatabase.getOrInsertFromE164(E164_A) - val recipientIdAciB: RecipientId = recipientDatabase.getOrInsertFromAci(ACI_B) + val recipientIdAciB: RecipientId = recipientDatabase.getOrInsertFromServiceId(ACI_B) val smsId1: Long = smsDatabase.insertMessageInbox(smsMessage(sender = recipientIdAci, time = 0, body = "0")).get().messageId val smsId2: Long = smsDatabase.insertMessageInbox(smsMessage(sender = recipientIdE164, time = 1, body = "1")).get().messageId @@ -127,7 +127,7 @@ class RecipientDatabaseTest_merges { // Recipient validation val retrievedRecipient = Recipient.resolved(retrievedId) - assertEquals(ACI_A, retrievedRecipient.requireAci()) + assertEquals(ACI_A, retrievedRecipient.requireServiceId()) assertEquals(E164_A, retrievedRecipient.requireE164()) val existingE164Recipient = Recipient.resolved(recipientIdE164) diff --git a/app/src/main/java/org/thoughtcrime/securesms/ContactSelectionListFragment.java b/app/src/main/java/org/thoughtcrime/securesms/ContactSelectionListFragment.java index b20c94435..5ceacad3d 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/ContactSelectionListFragment.java +++ b/app/src/main/java/org/thoughtcrime/securesms/ContactSelectionListFragment.java @@ -571,11 +571,11 @@ public final class ContactSelectionListFragment extends LoggingFragment AlertDialog loadingDialog = SimpleProgressDialog.show(requireContext()); SimpleTask.run(getViewLifecycleOwner().getLifecycle(), () -> { - return UsernameUtil.fetchAciForUsername(requireContext(), contact.getNumber()); + return UsernameUtil.fetchAciForUsername(contact.getNumber()); }, uuid -> { loadingDialog.dismiss(); if (uuid.isPresent()) { - Recipient recipient = Recipient.externalUsername(requireContext(), uuid.get(), contact.getNumber()); + Recipient recipient = Recipient.externalUsername(uuid.get(), contact.getNumber()); SelectedContact selected = SelectedContact.forUsername(recipient.getId(), contact.getNumber()); if (onContactSelectedListener != null) { diff --git a/app/src/main/java/org/thoughtcrime/securesms/NewConversationActivity.java b/app/src/main/java/org/thoughtcrime/securesms/NewConversationActivity.java index 17de312d7..9ac1bdfbb 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/NewConversationActivity.java +++ b/app/src/main/java/org/thoughtcrime/securesms/NewConversationActivity.java @@ -75,7 +75,7 @@ public class NewConversationActivity extends ContactSelectionActivity SimpleTask.run(getLifecycle(), () -> { Recipient resolved = Recipient.external(this, number); - if (!resolved.isRegistered() || !resolved.hasAci()) { + if (!resolved.isRegistered() || !resolved.hasServiceId()) { Log.i(TAG, "[onContactSelected] Not registered or no UUID. Doing a directory refresh."); try { DirectoryHelper.refreshDirectoryFor(this, resolved, false); diff --git a/app/src/main/java/org/thoughtcrime/securesms/components/settings/conversation/InternalConversationSettingsFragment.kt b/app/src/main/java/org/thoughtcrime/securesms/components/settings/conversation/InternalConversationSettingsFragment.kt index 0e0cf423f..25e054ba3 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/components/settings/conversation/InternalConversationSettingsFragment.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/components/settings/conversation/InternalConversationSettingsFragment.kt @@ -26,8 +26,7 @@ import org.thoughtcrime.securesms.util.Hex import org.thoughtcrime.securesms.util.SpanUtil import org.thoughtcrime.securesms.util.Util import org.thoughtcrime.securesms.util.livedata.Store -import org.whispersystems.signalservice.api.push.ACI -import org.whispersystems.signalservice.api.push.PNI +import org.whispersystems.signalservice.api.push.ServiceId import java.util.Objects /** @@ -61,18 +60,11 @@ class InternalConversationSettingsFragment : DSLSettingsFragment( ) if (!recipient.isGroup) { - val aci = recipient.aci.transform(ACI::toString).or("null") + val serviceId = recipient.serviceId.transform(ServiceId::toString).or("null") longClickPref( - title = DSLSettingsText.from("ACI"), - summary = DSLSettingsText.from(aci), - onLongClick = { copyToClipboard(aci) } - ) - - val pni = recipient.pni.transform(PNI::toString).or("null") - longClickPref( - title = DSLSettingsText.from("PNI"), - summary = DSLSettingsText.from(pni), - onLongClick = { copyToClipboard(pni) } + title = DSLSettingsText.from("ServiceId"), + summary = DSLSettingsText.from(serviceId), + onLongClick = { copyToClipboard(serviceId) } ) } @@ -153,17 +145,8 @@ class InternalConversationSettingsFragment : DSLSettingsFragment( .setTitle("Are you sure?") .setNegativeButton(android.R.string.cancel) { d, _ -> d.dismiss() } .setPositiveButton(android.R.string.ok) { _, _ -> - if (recipient.hasAci()) { - SignalDatabase.sessions.deleteAllFor(accountId = Recipient.self().requireAci(), addressName = recipient.requireAci().toString()) - SignalDatabase.sessions.deleteAllFor(accountId = Recipient.self().requirePni(), addressName = recipient.requireAci().toString()) - } - if (recipient.hasE164()) { - SignalDatabase.sessions.deleteAllFor(accountId = Recipient.self().requireAci(), addressName = recipient.requireE164()) - SignalDatabase.sessions.deleteAllFor(accountId = Recipient.self().requirePni(), addressName = recipient.requireE164()) - } - if (recipient.hasPni()) { - SignalDatabase.sessions.deleteAllFor(accountId = Recipient.self().requireAci(), addressName = recipient.requirePni().toString()) - SignalDatabase.sessions.deleteAllFor(accountId = Recipient.self().requirePni(), addressName = recipient.requirePni().toString()) + if (recipient.hasServiceId()) { + SignalDatabase.sessions.deleteAllFor(serviceId = SignalStore.account().requireAci(), addressName = recipient.requireServiceId().toString()) } } .show() diff --git a/app/src/main/java/org/thoughtcrime/securesms/components/webrtc/CallParticipantsState.kt b/app/src/main/java/org/thoughtcrime/securesms/components/webrtc/CallParticipantsState.kt index 40e2b74a8..6ca50ab71 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/components/webrtc/CallParticipantsState.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/components/webrtc/CallParticipantsState.kt @@ -127,10 +127,10 @@ data class CallParticipantsState( fun getIncomingRingingGroupDescription(context: Context): String? { if (callState == WebRtcViewModel.State.CALL_INCOMING && groupCallState == WebRtcViewModel.GroupCallState.RINGING && - ringerRecipient.hasAci() + ringerRecipient.hasServiceId() ) { val ringerName = ringerRecipient.getShortDisplayName(context) - val membersWithoutYouOrRinger: List = groupMembers.filterNot { it.member.isSelf || ringerRecipient.requireAci() == it.member.aci.orNull() } + val membersWithoutYouOrRinger: List = groupMembers.filterNot { it.member.isSelf || ringerRecipient.requireServiceId() == it.member.serviceId.orNull() } return when (membersWithoutYouOrRinger.size) { 0 -> context.getString(R.string.WebRtcCallView__s_is_calling_you, ringerName) diff --git a/app/src/main/java/org/thoughtcrime/securesms/contacts/sync/DirectoryHelper.java b/app/src/main/java/org/thoughtcrime/securesms/contacts/sync/DirectoryHelper.java index 982449d40..3bd5b5244 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/contacts/sync/DirectoryHelper.java +++ b/app/src/main/java/org/thoughtcrime/securesms/contacts/sync/DirectoryHelper.java @@ -112,9 +112,9 @@ public class DirectoryHelper { RecipientDatabase recipientDatabase = SignalDatabase.recipients(); for (Recipient recipient : recipients) { - if (recipient.hasAci() && !recipient.hasE164()) { - if (ApplicationDependencies.getSignalServiceAccountManager().isIdentifierRegistered(recipient.requireAci())) { - recipientDatabase.markRegistered(recipient.getId(), recipient.requireAci()); + if (recipient.hasServiceId() && !recipient.hasE164()) { + if (ApplicationDependencies.getSignalServiceAccountManager().isIdentifierRegistered(recipient.requireServiceId())) { + recipientDatabase.markRegistered(recipient.getId(), recipient.requireServiceId()); } else { recipientDatabase.markUnregistered(recipient.getId()); } @@ -136,11 +136,11 @@ public class DirectoryHelper { RegisteredState originalRegisteredState = recipient.resolve().getRegistered(); RegisteredState newRegisteredState; - if (recipient.hasAci() && !recipient.hasE164()) { - boolean isRegistered = ApplicationDependencies.getSignalServiceAccountManager().isIdentifierRegistered(recipient.requireAci()); + if (recipient.hasServiceId() && !recipient.hasE164()) { + boolean isRegistered = ApplicationDependencies.getSignalServiceAccountManager().isIdentifierRegistered(recipient.requireServiceId()); stopwatch.split("aci-network"); if (isRegistered) { - boolean idChanged = recipientDatabase.markRegistered(recipient.getId(), recipient.requireAci()); + boolean idChanged = recipientDatabase.markRegistered(recipient.getId(), recipient.requireServiceId()); if (idChanged) { Log.w(TAG, "ID changed during refresh by UUID."); } @@ -173,14 +173,14 @@ public class DirectoryHelper { if (aci != null) { boolean idChanged = recipientDatabase.markRegistered(recipient.getId(), aci); if (idChanged) { - recipient = Recipient.resolved(recipientDatabase.getByAci(aci).get()); + recipient = Recipient.resolved(recipientDatabase.getByServiceId(aci).get()); } } else { Log.w(TAG, "Registered number set had a null ACI!"); } - } else if (recipient.hasAci() && recipient.isRegistered() && hasCommunicatedWith(recipient)) { - if (ApplicationDependencies.getSignalServiceAccountManager().isIdentifierRegistered(recipient.requireAci())) { - recipientDatabase.markRegistered(recipient.getId(), recipient.requireAci()); + } else if (recipient.hasServiceId() && recipient.isRegistered() && hasCommunicatedWith(recipient)) { + if (ApplicationDependencies.getSignalServiceAccountManager().isIdentifierRegistered(recipient.requireServiceId())) { + recipientDatabase.markRegistered(recipient.getId(), recipient.requireServiceId()); } else { recipientDatabase.markUnregistered(recipient.getId()); } @@ -485,7 +485,13 @@ public class DirectoryHelper { } public static boolean hasSession(@NonNull RecipientId id) { - SignalProtocolAddress protocolAddress = new SignalProtocolAddress(Recipient.resolved(id).requireServiceId(), SignalServiceAddress.DEFAULT_DEVICE_ID); + Recipient recipient = Recipient.resolved(id); + + if (!recipient.hasServiceId()) { + return false; + } + + SignalProtocolAddress protocolAddress = Recipient.resolved(id).requireServiceId().toProtocolAddress(SignalServiceAddress.DEFAULT_DEVICE_ID); return ApplicationDependencies.getProtocolStore().aci().containsSession(protocolAddress) || ApplicationDependencies.getProtocolStore().pni().containsSession(protocolAddress); @@ -511,7 +517,7 @@ public class DirectoryHelper { List possiblyUnlisted = Stream.of(inactiveIds) .map(Recipient::resolved) .filter(Recipient::isRegistered) - .filter(Recipient::hasAci) + .filter(Recipient::hasServiceId) .filter(DirectoryHelper::hasCommunicatedWith) .toList(); @@ -546,12 +552,9 @@ public class DirectoryHelper { } private static boolean hasCommunicatedWith(@NonNull Recipient recipient) { - ACI localAci = Recipient.self().requireAci(); + ACI localAci = SignalStore.account().requireAci(); - return SignalDatabase.threads().hasThread(recipient.getId()) || - (recipient.hasAci() && SignalDatabase.sessions().hasSessionFor(localAci, recipient.requireAci().toString())) || - (recipient.hasPni() && SignalDatabase.sessions().hasSessionFor(localAci, recipient.requirePni().toString())) || - (recipient.hasE164() && SignalDatabase.sessions().hasSessionFor(localAci, recipient.requireE164())); + return SignalDatabase.threads().hasThread(recipient.getId()) || (recipient.hasServiceId() && SignalDatabase.sessions().hasSessionFor(localAci, recipient.requireServiceId().toString())); } static class DirectoryResult { diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationParentFragment.java b/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationParentFragment.java index fde50e3e3..b3855add5 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationParentFragment.java +++ b/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationParentFragment.java @@ -1554,14 +1554,14 @@ public class ConversationParentFragment extends Fragment smsEnabled = false; } - if (!isSecureText && !isPushGroupConversation() && !recipient.get().isAciOnly() && !recipient.get().isReleaseNotes() && smsEnabled) { + if (!isSecureText && !isPushGroupConversation() && !recipient.get().isServiceIdOnly() && !recipient.get().isReleaseNotes() && smsEnabled) { sendButton.disableTransport(Type.TEXTSECURE); } if (!recipient.get().isPushGroup() && recipient.get().isForceSmsSelection() && smsEnabled) { sendButton.setDefaultTransport(Type.SMS); } else { - if (isSecureText || isPushGroupConversation() || recipient.get().isAciOnly() || recipient.get().isReleaseNotes() || !smsEnabled) { + if (isSecureText || isPushGroupConversation() || recipient.get().isServiceIdOnly() || recipient.get().isReleaseNotes() || !smsEnabled) { sendButton.setDefaultTransport(Type.TEXTSECURE); } else { sendButton.setDefaultTransport(Type.SMS); @@ -3013,7 +3013,7 @@ public class ConversationParentFragment extends Fragment return new SettableFuture<>(null); } - final boolean sendPush = (isSecureText && !forceSms) || recipient.get().isAciOnly(); + final boolean sendPush = (isSecureText && !forceSms) || recipient.get().isServiceIdOnly(); final long thread = this.threadId; if (sendPush) { @@ -3076,7 +3076,7 @@ public class ConversationParentFragment extends Fragment final long thread = this.threadId; final Context context = requireContext().getApplicationContext(); final String messageBody = getMessage(); - final boolean sendPush = (isSecureText && !forceSms) || recipient.get().isAciOnly(); + final boolean sendPush = (isSecureText && !forceSms) || recipient.get().isServiceIdOnly(); OutgoingTextMessage message; diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationUpdateItem.java b/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationUpdateItem.java index 1fe5146c1..f4acd4372 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationUpdateItem.java +++ b/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationUpdateItem.java @@ -7,7 +7,6 @@ import android.text.SpannableString; import android.util.AttributeSet; import android.view.View; import android.view.ViewGroup; -import android.view.ViewTreeObserver; import android.widget.FrameLayout; import android.widget.TextView; @@ -52,6 +51,7 @@ import org.thoughtcrime.securesms.util.concurrent.ListenableFuture; import org.thoughtcrime.securesms.util.livedata.LiveDataUtil; import org.whispersystems.libsignal.util.guava.Optional; import org.whispersystems.signalservice.api.push.ACI; +import org.whispersystems.signalservice.api.push.ServiceId; import java.util.Collection; import java.util.Locale; @@ -351,12 +351,12 @@ public final class ConversationUpdateItem extends FrameLayout } }); } else if (conversationMessage.getMessageRecord().isGroupCall()) { - UpdateDescription updateDescription = MessageRecord.getGroupCallUpdateDescription(getContext(), conversationMessage.getMessageRecord().getBody(), true); - Collection acis = updateDescription.getMentioned(); + UpdateDescription updateDescription = MessageRecord.getGroupCallUpdateDescription(getContext(), conversationMessage.getMessageRecord().getBody(), true); + Collection acis = updateDescription.getMentioned(); int text = 0; if (Util.hasItems(acis)) { - if (acis.contains(Recipient.self().requireAci())) { + if (acis.contains(Recipient.self().requireServiceId())) { text = R.string.ConversationUpdateItem_return_to_call; } else if (GroupCallUpdateDetailsUtil.parse(conversationMessage.getMessageRecord().getBody()).getIsCallFull()) { text = R.string.ConversationUpdateItem_call_is_full; diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversation/ui/error/SafetyNumberChangeRepository.java b/app/src/main/java/org/thoughtcrime/securesms/conversation/ui/error/SafetyNumberChangeRepository.java index 558afff5b..02c41c7e3 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/conversation/ui/error/SafetyNumberChangeRepository.java +++ b/app/src/main/java/org/thoughtcrime/securesms/conversation/ui/error/SafetyNumberChangeRepository.java @@ -126,7 +126,7 @@ final class SafetyNumberChangeRepository { try(SignalSessionLock.Lock unused = ReentrantSessionLock.INSTANCE.acquire()) { for (ChangedRecipient changedRecipient : changedRecipients) { - SignalProtocolAddress mismatchAddress = new SignalProtocolAddress(changedRecipient.getRecipient().requireServiceId(), SignalServiceAddress.DEFAULT_DEVICE_ID); + SignalProtocolAddress mismatchAddress = changedRecipient.getRecipient().requireServiceId().toProtocolAddress(SignalServiceAddress.DEFAULT_DEVICE_ID); Log.d(TAG, "Saving identity for: " + changedRecipient.getRecipient().getId() + " " + changedRecipient.getIdentityRecord().getIdentityKey().hashCode()); SignalIdentityKeyStore.SaveResult result = ApplicationDependencies.getProtocolStore().aci().identities().saveIdentity(mismatchAddress, changedRecipient.getIdentityRecord().getIdentityKey(), true); diff --git a/app/src/main/java/org/thoughtcrime/securesms/crypto/SenderKeyUtil.java b/app/src/main/java/org/thoughtcrime/securesms/crypto/SenderKeyUtil.java index 6a23b04ce..67b503407 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/crypto/SenderKeyUtil.java +++ b/app/src/main/java/org/thoughtcrime/securesms/crypto/SenderKeyUtil.java @@ -22,7 +22,7 @@ public final class SenderKeyUtil { */ public static void rotateOurKey(@NonNull Context context, @NonNull DistributionId distributionId) { try (SignalSessionLock.Lock unused = ReentrantSessionLock.INSTANCE.acquire()) { - ApplicationDependencies.getProtocolStore().aci().senderKeys().deleteAllFor(Recipient.self().requireServiceId(), distributionId); + ApplicationDependencies.getProtocolStore().aci().senderKeys().deleteAllFor(SignalStore.account().requireAci().toString(), distributionId); SignalDatabase.senderKeyShared().deleteAllFor(distributionId); } } @@ -31,7 +31,7 @@ public final class SenderKeyUtil { * Gets when the sender key session was created, or -1 if it doesn't exist. */ public static long getCreateTimeForOurKey(@NonNull Context context, @NonNull DistributionId distributionId) { - SignalProtocolAddress address = new SignalProtocolAddress(Recipient.self().requireServiceId(), SignalStore.account().getDeviceId()); + SignalProtocolAddress address = new SignalProtocolAddress(SignalStore.account().requireAci().toString(), SignalStore.account().getDeviceId()); return SignalDatabase.senderKeys().getCreatedTime(address, distributionId); } diff --git a/app/src/main/java/org/thoughtcrime/securesms/crypto/storage/SignalBaseIdentityKeyStore.java b/app/src/main/java/org/thoughtcrime/securesms/crypto/storage/SignalBaseIdentityKeyStore.java index 202b049b3..7efd9df63 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/crypto/storage/SignalBaseIdentityKeyStore.java +++ b/app/src/main/java/org/thoughtcrime/securesms/crypto/storage/SignalBaseIdentityKeyStore.java @@ -23,6 +23,7 @@ import org.whispersystems.libsignal.IdentityKey; import org.whispersystems.libsignal.SignalProtocolAddress; import org.whispersystems.libsignal.state.IdentityKeyStore; import org.whispersystems.libsignal.util.guava.Optional; +import org.whispersystems.signalservice.api.push.ServiceId; import java.util.ArrayList; import java.util.List; @@ -110,8 +111,8 @@ public class SignalBaseIdentityKeyStore { boolean nonBlockingApproval) { Recipient recipient = Recipient.resolved(recipientId); - if (recipient.hasServiceIdentifier()) { - cache.save(recipient.requireServiceId(), recipientId, identityKey, verifiedStatus, firstUse, timestamp, nonBlockingApproval); + if (recipient.hasServiceId()) { + cache.save(recipient.requireServiceId().toString(), recipientId, identityKey, verifiedStatus, firstUse, timestamp, nonBlockingApproval); } else { Log.w(TAG, "[saveIdentity] No serviceId for " + recipient.getId()); } @@ -120,7 +121,7 @@ public class SignalBaseIdentityKeyStore { public boolean isTrustedIdentity(SignalProtocolAddress address, IdentityKey identityKey, IdentityKeyStore.Direction direction) { Recipient self = Recipient.self(); - boolean isSelf = address.getName().equals(self.requireAci().toString()) || + boolean isSelf = address.getName().equals(self.requireServiceId().toString()) || address.getName().equals(self.requireE164()); if (isSelf) { @@ -150,19 +151,20 @@ public class SignalBaseIdentityKeyStore { } public @NonNull Optional getIdentityRecord(@NonNull Recipient recipient) { - if (recipient.hasServiceIdentifier()) { - IdentityStoreRecord record = cache.get(recipient.requireServiceId()); + if (recipient.hasServiceId()) { + IdentityStoreRecord record = cache.get(recipient.requireServiceId().toString()); return Optional.fromNullable(record).transform(r -> r.toIdentityRecord(recipient.getId())); } else { - Log.w(TAG, "[getIdentityRecord] No serviceId for " + recipient.getId()); + Log.w(TAG, "[getIdentityRecord] No ServiceId for " + recipient.getId()); return Optional.absent(); } } public @NonNull IdentityRecordList getIdentityRecords(@NonNull List recipients) { List addressNames = recipients.stream() - .filter(Recipient::hasServiceIdentifier) + .filter(Recipient::hasServiceId) .map(Recipient::requireServiceId) + .map(ServiceId::toString) .collect(Collectors.toList()); if (addressNames.isEmpty()) { @@ -172,8 +174,8 @@ public class SignalBaseIdentityKeyStore { List records = new ArrayList<>(recipients.size()); for (Recipient recipient : recipients) { - if (recipient.hasServiceIdentifier()) { - IdentityStoreRecord record = cache.get(recipient.requireServiceId()); + if (recipient.hasServiceId()) { + IdentityStoreRecord record = cache.get(recipient.requireServiceId().toString()); if (record != null) { records.add(record.toIdentityRecord(recipient.getId())); @@ -189,8 +191,8 @@ public class SignalBaseIdentityKeyStore { public void setApproval(@NonNull RecipientId recipientId, boolean nonBlockingApproval) { Recipient recipient = Recipient.resolved(recipientId); - if (recipient.hasServiceIdentifier()) { - cache.setApproval(recipient.requireServiceId(), recipientId, nonBlockingApproval); + if (recipient.hasServiceId()) { + cache.setApproval(recipient.requireServiceId().toString(), recipientId, nonBlockingApproval); } else { Log.w(TAG, "[setApproval] No serviceId for " + recipient.getId()); } @@ -199,8 +201,8 @@ public class SignalBaseIdentityKeyStore { public void setVerified(@NonNull RecipientId recipientId, IdentityKey identityKey, VerifiedStatus verifiedStatus) { Recipient recipient = Recipient.resolved(recipientId); - if (recipient.hasServiceIdentifier()) { - cache.setVerified(recipient.requireServiceId(), recipientId, identityKey, verifiedStatus); + if (recipient.hasServiceId()) { + cache.setVerified(recipient.requireServiceId().toString(), recipientId, identityKey, verifiedStatus); } else { Log.w(TAG, "[setVerified] No serviceId for " + recipient.getId()); } diff --git a/app/src/main/java/org/thoughtcrime/securesms/crypto/storage/SignalServiceDataStoreImpl.java b/app/src/main/java/org/thoughtcrime/securesms/crypto/storage/SignalServiceDataStoreImpl.java index 53d02ec29..0542837e6 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/crypto/storage/SignalServiceDataStoreImpl.java +++ b/app/src/main/java/org/thoughtcrime/securesms/crypto/storage/SignalServiceDataStoreImpl.java @@ -7,7 +7,7 @@ import androidx.annotation.NonNull; import org.thoughtcrime.securesms.keyvalue.SignalStore; import org.thoughtcrime.securesms.util.TextSecurePreferences; import org.whispersystems.signalservice.api.SignalServiceDataStore; -import org.whispersystems.signalservice.api.push.AccountIdentifier; +import org.whispersystems.signalservice.api.push.ServiceId; public final class SignalServiceDataStoreImpl implements SignalServiceDataStore { @@ -25,7 +25,7 @@ public final class SignalServiceDataStoreImpl implements SignalServiceDataStore } @Override - public SignalServiceAccountDataStoreImpl get(@NonNull AccountIdentifier accountIdentifier) { + public SignalServiceAccountDataStoreImpl get(@NonNull ServiceId accountIdentifier) { if (accountIdentifier.equals(SignalStore.account().getAci())) { return aciStore; } else if (accountIdentifier.equals(SignalStore.account().getPni())) { diff --git a/app/src/main/java/org/thoughtcrime/securesms/crypto/storage/TextSecurePreKeyStore.java b/app/src/main/java/org/thoughtcrime/securesms/crypto/storage/TextSecurePreKeyStore.java index 29f5d334a..b5877948d 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/crypto/storage/TextSecurePreKeyStore.java +++ b/app/src/main/java/org/thoughtcrime/securesms/crypto/storage/TextSecurePreKeyStore.java @@ -9,7 +9,7 @@ import org.whispersystems.libsignal.state.PreKeyRecord; import org.whispersystems.libsignal.state.PreKeyStore; import org.whispersystems.libsignal.state.SignedPreKeyRecord; import org.whispersystems.libsignal.state.SignedPreKeyStore; -import org.whispersystems.signalservice.api.push.AccountIdentifier; +import org.whispersystems.signalservice.api.push.ServiceId; import java.util.List; @@ -21,9 +21,9 @@ public class TextSecurePreKeyStore implements PreKeyStore, SignedPreKeyStore { private static final Object LOCK = new Object(); @NonNull - private final AccountIdentifier accountId; + private final ServiceId accountId; - public TextSecurePreKeyStore(@NonNull AccountIdentifier accountId) { + public TextSecurePreKeyStore(@NonNull ServiceId accountId) { this.accountId = accountId; } diff --git a/app/src/main/java/org/thoughtcrime/securesms/crypto/storage/TextSecureSessionStore.java b/app/src/main/java/org/thoughtcrime/securesms/crypto/storage/TextSecureSessionStore.java index 36403a99e..7abd00d20 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/crypto/storage/TextSecureSessionStore.java +++ b/app/src/main/java/org/thoughtcrime/securesms/crypto/storage/TextSecureSessionStore.java @@ -1,7 +1,5 @@ package org.thoughtcrime.securesms.crypto.storage; -import android.content.Context; - import androidx.annotation.NonNull; import androidx.annotation.Nullable; @@ -15,7 +13,7 @@ import org.whispersystems.libsignal.SignalProtocolAddress; import org.whispersystems.libsignal.protocol.CiphertextMessage; import org.whispersystems.libsignal.state.SessionRecord; import org.whispersystems.signalservice.api.SignalServiceSessionStore; -import org.whispersystems.signalservice.api.push.AccountIdentifier; +import org.whispersystems.signalservice.api.push.ServiceId; import java.util.List; import java.util.Objects; @@ -28,9 +26,9 @@ public class TextSecureSessionStore implements SignalServiceSessionStore { private static final Object LOCK = new Object(); - private final AccountIdentifier accountId; + private final ServiceId accountId; - public TextSecureSessionStore(@NonNull AccountIdentifier accountId) { + public TextSecureSessionStore(@NonNull ServiceId accountId) { this.accountId = accountId; } @@ -135,8 +133,8 @@ public class TextSecureSessionStore implements SignalServiceSessionStore { synchronized (LOCK) { Recipient recipient = Recipient.resolved(recipientId); - if (recipient.hasAci()) { - archiveSession(new SignalProtocolAddress(recipient.requireAci().toString(), deviceId)); + if (recipient.hasServiceId()) { + archiveSession(new SignalProtocolAddress(recipient.requireServiceId().toString(), deviceId)); } if (recipient.hasE164()) { diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/GroupDatabase.java b/app/src/main/java/org/thoughtcrime/securesms/database/GroupDatabase.java index 8ed48223a..622982f70 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/GroupDatabase.java +++ b/app/src/main/java/org/thoughtcrime/securesms/database/GroupDatabase.java @@ -25,6 +25,7 @@ import org.thoughtcrime.securesms.crypto.SenderKeyUtil; import org.thoughtcrime.securesms.dependencies.ApplicationDependencies; import org.thoughtcrime.securesms.groups.v2.processing.GroupsV2StateProcessor; import org.thoughtcrime.securesms.jobs.RequestGroupV2InfoJob; +import org.thoughtcrime.securesms.keyvalue.SignalStore; import org.whispersystems.signalservice.api.push.ACI; import org.whispersystems.signalservice.api.push.DistributionId; import org.thoughtcrime.securesms.groups.GroupAccessControl; @@ -40,6 +41,7 @@ import org.whispersystems.libsignal.util.guava.Optional; import org.whispersystems.signalservice.api.groupsv2.DecryptedGroupUtil; import org.whispersystems.signalservice.api.groupsv2.GroupChangeReconstruct; import org.whispersystems.signalservice.api.messages.SignalServiceAttachmentPointer; +import org.whispersystems.signalservice.api.push.ServiceId; import org.whispersystems.signalservice.api.util.UuidUtil; import java.io.Closeable; @@ -821,7 +823,7 @@ private static final String[] GROUP_PROJECTION = { } private static boolean gv2GroupActive(@NonNull DecryptedGroup decryptedGroup) { - ACI aci = Recipient.self().requireAci(); + ACI aci = SignalStore.account().requireAci(); return DecryptedGroupUtil.findMemberByUuid(decryptedGroup.getMembersList(), aci.uuid()).isPresent() || DecryptedGroupUtil.findPendingByUuid(decryptedGroup.getPendingMembersList(), aci.uuid()).isPresent(); @@ -1232,9 +1234,9 @@ private static final String[] GROUP_PROJECTION = { */ public boolean isPendingMember(@NonNull Recipient recipient) { if (isV2Group()) { - Optional aci = recipient.getAci(); - if (aci.isPresent()) { - return DecryptedGroupUtil.findPendingByUuid(requireV2GroupProperties().getDecryptedGroup().getPendingMembersList(), aci.get().uuid()) + Optional serviceId = recipient.getServiceId(); + if (serviceId.isPresent()) { + return DecryptedGroupUtil.findPendingByUuid(requireV2GroupProperties().getDecryptedGroup().getPendingMembersList(), serviceId.get().uuid()) .isPresent(); } } @@ -1275,13 +1277,13 @@ private static final String[] GROUP_PROJECTION = { } public boolean isAdmin(@NonNull Recipient recipient) { - Optional aci = recipient.getAci(); + Optional serviceId = recipient.getServiceId(); - if (!aci.isPresent()) { + if (!serviceId.isPresent()) { return false; } - return DecryptedGroupUtil.findMemberByUuid(getDecryptedGroup().getMembersList(), aci.get().uuid()) + return DecryptedGroupUtil.findMemberByUuid(getDecryptedGroup().getMembersList(), serviceId.get().uuid()) .transform(t -> t.getRole() == Member.Role.ADMINISTRATOR) .or(false); } @@ -1291,21 +1293,21 @@ private static final String[] GROUP_PROJECTION = { } public MemberLevel memberLevel(@NonNull Recipient recipient) { - Optional aci = recipient.getAci(); + Optional serviceId = recipient.getServiceId(); - if (!aci.isPresent()) { + if (!serviceId.isPresent()) { return MemberLevel.NOT_A_MEMBER; } DecryptedGroup decryptedGroup = getDecryptedGroup(); - return DecryptedGroupUtil.findMemberByUuid(decryptedGroup.getMembersList(), aci.get().uuid()) + return DecryptedGroupUtil.findMemberByUuid(decryptedGroup.getMembersList(), serviceId.get().uuid()) .transform(member -> member.getRole() == Member.Role.ADMINISTRATOR ? MemberLevel.ADMINISTRATOR : MemberLevel.FULL_MEMBER) - .or(() -> DecryptedGroupUtil.findPendingByUuid(decryptedGroup.getPendingMembersList(), aci.get().uuid()) + .or(() -> DecryptedGroupUtil.findPendingByUuid(decryptedGroup.getPendingMembersList(), serviceId.get().uuid()) .transform(m -> MemberLevel.PENDING_MEMBER) - .or(() -> DecryptedGroupUtil.findRequestingByUuid(decryptedGroup.getRequestingMembersList(), aci.get().uuid()) + .or(() -> DecryptedGroupUtil.findRequestingByUuid(decryptedGroup.getRequestingMembersList(), serviceId.get().uuid()) .transform(m -> MemberLevel.REQUESTING_MEMBER) .or(MemberLevel.NOT_A_MEMBER))); } @@ -1317,7 +1319,7 @@ private static final String[] GROUP_PROJECTION = { public List getMemberRecipientIds(@NonNull MemberSet memberSet) { boolean includeSelf = memberSet.includeSelf; DecryptedGroup groupV2 = getDecryptedGroup(); - UUID selfUuid = Recipient.self().requireAci().uuid(); + UUID selfUuid = Recipient.self().requireServiceId().uuid(); List recipients = new ArrayList<>(groupV2.getMembersCount() + groupV2.getPendingMembersCount()); int unknownMembers = 0; int unknownPending = 0; diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/MentionUtil.java b/app/src/main/java/org/thoughtcrime/securesms/database/MentionUtil.java index 08338fdd8..ee8703e22 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/MentionUtil.java +++ b/app/src/main/java/org/thoughtcrime/securesms/database/MentionUtil.java @@ -19,7 +19,6 @@ import org.thoughtcrime.securesms.database.model.databaseprotos.BodyRangeList; import org.thoughtcrime.securesms.recipients.Recipient; import org.thoughtcrime.securesms.recipients.RecipientId; import org.whispersystems.signalservice.api.push.ACI; -import org.whispersystems.signalservice.api.util.UuidUtil; import java.util.ArrayList; import java.util.Collections; @@ -106,7 +105,7 @@ public final class MentionUtil { BodyRangeList.Builder builder = BodyRangeList.newBuilder(); for (Mention mention : mentions) { - String uuid = Recipient.resolved(mention.getRecipientId()).requireAci().toString(); + String uuid = Recipient.resolved(mention.getRecipientId()).requireServiceId().toString(); builder.addRanges(BodyRangeList.BodyRange.newBuilder() .setMentionUuid(uuid) .setStart(mention.getStart()) @@ -122,7 +121,7 @@ public final class MentionUtil { return Stream.of(BodyRangeList.parseFrom(data).getRangesList()) .filter(bodyRange -> bodyRange.getAssociatedValueCase() == BodyRangeList.BodyRange.AssociatedValueCase.MENTIONUUID) .map(mention -> { - RecipientId id = Recipient.externalPush(context, ACI.parseOrThrow(mention.getMentionUuid()), null, false).getId(); + RecipientId id = Recipient.externalPush(ACI.parseOrThrow(mention.getMentionUuid()), null, false).getId(); return new Mention(id, mention.getStart(), mention.getLength()); }) .toList(); diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/OneTimePreKeyDatabase.kt b/app/src/main/java/org/thoughtcrime/securesms/database/OneTimePreKeyDatabase.kt index 10268895f..89199695f 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/OneTimePreKeyDatabase.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/database/OneTimePreKeyDatabase.kt @@ -9,7 +9,7 @@ import org.whispersystems.libsignal.InvalidKeyException import org.whispersystems.libsignal.ecc.Curve import org.whispersystems.libsignal.ecc.ECKeyPair import org.whispersystems.libsignal.state.PreKeyRecord -import org.whispersystems.signalservice.api.push.AccountIdentifier +import org.whispersystems.signalservice.api.push.ServiceId import java.io.IOException class OneTimePreKeyDatabase(context: Context, databaseHelper: SignalDatabase) : Database(context, databaseHelper) { @@ -34,8 +34,8 @@ class OneTimePreKeyDatabase(context: Context, databaseHelper: SignalDatabase) : """ } - fun get(accountId: AccountIdentifier, keyId: Int): PreKeyRecord? { - readableDatabase.query(TABLE_NAME, null, "$ACCOUNT_ID = ? AND $KEY_ID = ?", SqlUtil.buildArgs(accountId, keyId), null, null, null).use { cursor -> + fun get(serviceId: ServiceId, keyId: Int): PreKeyRecord? { + readableDatabase.query(TABLE_NAME, null, "$ACCOUNT_ID = ? AND $KEY_ID = ?", SqlUtil.buildArgs(serviceId, keyId), null, null, null).use { cursor -> if (cursor.moveToFirst()) { try { val publicKey = Curve.decodePoint(Base64.decode(cursor.requireNonNullString(PUBLIC_KEY)), 0) @@ -52,9 +52,9 @@ class OneTimePreKeyDatabase(context: Context, databaseHelper: SignalDatabase) : return null } - fun insert(accountId: AccountIdentifier, keyId: Int, record: PreKeyRecord) { + fun insert(serviceId: ServiceId, keyId: Int, record: PreKeyRecord) { val contentValues = contentValuesOf( - ACCOUNT_ID to accountId.toString(), + ACCOUNT_ID to serviceId.toString(), KEY_ID to keyId, PUBLIC_KEY to Base64.encodeBytes(record.keyPair.publicKey.serialize()), PRIVATE_KEY to Base64.encodeBytes(record.keyPair.privateKey.serialize()) @@ -63,8 +63,8 @@ class OneTimePreKeyDatabase(context: Context, databaseHelper: SignalDatabase) : writableDatabase.replace(TABLE_NAME, null, contentValues) } - fun delete(accountId: AccountIdentifier, keyId: Int) { + fun delete(serviceId: ServiceId, keyId: Int) { val database = databaseHelper.signalWritableDatabase - database.delete(TABLE_NAME, "$ACCOUNT_ID = ? AND $KEY_ID = ?", SqlUtil.buildArgs(accountId, keyId)) + database.delete(TABLE_NAME, "$ACCOUNT_ID = ? AND $KEY_ID = ?", SqlUtil.buildArgs(serviceId, keyId)) } } diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/RecipientDatabase.kt b/app/src/main/java/org/thoughtcrime/securesms/database/RecipientDatabase.kt index 44c51773c..29a905660 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/RecipientDatabase.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/database/RecipientDatabase.kt @@ -79,6 +79,7 @@ import org.whispersystems.libsignal.util.guava.Optional import org.whispersystems.signalservice.api.profiles.SignalServiceProfile import org.whispersystems.signalservice.api.push.ACI import org.whispersystems.signalservice.api.push.PNI +import org.whispersystems.signalservice.api.push.ServiceId import org.whispersystems.signalservice.api.push.SignalServiceAddress import org.whispersystems.signalservice.api.storage.SignalAccountRecord import org.whispersystems.signalservice.api.storage.SignalContactRecord @@ -110,7 +111,7 @@ open class RecipientDatabase(context: Context, databaseHelper: SignalDatabase) : const val TABLE_NAME = "recipient" const val ID = "_id" - private const val ACI_COLUMN = "uuid" + private const val SERVICE_ID = "uuid" private const val PNI_COLUMN = "pni" private const val USERNAME = "username" const val PHONE = "phone" @@ -171,7 +172,7 @@ open class RecipientDatabase(context: Context, databaseHelper: SignalDatabase) : """ CREATE TABLE $TABLE_NAME ( $ID INTEGER PRIMARY KEY AUTOINCREMENT, - $ACI_COLUMN TEXT UNIQUE DEFAULT NULL, + $SERVICE_ID TEXT UNIQUE DEFAULT NULL, $USERNAME TEXT UNIQUE DEFAULT NULL, $PHONE TEXT UNIQUE DEFAULT NULL, $EMAIL TEXT UNIQUE DEFAULT NULL, @@ -232,7 +233,7 @@ open class RecipientDatabase(context: Context, databaseHelper: SignalDatabase) : private val RECIPIENT_PROJECTION: Array = arrayOf( ID, - ACI_COLUMN, + SERVICE_ID, PNI_COLUMN, USERNAME, PHONE, @@ -367,7 +368,7 @@ open class RecipientDatabase(context: Context, databaseHelper: SignalDatabase) : } fun containsPhoneOrUuid(id: String): Boolean { - val query = "$ACI_COLUMN = ? OR $PHONE = ?" + val query = "$SERVICE_ID = ? OR $PHONE = ?" val args = arrayOf(id, id) readableDatabase.query(TABLE_NAME, arrayOf(ID), query, args, null, null, null).use { cursor -> return cursor != null && cursor.moveToFirst() } } @@ -384,20 +385,20 @@ open class RecipientDatabase(context: Context, databaseHelper: SignalDatabase) : return getByColumn(GROUP_ID, groupId.toString()) } - fun getByAci(uuid: ACI): Optional { - return getByColumn(ACI_COLUMN, uuid.toString()) + fun getByServiceId(serviceId: ServiceId): Optional { + return getByColumn(SERVICE_ID, serviceId.toString()) } fun getByUsername(username: String): Optional { return getByColumn(USERNAME, username) } - fun getAndPossiblyMerge(aci: ACI?, e164: String?, highTrust: Boolean): RecipientId { - return getAndPossiblyMerge(aci, e164, highTrust, false) + fun getAndPossiblyMerge(serviceId: ServiceId?, e164: String?, highTrust: Boolean): RecipientId { + return getAndPossiblyMerge(serviceId, e164, highTrust, false) } - fun getAndPossiblyMerge(aci: ACI?, e164: String?, highTrust: Boolean, changeSelf: Boolean): RecipientId { - require(!(aci == null && e164 == null)) { "Must provide an ACI or E164!" } + fun getAndPossiblyMerge(serviceId: ServiceId?, e164: String?, highTrust: Boolean, changeSelf: Boolean): RecipientId { + require(!(serviceId == null && e164 == null)) { "Must provide an ACI or E164!" } val db = writableDatabase @@ -408,7 +409,7 @@ open class RecipientDatabase(context: Context, databaseHelper: SignalDatabase) : db.beginTransaction() try { - val fetch: RecipientFetch = fetchRecipient(aci, e164, highTrust, changeSelf) + val fetch: RecipientFetch = fetchRecipient(serviceId, e164, highTrust, changeSelf) if (fetch.logBundle != null) { Log.w(TAG, fetch.toString()) @@ -432,29 +433,29 @@ open class RecipientDatabase(context: Context, databaseHelper: SignalDatabase) : fetch.id } is RecipientFetch.MatchAndUpdateAci -> { - markRegistered(fetch.id, fetch.aci) + markRegistered(fetch.id, fetch.serviceId) recipientsNeedingRefresh = listOf(fetch.id) fetch.id } is RecipientFetch.MatchAndInsertAci -> { - val id = db.insert(TABLE_NAME, null, buildContentValuesForNewUser(null, fetch.aci)) + val id = db.insert(TABLE_NAME, null, buildContentValuesForNewUser(null, fetch.serviceId)) RecipientId.from(id) } is RecipientFetch.MatchAndMerge -> { - remapped = Pair(fetch.e164Id, fetch.aciId) - val mergedId: RecipientId = merge(fetch.aciId, fetch.e164Id) + remapped = Pair(fetch.e164Id, fetch.sidId) + val mergedId: RecipientId = merge(fetch.sidId, fetch.e164Id) recipientsNeedingRefresh = listOf(mergedId) recipientChangedNumber = fetch.changedNumber mergedId } is RecipientFetch.Insert -> { - val id = db.insert(TABLE_NAME, null, buildContentValuesForNewUser(fetch.e164, fetch.aci)) + val id = db.insert(TABLE_NAME, null, buildContentValuesForNewUser(fetch.e164, fetch.serviceId)) RecipientId.from(id) } is RecipientFetch.InsertAndReassignE164 -> { removePhoneNumber(fetch.e164Id, db) recipientsNeedingRefresh = listOf(fetch.e164Id) - val id = db.insert(TABLE_NAME, null, buildContentValuesForNewUser(fetch.e164, fetch.aci)) + val id = db.insert(TABLE_NAME, null, buildContentValuesForNewUser(fetch.e164, fetch.serviceId)) RecipientId.from(id) } } @@ -488,12 +489,12 @@ open class RecipientDatabase(context: Context, databaseHelper: SignalDatabase) : } } - private fun fetchRecipient(aci: ACI?, e164: String?, highTrust: Boolean, changeSelf: Boolean): RecipientFetch { + private fun fetchRecipient(serviceId: ServiceId?, e164: String?, highTrust: Boolean, changeSelf: Boolean): RecipientFetch { val byE164 = e164?.let { getByE164(it) } ?: Optional.absent() - val byAci = aci?.let { getByAci(it) } ?: Optional.absent() + val byAci = serviceId?.let { getByServiceId(it) } ?: Optional.absent() var logs = LogBundle( - byAci = byAci.transform { id -> RecipientLogDetails(id = id) }.orNull(), + bySid = byAci.transform { id -> RecipientLogDetails(id = id) }.orNull(), byE164 = byE164.transform { id -> RecipientLogDetails(id = id) }.orNull(), label = "L0" ) @@ -504,9 +505,9 @@ open class RecipientDatabase(context: Context, databaseHelper: SignalDatabase) : if (byAci.isPresent && byE164.isAbsent()) { val aciRecord: RecipientRecord = getRecord(byAci.get()) - logs = logs.copy(byAci = aciRecord.toLogDetails()) + logs = logs.copy(bySid = aciRecord.toLogDetails()) - if (highTrust && e164 != null && (changeSelf || aci != SignalStore.account().aci)) { + if (highTrust && e164 != null && (changeSelf || serviceId != SignalStore.account().aci)) { val changedNumber: RecipientId? = if (aciRecord.e164 != null && aciRecord.e164 != e164) aciRecord.id else null return RecipientFetch.MatchAndUpdateE164(byAci.get(), e164, changedNumber, logs.label("L1")) } else if (e164 == null) { @@ -520,12 +521,12 @@ open class RecipientDatabase(context: Context, databaseHelper: SignalDatabase) : val e164Record: RecipientRecord = getRecord(byE164.get()) logs = logs.copy(byE164 = e164Record.toLogDetails()) - if (highTrust && aci != null && e164Record.aci == null) { - return RecipientFetch.MatchAndUpdateAci(byE164.get(), aci, logs.label("L3")) - } else if (highTrust && aci != null && e164Record.aci != SignalStore.account().aci) { - return RecipientFetch.InsertAndReassignE164(aci, e164, byE164.get(), logs.label("L4")) - } else if (aci != null) { - return RecipientFetch.Insert(aci, null, logs.label("L5")) + if (highTrust && serviceId != null && e164Record.serviceId == null) { + return RecipientFetch.MatchAndUpdateAci(byE164.get(), serviceId, logs.label("L3")) + } else if (highTrust && serviceId != null && e164Record.serviceId != SignalStore.account().aci) { + return RecipientFetch.InsertAndReassignE164(serviceId, e164, byE164.get(), logs.label("L4")) + } else if (serviceId != null) { + return RecipientFetch.Insert(serviceId, null, logs.label("L5")) } else { return RecipientFetch.Match(byE164.get(), null) } @@ -533,9 +534,9 @@ open class RecipientDatabase(context: Context, databaseHelper: SignalDatabase) : if (byAci.isAbsent() && byE164.isAbsent()) { if (highTrust) { - return RecipientFetch.Insert(aci, e164, logs.label("L6")) - } else if (aci != null) { - return RecipientFetch.Insert(aci, null, logs.label("L7")) + return RecipientFetch.Insert(serviceId, e164, logs.label("L6")) + } else if (serviceId != null) { + return RecipientFetch.Insert(serviceId, null, logs.label("L7")) } else { return RecipientFetch.Insert(null, e164, logs.label("L8")) } @@ -546,17 +547,17 @@ open class RecipientDatabase(context: Context, databaseHelper: SignalDatabase) : val aciRecord: RecipientRecord = getRecord(byAci.get()) val e164Record: RecipientRecord = getRecord(byE164.get()) - logs = logs.copy(byAci = aciRecord.toLogDetails(), byE164 = e164Record.toLogDetails()) + logs = logs.copy(bySid = aciRecord.toLogDetails(), byE164 = e164Record.toLogDetails()) - if (e164Record.aci == null) { + if (e164Record.serviceId == null) { if (highTrust) { val changedNumber: RecipientId? = if (aciRecord.e164 != null) aciRecord.id else null - return RecipientFetch.MatchAndMerge(aciId = byAci.get(), e164Id = byE164.get(), changedNumber = changedNumber, logs.label("L9")) + return RecipientFetch.MatchAndMerge(sidId = byAci.get(), e164Id = byE164.get(), changedNumber = changedNumber, logs.label("L9")) } else { return RecipientFetch.Match(byAci.get(), logs.label("L10")) } } else { - if (highTrust && e164Record.aci != SignalStore.account().aci) { + if (highTrust && e164Record.serviceId != SignalStore.account().aci) { val changedNumber: RecipientId? = if (aciRecord.e164 != null) aciRecord.id else null return RecipientFetch.MatchAndReassignE164(id = byAci.get(), e164Id = byE164.get(), e164 = e164!!, changedNumber = changedNumber, logs.label("L11")) } else { @@ -565,8 +566,8 @@ open class RecipientDatabase(context: Context, databaseHelper: SignalDatabase) : } } - fun getOrInsertFromAci(aci: ACI): RecipientId { - return getOrInsertByColumn(ACI_COLUMN, aci.toString()).recipientId + fun getOrInsertFromServiceId(serviceId: ServiceId): RecipientId { + return getOrInsertByColumn(SERVICE_ID, serviceId.toString()).recipientId } fun getOrInsertFromE164(e164: String): RecipientId { @@ -785,13 +786,13 @@ open class RecipientDatabase(context: Context, databaseHelper: SignalDatabase) : val recipientId: RecipientId? if (id < 0) { Log.w(TAG, "[applyStorageSyncContactInsert] Failed to insert. Possibly merging.") - recipientId = getAndPossiblyMerge(if (insert.address.hasValidAci()) insert.address.aci else null, insert.address.number.orNull(), true) + recipientId = getAndPossiblyMerge(if (insert.address.hasValidServiceId()) insert.address.serviceId else null, insert.address.number.orNull(), true) db.update(TABLE_NAME, values, ID_WHERE, SqlUtil.buildArgs(recipientId)) } else { recipientId = RecipientId.from(id) } - if (insert.identityKey.isPresent && insert.address.hasValidAci()) { + if (insert.identityKey.isPresent && insert.address.hasValidServiceId()) { try { val identityKey = IdentityKey(insert.identityKey.get(), 0) identities.updateIdentityAfterSync(insert.address.identifier, recipientId!!, identityKey, StorageSyncModels.remoteToLocalIdentityStatus(insert.identityState)) @@ -818,7 +819,7 @@ open class RecipientDatabase(context: Context, databaseHelper: SignalDatabase) : var recipientId = getByColumn(STORAGE_SERVICE_ID, Base64.encodeBytes(update.old.id.raw)).get() Log.w(TAG, "[applyStorageSyncContactUpdate] Found user $recipientId. Possibly merging.") - recipientId = getAndPossiblyMerge(if (update.new.address.hasValidAci()) update.new.address.aci else null, update.new.address.number.orNull(), true) + recipientId = getAndPossiblyMerge(if (update.new.address.hasValidServiceId()) update.new.address.serviceId else null, update.new.address.number.orNull(), true) Log.w(TAG, "[applyStorageSyncContactUpdate] Merged into $recipientId") db.update(TABLE_NAME, values, ID_WHERE, SqlUtil.buildArgs(recipientId)) @@ -834,7 +835,7 @@ open class RecipientDatabase(context: Context, databaseHelper: SignalDatabase) : try { val oldIdentityRecord = identityStore.getIdentityRecord(recipientId) - if (update.new.identityKey.isPresent && update.new.address.hasValidAci()) { + if (update.new.identityKey.isPresent && update.new.address.hasValidServiceId()) { val identityKey = IdentityKey(update.new.identityKey.get(), 0) identities.updateIdentityAfterSync(update.new.address.identifier, recipientId, identityKey, StorageSyncModels.remoteToLocalIdentityStatus(update.new.identityState)) } @@ -982,7 +983,7 @@ open class RecipientDatabase(context: Context, databaseHelper: SignalDatabase) : private fun getRecordForSync(query: String?, args: Array?): List { val table = """ - $TABLE_NAME LEFT OUTER JOIN ${IdentityDatabase.TABLE_NAME} ON $TABLE_NAME.$ACI_COLUMN = ${IdentityDatabase.TABLE_NAME}.${IdentityDatabase.ADDRESS} + $TABLE_NAME LEFT OUTER JOIN ${IdentityDatabase.TABLE_NAME} ON $TABLE_NAME.$SERVICE_ID = ${IdentityDatabase.TABLE_NAME}.${IdentityDatabase.ADDRESS} LEFT OUTER JOIN ${GroupDatabase.TABLE_NAME} ON $TABLE_NAME.$GROUP_ID = ${GroupDatabase.TABLE_NAME}.${GroupDatabase.GROUP_ID} LEFT OUTER JOIN ${ThreadDatabase.TABLE_NAME} ON $TABLE_NAME.$ID = ${ThreadDatabase.TABLE_NAME}.${ThreadDatabase.RECIPIENT_ID} """.trimIndent() @@ -1018,7 +1019,7 @@ open class RecipientDatabase(context: Context, databaseHelper: SignalDatabase) : fun getContactStorageSyncIdsMap(): Map { val query = """ $STORAGE_SERVICE_ID NOT NULL AND ( - ($GROUP_TYPE = ? AND $ACI_COLUMN NOT NULL AND $ID != ?) + ($GROUP_TYPE = ? AND $SERVICE_ID NOT NULL AND $ID != ?) OR $GROUP_TYPE IN (?) ) @@ -1505,7 +1506,7 @@ open class RecipientDatabase(context: Context, databaseHelper: SignalDatabase) : val selfId = Recipient.self().id for ((key, value) in profileKeys) { - val recipientId = getOrInsertFromAci(key) + val recipientId = getOrInsertFromServiceId(key) if (setProfileKeyIfAbsent(recipientId, value)) { Log.i(TAG, "Learned new profile key") updated.add(recipientId) @@ -1513,7 +1514,7 @@ open class RecipientDatabase(context: Context, databaseHelper: SignalDatabase) : } for ((key, value) in authoritativeProfileKeys) { - val recipientId = getOrInsertFromAci(key) + val recipientId = getOrInsertFromServiceId(key) if (selfId == recipientId) { Log.i(TAG, "Seen authoritative update for self") @@ -1760,7 +1761,7 @@ open class RecipientDatabase(context: Context, databaseHelper: SignalDatabase) : Log.w(TAG, "[setPhoneNumber] Hit a conflict when trying to update $id. Possibly merging.") val existing: RecipientRecord = getRecord(id) - val newId = getAndPossiblyMerge(existing.aci, e164, true) + val newId = getAndPossiblyMerge(existing.serviceId, e164, true) Log.w(TAG, "[setPhoneNumber] Resulting id: $newId") db.setTransactionSuccessful() @@ -1812,7 +1813,7 @@ open class RecipientDatabase(context: Context, databaseHelper: SignalDatabase) : db.beginTransaction() try { val id = Recipient.self().id - val newId = getAndPossiblyMerge(Recipient.self().requireAci(), e164, highTrust = true, changeSelf = true) + val newId = getAndPossiblyMerge(Recipient.self().requireServiceId(), e164, highTrust = true, changeSelf = true) if (id == newId) { Log.i(TAG, "[updateSelfPhone] Phone updated for self") @@ -1874,19 +1875,19 @@ open class RecipientDatabase(context: Context, databaseHelper: SignalDatabase) : /** * @return True if setting the UUID resulted in changed recipientId, otherwise false. */ - fun markRegistered(id: RecipientId, aci: ACI): Boolean { + fun markRegistered(id: RecipientId, serviceId: ServiceId): Boolean { val db = writableDatabase db.beginTransaction() try { - markRegisteredOrThrow(id, aci) + markRegisteredOrThrow(id, serviceId) db.setTransactionSuccessful() return false } catch (e: SQLiteConstraintException) { Log.w(TAG, "[markRegistered] Hit a conflict when trying to update $id. Possibly merging.") val existing = getRecord(id) - val newId = getAndPossiblyMerge(aci, existing.e164, true) + val newId = getAndPossiblyMerge(serviceId, existing.e164, true) Log.w(TAG, "[markRegistered] Merged into $newId") db.setTransactionSuccessful() @@ -1899,10 +1900,10 @@ open class RecipientDatabase(context: Context, databaseHelper: SignalDatabase) : /** * Should only use if you are confident that this shouldn't result in any contact merging. */ - fun markRegisteredOrThrow(id: RecipientId, aci: ACI) { + fun markRegisteredOrThrow(id: RecipientId, serviceId: ServiceId) { val contentValues = ContentValues(2).apply { put(REGISTERED, RegisteredState.REGISTERED.id) - put(ACI_COLUMN, aci.toString().toLowerCase()) + put(SERVICE_ID, serviceId.toString().toLowerCase()) } if (update(id, contentValues)) { setStorageIdIfNotSet(id) @@ -1920,7 +1921,7 @@ open class RecipientDatabase(context: Context, databaseHelper: SignalDatabase) : } } - fun bulkUpdatedRegisteredStatus(registered: Map, unregistered: Collection) { + fun bulkUpdatedRegisteredStatus(registered: Map, unregistered: Collection) { val db = writableDatabase db.beginTransaction() @@ -1929,7 +1930,7 @@ open class RecipientDatabase(context: Context, databaseHelper: SignalDatabase) : val values = ContentValues(2).apply { put(REGISTERED, RegisteredState.REGISTERED.id) if (aci != null) { - put(ACI_COLUMN, aci.toString().toLowerCase()) + put(SERVICE_ID, aci.toString().toLowerCase()) } } @@ -1972,12 +1973,12 @@ open class RecipientDatabase(context: Context, databaseHelper: SignalDatabase) : db.beginTransaction() try { for ((e164, aci) in mapping) { - var aciEntry = if (aci != null) getByAci(aci) else Optional.absent() + var aciEntry = if (aci != null) getByServiceId(aci) else Optional.absent() if (aciEntry.isPresent) { val idChanged = setPhoneNumber(aciEntry.get(), e164) if (idChanged) { - aciEntry = getByAci(aci!!) + aciEntry = getByServiceId(aci!!) } } @@ -2272,7 +2273,7 @@ open class RecipientDatabase(context: Context, databaseHelper: SignalDatabase) : .toList() val blockedUuid = blocked - .map { b: SignalServiceAddress -> b.aci.toString().toLowerCase() } + .map { b: SignalServiceAddress -> b.serviceId.toString().toLowerCase() } .toList() val db = writableDatabase @@ -2293,7 +2294,7 @@ open class RecipientDatabase(context: Context, databaseHelper: SignalDatabase) : } for (uuid in blockedUuid) { - db.update(TABLE_NAME, setBlocked, "$ACI_COLUMN = ?", arrayOf(uuid)) + db.update(TABLE_NAME, setBlocked, "$SERVICE_ID = ?", arrayOf(uuid)) } val groupIdStrings: MutableList = ArrayList(groupIds.size) @@ -2604,10 +2605,10 @@ open class RecipientDatabase(context: Context, databaseHelper: SignalDatabase) : } // Sessions - val localAci: ACI = SignalStore.account().aci!! + val localAci: ACI = SignalStore.account().requireAci() val sessionDatabase = sessions val hasE164Session = sessionDatabase.getAllFor(localAci, e164Record.e164).isNotEmpty() - val hasAciSession = sessionDatabase.getAllFor(localAci, aciRecord.aci.toString()).isNotEmpty() + val hasAciSession = sessionDatabase.getAllFor(localAci, aciRecord.serviceId.toString()).isNotEmpty() if (hasE164Session && hasAciSession) { Log.w(TAG, "Had a session for both users. Deleting the E164.", true) @@ -2615,7 +2616,7 @@ open class RecipientDatabase(context: Context, databaseHelper: SignalDatabase) : } else if (hasE164Session && !hasAciSession) { Log.w(TAG, "Had a session for E164, but not ACI. Re-assigning to the ACI.", true) val values = ContentValues().apply { - put(SessionDatabase.ADDRESS, aciRecord.aci.toString()) + put(SessionDatabase.ADDRESS, aciRecord.serviceId.toString()) } db.update(SessionDatabase.TABLE_NAME, values, "${SessionDatabase.ACCOUNT_ID} = ? AND ${SessionDatabase.ADDRESS} = ?", SqlUtil.buildArgs(localAci, e164Record.e164)) } else if (!hasE164Session && hasAciSession) { @@ -2694,11 +2695,11 @@ open class RecipientDatabase(context: Context, databaseHelper: SignalDatabase) : check(writableDatabase.inTransaction()) { "Must be in a transaction!" } } - private fun buildContentValuesForNewUser(e164: String?, aci: ACI?): ContentValues { + private fun buildContentValuesForNewUser(e164: String?, serviceId: ServiceId?): ContentValues { val values = ContentValues() values.put(PHONE, e164) - if (aci != null) { - values.put(ACI_COLUMN, aci.toString().toLowerCase()) + if (serviceId != null) { + values.put(SERVICE_ID, serviceId.toString().toLowerCase()) values.put(REGISTERED, RegisteredState.REGISTERED.id) values.put(STORAGE_SERVICE_ID, Base64.encodeBytes(StorageSyncHelper.generateKey())) values.put(AVATAR_COLOR, AvatarColor.random().serialize()) @@ -2711,8 +2712,8 @@ open class RecipientDatabase(context: Context, databaseHelper: SignalDatabase) : val profileName = ProfileName.fromParts(contact.givenName.orNull(), contact.familyName.orNull()) val username = contact.username.orNull() - if (contact.address.hasValidAci()) { - put(ACI_COLUMN, contact.address.aci.toString()) + if (contact.address.hasValidServiceId()) { + put(SERVICE_ID, contact.address.serviceId.toString()) } put(PHONE, contact.address.number.orNull()) @@ -2845,7 +2846,7 @@ open class RecipientDatabase(context: Context, databaseHelper: SignalDatabase) : return RecipientRecord( id = recipientId, - aci = ACI.parseOrNull(cursor.requireString(ACI_COLUMN)), + serviceId = ACI.parseOrNull(cursor.requireString(SERVICE_ID)), pni = PNI.parseOrNull(cursor.requireString(PNI_COLUMN)), username = cursor.requireString(USERNAME), e164 = cursor.requireString(PHONE), @@ -3045,7 +3046,7 @@ open class RecipientDatabase(context: Context, databaseHelper: SignalDatabase) : private fun RecipientRecord.toLogDetails(): RecipientLogDetails { return RecipientLogDetails( id = this.id, - aci = this.aci, + serviceId = this.serviceId, e164 = this.e164 ) } @@ -3357,27 +3358,27 @@ open class RecipientDatabase(context: Context, databaseHelper: SignalDatabase) : /** * We found a matching recipient and can update them with a new ACI. */ - data class MatchAndUpdateAci(val id: RecipientId, val aci: ACI, val bundle: LogBundle) : RecipientFetch(bundle) + data class MatchAndUpdateAci(val id: RecipientId, val serviceId: ServiceId, val bundle: LogBundle) : RecipientFetch(bundle) /** * We found a matching recipient and can insert an ACI as a *new user*. */ - data class MatchAndInsertAci(val id: RecipientId, val aci: ACI, val bundle: LogBundle) : RecipientFetch(bundle) + data class MatchAndInsertAci(val id: RecipientId, val serviceId: ServiceId, val bundle: LogBundle) : RecipientFetch(bundle) /** * The ACI maps to ACI-only recipient, and the E164 maps to a different E164-only recipient. We need to merge the two together. */ - data class MatchAndMerge(val aciId: RecipientId, val e164Id: RecipientId, val changedNumber: RecipientId?, val bundle: LogBundle) : RecipientFetch(bundle) + data class MatchAndMerge(val sidId: RecipientId, val e164Id: RecipientId, val changedNumber: RecipientId?, val bundle: LogBundle) : RecipientFetch(bundle) /** * We don't have a matching recipient, so we need to insert one. */ - data class Insert(val aci: ACI?, val e164: String?, val bundle: LogBundle) : RecipientFetch(bundle) + data class Insert(val serviceId: ServiceId?, val e164: String?, val bundle: LogBundle) : RecipientFetch(bundle) /** * We need to create a new recipient and give it the E164 of an existing recipient. */ - data class InsertAndReassignE164(val aci: ACI?, val e164: String?, val e164Id: RecipientId, val bundle: LogBundle) : RecipientFetch(bundle) + data class InsertAndReassignE164(val serviceId: ServiceId?, val e164: String?, val e164Id: RecipientId, val bundle: LogBundle) : RecipientFetch(bundle) } /** @@ -3385,9 +3386,9 @@ open class RecipientDatabase(context: Context, databaseHelper: SignalDatabase) : */ private data class LogBundle( val label: String, - val aci: ACI? = null, + val serviceId: ServiceId? = null, val e164: String? = null, - val byAci: RecipientLogDetails? = null, + val bySid: RecipientLogDetails? = null, val byE164: RecipientLogDetails? = null ) { fun label(label: String): LogBundle { @@ -3400,7 +3401,7 @@ open class RecipientDatabase(context: Context, databaseHelper: SignalDatabase) : */ private data class RecipientLogDetails( val id: RecipientId, - val aci: ACI? = null, + val serviceId: ServiceId? = null, val e164: String? = null ) } diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/SenderKeyDatabase.java b/app/src/main/java/org/thoughtcrime/securesms/database/SenderKeyDatabase.java index d58fe373b..1c36552e1 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/SenderKeyDatabase.java +++ b/app/src/main/java/org/thoughtcrime/securesms/database/SenderKeyDatabase.java @@ -133,7 +133,7 @@ public class SenderKeyDatabase extends Database { public Cursor getAllCreatedBySelf() { SQLiteDatabase db = databaseHelper.getSignalReadableDatabase(); String query = ADDRESS + " = ?"; - String[] args = SqlUtil.buildArgs(Recipient.self().requireAci()); + String[] args = SqlUtil.buildArgs(Recipient.self().requireServiceId()); return db.query(TABLE_NAME, new String[]{ ID, DISTRIBUTION_ID, CREATED_AT }, query, args, null, null, CREATED_AT + " DESC"); } diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/SenderKeySharedDatabase.java b/app/src/main/java/org/thoughtcrime/securesms/database/SenderKeySharedDatabase.java index 7a995f7b1..37f066cd4 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/SenderKeySharedDatabase.java +++ b/app/src/main/java/org/thoughtcrime/securesms/database/SenderKeySharedDatabase.java @@ -145,8 +145,8 @@ public class SenderKeySharedDatabase extends Database { SQLiteDatabase db = databaseHelper.getSignalWritableDatabase(); Recipient recipient = Recipient.resolved(recipientId); - if (recipient.hasAci()) { - db.delete(TABLE_NAME, ADDRESS + " = ?", SqlUtil.buildArgs(recipient.requireAci().toString())); + if (recipient.hasServiceId()) { + db.delete(TABLE_NAME, ADDRESS + " = ?", SqlUtil.buildArgs(recipient.requireServiceId().toString())); } else { Log.w(TAG, "Recipient doesn't have a UUID! " + recipientId); } diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/SessionDatabase.kt b/app/src/main/java/org/thoughtcrime/securesms/database/SessionDatabase.kt index 94a419b3e..50d3d5f67 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/SessionDatabase.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/database/SessionDatabase.kt @@ -6,7 +6,7 @@ import org.thoughtcrime.securesms.util.CursorUtil import org.thoughtcrime.securesms.util.SqlUtil import org.whispersystems.libsignal.SignalProtocolAddress import org.whispersystems.libsignal.state.SessionRecord -import org.whispersystems.signalservice.api.push.AccountIdentifier +import org.whispersystems.signalservice.api.push.ServiceId import org.whispersystems.signalservice.api.push.SignalServiceAddress import java.io.IOException import java.util.ArrayList @@ -36,12 +36,12 @@ class SessionDatabase(context: Context, databaseHelper: SignalDatabase) : Databa """ } - fun store(accountId: AccountIdentifier, address: SignalProtocolAddress, record: SessionRecord) { + fun store(serviceId: ServiceId, address: SignalProtocolAddress, record: SessionRecord) { require(address.name[0] != '+') { "Cannot insert an e164 into this table!" } writableDatabase.compileStatement("INSERT INTO $TABLE_NAME ($ACCOUNT_ID, $ADDRESS, $DEVICE, $RECORD) VALUES (?, ?, ?, ?) ON CONFLICT ($ACCOUNT_ID, $ADDRESS, $DEVICE) DO UPDATE SET $RECORD = excluded.$RECORD").use { statement -> statement.apply { - bindString(1, accountId.toString()) + bindString(1, serviceId.toString()) bindString(2, address.name) bindLong(3, address.deviceId.toLong()) bindBlob(4, record.serialize()) @@ -50,10 +50,10 @@ class SessionDatabase(context: Context, databaseHelper: SignalDatabase) : Databa } } - fun load(accountId: AccountIdentifier, address: SignalProtocolAddress): SessionRecord? { + fun load(serviceId: ServiceId, address: SignalProtocolAddress): SessionRecord? { val projection = arrayOf(RECORD) val selection = "$ACCOUNT_ID = ? AND $ADDRESS = ? AND $DEVICE = ?" - val args = SqlUtil.buildArgs(accountId, address.name, address.deviceId) + val args = SqlUtil.buildArgs(serviceId, address.name, address.deviceId) readableDatabase.query(TABLE_NAME, projection, selection, args, null, null, null).use { cursor -> if (cursor.moveToFirst()) { @@ -68,14 +68,14 @@ class SessionDatabase(context: Context, databaseHelper: SignalDatabase) : Databa return null } - fun load(accountId: AccountIdentifier, addresses: List): List { + fun load(serviceId: ServiceId, addresses: List): List { val projection = arrayOf(ADDRESS, DEVICE, RECORD) val query = "$ACCOUNT_ID = ? AND $ADDRESS = ? AND $DEVICE = ?" val args: MutableList> = ArrayList(addresses.size) val sessions: HashMap = LinkedHashMap(addresses.size) for (address in addresses) { - args.add(SqlUtil.buildArgs(accountId, address.name, address.deviceId)) + args.add(SqlUtil.buildArgs(serviceId, address.name, address.deviceId)) sessions[address] = null } @@ -97,10 +97,10 @@ class SessionDatabase(context: Context, databaseHelper: SignalDatabase) : Databa return sessions.values.toList() } - fun getAllFor(accountId: AccountIdentifier, addressName: String): List { + fun getAllFor(serviceId: ServiceId, addressName: String): List { val results: MutableList = mutableListOf() - readableDatabase.query(TABLE_NAME, null, "$ACCOUNT_ID = ? AND $ADDRESS = ?", SqlUtil.buildArgs(accountId, addressName), null, null, null).use { cursor -> + readableDatabase.query(TABLE_NAME, null, "$ACCOUNT_ID = ? AND $ADDRESS = ?", SqlUtil.buildArgs(serviceId, addressName), null, null, null).use { cursor -> while (cursor.moveToNext()) { try { results.add( @@ -118,12 +118,12 @@ class SessionDatabase(context: Context, databaseHelper: SignalDatabase) : Databa return results } - fun getAllFor(accountId: AccountIdentifier, addressNames: List): List { + fun getAllFor(serviceId: ServiceId, addressNames: List): List { val query: SqlUtil.Query = SqlUtil.buildCollectionQuery(ADDRESS, addressNames) val results: MutableList = LinkedList() val queryString = "$ACCOUNT_ID = ? AND (${query.where})" - val queryArgs: Array = arrayOf(accountId.toString()) + query.whereArgs + val queryArgs: Array = arrayOf(serviceId.toString()) + query.whereArgs readableDatabase.query(TABLE_NAME, null, queryString, queryArgs, null, null, null).use { cursor -> while (cursor.moveToNext()) { @@ -143,10 +143,10 @@ class SessionDatabase(context: Context, databaseHelper: SignalDatabase) : Databa return results } - fun getAll(accountId: AccountIdentifier): List { + fun getAll(serviceId: ServiceId): List { val results: MutableList = mutableListOf() - readableDatabase.query(TABLE_NAME, null, "$ACCOUNT_ID = ?", SqlUtil.buildArgs(accountId), null, null, null).use { cursor -> + readableDatabase.query(TABLE_NAME, null, "$ACCOUNT_ID = ?", SqlUtil.buildArgs(serviceId), null, null, null).use { cursor -> while (cursor.moveToNext()) { try { results.add( @@ -164,10 +164,10 @@ class SessionDatabase(context: Context, databaseHelper: SignalDatabase) : Databa return results } - fun getSubDevices(accountId: AccountIdentifier, addressName: String): List { + fun getSubDevices(serviceId: ServiceId, addressName: String): List { val projection = arrayOf(DEVICE) val selection = "$ACCOUNT_ID = ? AND $ADDRESS = ? AND $DEVICE != ?" - val args = SqlUtil.buildArgs(accountId, addressName, SignalServiceAddress.DEFAULT_DEVICE_ID) + val args = SqlUtil.buildArgs(serviceId, addressName, SignalServiceAddress.DEFAULT_DEVICE_ID) val results: MutableList = mutableListOf() @@ -179,17 +179,17 @@ class SessionDatabase(context: Context, databaseHelper: SignalDatabase) : Databa return results } - fun delete(accountId: AccountIdentifier, address: SignalProtocolAddress) { - writableDatabase.delete(TABLE_NAME, "$ACCOUNT_ID = ? AND $ADDRESS = ? AND $DEVICE = ?", SqlUtil.buildArgs(accountId, address.name, address.deviceId)) + fun delete(serviceId: ServiceId, address: SignalProtocolAddress) { + writableDatabase.delete(TABLE_NAME, "$ACCOUNT_ID = ? AND $ADDRESS = ? AND $DEVICE = ?", SqlUtil.buildArgs(serviceId, address.name, address.deviceId)) } - fun deleteAllFor(accountId: AccountIdentifier, addressName: String) { - writableDatabase.delete(TABLE_NAME, "$ACCOUNT_ID = ? AND $ADDRESS = ?", SqlUtil.buildArgs(accountId, addressName)) + fun deleteAllFor(serviceId: ServiceId, addressName: String) { + writableDatabase.delete(TABLE_NAME, "$ACCOUNT_ID = ? AND $ADDRESS = ?", SqlUtil.buildArgs(serviceId, addressName)) } - fun hasSessionFor(accountId: AccountIdentifier, addressName: String): Boolean { + fun hasSessionFor(serviceId: ServiceId, addressName: String): Boolean { val query = "$ACCOUNT_ID = ? AND $ADDRESS = ?" - val args = SqlUtil.buildArgs(accountId, addressName) + val args = SqlUtil.buildArgs(serviceId, addressName) readableDatabase.query(TABLE_NAME, arrayOf("1"), query, args, null, null, null, "1").use { cursor -> return cursor.moveToFirst() } diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/SignedPreKeyDatabase.kt b/app/src/main/java/org/thoughtcrime/securesms/database/SignedPreKeyDatabase.kt index 7c5d88465..76303b9d1 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/SignedPreKeyDatabase.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/database/SignedPreKeyDatabase.kt @@ -9,7 +9,7 @@ import org.whispersystems.libsignal.InvalidKeyException import org.whispersystems.libsignal.ecc.Curve import org.whispersystems.libsignal.ecc.ECKeyPair import org.whispersystems.libsignal.state.SignedPreKeyRecord -import org.whispersystems.signalservice.api.push.AccountIdentifier +import org.whispersystems.signalservice.api.push.ServiceId import java.io.IOException import java.util.LinkedList @@ -39,8 +39,8 @@ class SignedPreKeyDatabase(context: Context, databaseHelper: SignalDatabase) : D """ } - fun get(accountId: AccountIdentifier, keyId: Int): SignedPreKeyRecord? { - readableDatabase.query(TABLE_NAME, null, "$ACCOUNT_ID = ? AND $KEY_ID = ?", SqlUtil.buildArgs(accountId, keyId), null, null, null).use { cursor -> + fun get(serviceId: ServiceId, keyId: Int): SignedPreKeyRecord? { + readableDatabase.query(TABLE_NAME, null, "$ACCOUNT_ID = ? AND $KEY_ID = ?", SqlUtil.buildArgs(serviceId, keyId), null, null, null).use { cursor -> if (cursor.moveToFirst()) { try { val publicKey = Curve.decodePoint(Base64.decode(cursor.requireNonNullString(PUBLIC_KEY)), 0) @@ -58,10 +58,10 @@ class SignedPreKeyDatabase(context: Context, databaseHelper: SignalDatabase) : D return null } - fun getAll(accountId: AccountIdentifier): List { + fun getAll(serviceId: ServiceId): List { val results: MutableList = LinkedList() - readableDatabase.query(TABLE_NAME, null, "$ACCOUNT_ID = ?", SqlUtil.buildArgs(accountId), null, null, null).use { cursor -> + readableDatabase.query(TABLE_NAME, null, "$ACCOUNT_ID = ?", SqlUtil.buildArgs(serviceId), null, null, null).use { cursor -> while (cursor.moveToNext()) { try { val keyId = cursor.requireInt(KEY_ID) @@ -81,9 +81,9 @@ class SignedPreKeyDatabase(context: Context, databaseHelper: SignalDatabase) : D return results } - fun insert(accountId: AccountIdentifier, keyId: Int, record: SignedPreKeyRecord) { + fun insert(serviceId: ServiceId, keyId: Int, record: SignedPreKeyRecord) { val contentValues = contentValuesOf( - ACCOUNT_ID to accountId.toString(), + ACCOUNT_ID to serviceId.toString(), KEY_ID to keyId, PUBLIC_KEY to Base64.encodeBytes(record.keyPair.publicKey.serialize()), PRIVATE_KEY to Base64.encodeBytes(record.keyPair.privateKey.serialize()), @@ -93,7 +93,7 @@ class SignedPreKeyDatabase(context: Context, databaseHelper: SignalDatabase) : D writableDatabase.replace(TABLE_NAME, null, contentValues) } - fun delete(accountId: AccountIdentifier, keyId: Int) { - writableDatabase.delete(TABLE_NAME, "$ACCOUNT_ID = ? AND $KEY_ID = ?", SqlUtil.buildArgs(accountId, keyId)) + fun delete(serviceId: ServiceId, keyId: Int) { + writableDatabase.delete(TABLE_NAME, "$ACCOUNT_ID = ? AND $KEY_ID = ?", SqlUtil.buildArgs(serviceId, keyId)) } } 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 029196c0c..12357ecca 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/SmsDatabase.java +++ b/app/src/main/java/org/thoughtcrime/securesms/database/SmsDatabase.java @@ -719,11 +719,11 @@ public class SmsDatabase extends MessageDatabase { if (!peerEraIdSameAsPrevious && !Util.isEmpty(peekGroupCallEraId)) { Recipient self = Recipient.self(); - boolean markRead = peekJoinedUuids.contains(self.requireAci().uuid()) || self.getId().equals(sender); + boolean markRead = peekJoinedUuids.contains(self.requireServiceId().uuid()) || self.getId().equals(sender); byte[] updateDetails = GroupCallUpdateDetails.newBuilder() .setEraId(Util.emptyIfNull(peekGroupCallEraId)) - .setStartedCallUuid(Recipient.resolved(sender).requireAci().toString()) + .setStartedCallUuid(Recipient.resolved(sender).requireServiceId().toString()) .setStartedCallTimestamp(timestamp) .addAllInCallUuids(Stream.of(peekJoinedUuids).map(UUID::toString).toList()) .setIsCallFull(isCallFull) @@ -800,7 +800,7 @@ public class SmsDatabase extends MessageDatabase { if (!sameEraId && !Util.isEmpty(messageGroupCallEraId)) { byte[] updateDetails = GroupCallUpdateDetails.newBuilder() .setEraId(Util.emptyIfNull(messageGroupCallEraId)) - .setStartedCallUuid(Recipient.resolved(sender).requireAci().toString()) + .setStartedCallUuid(Recipient.resolved(sender).requireServiceId().toString()) .setStartedCallTimestamp(timestamp) .addAllInCallUuids(Collections.emptyList()) .setIsCallFull(false) @@ -849,7 +849,7 @@ public class SmsDatabase extends MessageDatabase { } GroupCallUpdateDetails groupCallUpdateDetails = GroupCallUpdateDetailsUtil.parse(record.getBody()); - boolean containsSelf = peekJoinedUuids.contains(Recipient.self().requireAci().uuid()); + boolean containsSelf = peekJoinedUuids.contains(Recipient.self().requireServiceId().uuid()); sameEraId = groupCallUpdateDetails.getEraId().equals(peekGroupCallEraId) && !Util.isEmpty(peekGroupCallEraId); 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 0584cec8e..3d2ed53e7 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/ThreadDatabase.java +++ b/app/src/main/java/org/thoughtcrime/securesms/database/ThreadDatabase.java @@ -1208,7 +1208,7 @@ public class ThreadDatabase extends Database { Recipient pinnedRecipient; if (pinned.getContact().isPresent()) { - pinnedRecipient = Recipient.externalPush(context, pinned.getContact().get()); + pinnedRecipient = Recipient.externalPush(pinned.getContact().get()); } else if (pinned.getGroupV1Id().isPresent()) { try { pinnedRecipient = Recipient.externalGroupExact(context, GroupId.v1(pinned.getGroupV1Id().get())); diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/model/GroupCallUpdateMessageFactory.java b/app/src/main/java/org/thoughtcrime/securesms/database/model/GroupCallUpdateMessageFactory.java index 3658ad975..812daeb40 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/model/GroupCallUpdateMessageFactory.java +++ b/app/src/main/java/org/thoughtcrime/securesms/database/model/GroupCallUpdateMessageFactory.java @@ -6,11 +6,12 @@ import androidx.annotation.NonNull; import org.thoughtcrime.securesms.R; import org.thoughtcrime.securesms.database.model.databaseprotos.GroupCallUpdateDetails; +import org.thoughtcrime.securesms.keyvalue.SignalStore; import org.thoughtcrime.securesms.recipients.Recipient; import org.thoughtcrime.securesms.recipients.RecipientId; import org.thoughtcrime.securesms.util.DateUtils; -import org.thoughtcrime.securesms.util.TextSecurePreferences; import org.whispersystems.signalservice.api.push.ACI; +import org.whispersystems.signalservice.api.push.ServiceId; import java.util.ArrayList; import java.util.List; @@ -22,13 +23,13 @@ import java.util.Objects; */ public class GroupCallUpdateMessageFactory implements UpdateDescription.StringFactory { private final Context context; - private final List joinedMembers; + private final List joinedMembers; private final boolean withTime; private final GroupCallUpdateDetails groupCallUpdateDetails; private final ACI selfAci; public GroupCallUpdateMessageFactory(@NonNull Context context, - @NonNull List joinedMembers, + @NonNull List joinedMembers, boolean withTime, @NonNull GroupCallUpdateDetails groupCallUpdateDetails) { @@ -36,7 +37,7 @@ public class GroupCallUpdateMessageFactory implements UpdateDescription.StringFa this.joinedMembers = new ArrayList<>(joinedMembers); this.withTime = withTime; this.groupCallUpdateDetails = groupCallUpdateDetails; - this.selfAci = Recipient.self().requireAci(); + this.selfAci = SignalStore.account().requireAci(); boolean removed = this.joinedMembers.remove(selfAci); if (removed) { @@ -87,12 +88,12 @@ public class GroupCallUpdateMessageFactory implements UpdateDescription.StringFa } } - private @NonNull String describe(@NonNull ACI aci) { - if (aci.isUnknown()) { + private @NonNull String describe(@NonNull ServiceId serviceId) { + if (serviceId.isUnknown()) { return context.getString(R.string.MessageRecord_unknown); } - Recipient recipient = Recipient.resolved(RecipientId.from(aci, null)); + Recipient recipient = Recipient.resolved(RecipientId.from(serviceId, null)); if (recipient.isSelf()) { return context.getString(R.string.MessageRecord_you); diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/model/GroupsV2UpdateMessageProducer.java b/app/src/main/java/org/thoughtcrime/securesms/database/model/GroupsV2UpdateMessageProducer.java index 098e2d6f9..86e4fff08 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/model/GroupsV2UpdateMessageProducer.java +++ b/app/src/main/java/org/thoughtcrime/securesms/database/model/GroupsV2UpdateMessageProducer.java @@ -27,6 +27,7 @@ import org.thoughtcrime.securesms.util.StringUtil; import org.whispersystems.libsignal.util.guava.Optional; import org.whispersystems.signalservice.api.groupsv2.DecryptedGroupUtil; import org.whispersystems.signalservice.api.push.ACI; +import org.whispersystems.signalservice.api.push.ServiceId; import org.whispersystems.signalservice.api.util.UuidUtil; import java.util.Arrays; @@ -746,11 +747,11 @@ final class GroupsV2UpdateMessageProducer { /** * Map an ACI to a string that describes the group member. - * @param aci + * @param serviceId */ @NonNull @WorkerThread - String describe(@NonNull ACI aci); + String describe(@NonNull ServiceId serviceId); } private interface StringFactory1Arg { @@ -771,9 +772,9 @@ final class GroupsV2UpdateMessageProducer { @NonNull StringFactory1Arg stringFactory, @DrawableRes int iconResource) { - ACI aci1 = ACI.fromByteStringOrUnknown(uuid1Bytes); + ServiceId serviceId = ServiceId.fromByteStringOrUnknown(uuid1Bytes); - return UpdateDescription.mentioning(Collections.singletonList(aci1), () -> stringFactory.create(descriptionStrategy.describe(aci1)), iconResource); + return UpdateDescription.mentioning(Collections.singletonList(serviceId), () -> stringFactory.create(descriptionStrategy.describe(serviceId)), iconResource); } private UpdateDescription updateDescription(@NonNull ByteString uuid1Bytes, @@ -781,9 +782,9 @@ final class GroupsV2UpdateMessageProducer { @NonNull StringFactory2Args stringFactory, @DrawableRes int iconResource) { - ACI aci1 = ACI.fromByteStringOrUnknown(uuid1Bytes); - ACI aci2 = ACI.fromByteStringOrUnknown(uuid2Bytes); + ServiceId sid1 = ServiceId.fromByteStringOrUnknown(uuid1Bytes); + ServiceId sid2 = ServiceId.fromByteStringOrUnknown(uuid2Bytes); - return UpdateDescription.mentioning(Arrays.asList(aci1, aci2), () -> stringFactory.create(descriptionStrategy.describe(aci1), descriptionStrategy.describe(aci2)), iconResource); + return UpdateDescription.mentioning(Arrays.asList(sid1, sid2), () -> stringFactory.create(descriptionStrategy.describe(sid1), descriptionStrategy.describe(sid2)), iconResource); } } \ No newline at end of file diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/model/MessageRecord.java b/app/src/main/java/org/thoughtcrime/securesms/database/model/MessageRecord.java index f6903f671..daab92096 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/model/MessageRecord.java +++ b/app/src/main/java/org/thoughtcrime/securesms/database/model/MessageRecord.java @@ -60,7 +60,7 @@ import org.thoughtcrime.securesms.util.StringUtil; import org.thoughtcrime.securesms.util.Util; import org.whispersystems.libsignal.util.guava.Function; import org.whispersystems.signalservice.api.groupsv2.DecryptedGroupUtil; -import org.whispersystems.signalservice.api.push.ACI; +import org.whispersystems.signalservice.api.push.ServiceId; import org.whispersystems.signalservice.api.util.UuidUtil; import java.io.IOException; @@ -253,7 +253,7 @@ public abstract class MessageRecord extends DisplayRecord { private static boolean selfCreatedGroup(@NonNull DecryptedGroupChange change) { return change.getRevision() == 0 && - change.getEditor().equals(UuidUtil.toByteString(Recipient.self().requireAci().uuid())); + change.getEditor().equals(UuidUtil.toByteString(Recipient.self().requireServiceId().uuid())); } public static @NonNull UpdateDescription getGv2ChangeDescription(@NonNull Context context, @NonNull String body) { @@ -261,7 +261,7 @@ public abstract class MessageRecord extends DisplayRecord { ShortStringDescriptionStrategy descriptionStrategy = new ShortStringDescriptionStrategy(context); byte[] decoded = Base64.decode(body); DecryptedGroupV2Context decryptedGroupV2Context = DecryptedGroupV2Context.parseFrom(decoded); - GroupsV2UpdateMessageProducer updateMessageProducer = new GroupsV2UpdateMessageProducer(context, descriptionStrategy, Recipient.self().requireAci().uuid()); + GroupsV2UpdateMessageProducer updateMessageProducer = new GroupsV2UpdateMessageProducer(context, descriptionStrategy, Recipient.self().requireServiceId().uuid()); if (decryptedGroupV2Context.hasChange() && (decryptedGroupV2Context.getGroupState().getRevision() != 0 || decryptedGroupV2Context.hasPreviousGroupState())) { return UpdateDescription.concatWithNewLines(updateMessageProducer.describeChanges(decryptedGroupV2Context.getPreviousGroupState(), decryptedGroupV2Context.getChange())); @@ -292,7 +292,7 @@ public abstract class MessageRecord extends DisplayRecord { } DecryptedGroup groupState = decryptedGroupV2Context.getGroupState(); - boolean invited = DecryptedGroupUtil.findPendingByUuid(groupState.getPendingMembersList(), Recipient.self().requireAci().uuid()).isPresent(); + boolean invited = DecryptedGroupUtil.findPendingByUuid(groupState.getPendingMembersList(), Recipient.self().requireServiceId().uuid()).isPresent(); if (decryptedGroupV2Context.hasChange()) { UUID changeEditor = UuidUtil.fromByteStringOrNull(decryptedGroupV2Context.getChange().getEditor()); @@ -314,7 +314,7 @@ public abstract class MessageRecord extends DisplayRecord { @NonNull Function stringGenerator, @DrawableRes int iconResource) { - return UpdateDescription.mentioning(Collections.singletonList(recipient.getAci().or(ACI.UNKNOWN)), + return UpdateDescription.mentioning(Collections.singletonList(recipient.getServiceId().or(ServiceId.UNKNOWN)), () -> stringGenerator.apply(recipient.resolve()), iconResource); } @@ -382,11 +382,11 @@ public abstract class MessageRecord extends DisplayRecord { public static @NonNull UpdateDescription getGroupCallUpdateDescription(@NonNull Context context, @NonNull String body, boolean withTime) { GroupCallUpdateDetails groupCallUpdateDetails = GroupCallUpdateDetailsUtil.parse(body); - List joinedMembers = Stream.of(groupCallUpdateDetails.getInCallUuidsList()) - .map(UuidUtil::parseOrNull) - .withoutNulls() - .map(ACI::from) - .toList(); + List joinedMembers = Stream.of(groupCallUpdateDetails.getInCallUuidsList()) + .map(UuidUtil::parseOrNull) + .withoutNulls() + .map(ServiceId::from) + .toList(); UpdateDescription.StringFactory stringFactory = new GroupCallUpdateMessageFactory(context, joinedMembers, withTime, groupCallUpdateDetails); @@ -421,11 +421,11 @@ public abstract class MessageRecord extends DisplayRecord { } @Override - public @NonNull String describe(@NonNull ACI aci) { - if (aci.isUnknown()) { + public @NonNull String describe(@NonNull ServiceId serviceId) { + if (serviceId.isUnknown()) { return context.getString(R.string.MessageRecord_unknown); } - return Recipient.resolved(RecipientId.from(aci, null)).getDisplayName(context); + return Recipient.resolved(RecipientId.from(serviceId, null)).getDisplayName(context); } } diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/model/RecipientRecord.kt b/app/src/main/java/org/thoughtcrime/securesms/database/model/RecipientRecord.kt index 839c34d5c..aa50a1220 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/model/RecipientRecord.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/database/model/RecipientRecord.kt @@ -20,15 +20,15 @@ import org.thoughtcrime.securesms.recipients.Recipient import org.thoughtcrime.securesms.recipients.RecipientId import org.thoughtcrime.securesms.wallpaper.ChatWallpaper import org.whispersystems.libsignal.util.guava.Optional -import org.whispersystems.signalservice.api.push.ACI import org.whispersystems.signalservice.api.push.PNI +import org.whispersystems.signalservice.api.push.ServiceId /** * Database model for [RecipientDatabase]. */ data class RecipientRecord( val id: RecipientId, - val aci: ACI?, + val serviceId: ServiceId?, val pni: PNI?, val username: String?, val e164: String?, diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/model/UpdateDescription.java b/app/src/main/java/org/thoughtcrime/securesms/database/model/UpdateDescription.java index c92675cf2..2e5d1df4e 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/model/UpdateDescription.java +++ b/app/src/main/java/org/thoughtcrime/securesms/database/model/UpdateDescription.java @@ -9,6 +9,7 @@ import androidx.annotation.WorkerThread; import org.signal.core.util.ThreadUtil; import org.whispersystems.signalservice.api.push.ACI; +import org.whispersystems.signalservice.api.push.ServiceId; import org.whispersystems.signalservice.api.util.UuidUtil; import java.util.Collection; @@ -28,14 +29,14 @@ public final class UpdateDescription { String create(); } - private final Collection mentioned; - private final StringFactory stringFactory; - private final String staticString; - private final int lightIconResource; - private final int lightTint; - private final int darkTint; + private final Collection mentioned; + private final StringFactory stringFactory; + private final String staticString; + private final int lightIconResource; + private final int lightTint; + private final int darkTint; - private UpdateDescription(@NonNull Collection mentioned, + private UpdateDescription(@NonNull Collection mentioned, @Nullable StringFactory stringFactory, @Nullable String staticString, @DrawableRes int iconResource, @@ -60,11 +61,11 @@ public final class UpdateDescription { * @param mentioned UUIDs of recipients that are mentioned in the string. * @param stringFactory The background method for generating the string. */ - public static UpdateDescription mentioning(@NonNull Collection mentioned, + public static UpdateDescription mentioning(@NonNull Collection mentioned, @NonNull StringFactory stringFactory, @DrawableRes int iconResource) { - return new UpdateDescription(ACI.filterKnown(mentioned), + return new UpdateDescription(ServiceId.filterKnown(mentioned), stringFactory, null, iconResource, @@ -118,7 +119,7 @@ public final class UpdateDescription { } @AnyThread - public Collection getMentioned() { + public Collection getMentioned() { return mentioned; } @@ -149,7 +150,7 @@ public final class UpdateDescription { ); } - Set allMentioned = new HashSet<>(); + Set allMentioned = new HashSet<>(); for (UpdateDescription updateDescription : updateDescriptions) { allMentioned.addAll(updateDescription.getMentioned()); 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 a133931c3..87cf0a7ce 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/groups/GroupManagerV2.java +++ b/app/src/main/java/org/thoughtcrime/securesms/groups/GroupManagerV2.java @@ -104,7 +104,7 @@ final class GroupManagerV2 { this.groupsV2Operations = ApplicationDependencies.getGroupsV2Operations(); this.authorization = ApplicationDependencies.getGroupsV2Authorization(); this.groupsV2StateProcessor = ApplicationDependencies.getGroupsV2StateProcessor(); - this.selfAci = Recipient.self().requireAci(); + this.selfAci = SignalStore.account().requireAci(); this.groupCandidateHelper = new GroupCandidateHelper(context); } @@ -142,7 +142,7 @@ final class GroupManagerV2 { Map uuidCipherTexts = new HashMap<>(); for (Recipient recipient : recipients) { - uuidCipherTexts.put(recipient.requireAci().uuid(), clientZkGroupCipher.encryptUuid(recipient.requireAci().uuid())); + uuidCipherTexts.put(recipient.requireServiceId().uuid(), clientZkGroupCipher.encryptUuid(recipient.requireServiceId().uuid())); } return uuidCipherTexts; @@ -389,7 +389,7 @@ final class GroupManagerV2 { throws GroupChangeFailedException, GroupInsufficientRightsException, IOException, GroupNotAMemberException { Set uuids = Stream.of(recipientIds) - .map(r -> Recipient.resolved(r).requireAci().uuid()) + .map(r -> Recipient.resolved(r).requireServiceId().uuid()) .collect(Collectors.toSet()); return commitChangeWithConflictResolution(groupOperations.createApproveGroupJoinRequest(uuids)); @@ -400,7 +400,7 @@ final class GroupManagerV2 { throws GroupChangeFailedException, GroupInsufficientRightsException, IOException, GroupNotAMemberException { Set uuids = Stream.of(recipientIds) - .map(r -> Recipient.resolved(r).requireAci().uuid()) + .map(r -> Recipient.resolved(r).requireServiceId().uuid()) .collect(Collectors.toSet()); return commitChangeWithConflictResolution(groupOperations.createRefuseGroupJoinRequest(uuids)); @@ -412,7 +412,7 @@ final class GroupManagerV2 { throws GroupChangeFailedException, GroupInsufficientRightsException, IOException, GroupNotAMemberException { Recipient recipient = Recipient.resolved(recipientId); - return commitChangeWithConflictResolution(groupOperations.createChangeMemberRole(recipient.requireAci().uuid(), admin ? Member.Role.ADMINISTRATOR : Member.Role.DEFAULT)); + return commitChangeWithConflictResolution(groupOperations.createChangeMemberRole(recipient.requireServiceId().uuid(), admin ? Member.Role.ADMINISTRATOR : Member.Role.DEFAULT)); } @WorkerThread @@ -441,7 +441,7 @@ final class GroupManagerV2 { { Recipient recipient = Recipient.resolved(recipientId); - return commitChangeWithConflictResolution(groupOperations.createRemoveMembersChange(Collections.singleton(recipient.requireAci().uuid()))); + return commitChangeWithConflictResolution(groupOperations.createRemoveMembersChange(Collections.singleton(recipient.requireServiceId().uuid()))); } @WorkerThread @@ -449,7 +449,7 @@ final class GroupManagerV2 { throws GroupChangeFailedException, GroupNotAMemberException, GroupInsufficientRightsException, IOException { Recipient self = Recipient.self(); - List newAdminRecipients = Stream.of(newAdmins).map(id -> Recipient.resolved(id).requireAci().uuid()).toList(); + List newAdminRecipients = Stream.of(newAdmins).map(id -> Recipient.resolved(id).requireServiceId().uuid()).toList(); return commitChangeWithConflictResolution(groupOperations.createLeaveAndPromoteMembersToAdmin(selfAci.uuid(), newAdminRecipients)); diff --git a/app/src/main/java/org/thoughtcrime/securesms/groups/GroupProtoUtil.java b/app/src/main/java/org/thoughtcrime/securesms/groups/GroupProtoUtil.java index fdc4f82bc..5b3511d52 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/groups/GroupProtoUtil.java +++ b/app/src/main/java/org/thoughtcrime/securesms/groups/GroupProtoUtil.java @@ -19,6 +19,7 @@ import org.thoughtcrime.securesms.recipients.Recipient; import org.thoughtcrime.securesms.recipients.RecipientId; import org.whispersystems.signalservice.api.groupsv2.PartialDecryptedGroup; import org.whispersystems.signalservice.api.push.ACI; +import org.whispersystems.signalservice.api.push.ServiceId; import org.whispersystems.signalservice.api.util.UuidUtil; import org.whispersystems.signalservice.internal.push.SignalServiceProtos; @@ -85,24 +86,24 @@ public final class GroupProtoUtil { @WorkerThread public static Recipient uuidByteStringToRecipient(@NonNull Context context, @NonNull ByteString uuidByteString) { - ACI aci = ACI.fromByteString(uuidByteString); + ServiceId serviceId = ACI.fromByteString(uuidByteString); - if (aci.isUnknown()) { + if (serviceId.isUnknown()) { return Recipient.UNKNOWN; } - return Recipient.externalPush(context, aci, null, false); + return Recipient.externalPush(serviceId, null, false); } @WorkerThread public static @NonNull RecipientId uuidByteStringToRecipientId(@NonNull ByteString uuidByteString) { - ACI aci = ACI.fromByteString(uuidByteString); + ServiceId serviceId = ACI.fromByteString(uuidByteString); - if (aci.isUnknown()) { + if (serviceId.isUnknown()) { return RecipientId.UNKNOWN; } - return RecipientId.from(aci, null); + return RecipientId.from(serviceId, null); } public static boolean isMember(@NonNull UUID uuid, @NonNull List membersList) { 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 b4dad5637..b292318ec 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/groups/GroupV1MessageProcessor.java +++ b/app/src/main/java/org/thoughtcrime/securesms/groups/GroupV1MessageProcessor.java @@ -99,7 +99,7 @@ public final class GroupV1MessageProcessor { if (group.getMembers().isPresent()) { for (SignalServiceAddress member : group.getMembers().get()) { - members.add(Recipient.externalGV1Member(context, member).getId()); + members.add(Recipient.externalGV1Member(member).getId()); } } @@ -131,7 +131,7 @@ public final class GroupV1MessageProcessor { if (group.getMembers().isPresent()) { for (SignalServiceAddress messageMember : group.getMembers().get()) { - messageMembers.add(Recipient.externalGV1Member(context, messageMember).getId()); + messageMembers.add(Recipient.externalGV1Member(messageMember).getId()); } } 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 87fe434a5..48d80b70f 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/groups/GroupsV1MigrationUtil.java +++ b/app/src/main/java/org/thoughtcrime/securesms/groups/GroupsV1MigrationUtil.java @@ -232,7 +232,7 @@ public final class GroupsV1MigrationUtil { * True if the user meets all the requirements to be auto-migrated, otherwise false. */ public static boolean isAutoMigratable(@NonNull Recipient recipient) { - return recipient.hasAci() && + return recipient.hasServiceId() && recipient.getGroupsV2Capability() == Recipient.Capability.SUPPORTED && recipient.getGroupsV1MigrationCapability() == Recipient.Capability.SUPPORTED && recipient.getRegistered() == RecipientDatabase.RegisteredState.REGISTERED && diff --git a/app/src/main/java/org/thoughtcrime/securesms/groups/GroupsV2CapabilityChecker.java b/app/src/main/java/org/thoughtcrime/securesms/groups/GroupsV2CapabilityChecker.java index d232eeed9..c296703c8 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/groups/GroupsV2CapabilityChecker.java +++ b/app/src/main/java/org/thoughtcrime/securesms/groups/GroupsV2CapabilityChecker.java @@ -91,7 +91,7 @@ public final class GroupsV2CapabilityChecker { } } - if (!member.hasAci()) { + if (!member.hasServiceId()) { noUuidCount++; } } diff --git a/app/src/main/java/org/thoughtcrime/securesms/groups/LiveGroup.java b/app/src/main/java/org/thoughtcrime/securesms/groups/LiveGroup.java index 6f305406a..b0aba838b 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/groups/LiveGroup.java +++ b/app/src/main/java/org/thoughtcrime/securesms/groups/LiveGroup.java @@ -28,6 +28,7 @@ import org.thoughtcrime.securesms.recipients.Recipient; import org.thoughtcrime.securesms.recipients.RecipientId; import org.thoughtcrime.securesms.util.livedata.LiveDataUtil; import org.whispersystems.signalservice.api.push.ACI; +import org.whispersystems.signalservice.api.push.ServiceId; import org.whispersystems.signalservice.api.util.UuidUtil; import java.util.Collections; @@ -109,7 +110,7 @@ public final class LiveGroup { return Stream.of(requestingMembersList) .map(requestingMember -> { - Recipient recipient = Recipient.externalPush(ApplicationDependencies.getApplication(), ACI.fromByteString(requestingMember.getUuid()), null, false); + Recipient recipient = Recipient.externalPush(ServiceId.fromByteString(requestingMember.getUuid()), null, false); return new GroupMemberEntry.RequestingMember(recipient, selfAdmin); }) .toList(); diff --git a/app/src/main/java/org/thoughtcrime/securesms/groups/ui/invitesandrequests/invited/PendingMemberInvitesRepository.java b/app/src/main/java/org/thoughtcrime/securesms/groups/ui/invitesandrequests/invited/PendingMemberInvitesRepository.java index 47a17d41a..1cfab1376 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/groups/ui/invitesandrequests/invited/PendingMemberInvitesRepository.java +++ b/app/src/main/java/org/thoughtcrime/securesms/groups/ui/invitesandrequests/invited/PendingMemberInvitesRepository.java @@ -54,7 +54,7 @@ final class PendingMemberInvitesRepository { List pendingMembersList = decryptedGroup.getPendingMembersList(); List byMe = new ArrayList<>(pendingMembersList.size()); List byOthers = new ArrayList<>(pendingMembersList.size()); - ByteString self = Recipient.self().requireAci().toByteString(); + ByteString self = Recipient.self().requireServiceId().toByteString(); boolean selfIsAdmin = v2GroupProperties.isAdmin(Recipient.self()); Stream.of(pendingMembersList) diff --git a/app/src/main/java/org/thoughtcrime/securesms/groups/ui/migration/GroupsV1MigrationRepository.java b/app/src/main/java/org/thoughtcrime/securesms/groups/ui/migration/GroupsV1MigrationRepository.java index f053a7724..47628837e 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/groups/ui/migration/GroupsV1MigrationRepository.java +++ b/app/src/main/java/org/thoughtcrime/securesms/groups/ui/migration/GroupsV1MigrationRepository.java @@ -95,7 +95,7 @@ final class GroupsV1MigrationRepository { group = group.fresh(); List ineligible = Stream.of(group.getParticipants()) - .filter(r -> !r.hasAci() || + .filter(r -> !r.hasServiceId() || r.getGroupsV2Capability() != Recipient.Capability.SUPPORTED || r.getGroupsV1MigrationCapability() != Recipient.Capability.SUPPORTED || r.getRegistered() != RecipientDatabase.RegisteredState.REGISTERED) diff --git a/app/src/main/java/org/thoughtcrime/securesms/groups/v2/GroupCandidateHelper.java b/app/src/main/java/org/thoughtcrime/securesms/groups/v2/GroupCandidateHelper.java index 32ca1c7fd..5314186af 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/groups/v2/GroupCandidateHelper.java +++ b/app/src/main/java/org/thoughtcrime/securesms/groups/v2/GroupCandidateHelper.java @@ -18,6 +18,7 @@ import org.whispersystems.libsignal.util.guava.Optional; import org.whispersystems.signalservice.api.SignalServiceAccountManager; import org.whispersystems.signalservice.api.groupsv2.GroupCandidate; import org.whispersystems.signalservice.api.push.ACI; +import org.whispersystems.signalservice.api.push.ServiceId; import java.io.IOException; import java.util.Collection; @@ -47,13 +48,13 @@ public final class GroupCandidateHelper { { final Recipient recipient = Recipient.resolved(recipientId); - ACI aci = recipient.getAci().orNull(); - if (aci == null) { + ServiceId serviceId = recipient.getServiceId().orNull(); + if (serviceId == null) { throw new AssertionError("Non UUID members should have need detected by now"); } Optional profileKeyCredential = Optional.fromNullable(recipient.getProfileKeyCredential()); - GroupCandidate candidate = new GroupCandidate(aci.uuid(), profileKeyCredential); + GroupCandidate candidate = new GroupCandidate(serviceId.uuid(), profileKeyCredential); if (!candidate.hasProfileKeyCredential()) { ProfileKey profileKey = ProfileKeyUtil.profileKeyOrNull(recipient.getProfileKey()); @@ -61,7 +62,7 @@ public final class GroupCandidateHelper { if (profileKey != null) { Log.i(TAG, String.format("No profile key credential on recipient %s, fetching", recipient.getId())); - Optional profileKeyCredentialOptional = signalServiceAccountManager.resolveProfileKeyCredential(aci, profileKey, Locale.getDefault()); + Optional profileKeyCredentialOptional = signalServiceAccountManager.resolveProfileKeyCredential(serviceId, profileKey, Locale.getDefault()); if (profileKeyCredentialOptional.isPresent()) { boolean updatedProfileKey = recipientDatabase.setProfileKeyCredential(recipient.getId(), profileKey, profileKeyCredentialOptional.get()); 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 c0d2385f8..036af5ec8 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 @@ -103,7 +103,7 @@ public final class GroupsV2StateProcessor { } public StateProcessorForGroup forGroup(@NonNull GroupMasterKey groupMasterKey) { - ACI selfAci = Recipient.self().requireAci(); + ACI selfAci = SignalStore.account().requireAci(); ProfileAndMessageHelper profileAndMessageHelper = new ProfileAndMessageHelper(context, selfAci, groupMasterKey, GroupId.v2(groupMasterKey), recipientDatabase); return new StateProcessorForGroup(selfAci, context, groupDatabase, groupsV2Api, groupsV2Authorization, groupMasterKey, profileAndMessageHelper); @@ -546,14 +546,14 @@ public final class GroupsV2StateProcessor { static class ProfileAndMessageHelper { private final Context context; - private final ACI aci; + private final ACI selfAci; private final GroupMasterKey masterKey; private final GroupId.V2 groupId; private final RecipientDatabase recipientDatabase; - ProfileAndMessageHelper(@NonNull Context context, @NonNull ACI aci, @NonNull GroupMasterKey masterKey, @NonNull GroupId.V2 groupId, @NonNull RecipientDatabase recipientDatabase) { + ProfileAndMessageHelper(@NonNull Context context, @NonNull ACI selfAci, @NonNull GroupMasterKey masterKey, @NonNull GroupId.V2 groupId, @NonNull RecipientDatabase recipientDatabase) { this.context = context; - this.aci = aci; + this.selfAci = selfAci; this.masterKey = masterKey; this.groupId = groupId; this.recipientDatabase = recipientDatabase; @@ -561,14 +561,14 @@ public final class GroupsV2StateProcessor { void determineProfileSharing(@NonNull GlobalGroupState inputGroupState, @NonNull DecryptedGroup newLocalState) { if (inputGroupState.getLocalState() != null) { - boolean wasAMemberAlready = DecryptedGroupUtil.findMemberByUuid(inputGroupState.getLocalState().getMembersList(), aci.uuid()).isPresent(); + boolean wasAMemberAlready = DecryptedGroupUtil.findMemberByUuid(inputGroupState.getLocalState().getMembersList(), selfAci.uuid()).isPresent(); if (wasAMemberAlready) { return; } } - Optional selfAsMemberOptional = DecryptedGroupUtil.findMemberByUuid(newLocalState.getMembersList(), aci.uuid()); + Optional selfAsMemberOptional = DecryptedGroupUtil.findMemberByUuid(newLocalState.getMembersList(), selfAci.uuid()); if (selfAsMemberOptional.isPresent()) { DecryptedMember selfAsMember = selfAsMemberOptional.get(); @@ -579,7 +579,7 @@ public final class GroupsV2StateProcessor { .filter(c -> c != null && c.getRevision() == revisionJoinedAt) .findFirst() .map(c -> Optional.fromNullable(UuidUtil.fromByteStringOrNull(c.getEditor())) - .transform(a -> Recipient.externalPush(context, ACI.fromByteStringOrNull(c.getEditor()), null, false))) + .transform(a -> Recipient.externalPush(ACI.fromByteStringOrNull(c.getEditor()), null, false))) .orElse(Optional.absent()); if (addedByOptional.isPresent()) { @@ -652,7 +652,7 @@ public final class GroupsV2StateProcessor { void storeMessage(@NonNull DecryptedGroupV2Context decryptedGroupV2Context, long timestamp) { Optional editor = getEditor(decryptedGroupV2Context).transform(ACI::from); - boolean outgoing = !editor.isPresent() || aci.equals(editor.get()); + boolean outgoing = !editor.isPresent() || selfAci.equals(editor.get()); if (outgoing) { try { @@ -690,7 +690,7 @@ public final class GroupsV2StateProcessor { if (changeEditor.isPresent()) { return changeEditor; } else { - Optional pendingByUuid = DecryptedGroupUtil.findPendingByUuid(decryptedGroupV2Context.getGroupState().getPendingMembersList(), aci.uuid()); + Optional pendingByUuid = DecryptedGroupUtil.findPendingByUuid(decryptedGroupV2Context.getGroupState().getPendingMembersList(), selfAci.uuid()); if (pendingByUuid.isPresent()) { return Optional.fromNullable(UuidUtil.fromByteStringOrNull(pendingByUuid.get().getAddedByUuid())); } diff --git a/app/src/main/java/org/thoughtcrime/securesms/jobs/CreateSignedPreKeyJob.java b/app/src/main/java/org/thoughtcrime/securesms/jobs/CreateSignedPreKeyJob.java index c26063f2c..ca98692f9 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/jobs/CreateSignedPreKeyJob.java +++ b/app/src/main/java/org/thoughtcrime/securesms/jobs/CreateSignedPreKeyJob.java @@ -14,7 +14,8 @@ import org.thoughtcrime.securesms.keyvalue.SignalStore; import org.whispersystems.libsignal.state.SignalProtocolStore; import org.whispersystems.libsignal.state.SignedPreKeyRecord; import org.whispersystems.signalservice.api.SignalServiceAccountManager; -import org.whispersystems.signalservice.api.push.AccountIdentifier; +import org.whispersystems.signalservice.api.push.ServiceId; +import org.whispersystems.signalservice.api.push.ServiceIdType; import org.whispersystems.signalservice.api.push.exceptions.PushNetworkException; import java.io.IOException; @@ -70,27 +71,27 @@ public class CreateSignedPreKeyJob extends BaseJob { return; } - createPreKeys(SignalStore.account().getAci(), ApplicationDependencies.getProtocolStore().aci(), SignalStore.account().aciPreKeys()); - createPreKeys(SignalStore.account().getPni(), ApplicationDependencies.getProtocolStore().pni(), SignalStore.account().pniPreKeys()); + createPreKeys(ServiceIdType.ACI, SignalStore.account().getAci(), ApplicationDependencies.getProtocolStore().aci(), SignalStore.account().aciPreKeys()); + createPreKeys(ServiceIdType.PNI, SignalStore.account().getPni(), ApplicationDependencies.getProtocolStore().pni(), SignalStore.account().pniPreKeys()); } - private void createPreKeys(@Nullable AccountIdentifier accountId, @NonNull SignalProtocolStore protocolStore, @NonNull PreKeyMetadataStore metadataStore) + private void createPreKeys(@NonNull ServiceIdType serviceIdType, @Nullable ServiceId serviceId, @NonNull SignalProtocolStore protocolStore, @NonNull PreKeyMetadataStore metadataStore) throws IOException { - if (accountId == null) { + if (serviceId == null) { warn(TAG, "AccountId not set!"); return; } if (metadataStore.isSignedPreKeyRegistered()) { - warn(TAG, "Signed prekey for " + (accountId.isAci() ? "ACI" : "PNI") + " already registered..."); + warn(TAG, "Signed prekey for " + serviceIdType + " already registered..."); return; } SignalServiceAccountManager accountManager = ApplicationDependencies.getSignalServiceAccountManager(); SignedPreKeyRecord signedPreKeyRecord = PreKeyUtil.generateAndStoreSignedPreKey(protocolStore, metadataStore, true); - accountManager.setSignedPreKey(accountId, signedPreKeyRecord); + accountManager.setSignedPreKey(serviceIdType, signedPreKeyRecord); metadataStore.setSignedPreKeyRegistered(true); } diff --git a/app/src/main/java/org/thoughtcrime/securesms/jobs/MultiDeviceBlockedUpdateJob.java b/app/src/main/java/org/thoughtcrime/securesms/jobs/MultiDeviceBlockedUpdateJob.java index 305bf4d0a..deda767b2 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/jobs/MultiDeviceBlockedUpdateJob.java +++ b/app/src/main/java/org/thoughtcrime/securesms/jobs/MultiDeviceBlockedUpdateJob.java @@ -82,7 +82,7 @@ public class MultiDeviceBlockedUpdateJob extends BaseJob { while ((recipient = reader.getNext()) != null) { if (recipient.isPushGroup()) { blockedGroups.add(recipient.requireGroupId().getDecodedId()); - } else if (recipient.isMaybeRegistered() && (recipient.hasAci() || recipient.hasE164())) { + } else if (recipient.isMaybeRegistered() && (recipient.hasServiceId() || recipient.hasE164())) { blockedIndividuals.add(RecipientUtil.toSignalServiceAddress(context, recipient)); } } diff --git a/app/src/main/java/org/thoughtcrime/securesms/jobs/MultiDeviceContactSyncJob.kt b/app/src/main/java/org/thoughtcrime/securesms/jobs/MultiDeviceContactSyncJob.kt index cb6f7d4d2..e0d49d753 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/jobs/MultiDeviceContactSyncJob.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/jobs/MultiDeviceContactSyncJob.kt @@ -75,7 +75,7 @@ class MultiDeviceContactSyncJob(parameters: Parameters, private val attachmentPo var contact: DeviceContact? = deviceContacts.read() while (contact != null) { - val recipient = Recipient.externalPush(context, contact.address.aci, contact.address.number.orNull(), true) + val recipient = Recipient.externalPush(contact.address.serviceId, contact.address.number.orNull(), true) if (recipient.isSelf) { contact = deviceContacts.read() diff --git a/app/src/main/java/org/thoughtcrime/securesms/jobs/MultiDeviceMessageRequestResponseJob.java b/app/src/main/java/org/thoughtcrime/securesms/jobs/MultiDeviceMessageRequestResponseJob.java index 2f21e8604..74bb9292f 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/jobs/MultiDeviceMessageRequestResponseJob.java +++ b/app/src/main/java/org/thoughtcrime/securesms/jobs/MultiDeviceMessageRequestResponseJob.java @@ -101,8 +101,8 @@ public class MultiDeviceMessageRequestResponseJob extends BaseJob { SignalServiceMessageSender messageSender = ApplicationDependencies.getSignalServiceMessageSender(); Recipient recipient = Recipient.resolved(threadRecipient); - if (!recipient.hasServiceIdentifier()) { - Log.i(TAG, "Queued for recipient without service identifier"); + if (!recipient.hasServiceId()) { + Log.i(TAG, "Queued for recipient without ServiceId"); return; } diff --git a/app/src/main/java/org/thoughtcrime/securesms/jobs/MultiDeviceOutgoingPaymentSyncJob.java b/app/src/main/java/org/thoughtcrime/securesms/jobs/MultiDeviceOutgoingPaymentSyncJob.java index cb9b8988f..0c7657652 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/jobs/MultiDeviceOutgoingPaymentSyncJob.java +++ b/app/src/main/java/org/thoughtcrime/securesms/jobs/MultiDeviceOutgoingPaymentSyncJob.java @@ -91,7 +91,7 @@ public final class MultiDeviceOutgoingPaymentSyncJob extends BaseJob { Optional uuid; if (!defrag && payment.getPayee().hasRecipientId()) { - uuid = Optional.of(new SignalServiceAddress(Recipient.resolved(payment.getPayee().requireRecipientId()).requireAci())); + uuid = Optional.of(new SignalServiceAddress(Recipient.resolved(payment.getPayee().requireRecipientId()).requireServiceId())); } else { uuid = Optional.absent(); } diff --git a/app/src/main/java/org/thoughtcrime/securesms/jobs/PushGroupSilentUpdateSendJob.java b/app/src/main/java/org/thoughtcrime/securesms/jobs/PushGroupSilentUpdateSendJob.java index b412d9eec..cb9a0a7f1 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/jobs/PushGroupSilentUpdateSendJob.java +++ b/app/src/main/java/org/thoughtcrime/securesms/jobs/PushGroupSilentUpdateSendJob.java @@ -74,8 +74,8 @@ public final class PushGroupSilentUpdateSendJob extends BaseJob { Set recipients = Stream.concat(Stream.of(memberUuids), Stream.of(pendingUuids)) .filter(uuid -> !UuidUtil.UNKNOWN_UUID.equals(uuid)) - .filter(uuid -> !Recipient.self().requireAci().uuid().equals(uuid)) - .map(uuid -> Recipient.externalPush(context, ACI.from(uuid), null, false)) + .filter(uuid -> !Recipient.self().requireServiceId().uuid().equals(uuid)) + .map(uuid -> Recipient.externalPush(ACI.from(uuid), null, false)) .filter(recipient -> recipient.getRegistered() != RecipientDatabase.RegisteredState.NOT_REGISTERED) .map(Recipient::getId) .collect(Collectors.toSet()); diff --git a/app/src/main/java/org/thoughtcrime/securesms/jobs/PushMediaSendJob.java b/app/src/main/java/org/thoughtcrime/securesms/jobs/PushMediaSendJob.java index ee062da34..72851c65e 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/jobs/PushMediaSendJob.java +++ b/app/src/main/java/org/thoughtcrime/securesms/jobs/PushMediaSendJob.java @@ -41,7 +41,6 @@ import org.whispersystems.signalservice.api.messages.SendMessageResult; import org.whispersystems.signalservice.api.messages.SignalServiceAttachment; import org.whispersystems.signalservice.api.messages.SignalServiceDataMessage; import org.whispersystems.signalservice.api.messages.SignalServiceDataMessage.Preview; -import org.whispersystems.signalservice.api.messages.multidevice.SignalServiceSyncMessage; import org.whispersystems.signalservice.api.messages.shared.SharedContact; import org.whispersystems.signalservice.api.push.SignalServiceAddress; import org.whispersystems.signalservice.api.push.exceptions.ProofRequiredException; @@ -75,8 +74,8 @@ public class PushMediaSendJob extends PushSendJob { @WorkerThread public static void enqueue(@NonNull Context context, @NonNull JobManager jobManager, long messageId, @NonNull Recipient recipient) { try { - if (!recipient.hasServiceIdentifier()) { - throw new AssertionError(); + if (!recipient.hasServiceId()) { + throw new AssertionError("No ServiceId!"); } MessageDatabase database = SignalDatabase.mms(); @@ -226,7 +225,7 @@ public class PushMediaSendJob extends PushSendJob { .asExpirationUpdate(message.isExpirationUpdate()) .build(); - if (Util.equals(SignalStore.account().getAci(), address.getAci())) { + if (Util.equals(SignalStore.account().getAci(), address.getServiceId())) { Optional syncAccess = UnidentifiedAccessUtil.getAccessForSync(context); SendMessageResult result = messageSender.sendSyncMessage(mediaMessage); SignalDatabase.messageLog().insertIfPossible(messageRecipient.getId(), message.getSentTimeMillis(), result, ContentHint.RESENDABLE, new MessageId(messageId, true)); diff --git a/app/src/main/java/org/thoughtcrime/securesms/jobs/PushSendJob.java b/app/src/main/java/org/thoughtcrime/securesms/jobs/PushSendJob.java index a519f5690..9818a2ff3 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/jobs/PushSendJob.java +++ b/app/src/main/java/org/thoughtcrime/securesms/jobs/PushSendJob.java @@ -49,17 +49,13 @@ import org.thoughtcrime.securesms.util.BitmapUtil; import org.thoughtcrime.securesms.util.FeatureFlags; import org.thoughtcrime.securesms.util.Hex; import org.thoughtcrime.securesms.util.MediaUtil; -import org.thoughtcrime.securesms.util.TextSecurePreferences; import org.thoughtcrime.securesms.util.Util; import org.whispersystems.libsignal.util.guava.Optional; -import org.whispersystems.signalservice.api.crypto.UnidentifiedAccessPair; import org.whispersystems.signalservice.api.messages.SignalServiceAttachment; import org.whispersystems.signalservice.api.messages.SignalServiceAttachmentPointer; import org.whispersystems.signalservice.api.messages.SignalServiceAttachmentRemoteId; import org.whispersystems.signalservice.api.messages.SignalServiceDataMessage; import org.whispersystems.signalservice.api.messages.SignalServiceDataMessage.Preview; -import org.whispersystems.signalservice.api.messages.multidevice.SentTranscriptMessage; -import org.whispersystems.signalservice.api.messages.multidevice.SignalServiceSyncMessage; import org.whispersystems.signalservice.api.messages.shared.SharedContact; import org.whispersystems.signalservice.api.push.SignalServiceAddress; import org.whispersystems.signalservice.api.push.exceptions.NonSuccessfulResponseCodeException; @@ -70,7 +66,6 @@ import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; import java.util.Collection; -import java.util.Collections; import java.util.HashSet; import java.util.LinkedList; import java.util.List; @@ -409,7 +404,7 @@ public abstract class PushSendJob extends SendJob { List getMentionsFor(@NonNull List mentions) { return Stream.of(mentions) - .map(m -> new SignalServiceDataMessage.Mention(Recipient.resolved(m.getRecipientId()).requireAci(), m.getStart(), m.getLength())) + .map(m -> new SignalServiceDataMessage.Mention(Recipient.resolved(m.getRecipientId()).requireServiceId(), m.getStart(), m.getLength())) .toList(); } diff --git a/app/src/main/java/org/thoughtcrime/securesms/jobs/PushTextSendJob.java b/app/src/main/java/org/thoughtcrime/securesms/jobs/PushTextSendJob.java index fada00f4d..d3d0ac658 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/jobs/PushTextSendJob.java +++ b/app/src/main/java/org/thoughtcrime/securesms/jobs/PushTextSendJob.java @@ -31,7 +31,6 @@ import org.whispersystems.signalservice.api.crypto.UnidentifiedAccessPair; import org.whispersystems.signalservice.api.crypto.UntrustedIdentityException; import org.whispersystems.signalservice.api.messages.SendMessageResult; import org.whispersystems.signalservice.api.messages.SignalServiceDataMessage; -import org.whispersystems.signalservice.api.messages.multidevice.SignalServiceSyncMessage; import org.whispersystems.signalservice.api.push.SignalServiceAddress; import org.whispersystems.signalservice.api.push.exceptions.ProofRequiredException; import org.whispersystems.signalservice.api.push.exceptions.ServerRejectedException; @@ -188,7 +187,7 @@ public class PushTextSendJob extends PushSendJob { .asEndSessionMessage(message.isEndSession()) .build(); - if (Util.equals(SignalStore.account().getAci(), address.getAci())) { + if (Util.equals(SignalStore.account().getAci(), address.getServiceId())) { Optional syncAccess = UnidentifiedAccessUtil.getAccessForSync(context); SignalLocalMetrics.IndividualMessageSend.onDeliveryStarted(messageId); diff --git a/app/src/main/java/org/thoughtcrime/securesms/jobs/RefreshPreKeysJob.java b/app/src/main/java/org/thoughtcrime/securesms/jobs/RefreshPreKeysJob.java index d838219a6..e4b31b6df 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/jobs/RefreshPreKeysJob.java +++ b/app/src/main/java/org/thoughtcrime/securesms/jobs/RefreshPreKeysJob.java @@ -17,8 +17,9 @@ import org.whispersystems.libsignal.state.SignalProtocolStore; import org.whispersystems.libsignal.state.SignedPreKeyRecord; import org.whispersystems.signalservice.api.SignalServiceAccountManager; import org.whispersystems.signalservice.api.push.ACI; -import org.whispersystems.signalservice.api.push.AccountIdentifier; +import org.whispersystems.signalservice.api.push.ServiceId; import org.whispersystems.signalservice.api.push.PNI; +import org.whispersystems.signalservice.api.push.ServiceIdType; import org.whispersystems.signalservice.api.push.exceptions.NonSuccessfulResponseCodeException; import org.whispersystems.signalservice.api.push.exceptions.PushNetworkException; @@ -81,19 +82,17 @@ public class RefreshPreKeysJob extends BaseJob { return; } - ACI aci = SignalStore.account().getAci(); SignalProtocolStore aciProtocolStore = ApplicationDependencies.getProtocolStore().aci(); PreKeyMetadataStore aciPreKeyStore = SignalStore.account().aciPreKeys(); - PNI pni = SignalStore.account().getPni(); SignalProtocolStore pniProtocolStore = ApplicationDependencies.getProtocolStore().pni(); PreKeyMetadataStore pniPreKeyStore = SignalStore.account().pniPreKeys(); - if (refreshKeys(aci, aciProtocolStore, aciPreKeyStore)) { + if (refreshKeys(ServiceIdType.ACI, aciProtocolStore, aciPreKeyStore)) { PreKeyUtil.cleanSignedPreKeys(aciProtocolStore, aciPreKeyStore); } - if (refreshKeys(pni, pniProtocolStore, pniPreKeyStore)) { + if (refreshKeys(ServiceIdType.PNI, pniProtocolStore, pniPreKeyStore)) { PreKeyUtil.cleanSignedPreKeys(pniProtocolStore, pniPreKeyStore); } @@ -104,16 +103,12 @@ public class RefreshPreKeysJob extends BaseJob { /** * @return True if we need to clean prekeys, otherwise false. */ - private boolean refreshKeys(@Nullable AccountIdentifier accountId, @NonNull SignalProtocolStore protocolStore, @NonNull PreKeyMetadataStore metadataStore) throws IOException { - if (accountId == null) { - throw new IOException("Unset identifier!"); - } - - String logPrefix = "[" + (accountId.isAci() ? "ACI" : "PNI") + "] "; + private boolean refreshKeys(@NonNull ServiceIdType serviceIdType, @NonNull SignalProtocolStore protocolStore, @NonNull PreKeyMetadataStore metadataStore) throws IOException { + String logPrefix = "[" + serviceIdType + "] "; SignalServiceAccountManager accountManager = ApplicationDependencies.getSignalServiceAccountManager(); - int availableKeys = accountManager.getPreKeysCount(accountId); + int availableKeys = accountManager.getPreKeysCount(serviceIdType); log(TAG, logPrefix + "Available keys: " + availableKeys); if (availableKeys >= PREKEY_MINIMUM && metadataStore.isSignedPreKeyRegistered()) { @@ -127,7 +122,7 @@ public class RefreshPreKeysJob extends BaseJob { log(TAG, logPrefix + "Registering new prekeys..."); - accountManager.setPreKeys(accountId, identityKey.getPublicKey(), signedPreKeyRecord, preKeyRecords); + accountManager.setPreKeys(serviceIdType, identityKey.getPublicKey(), signedPreKeyRecord, preKeyRecords); metadataStore.setActiveSignedPreKeyId(signedPreKeyRecord.getId()); metadataStore.setSignedPreKeyRegistered(true); diff --git a/app/src/main/java/org/thoughtcrime/securesms/jobs/ResendMessageJob.java b/app/src/main/java/org/thoughtcrime/securesms/jobs/ResendMessageJob.java index e2912507b..376833a76 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/jobs/ResendMessageJob.java +++ b/app/src/main/java/org/thoughtcrime/securesms/jobs/ResendMessageJob.java @@ -158,7 +158,7 @@ public class ResendMessageJob extends BaseJob { List addresses = result.getSuccess() .getDevices() .stream() - .map(device -> new SignalProtocolAddress(recipient.requireServiceId(), device)) + .map(device -> recipient.requireServiceId().toProtocolAddress(device)) .collect(Collectors.toList()); ApplicationDependencies.getProtocolStore().aci().markSenderKeySharedWith(distributionId, addresses); diff --git a/app/src/main/java/org/thoughtcrime/securesms/jobs/RetrieveProfileJob.java b/app/src/main/java/org/thoughtcrime/securesms/jobs/RetrieveProfileJob.java index 9a950ab1e..9067e4875 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/jobs/RetrieveProfileJob.java +++ b/app/src/main/java/org/thoughtcrime/securesms/jobs/RetrieveProfileJob.java @@ -47,7 +47,7 @@ import org.whispersystems.signalservice.api.crypto.InvalidCiphertextException; import org.whispersystems.signalservice.api.crypto.ProfileCipher; import org.whispersystems.signalservice.api.profiles.ProfileAndCredential; import org.whispersystems.signalservice.api.profiles.SignalServiceProfile; -import org.whispersystems.signalservice.api.push.ACI; +import org.whispersystems.signalservice.api.push.ServiceId; import org.whispersystems.signalservice.api.services.ProfileService; import org.whispersystems.signalservice.internal.ServiceResponse; @@ -257,7 +257,7 @@ public class RetrieveProfileJob extends BaseJob { ApplicationDependencies.getSignalWebSocket()); List>>> requests = Stream.of(recipients) - .filter(Recipient::hasServiceIdentifier) + .filter(Recipient::hasServiceId) .map(r -> ProfileUtil.retrieveProfile(context, r, getRequestType(r), profileService).toObservable()) .toList(); stopwatch.split("requests"); @@ -288,11 +288,11 @@ public class RetrieveProfileJob extends BaseJob { Set success = SetUtil.difference(recipientIds, operationState.retries); - Map newlyRegistered = Stream.of(operationState.profiles) - .map(Pair::first) - .filterNot(Recipient::isRegistered) - .collect(Collectors.toMap(Recipient::getId, - r -> r.getAci().orNull())); + Map newlyRegistered = Stream.of(operationState.profiles) + .map(Pair::first) + .filterNot(Recipient::isRegistered) + .collect(Collectors.toMap(Recipient::getId, + r -> r.getServiceId().orNull())); //noinspection SimplifyStreamApiCallChains @@ -401,7 +401,7 @@ public class RetrieveProfileJob extends BaseJob { return; } - IdentityUtil.saveIdentity(recipient.requireServiceId(), identityKey); + IdentityUtil.saveIdentity(recipient.requireServiceId().toString(), identityKey); } catch (InvalidKeyException | IOException e) { Log.w(TAG, e); } diff --git a/app/src/main/java/org/thoughtcrime/securesms/jobs/RotateSignedPreKeyJob.java b/app/src/main/java/org/thoughtcrime/securesms/jobs/RotateSignedPreKeyJob.java index 1e0fd9724..9e039c999 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/jobs/RotateSignedPreKeyJob.java +++ b/app/src/main/java/org/thoughtcrime/securesms/jobs/RotateSignedPreKeyJob.java @@ -11,13 +11,13 @@ import org.thoughtcrime.securesms.jobmanager.Data; import org.thoughtcrime.securesms.jobmanager.Job; import org.thoughtcrime.securesms.jobmanager.impl.NetworkConstraint; import org.thoughtcrime.securesms.keyvalue.SignalStore; -import org.thoughtcrime.securesms.util.TextSecurePreferences; import org.whispersystems.libsignal.state.SignalProtocolStore; import org.whispersystems.libsignal.state.SignedPreKeyRecord; import org.whispersystems.signalservice.api.SignalServiceAccountManager; import org.whispersystems.signalservice.api.push.ACI; -import org.whispersystems.signalservice.api.push.AccountIdentifier; +import org.whispersystems.signalservice.api.push.ServiceId; import org.whispersystems.signalservice.api.push.PNI; +import org.whispersystems.signalservice.api.push.ServiceIdType; import org.whispersystems.signalservice.api.push.exceptions.PushNetworkException; import java.io.IOException; @@ -73,17 +73,17 @@ public class RotateSignedPreKeyJob extends BaseJob { return; } - rotate(aci, ApplicationDependencies.getProtocolStore().aci(), SignalStore.account().aciPreKeys()); - rotate(pni, ApplicationDependencies.getProtocolStore().pni(), SignalStore.account().pniPreKeys()); + rotate(ServiceIdType.ACI, ApplicationDependencies.getProtocolStore().aci(), SignalStore.account().aciPreKeys()); + rotate(ServiceIdType.PNI, ApplicationDependencies.getProtocolStore().pni(), SignalStore.account().pniPreKeys()); } - private void rotate(@NonNull AccountIdentifier accountId, @NonNull SignalProtocolStore protocolStore, @NonNull PreKeyMetadataStore metadataStore) + private void rotate(@NonNull ServiceIdType serviceIdType, @NonNull SignalProtocolStore protocolStore, @NonNull PreKeyMetadataStore metadataStore) throws IOException { SignalServiceAccountManager accountManager = ApplicationDependencies.getSignalServiceAccountManager(); SignedPreKeyRecord signedPreKeyRecord = PreKeyUtil.generateAndStoreSignedPreKey(protocolStore, metadataStore, false); - accountManager.setSignedPreKey(accountId, signedPreKeyRecord); + accountManager.setSignedPreKey(serviceIdType, signedPreKeyRecord); metadataStore.setActiveSignedPreKeyId(signedPreKeyRecord.getId()); metadataStore.setSignedPreKeyRegistered(true); diff --git a/app/src/main/java/org/thoughtcrime/securesms/jobs/SenderKeyDistributionSendJob.java b/app/src/main/java/org/thoughtcrime/securesms/jobs/SenderKeyDistributionSendJob.java index e63accf8f..99dd47275 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/jobs/SenderKeyDistributionSendJob.java +++ b/app/src/main/java/org/thoughtcrime/securesms/jobs/SenderKeyDistributionSendJob.java @@ -107,7 +107,7 @@ public final class SenderKeyDistributionSendJob extends BaseJob { List addresses = result.getSuccess() .getDevices() .stream() - .map(device -> new SignalProtocolAddress(recipient.requireServiceId(), device)) + .map(device -> recipient.requireServiceId().toProtocolAddress(device)) .collect(Collectors.toList()); ApplicationDependencies.getProtocolStore().aci().markSenderKeySharedWith(distributionId, addresses); diff --git a/app/src/main/java/org/thoughtcrime/securesms/jobs/StorageSyncJob.java b/app/src/main/java/org/thoughtcrime/securesms/jobs/StorageSyncJob.java index ddaa5e8c1..2399f10f8 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/jobs/StorageSyncJob.java +++ b/app/src/main/java/org/thoughtcrime/securesms/jobs/StorageSyncJob.java @@ -176,7 +176,7 @@ public class StorageSyncJob extends BaseJob { return; } - if (!Recipient.self().hasE164() || !Recipient.self().hasAci()) { + if (!Recipient.self().hasE164() || !Recipient.self().hasServiceId()) { Log.w(TAG, "Missing E164 or ACI!"); return; } diff --git a/app/src/main/java/org/thoughtcrime/securesms/keyvalue/AccountValues.kt b/app/src/main/java/org/thoughtcrime/securesms/keyvalue/AccountValues.kt index bd5406938..d0cba9feb 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/keyvalue/AccountValues.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/keyvalue/AccountValues.kt @@ -88,6 +88,11 @@ internal class AccountValues internal constructor(store: KeyValueStore) : Signal val aci: ACI? get() = ACI.parseOrNull(getString(KEY_ACI, null)) + /** The local user's [ACI]. Will throw if not present. */ + fun requireAci(): ACI { + return ACI.parseOrThrow(getString(KEY_ACI, null)) + } + fun setAci(aci: ACI) { putString(KEY_ACI, aci.toString()) } @@ -96,6 +101,11 @@ internal class AccountValues internal constructor(store: KeyValueStore) : Signal val pni: PNI? get() = PNI.parseOrNull(getString(KEY_PNI, null)) + /** The local user's [PNI]. Will throw if not present. */ + fun requirePni(): PNI { + return PNI.parseOrThrow(getString(KEY_PNI, null)) + } + fun setPni(pni: PNI) { putString(KEY_PNI, pni.toString()) } diff --git a/app/src/main/java/org/thoughtcrime/securesms/messages/GroupSendUtil.java b/app/src/main/java/org/thoughtcrime/securesms/messages/GroupSendUtil.java index f0d102367..248251e9e 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/messages/GroupSendUtil.java +++ b/app/src/main/java/org/thoughtcrime/securesms/messages/GroupSendUtil.java @@ -42,7 +42,6 @@ import org.whispersystems.signalservice.api.messages.calls.SignalServiceCallMess import org.whispersystems.signalservice.api.push.DistributionId; import org.whispersystems.signalservice.api.push.SignalServiceAddress; import org.whispersystems.signalservice.api.push.exceptions.NotFoundException; -import org.whispersystems.signalservice.api.push.exceptions.UnregisteredUserException; import org.whispersystems.signalservice.internal.push.exceptions.InvalidUnidentifiedAccessHeaderException; import org.whispersystems.signalservice.internal.push.http.CancelationSignal; import org.whispersystems.signalservice.internal.push.http.PartialSendCompleteListener; @@ -176,7 +175,7 @@ public final class GroupSendUtil { boolean validMembership = groupRecord.isPresent() && groupRecord.get().getMembers().contains(recipient.getId()); if (recipient.getSenderKeyCapability() == Recipient.Capability.SUPPORTED && - recipient.hasAci() && + recipient.hasServiceId() && access.isPresent() && access.get().getTargetUnidentifiedAccess().isPresent() && validMembership) @@ -311,8 +310,8 @@ public final class GroupSendUtil { Log.w(TAG, "There are " + unregisteredTargets.size() + " unregistered targets. Including failure results."); List unregisteredResults = unregisteredTargets.stream() - .filter(Recipient::hasAci) - .map(t -> SendMessageResult.unregisteredFailure(new SignalServiceAddress(t.requireAci(), t.getE164().orNull()))) + .filter(Recipient::hasServiceId) + .map(t -> SendMessageResult.unregisteredFailure(new SignalServiceAddress(t.requireServiceId(), t.getE164().orNull()))) .collect(Collectors.toList()); if (unregisteredResults.size() < unregisteredTargets.size()) { 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 7ced42817..471b0cd95 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/messages/MessageContentProcessor.java +++ b/app/src/main/java/org/thoughtcrime/securesms/messages/MessageContentProcessor.java @@ -652,7 +652,7 @@ public final class MessageContentProcessor { } ApplicationDependencies.getSignalCallManager() - .receivedOpaqueMessage(new WebRtcData.OpaqueMessageMetadata(senderRecipient.requireAci().uuid(), + .receivedOpaqueMessage(new WebRtcData.OpaqueMessageMetadata(senderRecipient.requireServiceId().uuid(), message.getOpaque(), content.getSenderDevice(), messageAgeSeconds)); @@ -734,7 +734,7 @@ public final class MessageContentProcessor { long threadId = SignalDatabase.threads().getOrCreateThreadIdFor(recipient); if (!recipient.isGroup()) { - ApplicationDependencies.getProtocolStore().aci().deleteAllSessions(recipient.requireServiceId()); + ApplicationDependencies.getProtocolStore().aci().deleteAllSessions(recipient.requireServiceId().toString()); SecurityEvent.broadcastSecurityUpdateEvent(context); @@ -867,7 +867,7 @@ public final class MessageContentProcessor { return null; } - Recipient targetAuthor = Recipient.externalPush(context, reaction.getTargetAuthor()); + Recipient targetAuthor = Recipient.externalPush(reaction.getTargetAuthor()); MessageRecord targetMessage = SignalDatabase.mmsSms().getMessageFor(reaction.getTargetSentTimestamp(), targetAuthor.getId()); if (targetMessage == null) { @@ -1019,7 +1019,7 @@ public final class MessageContentProcessor { Recipient recipient; if (response.getPerson().isPresent()) { - recipient = Recipient.externalPush(context, response.getPerson().get()); + recipient = Recipient.externalPush(response.getPerson().get()); } else if (response.getGroupId().isPresent()) { GroupId groupId = GroupId.v1(response.getGroupId().get()); recipient = Recipient.externalPossiblyMigratedGroup(context, groupId); @@ -1271,7 +1271,7 @@ public final class MessageContentProcessor { List toMarkViewed = Stream.of(viewedMessages) .map(message -> { - RecipientId author = Recipient.externalPush(context, message.getSender()).getId(); + RecipientId author = Recipient.externalPush(message.getSender()).getId(); return SignalDatabase.mmsSms().getMessageFor(message.getTimestamp(), author); }) .filter(message -> message != null && message.isMms()) @@ -1289,7 +1289,7 @@ public final class MessageContentProcessor { private void handleSynchronizeViewOnceOpenMessage(@NonNull ViewOnceOpenMessage openMessage, long envelopeTimestamp) { log(envelopeTimestamp, "Handling a view-once open for message: " + openMessage.getTimestamp()); - RecipientId author = Recipient.externalPush(context, openMessage.getSender()).getId(); + RecipientId author = Recipient.externalPush(openMessage.getSender()).getId(); long timestamp = openMessage.getTimestamp(); MessageRecord record = SignalDatabase.mmsSms().getMessageFor(timestamp, author); @@ -1547,7 +1547,7 @@ public final class MessageContentProcessor { } List> unidentifiedStatus = Stream.of(members) - .map(m -> new org.whispersystems.libsignal.util.Pair<>(m.getId(), message.isUnidentified(m.requireServiceId()))) + .map(m -> new org.whispersystems.libsignal.util.Pair<>(m.getId(), message.isUnidentified(m.requireServiceId().toString()))) .toList(); receiptDatabase.setUnidentified(unidentifiedStatus, messageId); } @@ -1913,7 +1913,7 @@ public final class MessageContentProcessor { warn(content.getTimestamp(), "[RetryReceipt] Received a retry receipt from " + formatSender(senderRecipient, content) + " for message with timestamp " + sentTimestamp + "."); - if (!senderRecipient.hasAci()) { + if (!senderRecipient.hasServiceId()) { warn(content.getTimestamp(), "[RetryReceipt] Requester " + senderRecipient.getId() + " somehow has no UUID! timestamp: " + sentTimestamp); return; } @@ -1953,7 +1953,7 @@ public final class MessageContentProcessor { GroupId.V2 groupId = threadRecipient.requireGroupId().requireV2(); DistributionId distributionId = SignalDatabase.groups().getOrCreateDistributionId(groupId); - SignalProtocolAddress requesterAddress = new SignalProtocolAddress(requester.requireAci().toString(), content.getSenderDevice()); + SignalProtocolAddress requesterAddress = new SignalProtocolAddress(requester.requireServiceId().toString(), content.getSenderDevice()); SignalDatabase.senderKeyShared().delete(distributionId, Collections.singleton(requesterAddress)); @@ -2030,7 +2030,7 @@ public final class MessageContentProcessor { } public static boolean ratchetKeyMatches(@NonNull Recipient recipient, int deviceId, @NonNull ECPublicKey ratchetKey) { - SignalProtocolAddress address = new SignalProtocolAddress(recipient.resolve().requireServiceId(), deviceId); + SignalProtocolAddress address = recipient.resolve().requireServiceId().toProtocolAddress(deviceId); SessionRecord session = ApplicationDependencies.getProtocolStore().aci().loadSession(address); return session.currentRatchetKeyMatches(ratchetKey); @@ -2064,7 +2064,7 @@ public final class MessageContentProcessor { return Optional.absent(); } - RecipientId author = Recipient.externalPush(context, quote.get().getAuthor()).getId(); + RecipientId author = Recipient.externalPush(quote.get().getAuthor()).getId(); MessageRecord message = SignalDatabase.mmsSms().getMessageFor(quote.get().getId(), author); if (message != null && !message.isRemoteDelete()) { @@ -2200,7 +2200,7 @@ public final class MessageContentProcessor { List mentions = new ArrayList<>(signalServiceMentions.size()); for (SignalServiceDataMessage.Mention mention : signalServiceMentions) { - mentions.add(new Mention(Recipient.externalPush(context, mention.getAci(), null, false).getId(), mention.getStart(), mention.getLength())); + mentions.add(new Mention(Recipient.externalPush(mention.getAci(), null, false).getId(), mention.getStart(), mention.getLength())); } return mentions; @@ -2223,7 +2223,7 @@ public final class MessageContentProcessor { private Recipient getSyncMessageDestination(@NonNull SentTranscriptMessage message) throws BadGroupIdException { - return getGroupRecipient(message.getMessage().getGroupContext()).or(() -> Recipient.externalPush(context, message.getDestination().get())); + return getGroupRecipient(message.getMessage().getGroupContext()).or(() -> Recipient.externalPush(message.getDestination().get())); } private Recipient getMessageDestination(@NonNull SignalServiceContent content) throws BadGroupIdException { @@ -2339,8 +2339,8 @@ public final class MessageContentProcessor { if (recipient.hasE164()) { unidentified |= message.isUnidentified(recipient.requireE164()); } - if (recipient.hasAci()) { - unidentified |= message.isUnidentified(recipient.requireAci()); + if (recipient.hasServiceId()) { + unidentified |= message.isUnidentified(recipient.requireServiceId()); } return unidentified; 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 e6dbaf3cf..2b95d7d99 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/messages/MessageDecryptionUtil.java +++ b/app/src/main/java/org/thoughtcrime/securesms/messages/MessageDecryptionUtil.java @@ -44,7 +44,6 @@ import org.thoughtcrime.securesms.util.FeatureFlags; import org.thoughtcrime.securesms.util.GroupUtil; import org.whispersystems.libsignal.protocol.CiphertextMessage; import org.whispersystems.libsignal.protocol.DecryptionErrorMessage; -import org.whispersystems.libsignal.state.SignalProtocolStore; import org.whispersystems.libsignal.util.guava.Optional; import org.whispersystems.signalservice.api.InvalidMessageStructureException; import org.whispersystems.signalservice.api.SignalServiceAccountDataStore; @@ -78,7 +77,7 @@ public final class MessageDecryptionUtil { */ public static @NonNull DecryptionResult decrypt(@NonNull Context context, @NonNull SignalServiceEnvelope envelope) { SignalServiceAccountDataStore protocolStore = ApplicationDependencies.getProtocolStore().aci(); - SignalServiceAddress localAddress = new SignalServiceAddress(Recipient.self().requireAci(), Recipient.self().requireE164()); + SignalServiceAddress localAddress = new SignalServiceAddress(Recipient.self().requireServiceId(), Recipient.self().requireE164()); SignalServiceCipher cipher = new SignalServiceCipher(localAddress, SignalStore.account().getDeviceId(), protocolStore, ReentrantSessionLock.INSTANCE, UnidentifiedAccessUtil.getCertificateValidator()); List jobs = new LinkedList<>(); diff --git a/app/src/main/java/org/thoughtcrime/securesms/migrations/PniAccountInitializationMigrationJob.java b/app/src/main/java/org/thoughtcrime/securesms/migrations/PniAccountInitializationMigrationJob.java index d0ec9be74..5361b8c83 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/migrations/PniAccountInitializationMigrationJob.java +++ b/app/src/main/java/org/thoughtcrime/securesms/migrations/PniAccountInitializationMigrationJob.java @@ -17,6 +17,7 @@ import org.whispersystems.libsignal.state.SignalProtocolStore; import org.whispersystems.libsignal.state.SignedPreKeyRecord; import org.whispersystems.signalservice.api.SignalServiceAccountManager; import org.whispersystems.signalservice.api.push.PNI; +import org.whispersystems.signalservice.api.push.ServiceIdType; import java.io.IOException; import java.util.List; @@ -71,7 +72,7 @@ public class PniAccountInitializationMigrationJob extends MigrationJob { SignedPreKeyRecord signedPreKey = PreKeyUtil.generateAndStoreSignedPreKey(protocolStore, metadataStore, true); List oneTimePreKeys = PreKeyUtil.generateAndStoreOneTimePreKeys(protocolStore, metadataStore); - accountManager.setPreKeys(pni, protocolStore.getIdentityKeyPair().getPublicKey(), signedPreKey, oneTimePreKeys); + accountManager.setPreKeys(ServiceIdType.PNI, protocolStore.getIdentityKeyPair().getPublicKey(), signedPreKey, oneTimePreKeys); metadataStore.setSignedPreKeyRegistered(true); } diff --git a/app/src/main/java/org/thoughtcrime/securesms/mms/MessageGroupContext.java b/app/src/main/java/org/thoughtcrime/securesms/mms/MessageGroupContext.java index fee0df56b..5d1abf1bf 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/mms/MessageGroupContext.java +++ b/app/src/main/java/org/thoughtcrime/securesms/mms/MessageGroupContext.java @@ -16,6 +16,7 @@ import org.thoughtcrime.securesms.recipients.RecipientId; import org.thoughtcrime.securesms.util.Base64; import org.whispersystems.signalservice.api.groupsv2.DecryptedGroupUtil; import org.whispersystems.signalservice.api.push.ACI; +import org.whispersystems.signalservice.api.push.ServiceId; import org.whispersystems.signalservice.api.util.UuidUtil; import org.whispersystems.signalservice.internal.push.SignalServiceProtos.GroupContext; import org.whispersystems.signalservice.internal.push.SignalServiceProtos.GroupContextV2; @@ -191,7 +192,7 @@ public final class MessageGroupContext { List members = new ArrayList<>(decryptedGroupV2Context.getGroupState().getMembersCount()); for (DecryptedMember member : decryptedGroupV2Context.getGroupState().getMembersList()) { - RecipientId recipient = RecipientId.from(ACI.fromByteString(member.getUuid()), null); + RecipientId recipient = RecipientId.from(ServiceId.fromByteString(member.getUuid()), null); if (!Recipient.self().getId().equals(recipient)) { members.add(recipient); } diff --git a/app/src/main/java/org/thoughtcrime/securesms/recipients/LiveRecipientCache.java b/app/src/main/java/org/thoughtcrime/securesms/recipients/LiveRecipientCache.java index 30b9af0c7..09793a57d 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/recipients/LiveRecipientCache.java +++ b/app/src/main/java/org/thoughtcrime/securesms/recipients/LiveRecipientCache.java @@ -7,8 +7,6 @@ import android.database.Cursor; import androidx.annotation.AnyThread; import androidx.annotation.NonNull; -import net.zetetic.database.sqlcipher.SQLiteDatabase; - import org.signal.core.util.ThreadUtil; import org.signal.core.util.concurrent.SignalExecutors; import org.signal.core.util.logging.Log; @@ -153,7 +151,7 @@ public final class LiveRecipientCache { String localE164 = SignalStore.account().getE164(); if (localAci != null) { - selfId = recipientDatabase.getByAci(localAci).or(recipientDatabase.getByE164(localE164)).orNull(); + selfId = recipientDatabase.getByServiceId(localAci).or(recipientDatabase.getByE164(localE164)).orNull(); } else if (localE164 != null) { selfId = recipientDatabase.getByE164(localE164).orNull(); } else { @@ -235,6 +233,6 @@ public final class LiveRecipientCache { } private boolean isValidForCache(@NonNull Recipient recipient) { - return !recipient.getId().isUnknown() && (recipient.hasServiceIdentifier() || recipient.getGroupId().isPresent() || recipient.hasSmsAddress()); + return !recipient.getId().isUnknown() && (recipient.hasServiceId() || recipient.getGroupId().isPresent() || recipient.hasSmsAddress()); } } diff --git a/app/src/main/java/org/thoughtcrime/securesms/recipients/Recipient.java b/app/src/main/java/org/thoughtcrime/securesms/recipients/Recipient.java index bda1393f8..6b8db262c 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/recipients/Recipient.java +++ b/app/src/main/java/org/thoughtcrime/securesms/recipients/Recipient.java @@ -49,6 +49,7 @@ import org.thoughtcrime.securesms.wallpaper.ChatWallpaper; import org.whispersystems.libsignal.util.guava.Optional; import org.whispersystems.libsignal.util.guava.Preconditions; import org.whispersystems.signalservice.api.push.ACI; +import org.whispersystems.signalservice.api.push.ServiceId; import org.whispersystems.signalservice.api.push.PNI; import org.whispersystems.signalservice.api.push.SignalServiceAddress; import org.whispersystems.signalservice.api.util.UuidUtil; @@ -78,7 +79,7 @@ public class Recipient { private final RecipientId id; private final boolean resolving; - private final ACI aci; + private final ServiceId serviceId; private final PNI pni; private final String username; private final String e164; @@ -166,8 +167,8 @@ public class Recipient { * Returns a fully-populated {@link Recipient} and associates it with the provided username. */ @WorkerThread - public static @NonNull Recipient externalUsername(@NonNull Context context, @NonNull ACI aci, @NonNull String username) { - Recipient recipient = externalPush(context, aci, null, false); + public static @NonNull Recipient externalUsername(@NonNull ServiceId serviceId, @NonNull String username) { + Recipient recipient = externalPush(serviceId, null, false); SignalDatabase.recipients().setUsername(recipient.getId(), username); return recipient; } @@ -175,11 +176,11 @@ public class Recipient { /** * Returns a fully-populated {@link Recipient} based off of a {@link SignalServiceAddress}, * creating one in the database if necessary. Convenience overload of - * {@link #externalPush(Context, ACI, String, boolean)} + * {@link #externalPush(ServiceId, String, boolean)} */ @WorkerThread - public static @NonNull Recipient externalPush(@NonNull Context context, @NonNull SignalServiceAddress signalServiceAddress) { - return externalPush(context, signalServiceAddress.getAci(), signalServiceAddress.getNumber().orNull(), false); + public static @NonNull Recipient externalPush(@NonNull SignalServiceAddress signalServiceAddress) { + return externalPush(signalServiceAddress.getServiceId(), signalServiceAddress.getNumber().orNull(), false); } /** @@ -188,11 +189,11 @@ public class Recipient { * prioritize E164 addresses and not use the UUIDs if possible. */ @WorkerThread - public static @NonNull Recipient externalGV1Member(@NonNull Context context, @NonNull SignalServiceAddress address) { + public static @NonNull Recipient externalGV1Member(@NonNull SignalServiceAddress address) { if (address.getNumber().isPresent()) { - return externalPush(context, null, address.getNumber().get(), false); + return externalPush(null, address.getNumber().get(), false); } else { - return externalPush(context, address.getAci(), null, false); + return externalPush(address.getServiceId(), null, false); } } @@ -207,7 +208,7 @@ public class Recipient { */ @WorkerThread public static @NonNull Recipient externalHighTrustPush(@NonNull Context context, @NonNull SignalServiceAddress signalServiceAddress) { - return externalPush(context, signalServiceAddress.getAci(), signalServiceAddress.getNumber().orNull(), true); + return externalPush(signalServiceAddress.getServiceId(), signalServiceAddress.getNumber().orNull(), true); } /** @@ -223,13 +224,13 @@ public class Recipient { * that can be trusted as accurate (like an envelope). */ @WorkerThread - public static @NonNull Recipient externalPush(@NonNull Context context, @Nullable ACI aci, @Nullable String e164, boolean highTrust) { - if (ACI.UNKNOWN.equals(aci)) { + public static @NonNull Recipient externalPush(@Nullable ServiceId serviceId, @Nullable String e164, boolean highTrust) { + if (ServiceId.UNKNOWN.equals(serviceId)) { throw new AssertionError(); } RecipientDatabase db = SignalDatabase.recipients(); - RecipientId recipientId = db.getAndPossiblyMerge(aci, e164, highTrust); + RecipientId recipientId = db.getAndPossiblyMerge(serviceId, e164, highTrust); Recipient resolved = resolved(recipientId); @@ -237,9 +238,9 @@ public class Recipient { Log.w(TAG, "Resolved " + recipientId + ", but got back a recipient with " + resolved.getId()); } - if (highTrust && !resolved.isRegistered() && aci != null) { + if (highTrust && !resolved.isRegistered() && serviceId != null) { Log.w(TAG, "External high-trust push was locally marked unregistered. Marking as registered."); - db.markRegistered(recipientId, aci); + db.markRegistered(recipientId, serviceId); } else if (highTrust && !resolved.isRegistered()) { Log.w(TAG, "External high-trust push was locally marked unregistered, but we don't have an ACI, so we can't do anything.", new Throwable()); } @@ -305,7 +306,7 @@ public class Recipient { * or serialized groupId. * * If the identifier is a UUID of a Signal user, prefer using - * {@link #externalPush(Context, ACI, String, boolean)} or its overload, as this will let us associate + * {@link #externalPush(ServiceId, String, boolean)} or its overload, as this will let us associate * the phone number with the recipient. */ @WorkerThread @@ -317,7 +318,7 @@ public class Recipient { if (UuidUtil.isUuid(identifier)) { ACI uuid = ACI.parseOrThrow(identifier); - id = db.getOrInsertFromAci(uuid); + id = db.getOrInsertFromServiceId(uuid); } else if (GroupId.isEncodedGroup(identifier)) { id = db.getOrInsertFromGroupId(GroupId.parseOrThrow(identifier)); } else if (NumberUtil.isValidEmail(identifier)) { @@ -337,7 +338,7 @@ public class Recipient { Recipient(@NonNull RecipientId id) { this.id = id; this.resolving = true; - this.aci = null; + this.serviceId = null; this.pni = null; this.username = null; this.e164 = null; @@ -392,9 +393,9 @@ public class Recipient { public Recipient(@NonNull RecipientId id, @NonNull RecipientDetails details, boolean resolved) { this.id = id; - this.resolving = !resolved; - this.aci = details.aci; - this.pni = details.pni; + this.resolving = !resolved; + this.serviceId = details.serviceId; + this.pni = details.pni; this.username = details.username; this.e164 = details.e164; this.email = details.email; @@ -614,8 +615,8 @@ public class Recipient { return StringUtil.isolateBidi(name); } - public @NonNull Optional getAci() { - return Optional.fromNullable(aci); + public @NonNull Optional getServiceId() { + return Optional.fromNullable(serviceId); } public @NonNull Optional getPni() { @@ -646,16 +647,6 @@ public class Recipient { return Optional.fromNullable(e164).or(Optional.fromNullable(email)); } - public @NonNull ACI requireAci() { - ACI resolved = resolving ? resolve().aci : aci; - - if (resolved == null) { - throw new MissingAddressError(id); - } - - return resolved; - } - public @NonNull PNI requirePni() { PNI resolved = resolving ? resolve().pni : pni; @@ -706,16 +697,12 @@ public class Recipient { return getE164().isPresent(); } - public boolean hasAci() { - return getAci().isPresent(); + public boolean hasServiceId() { + return getServiceId().isPresent(); } - public boolean hasPni() { - return getPni().isPresent(); - } - - public boolean isAciOnly() { - return hasAci() && !hasSmsAddress(); + public boolean isServiceIdOnly() { + return hasServiceId() && !hasSmsAddress(); } public @NonNull GroupId requireGroupId() { @@ -728,36 +715,31 @@ public class Recipient { return resolved; } - public boolean hasServiceIdentifier() { - return aci != null || e164 != null; - } - /** - * @return A string identifier able to be used with the Signal service. Prefers ACI, and if not - * available, will return an E164 number. + * The {@link ServiceId} of the user if available, otherwise throw. */ - public @NonNull String requireServiceId() { - Recipient resolved = resolving ? resolve() : this; + public @NonNull ServiceId requireServiceId() { + ServiceId resolved = resolving ? resolve().serviceId : serviceId; - if (resolved.getAci().isPresent()) { - return resolved.requireAci().toString(); - } else { - return getE164().get(); + if (resolved == null) { + throw new MissingAddressError(id); } + + return resolved; } /** * @return A single string to represent the recipient, in order of precedence: * - * Group ID > ACI > Phone > Email + * Group ID > ServiceId > Phone > Email */ public @NonNull String requireStringId() { Recipient resolved = resolving ? resolve() : this; if (resolved.isGroup()) { return resolved.requireGroupId().toString(); - } else if (resolved.getAci().isPresent()) { - return resolved.requireAci().toString(); + } else if (resolved.getServiceId().isPresent()) { + return resolved.requireServiceId().toString(); } return requireSmsAddress(); @@ -1214,7 +1196,7 @@ public class Recipient { profileSharing == other.profileSharing && lastProfileFetch == other.lastProfileFetch && forceSmsSelection == other.forceSmsSelection && - Objects.equals(aci, other.aci) && + Objects.equals(serviceId, other.serviceId) && Objects.equals(username, other.username) && Objects.equals(e164, other.e164) && Objects.equals(email, other.email) && diff --git a/app/src/main/java/org/thoughtcrime/securesms/recipients/RecipientDetails.java b/app/src/main/java/org/thoughtcrime/securesms/recipients/RecipientDetails.java index bd6e9ffd9..c7c831c7b 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/recipients/RecipientDetails.java +++ b/app/src/main/java/org/thoughtcrime/securesms/recipients/RecipientDetails.java @@ -25,6 +25,7 @@ import org.thoughtcrime.securesms.wallpaper.ChatWallpaper; import org.whispersystems.libsignal.util.guava.Optional; import org.whispersystems.signalservice.api.push.ACI; import org.whispersystems.signalservice.api.push.PNI; +import org.whispersystems.signalservice.api.push.ServiceId; import java.util.Collections; import java.util.LinkedList; @@ -32,7 +33,7 @@ import java.util.List; public class RecipientDetails { - final ACI aci; + final ServiceId serviceId; final PNI pni; final String username; final String e164; @@ -99,7 +100,7 @@ public class RecipientDetails { this.systemContactPhoto = Util.uri(record.getSystemContactPhotoUri()); this.customLabel = record.getSystemPhoneLabel(); this.contactUri = Util.uri(record.getSystemContactUri()); - this.aci = record.getAci(); + this.serviceId = record.getServiceId(); this.pni = record.getPni(); this.username = record.getUsername(); this.e164 = record.getE164(); @@ -156,9 +157,9 @@ public class RecipientDetails { this.groupAvatarId = null; this.systemContactPhoto = null; this.customLabel = null; - this.contactUri = null; - this.aci = null; - this.pni = null; + this.contactUri = null; + this.serviceId = null; + this.pni = null; this.username = null; this.e164 = null; this.email = null; @@ -210,7 +211,7 @@ public class RecipientDetails { public static @NonNull RecipientDetails forIndividual(@NonNull Context context, @NonNull RecipientRecord settings) { boolean systemContact = !settings.getSystemProfileName().isEmpty(); boolean isSelf = (settings.getE164() != null && settings.getE164().equals(SignalStore.account().getE164())) || - (settings.getAci() != null && settings.getAci().equals(SignalStore.account().getAci())); + (settings.getServiceId() != null && settings.getServiceId().equals(SignalStore.account().getAci())); boolean isReleaseChannel = settings.getId().equals(SignalStore.releaseChannelValues().getReleaseChannelRecipientId()); RegisteredState registeredState = settings.getRegistered(); diff --git a/app/src/main/java/org/thoughtcrime/securesms/recipients/RecipientId.java b/app/src/main/java/org/thoughtcrime/securesms/recipients/RecipientId.java index f53c82f3d..951ab2880 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/recipients/RecipientId.java +++ b/app/src/main/java/org/thoughtcrime/securesms/recipients/RecipientId.java @@ -15,13 +15,13 @@ import org.thoughtcrime.securesms.dependencies.ApplicationDependencies; import org.thoughtcrime.securesms.util.DelimiterUtil; import org.thoughtcrime.securesms.util.Util; import org.whispersystems.signalservice.api.push.ACI; +import org.whispersystems.signalservice.api.push.ServiceId; import org.whispersystems.signalservice.api.push.SignalServiceAddress; import org.whispersystems.signalservice.api.util.UuidUtil; import java.util.ArrayList; import java.util.Collection; import java.util.List; -import java.util.UUID; import java.util.regex.Pattern; public class RecipientId implements Parcelable, Comparable { @@ -55,7 +55,7 @@ public class RecipientId implements Parcelable, Comparable { @AnyThread public static @NonNull RecipientId from(@NonNull SignalServiceAddress address) { - return from(address.getAci(), address.getNumber().orNull(), false); + return from(address.getServiceId(), address.getNumber().orNull(), false); } /** @@ -78,7 +78,7 @@ public class RecipientId implements Parcelable, Comparable { */ @AnyThread public static @NonNull RecipientId fromHighTrust(@NonNull SignalServiceAddress address) { - return from(address.getAci(), address.getNumber().orNull(), true); + return from(address.getServiceId(), address.getNumber().orNull(), true); } /** @@ -86,17 +86,17 @@ public class RecipientId implements Parcelable, Comparable { */ @AnyThread @SuppressLint("WrongThread") - public static @NonNull RecipientId from(@Nullable ACI aci, @Nullable String e164) { + public static @NonNull RecipientId from(@Nullable ServiceId aci, @Nullable String e164) { return from(aci, e164, false); } @AnyThread @SuppressLint("WrongThread") - private static @NonNull RecipientId from(@Nullable ACI aci, @Nullable String e164, boolean highTrust) { + private static @NonNull RecipientId from(@Nullable ServiceId aci, @Nullable String e164, boolean highTrust) { RecipientId recipientId = RecipientIdCache.INSTANCE.get(aci, e164); if (recipientId == null) { - Recipient recipient = Recipient.externalPush(ApplicationDependencies.getApplication(), aci, e164, highTrust); + Recipient recipient = Recipient.externalPush(aci, e164, highTrust); RecipientIdCache.INSTANCE.put(recipient); recipientId = recipient.getId(); } diff --git a/app/src/main/java/org/thoughtcrime/securesms/recipients/RecipientIdCache.java b/app/src/main/java/org/thoughtcrime/securesms/recipients/RecipientIdCache.java index b13c68ca9..448e8607a 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/recipients/RecipientIdCache.java +++ b/app/src/main/java/org/thoughtcrime/securesms/recipients/RecipientIdCache.java @@ -5,11 +5,10 @@ import androidx.annotation.Nullable; import org.signal.core.util.logging.Log; import org.whispersystems.libsignal.util.guava.Optional; -import org.whispersystems.signalservice.api.push.ACI; +import org.whispersystems.signalservice.api.push.ServiceId; import java.util.LinkedHashMap; import java.util.Map; -import java.util.UUID; /** * Thread safe cache that allows faster looking up of {@link RecipientId}s without hitting the database. @@ -34,22 +33,22 @@ final class RecipientIdCache { } synchronized void put(@NonNull Recipient recipient) { - RecipientId recipientId = recipient.getId(); - Optional e164 = recipient.getE164(); - Optional aci = recipient.getAci(); + RecipientId recipientId = recipient.getId(); + Optional e164 = recipient.getE164(); + Optional serviceId = recipient.getServiceId(); if (e164.isPresent()) { ids.put(e164.get(), recipientId); } - if (aci.isPresent()) { - ids.put(aci.get(), recipientId); + if (serviceId.isPresent()) { + ids.put(serviceId.get(), recipientId); } } - synchronized @Nullable RecipientId get(@Nullable ACI aci, @Nullable String e164) { - if (aci != null && e164 != null) { - RecipientId recipientIdByAci = ids.get(aci); + synchronized @Nullable RecipientId get(@Nullable ServiceId serviceId, @Nullable String e164) { + if (serviceId != null && e164 != null) { + RecipientId recipientIdByAci = ids.get(serviceId); if (recipientIdByAci == null) return null; RecipientId recipientIdByE164 = ids.get(e164); @@ -58,13 +57,13 @@ final class RecipientIdCache { if (recipientIdByAci.equals(recipientIdByE164)) { return recipientIdByAci; } else { - ids.remove(aci); + ids.remove(serviceId); ids.remove(e164); Log.w(TAG, "Seen invalid RecipientIdCacheState"); return null; } - } else if (aci != null) { - return ids.get(aci); + } else if (serviceId != null) { + return ids.get(serviceId); } else if (e164 != null) { return ids.get(e164); } 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 c3166f36b..b554b2a36 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/recipients/RecipientUtil.java +++ b/app/src/main/java/org/thoughtcrime/securesms/recipients/RecipientUtil.java @@ -49,11 +49,11 @@ public class RecipientUtil { { recipient = recipient.resolve(); - if (!recipient.getAci().isPresent() && !recipient.getE164().isPresent()) { + if (!recipient.getServiceId().isPresent() && !recipient.getE164().isPresent()) { throw new AssertionError(recipient.getId() + " - No UUID or phone number!"); } - if (!recipient.getAci().isPresent()) { + if (!recipient.getServiceId().isPresent()) { Log.i(TAG, recipient.getId() + " is missing a UUID..."); RegisteredState state = DirectoryHelper.refreshDirectoryFor(context, recipient, false); @@ -61,8 +61,8 @@ public class RecipientUtil { Log.i(TAG, "Successfully performed a UUID fetch for " + recipient.getId() + ". Registered: " + state); } - if (recipient.hasAci()) { - return new SignalServiceAddress(recipient.requireAci(), Optional.fromNullable(recipient.resolve().getE164().orNull())); + if (recipient.hasServiceId()) { + return new SignalServiceAddress(recipient.requireServiceId(), Optional.fromNullable(recipient.resolve().getE164().orNull())); } else { throw new NotFoundException(recipient.getId() + " is not registered!"); } @@ -81,7 +81,7 @@ public class RecipientUtil { return Stream.of(recipients) .map(Recipient::resolve) - .map(r -> new SignalServiceAddress(r.requireAci(), r.getE164().orNull())) + .map(r -> new SignalServiceAddress(r.requireServiceId(), r.getE164().orNull())) .toList(); } @@ -93,7 +93,7 @@ public class RecipientUtil { { List recipientsWithoutUuids = Stream.of(recipients) .map(Recipient::resolve) - .filterNot(Recipient::hasAci) + .filterNot(Recipient::hasServiceId) .toList(); if (recipientsWithoutUuids.size() > 0) { @@ -178,7 +178,7 @@ public class RecipientUtil { ApplicationDependencies.getJobManager().add(new MultiDeviceBlockedUpdateJob()); StorageSyncHelper.scheduleSyncForDataChange(); - if (recipient.hasServiceIdentifier()) { + if (recipient.hasServiceId()) { ApplicationDependencies.getJobManager().add(MultiDeviceMessageRequestResponseJob.forAccept(recipient.getId())); } } diff --git a/app/src/main/java/org/thoughtcrime/securesms/registration/RegistrationRepository.java b/app/src/main/java/org/thoughtcrime/securesms/registration/RegistrationRepository.java index 8e59d307d..cc145d4b8 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/registration/RegistrationRepository.java +++ b/app/src/main/java/org/thoughtcrime/securesms/registration/RegistrationRepository.java @@ -37,8 +37,9 @@ import org.whispersystems.libsignal.util.guava.Optional; import org.whispersystems.signalservice.api.KbsPinData; import org.whispersystems.signalservice.api.SignalServiceAccountManager; import org.whispersystems.signalservice.api.push.ACI; -import org.whispersystems.signalservice.api.push.AccountIdentifier; +import org.whispersystems.signalservice.api.push.ServiceId; import org.whispersystems.signalservice.api.push.PNI; +import org.whispersystems.signalservice.api.push.ServiceIdType; import org.whispersystems.signalservice.api.push.SignalServiceAddress; import org.whispersystems.signalservice.internal.ServiceResponse; import org.whispersystems.signalservice.internal.push.VerifyAccountResponse; @@ -142,15 +143,15 @@ public final class RegistrationRepository { SignalServiceAccountDataStoreImpl aciProtocolStore = ApplicationDependencies.getProtocolStore().aci(); SignalServiceAccountDataStoreImpl pniProtocolStore = ApplicationDependencies.getProtocolStore().pni(); - generateAndRegisterPreKeys(aci, accountManager, aciProtocolStore, SignalStore.account().aciPreKeys()); - generateAndRegisterPreKeys(pni, accountManager, pniProtocolStore, SignalStore.account().pniPreKeys()); + generateAndRegisterPreKeys(ServiceIdType.ACI, accountManager, aciProtocolStore, SignalStore.account().aciPreKeys()); + generateAndRegisterPreKeys(ServiceIdType.PNI, accountManager, pniProtocolStore, SignalStore.account().pniPreKeys()); if (registrationData.isFcm()) { accountManager.setGcmId(Optional.fromNullable(registrationData.getFcmToken())); } RecipientDatabase recipientDatabase = SignalDatabase.recipients(); - RecipientId selfId = Recipient.externalPush(context, aci, registrationData.getE164(), true).getId(); + RecipientId selfId = Recipient.externalPush(aci, registrationData.getE164(), true).getId(); recipientDatabase.setProfileSharing(selfId, true); recipientDatabase.markRegisteredOrThrow(selfId, aci); @@ -175,7 +176,7 @@ public final class RegistrationRepository { PinState.onRegistration(context, kbsData, pin, hasPin); } - private void generateAndRegisterPreKeys(@NonNull AccountIdentifier accountId, + private void generateAndRegisterPreKeys(@NonNull ServiceIdType serviceIdType, @NonNull SignalServiceAccountManager accountManager, @NonNull SignalProtocolStore protocolStore, @NonNull PreKeyMetadataStore metadataStore) @@ -184,7 +185,7 @@ public final class RegistrationRepository { SignedPreKeyRecord signedPreKey = PreKeyUtil.generateAndStoreSignedPreKey(protocolStore, metadataStore, true); List oneTimePreKeys = PreKeyUtil.generateAndStoreOneTimePreKeys(protocolStore, metadataStore); - accountManager.setPreKeys(accountId, protocolStore.getIdentityKeyPair().getPublicKey(), signedPreKey, oneTimePreKeys); + accountManager.setPreKeys(serviceIdType, protocolStore.getIdentityKeyPair().getPublicKey(), signedPreKey, oneTimePreKeys); metadataStore.setSignedPreKeyRegistered(true); } diff --git a/app/src/main/java/org/thoughtcrime/securesms/service/webrtc/GroupActionProcessor.java b/app/src/main/java/org/thoughtcrime/securesms/service/webrtc/GroupActionProcessor.java index 6714f6ec2..0595e2fc2 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/service/webrtc/GroupActionProcessor.java +++ b/app/src/main/java/org/thoughtcrime/securesms/service/webrtc/GroupActionProcessor.java @@ -83,7 +83,7 @@ public class GroupActionProcessor extends DeviceAwareActionProcessor { seen.add(Recipient.self()); for (GroupCall.RemoteDeviceState device : remoteDeviceStates) { - Recipient recipient = Recipient.externalPush(context, ACI.from(device.getUserId()), null, false); + Recipient recipient = Recipient.externalPush(ACI.from(device.getUserId()), null, false); CallParticipantId callParticipantId = new CallParticipantId(device.getDemuxId(), recipient.getId()); CallParticipant callParticipant = participants.get(callParticipantId); diff --git a/app/src/main/java/org/thoughtcrime/securesms/service/webrtc/GroupConnectedActionProcessor.java b/app/src/main/java/org/thoughtcrime/securesms/service/webrtc/GroupConnectedActionProcessor.java index 2f1774647..4e59654c2 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/service/webrtc/GroupConnectedActionProcessor.java +++ b/app/src/main/java/org/thoughtcrime/securesms/service/webrtc/GroupConnectedActionProcessor.java @@ -123,8 +123,8 @@ public class GroupConnectedActionProcessor extends GroupActionProcessor { webRtcInteractor.sendGroupCallMessage(currentState.getCallInfoState().getCallRecipient(), eraId); List members = new ArrayList<>(peekInfo.getJoinedMembers()); - if (!members.contains(Recipient.self().requireAci().uuid())) { - members.add(Recipient.self().requireAci().uuid()); + if (!members.contains(Recipient.self().requireServiceId().uuid())) { + members.add(Recipient.self().requireServiceId().uuid()); } webRtcInteractor.updateGroupCallUpdateMessage(currentState.getCallInfoState().getCallRecipient().getId(), eraId, members, WebRtcUtil.isCallFull(peekInfo)); @@ -149,7 +149,7 @@ public class GroupConnectedActionProcessor extends GroupActionProcessor { String eraId = WebRtcUtil.getGroupCallEraId(groupCall); webRtcInteractor.sendGroupCallMessage(currentState.getCallInfoState().getCallRecipient(), eraId); - List members = Stream.of(currentState.getCallInfoState().getRemoteCallParticipants()).map(p -> p.getRecipient().requireAci().uuid()).toList(); + List members = Stream.of(currentState.getCallInfoState().getRemoteCallParticipants()).map(p -> p.getRecipient().requireServiceId().uuid()).toList(); webRtcInteractor.updateGroupCallUpdateMessage(currentState.getCallInfoState().getCallRecipient().getId(), eraId, members, false); currentState = currentState.builder() diff --git a/app/src/main/java/org/thoughtcrime/securesms/service/webrtc/GroupPreJoinActionProcessor.java b/app/src/main/java/org/thoughtcrime/securesms/service/webrtc/GroupPreJoinActionProcessor.java index 206bf4492..91c4f5761 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/service/webrtc/GroupPreJoinActionProcessor.java +++ b/app/src/main/java/org/thoughtcrime/securesms/service/webrtc/GroupPreJoinActionProcessor.java @@ -114,7 +114,7 @@ public class GroupPreJoinActionProcessor extends GroupActionProcessor { } List callParticipants = Stream.of(peekInfo.getJoinedMembers()) - .map(uuid -> Recipient.externalPush(context, ACI.from(uuid), null, false)) + .map(uuid -> Recipient.externalPush(ACI.from(uuid), null, false)) .toList(); WebRtcServiceStateBuilder.CallInfoStateBuilder builder = currentState.builder() diff --git a/app/src/main/java/org/thoughtcrime/securesms/service/webrtc/IncomingGroupCallActionProcessor.java b/app/src/main/java/org/thoughtcrime/securesms/service/webrtc/IncomingGroupCallActionProcessor.java index c186d0caf..aaba5efaa 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/service/webrtc/IncomingGroupCallActionProcessor.java +++ b/app/src/main/java/org/thoughtcrime/securesms/service/webrtc/IncomingGroupCallActionProcessor.java @@ -138,7 +138,7 @@ public final class IncomingGroupCallActionProcessor extends DeviceAwareActionPro .changeCallSetupState(RemotePeer.GROUP_CALL_ID) .isRemoteVideoOffer(true) .ringId(ringId) - .ringerRecipient(Recipient.externalPush(context, ACI.from(uuid), null, false)) + .ringerRecipient(Recipient.externalPush(ACI.from(uuid), null, false)) .commit() .changeCallInfoState() .activePeer(new RemotePeer(currentState.getCallInfoState().getCallRecipient().getId(), RemotePeer.GROUP_CALL_ID)) 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 793957796..8d29cdfe8 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 @@ -154,7 +154,7 @@ public final class SignalCallManager implements CallManager.Observer, GroupCall. serviceExecutor.execute(() -> { if (needsToSetSelfUuid) { try { - callManager.setSelfUuid(Recipient.self().requireAci().uuid()); + callManager.setSelfUuid(Recipient.self().requireServiceId().uuid()); needsToSetSelfUuid = false; } catch (CallException e) { Log.w(TAG, "Unable to set self UUID on CallManager", e); diff --git a/app/src/main/java/org/thoughtcrime/securesms/storage/ContactRecordProcessor.java b/app/src/main/java/org/thoughtcrime/securesms/storage/ContactRecordProcessor.java index a885de696..c68afa9bd 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/storage/ContactRecordProcessor.java +++ b/app/src/main/java/org/thoughtcrime/securesms/storage/ContactRecordProcessor.java @@ -13,9 +13,9 @@ import org.thoughtcrime.securesms.recipients.Recipient; import org.thoughtcrime.securesms.recipients.RecipientId; import org.whispersystems.libsignal.util.guava.Optional; import org.whispersystems.signalservice.api.push.ACI; +import org.whispersystems.signalservice.api.push.ServiceId; import org.whispersystems.signalservice.api.push.SignalServiceAddress; import org.whispersystems.signalservice.api.storage.SignalContactRecord; -import org.whispersystems.signalservice.api.util.UuidUtil; import org.whispersystems.signalservice.internal.storage.protos.ContactRecord.IdentityState; import java.util.Arrays; @@ -51,10 +51,10 @@ public class ContactRecordProcessor extends DefaultStorageRecordProcessor getMatching(@NonNull SignalContactRecord remote, @NonNull StorageKeyGenerator keyGenerator) { SignalServiceAddress address = remote.getAddress(); - Optional byUuid = recipientDatabase.getByAci(address.getAci()); + Optional byUuid = recipientDatabase.getByServiceId(address.getServiceId()); Optional byE164 = address.getNumber().isPresent() ? recipientDatabase.getByE164(address.getNumber().get()) : Optional.absent(); return byUuid.or(byE164).transform(recipientDatabase::getRecordForSync) @@ -98,9 +98,9 @@ public class ContactRecordProcessor extends DefaultStorageRecordProcessor { Recipient recipient = Recipient.external(activity, e164); - if (!recipient.isRegistered() || !recipient.hasAci()) { + if (!recipient.isRegistered() || !recipient.hasServiceId()) { try { DirectoryHelper.refreshDirectoryFor(activity, recipient, false); recipient = Recipient.resolved(recipient.getId()); 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 21c3db8d9..fd7b9e128 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/util/IdentityUtil.java +++ b/app/src/main/java/org/thoughtcrime/securesms/util/IdentityUtil.java @@ -161,7 +161,7 @@ public final class IdentityUtil { public static void processVerifiedMessage(Context context, VerifiedMessage verifiedMessage) { try(SignalSessionLock.Lock unused = ReentrantSessionLock.INSTANCE.acquire()) { SignalIdentityKeyStore identityStore = ApplicationDependencies.getProtocolStore().aci().identities(); - Recipient recipient = Recipient.externalPush(context, verifiedMessage.getDestination()); + Recipient recipient = Recipient.externalPush(verifiedMessage.getDestination()); Optional identityRecord = identityStore.getIdentityRecord(recipient.getId()); if (!identityRecord.isPresent() && verifiedMessage.getVerified() == VerifiedMessage.VerifiedState.DEFAULT) { diff --git a/app/src/main/java/org/thoughtcrime/securesms/util/LocaleFeatureFlags.java b/app/src/main/java/org/thoughtcrime/securesms/util/LocaleFeatureFlags.java index f7d0f9e84..c7426d2fd 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/util/LocaleFeatureFlags.java +++ b/app/src/main/java/org/thoughtcrime/securesms/util/LocaleFeatureFlags.java @@ -76,12 +76,12 @@ public final class LocaleFeatureFlags { Map countryCodeValues = parseCountryValues(serialized, 0); Recipient self = Recipient.self(); - if (countryCodeValues.isEmpty() || !self.getE164().isPresent() || !self.getAci().isPresent()) { + if (countryCodeValues.isEmpty() || !self.getE164().isPresent() || !self.getServiceId().isPresent()) { return false; } long countEnabled = getCountryValue(countryCodeValues, self.getE164().or(""), 0); - long currentUserBucket = BucketingUtil.bucket(flag, self.requireAci().uuid(), 1_000_000); + long currentUserBucket = BucketingUtil.bucket(flag, self.requireServiceId().uuid(), 1_000_000); return countEnabled > currentUserBucket; } diff --git a/app/src/main/java/org/thoughtcrime/securesms/util/ProfileUtil.java b/app/src/main/java/org/thoughtcrime/securesms/util/ProfileUtil.java index c33eeab77..7df9d9984 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/util/ProfileUtil.java +++ b/app/src/main/java/org/thoughtcrime/securesms/util/ProfileUtil.java @@ -10,7 +10,6 @@ import org.signal.core.util.logging.Log; import org.signal.zkgroup.InvalidInputException; import org.signal.zkgroup.profiles.ProfileKey; import org.thoughtcrime.securesms.badges.models.Badge; -import org.thoughtcrime.securesms.crypto.IdentityKeyUtil; import org.thoughtcrime.securesms.crypto.ProfileKeyUtil; import org.thoughtcrime.securesms.crypto.UnidentifiedAccessUtil; import org.thoughtcrime.securesms.database.RecipientDatabase; @@ -284,7 +283,7 @@ public final class ProfileUtil { ProfileKey profileKey = ProfileKeyUtil.getSelfProfileKey(); SignalServiceAccountManager accountManager = ApplicationDependencies.getSignalServiceAccountManager(); - String avatarPath = accountManager.setVersionedProfile(Recipient.self().requireAci(), + String avatarPath = accountManager.setVersionedProfile(SignalStore.account().requireAci(), profileKey, profileName.serialize(), about, @@ -321,8 +320,8 @@ public final class ProfileUtil { private static @NonNull SignalServiceAddress toSignalServiceAddress(@NonNull Context context, @NonNull Recipient recipient) throws IOException { if (recipient.getRegistered() == RecipientDatabase.RegisteredState.NOT_REGISTERED) { - if (recipient.hasAci()) { - return new SignalServiceAddress(recipient.requireAci(), recipient.getE164().orNull()); + if (recipient.hasServiceId()) { + return new SignalServiceAddress(recipient.requireServiceId(), recipient.getE164().orNull()); } else { throw new IOException(recipient.getId() + " not registered!"); } diff --git a/app/src/main/java/org/thoughtcrime/securesms/util/RecipientAccessList.kt b/app/src/main/java/org/thoughtcrime/securesms/util/RecipientAccessList.kt index d81d2a5cd..7bd7acb64 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/util/RecipientAccessList.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/util/RecipientAccessList.kt @@ -2,7 +2,7 @@ package org.thoughtcrime.securesms.util import org.thoughtcrime.securesms.recipients.Recipient import org.thoughtcrime.securesms.recipients.RecipientId -import org.whispersystems.signalservice.api.push.ACI +import org.whispersystems.signalservice.api.push.ServiceId import org.whispersystems.signalservice.api.push.SignalServiceAddress /** @@ -11,10 +11,10 @@ import org.whispersystems.signalservice.api.push.SignalServiceAddress */ class RecipientAccessList(private val recipients: List) : List by recipients { - private val byAci: Map by lazy { + private val byServiceId: Map by lazy { recipients - .filter { it.hasAci() } - .associateBy { it.requireAci() } + .filter { it.hasServiceId() } + .associateBy { it.requireServiceId() } } private val byE164: Map by lazy { @@ -24,8 +24,8 @@ class RecipientAccessList(private val recipients: List) : List fetchAciForUsername(@NonNull Context context, @NonNull String username) { + public static @NonNull Optional fetchAciForUsername(@NonNull String username) { Optional localId = SignalDatabase.recipients().getByUsername(username); if (localId.isPresent()) { Recipient recipient = Recipient.resolved(localId.get()); - if (recipient.getAci().isPresent()) { + if (recipient.getServiceId().isPresent()) { Log.i(TAG, "Found username locally -- using associated UUID."); - return recipient.getAci(); + return recipient.getServiceId(); } else { Log.w(TAG, "Found username locally, but it had no associated UUID! Clearing it."); SignalDatabase.recipients().clearUsernameIfExists(username); diff --git a/app/src/main/java/org/thoughtcrime/securesms/verify/VerifyDisplayFragment.java b/app/src/main/java/org/thoughtcrime/securesms/verify/VerifyDisplayFragment.java index 513b01a7f..29d17dbb0 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/verify/VerifyDisplayFragment.java +++ b/app/src/main/java/org/thoughtcrime/securesms/verify/VerifyDisplayFragment.java @@ -16,7 +16,6 @@ import android.text.TextUtils; import android.text.method.LinkMovementMethod; import android.view.ContextMenu; import android.view.LayoutInflater; -import android.view.Menu; import android.view.MenuInflater; import android.view.MenuItem; import android.view.View; @@ -35,7 +34,6 @@ import android.widget.Toast; import androidx.annotation.DrawableRes; import androidx.annotation.NonNull; import androidx.annotation.Nullable; -import androidx.appcompat.app.AppCompatActivity; import androidx.appcompat.widget.Toolbar; import androidx.fragment.app.Fragment; import androidx.interpolator.view.animation.FastOutSlowInInterpolator; @@ -212,18 +210,18 @@ public class VerifyDisplayFragment extends Fragment implements ViewTreeObserver. //noinspection WrongThread Recipient resolved = recipient.resolve(); - if (FeatureFlags.verifyV2() && resolved.getAci().isPresent()) { + if (FeatureFlags.verifyV2() && resolved.getServiceId().isPresent()) { Log.i(TAG, "Using UUID (version 2)."); version = 2; - localId = Recipient.self().requireAci().toByteArray(); - remoteId = resolved.requireAci().toByteArray(); + localId = Recipient.self().requireServiceId().toByteArray(); + remoteId = resolved.requireServiceId().toByteArray(); } else if (!FeatureFlags.verifyV2() && resolved.getE164().isPresent()) { Log.i(TAG, "Using E164 (version 1)."); version = 1; localId = Recipient.self().requireE164().getBytes(); remoteId = resolved.requireE164().getBytes(); } else { - Log.w(TAG, String.format(Locale.ENGLISH, "Could not show proper verification! verifyV2: %s, hasUuid: %s, hasE164: %s", FeatureFlags.verifyV2(), resolved.getAci().isPresent(), resolved.getE164().isPresent())); + Log.w(TAG, String.format(Locale.ENGLISH, "Could not show proper verification! verifyV2: %s, hasUuid: %s, hasE164: %s", FeatureFlags.verifyV2(), resolved.getServiceId().isPresent(), resolved.getE164().isPresent())); new MaterialAlertDialogBuilder(requireContext()) .setMessage(getString(R.string.VerifyIdentityActivity_you_must_first_exchange_messages_in_order_to_view, resolved.getDisplayName(requireContext()))) .setPositiveButton(android.R.string.ok, (dialog, which) -> requireActivity().finish()) diff --git a/app/src/test/java/org/thoughtcrime/securesms/database/model/GroupsV2UpdateMessageProducerTest.java b/app/src/test/java/org/thoughtcrime/securesms/database/model/GroupsV2UpdateMessageProducerTest.java index 2e77cc4a6..2cbebc7f6 100644 --- a/app/src/test/java/org/thoughtcrime/securesms/database/model/GroupsV2UpdateMessageProducerTest.java +++ b/app/src/test/java/org/thoughtcrime/securesms/database/model/GroupsV2UpdateMessageProducerTest.java @@ -26,6 +26,7 @@ import org.signal.storageservice.protos.groups.local.DecryptedMember; import org.signal.storageservice.protos.groups.local.DecryptedPendingMember; import org.thoughtcrime.securesms.testutil.MainThreadUtil; import org.whispersystems.signalservice.api.push.ACI; +import org.whispersystems.signalservice.api.push.ServiceId; import org.whispersystems.signalservice.api.util.UuidUtil; import java.util.Arrays; @@ -1351,14 +1352,14 @@ public final class GroupsV2UpdateMessageProducerTest { } private void assertSingleChangeMentioning(DecryptedGroupChange change, List expectedMentions) { - List expectedMentionAcis = expectedMentions.stream().map(ACI::from).collect(Collectors.toList()); + List expectedMentionSids = expectedMentions.stream().map(ServiceId::from).collect(Collectors.toList()); List changes = producer.describeChanges(null, change); assertThat(changes.size(), is(1)); UpdateDescription description = changes.get(0); - assertThat(description.getMentioned(), is(expectedMentionAcis)); + assertThat(description.getMentioned(), is(expectedMentionSids)); if (expectedMentions.isEmpty()) { assertTrue(description.isStringStatic()); @@ -1397,8 +1398,8 @@ public final class GroupsV2UpdateMessageProducerTest { } private static @NonNull GroupsV2UpdateMessageProducer.DescribeMemberStrategy createDescriber(@NonNull Map map) { - return aci -> { - String name = map.get(aci.uuid()); + return serviceId -> { + String name = map.get(serviceId.uuid()); assertNotNull(name); return name; }; diff --git a/app/src/test/java/org/thoughtcrime/securesms/recipients/RecipientIdCacheTest.java b/app/src/test/java/org/thoughtcrime/securesms/recipients/RecipientIdCacheTest.java index f888a3769..4eb0c471b 100644 --- a/app/src/test/java/org/thoughtcrime/securesms/recipients/RecipientIdCacheTest.java +++ b/app/src/test/java/org/thoughtcrime/securesms/recipients/RecipientIdCacheTest.java @@ -266,7 +266,7 @@ public final class RecipientIdCacheTest { Recipient mock = mock(Recipient.class); when(mock.getId()).thenReturn(recipientId); - when(mock.getAci()).thenReturn(Optional.fromNullable(aci)); + when(mock.getServiceId()).thenReturn(Optional.fromNullable(aci)); when(mock.getE164()).thenReturn(Optional.fromNullable(e164)); return mock; diff --git a/app/src/test/java/org/thoughtcrime/securesms/storage/StorageSyncHelperTest.java b/app/src/test/java/org/thoughtcrime/securesms/storage/StorageSyncHelperTest.java index 62689405f..6cdd9010b 100644 --- a/app/src/test/java/org/thoughtcrime/securesms/storage/StorageSyncHelperTest.java +++ b/app/src/test/java/org/thoughtcrime/securesms/storage/StorageSyncHelperTest.java @@ -27,10 +27,8 @@ import org.whispersystems.signalservice.api.storage.StorageId; import java.util.Arrays; import java.util.HashMap; -import java.util.LinkedHashSet; import java.util.List; import java.util.Map; -import java.util.Set; import static junit.framework.TestCase.assertTrue; import static org.junit.Assert.assertEquals; @@ -57,7 +55,7 @@ public final class StorageSyncHelperTest { private static final Recipient SELF = mock(Recipient.class); static { - when(SELF.getAci()).thenReturn(Optional.of(ACI_SELF)); + when(SELF.getServiceId()).thenReturn(Optional.of(ACI_SELF)); when(SELF.getE164()).thenReturn(Optional.of(E164_SELF)); when(SELF.resolve()).thenReturn(SELF); } diff --git a/libsignal/service/src/main/java/org/whispersystems/signalservice/api/SignalServiceAccountManager.java b/libsignal/service/src/main/java/org/whispersystems/signalservice/api/SignalServiceAccountManager.java index ce9a54ca4..fb15e571d 100644 --- a/libsignal/service/src/main/java/org/whispersystems/signalservice/api/SignalServiceAccountManager.java +++ b/libsignal/service/src/main/java/org/whispersystems/signalservice/api/SignalServiceAccountManager.java @@ -35,8 +35,9 @@ import org.whispersystems.signalservice.api.payments.CurrencyConversions; import org.whispersystems.signalservice.api.profiles.ProfileAndCredential; import org.whispersystems.signalservice.api.profiles.SignalServiceProfileWrite; import org.whispersystems.signalservice.api.push.ACI; -import org.whispersystems.signalservice.api.push.AccountIdentifier; +import org.whispersystems.signalservice.api.push.ServiceId; import org.whispersystems.signalservice.api.push.PNI; +import org.whispersystems.signalservice.api.push.ServiceIdType; import org.whispersystems.signalservice.api.push.SignedPreKeyEntity; import org.whispersystems.signalservice.api.push.exceptions.NoContentException; import org.whispersystems.signalservice.api.push.exceptions.NonSuccessfulResponseCodeException; @@ -420,18 +421,18 @@ public class SignalServiceAccountManager { * * @throws IOException */ - public void setPreKeys(AccountIdentifier accountId, IdentityKey identityKey, SignedPreKeyRecord signedPreKey, List oneTimePreKeys) + public void setPreKeys(ServiceIdType serviceIdType, IdentityKey identityKey, SignedPreKeyRecord signedPreKey, List oneTimePreKeys) throws IOException { - this.pushServiceSocket.registerPreKeys(accountId, identityKey, signedPreKey, oneTimePreKeys); + this.pushServiceSocket.registerPreKeys(serviceIdType, identityKey, signedPreKey, oneTimePreKeys); } /** * @return The server's count of currently available (eg. unused) prekeys for this user. * @throws IOException */ - public int getPreKeysCount(AccountIdentifier accountId) throws IOException { - return this.pushServiceSocket.getAvailablePreKeys(accountId); + public int getPreKeysCount(ServiceIdType serviceIdType) throws IOException { + return this.pushServiceSocket.getAvailablePreKeys(serviceIdType); } /** @@ -440,22 +441,22 @@ public class SignalServiceAccountManager { * @param signedPreKey The client's new signed prekey. * @throws IOException */ - public void setSignedPreKey(AccountIdentifier accountId, SignedPreKeyRecord signedPreKey) throws IOException { - this.pushServiceSocket.setCurrentSignedPreKey(accountId, signedPreKey); + public void setSignedPreKey(ServiceIdType serviceIdType, SignedPreKeyRecord signedPreKey) throws IOException { + this.pushServiceSocket.setCurrentSignedPreKey(serviceIdType, signedPreKey); } /** * @return The server's view of the client's current signed prekey. * @throws IOException */ - public SignedPreKeyEntity getSignedPreKey(AccountIdentifier accountId) throws IOException { - return this.pushServiceSocket.getCurrentSignedPreKey(accountId); + public SignedPreKeyEntity getSignedPreKey(ServiceIdType serviceIdType) throws IOException { + return this.pushServiceSocket.getCurrentSignedPreKey(serviceIdType); } /** * @return True if the identifier corresponds to a registered user, otherwise false. */ - public boolean isIdentifierRegistered(AccountIdentifier identifier) throws IOException { + public boolean isIdentifierRegistered(ServiceId identifier) throws IOException { return pushServiceSocket.isIdentifierRegistered(identifier); } @@ -815,11 +816,11 @@ public class SignalServiceAccountManager { profileAvatarData); } - public Optional resolveProfileKeyCredential(ACI aci, ProfileKey profileKey, Locale locale) + public Optional resolveProfileKeyCredential(ServiceId serviceId, ProfileKey profileKey, Locale locale) throws NonSuccessfulResponseCodeException, PushNetworkException { try { - ProfileAndCredential credential = this.pushServiceSocket.retrieveVersionedProfileAndCredential(aci.uuid(), profileKey, Optional.absent(), locale).get(10, TimeUnit.SECONDS); + ProfileAndCredential credential = this.pushServiceSocket.retrieveVersionedProfileAndCredential(serviceId.uuid(), profileKey, Optional.absent(), locale).get(10, TimeUnit.SECONDS); return credential.getProfileKeyCredential(); } catch (InterruptedException | TimeoutException e) { throw new PushNetworkException(e); diff --git a/libsignal/service/src/main/java/org/whispersystems/signalservice/api/SignalServiceDataStore.java b/libsignal/service/src/main/java/org/whispersystems/signalservice/api/SignalServiceDataStore.java index 28250c61b..3b9cf25d2 100644 --- a/libsignal/service/src/main/java/org/whispersystems/signalservice/api/SignalServiceDataStore.java +++ b/libsignal/service/src/main/java/org/whispersystems/signalservice/api/SignalServiceDataStore.java @@ -1,6 +1,6 @@ package org.whispersystems.signalservice.api; -import org.whispersystems.signalservice.api.push.AccountIdentifier; +import org.whispersystems.signalservice.api.push.ServiceId; /** * And extension of the normal protocol store interface that has additional methods that are needed @@ -11,7 +11,7 @@ public interface SignalServiceDataStore { /** * @return A {@link SignalServiceAccountDataStore} for the specified account. */ - SignalServiceAccountDataStore get(AccountIdentifier accountIdentifier); + SignalServiceAccountDataStore get(ServiceId accountIdentifier); /** * @return A {@link SignalServiceAccountDataStore} for the ACI account. diff --git a/libsignal/service/src/main/java/org/whispersystems/signalservice/api/SignalServiceMessageReceiver.java b/libsignal/service/src/main/java/org/whispersystems/signalservice/api/SignalServiceMessageReceiver.java index e706e4601..5f336055a 100644 --- a/libsignal/service/src/main/java/org/whispersystems/signalservice/api/SignalServiceMessageReceiver.java +++ b/libsignal/service/src/main/java/org/whispersystems/signalservice/api/SignalServiceMessageReceiver.java @@ -21,10 +21,10 @@ import org.whispersystems.signalservice.api.messages.SignalServiceStickerManifes import org.whispersystems.signalservice.api.profiles.ProfileAndCredential; import org.whispersystems.signalservice.api.profiles.SignalServiceProfile; import org.whispersystems.signalservice.api.push.ACI; +import org.whispersystems.signalservice.api.push.ServiceId; import org.whispersystems.signalservice.api.push.SignalServiceAddress; import org.whispersystems.signalservice.api.push.exceptions.MissingConfigurationException; import org.whispersystems.signalservice.api.util.CredentialsProvider; -import org.whispersystems.signalservice.api.util.UuidUtil; import org.whispersystems.signalservice.internal.configuration.SignalServiceConfiguration; import org.whispersystems.signalservice.internal.push.PushServiceSocket; import org.whispersystems.signalservice.internal.push.SignalServiceEnvelopeEntity; @@ -43,7 +43,6 @@ import java.util.ArrayList; import java.util.LinkedList; import java.util.List; import java.util.Locale; -import java.util.UUID; /** * The primary interface for receiving Signal Service messages. @@ -91,13 +90,13 @@ public class SignalServiceMessageReceiver { SignalServiceProfile.RequestType requestType, Locale locale) { - ACI aci = address.getAci(); + ServiceId serviceId = address.getServiceId(); if (profileKey.isPresent()) { if (requestType == SignalServiceProfile.RequestType.PROFILE_AND_CREDENTIAL) { - return socket.retrieveVersionedProfileAndCredential(aci.uuid(), profileKey.get(), unidentifiedAccess, locale); + return socket.retrieveVersionedProfileAndCredential(serviceId.uuid(), profileKey.get(), unidentifiedAccess, locale); } else { - return FutureTransformers.map(socket.retrieveVersionedProfile(aci.uuid(), profileKey.get(), unidentifiedAccess, locale), profile -> { + return FutureTransformers.map(socket.retrieveVersionedProfile(serviceId.uuid(), profileKey.get(), unidentifiedAccess, locale), profile -> { return new ProfileAndCredential(profile, SignalServiceProfile.RequestType.PROFILE, Optional.absent()); diff --git a/libsignal/service/src/main/java/org/whispersystems/signalservice/api/SignalServiceMessageSender.java b/libsignal/service/src/main/java/org/whispersystems/signalservice/api/SignalServiceMessageSender.java index 40b37c56b..3e09852c6 100644 --- a/libsignal/service/src/main/java/org/whispersystems/signalservice/api/SignalServiceMessageSender.java +++ b/libsignal/service/src/main/java/org/whispersystems/signalservice/api/SignalServiceMessageSender.java @@ -64,6 +64,7 @@ import org.whispersystems.signalservice.api.messages.multidevice.ViewedMessage; import org.whispersystems.signalservice.api.messages.shared.SharedContact; import org.whispersystems.signalservice.api.push.ACI; import org.whispersystems.signalservice.api.push.DistributionId; +import org.whispersystems.signalservice.api.push.ServiceId; import org.whispersystems.signalservice.api.push.SignalServiceAddress; import org.whispersystems.signalservice.api.push.exceptions.AuthorizationFailedException; import org.whispersystems.signalservice.api.push.exceptions.MalformedResponseException; @@ -118,7 +119,6 @@ import org.whispersystems.signalservice.internal.push.http.ResumableUploadSpec; import org.whispersystems.signalservice.internal.util.Util; import org.whispersystems.util.Base64; import org.whispersystems.util.ByteArrayUtil; -import org.whispersystems.util.FlagUtil; import java.io.IOException; import java.io.InputStream; @@ -795,7 +795,7 @@ public class SignalServiceMessageSender { DataMessage.Quote.Builder quoteBuilder = DataMessage.Quote.newBuilder() .setId(message.getQuote().get().getId()) .setText(message.getQuote().get().getText()) - .setAuthorUuid(message.getQuote().get().getAuthor().getAci().toString()); + .setAuthorUuid(message.getQuote().get().getAuthor().getServiceId().toString()); if (!message.getQuote().get().getMentions().isEmpty()) { for (SignalServiceDataMessage.Mention mention : message.getQuote().get().getMentions()) { @@ -891,7 +891,7 @@ public class SignalServiceMessageSender { .setEmoji(message.getReaction().get().getEmoji()) .setRemove(message.getReaction().get().isRemove()) .setTargetSentTimestamp(message.getReaction().get().getTargetSentTimestamp()) - .setTargetAuthorUuid(message.getReaction().get().getTargetAuthor().getAci().toString()); + .setTargetAuthorUuid(message.getReaction().get().getTargetAuthor().getServiceId().toString()); builder.setReaction(reactionBuilder.build()); builder.setRequiredProtocolVersion(Math.max(DataMessage.ProtocolVersion.REACTIONS_VALUE, builder.getRequiredProtocolVersion())); @@ -1071,7 +1071,7 @@ public class SignalServiceMessageSender { if (result.getSuccess() != null) { SyncMessage.Sent.UnidentifiedDeliveryStatus.Builder builder = SyncMessage.Sent.UnidentifiedDeliveryStatus.newBuilder(); - builder.setDestinationUuid(result.getAddress().getAci().toString()); + builder.setDestinationUuid(result.getAddress().getServiceId().toString()); if (result.getAddress().getNumber().isPresent()) { builder.setDestinationE164(result.getAddress().getNumber().get()); @@ -1084,7 +1084,7 @@ public class SignalServiceMessageSender { } if (recipient.isPresent()) { - sentMessage.setDestinationUuid(recipient.get().getAci().toString()); + sentMessage.setDestinationUuid(recipient.get().getServiceId().toString()); if (recipient.get().getNumber().isPresent()) { sentMessage.setDestinationE164(recipient.get().getNumber().get()); @@ -1112,7 +1112,7 @@ public class SignalServiceMessageSender { for (ReadMessage readMessage : readMessages) { SyncMessage.Read.Builder readBuilder = SyncMessage.Read.newBuilder().setTimestamp(readMessage.getTimestamp()); - readBuilder.setSenderUuid(readMessage.getSender().getAci().toString()); + readBuilder.setSenderUuid(readMessage.getSender().getServiceId().toString()); if (readMessage.getSender().getNumber().isPresent()) { readBuilder.setSenderE164(readMessage.getSender().getNumber().get()); @@ -1131,7 +1131,7 @@ public class SignalServiceMessageSender { for (ViewedMessage readMessage : readMessages) { SyncMessage.Viewed.Builder viewedBuilder = SyncMessage.Viewed.newBuilder().setTimestamp(readMessage.getTimestamp()); - viewedBuilder.setSenderUuid(readMessage.getSender().getAci().toString()); + viewedBuilder.setSenderUuid(readMessage.getSender().getServiceId().toString()); if (readMessage.getSender().getNumber().isPresent()) { viewedBuilder.setSenderE164(readMessage.getSender().getNumber().get()); @@ -1148,7 +1148,7 @@ public class SignalServiceMessageSender { SyncMessage.Builder builder = createSyncMessageBuilder(); SyncMessage.ViewOnceOpen.Builder viewOnceBuilder = SyncMessage.ViewOnceOpen.newBuilder().setTimestamp(readMessage.getTimestamp()); - viewOnceBuilder.setSenderUuid(readMessage.getSender().getAci().toString()); + viewOnceBuilder.setSenderUuid(readMessage.getSender().getServiceId().toString()); if (readMessage.getSender().getNumber().isPresent()) { viewOnceBuilder.setSenderE164(readMessage.getSender().getNumber().get()); @@ -1165,7 +1165,7 @@ public class SignalServiceMessageSender { SyncMessage.Blocked.Builder blockedMessage = SyncMessage.Blocked.newBuilder(); for (SignalServiceAddress address : blocked.getAddresses()) { - blockedMessage.addUuids(address.getAci().toString()); + blockedMessage.addUuids(address.getServiceId().toString()); if (address.getNumber().isPresent()) { blockedMessage.addNumbers(address.getNumber().get()); } @@ -1268,7 +1268,7 @@ public class SignalServiceMessageSender { if (message.getPerson().get().getNumber().isPresent()) { responseMessage.setThreadE164(message.getPerson().get().getNumber().get()); } - responseMessage.setThreadUuid(message.getPerson().get().getAci().toString()); + responseMessage.setThreadUuid(message.getPerson().get().getServiceId().toString()); } switch (message.getType()) { @@ -1301,7 +1301,7 @@ public class SignalServiceMessageSender { SyncMessage.OutgoingPayment.Builder paymentMessage = SyncMessage.OutgoingPayment.newBuilder(); if (message.getRecipient().isPresent()) { - paymentMessage.setRecipientUuid(message.getRecipient().get().getAci().toString()); + paymentMessage.setRecipientUuid(message.getRecipient().get().getServiceId().toString()); } if (message.getNote().isPresent()) { @@ -1353,7 +1353,7 @@ public class SignalServiceMessageSender { verifiedMessageBuilder.setNullMessage(ByteString.copyFrom(nullMessage)); verifiedMessageBuilder.setIdentityKey(ByteString.copyFrom(verifiedMessage.getIdentityKey().serialize())); - verifiedMessageBuilder.setDestinationUuid(verifiedMessage.getDestination().getAci().toString()); + verifiedMessageBuilder.setDestinationUuid(verifiedMessage.getDestination().getServiceId().toString()); if (verifiedMessage.getDestination().getNumber().isPresent()) { verifiedMessageBuilder.setDestinationE164(verifiedMessage.getDestination().getNumber().get()); @@ -1745,12 +1745,12 @@ public class SignalServiceMessageSender { Preconditions.checkArgument(recipients.size() == unidentifiedAccess.size(), "[" + timestamp + "] Unidentified access mismatch!"); - Map accessByAci = new HashMap<>(); - Iterator addressIterator = recipients.iterator(); - Iterator accessIterator = unidentifiedAccess.iterator(); + Map accessBySid = new HashMap<>(); + Iterator addressIterator = recipients.iterator(); + Iterator accessIterator = unidentifiedAccess.iterator(); while (addressIterator.hasNext()) { - accessByAci.put(addressIterator.next().getAci(), accessIterator.next()); + accessBySid.put(addressIterator.next().getServiceId(), accessIterator.next()); } for (int i = 0; i < RETRY_COUNT; i++) { @@ -1758,7 +1758,7 @@ public class SignalServiceMessageSender { Set sharedWith = store.getSenderKeySharedWith(distributionId); List needsSenderKey = targetInfo.destinations.stream() .filter(a -> !sharedWith.contains(a)) - .map(a -> ACI.parseOrThrow(a.getName())) + .map(a -> ServiceId.parseOrThrow(a.getName())) .distinct() .map(SignalServiceAddress::new) .collect(Collectors.toList()); @@ -1767,7 +1767,7 @@ public class SignalServiceMessageSender { SenderKeyDistributionMessage message = getOrCreateNewGroupSession(distributionId); List> access = needsSenderKey.stream() .map(r -> { - UnidentifiedAccess targetAccess = accessByAci.get(r.getAci()); + UnidentifiedAccess targetAccess = accessBySid.get(r.getServiceId()); return Optional.of(new UnidentifiedAccessPair(targetAccess, targetAccess)); }) .collect(Collectors.toList()); @@ -1779,8 +1779,8 @@ public class SignalServiceMessageSender { .map(SendMessageResult::getAddress) .collect(Collectors.toList()); - Set successAcis = successes.stream().map(a -> a.getAci().toString()).collect(Collectors.toSet()); - Set successAddresses = targetInfo.destinations.stream().filter(a -> successAcis.contains(a.getName())).collect(Collectors.toSet()); + Set successSids = successes.stream().map(a -> a.getServiceId().toString()).collect(Collectors.toSet()); + Set successAddresses = targetInfo.destinations.stream().filter(a -> successSids.contains(a.getName())).collect(Collectors.toSet()); store.markSenderKeySharedWith(distributionId, successAddresses); @@ -1794,12 +1794,12 @@ public class SignalServiceMessageSender { .filter(r -> !r.isSuccess()) .collect(Collectors.toList()); - Set failedAddresses = trueFailures.stream() - .map(result -> result.getAddress().getAci()) - .collect(Collectors.toSet()); + Set failedAddresses = trueFailures.stream() + .map(result -> result.getAddress().getServiceId()) + .collect(Collectors.toSet()); List fakeNetworkFailures = recipients.stream() - .filter(r -> !failedAddresses.contains(r.getAci())) + .filter(r -> !failedAddresses.contains(r.getServiceId())) .map(SendMessageResult::networkFailure) .collect(Collectors.toList()); @@ -1914,7 +1914,7 @@ public class SignalServiceMessageSender { List success = recipients.keySet() .stream() - .filter(r -> !unregistered.contains(r.getAci())) + .filter(r -> !unregistered.contains(r.getServiceId())) .map(a -> SendMessageResult.success(a, recipients.get(a), true, store.isMultiDevice(), -1, Optional.of(content))) .collect(Collectors.toList()); @@ -2064,7 +2064,7 @@ public class SignalServiceMessageSender { List addresses = new ArrayList<>(devices.size()); for (int staleDeviceId : devices) { - addresses.add(new SignalProtocolAddress(recipient.getAci().toString(), staleDeviceId)); + addresses.add(new SignalProtocolAddress(recipient.getServiceId().toString(), staleDeviceId)); if (recipient.getNumber().isPresent()) { addresses.add(new SignalProtocolAddress(recipient.getNumber().get(), staleDeviceId)); diff --git a/libsignal/service/src/main/java/org/whispersystems/signalservice/api/crypto/SignalServiceCipher.java b/libsignal/service/src/main/java/org/whispersystems/signalservice/api/crypto/SignalServiceCipher.java index 30b976097..ff5d4b4aa 100644 --- a/libsignal/service/src/main/java/org/whispersystems/signalservice/api/crypto/SignalServiceCipher.java +++ b/libsignal/service/src/main/java/org/whispersystems/signalservice/api/crypto/SignalServiceCipher.java @@ -100,7 +100,7 @@ public class SignalServiceCipher { PushTransportDetails transport = new PushTransportDetails(); SignalProtocolAddress localProtocolAddress = new SignalProtocolAddress(localAddress.getIdentifier(), localDeviceId); SignalGroupCipher groupCipher = new SignalGroupCipher(sessionLock, new GroupCipher(signalProtocolStore, localProtocolAddress)); - SignalSealedSessionCipher sessionCipher = new SignalSealedSessionCipher(sessionLock, new SealedSessionCipher(signalProtocolStore, localAddress.getAci().uuid(), localAddress.getNumber().orNull(), localDeviceId)); + SignalSealedSessionCipher sessionCipher = new SignalSealedSessionCipher(sessionLock, new SealedSessionCipher(signalProtocolStore, localAddress.getServiceId().uuid(), localAddress.getNumber().orNull(), localDeviceId)); CiphertextMessage message = groupCipher.encrypt(distributionId.asUuid(), transport.getPaddedMessageBody(unpaddedMessage)); UnidentifiedSenderMessageContent messageContent = new UnidentifiedSenderMessageContent(message, senderCertificate, @@ -117,7 +117,7 @@ public class SignalServiceCipher { { if (unidentifiedAccess.isPresent()) { SignalSessionCipher sessionCipher = new SignalSessionCipher(sessionLock, new SessionCipher(signalProtocolStore, destination)); - SignalSealedSessionCipher sealedSessionCipher = new SignalSealedSessionCipher(sessionLock, new SealedSessionCipher(signalProtocolStore, localAddress.getAci().uuid(), localAddress.getNumber().orNull(), localDeviceId)); + SignalSealedSessionCipher sealedSessionCipher = new SignalSealedSessionCipher(sessionLock, new SealedSessionCipher(signalProtocolStore, localAddress.getServiceId().uuid(), localAddress.getNumber().orNull(), localDeviceId)); return content.processSealedSender(sessionCipher, sealedSessionCipher, destination, unidentifiedAccess.get().getUnidentifiedCertificate()); } else { @@ -208,7 +208,7 @@ public class SignalServiceCipher { paddedMessage = new PlaintextContent(ciphertext).getBody(); metadata = new SignalServiceMetadata(envelope.getSourceAddress(), envelope.getSourceDevice(), envelope.getTimestamp(), envelope.getServerReceivedTimestamp(), envelope.getServerDeliveredTimestamp(), false, envelope.getServerGuid(), Optional.absent()); } else if (envelope.isUnidentifiedSender()) { - SignalSealedSessionCipher sealedSessionCipher = new SignalSealedSessionCipher(sessionLock, new SealedSessionCipher(signalProtocolStore, localAddress.getAci().uuid(), localAddress.getNumber().orNull(), localDeviceId)); + SignalSealedSessionCipher sealedSessionCipher = new SignalSealedSessionCipher(sessionLock, new SealedSessionCipher(signalProtocolStore, localAddress.getServiceId().uuid(), localAddress.getNumber().orNull(), localDeviceId)); DecryptionResult result = sealedSessionCipher.decrypt(certificateValidator, ciphertext, envelope.getServerReceivedTimestamp()); SignalServiceAddress resultAddress = new SignalServiceAddress(ACI.parseOrThrow(result.getSenderUuid()), result.getSenderE164()); Optional groupId = result.getGroupId(); diff --git a/libsignal/service/src/main/java/org/whispersystems/signalservice/api/messages/SignalServiceDataMessage.java b/libsignal/service/src/main/java/org/whispersystems/signalservice/api/messages/SignalServiceDataMessage.java index dab6be261..39b002141 100644 --- a/libsignal/service/src/main/java/org/whispersystems/signalservice/api/messages/SignalServiceDataMessage.java +++ b/libsignal/service/src/main/java/org/whispersystems/signalservice/api/messages/SignalServiceDataMessage.java @@ -11,6 +11,7 @@ import org.whispersystems.libsignal.InvalidMessageException; import org.whispersystems.libsignal.util.guava.Optional; import org.whispersystems.signalservice.api.messages.shared.SharedContact; import org.whispersystems.signalservice.api.push.ACI; +import org.whispersystems.signalservice.api.push.ServiceId; import org.whispersystems.signalservice.api.push.SignalServiceAddress; import org.whispersystems.signalservice.api.util.OptionalUtil; @@ -610,17 +611,17 @@ public class SignalServiceDataMessage { } public static class Mention { - private final ACI aci; - private final int start; - private final int length; + private final ServiceId aci; + private final int start; + private final int length; - public Mention(ACI aci, int start, int length) { + public Mention(ServiceId aci, int start, int length) { this.aci = aci; this.start = start; this.length = length; } - public ACI getAci() { + public ServiceId getAci() { return aci; } diff --git a/libsignal/service/src/main/java/org/whispersystems/signalservice/api/messages/SignalServiceEnvelope.java b/libsignal/service/src/main/java/org/whispersystems/signalservice/api/messages/SignalServiceEnvelope.java index f1670761b..66c35a386 100644 --- a/libsignal/service/src/main/java/org/whispersystems/signalservice/api/messages/SignalServiceEnvelope.java +++ b/libsignal/service/src/main/java/org/whispersystems/signalservice/api/messages/SignalServiceEnvelope.java @@ -12,7 +12,6 @@ import com.google.protobuf.InvalidProtocolBufferException; import org.whispersystems.libsignal.util.guava.Optional; import org.whispersystems.signalservice.api.push.ACI; import org.whispersystems.signalservice.api.push.SignalServiceAddress; -import org.whispersystems.signalservice.api.util.UuidUtil; import org.whispersystems.signalservice.internal.push.SignalServiceProtos.Envelope; import org.whispersystems.signalservice.internal.serialize.protos.SignalServiceEnvelopeProto; import org.whispersystems.util.Base64; @@ -71,7 +70,7 @@ public class SignalServiceEnvelope { .setServerTimestamp(serverReceivedTimestamp); if (sender.isPresent()) { - builder.setSourceUuid(sender.get().getAci().toString()); + builder.setSourceUuid(sender.get().getServiceId().toString()); if (sender.get().getNumber().isPresent()) { builder.setSourceE164(sender.get().getNumber().get()); diff --git a/libsignal/service/src/main/java/org/whispersystems/signalservice/api/messages/multidevice/DeviceContactsOutputStream.java b/libsignal/service/src/main/java/org/whispersystems/signalservice/api/messages/multidevice/DeviceContactsOutputStream.java index 27820f1ad..5e72d8c48 100644 --- a/libsignal/service/src/main/java/org/whispersystems/signalservice/api/messages/multidevice/DeviceContactsOutputStream.java +++ b/libsignal/service/src/main/java/org/whispersystems/signalservice/api/messages/multidevice/DeviceContactsOutputStream.java @@ -37,7 +37,7 @@ public class DeviceContactsOutputStream extends ChunkedOutputStream { private void writeContactDetails(DeviceContact contact) throws IOException { SignalServiceProtos.ContactDetails.Builder contactDetails = SignalServiceProtos.ContactDetails.newBuilder(); - contactDetails.setUuid(contact.getAddress().getAci().toString()); + contactDetails.setUuid(contact.getAddress().getServiceId().toString()); if (contact.getAddress().getNumber().isPresent()) { contactDetails.setNumber(contact.getAddress().getNumber().get()); @@ -69,7 +69,7 @@ public class DeviceContactsOutputStream extends ChunkedOutputStream { SignalServiceProtos.Verified.Builder verifiedBuilder = SignalServiceProtos.Verified.newBuilder() .setIdentityKey(ByteString.copyFrom(contact.getVerified().get().getIdentityKey().serialize())) - .setDestinationUuid(contact.getVerified().get().getDestination().getAci().toString()) + .setDestinationUuid(contact.getVerified().get().getDestination().getServiceId().toString()) .setState(state); if (contact.getVerified().get().getDestination().getNumber().isPresent()) { diff --git a/libsignal/service/src/main/java/org/whispersystems/signalservice/api/messages/multidevice/SentTranscriptMessage.java b/libsignal/service/src/main/java/org/whispersystems/signalservice/api/messages/multidevice/SentTranscriptMessage.java index b7c8b83ef..0d9a23c0b 100644 --- a/libsignal/service/src/main/java/org/whispersystems/signalservice/api/messages/multidevice/SentTranscriptMessage.java +++ b/libsignal/service/src/main/java/org/whispersystems/signalservice/api/messages/multidevice/SentTranscriptMessage.java @@ -8,7 +8,7 @@ package org.whispersystems.signalservice.api.messages.multidevice; import org.whispersystems.libsignal.util.guava.Optional; import org.whispersystems.signalservice.api.messages.SignalServiceDataMessage; -import org.whispersystems.signalservice.api.push.ACI; +import org.whispersystems.signalservice.api.push.ServiceId; import org.whispersystems.signalservice.api.push.SignalServiceAddress; import java.util.HashMap; @@ -21,26 +21,29 @@ public class SentTranscriptMessage { private final long timestamp; private final long expirationStartTimestamp; private final SignalServiceDataMessage message; - private final Map unidentifiedStatusByAci; + private final Map unidentifiedStatusBySid; private final Map unidentifiedStatusByE164; private final Set recipients; private final boolean isRecipientUpdate; - public SentTranscriptMessage(Optional destination, long timestamp, SignalServiceDataMessage message, - long expirationStartTimestamp, Map unidentifiedStatus, + public SentTranscriptMessage(Optional destination, + long timestamp, + SignalServiceDataMessage message, + long expirationStartTimestamp, + Map unidentifiedStatus, boolean isRecipientUpdate) { this.destination = destination; this.timestamp = timestamp; this.message = message; this.expirationStartTimestamp = expirationStartTimestamp; - this.unidentifiedStatusByAci = new HashMap<>(); + this.unidentifiedStatusBySid = new HashMap<>(); this.unidentifiedStatusByE164 = new HashMap<>(); this.recipients = unidentifiedStatus.keySet(); this.isRecipientUpdate = isRecipientUpdate; for (Map.Entry entry : unidentifiedStatus.entrySet()) { - unidentifiedStatusByAci.put(entry.getKey().getAci().toString(), entry.getValue()); + unidentifiedStatusBySid.put(entry.getKey().getServiceId().toString(), entry.getValue()); if (entry.getKey().getNumber().isPresent()) { unidentifiedStatusByE164.put(entry.getKey().getNumber().get(), entry.getValue()); @@ -64,13 +67,13 @@ public class SentTranscriptMessage { return message; } - public boolean isUnidentified(ACI aci) { - return isUnidentified(aci.toString()); + public boolean isUnidentified(ServiceId serviceId) { + return isUnidentified(serviceId.toString()); } public boolean isUnidentified(String destination) { - if (unidentifiedStatusByAci.containsKey(destination)) { - return unidentifiedStatusByAci.get(destination); + if (unidentifiedStatusBySid.containsKey(destination)) { + return unidentifiedStatusBySid.get(destination); } else if (unidentifiedStatusByE164.containsKey(destination)) { return unidentifiedStatusByE164.get(destination); } else { diff --git a/libsignal/service/src/main/java/org/whispersystems/signalservice/api/push/ACI.java b/libsignal/service/src/main/java/org/whispersystems/signalservice/api/push/ACI.java index ca99bfe13..cea7d1a16 100644 --- a/libsignal/service/src/main/java/org/whispersystems/signalservice/api/push/ACI.java +++ b/libsignal/service/src/main/java/org/whispersystems/signalservice/api/push/ACI.java @@ -2,19 +2,15 @@ package org.whispersystems.signalservice.api.push; import com.google.protobuf.ByteString; -import org.whispersystems.libsignal.util.guava.Optional; import org.whispersystems.signalservice.api.util.UuidUtil; -import java.util.Collection; -import java.util.List; import java.util.UUID; -import java.util.stream.Collectors; /** * An ACI is an "Account Identity". They're just UUIDs, but given multiple different things could be UUIDs, this wrapper exists to give us type safety around * this *specific type* of UUID. */ -public final class ACI extends AccountIdentifier { +public final class ACI extends ServiceId { public static final ACI UNKNOWN = ACI.from(UuidUtil.UNKNOWN_UUID); @@ -22,51 +18,15 @@ public final class ACI extends AccountIdentifier { return new ACI(uuid); } - public static Optional parse(String raw) { - return UuidUtil.parse(raw).transform(ACI::from); - } - public static ACI parseOrThrow(String raw) { return from(UUID.fromString(raw)); } - public static ACI parseOrThrow(byte[] raw) { - return from(UuidUtil.parseOrThrow(raw)); - } - public static ACI parseOrNull(String raw) { UUID uuid = UuidUtil.parseOrNull(raw); return uuid != null ? from(uuid) : null; } - public static ACI parseOrNull(byte[] raw) { - UUID uuid = UuidUtil.parseOrNull(raw); - return uuid != null ? from(uuid) : null; - } - - public static ACI parseOrUnknown(String raw) { - ACI aci = parseOrNull(raw); - return aci != null ? aci : UNKNOWN; - } - - public static ACI fromByteString(ByteString bytes) { - return parseOrThrow(bytes.toByteArray()); - } - - public static ACI fromByteStringOrNull(ByteString bytes) { - UUID uuid = UuidUtil.fromByteStringOrNull(bytes); - return uuid != null ? from(uuid) : null; - } - - public static ACI fromByteStringOrUnknown(ByteString bytes) { - ACI uuid = fromByteStringOrNull(bytes); - return uuid != null ? uuid : UNKNOWN; - } - - public static List filterKnown(Collection acis) { - return acis.stream().filter(aci -> !aci.equals(UNKNOWN)).collect(Collectors.toList()); - } - private ACI(UUID uuid) { super(uuid); } @@ -79,13 +39,13 @@ public final class ACI extends AccountIdentifier { return UuidUtil.toByteArray(uuid); } - public boolean isUnknown() { - return this.equals(UNKNOWN); - } - @Override - public boolean isAci() { - return true; + public boolean equals(Object other) { + if (other instanceof ServiceId) { + return uuid.equals(((ServiceId) other).uuid); + } else { + return false; + } } @Override @@ -93,15 +53,6 @@ public final class ACI extends AccountIdentifier { return uuid.hashCode(); } - @Override - public boolean equals(Object other) { - if (other instanceof ACI) { - return uuid.equals(((ACI) other).uuid); - } else { - return false; - } - } - @Override public String toString() { return uuid.toString(); diff --git a/libsignal/service/src/main/java/org/whispersystems/signalservice/api/push/AccountIdentifier.java b/libsignal/service/src/main/java/org/whispersystems/signalservice/api/push/AccountIdentifier.java deleted file mode 100644 index 3f2b6e936..000000000 --- a/libsignal/service/src/main/java/org/whispersystems/signalservice/api/push/AccountIdentifier.java +++ /dev/null @@ -1,30 +0,0 @@ -package org.whispersystems.signalservice.api.push; - -import java.util.UUID; - -/** - * A wrapper around a UUID that represents an identifier for an account. Today, that is either an {@link ACI} or a {@link PNI}. - */ -public abstract class AccountIdentifier { - - protected final UUID uuid; - - protected AccountIdentifier(UUID uuid) { - this.uuid = uuid; - } - - public UUID uuid() { - return uuid; - } - - public abstract boolean isAci(); - - public final boolean isPni() { - return !isAci(); - } - - @Override - public String toString() { - return uuid.toString(); - } -} diff --git a/libsignal/service/src/main/java/org/whispersystems/signalservice/api/push/PNI.java b/libsignal/service/src/main/java/org/whispersystems/signalservice/api/push/PNI.java index ef57dd0b4..5a8504ce2 100644 --- a/libsignal/service/src/main/java/org/whispersystems/signalservice/api/push/PNI.java +++ b/libsignal/service/src/main/java/org/whispersystems/signalservice/api/push/PNI.java @@ -8,7 +8,7 @@ import java.util.UUID; * A PNI is a "Phone Number Identity". They're just UUIDs, but given multiple different things could be UUIDs, this wrapper exists to give us type safety around * this *specific type* of UUID. */ -public final class PNI extends AccountIdentifier { +public final class PNI extends ServiceId { public static PNI from(UUID uuid) { return new PNI(uuid); @@ -27,11 +27,6 @@ public final class PNI extends AccountIdentifier { super(uuid); } - @Override - public boolean isAci() { - return false; - } - @Override public int hashCode() { return uuid.hashCode(); diff --git a/libsignal/service/src/main/java/org/whispersystems/signalservice/api/push/ServiceId.java b/libsignal/service/src/main/java/org/whispersystems/signalservice/api/push/ServiceId.java new file mode 100644 index 000000000..118674286 --- /dev/null +++ b/libsignal/service/src/main/java/org/whispersystems/signalservice/api/push/ServiceId.java @@ -0,0 +1,115 @@ +package org.whispersystems.signalservice.api.push; + +import com.google.protobuf.ByteString; + +import org.whispersystems.libsignal.SignalProtocolAddress; +import org.whispersystems.libsignal.util.guava.Optional; +import org.whispersystems.signalservice.api.util.UuidUtil; + +import java.util.Collection; +import java.util.List; +import java.util.Objects; +import java.util.UUID; +import java.util.stream.Collectors; + +/** + * A wrapper around a UUID that represents an identifier for an account. Today, that is either an {@link ACI} or a {@link PNI}. + * However, that doesn't mean every {@link ServiceId} is an instance of one of those classes. In reality, we often + * do not know which we have. And it shouldn't really matter. + * + * The only times you truly know, and the only times you should actually care, is during CDS refreshes or specific inbound messages + * that link them together. + */ +public class ServiceId { + + public static final ServiceId UNKNOWN = ServiceId.from(UuidUtil.UNKNOWN_UUID); + + protected final UUID uuid; + + protected ServiceId(UUID uuid) { + this.uuid = uuid; + } + + public static ServiceId from(UUID uuid) { + return new ServiceId(uuid); + } + + public static ServiceId parseOrThrow(String raw) { + return from(UUID.fromString(raw)); + } + + public static ServiceId parseOrThrow(byte[] raw) { + return from(UuidUtil.parseOrThrow(raw)); + } + + public static ServiceId parseOrNull(String raw) { + UUID uuid = UuidUtil.parseOrNull(raw); + return uuid != null ? from(uuid) : null; + } + + public static ServiceId parseOrNull(byte[] raw) { + UUID uuid = UuidUtil.parseOrNull(raw); + return uuid != null ? from(uuid) : null; + } + + public static ServiceId parseOrUnknown(String raw) { + ServiceId aci = parseOrNull(raw); + return aci != null ? aci : UNKNOWN; + } + + public static ServiceId fromByteString(ByteString bytes) { + return parseOrThrow(bytes.toByteArray()); + } + + public static ServiceId fromByteStringOrNull(ByteString bytes) { + UUID uuid = UuidUtil.fromByteStringOrNull(bytes); + return uuid != null ? from(uuid) : null; + } + + public static ServiceId fromByteStringOrUnknown(ByteString bytes) { + ServiceId uuid = fromByteStringOrNull(bytes); + return uuid != null ? uuid : UNKNOWN; + } + + public UUID uuid() { + return uuid; + } + + public boolean isUnknown() { + return uuid.equals(UNKNOWN.uuid); + } + + public SignalProtocolAddress toProtocolAddress(int deviceId) { + return new SignalProtocolAddress(uuid.toString(), deviceId); + } + + public ByteString toByteString() { + return UuidUtil.toByteString(uuid); + } + + public byte[] toByteArray() { + return UuidUtil.toByteArray(uuid); + } + + public static List filterKnown(Collection serviceIds) { + return serviceIds.stream().filter(sid -> !sid.equals(UNKNOWN)).collect(Collectors.toList()); + } + + @Override + public String toString() { + return uuid.toString(); + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (!(o instanceof ServiceId)) return false; + final ServiceId serviceId = (ServiceId) o; + return Objects.equals(uuid, serviceId.uuid); + } + + @Override + public int hashCode() { + return uuid.hashCode(); + } +} diff --git a/libsignal/service/src/main/java/org/whispersystems/signalservice/api/push/ServiceIdType.java b/libsignal/service/src/main/java/org/whispersystems/signalservice/api/push/ServiceIdType.java new file mode 100644 index 000000000..909d9cf94 --- /dev/null +++ b/libsignal/service/src/main/java/org/whispersystems/signalservice/api/push/ServiceIdType.java @@ -0,0 +1,15 @@ +package org.whispersystems.signalservice.api.push; + +public enum ServiceIdType { + ACI("aci"), PNI("pni"); + + private final String queryParamName; + + ServiceIdType(String queryParamName) { + this.queryParamName = queryParamName; + } + + public String queryParam() { + return queryParamName; + } +} diff --git a/libsignal/service/src/main/java/org/whispersystems/signalservice/api/push/SignalServiceAddress.java b/libsignal/service/src/main/java/org/whispersystems/signalservice/api/push/SignalServiceAddress.java index c7c42394f..7178c58ff 100644 --- a/libsignal/service/src/main/java/org/whispersystems/signalservice/api/push/SignalServiceAddress.java +++ b/libsignal/service/src/main/java/org/whispersystems/signalservice/api/push/SignalServiceAddress.java @@ -20,50 +20,50 @@ public class SignalServiceAddress { public static final int DEFAULT_DEVICE_ID = 1; - private final ACI aci; + private final ServiceId serviceId; private final Optional e164; /** * Construct a PushAddress. * - * @param aci The UUID of the user, if available. + * @param serviceId The UUID of the user, if available. * @param e164 The phone number of the user, if available. */ - public SignalServiceAddress(ACI aci, Optional e164) { - this.aci = Preconditions.checkNotNull(aci); - this.e164 = e164; + public SignalServiceAddress(ServiceId serviceId, Optional e164) { + this.serviceId = Preconditions.checkNotNull(serviceId); + this.e164 = e164; } - public SignalServiceAddress(ACI aci) { - this.aci = Preconditions.checkNotNull(aci); - this.e164 = Optional.absent(); + public SignalServiceAddress(ServiceId serviceId) { + this.serviceId = Preconditions.checkNotNull(serviceId); + this.e164 = Optional.absent(); } /** * Convenience constructor that will consider a UUID/E164 string absent if it is null or empty. */ - public SignalServiceAddress(ACI aci, String e164) { - this(aci, OptionalUtil.absentIfEmpty(e164)); + public SignalServiceAddress(ServiceId serviceId, String e164) { + this(serviceId, OptionalUtil.absentIfEmpty(e164)); } public Optional getNumber() { return e164; } - public ACI getAci() { - return aci; + public ServiceId getServiceId() { + return serviceId; } - public boolean hasValidAci() { - return !aci.uuid().equals(UuidUtil.UNKNOWN_UUID); + public boolean hasValidServiceId() { + return !serviceId.isUnknown(); } public String getIdentifier() { - return aci.toString(); + return serviceId.toString(); } public boolean matches(SignalServiceAddress other) { - return this.aci.equals(other.aci); + return this.serviceId.equals(other.serviceId); } public static boolean isValidAddress(String rawUuid, String e164) { @@ -82,10 +82,10 @@ public class SignalServiceAddress { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; final SignalServiceAddress that = (SignalServiceAddress) o; - return aci.equals(that.aci) && e164.equals(that.e164); + return serviceId.equals(that.serviceId) && e164.equals(that.e164); } @Override public int hashCode() { - return Objects.hash(aci, e164); + return Objects.hash(serviceId, e164); } } diff --git a/libsignal/service/src/main/java/org/whispersystems/signalservice/api/services/ProfileService.java b/libsignal/service/src/main/java/org/whispersystems/signalservice/api/services/ProfileService.java index 4586c953c..ba5ea15be 100644 --- a/libsignal/service/src/main/java/org/whispersystems/signalservice/api/services/ProfileService.java +++ b/libsignal/service/src/main/java/org/whispersystems/signalservice/api/services/ProfileService.java @@ -16,6 +16,7 @@ import org.whispersystems.signalservice.api.crypto.UnidentifiedAccess; import org.whispersystems.signalservice.api.profiles.ProfileAndCredential; import org.whispersystems.signalservice.api.profiles.SignalServiceProfile; import org.whispersystems.signalservice.api.push.ACI; +import org.whispersystems.signalservice.api.push.ServiceId; import org.whispersystems.signalservice.api.push.SignalServiceAddress; import org.whispersystems.signalservice.api.push.exceptions.MalformedResponseException; import org.whispersystems.signalservice.internal.ServiceResponse; @@ -29,7 +30,6 @@ import org.whispersystems.signalservice.internal.websocket.WebSocketProtos; import java.security.SecureRandom; import java.util.Locale; -import java.util.UUID; import java.util.concurrent.TimeUnit; import io.reactivex.rxjava3.core.Single; @@ -61,8 +61,8 @@ public final class ProfileService { SignalServiceProfile.RequestType requestType, Locale locale) { - ACI aci = address.getAci(); - SecureRandom random = new SecureRandom(); + ServiceId serviceId = address.getServiceId(); + SecureRandom random = new SecureRandom(); ProfileKeyCredentialRequestContext requestContext = null; WebSocketProtos.WebSocketRequestMessage.Builder builder = WebSocketProtos.WebSocketRequestMessage.newBuilder() @@ -70,18 +70,18 @@ public final class ProfileService { .setVerb("GET"); if (profileKey.isPresent()) { - ProfileKeyVersion profileKeyIdentifier = profileKey.get().getProfileKeyVersion(aci.uuid()); + ProfileKeyVersion profileKeyIdentifier = profileKey.get().getProfileKeyVersion(serviceId.uuid()); String version = profileKeyIdentifier.serialize(); if (requestType == SignalServiceProfile.RequestType.PROFILE_AND_CREDENTIAL) { - requestContext = clientZkProfileOperations.createProfileKeyCredentialRequestContext(random, aci.uuid(), profileKey.get()); + requestContext = clientZkProfileOperations.createProfileKeyCredentialRequestContext(random, serviceId.uuid(), profileKey.get()); ProfileKeyCredentialRequest request = requestContext.getRequest(); String credentialRequest = Hex.toStringCondensed(request.serialize()); - builder.setPath(String.format("/v1/profile/%s/%s/%s", aci, version, credentialRequest)); + builder.setPath(String.format("/v1/profile/%s/%s/%s", serviceId, version, credentialRequest)); } else { - builder.setPath(String.format("/v1/profile/%s/%s", aci, version)); + builder.setPath(String.format("/v1/profile/%s/%s", serviceId, version)); } } else { builder.setPath(String.format("/v1/profile/%s", address.getIdentifier())); diff --git a/libsignal/service/src/main/java/org/whispersystems/signalservice/api/storage/SignalAccountRecord.java b/libsignal/service/src/main/java/org/whispersystems/signalservice/api/storage/SignalAccountRecord.java index 8a1f3f8e5..e2cb69596 100644 --- a/libsignal/service/src/main/java/org/whispersystems/signalservice/api/storage/SignalAccountRecord.java +++ b/libsignal/service/src/main/java/org/whispersystems/signalservice/api/storage/SignalAccountRecord.java @@ -11,7 +11,6 @@ import org.whispersystems.signalservice.api.push.SignalServiceAddress; import org.whispersystems.signalservice.api.util.OptionalUtil; import org.whispersystems.signalservice.api.util.ProtoUtil; import org.whispersystems.signalservice.internal.storage.protos.AccountRecord; -import org.whispersystems.signalservice.internal.storage.protos.GroupV2Record; import java.util.ArrayList; import java.util.Arrays; @@ -346,7 +345,7 @@ public final class SignalAccountRecord implements SignalRecord { if (contact.isPresent()) { AccountRecord.PinnedConversation.Contact.Builder contactBuilder = AccountRecord.PinnedConversation.Contact.newBuilder(); - contactBuilder.setUuid(contact.get().getAci().toString()); + contactBuilder.setUuid(contact.get().getServiceId().toString()); if (contact.get().getNumber().isPresent()) { contactBuilder.setE164(contact.get().getNumber().get()); diff --git a/libsignal/service/src/main/java/org/whispersystems/signalservice/api/storage/SignalContactRecord.java b/libsignal/service/src/main/java/org/whispersystems/signalservice/api/storage/SignalContactRecord.java index 4d47694e5..85863a597 100644 --- a/libsignal/service/src/main/java/org/whispersystems/signalservice/api/storage/SignalContactRecord.java +++ b/libsignal/service/src/main/java/org/whispersystems/signalservice/api/storage/SignalContactRecord.java @@ -9,10 +9,8 @@ import org.whispersystems.signalservice.api.push.ACI; import org.whispersystems.signalservice.api.push.SignalServiceAddress; import org.whispersystems.signalservice.api.util.OptionalUtil; import org.whispersystems.signalservice.api.util.ProtoUtil; -import org.whispersystems.signalservice.api.util.UuidUtil; import org.whispersystems.signalservice.internal.storage.protos.ContactRecord; import org.whispersystems.signalservice.internal.storage.protos.ContactRecord.IdentityState; -import org.whispersystems.signalservice.internal.storage.protos.GroupV2Record; import java.util.Arrays; import java.util.LinkedList; @@ -71,7 +69,7 @@ public final class SignalContactRecord implements SignalRecord { diff.add("E164"); } - if (!Objects.equals(this.getAddress().getAci(), that.getAddress().getAci())) { + if (!Objects.equals(this.getAddress().getServiceId(), that.getAddress().getServiceId())) { diff.add("UUID"); } @@ -216,7 +214,7 @@ public final class SignalContactRecord implements SignalRecord { this.builder = ContactRecord.newBuilder(); } - builder.setServiceUuid(address.getAci().toString()); + builder.setServiceUuid(address.getServiceId().toString()); builder.setServiceE164(address.getNumber().or("")); } diff --git a/libsignal/service/src/main/java/org/whispersystems/signalservice/internal/push/PushServiceSocket.java b/libsignal/service/src/main/java/org/whispersystems/signalservice/internal/push/PushServiceSocket.java index b8cba0bb5..29eb96e77 100644 --- a/libsignal/service/src/main/java/org/whispersystems/signalservice/internal/push/PushServiceSocket.java +++ b/libsignal/service/src/main/java/org/whispersystems/signalservice/internal/push/PushServiceSocket.java @@ -52,7 +52,8 @@ import org.whispersystems.signalservice.api.payments.CurrencyConversions; import org.whispersystems.signalservice.api.profiles.ProfileAndCredential; import org.whispersystems.signalservice.api.profiles.SignalServiceProfile; import org.whispersystems.signalservice.api.profiles.SignalServiceProfileWrite; -import org.whispersystems.signalservice.api.push.AccountIdentifier; +import org.whispersystems.signalservice.api.push.ServiceId; +import org.whispersystems.signalservice.api.push.ServiceIdType; import org.whispersystems.signalservice.api.push.SignalServiceAddress; import org.whispersystems.signalservice.api.push.SignedPreKeyEntity; import org.whispersystems.signalservice.api.push.exceptions.AuthorizationFailedException; @@ -330,7 +331,7 @@ public class PushServiceSocket { return JsonUtil.fromJson(makeServiceRequest(WHO_AM_I, "GET", null), WhoAmIResponse.class); } - public boolean isIdentifierRegistered(AccountIdentifier identifier) throws IOException { + public boolean isIdentifierRegistered(ServiceId identifier) throws IOException { try { makeServiceRequestWithoutAuthentication(String.format(IDENTIFIER_REGISTERED_PATH, identifier.toString()), "HEAD", null); return true; @@ -563,7 +564,7 @@ public class PushServiceSocket { makeServiceRequest(String.format(UUID_ACK_MESSAGE_PATH, uuid), "DELETE", null); } - public void registerPreKeys(AccountIdentifier accountId, + public void registerPreKeys(ServiceIdType serviceIdType, IdentityKey identityKey, SignedPreKeyRecord signedPreKey, List records) @@ -582,13 +583,13 @@ public class PushServiceSocket { signedPreKey.getKeyPair().getPublicKey(), signedPreKey.getSignature()); - makeServiceRequest(String.format(Locale.US, PREKEY_PATH, "", accountId.isAci() ? "aci" : "pni"), + makeServiceRequest(String.format(Locale.US, PREKEY_PATH, "", serviceIdType.queryParam()), "PUT", JsonUtil.toJson(new PreKeyState(entities, signedPreKeyEntity, identityKey))); } - public int getAvailablePreKeys(AccountIdentifier accountId) throws IOException { - String path = String.format(PREKEY_METADATA_PATH, accountId.isAci() ? "aci" : "pni"); + public int getAvailablePreKeys(ServiceIdType serviceIdType) throws IOException { + String path = String.format(PREKEY_METADATA_PATH, serviceIdType.queryParam()); String responseText = makeServiceRequest(path, "GET", null); PreKeyStatus preKeyStatus = JsonUtil.fromJson(responseText, PreKeyStatus.class); @@ -678,9 +679,9 @@ public class PushServiceSocket { } } - public SignedPreKeyEntity getCurrentSignedPreKey(AccountIdentifier accountId) throws IOException { + public SignedPreKeyEntity getCurrentSignedPreKey(ServiceIdType serviceIdType) throws IOException { try { - String path = String.format(SIGNED_PREKEY_PATH, accountId.isAci() ? "aci" : "pni"); + String path = String.format(SIGNED_PREKEY_PATH, serviceIdType.queryParam()); String responseText = makeServiceRequest(path, "GET", null); return JsonUtil.fromJson(responseText, SignedPreKeyEntity.class); } catch (NotFoundException e) { @@ -689,8 +690,8 @@ public class PushServiceSocket { } } - public void setCurrentSignedPreKey(AccountIdentifier accountId, SignedPreKeyRecord signedPreKey) throws IOException { - String path = String.format(SIGNED_PREKEY_PATH, accountId.isAci() ? "aci" : "pni"); + public void setCurrentSignedPreKey(ServiceIdType serviceIdType, SignedPreKeyRecord signedPreKey) throws IOException { + String path = String.format(SIGNED_PREKEY_PATH, serviceIdType.queryParam()); SignedPreKeyEntity signedPreKeyEntity = new SignedPreKeyEntity(signedPreKey.getId(), signedPreKey.getKeyPair().getPublicKey(), signedPreKey.getSignature()); diff --git a/libsignal/service/src/main/java/org/whispersystems/signalservice/internal/push/SendGroupMessageResponse.java b/libsignal/service/src/main/java/org/whispersystems/signalservice/internal/push/SendGroupMessageResponse.java index ec054dc59..83e0bb984 100644 --- a/libsignal/service/src/main/java/org/whispersystems/signalservice/internal/push/SendGroupMessageResponse.java +++ b/libsignal/service/src/main/java/org/whispersystems/signalservice/internal/push/SendGroupMessageResponse.java @@ -21,9 +21,9 @@ public class SendGroupMessageResponse { Set acis = new HashSet<>(uuids404.length); for (String raw : uuids404) { - Optional parsed = ACI.parse(raw); - if (parsed.isPresent()) { - acis.add(parsed.get()); + ACI parsed = ACI.parseOrNull(raw); + if (parsed != null) { + acis.add(parsed); } } diff --git a/libsignal/service/src/main/java/org/whispersystems/signalservice/internal/serialize/SignalServiceAddressProtobufSerializer.java b/libsignal/service/src/main/java/org/whispersystems/signalservice/internal/serialize/SignalServiceAddressProtobufSerializer.java index 4f9f51794..683e10afe 100644 --- a/libsignal/service/src/main/java/org/whispersystems/signalservice/internal/serialize/SignalServiceAddressProtobufSerializer.java +++ b/libsignal/service/src/main/java/org/whispersystems/signalservice/internal/serialize/SignalServiceAddressProtobufSerializer.java @@ -2,6 +2,7 @@ package org.whispersystems.signalservice.internal.serialize; import org.whispersystems.libsignal.util.guava.Optional; import org.whispersystems.signalservice.api.push.ACI; +import org.whispersystems.signalservice.api.push.ServiceId; import org.whispersystems.signalservice.api.push.SignalServiceAddress; import org.whispersystems.signalservice.internal.serialize.protos.AddressProto; @@ -13,7 +14,7 @@ public final class SignalServiceAddressProtobufSerializer { public static AddressProto toProtobuf(SignalServiceAddress signalServiceAddress) { AddressProto.Builder builder = AddressProto.newBuilder(); - builder.setUuid(signalServiceAddress.getAci().toByteString()); + builder.setUuid(signalServiceAddress.getServiceId().toByteString()); if(signalServiceAddress.getNumber().isPresent()){ builder.setE164(signalServiceAddress.getNumber().get()); @@ -23,9 +24,9 @@ public final class SignalServiceAddressProtobufSerializer { } public static SignalServiceAddress fromProtobuf(AddressProto addressProto) { - ACI aci = ACI.parseOrThrow(addressProto.getUuid().toByteArray()); - Optional number = addressProto.hasE164() ? Optional.of(addressProto.getE164()) : Optional.absent(); + ServiceId serviceId = ServiceId.parseOrThrow(addressProto.getUuid().toByteArray()); + Optional number = addressProto.hasE164() ? Optional.of(addressProto.getE164()) : Optional.absent(); - return new SignalServiceAddress(aci, number); + return new SignalServiceAddress(serviceId, number); } } diff --git a/libsignal/service/src/test/java/org/whispersystems/signalservice/internal/serialize/SignalServiceAddressProtobufSerializerTest.java b/libsignal/service/src/test/java/org/whispersystems/signalservice/internal/serialize/SignalServiceAddressProtobufSerializerTest.java index 38761fb3e..5d00e7447 100644 --- a/libsignal/service/src/test/java/org/whispersystems/signalservice/internal/serialize/SignalServiceAddressProtobufSerializerTest.java +++ b/libsignal/service/src/test/java/org/whispersystems/signalservice/internal/serialize/SignalServiceAddressProtobufSerializerTest.java @@ -3,6 +3,7 @@ package org.whispersystems.signalservice.internal.serialize; import org.junit.Test; import org.whispersystems.libsignal.util.guava.Optional; import org.whispersystems.signalservice.api.push.ACI; +import org.whispersystems.signalservice.api.push.ServiceId; import org.whispersystems.signalservice.api.push.SignalServiceAddress; import org.whispersystems.signalservice.internal.serialize.protos.AddressProto; @@ -14,7 +15,7 @@ public final class SignalServiceAddressProtobufSerializerTest { @Test public void serialize_and_deserialize_uuid_address() { - SignalServiceAddress address = new SignalServiceAddress(ACI.from(UUID.randomUUID()), Optional.absent()); + SignalServiceAddress address = new SignalServiceAddress(ServiceId.from(UUID.randomUUID()), Optional.absent()); AddressProto addressProto = org.whispersystems.signalservice.internal.serialize.SignalServiceAddressProtobufSerializer.toProtobuf(address); SignalServiceAddress deserialized = org.whispersystems.signalservice.internal.serialize.SignalServiceAddressProtobufSerializer.fromProtobuf(addressProto); @@ -23,7 +24,7 @@ public final class SignalServiceAddressProtobufSerializerTest { @Test public void serialize_and_deserialize_both_address() { - SignalServiceAddress address = new SignalServiceAddress(ACI.from(UUID.randomUUID()), Optional.of("+15552345678")); + SignalServiceAddress address = new SignalServiceAddress(ServiceId.from(UUID.randomUUID()), Optional.of("+15552345678")); AddressProto addressProto = org.whispersystems.signalservice.internal.serialize.SignalServiceAddressProtobufSerializer.toProtobuf(address); SignalServiceAddress deserialized = org.whispersystems.signalservice.internal.serialize.SignalServiceAddressProtobufSerializer.fromProtobuf(addressProto);